在 WPF 中显示来自我的网络摄像头的视频流?
Displaying a videostream from my webcam in WPF?
我有一个问题,如何在 WPF 的图像容器中显示来自网络摄像头的流?我已经使用 Emgu 获取了流并将其转换为 BitmapSource,但现在我不明白如何使用 caliburn (MVVM) 将图像从我的网络摄像头绑定到 WPF,每 X ms ....
<Image x:Name="imageWebcam" />
你应该使用MediaElement
来显示视频,而不是Image
控件:
XAML:
<MediaElement Source="{Binding VideoAddress}" />
视图模型:
private URI videoAddress=new URI("C:\video.wmv");
public URI VideoAddress
{
get { return videoAddress; }
set
{
videoAddress = value;
OnPropertyChanged("LeafName");
}
}
此外,您可以使用 WPF-MediaKit to show video from WebCam. Or see this tutorial。
更新:
您应该使用 Image
来显示图像:
<Image x:Name="imageWebcam" />
和 C#:
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("C:/1.png");
logo.EndInit();
imageWebcam.Source = logo;
使用 WriteableBitmap 作为图像元素的来源。您应该在视图模型中提供一个回调,为每个新框架传递框架数据。在后面的代码中从您的视图订阅此回调。然后您可以将每个帧写入位图。在这种情况下,我认为数据绑定不是一个好方法。
在处理视频帧流时,WriteableBitmap 是迄今为止 WPF 中的最佳选择:
找到好的解决方案。
我无法显示整个代码,但我可以解释一下,以绑定 wpf 视图:
<Image x:Name="ImageWebcam" />
对于我的 ViewModel(使用 Caliburn FrameWork,但这可以很容易地适应 MVVM 模式)我必须使用具有相同名称的函数绑定图像:
public WriteableBitmap ImageWebcam
{
get
{
return this.imageWebcam;
}
set
{
this.imageWebcam = value;
this.NotifyOfPropertyChange(() => this.ImageWebcam);
}
}
为了更新这个图像,我使用了一个计时器,它必须初始化到 ViewModel 构造函数中:
public MachinBidule()
{
timeIsRunningOut= new System.Timers.Timer();
timeIsRunningOut.AutoReset = true;
timeIsRunningOut.Interval = 10;
timeIsRunningOut.Elapsed += (sender, e) => { UpdateImage(); };
capture = new Capture(); // Capture the webcam using EmguCV
}
现在您可以使用调度程序管理更新:
// Update the image, method called by the timer every 10 ms
private void UpdateImage()
{
// If capture is working
if(capture.QueryFrame()!= null)
{
//capture an Image from webcam stream and
Image<Bgr, Byte> currentFrame = capture.QueryFrame().ToImage<Bgr, Byte>();
if (currentFrame != null)
{
Application.Current.Dispatcher.BeginInvoke(new System.Action(() => { imageWebcam = new WriteableBitmap(BitmapSourceConvert.ToBitmapSource(currentFrame)); NotifyOfPropertyChange(() => ImageWebcam); }));
}
}
}
您可以注意到我们需要从 emguCV Image<Bgr,Byte>
转换为 WPF WriteableBitmap
并通过 NotifyOfPropertyChange(() => ImageWebcam)
.
通知更新
如果您有任何问题,请随时与我联系或发表评论。
如果您发现任何错误,请随时纠正我(语法和代码)。
这是我基于 WritableBitmap. I have a web cam that streams images at 30 FPS. I need to process those images real time and display them. CameraOnFrame
is an event handler which fires 30 times per second on a non-UI thread, so Dispatcher.Invoke
is needed. Image<Bgr, byte>
is an Emgu.CV 图像得出的解决方案,但它基本上是 24 位 BGR 图像的包装器。
XAML:
<Image x:Name="ImageDisplay"/>
代码:
_writableBitmap = new WriteableBitmap(_imageWidth, _imageHeight, 96, 96, PixelFormats.Bgr24, null);
ImageDisplay.Source = _writableBitmap;
...
private void CameraOnFrame(object sender, Image<Bgr, byte> img)
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(() => CameraOnFrame(sender, img));
return;
}
_writableBitmap.WritePixels(new Int32Rect(0, 0, img.Width, img.Height), img.MIplImage.ImageData, img.MIplImage.ImageSize, img.MIplImage.WidthStep);
}
我有一个问题,如何在 WPF 的图像容器中显示来自网络摄像头的流?我已经使用 Emgu 获取了流并将其转换为 BitmapSource,但现在我不明白如何使用 caliburn (MVVM) 将图像从我的网络摄像头绑定到 WPF,每 X ms ....
<Image x:Name="imageWebcam" />
你应该使用MediaElement
来显示视频,而不是Image
控件:
XAML:
<MediaElement Source="{Binding VideoAddress}" />
视图模型:
private URI videoAddress=new URI("C:\video.wmv");
public URI VideoAddress
{
get { return videoAddress; }
set
{
videoAddress = value;
OnPropertyChanged("LeafName");
}
}
此外,您可以使用 WPF-MediaKit to show video from WebCam. Or see this tutorial。
更新:
您应该使用 Image
来显示图像:
<Image x:Name="imageWebcam" />
和 C#:
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("C:/1.png");
logo.EndInit();
imageWebcam.Source = logo;
使用 WriteableBitmap 作为图像元素的来源。您应该在视图模型中提供一个回调,为每个新框架传递框架数据。在后面的代码中从您的视图订阅此回调。然后您可以将每个帧写入位图。在这种情况下,我认为数据绑定不是一个好方法。
在处理视频帧流时,WriteableBitmap 是迄今为止 WPF 中的最佳选择:
找到好的解决方案。 我无法显示整个代码,但我可以解释一下,以绑定 wpf 视图:
<Image x:Name="ImageWebcam" />
对于我的 ViewModel(使用 Caliburn FrameWork,但这可以很容易地适应 MVVM 模式)我必须使用具有相同名称的函数绑定图像:
public WriteableBitmap ImageWebcam
{
get
{
return this.imageWebcam;
}
set
{
this.imageWebcam = value;
this.NotifyOfPropertyChange(() => this.ImageWebcam);
}
}
为了更新这个图像,我使用了一个计时器,它必须初始化到 ViewModel 构造函数中:
public MachinBidule()
{
timeIsRunningOut= new System.Timers.Timer();
timeIsRunningOut.AutoReset = true;
timeIsRunningOut.Interval = 10;
timeIsRunningOut.Elapsed += (sender, e) => { UpdateImage(); };
capture = new Capture(); // Capture the webcam using EmguCV
}
现在您可以使用调度程序管理更新:
// Update the image, method called by the timer every 10 ms
private void UpdateImage()
{
// If capture is working
if(capture.QueryFrame()!= null)
{
//capture an Image from webcam stream and
Image<Bgr, Byte> currentFrame = capture.QueryFrame().ToImage<Bgr, Byte>();
if (currentFrame != null)
{
Application.Current.Dispatcher.BeginInvoke(new System.Action(() => { imageWebcam = new WriteableBitmap(BitmapSourceConvert.ToBitmapSource(currentFrame)); NotifyOfPropertyChange(() => ImageWebcam); }));
}
}
}
您可以注意到我们需要从 emguCV Image<Bgr,Byte>
转换为 WPF WriteableBitmap
并通过 NotifyOfPropertyChange(() => ImageWebcam)
.
如果您有任何问题,请随时与我联系或发表评论。 如果您发现任何错误,请随时纠正我(语法和代码)。
这是我基于 WritableBitmap. I have a web cam that streams images at 30 FPS. I need to process those images real time and display them. CameraOnFrame
is an event handler which fires 30 times per second on a non-UI thread, so Dispatcher.Invoke
is needed. Image<Bgr, byte>
is an Emgu.CV 图像得出的解决方案,但它基本上是 24 位 BGR 图像的包装器。
XAML:
<Image x:Name="ImageDisplay"/>
代码:
_writableBitmap = new WriteableBitmap(_imageWidth, _imageHeight, 96, 96, PixelFormats.Bgr24, null);
ImageDisplay.Source = _writableBitmap;
...
private void CameraOnFrame(object sender, Image<Bgr, byte> img)
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(() => CameraOnFrame(sender, img));
return;
}
_writableBitmap.WritePixels(new Int32Rect(0, 0, img.Width, img.Height), img.MIplImage.ImageData, img.MIplImage.ImageSize, img.MIplImage.WidthStep);
}