在C# WPF应用程序中通过DLL进行摄像头捕获,通常涉及以下核心概念:
优势:
示例代码:
using DirectShowLib;
using System;
using System.Windows;
using System.Windows.Interop;
public class CameraCapture
{
private DsDevice _captureDevice;
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaControl;
public void InitializeCamera()
{
// 获取视频输入设备
DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
if (devices.Length == 0)
{
MessageBox.Show("未找到摄像头设备");
return;
}
_captureDevice = devices[0];
// 创建Filter Graph
_filterGraph = (IFilterGraph2)new FilterGraph();
// 添加捕获设备
int hr = _filterGraph.AddSourceFilterForMoniker(
_captureDevice.Mon, null, _captureDevice.Name, out IBaseFilter sourceFilter);
DsError.ThrowExceptionForHR(hr);
// 创建Sample Grabber用于捕获帧
IBaseFilter grabber = (IBaseFilter)new SampleGrabber();
hr = _filterGraph.AddFilter(grabber, "Sample Grabber");
DsError.ThrowExceptionForHR(hr);
// 设置媒体类型
var mediaType = new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24
};
((ISampleGrabber)grabber).SetMediaType(mediaType);
DsUtils.FreeAMMediaType(mediaType);
// 连接过滤器
hr = _filterGraph.Connect(
DsFindPin.ByName(sourceFilter, "Capture"),
DsFindPin.ByName(grabber, "Input"));
DsError.ThrowExceptionForHR(hr);
// 获取媒体控制接口
_mediaControl = (IMediaControl)_filterGraph;
// 开始捕获
hr = _mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
public void StopCapture()
{
if (_mediaControl != null)
{
_mediaControl.Stop();
}
}
}
优势:
示例代码:
// 假设有一个名为CameraSDK.dll的第三方库
[DllImport("CameraSDK.dll")]
public static extern int Camera_Initialize(int deviceIndex);
[DllImport("CameraSDK.dll")]
public static extern int Camera_StartCapture(IntPtr hwnd);
[DllImport("CameraSDK.dll")]
public static extern int Camera_StopCapture();
public class CameraWrapper
{
public bool Initialize(int deviceIndex)
{
return Camera_Initialize(deviceIndex) == 0;
}
public bool StartCapture(Window window)
{
var hwnd = new WindowInteropHelper(window).Handle;
return Camera_StartCapture(hwnd) == 0;
}
public bool StopCapture()
{
return Camera_StopCapture() == 0;
}
}
原因:
解决方案:
原因:
解决方案:
原因:
解决方案:
using System;
using System.Windows;
using System.Windows.Media.Imaging;
using DirectShowLib;
using System.Runtime.InteropServices;
public partial class MainWindow : Window
{
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaControl;
private ISampleGrabber _sampleGrabber;
public MainWindow()
{
InitializeComponent();
InitializeCamera();
}
private void InitializeCamera()
{
try
{
// 创建Filter Graph
_filterGraph = (IFilterGraph2)new FilterGraph();
// 添加视频输入设备
DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
if (devices.Length == 0) throw new Exception("未找到摄像头");
int hr = _filterGraph.AddSourceFilterForMoniker(
devices[0].Mon, null, devices[0].Name, out IBaseFilter sourceFilter);
DsError.ThrowExceptionForHR(hr);
// 创建Sample Grabber
IBaseFilter grabber = (IBaseFilter)new SampleGrabber();
hr = _filterGraph.AddFilter(grabber, "Sample Grabber");
DsError.ThrowExceptionForHR(hr);
_sampleGrabber = (ISampleGrabber)grabber;
// 设置媒体类型为RGB24
var mediaType = new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24
};
hr = _sampleGrabber.SetMediaType(mediaType);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(mediaType);
// 设置回调
hr = _sampleGrabber.SetCallback(new SampleGrabberCallback(this), 1);
DsError.ThrowExceptionForHR(hr);
// 创建Null Renderer用于视频渲染
IBaseFilter nullRenderer = (IBaseFilter)new NullRenderer();
hr = _filterGraph.AddFilter(nullRenderer, "Null Renderer");
DsError.ThrowExceptionForHR(hr);
// 连接过滤器
hr = _filterGraph.Connect(
DsFindPin.ByName(sourceFilter, "Capture"),
DsFindPin.ByName(grabber, "Input"));
DsError.ThrowExceptionForHR(hr);
hr = _filterGraph.Connect(
DsFindPin.ByName(grabber, "Output"),
DsFindPin.ByName(nullRenderer, "In"));
DsError.ThrowExceptionForHR(hr);
// 开始捕获
_mediaControl = (IMediaControl)_filterGraph;
hr = _mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
catch (Exception ex)
{
MessageBox.Show($"初始化摄像头失败: {ex.Message}");
}
}
private void UpdateImage(IntPtr buffer, int width, int height)
{
Dispatcher.Invoke(() =>
{
var bitmap = new WriteableBitmap(width, height, 96, 96,
System.Windows.Media.PixelFormats.Bgr24, null);
bitmap.Lock();
CopyMemory(bitmap.BackBuffer, buffer, (uint)(width * height * 3));
bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
bitmap.Unlock();
CameraImage.Source = bitmap;
});
}
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
private static extern void CopyMemory(IntPtr dest, IntPtr src, uint length);
private class SampleGrabberCallback : ISampleGrabberCB
{
private readonly MainWindow _window;
public SampleGrabberCallback(MainWindow window)
{
_window = window;
}
public int SampleCB(double sampleTime, IMediaSample pSample)
{
return 0;
}
public int BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
// 假设图像为640x480 RGB24
_window.UpdateImage(pBuffer, 640, 480);
return 0;
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
_mediaControl?.Stop();
}
}