[海康Demo] GrabStrategies

目录

1、海康Demo代码

2、示例代码说明

1. 概述

2. 功能模块说明

2.1 设备枚举与选择

2.2 设备连接与配置

2.3 图像采集策略

2.4 图像采集与处理

2.5 资源释放

3. 代码流程分析

4. 注意事项

5. 示例代码运行环境

6. 示例代码输出示例

7. 示例代码的扩展方向

8. 结论


1、海康Demo代码

#include <stdio.h>
#include <Windows.h>
#include <process.h>
#include <conio.h>
#include "MvCameraControl.h"

// ch:等待按键输入 | en:Wait for key press
void WaitForKeyPress(void)
{
    while(!_kbhit())
    {
        Sleep(10);
    }
    _getch();
}

bool PrintDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo)
{
    if (NULL == pstMVDevInfo)
    {
        printf("The Pointer of pstMVDevInfo is NULL!
");
        return false;
    }

    if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE)
    {
        int nIp1 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
        int nIp2 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
        int nIp3 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
        int nIp4 = (pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);

        printf("CurrentIp: %d.%d.%d.%d
" , nIp1, nIp2, nIp3, nIp4);
        printf("UserDefinedName: %s

" , pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
    }
    else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE)
    {
        printf("UserDefinedName: %s
", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
        printf("Serial Number: %s
", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chSerialNumber);
        printf("Device Number: %d

", pstMVDevInfo->SpecialInfo.stUsb3VInfo.nDeviceNumber);
    }
    else if (pstMVDevInfo->nTLayerType == MV_GENTL_GIGE_DEVICE)
    {
        printf("UserDefinedName: %s
", pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
        printf("Serial Number: %s
", pstMVDevInfo->SpecialInfo.stGigEInfo.chSerialNumber);
        printf("Model Name: %s

", pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName);
    }
    else if (pstMVDevInfo->nTLayerType == MV_GENTL_CAMERALINK_DEVICE)
    {
        printf("UserDefinedName: %s
", pstMVDevInfo->SpecialInfo.stCMLInfo.chUserDefinedName);
        printf("Serial Number: %s
", pstMVDevInfo->SpecialInfo.stCMLInfo.chSerialNumber);
        printf("Model Name: %s

", pstMVDevInfo->SpecialInfo.stCMLInfo.chModelName);
    }
    else if (pstMVDevInfo->nTLayerType == MV_GENTL_CXP_DEVICE)
    {
        printf("UserDefinedName: %s
", pstMVDevInfo->SpecialInfo.stCXPInfo.chUserDefinedName);
        printf("Serial Number: %s
", pstMVDevInfo->SpecialInfo.stCXPInfo.chSerialNumber);
        printf("Model Name: %s

", pstMVDevInfo->SpecialInfo.stCXPInfo.chModelName);
    }
    else if (pstMVDevInfo->nTLayerType == MV_GENTL_XOF_DEVICE)
    {
        printf("UserDefinedName: %s
", pstMVDevInfo->SpecialInfo.stXoFInfo.chUserDefinedName);
        printf("Serial Number: %s
", pstMVDevInfo->SpecialInfo.stXoFInfo.chSerialNumber);
        printf("Model Name: %s

", pstMVDevInfo->SpecialInfo.stXoFInfo.chModelName);
    }
    else
    {
        printf("Not support.
");
    }

    return true;
}

static  unsigned int __stdcall UpcomingThread(void* pUser)
{
    Sleep(3000);//为了等MV_CC_GetImageBuffer调用后再发送软触发命令

    printf("Trigger Software Once for MV_GrabStrategy_UpcomingImage
");
    MV_CC_SetCommandValue(pUser, "TriggerSoftware");

    return 0;
}

int main()
{
    int nRet = MV_OK;
    void* handle = NULL;
    unsigned char * pData = NULL;

    do 
    {
                // ch:初始化SDK | en:Initialize SDK
                nRet = MV_CC_Initialize();
                if (MV_OK != nRet)
                {
                        printf("Initialize SDK fail! nRet [0x%x]
", nRet);
                        break;
                }

        // ch:枚举设备 | en:Enum device
        MV_CC_DEVICE_INFO_LIST stDeviceList = {0};
        nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE, &stDeviceList);
        if (MV_OK != nRet)
        {
            printf("Enum Devices fail! nRet [0x%x]
", nRet);
            break;
        }

        if (stDeviceList.nDeviceNum > 0)
        {
            for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
            {
                printf("[device %d]:
", i);
                MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
                if (NULL == pDeviceInfo)
                {
                    break;
                } 
                PrintDeviceInfo(pDeviceInfo);            
            }  
        } 
        else
        {
            printf("Find No Devices!
");
            break;
        } 

        printf("Please Input camera index(0-%d):", stDeviceList.nDeviceNum-1);
        unsigned int nIndex = 0;
        scanf_s("%d", &nIndex);

        if (nIndex >= stDeviceList.nDeviceNum)
        {
            printf("Input error!
");
            break;
        }

        // ch:选择设备并创建句柄 | en:Select device and create handle
        nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
        if (MV_OK != nRet)
        {
            printf("Create Handle fail! nRet [0x%x]
", nRet);
            break;
        }

        // ch:打开设备 | en:Open device
        nRet = MV_CC_OpenDevice(handle);
        if (MV_OK != nRet)
        {
            printf("Open Device fail! nRet [0x%x]
", nRet);
            break;
        }

        // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
        if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
        {
            int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
            if (nPacketSize > 0)
            {
                if(MV_CC_SetIntValueEx(handle,"GevSCPSPacketSize",nPacketSize) != MV_OK)
                {
                    printf("Warning: Set Packet Size fail nRet [0x%x]!", nRet);
                }
            }
            else
            {
                printf("Warning: Get Packet Size fail nRet [0x%x]!", nPacketSize);
            }
        }

        // ch:设置软触发模式 | en:Set Trigger Mode and Set Trigger Source
        nRet = MV_CC_SetEnumValueByString(handle, "TriggerMode", "On");
        if (MV_OK != nRet)
        {
            printf("Set Trigger Mode fail! nRet [0x%x]
", nRet);
            break;
        }
        nRet = MV_CC_SetEnumValueByString(handle, "TriggerSource", "Software");
        if (MV_OK != nRet)
        {
            printf("Set Trigger Source fail! nRet [0x%x]
", nRet);
            break;
        }

        unsigned int nImageNodeNum = 5;
        // ch:设置缓存节点个数 | en:Set number of image node
        nRet = MV_CC_SetImageNodeNum(handle, nImageNodeNum);
        if (MV_OK != nRet)
        {
            printf("Set number of image node fail! nRet [0x%x]
", nRet);
            break;
        }

        printf("
**************************************************************************
");
        printf("* 0.MV_GrabStrategy_OneByOne;       1.MV_GrabStrategy_LatestImagesOnly;  *
");
        printf("* 2.MV_GrabStrategy_LatestImages;   3.MV_GrabStrategy_UpcomingImage;     *
");
        printf("**************************************************************************
");

        printf("Please Input Grab Strategy:");
        unsigned int nGrabStrategy = 0;
        scanf_s("%d", &nGrabStrategy);

        // ch:U3V相机不支持MV_GrabStrategy_UpcomingImage | en:U3V device not support UpcomingImage
        if (nGrabStrategy == MV_GrabStrategy_UpcomingImage && MV_USB_DEVICE == stDeviceList.pDeviceInfo[nIndex]->nTLayerType)
        {
            printf("U3V device not support UpcomingImage
");
            break;
        }

        switch(nGrabStrategy)
        {
        case MV_GrabStrategy_OneByOne:
            {
                printf("Grab using the MV_GrabStrategy_OneByOne default strategy
");
                nRet = MV_CC_SetGrabStrategy(handle, MV_GrabStrategy_OneByOne);
                if (MV_OK != nRet)
                {
                    printf("Set Grab Strategy fail! nRet [0x%x]
", nRet);
                    break;
                }
            }
            break;
        case MV_GrabStrategy_LatestImagesOnly:
            {
                printf("Grab using strategy MV_GrabStrategy_LatestImagesOnly
");
                nRet = MV_CC_SetGrabStrategy(handle, MV_GrabStrategy_LatestImagesOnly);
                if (MV_OK != nRet)
                {
                    printf("Set Grab Strategy fail! nRet [0x%x]
", nRet);
                    break;
                }
            }
            break;
        case MV_GrabStrategy_LatestImages:
            {
                printf("Grab using strategy MV_GrabStrategy_LatestImages
");
                nRet = MV_CC_SetGrabStrategy(handle, MV_GrabStrategy_LatestImages);
                if (MV_OK != nRet)
                {
                    printf("Set Grab Strategy fail! nRet [0x%x]
", nRet);
                    break;
                }

                // ch:设置输出缓存个数 | en:Set Output Queue Size
                nRet = MV_CC_SetOutputQueueSize(handle, 2);
                if (MV_OK != nRet)
                {
                    printf("Set Output Queue Size fail! nRet [0x%x]
", nRet);
                    break;
                }
            }
            break;
        case MV_GrabStrategy_UpcomingImage:
            {
                printf("Grab using strategy MV_GrabStrategy_UpcomingImage
");
                nRet = MV_CC_SetGrabStrategy(handle, MV_GrabStrategy_UpcomingImage);
                if (MV_OK != nRet)
                {
                    printf("Set Grab Strategy fail! nRet [0x%x]
", nRet);
                    break;
                }

                unsigned int nThreadID = 0;
                void* hThreadHandle = (void*) _beginthreadex( NULL , 0 , UpcomingThread , handle, 0 , &nThreadID );
                if (NULL == hThreadHandle)
                {
                    break;
                }
            }
            break;
        default:
            printf("Input error!Use default strategy:MV_GrabStrategy_OneByOne
");
            break;
        }

        // ch:开始取流 | en:Start grab image
        nRet = MV_CC_StartGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("Start Grabbing fail! nRet [0x%x]
", nRet);
            break;
        }

        // ch:发送软触发命令 | en:Send Trigger Software command
        for (unsigned int i = 0;i < nImageNodeNum;i++)
        {
            nRet = MV_CC_SetCommandValue(handle, "TriggerSoftware");
            if (MV_OK != nRet)
            {
                printf("Send Trigger Software command fail! nRet [0x%x]
", nRet);
                break;
            }
            Sleep(500);//如果帧率过小或TriggerDelay很大,可能会出现软触发命令没有全部起效而导致取不到数据的情况
        }

        MV_FRAME_OUT stOutFrame = {0};
        if (nGrabStrategy != MV_GrabStrategy_UpcomingImage)
        {
            while(true)
            {
                nRet = MV_CC_GetImageBuffer(handle, &stOutFrame, 0);//超时时间设置成0,因为缓存列表中已经有数据存在
                if (nRet == MV_OK)
                {
                    printf("Get One Frame: Width[%d], Height[%d], FrameNum[%d]
", 
                        stOutFrame.stFrameInfo.nExtendWidth, stOutFrame.stFrameInfo.nExtendHeight, stOutFrame.stFrameInfo.nFrameNum);
                }
                else
                {
                    printf("Get Image fail! nRet [0x%x]
", nRet);
                    break;
                }

                nRet = MV_CC_FreeImageBuffer(handle, &stOutFrame);
                if(nRet != MV_OK)
                {
                    printf("Free Image Buffer fail! nRet [0x%x]
", nRet);
                }
            }
        }
        else//仅用于upcoming
        {
            nRet = MV_CC_GetImageBuffer(handle, &stOutFrame, 5000);//需要比较大的超时时间来获取即将到达的这帧数据
            if (nRet == MV_OK)
            {
                printf("Get One Frame: Width[%d], Height[%d], FrameNum[%d]
", 
                    stOutFrame.stFrameInfo.nExtendWidth, stOutFrame.stFrameInfo.nExtendHeight, stOutFrame.stFrameInfo.nFrameNum);

                nRet = MV_CC_FreeImageBuffer(handle, &stOutFrame);
                if(nRet != MV_OK)
                {
                    printf("Free Image Buffer fail! nRet [0x%x]
", nRet);
                }
            }
            else
            {
                printf("Get Image fail! nRet [0x%x]
", nRet);
            }
        }

        // ch:停止取流 | en:Stop grab image
        nRet = MV_CC_StopGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("Stop Grabbing fail! nRet [0x%x]
", nRet);
            break;
        }

        // ch:关闭设备 | en:Close device
        nRet = MV_CC_CloseDevice(handle);
        if (MV_OK != nRet)
        {
            printf("Close Device fail! nRet [0x%x]
", nRet);
            break;
        }

        // ch:销毁句柄 | en:Destroy handle
        nRet = MV_CC_DestroyHandle(handle);
        if (MV_OK != nRet)
        {
            printf("Destroy Handle fail! nRet [0x%x]
", nRet);
            break;
        }
                handle = NULL;
    } while (0);


        if (handle != NULL)
        {
                MV_CC_DestroyHandle(handle);
                handle = NULL;
        }


        // ch:反初始化SDK | en:Finalize SDK
        MV_CC_Finalize();

    printf("Press a key to exit.
");
    WaitForKeyPress();

    return 0;
}

2、示例代码说明

1. 概述

本示例代码演示了如何使用海康相机SDK(MvCameraControl.h)进行设备枚举、连接、配置、图像采集和释放资源的完整流程。代码支持多种相机类型(如GigE、USB、CameraLink等),并展示了不同的图像采集策略(如逐帧采集、获取最新图像、获取即将到达的图像等)。通过本示例,用户可以快速了解如何与海康相机进行交互,并实现基本的图像采集功能。

2. 功能模块说明

2.1 设备枚举与选择

枚举设备:通过MV_CC_EnumDevices函数枚举所有连接的海康相机设备。支持的设备类型包括GigE、USB、CameraLink、CXP和XOF等。

打印设备信息:调用PrintDeviceInfo函数,根据设备类型(如GigE、USB等)打印设备的详细信息,如IP地址、用户定义名称、序列号等。

选择设备:用户通过输入设备索引(0到设备总数减1)选择要连接的相机设备。

2.2 设备连接与配置

创建设备句柄:使用MV_CC_CreateHandle函数根据用户选择的设备信息创建设备句柄。

打开设备:通过MV_CC_OpenDevice函数打开相机设备。

设置网络参数(仅限GigE相机):调用MV_CC_GetOptimalPacketSize获取最佳网络包大小,并通过MV_CC_SetIntValueEx设置GigE相机的包大小。

配置触发模式

设置触发模式为“On”(MV_CC_SetEnumValueByString(handle, "TriggerMode", "On"))。

设置触发源为“Software”(MV_CC_SetEnumValueByString(handle, "TriggerSource", "Software"))。

设置图像缓存节点个数:通过MV_CC_SetImageNodeNum设置图像缓存节点的数量。

2.3 图像采集策略

用户可以选择以下四种图像采集策略之一:

MV_GrabStrategy_OneByOne:逐帧采集图像。

MV_GrabStrategy_LatestImagesOnly:仅获取最新图像。

MV_GrabStrategy_LatestImages:获取最新多帧图像。

MV_GrabStrategy_UpcomingImage:获取即将到达的图像(仅支持GigE相机)。

2.4 图像采集与处理

开始采集:调用MV_CC_StartGrabbing函数开始图像采集。

发送软触发命令:通过MV_CC_SetCommandValue(handle, "TriggerSoftware")发送软触发命令,触发相机采集图像。

获取图像数据

对于非“即将到达的图像”策略,调用MV_CC_GetImageBuffer函数从缓存中获取图像数据。

对于“即将到达的图像”策略,设置较大的超时时间(如5000毫秒),等待即将到达的图像数据。

释放图像缓存:通过MV_CC_FreeImageBuffer函数释放获取的图像缓存。

2.5 资源释放

停止采集:调用MV_CC_StopGrabbing函数停止图像采集。

关闭设备:通过MV_CC_CloseDevice函数关闭相机设备。

销毁句柄:调用MV_CC_DestroyHandle函数销毁设备句柄。

反初始化SDK:调用MV_CC_Finalize函数完成SDK的反初始化操作。

3. 代码流程分析

初始化SDK:调用MV_CC_Initialize函数初始化SDK。

枚举设备:调用MV_CC_EnumDevices函数枚举所有连接的相机设备,并打印设备信息。

选择设备:用户输入设备索引,选择要连接的相机设备。

设备连接与配置:创建设备句柄、打开设备、设置网络参数(仅限GigE相机)、配置触发模式和图像缓存节点个数。

设置图像采集策略:用户选择图像采集策略。

图像采集:开始采集图像、发送软触发命令、获取图像数据、释放图像缓存。

资源释放:停止采集、关闭设备、销毁句柄、反初始化SDK。

等待按键退出:调用WaitForKeyPress函数等待用户按键后退出程序。

4. 注意事项

设备支持性

U3V(USB3 Vision)设备不支持“即将到达的图像”策略(MV_GrabStrategy_UpcomingImage)。

不同类型的相机(如GigE、USB等)可能需要不同的配置参数。

图像采集超时时间

对于“即将到达的图像”策略,需要设置较大的超时时间(如5000毫秒),以确保能够成功获取即将到达的图像。

对于其他策略,超时时间可以设置为0,因为缓存中已经有图像数据。

软触发命令间隔

如果相机帧率较低或TriggerDelay较大,软触发命令之间需要有足够的间隔时间(如500毫秒),以确保触发命令能够正确生效。

资源释放顺序

在程序结束前,必须按照正确的顺序释放资源(如停止采集、关闭设备、销毁句柄、反初始化SDK),以避免资源泄漏或程序崩溃。

5. 示例代码运行环境

硬件环境

海康相机(支持GigE、USB、CameraLink、CXP或XOF接口)。

与相机匹配的计算机硬件(如网卡、USB接口等)。

软件环境

操作系统:Windows(支持Windows XP及以上版本)。

编译工具:Visual Studio(支持2010及以上版本)。

海康相机SDK:确保已正确安装并配置海康相机SDK,包括头文件(MvCameraControl.h)和动态链接库(DLL)。

6. 示例代码输出示例

假设连接了一台GigE相机,运行程序后可能的输出如下:

[device 0]:
CurrentIp: 192.168.1.100
UserDefinedName: Camera1

Please Input camera index(0-0):0
Please Input Grab Strategy:
0.MV_GrabStrategy_OneByOne;       1.MV_GrabStrategy_LatestImagesOnly;
2.MV_GrabStrategy_LatestImages;   3.MV_GrabStrategy_UpcomingImage;
**************************************************************************
Please Input Grab Strategy:0
Grab using the MV_GrabStrategy_OneByOne default strategy
Get One Frame: Width[1920], Height[1080], FrameNum[1]
Get One Frame: Width[1920], Height[1080], FrameNum[2]
...
Press a key to exit.

7. 示例代码的扩展方向

图像处理功能:在获取图像数据后,可以添加图像处理算法(如边缘检测、特征提取等)。

多线程采集:实现多线程图像采集,提高采集效率。

网络传输:将采集的图像通过网络传输到其他设备进行处理或存储。

用户界面:开发图形用户界面(GUI),方便用户操作和配置相机参数。

8. 结论

本示例代码展示了如何使用海康相机SDK进行设备枚举、连接、配置、图像采集和资源释放的完整流程。通过学习本示例代码,用户可以快速掌握海康相机SDK的基本使用方法,并根据实际需求进行扩展和应用。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容