В настоящее время я работаю над проектом, использующим распознавание лиц.
Поэтому мне нужен способ отображения изображений веб-камеры для пользователя, чтобы он мог настроить свое лицо.
Я пробовал много вещей, чтобы получить изображения с веб-камеры, используя как можно меньше CPU:
Но ни один из них не был в порядке... В любом случае слишком медленный или слишком много ресурсов процессора.
Затем я попробовал библиотеку Emgu, и я чувствовал себя прекрасно.
Сначала я попробовал его в проекте Windows Form и обновлял изображение в Picture Box.
Но затем, когда я попытался интегрировать его в свой проект WPF, я застрял в том, как передать свое изображение в мой контроль над изображением.
Сейчас у меня есть следующий исходный код:
<Window x:Class="HA.FacialRecognition.Enroll.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Width="800" Height="600"
Loaded="Window_Loaded" Closing="Window_Closing">
<Grid>
<Image x:Name="webcam" Width="640" Height="480" >
<Image.Clip>
<EllipseGeometry RadiusX="240" RadiusY="240">
<EllipseGeometry.Center>
<Point X="320" Y="240" />
</EllipseGeometry.Center>
</EllipseGeometry>
</Image.Clip>
</Image>
</Grid>
</Window>
И код позади:
private Capture capture;
private System.Timers.Timer timer;
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
capture = new Capture();
capture.FlipHorizontal = true;
timer = new System.Timers.Timer();
timer.Interval = 15;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
using (Image<Bgr, byte> frame = capture.QueryFrame())
{
if (frame != null)
{
var bmp = frame.Bitmap;
// How do I pass this bitmap to my Image control called "webcam"?
}
}
}
private void Window_Closing(object sender, CancelEventArgs e)
{
if (capture != null)
{
capture.Dispose();
}
}
Мое предположение заключалось в использовании BitmapSource/WriteableBitmap, но я не получил их работу...
Спасибо!
Ответ 1
Image Class имеет свойство UriSource, которое вы можете искать
Ответ 2
Посмотрите на вики-версию Emgu → Учебники → Примеры → WPF (Windows Presentation Foundation)
Он содержит следующий фрагмент кода для преобразования вашего IImage в BitmapSource, который вы можете напрямую применить к своему управлению.
с использованием Emgu.CV;
используя System.Runtime.InteropServices;
...
/// <summary>
/// Delete a GDI object
/// </summary>
/// <param name="o">The poniter to the GDI object to be deleted</param>
/// <returns></returns>
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
/// <summary>
/// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source
/// </summary>
/// <param name="image">The Emgu CV Image</param>
/// <returns>The equivalent BitmapSource</returns>
public static BitmapSource ToBitmapSource(IImage image)
{
using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
Ответ 3
Я считаю, что все, что вы ищете, это:
Image<Bgr, Byte> frame = capture.QueryFrame();
pictureBox1.Image = image.ToBitmap(pictureBox1.Width, pictureBox1.Height);
Ответ 4
Если вы используете WPF и MVVM, вот как вы это сделаете, используя EMGU.
Вид:
<Window x:Class="HA.FacialRecognition.Enroll.Views.PhotoCaptureView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Width="800" Height="600">
<Grid>
<Image Width="640" Height="480" Source="{Binding CurrentFrame}">
<Image.Clip>
<EllipseGeometry RadiusX="240" RadiusY="240">
<EllipseGeometry.Center>
<Point X="320" Y="240" />
</EllipseGeometry.Center>
</EllipseGeometry>
</Image.Clip>
</Image>
</Grid>
ViewModel:
namespace HA.FacialRecognition.Enroll.ViewModels
{
public class PhotoCaptureViewModel : INotifyPropertyChanged
{
public PhotoCaptureViewModel()
{
StartVideo();
}
private DispatcherTimer Timer { get; set; }
private Capture Capture { get; set; }
private BitmapSource _currentFrame;
public BitmapSource CurrentFrame
{
get { return _currentFrame; }
set
{
if (_currentFrame != value)
{
_currentFrame = value;
OnPropertyChanged();
}
}
}
private void StartVideo()
{
Capture = new Capture();
Timer = new DispatcherTimer();
//framerate of 10fps
Timer.Interval = TimeSpan.FromMilliseconds(100);
Timer.Tick += new EventHandler(async (object s, EventArgs a) =>
{
//draw the image obtained from camera
using (Image<Bgr, byte> frame = Capture.QueryFrame())
{
if (frame != null)
{
CurrentFrame = ToBitmapSource(frame);
}
}
});
Timer.Start();
}
public static BitmapSource ToBitmapSource(IImage image)
{
using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
/// <summary>
/// Delete a GDI object
/// </summary>
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
//implementation of INotifyPropertyChanged, viewmodel disposal etc
}
Ответ 5
Я считаю, что вам нужно использовать interop (источник):
using System.Windows.Interop;
using System.Windows.Media.Imaging;
public static ImageSource AsImageSource<TColor, TDepth>(
this Image<TColor, TDepth> image) where TColor : IColor, new()
{
return Imaging.CreateBitmapSourceFromHBitmap(image.Bitmap.GetHbitmap(),
IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
Что можно использовать следующим образом:
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
using (Image<Bgr, byte> frame = capture.QueryFrame())
{
if (frame != null)
{
var bmp = frame.AsImageSource();
}
}
}
Если interop не работает достаточно хорошо, посмотрите источник Image.ToBitmap
и Image.get_Bitmap
, чтобы узнать, как вы могли реализовать свой собственный WriteableBitmap
.
Ответ 6
http://blogs.microsoft.co.il/blogs/tamir/archive/2008/04/23/webcam-control-with-wpf-or-how-to-create-high-framerate-player-with-directshow-by-using-interopbitmap-in-wpf-application.aspx
Ответ 7
Попробуйте это.
http://easywebcam.codeplex.com/
Я использовал его, и это было отлично..