本文出處:https://www.cnblogs.com/xiawuhao2013/p/9295781.html
使用工業相機采集圖像,首先需要對相機的相關參數進行設置。現在項目需要使用SDK進行二次開發。依照以下步驟進行:
1.枚舉設備 -> 2.創建句柄 -> 3.打開設備 -> 4.開始抓圖 -> 5.獲取一幀並保存圖像 -> 6.停止抓圖 -> 7.關閉設備 -> 8.銷毀句柄
第一次使用海康相機SDK,初步按照以下流程進行開發:
第一步: 了解C接口流程。
a.設備連接 b.圖像采集顯示
設備連接接口流程:
主動取流流程圖
回調出流流程圖
第二步:學習實例代碼,查詢C接口定義
1. 枚舉設備
1 int MV_CC_EnumDevices(unsigned int nTLayerType, \
MV_CC_DEVICE_INFO_LIST *pstDevList);
參數:
nTLayerType [in] 傳輸層協議類型,按位表示,支持復選,可選協議類型如下:
pstDevList [out] 查找到的設備信息列表
返回值:
成功,返回MV_OK (0);失敗,返回錯誤碼。
1 #include "MvCameraControl.h" 2 3 void main() 4 { 5 unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE; 6 7 MV_CC_DEVICE_INFO_LIST m_stDevList = {0}; 8 int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); 9 if (MV_OK != nRet) 10 { 11 printf("error: EnumDevices fail [%x]\n", nRet); 12 } 13 }
2. 創建設備句柄
int MV_CC_CreateHandle(void **handle, const MV_CC_DEVIEC_INFO *pstDevInfo);
參數:
handle [out] 設備句柄,輸出參數;
pstDevInfo [in] 設備信息版本、MAC地址、傳輸層類型以及其它設備信息;
返回值:
成功,返回MV_OK (0);失敗,返回錯誤碼。
1 #include "MvCameraControl.h" 2 3 void main() 4 { 5 int nRet = -1; 6 void* m_handle = NULL; 7 8 //枚舉子網內指定的傳輸協議對應的所有設備 9 unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE; 10 MV_CC_DEVICE_INFO_LIST m_stDevList = {0}; 11 int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); 12 if (MV_OK != nRet) 13 { 14 printf("error: EnumDevices fail [%x]\n", nRet); 15 return; 16 } 17 18 int i = 0; 19 if (m_stDevList.nDeviceNum == 0) 20 { 21 printf("no camera found!\n"); 22 return; 23 } 24 25 //選擇查找到的第一台在線設備,創建設備句柄 26 int nDeviceIndex = 0; 27 28 MV_CC_DEVICE_INFO m_stDevInfo = {0}; 29 memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO)); 30 31 nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); 32 33 if (MV_OK != nRet) 34 { 35 printf("error: CreateHandle fail [%x]\n", nRet); 36 return; 37 } 38 39 //...其他處理 40 41 //銷毀句柄,釋放資源 42 nRet = MV_CC_DestroyHandle(m_handle); 43 if (MV_OK != nRet) 44 { 45 printf("error: DestroyHandle fail [%x]\n", nRet); 46 return; 47 } 48 }
3. 關閉設備
int MV_CC_CloseDevice(void *handle);
參數:
handle [in] 設備句柄,MV_CC_CreateHandle或MV_CC_CreateHandleWithoutLog的[out]參數。
4. 釋放句柄
int MV_CC_DestroyHandle(void *handle);
5. 注冊圖像數據回調函數,支持獲取chunk信息
int MV_CC_RegisterImageCallBackEx(void *handle, const char *pEventName, \
cbEvent cbEvent, void *pUser);
參數:
pEventName [in] 事件名;
fEventCallBack [in] 接收Event事件的回調函數
pUser [in] 用戶自定義變量
回調函數
void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser);
回調函數參數:
pEventInfo [out] 外部輸出Event Info;
pUser [out] 用戶自定義變量;
注意:通過該接口設置事件回調,可以在回調函數里面獲取采集、曝光等事件信息。
6. 開始采集圖像
int MV_CC_StartGrabbing(void *handle);
7. 獲取一幀圖像數據
int MV_CC_GetOneFrame(void *handle, unsigned char *pData, \ unsigned int nDataSize, \
MV_FRAME_OUT_INFO *pFrameInfo
);
參數:
pData [in] 用於保存圖像數據的緩存地址;
nDataSize [in] 緩存區大小;
pFrameInfo [out] 獲取到的幀信息;
int MV_CC_GetOneFrameTimeout(void *handle, \ unsigned char *pData, \ unsigned int nDataSize, \ MV_FRAME_OUT_INFO_EX *pFrameInfo, \
int nMsec);
參數:
nMsec [in] 等待超時時間,單位為毫秒;
注意:該接口對於U3V、GIGE相機均可支持。
#include "MvCameraControl.h" void main() { int nRet = -1; void* m_handle = NULL; //枚舉子網內指定的傳輸協議對應的所有設備 unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE; MV_CC_DEVICE_INFO_LIST m_stDevList = {0}; int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); if (MV_OK != nRet) { printf("error: EnumDevices fail [%x]\n", nRet); return; } int i = 0; if (m_stDevList.nDeviceNum == 0) { printf("no camera found!\n"); return; } //選擇查找到的第一台在線設備,創建設備句柄 int nDeviceIndex = 0; MV_CC_DEVICE_INFO m_stDevInfo = {0}; memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO)); nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); if (MV_OK != nRet) { printf("error: CreateHandle fail [%x]\n", nRet); return; } //連接設備 nRet = MV_CC_OpenDevice(m_handle, nAccessMode, nSwitchoverKey); if (MV_OK != nRet) { printf("error: OpenDevice fail [%x]\n", nRet); return; } //...其他處理 //開始采集圖像 nRet = MV_CC_StartGrabbing(m_handle); if (MV_OK != nRet) { printf("error: StartGrabbing fail [%x]\n", nRet); return; } //獲取一幀數據的大小 MVCC_INTVALUE stIntvalue = {0}; nRet = MV_CC_GetIntValue(m_handle, "PayloadSize", &stIntvalue); if (nRet != MV_OK) { printf("Get PayloadSize failed! nRet [%x]\n", nRet); return; } int nBufSize = stIntvalue.nCurValue; //一幀數據大小 unsigned int nTestFrameSize = 0; unsigned char* pFrameBuf = NULL; pFrameBuf = (unsigned char*)malloc(nBufSize); MV_FRAME_OUT_INFO_EX stInfo; memset(&stInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX)); //上層應用程序需要根據幀率,控制好調用該接口的頻率 //此次代碼僅供參考,實際應用建議另建線程進行圖像幀采集和處理 while(1) { if (nTestFrameSize > 99) { break; } nRet = MV_CC_GetOneFrameTimeout(m_handle, pFrameBuf, nBufSize, &stInfo, 1000); if (MV_OK != nRet) { Sleep(10); } else { //...圖像數據處理 nTestFrameSize++; } } //...其他處理 //停止采集圖像 nRet = MV_CC_StopGrabbing(m_handle); if (MV_OK != nRet) { printf("error: StopGrabbing fail [%x]\n", nRet); return; } //關閉設備,釋放資源 nRet = MV_CC_CloseDevice(m_handle); if (MV_OK != nRet) { printf("error: CloseDevice fail [%x]\n", nRet); return; } //銷毀句柄,釋放資源 nRet = MV_CC_DestroyHandle(m_handle); if (MV_OK != nRet) { printf("error: DestroyHandle fail [%x]\n", nRet); return; } }
8. 獲取相機節點值
int MV_CC_GetIntValue(void *handle, const char *strKey, MVCC_INTVALUE *pIntValue);
參數:
strKey [in] 節點名稱;
pIntValue [out] 獲取到的節點值;
可以用來獲取需要的節點值。
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
day1.20180716
問題記錄:
1. 測試相機采圖時遇到問題:
首先,推測是圖像數據格式錯誤
代碼摘要:
1 //像素格式轉換輸入輸出參數 2 MV_CC_PIXEL_CONVERT_PARAM stParam; 3 memset(&stParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM)); 4 5 //源數據 6 stParam.pSrcData = m_pFrameBuf; //原始圖像數據 7 stParam.nSrcDataLen = stInfo.nFrameLen; //原始圖像數據長度 8 stParam.enSrcPixelType = stInfo.enPixelType; //原始圖像數據的像素格式 9 stParam.nWidth = stInfo.nWidth; //圖像寬 10 stParam.nHeight = stInfo.nHeight; //圖像高 11 12 //目標數據 13 stParam.enDstPixelType = PixelType_Gvsp_Mono8; //需要保存的像素格式類型,轉換成MONO8格式 14 stParam.nDstBufferSize; //存儲節點的大小 15 unsigned char* pImage = (unsigned char*)malloc(stParam.nDstBufferSize); 16 stParam.pDstBuffer; //輸出數據緩沖區,存放轉換之后的數據 17 18 nRet = MV_CC_ConvertPixelType(m_handle, &stParam); 19 if(MV_OK != nRet) 20 { 21 m_pImgBuf = (unsigned char *)malloc (stParam.nDstBufferSize); 22 memcpy(m_pImgBuf, stParam.pDstBuffer, stParam.nDstBufferSize); 23 break; 24 } 25 26 free(pImage); 27 28 29 顯示: 30 gen_image1(&g_img, "byte", g_uiWidth, g_uiHeight, pimgPointer); 31 open_window (0, 0, (Hlong)g_uiWidth, (Hlong)g_uiHeight, (Hlong)g_uiID, "visible", "", &g_window); 32 disp_image(g_img, g_window);
檢查圖像格式,為單色8位圖像,沒有錯誤。
檢查halcon接口的創建圖像,發現錯誤定義圖像的尺寸大小。
所以,應該在打開相機后查詢相機的ROI參數。改正后,單幀圖像采集功能正常。
筆記:
1. IP設置
強制設置相機網絡參數,包括IP地址、子網掩碼、默認網關。
int MV_GIGE_ForceIpEx(void *handle, unsigned int nIP, \
unsigned int nSubNetMask, \
unsigned int nDefaultGateWay);
強制設置之后需要重新創建設備句柄,僅支持GigEVision相機。
如果設備未DHCP的狀態,調用該接口后設備將會重啟~
int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); ... nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); ... // 設置設備網絡屬性 unsigned int nIP = ... // 這里。需要知道怎么把IP地址表示為unsigned int ... nRet = MV_GIGE_ForceIpEx(m_handle, nIP, nSubNetMask, nDefaultGateWay); ... // 重新創建設備句柄 nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);
2. 設置配置IP的方式
int MV_GIGE_SetIpConfig(void *handle, unsigned int nType);
參數nType:IP配置方式,定義如下
3. 相機的log文檔
int MV_CC_SetSDKLogPath(IN const char *pSDKLogPath);
設置好路徑后,可以在指定路徑下存放sdk日志。
1 ... 2 string strPath = "D:/Hik/SDK"; 3 nRet = MV_CC_SetSDKLogPath(strPath.c_str());
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接下來,做連續采集。