Пробую Emgu. А именно захват видео с веб камеры. Приложение на Windows Forms нормально работает. Решил перейти на WPF и столкнулся с тем, что там нет контрола ImageBox. Я сделал через Windowsformshost. Все работает. Но я бы хотел использовать родной контрол Image. И тут у меня не получается, картинки нет. Разметка:
<Image Name="imageBox" Height="500" Width="500"/>
<Button x:Name="captureButton" Content="Start" Click="captureButton_Click"
Margin="33,36,25,473" FontFamily="Arial" Grid.Column="1"
Width="60" Height="60"/>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private VideoCapture _capture = null;
private bool _captureInProgress;
private Mat _frame;
public MainWindow()
{
InitializeComponent();
// Инит EMGUU
CvInvoke.UseOpenCL = false;
try
{
_capture = new VideoCapture();
// Подписываемся на событие
_capture.ImageGrabbed += ProcessFrame;
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
_frame = new Mat();
}
private void ProcessFrame(object sender, EventArgs arg)
{
if (_capture != null && _capture.Ptr != IntPtr.Zero)
{
_capture.Retrieve(_frame, 0);
var temp = _frame.ToImage<Bgr, byte>().Bitmap;
using (Image<Bgr, byte> frame = _capture.QueryFrame().ToImage<Bgr, Byte>())
{
//Вот тут что-то не то =((((
imageBox.Source = BitmapSourceConvert.ToBitmapSource(frame);
// imageBox.Source = BitmapSourceConvert.ToBitmapSource(temp as Image);
}
}
}
private void captureButton_Click(object sender, RoutedEventArgs e)
{
if (_capture != null)
{
if (_captureInProgress)
{ //stop the capture
captureButton.Content = "Start Capture";
_capture.Pause();
}
else
{
//start the capture
captureButton.Content = "Stop";
_capture.Start();
}
_captureInProgress = !_captureInProgress;
}
}
private void ReleaseData()
{
if (_capture != null)
_capture.Dispose();
}
}
Класс конвертер
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;
}
}
}
В общем приложение компилируется, запускается, зажигается индикатор на веб камере, а изображения нет.
ПС: Если использовать
<WindowsFormsHost Width="550px" Height="550px" HorizontalAlignment="Left" VerticalAlignment="Top">
<emui:ImageBox x:Name="imageBox"></emui:ImageBox>
</WindowsFormsHost>
И в MainWindow.xaml.cs писать в контрол, подтянутый из WinForms:
imageBox.Image = _frame;
Все работает.
Сделал рабочий тестовый проект, обработчик у меня получился следующего вида:
private void ProcessFrame(object sender, EventArgs arg)
{
if (System.Threading.Monitor.TryEnter(lockObj))
{
if (_capture != null && _capture.Ptr != IntPtr.Zero)
{
Dispatcher.BeginInvoke(new Action(() =>
{
using (Image<Bgr, byte> emguFrame = _capture.QueryFrame().ToImage<Bgr, Byte>())
{
imageBox.Source = Convert(emguFrame.Bitmap);
}
}));
}
System.Threading.Thread.Sleep(50);
System.Threading.Monitor.Exit(lockObj);
}
}
Код конвертации Bitmap в BitmapSource:
public BitmapSource Convert(System.Drawing.Bitmap bitmap)
{
var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
PixelFormatConverter convert = new PixelFormatConverter();
var bitmapSource = BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, ConvertPixelFormat(bitmap.PixelFormat), null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
bitmap.UnlockBits(bitmapData);
return bitmapSource;
}
private static System.Windows.Media.PixelFormat ConvertPixelFormat(System.Drawing.Imaging.PixelFormat sourceFormat)
{
switch (sourceFormat)
{
case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
return PixelFormats.Bgr24;
case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
return PixelFormats.Bgra32;
case System.Drawing.Imaging.PixelFormat.Format32bppRgb:
return PixelFormats.Bgr32;
case System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:
return PixelFormats.Gray16;
default:
return PixelFormats.Bgr24;
}
}
P.S. Возможно Вам пригодится. Я в своем проекте делал захват видео с помощью Accord Framework .NET ссылка, отображение делал на WPF при помощи Image
контрола и класса WritableBitmap
. Небольшая модификация кода Accord Framework .NET, позволила получить не Bitmap
, а указатель на массив байт, который с дополнительными параметрами передавал методу WritePixels
объекта класса WriteablreBitmap
, это работало быстрее и избавляло от необходимости конвертации Bitmap
.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Подскажите пожалуйста каким способом можно сделать управление выбранным персонажем (например кораблем в космосе), через touch (без использования...
Возможно ли использовать асинхронные методы в цепочке?
Можно ли используя Afforge проигрывать в его плеере одну картинку, взятую из jpeg-файла без формирования видеофайлов с помощью класса VideoFileWriter...