using System; using System.Runtime.InteropServices; using System.Text; namespace AutoFocusTool.Camera { /// /// Microview MVC2000 相机封装。精简自原工程 aivfo_ccd\Util\Camera.cs + /// ivf_tl_CameraHelper\Camera.cs,只保留自动对焦测试程序需要的能力: /// 连接 / 采集模式 / 抓单帧 / 调曝光增益 / 取像素 / 转 WPF 位图 / 序列号。 /// /// 重要:所有原生调用用同一把锁串行化(SDK 非线程安全)。 /// 多舱室共用同一 SDK,跨相机操作也走这把全局锁。 /// public class Camera : IDisposable { private static readonly object Locker = new object(); private readonly int _width; private readonly int _height; private int _index; private int _exposure; private CapInfoStruct _capInfo; private IntPtr _hImager; // MV_Usb2Init 返回的设备句柄 private IntPtr _pDest; // RGB 输出缓冲(width*height*3) public int Index => _index; public int Width => _width; public int Height => _height; public int Exposure => _exposure; public string SerialNumber { get; private set; } = ""; public bool IsInit { get; private set; } public bool IsStart { get; private set; } /// 相机枚举索引 0..9(MV_Usb2Init 用) /// 分辨率宽,默认 1600 /// 分辨率高,默认 1200 /// 曝光时间,单位 100us public Camera(int index, int width = 1600, int height = 1200, int exposure = 400) { _index = index; _width = width; _height = height; _exposure = exposure; _pDest = Marshal.AllocCoTaskMem(_width * _height * 3); } /// 初始化相机。执行后需立即 SetOpMode 才能抓图。返回 0 成功。 public int Init(byte redGain = 25, byte greenGain = 14, byte blueGain = 25) { _capInfo.Buffer = Marshal.AllocCoTaskMem(_width * _height * 3); _capInfo.Width = _width; _capInfo.Height = _height; _capInfo.HorizontalOffset = 0; _capInfo.VerticalOffset = 0; _capInfo.Exposure = _exposure; _capInfo.Gain = new byte[] { redGain, greenGain, blueGain }; _capInfo.Control = 0x04; _capInfo.Reserved = new byte[8]; int result; lock (Locker) { result = MVCAPI.MV_Usb2Init("MVC2000", out _index, ref _capInfo, out _hImager); } IsInit = result == 0; return result; } /// 设置采集模式:0=拍照(单帧,对焦用),1=实时图像。返回 0 成功。 public int SetOpMode(byte mode = 0, bool strobe = false) { if (!IsInit) return -1; int result; lock (Locker) { result = MVCAPI.MV_Usb2SetOpMode(_hImager, mode, strobe); } IsStart = result == 0; return result; } /// 读相机序列号到 SerialNumber。返回 0 成功。 public int ReadSerial() { try { lock (Locker) { var sb = new StringBuilder(125); int r = MVCAPI.MV_Usb2GetSerial(_hImager, sb); SerialNumber = sb.ToString(); return r; } } catch { return -2; } } /// 抓取一帧 RGB 到内部缓冲。返回 0 成功,之后用 GetSourceBuffer / GetBitmapSource 取。 public int GrabRgb() { if (!IsStart) return -1; lock (Locker) { return MVCAPI.MV_Usb2GetRgbData(_hImager, ref _capInfo, _pDest); } } /// 设置曝光时间(单位 100us)。返回 0 成功。 public int SetExposure(int exposure100us) { _exposure = exposure100us; _capInfo.Exposure = exposure100us; lock (Locker) { return MVCAPI.MV_Usb2SetPartOfCapInfo(_hImager, ref _capInfo); } } /// 设置 RGB 三通道增益(0-255)。返回 0 成功。 public int SetGain(byte red, byte green, byte blue) { if (_capInfo.Gain == null) _capInfo.Gain = new byte[3]; _capInfo.Gain[0] = red; _capInfo.Gain[1] = green; _capInfo.Gain[2] = blue; lock (Locker) { return MVCAPI.MV_Usb2SetPartOfCapInfo(_hImager, ref _capInfo); } } /// 取当前帧像素(24bpp BGR,width*height*3 字节,未翻转)。 public byte[] GetSourceBuffer() { byte[] buf = new byte[_width * _height * 3]; Marshal.Copy(_pDest, buf, 0, buf.Length); return buf; } /// 卸载相机。 public int UnInit() { int result = 0; lock (Locker) { if (_hImager != IntPtr.Zero) result = MVCAPI.MV_Usb2Uninit(ref _hImager); } IsInit = false; IsStart = false; return result; } public void Dispose() { try { UnInit(); } catch { } if (_pDest != IntPtr.Zero) { Marshal.FreeCoTaskMem(_pDest); _pDest = IntPtr.Zero; } if (_capInfo.Buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(_capInfo.Buffer); _capInfo.Buffer = IntPtr.Zero; } } } }