• 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_testfilesMain.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_svnuniversal-projectSimpleClientProgram.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图形用户界面相关程序,包含的函数用来绘制图像和显示文字。

    
    
  • 相关阅读:
    记一次失败的发布经历
    使用Test Director 编写测试用例的一点经验
    Windows Embedded 7 Standard 裁剪过程图解教程
    人生中第一次刮餐饮发票中奖5块!
    Proj EULibHarn Paper Reading: IntelliGen: Automatic Driver Synthesis for FuzzTesting
    Proj EULibHarn Paper Reading: FuzzGen: Automatic Fuzzer Generation
    Proj THUDBFuzz Paper Reading: Lenient Execution of C on a Java Virtual Machine
    Proj AutoWriter Paper Reading: Abstract Syntax Networks for Code Generation and Semantic Parsing
    Proj THUDBFuzz Paper Reading: ContextAware FailureOblivious Computing as a Means of Preventing Buffer Overflows
    Proj EULibHarn Paper Reading: FUDGE: Fuzz Driver Generation at Scale
  • 原文地址:https://www.cnblogs.com/kissfu/p/3314166.html
Copyright © 2020-2023  润新知