Camera.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4. namespace AutoFocusTool.Camera
  5. {
  6. /// <summary>
  7. /// Microview MVC2000 相机封装。精简自原工程 aivfo_ccd\Util\Camera.cs +
  8. /// ivf_tl_CameraHelper\Camera.cs,只保留自动对焦测试程序需要的能力:
  9. /// 连接 / 采集模式 / 抓单帧 / 调曝光增益 / 取像素 / 转 WPF 位图 / 序列号。
  10. ///
  11. /// 重要:所有原生调用用同一把锁串行化(SDK 非线程安全)。
  12. /// 多舱室共用同一 SDK,跨相机操作也走这把全局锁。
  13. /// </summary>
  14. public class Camera : IDisposable
  15. {
  16. private static readonly object Locker = new object();
  17. private readonly int _width;
  18. private readonly int _height;
  19. private int _index;
  20. private int _exposure;
  21. private CapInfoStruct _capInfo;
  22. private IntPtr _hImager; // MV_Usb2Init 返回的设备句柄
  23. private IntPtr _pDest; // RGB 输出缓冲(width*height*3)
  24. public int Index => _index;
  25. public int Width => _width;
  26. public int Height => _height;
  27. public int Exposure => _exposure;
  28. public string SerialNumber { get; private set; } = "";
  29. public bool IsInit { get; private set; }
  30. public bool IsStart { get; private set; }
  31. /// <param name="index">相机枚举索引 0..9(MV_Usb2Init 用)</param>
  32. /// <param name="width">分辨率宽,默认 1600</param>
  33. /// <param name="height">分辨率高,默认 1200</param>
  34. /// <param name="exposure">曝光时间,单位 100us</param>
  35. public Camera(int index, int width = 1600, int height = 1200, int exposure = 400)
  36. {
  37. _index = index;
  38. _width = width;
  39. _height = height;
  40. _exposure = exposure;
  41. _pDest = Marshal.AllocCoTaskMem(_width * _height * 3);
  42. }
  43. /// <summary>初始化相机。执行后需立即 SetOpMode 才能抓图。返回 0 成功。</summary>
  44. public int Init(byte redGain = 25, byte greenGain = 14, byte blueGain = 25)
  45. {
  46. _capInfo.Buffer = Marshal.AllocCoTaskMem(_width * _height * 3);
  47. _capInfo.Width = _width;
  48. _capInfo.Height = _height;
  49. _capInfo.HorizontalOffset = 0;
  50. _capInfo.VerticalOffset = 0;
  51. _capInfo.Exposure = _exposure;
  52. _capInfo.Gain = new byte[] { redGain, greenGain, blueGain };
  53. _capInfo.Control = 0x04;
  54. _capInfo.Reserved = new byte[8];
  55. int result;
  56. lock (Locker)
  57. {
  58. result = MVCAPI.MV_Usb2Init("MVC2000", out _index, ref _capInfo, out _hImager);
  59. }
  60. IsInit = result == 0;
  61. return result;
  62. }
  63. /// <summary>设置采集模式:0=拍照(单帧,对焦用),1=实时图像。返回 0 成功。</summary>
  64. public int SetOpMode(byte mode = 0, bool strobe = false)
  65. {
  66. if (!IsInit) return -1;
  67. int result;
  68. lock (Locker)
  69. {
  70. result = MVCAPI.MV_Usb2SetOpMode(_hImager, mode, strobe);
  71. }
  72. IsStart = result == 0;
  73. return result;
  74. }
  75. /// <summary>读相机序列号到 SerialNumber。返回 0 成功。</summary>
  76. public int ReadSerial()
  77. {
  78. try
  79. {
  80. lock (Locker)
  81. {
  82. var sb = new StringBuilder(125);
  83. int r = MVCAPI.MV_Usb2GetSerial(_hImager, sb);
  84. SerialNumber = sb.ToString();
  85. return r;
  86. }
  87. }
  88. catch { return -2; }
  89. }
  90. /// <summary>抓取一帧 RGB 到内部缓冲。返回 0 成功,之后用 GetSourceBuffer / GetBitmapSource 取。</summary>
  91. public int GrabRgb()
  92. {
  93. if (!IsStart) return -1;
  94. lock (Locker)
  95. {
  96. return MVCAPI.MV_Usb2GetRgbData(_hImager, ref _capInfo, _pDest);
  97. }
  98. }
  99. /// <summary>设置曝光时间(单位 100us)。返回 0 成功。</summary>
  100. public int SetExposure(int exposure100us)
  101. {
  102. _exposure = exposure100us;
  103. _capInfo.Exposure = exposure100us;
  104. lock (Locker)
  105. {
  106. return MVCAPI.MV_Usb2SetPartOfCapInfo(_hImager, ref _capInfo);
  107. }
  108. }
  109. /// <summary>设置 RGB 三通道增益(0-255)。返回 0 成功。</summary>
  110. public int SetGain(byte red, byte green, byte blue)
  111. {
  112. if (_capInfo.Gain == null) _capInfo.Gain = new byte[3];
  113. _capInfo.Gain[0] = red;
  114. _capInfo.Gain[1] = green;
  115. _capInfo.Gain[2] = blue;
  116. lock (Locker)
  117. {
  118. return MVCAPI.MV_Usb2SetPartOfCapInfo(_hImager, ref _capInfo);
  119. }
  120. }
  121. /// <summary>取当前帧像素(24bpp BGR,width*height*3 字节,未翻转)。</summary>
  122. public byte[] GetSourceBuffer()
  123. {
  124. byte[] buf = new byte[_width * _height * 3];
  125. Marshal.Copy(_pDest, buf, 0, buf.Length);
  126. return buf;
  127. }
  128. /// <summary>卸载相机。</summary>
  129. public int UnInit()
  130. {
  131. int result = 0;
  132. lock (Locker)
  133. {
  134. if (_hImager != IntPtr.Zero)
  135. result = MVCAPI.MV_Usb2Uninit(ref _hImager);
  136. }
  137. IsInit = false;
  138. IsStart = false;
  139. return result;
  140. }
  141. public void Dispose()
  142. {
  143. try { UnInit(); } catch { }
  144. if (_pDest != IntPtr.Zero) { Marshal.FreeCoTaskMem(_pDest); _pDest = IntPtr.Zero; }
  145. if (_capInfo.Buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(_capInfo.Buffer); _capInfo.Buffer = IntPtr.Zero; }
  146. }
  147. }
  148. }