海康采图Demo
-
- 准备资料
- 代码流程分析
- 成果展示
#为中华工控崛起而开源
欢迎各位老铁一起交流 微信号:V1ncent-xuan。
准备资料
项目 | Value |
---|---|
项目依赖项 | halcon、halcondotnet、MvCameraControl.Net |
软件VS2019 | 链接: link. |
海康MVS | 链接: link. |
代码流程分析
- 1:UI设计
- 2:定义程序变量
private MyCamera m_Camera;
public MyCamera.cbOutputExdelegate ImageCallback;
private ManualResetEvent m_autoEvent = new ManualResetEvent(false);
private ConcurrentQueue<HImage> m_queImage = new ConcurrentQueue<HImage>();
private HWindow m_hWnd;
- 3:程序方法
- 按钮1:枚举、创建、打开、探测、图片尺寸、设置参数、开启抓图
private void button1_Click_1(object sender, EventArgs e)
{
MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList);
if (MyCamera.MV_OK != nRet)
{
Log(string.Format("HikVision Enum device failed:{0:x8}", nRet));
return;
}
if (stDevList.nDeviceNum<=0)
{
Log("枚举设备失败");
return;
}
MyCamera.MV_CC_DEVICE_INFO stDevInfo;
stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[0], typeof(MyCamera.MV_CC_DEVICE_INFO));
string strDeviceName = string.Empty;
if (MyCamera.MV_GIGE_DEVICE == stDevInfo.nTLayerType)
{
MyCamera.MV_GIGE_DEVICE_INFO stGigEDeviceInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
//Console.WriteLine("\n" + i.ToString() + ": [GigE] User Define Name : " + stGigEDeviceInfo.chUserDefinedName);
strDeviceName = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4;
Log($"打开相机IP:{strDeviceName}");
}
m_Camera = new MyCamera();
Log($"创建设备");
nRet = m_Camera.MV_CC_CreateDevice_NET(ref stDevInfo);
if (MyCamera.MV_OK != nRet)
{
return ;
}
// ch:打开设备 | en:Open device
Log($"打开设备");
nRet = m_Camera.MV_CC_OpenDevice_NET();
if (MyCamera.MV_OK != nRet)
{
Log($"打开设备失败");
return ;
}
Log($"探测网络最佳包");
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
int nPacketSize = m_Camera.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
Log($"nPacketSize>0");
nRet = m_Camera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
if (nRet != MyCamera.MV_OK)
{
}
}
else
{
Log($"nPacketSize<0");
}
}
Log($"获取包大小");
// ch:获取包大小 || en: Get Payload Size
MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
nRet = m_Camera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
if (MyCamera.MV_OK != nRet)
{
//LogHelper.Warn(string.Format("Warning: Get PayloadSize failed {0:x8}", nRet));
}
int width = 0, height = 0;//创建变量用于接收图像尺寸
nRet = m_Camera.MV_CC_GetIntValue_NET("HeightMax", ref stParam);
height= (int)stParam.nCurValue;
nRet = m_Camera.MV_CC_GetIntValue_NET("WidthMax", ref stParam);
width = (int)stParam.nCurValue;
m_hWnd.SetPart(0, 0, height - 1, width - 1);//设置Halcon控件中图像的显示尺寸
// ch:设置采集连续模式 | en:Set Continues Aquisition Mode
Log($"设置连续采集2");
nRet = m_Camera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
Log($"触发模式1");
nRet = m_Camera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
//软触发
Log($"软触发7");
nRet = m_Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MyCamera.cbOutputExdelegate(OnImageGrabbed);
nRet = m_Camera.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
// ch:开启抓图 || en: start grab image
nRet = m_Camera.MV_CC_StartGrabbing_NET();
}
- 按钮2:采图
private void button2_Click(object sender, EventArgs e)
{
// ch:触发命令 | en:Trigger command
int nRet = m_Camera.MV_CC_SetCommandValue_NET("TriggerSoftware");
Log("软触发一次");
}
- 3:采图窗体加载显示Handler图片线程。
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(ThreadProc);
thread.IsBackground = true;
thread.Start(m_queImage);
m_hWnd = this.hWindowControl1.HalconWindow;
}
private void ThreadProc( object obj)
{
//图片在队列 随便怎么处理。算法下期见!
ConcurrentQueue<HImage> queImage = obj as ConcurrentQueue<HImage>;
HImage image1 = new HImage();
while (true)
{
m_autoEvent.WaitOne();
if (queImage.Count>0)
{
queImage.TryDequeue(out image1);
//添加处理图像方法
//XXX
//最后显示
ShowImage(image1);
}
Thread.Sleep(100);
}
}
public void ShowImage( HImage image)
{
if (this.InvokeRequired)
{
this.BeginInvoke((MethodInvoker)delegate
{
ShowImage( image);
});
}
else
{
HSystem.SetSystem("flush_graphic", "false");
m_hWnd.ClearWindow();
m_hWnd.DispObj(image);
HSystem.SetSystem("flush_graphic", "true");
m_hWnd.SetColor("black");
m_hWnd.DispLine(-100.0, -100.0, -101.0, -101.0);
}
}
4 按钮2点击,采图后进入回调。
private void OnImageGrabbed(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
Log("Get one frame: Width[" + Convert.ToString(pFrameInfo.nWidth) + "] , Height[" + Convert.ToString(pFrameInfo.nHeight)
+ "] , FrameNum[" + Convert.ToString(pFrameInfo.nFrameNum) + "]");
HImage image = new HImage();
int nWidth = pFrameInfo.nWidth;
int nHeight = pFrameInfo.nHeight;
IntPtr pTemp = IntPtr.Zero;
pTemp = pData;
image.GenImage1Extern("byte", nWidth, nHeight, pTemp, IntPtr.Zero);
//防止一直采集把内存占满
if (m_queImage.Count > 5)
{
HImage temp;
m_queImage.TryDequeue(out temp);
}
m_queImage.Enqueue(image);
m_autoEvent.Set();
}
- 窗体关闭进行 资源关闭
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (m_Camera!=null)
{
int nRet = m_Camera.MV_CC_StopGrabbing_NET();
// ch:关闭设备 | en:Close device
nRet = m_Camera.MV_CC_CloseDevice_NET();
// ch:销毁设备 | en:Destroy device
nRet = m_Camera.MV_CC_DestroyDevice_NET();
}
m_Camera = null;
}