WPF 展示视频修改为WriteableBitmap
WPF開發(fā)者QQ群:340500857
?? ??? 由于微信群人數(shù)太多入群請(qǐng)?zhí)砑有【幬⑿盘?hào)
?yanjinhuawechat 或 W_Feng_aiQ?邀請(qǐng)入群
?需備注WPF開發(fā)者?
? PS:有更好的方式歡迎推薦。
??接著上一篇,進(jìn)行WriteableBitmap性能優(yōu)化
? 修改后運(yùn)行對(duì)比如下:
? 前(CPU與內(nèi)存不穩(wěn)定):
? 后:
使用NuGet如下:
01
—
代碼如下
一、創(chuàng)建MainWindow.xaml代碼如下。
<ws:Window?x:Class="OpenCVSharpExample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:ws="https://github.com/WPFDevelopersOrg.WPFDevelopers.Minimal"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:OpenCVSharpExample"Icon="OpenCV_Logo.png"mc:Ignorable="d"?WindowStartupLocation="CenterScreen"Title="OpenCVSharpExample?https://github.com/WPFDevelopersOrg"?Height="450"?Width="800"><Grid?Margin="4"><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition?Width="Auto"/></Grid.ColumnDefinitions><Image?Grid.Row="0"?Name="imgViewport"/><GroupBox?Header="Operation"?Grid.Column="1"?Margin="0,0,4,0"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition?Height="Auto"/></Grid.RowDefinitions><StackPanel?Grid.Row="0"?HorizontalAlignment="Center"><CheckBox?IsChecked="{Binding?IsSave,RelativeSource={RelativeSource?AncestorType=local:MainWindow}}"VerticalAlignment="Center"?Content="Save"?Margin="0,4"/><ComboBox?Name="ComboBoxCamera"?ItemsSource="{Binding?CameraArray,RelativeSource={RelativeSource?AncestorType=local:MainWindow}}"?SelectedIndex="{Binding?CameraIndex,RelativeSource={RelativeSource?AncestorType=local:MainWindow}}"SelectionChanged="ComboBoxCamera_SelectionChanged"/></StackPanel><StackPanel?Orientation="Horizontal"?Grid.Row="2"?HorizontalAlignment="Center"><Button?Name="btPlay"?Content="Play"?Style="{StaticResource?PrimaryButton}"?Click="btPlay_Click"?IsEnabled="False"/><Button?Name="btStop"?Click="btStop_Click"?Content="Stop"?Margin="4,0"/></StackPanel></Grid></GroupBox></Grid> </ws:Window>二、MainWindow.xaml.cs代碼如下。
using?OpenCvSharp; using?OpenCvSharp.Extensions; using?System; using?System.Collections.Generic; using?System.ComponentModel; using?System.Drawing; using?System.Drawing.Imaging; using?System.IO; using?System.Management; using?System.Threading; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Media.Imaging; using?System.Windows.Threading;namespace?OpenCVSharpExample {///?<summary>///?MainWindow.xaml?的交互邏輯///?</summary>public?partial?class?MainWindow{private?VideoCapture?capCamera;private?VideoWriter?videoWriter;private?Mat?matImage?=?new?Mat();private?Thread?cameraThread;private?Thread?writerThread;private?CascadeClassifier?haarCascade;private?WriteableBitmap?writeableBitmap;private?Rectangle?rectangle;public?List<string>?CameraArray{get?{?return?(List<string>)GetValue(CameraArrayProperty);?}set?{?SetValue(CameraArrayProperty,?value);?}}public?static?readonly?DependencyProperty?CameraArrayProperty?=DependencyProperty.Register("CameraArray",?typeof(List<string>),?typeof(MainWindow),?new?PropertyMetadata(null));public?int?CameraIndex{get?{?return?(int)GetValue(CameraIndexProperty);?}set?{?SetValue(CameraIndexProperty,?value);?}}public?static?readonly?DependencyProperty?CameraIndexProperty?=DependencyProperty.Register("CameraIndex",?typeof(int),?typeof(MainWindow),?new?PropertyMetadata(0));public?bool?IsSave{get?{?return?(bool)GetValue(IsSaveProperty);?}set?{?SetValue(IsSaveProperty,?value);?}}public?static?readonly?DependencyProperty?IsSaveProperty?=DependencyProperty.Register("IsSave",?typeof(bool),?typeof(MainWindow),?new?UIPropertyMetadata(IsSaveChanged));private?static?void?IsSaveChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e){var?mainWindow?=?d?as?MainWindow;if?(e.NewValue?!=?null){var?save?=?(bool)?e.NewValue;if?(save)mainWindow.StartRecording();elsemainWindow.StopRecording();}}public?MainWindow(){InitializeComponent();Width?=?SystemParameters.WorkArea.Width?/?1.5;Height?=?SystemParameters.WorkArea.Height?/?1.5;this.Loaded?+=?MainWindow_Loaded;}private?void?MainWindow_Loaded(object?sender,?RoutedEventArgs?e){InitializeCamera();}private?void?ComboBoxCamera_SelectionChanged(object?sender,?SelectionChangedEventArgs?e){if?(CameraArray.Count?-?1?<?CameraIndex)return;if?(capCamera?!=?null?&&?cameraThread?!=?null){cameraThread.Abort();StopDispose();}CreateCamera();writeableBitmap?=?new?WriteableBitmap(capCamera.FrameWidth,?capCamera.FrameHeight,?0,?0,?System.Windows.Media.PixelFormats.Bgra32,?null);imgViewport.Source?=?writeableBitmap;}private?void?InitializeCamera(){CameraArray?=?GetAllConnectedCameras();}List<string>?GetAllConnectedCameras(){var?cameraNames?=?new?List<string>();using?(var?searcher?=?new?ManagementObjectSearcher("SELECT?*?FROM?Win32_PnPEntity?WHERE?(PNPClass?=?'Image'?OR?PNPClass?=?'Camera')")){foreach?(var?device?in?searcher.Get()){cameraNames.Add(device["Caption"].ToString());}}return?cameraNames;}void?CreateCamera(){capCamera?=?new?VideoCapture(CameraIndex);capCamera.Fps?=?30;cameraThread?=?new?Thread(PlayCamera);cameraThread.Start();}private?void?PlayCamera(){while?(capCamera?!=?null?&&?!capCamera.IsDisposed){capCamera.Read(matImage);if?(matImage.Empty())?break;//Dispatcher.BeginInvoke(DispatcherPriority.Normal,?new?Action(()?=>//{//????var?converted?=?Convert(BitmapConverter.ToBitmap(matImage));//????imgViewport.Source?=?converted;//}));using?(var?img?=?BitmapConverter.ToBitmap(matImage)){var?now?=?DateTime.Now;var?g?=?Graphics.FromImage(img);var?brush?=?new?SolidBrush(System.Drawing.Color.Red);g.DrawString($"北京時(shí)間:{?now.ToString("yyyy年MM月dd日?HH:mm:ss")}",?new?System.Drawing.Font("Arial",?18),?brush,?new?PointF(5,?5));rectangle?=?new?Rectangle(0,?0,?img.Width,?img.Height);brush.Dispose();g.Dispose();Dispatcher.Invoke(new?Action(()?=>{WriteableBitmapHelper.BitmapCopyToWriteableBitmap(img,?writeableBitmap,?rectangle,?0,?0,?System.Drawing.Imaging.PixelFormat.Format32bppArgb);}));};Thread.Sleep(100);}}private?void?StartRecording(){if?(capCamera?==?null){WPFDevelopers.Minimal.Controls.MessageBox.Show("未開啟攝像機(jī)","提示",MessageBoxButton.OKCancel,MessageBoxImage.Error);return;}var?videoFile?=?System.IO.Path.Combine(System.Environment.CurrentDirectory,?"Video");if?(!System.IO.Directory.Exists(videoFile))System.IO.Directory.CreateDirectory(videoFile);var?currentTime?=?System.IO.Path.Combine(videoFile,?$"{DateTime.Now.ToString("yyyyMMddHHmmsshh")}.avi");videoWriter?=?new?VideoWriter(currentTime,?FourCCValues.XVID,?capCamera.Fps,?new?OpenCvSharp.Size(capCamera.FrameWidth,?capCamera.FrameHeight));writerThread?=?new?Thread(AddCameraFrameToRecording);writerThread.Start();}private?void?StopRecording(){if?(videoWriter?!=?null?&&?!videoWriter.IsDisposed){videoWriter.Release();videoWriter.Dispose();videoWriter?=?null;}}private?void?AddCameraFrameToRecording(){var?waitTimeBetweenFrames?=?1_000?/?capCamera.Fps;var?lastWrite?=?DateTime.Now;while?(!videoWriter.IsDisposed){if?(DateTime.Now.Subtract(lastWrite).TotalMilliseconds?<?waitTimeBetweenFrames)continue;lastWrite?=?DateTime.Now;videoWriter.Write(matImage);}}private?void?btStop_Click(object?sender,?RoutedEventArgs?e){StopDispose();btStop.IsEnabled?=?false;}void?StopDispose(){if?(capCamera?!=?null?&&?capCamera.IsOpened()){capCamera.Dispose();capCamera?=?null;}if?(videoWriter?!=?null?&&?!videoWriter.IsDisposed){videoWriter.Release();videoWriter.Dispose();videoWriter?=?null;}btPlay.IsEnabled?=?true;GC.Collect();}void?CreateRecord(){cameraThread?=?new?Thread(PlayCamera);cameraThread.Start();}BitmapImage?Convert(Bitmap?src){System.Drawing.Image?img?=?src;var?now?=?DateTime.Now;var?g?=?Graphics.FromImage(img);var?brush?=?new?SolidBrush(System.Drawing.Color.Red);g.DrawString($"北京時(shí)間:{?now.ToString("yyyy年MM月dd日?HH:mm:ss")}",?new?System.Drawing.Font("Arial",?18),?brush,?new?PointF(5,?5));brush.Dispose();g.Dispose();var?writeableBitmap?=?WriteableBitmapHelper.BitmapToWriteableBitmap(src);return?WriteableBitmapHelper.ConvertWriteableBitmapToBitmapImage(writeableBitmap);}protected?override?void?OnClosing(CancelEventArgs?e){if(WPFDevelopers.Minimal.Controls.MessageBox.Show("是否關(guān)閉系統(tǒng)?",?"詢問",?MessageBoxButton.OKCancel,?MessageBoxImage.Question)?!=?MessageBoxResult.OK)?{e.Cancel?=?true;return;}}protected?override?void?OnClosed(EventArgs?e){StopDispose();}private?void?btPlay_Click(object?sender,?RoutedEventArgs?e){btPlay.IsEnabled?=?false;btStop.IsEnabled?=?true;CreateCamera();}} }三、WriteableBitmapHelper.cs代碼如下。
using?System.IO; using?System.Windows; using?System.Windows.Media.Imaging;namespace?OpenCVSharpExample {public?class?WriteableBitmapHelper{//將Bitmap?轉(zhuǎn)換成WriteableBitmap?public?static?WriteableBitmap?BitmapToWriteableBitmap(System.Drawing.Bitmap?src){var?wb?=?CreateCompatibleWriteableBitmap(src);System.Drawing.Imaging.PixelFormat?format?=?src.PixelFormat;if?(wb?==?null){wb?=?new?WriteableBitmap(src.Width,?src.Height,?0,?0,?System.Windows.Media.PixelFormats.Bgra32,?null);format?=?System.Drawing.Imaging.PixelFormat.Format32bppArgb;}BitmapCopyToWriteableBitmap(src,?wb,?new?System.Drawing.Rectangle(0,?0,?src.Width,?src.Height),?0,?0,?format);return?wb;}//創(chuàng)建尺寸和格式與Bitmap兼容的WriteableBitmappublic?static?WriteableBitmap?CreateCompatibleWriteableBitmap(System.Drawing.Bitmap?src){System.Windows.Media.PixelFormat?format;switch?(src.PixelFormat){case?System.Drawing.Imaging.PixelFormat.Format16bppRgb555:format?=?System.Windows.Media.PixelFormats.Bgr555;break;case?System.Drawing.Imaging.PixelFormat.Format16bppRgb565:format?=?System.Windows.Media.PixelFormats.Bgr565;break;case?System.Drawing.Imaging.PixelFormat.Format24bppRgb:format?=?System.Windows.Media.PixelFormats.Bgr24;break;case?System.Drawing.Imaging.PixelFormat.Format32bppRgb:format?=?System.Windows.Media.PixelFormats.Bgr32;break;case?System.Drawing.Imaging.PixelFormat.Format32bppPArgb:format?=?System.Windows.Media.PixelFormats.Pbgra32;break;case?System.Drawing.Imaging.PixelFormat.Format32bppArgb:format?=?System.Windows.Media.PixelFormats.Bgra32;break;default:return?null;}return?new?WriteableBitmap(src.Width,?src.Height,?0,?0,?format,?null);}//將Bitmap數(shù)據(jù)寫入WriteableBitmap中public?static?void?BitmapCopyToWriteableBitmap(System.Drawing.Bitmap?src,?WriteableBitmap?dst,?System.Drawing.Rectangle?srcRect,?int?destinationX,?int?destinationY,?System.Drawing.Imaging.PixelFormat?srcPixelFormat){var?data?=?src.LockBits(new?System.Drawing.Rectangle(new?System.Drawing.Point(0,?0),?src.Size),?System.Drawing.Imaging.ImageLockMode.ReadOnly,?srcPixelFormat);dst.WritePixels(new?Int32Rect(srcRect.X,?srcRect.Y,?srcRect.Width,?srcRect.Height),?data.Scan0,?data.Height?*?data.Stride,?data.Stride,?destinationX,?destinationY);src.UnlockBits(data);}public?static?BitmapImage?ConvertWriteableBitmapToBitmapImage(WriteableBitmap?wbm){BitmapImage?bmImage?=?new?BitmapImage();using?(MemoryStream?stream?=?new?MemoryStream()){PngBitmapEncoder?encoder?=?new?PngBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(wbm));encoder.Save(stream);bmImage.BeginInit();bmImage.CacheOption?=?BitmapCacheOption.OnLoad;bmImage.StreamSource?=?stream;bmImage.EndInit();bmImage.Freeze();}return?bmImage;}} }02
—
效果預(yù)覽
鳴謝素材提供者 -?李付華
源碼地址如下
Github:https://github.com/WPFDevelopersOrg
https://github.com/WPFDevelopersOrg/OpenCVSharpExample
Gitee:https://gitee.com/WPFDevelopersOrg
WPF開發(fā)者QQ群:?340500857?
Github:https://github.com/WPFDevelopersOrg
出處:https://www.cnblogs.com/yanjinhua
版權(quán):本作品采用「署名-非商業(yè)性使用-相同方式共享 4.0 國際」許可協(xié)議進(jìn)行許可。
轉(zhuǎn)載請(qǐng)著名作者 出處 https://github.com/WPFDevelopersOrg
掃一掃關(guān)注我們,
更多知識(shí)早知道!
點(diǎn)擊閱讀原文可跳轉(zhuǎn)至源代碼
總結(jié)
以上是生活随笔為你收集整理的WPF 展示视频修改为WriteableBitmap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS单机安装k8s并部署.NET
- 下一篇: 使用 Playwright 对 ASP.