• 海康SDK开发步骤


    本文出处: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]
    ", 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]
    ", nRet);
    15         return;
    16     }
    17 
    18     int i = 0;
    19     if (m_stDevList.nDeviceNum == 0)
    20     {
    21         printf("no camera found!
    ");
    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]
    ", 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]
    ", 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]
    ", nRet);
            return;
        }
    
        int i = 0;
        if (m_stDevList.nDeviceNum == 0)
        {
            printf("no camera found!
    ");
            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]
    ", nRet);
            return;
        }
    
        //连接设备
         nRet = MV_CC_OpenDevice(m_handle, nAccessMode, nSwitchoverKey);
        if (MV_OK != nRet)
        {
            printf("error: OpenDevice fail [%x]
    ", nRet);
            return;
        }
        //...其他处理 
    
        //开始采集图像
         nRet = MV_CC_StartGrabbing(m_handle);
        if (MV_OK != nRet)
        {
            printf("error: StartGrabbing fail [%x]
    ", nRet);
            return;
        }
    
        //获取一帧数据的大小
        MVCC_INTVALUE stIntvalue = {0};
        nRet = MV_CC_GetIntValue(m_handle, "PayloadSize", &stIntvalue);
        if (nRet != MV_OK)
        {
            printf("Get PayloadSize failed! nRet [%x]
    ", 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]
    ", nRet);
            return;
        }
    
        //关闭设备,释放资源
         nRet = MV_CC_CloseDevice(m_handle);
        if (MV_OK != nRet)
        {
            printf("error: CloseDevice fail [%x]
    ", nRet);
            return;
        }
    
        //销毁句柄,释放资源
         nRet = MV_CC_DestroyHandle(m_handle);
        if (MV_OK != nRet)
        {
            printf("error: DestroyHandle fail [%x]
    ", 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());

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

    接下来,做连续采集。

  • 相关阅读:
    由typedef和函数指针引起的危机
    从JVM角度看Java多态
    C语言中判断字符串str1是否以str2开始或结束
    Linux下利用json-c从一个json数组中提取每一个元素中的部分字段组成一个新json数组
    C语言中的条件编译
    学会 Python 到底能干嘛?我们整理出了 7 大工作方向……
    新手指南:我应该学哪种编程语言?
    盘点:2019年最赚钱的10种编程语言
    11个提升编程能力的小方法
    收好这份 Vue 升级图,假期偷偷上个钻
  • 原文地址:https://www.cnblogs.com/eve612/p/13841720.html
Copyright © 2020-2023  润新知