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 Memberspublic 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 Memberspublic 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圖形用戶界面相關程序,包含的函數用來繪制圖像和顯示文字。
posted on 2018-10-20 14:36 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/lonelyxmas/p/9821618.html
總結
以上是生活随笔為你收集整理的C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个猫三个路由器怎么连接电脑(一个电脑猫
- 下一篇: C# 获取对象 大小 Marshal.S