海康采圖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;
}