本文出處: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());
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接下來,做連續采集。

