HuaRui/HikCamera.cs

551 lines
25 KiB
C#
Raw Permalink Normal View History

2024-08-17 14:06:39 +08:00
using Autofac.Core;
using MvCamCtrl.NET;
using OpenCvSharp;
using OpenCvSharp.Dnn;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace YSDetection
{
public class HikCamera
{
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
int nRet = MyCamera.MV_OK;
MyCamera.cbExceptiondelegate pCallBackFunc;
public MyCamera device = new MyCamera();
bool m_bGrabbing = false;
Thread m_hReceiveThread = null;
MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
MyCamera.MV_CC_DEVICE_INFO stDevInfo = new MyCamera.MV_CC_DEVICE_INFO();
// ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver
UInt32 m_nBufSizeForDriver = 0;
IntPtr m_BufForDriver = IntPtr.Zero;
private static Object BufForDriverLock = new Object();
bool _snapFlag = false;
public MyCamera.cbOutputExdelegate ImageCallback;
MyCamera.MV_FRAME_OUT _frame = new MyCamera.MV_FRAME_OUT();
readonly ManualResetEvent _snapHandle = new ManualResetEvent(false);
//ImageSet _bufferImgSet = null;
ManualResetEvent _bufferHandle = new ManualResetEvent(false);
public Action<DateTime, Mat, int> OnHImageOutput { get; set; }
public Action<DateTime, Mat, int> OnHImageOutput2 { get; set; }
/// <summary>
/// 相机拍照计数
/// </summary>
public volatile int SnapshotCount = 0;
public bool Ifsucess = false;
public HikCamera() { }
private void DeviceListAcq()
{
// ch:创建设备列表 | en:Create Device List
System.GC.Collect();
// cbDeviceList.Items.Clear();
// m_stDeviceList.nDeviceNum = 0;
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
if (0 != nRet)
{
// ShowErrorMsg("Enumerate devices fail!", 0);
return;
}
// ch:在窗体列表中显示设备名 | en:Display device name in the form list
for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
{
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
if (gigeInfo.chUserDefinedName != "")
{
//cbDeviceList.Items.Add("GEV: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")");
}
else
{
// cbDeviceList.Items.Add("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")");
}
}
else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
{
MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
if (usbInfo.chUserDefinedName != "")
{
//cbDeviceList.Items.Add("U3V: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")");
}
else
{
//cbDeviceList.Items.Add("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")");
}
}
}
// ch:选择第一项 | en:Select the first item
if (m_stDeviceList.nDeviceNum != 0)
{
//cbDeviceList.SelectedIndex = 0;
}
}
public bool Start(string id)
{
#region IP地址匹配连接相机
//将IP地址转换为字节数组
uint intAddress = 0;
if (/*(IIConfig.HikCameraType == EnumHelper.HikCameraType.Gige) &&*/ (!string.IsNullOrWhiteSpace(id)))
{
byte[] IPArr = IPAddress.Parse(id).GetAddressBytes();
for (int i = 0; i < IPArr.Length; i++)
{
intAddress += (uint)(IPArr[i] << (IPArr.Length - 1 - i) * 8);
}
}
MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList);
if (0 != nRet)
{
throw new Exception($"Enumerate devices fail!");
}
else
{
//LogAsync(DateTime.Now, $"搜索获取{m_pDeviceList.nDeviceNum.ToInt()}台相机在线", "");
}
bool isCameraFound = false;
for (int i = 0; i < m_pDeviceList.nDeviceNum; i++)
{
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
IntPtr buffer = IntPtr.Zero;
if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0);
MyCamera.MV_GIGE_DEVICE_INFO stGigEDev = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
if (stGigEDev.nCurrentIp == intAddress)
{
stDevInfo = device;
isCameraFound = true;
}
}
else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
{
//buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stUsb3VInfo, 0);
//MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_USB3_DEVICE_INFO));
//if (usbInfo.chSerialNumber == IConfig.SerialNum)
//{
// stDevInfo = device;
// isCameraFound = true;
//}
}
//释放内存空间
//Marshal.FreeHGlobal(buffer);
if (isCameraFound)
break;
}
if (!isCameraFound)
{
throw new Exception($"相机未能找到");
}
#endregion
// ch:创建设备 | en: Create device
nRet = device.MV_CC_CreateDevice_NET(ref stDevInfo);
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Create device failed:{nRet:x8}");
}
// ch:打开设备 | en:Open device
nRet = device.MV_CC_OpenDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Open device failed:{nRet:x8}");
}
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
int nPacketSize = device.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
nRet = device.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
if (nRet != MyCamera.MV_OK)
{
Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
}
}
else
{
Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
}
}
// ch:注册异常回调函数 | en:Register Exception Callback
nRet = device.MV_CC_RegisterExceptionCallBack_NET(pCallBackFunc, IntPtr.Zero);
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Register expection callback failed:{nRet}");
}
GC.KeepAlive(pCallBackFunc);
// ch:设置采集连续模式 | en:Set Continues Aquisition Mode
device.MV_CC_SetEnumValue_NET("AcquisitionMode", 2);// ch:工作在连续模式 | en:Acquisition On Continuous Mode
if (false)
{
device.MV_CC_SetEnumValue_NET("TriggerMode", 0); // ch:连续模式 | en:Continuous
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Register image callback failed!");
}
}
else
{
// ch:设置触发模式为off || en:set trigger mode as off
nRet = device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Set TriggerMode failed!");
}
if (false)
{
// ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
// 1 - Line1;
// 2 - Line2;
// 3 - Line3;
// 4 - Counter;
// 7 - Software;
nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", 0);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Set Line0 Trigger failed!");
}
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Register image callback failed!");
}
}
else
{
nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", 7);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Set Software Trigger failed!");
}
}
}
// ch:开启抓图 || en: start grab image
nRet = device.MV_CC_StartGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Start grabbing failed:{nRet:x8}");
}
else
{
Ifsucess = true;
}
return true;
}
public void Stop(MyCamera hik)
{
if(Ifsucess)
{
// IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
// ch:停止抓图 | en:Stop grab image
nRet = hik.MV_CC_StopGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Stop grabbing failed{nRet:x8}");
}
// ch:关闭设备 | en:Close device
nRet = hik.MV_CC_CloseDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Close device failed{nRet:x8}");
}
// ch:销毁设备 | en:Destroy device
nRet = hik.MV_CC_DestroyDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Destroy device failed:{nRet:x8}");
}
}
Ifsucess = false;
}
void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
try
{
// if (false)
// {
// // SnapshotCount++;
// Interlocked.Increment(ref SnapshotCount);
// // Console.WriteLine($">>>> {IIConfig.Name} 相机硬触发...");
// //LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机硬触发");
// //Stopwatch sw = new Stopwatch();
// //sw.Start();
// int nWidth = pFrameInfo.nWidth;
// int nHeight = pFrameInfo.nHeight;
// //HImage hImage = new HImage();
// //HObject Hobj = new HObject();
// //IntPtr pTemp = IntPtr.Zero;
// //hImage.GenImage1((HTuple)"byte", nWidth, nHeight, pData);
// //var imgSet = new ImageSet
// //{
// // HImage = hImage,
// // ImageSaveOption = IConfig.ImageSaveOption.Copy()
// //};
// //测试图片颜色
// //if (IsColor(pFrameInfo.enPixelType))
// //{
// // //pFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
// // // 彩色图
// // switch (pFrameInfo.enPixelType)
// // {
// // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
// // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_gr", "bilinear");
// // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage();
// // break;
// // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
// // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_rg", "bilinear");
// // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage();
// // break;
// // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
// // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_gb", "bilinear");
// // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage();
// // break;
// // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
// // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_bg", "bilinear");
// // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage();
// // break;
// // }
// //}
// if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
// {
// // Console.WriteLine("image pixel format is rgb8...");
// //pTemp = pData;
// //HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
// //HobjectToRGBHimage(Hobj, ref hImage);
// }
// // Console.WriteLine($">>>> {IIConfig.Name} 相机数据转换完成 ...");
// //if (!IsMonoData(pFrameInfo.enPixelType))
// //{
// // pImageBuf = Marshal.AllocHGlobal((int)stFrameInfo.nWidth * stFrameInfo.nHeight * 3);
// // HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
// //}
//#if false
// if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
// {
// //加入内部队列
// InitialImageSet(imgSet);
// //业务图片处理加入外部队列
// var outImgSet = CopyImageSet(imgSet);
// if (IIConfig.IsDirectHardwareTrigger)
// {
// //传感器直接触发 收到图片后 传出
// OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet);
// }
// else
// {
// _bufferImgSet = outImgSet;
// //_bufferImgSetQueue.Enqueue(outImgSet);
// _bufferHandle.Set();
// }
// ClearImageSet(imgSet);
// }
// else
// {
// Console.WriteLine($">>>> 像素类型:{pFrameInfo.enPixelType}");
// }
//#else
// //加入内部队列
// InitialImageSet(imgSet);
// //业务图片处理加入外部队列
// var outImgSet = CopyImageSet(imgSet);
// // LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机取像, 次数:{SnapshotCount}");
// // Console.WriteLine($">>>> {IIConfig.Name} 相机回调 OnHImageOutput ...");
// if (IIConfig.IsDirectHardwareTrigger)
// {
// // 传感器直接触发 收到图片后 传出
// OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet);
// }
// else
// {
// _bufferImgSet = outImgSet;
// // _bufferImgSetQueue.Enqueue(outImgSet);
// _bufferHandle.Set();
// }
// //处理完图片 会清理内部队列的图像
// DisplayAndSaveOriginImage(imgSet.Id);
// //ClearImageSet(imgSet);
//#endif
// }
//else
//{
if (_snapFlag)
{
_snapFlag = false;
_frame = new MyCamera.MV_FRAME_OUT
{
stFrameInfo = pFrameInfo,
pBufAddr = pData
};
_snapHandle.Set();
}
// }
}
catch (Exception ex)
{
//LogAsync(DateTime.Now, LogLevel.Exception, $"{Name}相机取像异常,{ex.GetExceptionMessage()}");
}
}
public void Snapshot()
{
Stopwatch sw = new Stopwatch();
sw.Start();
// ImageSet set = new ImageSet();
// set.SnapshotCount = SnapshotCount;
// set.SnapshotFileName = SnapshotFileNames;
//InitialImageSet(set);
MyCamera.MV_FRAME_OUT frameInfo = new MyCamera.MV_FRAME_OUT();
nRet = MyCamera.MV_OK;
if (true)
{
// ch: 触发命令 || en: Trigger command
nRet = device.MV_CC_SetCommandValue_NET("TriggerSoftware");
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"相机拍照触发失败:{nRet}");
}
nRet = device.MV_CC_GetImageBuffer_NET(ref frameInfo, 1000);
nRet = device.MV_CC_FreeImageBuffer_NET(ref frameInfo);
}
else
{
_snapHandle.Reset();
_snapFlag = true;
_snapHandle.WaitOne();
//lock (_imgCallBackLock)
{
frameInfo.stFrameInfo = _frame.stFrameInfo;
frameInfo.pBufAddr = _frame.pBufAddr;
}
}
// ch:获取一帧图像 | en:Get one image
if (MyCamera.MV_OK == nRet)
{
if (frameInfo.pBufAddr != IntPtr.Zero)
{
if (nRet == MyCamera.MV_OK)
{
var pFrameInfo = frameInfo.stFrameInfo;
//图像格式存储格式
Mat mat=new Mat(pFrameInfo.nHeight, pFrameInfo.nWidth, MatType.CV_8UC1, frameInfo.pBufAddr);
OnHImageOutput?.Invoke(DateTime.Now, mat, SnapshotCount);
mat.ImWrite("D://123.jpg");
//OnHImageOutput2?.Invoke(DateTime.Now, mat2, SnapshotCount);
//mat2.ImWrite("D://456.jpg");
//HImage hImage = new HImage();
//HObject Hobj = new HObject();
//IntPtr pTemp = IntPtr.Zero;
//hImage.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, frameInfo.pBufAddr);
////hImage.ConvertHImageTo16GrayBitmap();
//var imgSet = new ImageSet
//{
// HImage = hImage,
// ImageSaveOption = IConfig.ImageSaveOption.Copy()
//};
//if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
//{
// // Console.WriteLine("image pixel format is rgb8...");
// pTemp = frameInfo.pBufAddr;
// HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
// HobjectToRGBHimage(Hobj, ref hImage);
//}
//加入内部队列
//InitialImageSet(imgSet);
////业务图片处理加入外部队列
//var outImgSet = CopyImageSet(imgSet);
//OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet);
//LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机取像, 次数:{SnapshotCount}");
//DisplayAndSaveOriginImage(imgSet.Id);
//HikToBitmap(pFrameInfo, frameInfo.pBufAddr);
//Generate8GrayImageByPointer((int)nWidth, (int)nHeight, frameInfo.pBufAddr, "");
}
}
}
else
{
throw new Exception($"Grap Image Failed:{nRet:x8}");
}
sw.Stop();
//LogAsync(DateTime.Now, LogLevel.Information, $"取像耗时:{sw.ElapsedMilliseconds} ms");
}
}
}