C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试

简介: 原文:C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试WPF 没有用到 PictureBox, 而是用Image代替. 下面我试着加载显示一个图片 。 XAML CS Attempt 1: ImageMy_Image=newImage(Openfile.
原文: C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试

WPF 没有用到 PictureBox, 而是用Image代替.

下面我试着加载显示一个图片 。

XAML

<Image x:Name="srcImg"Width="400"Height="300"></Image>

CS Attempt 1:

Image<Bgr,Byte>My_Image=newImage<Bgr,byte>(Openfile.FileName);
srcImg.Source=My_Image.ToBitmap();

Error Message

Cannot implicitly convert type 'System.Drawing.Bitmap' 
to 'System.Windows.Media.ImageSource'

CS Attempt 2:

Image<Bgr,Byte>My_Image=newImage<Bgr,byte>(Openfile.FileName);
srcImg.Source=newBitmapImage(My_Image);

Error Message

Error1The best overloaded method match for'System.Windows.Media.Imaging.BitmapImage.BitmapImage(System.Uri)' has some invalid arguments  
Error2Argument1: cannot convert from'Emgu.CV.Image<Emgu.CV.Structure.Bgr,byte>' to 'System.Uri'

解决方法:

Image<Bgr, Byte> My_Image = new Image<Bgr, byte>(Openfile.FileName);
srcImg.Source = BitmapSourceConvert.ToBitmapSource(myImage);
public static class BitmapSourceConvert
{
    [DllImport("gdi32")]
    private static extern int DeleteObject(IntPtr o);

    public static BitmapSource ToBitmapSource(IImage image)
    {
        using (System.Drawing.Bitmap source = image.Bitmap)
        {
            IntPtr ptr = source.GetHbitmap();

            BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                ptr,
                IntPtr.Zero,
                Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

            DeleteObject(ptr);
            return bs;
        }
    }
}

 

 测试:

 Bitmap bm = (Bitmap)Bitmap.FromFile(@"D:\my_testfiles\Main.png");
            int count = 10000000;
            for (int i = 0; i < count; i++)
            {
                Commons.BitMapToImageSource(bm.Clone() as Bitmap);

            }
 
结果:

当循环 1527次,  耗时 00:00:17.8860231后  报错。


ErrorTrace:
 at System.Drawing.Bitmap.GetHbitmap(Color background)
   at System.Drawing.Bitmap.GetHbitmap()
   at SimpleClient.Commons.BitMapToImageSource(Bitmap bitmap) in D:\my_svn\universal-project\SimpleClient\Program.cs:line 165
 

ErrorMessage:

system.OutOfMemoryException: Out of memory.

改进:

写一个视频显示控件,内部实现显示Bitmap转换成BitmapSource。为控件Source开辟一块内存控件,然后一直刷新。首先我们使用EmuguCV里面的Capture。
控件继承Image、IDisposable接口并开放一个属性
VideoSource
代码如下:
    public class CapPlayer : Image, IDisposable
    {
        private Capture videoSource;
        public Capture VideoSource
        {
            set
            {
                if (value != null)
                {
                    this.videoSource = value;
                    this.LaodCapPlayer();
                }
            }
        }

        private InteropBitmap bitmapSource;
        private IntPtr map;
        private IntPtr section;

        public CapPlayer()
        {
            Application.Current.Exit += new ExitEventHandler(Current_Exit);
        }

        private void LaodCapPlayer()
        {
            videoSource.ImageGrabbed += new Capture.GrabEventHandler(videoSource_ImageGrabbed);
            videoSource.Start();

            uint pcount = (uint)(videoSource.Width * videoSource.Height * PixelFormats.Bgr32.BitsPerPixel / 8);
            section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
            map = MapViewOfFile(section, 0xF001F, 0, 0, pcount);
            bitmapSource = Imaging.CreateBitmapSourceFromMemorySection(section, (int)videoSource.Width, (int)videoSource.Height, PixelFormats.Bgr32,
                (int)(videoSource.Width * PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap;
            this.Source = bitmapSource;
        }

        void videoSource_ImageGrabbed(object sender, EventArgs e)
        {
            Capture camera = sender as Capture;
            var frame = camera.RetrieveBgrFrame().Bitmap;
            if (this.Dispatcher != null)
            {
                this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
                {
                    if (map != IntPtr.Zero)
                    {
                        try
                        {
                            System.Drawing.Imaging.BitmapData bmpData = frame.LockBits(new System.Drawing.Rectangle(0, 0, (int)videoSource.Width, (int)videoSource.Height),
                            System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
                            /* Get the pointer to the pixels */
                            IntPtr pBmp = bmpData.Scan0;
                            int srcStride = bmpData.Stride;
                            int pSize = srcStride * (int)videoSource.Height;
                            CopyMemory(map, pBmp, pSize);
                            frame.UnlockBits(bmpData);
                        }
                        catch (Exception ex)
                        {
                            Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(ex, "Info", 0);
                        }

                    }

                    if (bitmapSource != null)
                    {
                        bitmapSource.Invalidate();
                    }
                }, null);

            }

            if (captureLock)
            {
                try
                {
                    lock (mutCurrentImg)
                    {
                        camera.RetrieveBgrFrame().Save(imageFileName);
                    }
                }
                catch (System.Exception ex)
                {
                    Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(ex, "Info", 0);
                }
                captureLock = false;
            }
        }

        void Current_Exit(object sender, ExitEventArgs e)
        {
            this.Dispose();
        }
        object mutCurrentImg = new object();
        bool captureLock = false;
        string imageFileName = string.Empty;
        public void ImaggingCapture(string imageFileName)
        {
            this.imageFileName = imageFileName;
            this.captureLock = true;
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (videoSource != null)
                videoSource.Stop();
            Application.Current.Exit -= new ExitEventHandler(Current_Exit);
        }

        #endregion


        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
        private static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);

    }
 

测试结果:无异常,但是发现比较占用CPU 10%左右,内存 122M 左右,线程数32.

感觉不太理想CPU占用太多,我们把EmuguCV的Capture改为AForge.NEt的VideoCaptureDevice,代码如下:

    public class CapPlayer : Image, IDisposable
    {
        private  VideoCaptureDevice videoSource;
        private InteropBitmap bitmapSource;
        private IntPtr map;
        private IntPtr section;

        public CapPlayer()
        {

            Application.Current.Exit += new ExitEventHandler(Current_Exit);
            this.Loaded += new RoutedEventHandler(CapPlayer_Loaded);
            videoSource = new VideoCaptureDevice(@"device:pnp:\\?\usb#vid_0ac8&pid_305b#5&ee85354&0&2#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global");  
      
        }

        void CapPlayer_Loaded(object sender, RoutedEventArgs e)
        {
            videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame);
            videoSource.Start();

            uint pcount = (uint)(this.Width * this.Height * PixelFormats.Bgr32.BitsPerPixel / 8);
            section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
            map = MapViewOfFile(section, 0xF001F, 0, 0, pcount);
            bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, (int)this.Width, (int)this.Height, PixelFormats.Bgr32,
                (int)(this.Width * PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap;
            this.Source = bitmapSource;
        }

        void Current_Exit(object sender, ExitEventArgs e)
        {
            this.Dispose();
        }
        object mutCurrentImg = new object();
        bool captureLock = false;
        string imageFileName = string.Empty;
        public void ImaggingCapture(string imageFileName)
        {
            this.imageFileName = imageFileName;
            this.captureLock = true;
        }

        private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            //eventArgs.Frame.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);

            if (this.Dispatcher != null)
            {
                this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
                {
                    if (map != IntPtr.Zero)
                    {
                        System.Drawing.Imaging.BitmapData bmpData = eventArgs.Frame.LockBits(new System.Drawing.Rectangle(0, 0, (int)this.Width, (int)this.Height),
                        System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
                        /* Get the pointer to the pixels */
                        IntPtr pBmp = bmpData.Scan0;
                        int srcStride = bmpData.Stride;
                        int pSize = srcStride * (int)this.Height;
                        CopyMemory(map, pBmp, pSize);
                        eventArgs.Frame.UnlockBits(bmpData);
                    }

                    if (bitmapSource != null)
                    {
                        bitmapSource.Invalidate();
                    }
                }, null);

            }

            if (captureLock)
            {
                try
                {
                    lock (mutCurrentImg)
                    {
                        eventArgs.Frame.Save(imageFileName);
                    }
                }
                catch (System.Exception ex)
                {
                }
                captureLock = false;
            }
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (videoSource != null)
                videoSource.SignalToStop();
        }

        #endregion


        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
        private static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);

    }

 

测试结果:无异常,但是发现占用CPU 1%左右,内存 72M 左右,线程数28. 是不是比较理想呢!!

 

CPU

内存

线程数

EmuguCV

10%左右

122M左右

32

Aforge.Net

1%左右

72M左右

28

 

我的电脑配置.

摄像头:FrameRate 30,Width 320 Height 240.

电脑型号 戴尔 Precision WorkStation T3400 Tower
操作系统 Windows 7 旗舰版 32位 SP1 ( DirectX 11 )
处理器 英特尔 酷睿2 双核 E8400 @ 3.00GHz
主板 戴尔 0HY553 (英特尔 X38/X48 Express 芯片组 - ICH9R)
内存 4 GB ( 海力士 DDR2 800MHz / 金士顿 DDR2 667MHz )
主硬盘 西数 WDC WD3200AAKS-75L9A0 ( 320 GB / 7200 转/分 )
显卡 Nvidia Quadro NVS 290 ( 256 MB / Nvidia )
显示器 戴尔 DELA04A DELL E170S ( 17.1 英寸 )
光驱 飞利浦-建兴 DVD-ROM DH-16D5S DVD光驱
声卡 Analog Devices AD1984 @ 英特尔 82801I(ICH9) 高保真音频
网卡 博通 BCM5754 NetXtreme Gigabit Ethernet / 戴尔

gdi32.dll

系统文件gdi32.dll是存放在Windows系统文件夹中的重要文件,通常情况下是在安装操作系统过程中自动创建的,对于系统正常运行来说至关重要。除非用户电脑被木马病毒、或是流氓软件篡改导致出现gdi32.dll丢失、缺失损坏等弹窗现象,否则不建议用户对该类文件(gdi32.dll)进行随意的修改。

gdi32.dll是Windows GDI图形用户界面相关程序,包含的函数用来绘制图像和显示文字。

目录
相关文章
|
17天前
|
jenkins 测试技术 持续交付
解锁.NET项目高效秘籍:从理论迷雾到实践巅峰,持续集成与自动化测试如何悄然改变游戏规则?
【8月更文挑战第28天】在软件开发领域,持续集成(CI)与自动化测试已成为提升效率和质量的关键工具。尤其在.NET项目中,二者的结合能显著提高开发速度并保证软件稳定性。本文将从理论到实践,详细介绍CI与自动化测试的重要性,并以ASP.NET Core Web API项目为例,演示如何使用Jenkins和NUnit实现自动化构建与测试。每次代码提交后,Jenkins自动触发构建流程,通过编译和运行NUnit测试确保代码质量。这种方式不仅节省了时间,还能快速发现并解决问题,推动.NET项目开发迈向更高水平。
33 8
|
17天前
|
测试技术 API 开发者
.NET单元测试框架大比拼:MSTest、xUnit与NUnit的实战较量与选择指南
【8月更文挑战第28天】单元测试是软件开发中不可或缺的一环,它能够确保代码的质量和稳定性。在.NET生态系统中,MSTest、xUnit和NUnit是最为流行的单元测试框架。本文将对这三种测试框架进行全面解析,并通过示例代码展示它们的基本用法和特点。
34 7
|
14天前
|
测试技术 C# 开发者
“代码守护者:详解WPF开发中的单元测试策略与实践——从选择测试框架到编写模拟对象,全方位保障你的应用程序质量”
【8月更文挑战第31天】单元测试是确保软件质量的关键实践,尤其在复杂的WPF应用中更为重要。通过为每个小模块编写独立测试用例,可以验证代码的功能正确性并在早期发现错误。本文将介绍如何在WPF项目中引入单元测试,并通过具体示例演示其实施过程。首先选择合适的测试框架如NUnit或xUnit.net,并利用Moq模拟框架隔离外部依赖。接着,通过一个简单的WPF应用程序示例,展示如何模拟`IUserRepository`接口并验证`MainViewModel`加载用户数据的正确性。这有助于确保代码质量和未来的重构与扩展。
25 0
|
14天前
|
持续交付 C# 敏捷开发
“敏捷之道:揭秘WPF项目中的快速迭代与持续交付——从需求管理到自动化测试,打造高效开发流程的全方位指南”
【8月更文挑战第31天】敏捷开发是一种注重快速迭代和持续交付的软件开发方法,通过短周期开发提高产品质量并快速响应变化。本文通过问题解答形式,探讨在Windows Presentation Foundation(WPF)项目中应用敏捷开发的最佳实践,涵盖需求管理、版本控制、自动化测试及持续集成等方面,并通过具体示例代码展示其实施过程,帮助团队提升代码质量和开发效率。
29 0
|
14天前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
29 0
|
14天前
|
C# Windows 开发者
超越选择焦虑:深入解析WinForms、WPF与UWP——谁才是打造顶级.NET桌面应用的终极利器?从开发效率到视觉享受,全面解读三大框架优劣,助你精准匹配项目需求,构建完美桌面应用生态系统
【8月更文挑战第31天】.NET框架为开发者提供了多种桌面应用开发选项,包括WinForms、WPF和UWP。WinForms简单易用,适合快速开发基本应用;WPF提供强大的UI设计工具和丰富的视觉体验,支持XAML,易于实现复杂布局;UWP专为Windows 10设计,支持多设备,充分利用现代硬件特性。本文通过示例代码详细介绍这三种框架的特点,帮助读者根据项目需求做出明智选择。以下是各框架的简单示例代码,便于理解其基本用法。
52 0
|
14天前
|
Java Spring UED
Spring框架的异常处理秘籍:打造不败之身的应用!
【8月更文挑战第31天】在软件开发中,异常处理对应用的稳定性和健壮性至关重要。Spring框架提供了一套完善的异常处理机制,包括使用`@ExceptionHandler`注解和配置`@ControllerAdvice`。本文将详细介绍这两种方式,并通过示例代码展示其具体应用。`@ExceptionHandler`可用于控制器类中的方法,处理特定异常;而`@ControllerAdvice`则允许定义全局异常处理器,捕获多个控制器中的异常。
33 0
|
14天前
|
API 开发者 Java
API 版本控制不再难!Spring 框架带你玩转多样化的版本管理策略,轻松应对升级挑战!
【8月更文挑战第31天】在开发RESTful服务时,为解决向后兼容性问题,常需进行API版本控制。本文以Spring框架为例,探讨四种版本控制策略:URL版本控制、请求头版本控制、查询参数版本控制及媒体类型版本控制,并提供示例代码。此外,还介绍了通过自定义注解与过滤器实现更灵活的版本控制方案,帮助开发者根据项目需求选择最适合的方法,确保API演化的管理和客户端使用的稳定与兼容。
50 0
|
2月前
|
测试技术 C#
.NET单元测试使用Bogus或AutoFixture按需填充的几种方式和最佳实践
【7月更文挑战第13天】AutoFixture 和 Bogus 都是流行的 C#库,用于在单元测试中按需填充测试数据。以下是它们的几种使用方式和最佳实践:一、AutoFixture:1.直接定制 2.使用匿名函数 3.实现ICustomization接口 4.使用Build方法。 二、最佳实践Bogus:1.安装2.使用。
|
30天前
分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了
分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了