using IvfTl.Control.Entity.GlobalEnums; using System.Drawing; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; using System.Text; namespace ivf_tl_CameraHelper { /// /// 相机助手类 /// public class Camera { public event Action ExceptionLogEvent; public event Action HouseLogEvent; private int index = 0; private int width = 0; private int height = 0; private int exposure = 0; public int camnums = 0; [MarshalAs(UnmanagedType.LPTStr)] public string NumBer = ""; /// /// MVC数字相机的索引号(从0开始),用于指定要进行初始化操作的相机。 /// public int Index { get { return index; } } /// /// 图像宽度 /// public int Width { get { return width; } } /// /// 图像高度 /// public int Height { get { return height; } } /// /// 曝光时间(单位:100us) /// public int Exposure { get { return exposure; } } /// /// CCD是否加载 /// public bool IsInit { get; set; } = false; /// /// CCD是否开启 /// public bool IsStart { get; set; } = false; /// /// 图像字节数组 /// public byte[] SourceBuffer //{ get; private set; } { get { byte[] sourceBuffer = new byte[this.width * this.height * 3]; Marshal.Copy(pDest, sourceBuffer, 0, sourceBuffer.Length); return sourceBuffer; } } public byte[] SaveRgbData = new byte[3]; public void UpdataSourceBuffer() { //SourceBuffer = new byte[this.width * this.height * 3]; //Marshal.Copy(pDest, SourceBuffer, 0, SourceBuffer.Length); } /// /// 获取相机对应得序列号 /// /// [HandleProcessCorruptedStateExceptions] [SecurityCritical] public int GetNumbet() { try { int result = -1; lock (locker) { StringBuilder strSerial = new StringBuilder(125); result = MVCAPI.MV_Usb2GetSerial(this.hImager, strSerial); NumBer = strSerial.ToString(); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, "获取序列号", null, LogEnum.RunException); return -2; } } /// /// 获取一张图像 /// //public BitmapImage BitmapImage //{ // get // { // Bitmap bitmap = new Bitmap(this.width, this.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); // System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bitmap.PixelFormat); // Marshal.Copy(this.SourceBuffer, 0, bmpData.Scan0, this.SourceBuffer.Length); // bitmap.UnlockBits(bmpData); // bitmap.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipY); // BitmapImage bitmapImage = new BitmapImage(); // using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) // { // bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); // bitmapImage.BeginInit(); // bitmapImage.StreamSource = ms; // bitmapImage.CacheOption = BitmapCacheOption.OnLoad; // bitmapImage.EndInit(); // bitmapImage.Freeze(); // } // return bitmapImage; // } //} /// /// 结构体 /// private CapInfoStruct capInfoStruct = new CapInfoStruct(); /// /// 由MV_Usb2Init返回的MVC设备句柄 /// public IntPtr hImager; /// /// 回传的图像字节数组 /// private IntPtr pDest; public Camera(int index, int width, int height, int exposure) { this.index = index; this.width = width; this.height = height; this.exposure = exposure; pDest = Marshal.AllocCoTaskMem(this.width * this.height * 3); } public Camera(CameraModel model) { this.index = model.Index; this.width = model.Width; this.height = model.Height; this.exposure = model.Exposure; pDest = Marshal.AllocCoTaskMem(this.width * this.height * 3); } /// /// 初使化相机[注:执行init()之后立即执行SetOpMode()以开启像捕捉 2021.11.11] /// /// public int Init() { try { byte[] mGain = new byte[3]; mGain[0] = Convert.ToByte(25); mGain[1] = Convert.ToByte(14); mGain[2] = Convert.ToByte(25); byte Control = Convert.ToByte(04); capInfoStruct.Buffer = Marshal.AllocCoTaskMem(this.width * this.height * 3); capInfoStruct.Width = this.width; capInfoStruct.Height = this.height; capInfoStruct.HorizontalOffset = 0; capInfoStruct.VerticalOffset = 0; capInfoStruct.Exposure = this.exposure; capInfoStruct.Gain = mGain; capInfoStruct.Control = Control; var result = InitCamera(this); if (result == 0) this.IsInit = true; // D1-10:相机初始化边界审计埋点(module=相机)。全 try 兜底,镜像 operate 死栈同款 P3b。 try { Aivfo.OperationLog.OperationLogger.Log("相机", "初始化", input: new { index, width, height, exposure }, output: new { result }, result: result == 0 ? "成功" : "失败", error: result == 0 ? null : $"InitCamera 返回 {result}"); } catch { } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机初始化", null, LogEnum.RunException); return -2; } } public bool DisPose() { try { Marshal.FreeCoTaskMem(capInfoStruct.Buffer); Marshal.FreeCoTaskMem(pDest); return true; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机释放内存", null, LogEnum.RunException); return false; } } public int Usb2Start(IntPtr mControlPtr, int left, int top, int width, int height) { var nRetValue = MVCAPI.MV_Usb2Start(hImager, "MVC Camera Preview", MVCAPI.WS_CHILD | MVCAPI.WS_VISIBLE, left, top, width, height, mControlPtr, 0, (int)System.Threading.ThreadPriority.Highest, (int)System.Threading.ThreadPriority.Highest); return nRetValue; } public int Usb2Stop() { var nRetValue = MVCAPI.MV_Usb2Stop(hImager); return nRetValue; } public int Usb2StartCapture() { try { var nRetValue = MVCAPI.MV_Usb2StartCapture(hImager, true); return nRetValue; } catch (Exception) { return -1; } } public int Usb2StopCapture() { try { var nRetValue = MVCAPI.MV_Usb2StartCapture(hImager, false); return nRetValue; } catch (Exception) { return -1; } } /// /// 多个方法共同锁 /// private static readonly object locker = new object(); [HandleProcessCorruptedStateExceptions] [SecurityCritical] private int InitCamera(Camera camera) { try { int result = -1; lock (locker) { //MVC2000 result = MVCAPI.MV_Usb2Init("MVC2000", out camera.index, ref camera.capInfoStruct, out camera.hImager); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{camera.index}号相机初始化", null, LogEnum.RunException); return -2; } } /// /// 卸载相机 /// /// public int UnInit() { try { this.IsInit = false; var result = UnInit(this); // D1-10:相机卸载边界审计埋点(module=相机)。全 try 兜底。 try { Aivfo.OperationLog.OperationLogger.Log("相机", "卸载", input: new { index }, output: new { result }, result: result == 0 ? "成功" : "失败"); } catch { } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机卸载", null, LogEnum.RunException); return -1; } } [HandleProcessCorruptedStateExceptions] [SecurityCritical] private int UnInit(Camera camera) { try { int result = -1; lock (locker) { result = MVCAPI.MV_Usb2Uninit(ref hImager); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{camera.index}号相机卸载", null, LogEnum.RunException); return -2; } } /// /// 设置摄像头的采集模式为连续采集模式 /// /// public int SetOpMode() { try { if (this.IsInit == false) return -1; var result = SetOpMode(this); this.IsStart = result == 0; return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机设置采集模式", null, LogEnum.RunException); return -1; } } [HandleProcessCorruptedStateExceptions] [SecurityCritical] private int SetOpMode(Camera camera) { try { int result = -1; lock (locker) { result = MVCAPI.MV_Usb2SetOpMode(camera.hImager, 0, false); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{camera.index}号相机设置采集模式", null, LogEnum.RunException); return -2; } } /// /// 抓取一张图像 /// /// 返回该图字节数组 public int GetRgbData() { try { if (this.IsStart == false) return -1; return GetRgbData(this); } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机抓图", null, LogEnum.RunException); return -2; } } [HandleProcessCorruptedStateExceptions] [SecurityCritical] private int GetRgbData(Camera camera) { try { int result = -1; lock (locker) { result = MVCAPI.MV_Usb2GetRgbData(camera.hImager, ref camera.capInfoStruct, camera.pDest); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{camera.index}号相机抓图", null, LogEnum.RunException); return -2; } } /// /// 抓取一张图像 /// /// 返回该图字节数组 public int GetRawData() { if (this.IsStart == false) return -1; return GetRawData(this); } private int GetRawData(Camera camera) { try { int result = -1; lock (locker) { result = MVCAPI.MV_Usb2GetRawData(camera.hImager, ref camera.capInfoStruct); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机抓图", null, LogEnum.RunException); return -2; } } public int GetCamNum() { try { if (this.IsStart == false) return -1; int nRetValue = -1; nRetValue = MVCAPI.MV_Usb2GetNumberDevicesEX(out camnums); if (nRetValue == 0) return camnums; ExceptionLogEvent?.Invoke(new Exception($"{index}号相机获取相机数量失败"), $"{index}号相机获取相机数量", null, LogEnum.RunException); return nRetValue; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机获取相机数量", null, LogEnum.RunException); return -2; } } /// /// 抓取一张图像 /// /// 返回该图字节数组 public int RawToRgb() { if (this.IsStart == false) return -1; return RawToRgb(this); } private int RawToRgb(Camera camera) { try { int result = -1; lock (locker) { result = MVCAPI.MV_Usb2ConvertRawToRgb(camera.hImager, camera.capInfoStruct.Buffer, camera.width, camera.height, camera.pDest); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机RawToRgb", null, LogEnum.RunException); return -2; } } /// /// 设置相机参数 /// /// /// public int SetPartOfCapInfo(int Exposure) { return SetPartOfCapInfo(this, Exposure); } [HandleProcessCorruptedStateExceptions] [SecurityCritical] public int SetPartOfCapInfo(Camera camera, int Exposure) { try { int result; capInfoStruct.Exposure = Exposure; //this.width = model.Width; //this.height = model.Height; //capInfoStruct.Gain[0] = Convert.ToByte(model.Red); //capInfoStruct.Gain[1] = Convert.ToByte(model.Green); //capInfoStruct.Gain[2] = Convert.ToByte(model.Blue); //capInfoStruct.HorizontalOffset = model.HorizontalOffset; //capInfoStruct.VerticalOffset = model.VerticalOffset; //capInfoStruct.Exposure = model.Exposure; //capInfoStruct.Width = this.width; //capInfoStruct.Height = this.height; //capInfoStruct.Buffer = Marshal.AllocCoTaskMem(this.width * this.height); //pDest = Marshal.AllocCoTaskMem(this.width * this.height * 3); lock (locker) { result = MVCAPI.MV_Usb2SetPartOfCapInfo(hImager, ref capInfoStruct); } return result; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{camera.index}号相机设置参数", null, LogEnum.RunException); return -2; } } /// /// 保存当前缓存中的原图 /// /// /// public bool SaveBmpPic(string fullName) { bool result = false; try { //位图对象 System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap( this.width, this.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); //图像数据 System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits( new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, bitmap.PixelFormat); Marshal.Copy(this.SourceBuffer, 0, bmpData.Scan0, this.SourceBuffer.Length); //解锁 bitmap.UnlockBits(bmpData); //翻转 bitmap.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipY); //保存 bitmap.Save(fullName); result = true; } catch { return result; } return result; } public bool SaveJPG(string fullName) { MemoryStream memoryStream = null; FileStream fs = null; bool success = false; try { memoryStream = new MemoryStream(this.SourceBuffer); fs = new FileStream(fullName, FileMode.OpenOrCreate); memoryStream.WriteTo(fs); success = true; } catch (Exception ex) { success = false; } finally { if (fs != null) { fs.Close(); fs.Dispose(); } if (memoryStream != null) { memoryStream.Close(); memoryStream.Dispose(); } } return success; } public byte[] LastSourceBufferHash { get; set; } public void SavePreMem() { try { LastSourceBufferHash = GetHash(SourceBuffer); //var aa = SourceBuffer; //LastSourceBuffer = new byte[aa.Length]; //Buffer.BlockCopy(aa, 0, LastSourceBuffer, 0, aa.Length); //HouseLogEvent?.Invoke(DateTime.Now, $"{index}号相机保存后的数据比较 [{aa.SequenceEqual(LastSourceBuffer)}]", LogEnum.HouseRunRecord); //HouseLogEvent?.Invoke(DateTime.Now, $"{index}号相机保存数据记录开始 [{ByteToHexStr(SaveRgbData)}]", LogEnum.HouseRunRecord); //SaveRgbData[0] = aa[0]; //SaveRgbData[1] = aa[aa.Length / 2]; //SaveRgbData[2] = aa[aa.Length - 1]; //HouseLogEvent?.Invoke(DateTime.Now, $"{index}号相机保存数据记录结束 [{ByteToHexStr(SaveRgbData)}]", LogEnum.HouseRunRecord); } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机保存数据", null, LogEnum.RunException); } } public bool CheckRgbData() { try { //var aa = SourceBuffer; byte[] SourceBufferHash = GetHash(SourceBuffer); if (LastSourceBufferHash.SequenceEqual(SourceBufferHash)) { return false; } LastSourceBufferHash = new byte[SourceBufferHash.Length]; Buffer.BlockCopy(SourceBufferHash, 0, LastSourceBufferHash, 0, SourceBufferHash.Length); return true; //if (SourceBuffer.SequenceEqual(LastSourceBuffer)) //{ // return false; //} //return true; //var aa = SourceBuffer; //if (SaveRgbData[0] == aa[0] && SaveRgbData[1] == aa[aa.Length / 2] && SaveRgbData[2] == aa[aa.Length - 1]) //{ // return false; //} //return true; } catch (Exception ex) { ExceptionLogEvent?.Invoke(ex, $"{index}号相机校验拍照数据", null, LogEnum.RunException); return false; } } public string ByteToHexStr(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2") + " "; } } return returnStr; } public byte[] GetHash(byte[] bytes) { return SHA256.HashData(bytes); } } }