^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

day1.20180712

  使用工业相机采集图像,首先需要对相机的相关参数进行设置。现在项目需要使用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());

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

接下来,做连续采集

 

posted on 2018-07-12 10:49  xiawuhao2013  阅读(3616)  评论(0编辑  收藏  举报