Hikvision MVS client and virtual camera c++ development case

1. Basic introduction

1.1 Hikvision MVS client

Machine vision industrial camera client MVS is a software application developed to support Hikvision machine vision camera products. It is suitable for all Hikvision machine vision area scan and line scan cameras. product. MVS includes client, IP configuration tool, firmware upgrade tool, import/export attribute tool, log viewing tool, network card configuration tool, driver management tool, system information tool, diagnostic tool, bandwidth management tool, SDK and Demo.

Operating system: Windows 7/10/11 32/64bit
Features

1. Ethernet ports and USB cameras can automatically search for all devices connected to the same subnet, and CameraLink cameras can manually search for connected devices
2. Support viewing and modifying camera device parameters , Search for specified parameters
3. Support simultaneous connection, acquisition, and preview of multiple cameras
4. Support saving personal preference parameter configurations and a complete set of equipment parameter plans 6. The network port camera supports modifying the IP configuration method, IP address, subcode mask, and default gateway 8. Support GigE Vision action commands 7. Support online device upgrade
5. Supports real-time preview, picture interception, and video storage


Update instructions
[MVS V4.3.0]
1. [New] New ISP tool in the tool set
2. [New] The attribute import and export tool supports capture cards
3. [New] The event configuration tool supports file import and export
4. [Optimization 】Firmware upgrade tool: Optimize the firmware upgrade operation of the capture card device.

[Industrial Camera SDK V4.2.1]
1. [New] Support GE1104 capture card

[Industrial capture card SDK V2.3.0]
1. [New] Support GE1104 capture card
For detailed update instructions, please see the MVS installation path ReleaseNote.txt file under

1.2 Hikvision virtual camera

Hikvision virtual camera corresponds to the actual industrial camera. It is a camera simulated by software. It is essentially a program running on a PC. Development using the industrial camera SDK requires connecting to an industrial camera. Building a real camera physical environment is sometimes quite complicated. In order to solve the problem that it is sometimes inconvenient to build a real environment, virtual camera gadgets are used for simulation development. The industrial camera SDK has completely consistent access to virtual cameras and physical industrial cameras, so users can use virtual cameras to replace physical industrial cameras for development and debugging during the development phase.

2. Installation and use

2.1 Hikvision MVS client

Official website address: https://www.hikrobotics.com/cn/machinevision/service/download?module=0
Open the above website and you will see the following interface After the installation is completed, you can enter the following program interface There are no special usage requirements, just install the default configuration items of the software. Unzip the downloaded file to get the executable file, double-click to enter the installation process
Insert image description here
Click Download and enter the required information, then click OK to download
Insert image description here

Insert image description here
Insert image description here

Insert image description here

2.2 Hikvision virtual camera

Download address: https://download.csdn.net/download/m0_74259636/88597229
This software comes from the collection of Internet resources. After downloading the resources, unzip and double-click to complete. Install.
Insert image description here

Currently supported camera models are: MV-CA013-20GM/GC, MV-CA050-10GM/GC, MVCA060-11GM, MV-CA060-10GC, MV-CE200-10GM/GC, MV-CA003-< /span> connected industrial cameras. After the simulation mode is turned on, the MVS client or SDK can only enumerate virtual cameras and cannot enumerate the actual
21UM/UC, MV-CH120-10UM/UC.

After the addition is completed, you can see the added camera through the MVS terminal. You can also connect and preview images and set camera parameters just like operating an industrial camera object
As shown below.
The preview screen of MV-CA013-20GM, MV-CA050-10GM, MV-CA060-11GM model virtual camera
defaults to a cyclic display of pictures under a fixed path. ; The
preview screen of other newly added virtual cameras defaults to a simulation image, and pictures that meet the requirements can be placed in a fixed path for looping
display.
The fixed path for storing pictures is: C:\Windows\Temp\VirtualCamera\Cameras. Black
white pictures are placed in the Mono8 folder, and color pictures are placed in the under the RGB24 folder.
The replacement image must have the same resolution as the virtual camera model and be a bmp format image
.

2.3 Basic use of virtual camera and MVS client

Click the VirtualCamTool icon on the desktop to enter the virtual camera operation interface. Click the tab to select the camera model, and click "Add Virtual Camera" to complete the addition. If it prompts that the sdk is occupied, please exit the MVS program first.
Insert image description here
After re-entering the MVS client, you can find the virtual camera.
Insert image description here
The default preview screen is a cyclic display of pictures under a fixed path; the
preview screen for other newly added models of virtual cameras defaults to a simulation image, which can be placed under a fixed path Pictures that meet the requirements are displayed in a loop
.
Insert image description here

The fixed path for storing pictures is: C:\Windows\Temp\VirtualCamera\Cameras\Camera ID, black
White pictures are placed in the Mono8 folder, and color pictures are placed in RGB24 folder.
The replacement image must have the same resolution as the virtual camera model and be a bmp format image
.

3. Use cases

There is the following development demo program in the C:\Program Files (x86)\MVS\Development\Samples directory. The c++ program provided by default is the sln file of vs2015, which can be opened with vs2019. For easy development, we recommend learning to use OpenCV demo.
Insert image description here

3.1 opencv Demo configuration

Enter the following directoryInsert image description here
Double-click Samples_VS2015.sln to open the solution with vs2019. At this time, it is found that the inclde related to opencv is reporting errors, so opencv needs to be configured.
Insert image description here
The configuration of opencv can refer to opencv-basic operating environment configuration (download and installation, writing code, configuration environment) , among which It mainly configures the include directory, lib directory and additional dependencies, and adds the bin directory to the system environment variable path. You need to pay attention to the setting of release|x64.
Insert image description here
Insert image description here

3.2 Demo running effect

The running effect of the demo program is as follows. It first lists all Hikvision camera IDs (device0 in the picture below), and then enters the camera ID and format code to complete the program operation.
Insert image description here

3.3 Key code extraction

The demo program provided by MVS is relatively complicated, so we will organize it for this purpose. The compiled usage code is as follows:

    MVS_camera_client camera;
    camera.init_camera();
    cv::Mat img = camera.take_photos();
    camera.destory();

The complete code is as follows:

/***************************************************************************************************
*
* Notes about how to configure your OpenCV environment and project.
* 1. You can prepare the required installation package from the official website. https://opencv.org/releases.html
* 2. If the *.lib files doesn't exist in the package download, you need to compile by yourself with the CMake tool.
* 3. Add the 'bin' folder path to the PATH.
* 4. Configure the 'Additional Include Directories', 'Additional Library Directories' and 'Additional Dependencies' for current project property.
*
* If there is any question or request, please feel free to contact us.

***************************************************************************************************/

#include <stdio.h>
#include <string.h>
#include "opencv2/core/core_c.h"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "MvCameraControl.h"

enum CONVERT_TYPE
{
    
    
    OpenCV_Mat = 0,    // ch:Mat图像格式 | en:Mat format
    OpenCV_IplImage = 1,    // ch:IplImage图像格式 | en:IplImage format
};

// ch:显示枚举到的设备信息 | en:Print the discovered devices' information
void PrintDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo)
{
    
    
    if (NULL == pstMVDevInfo)
    {
    
    
        printf("    NULL info.\n\n");
        return;
    }

    // 获取图像数据帧仅支持GigE和U3V设备
    if (MV_GIGE_DEVICE == pstMVDevInfo->nTLayerType)
    {
    
    
        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);

        // ch:显示IP和设备名 | en:Print current ip and user defined name
        printf("    IP: %d.%d.%d.%d\n", nIp1, nIp2, nIp3, nIp4);
        printf("    UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
        printf("    Device Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName);
    }
    else if (MV_USB_DEVICE == pstMVDevInfo->nTLayerType)
    {
    
    
        printf("    UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
        printf("    Device Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chModelName);
    }
    else
    {
    
    
        printf("    Not support.\n\n");
    }
}

// ch:帧数据转换为Mat格式图片并保存 | en:Convert data stream to Mat format then save image
bool Convert2Mat(cv::Mat& srcImage, MV_FRAME_OUT_INFO_EX* pstImageInfo, unsigned char* pData)
{
    
    
    if (NULL == pstImageInfo || NULL == pData)
    {
    
    
        printf("NULL info or data.\n");
        return false;
    }

    ;

    if (PixelType_Gvsp_Mono8 == pstImageInfo->enPixelType)                // Mono8类型
    {
    
    
        srcImage = cv::Mat(pstImageInfo->nHeight, pstImageInfo->nWidth, CV_8UC1, pData);
    }
    else if (PixelType_Gvsp_RGB8_Packed == pstImageInfo->enPixelType)     // RGB8类型
    {
    
    
        // Mat像素排列格式为BGR,需要转换
        //RGB2BGR(pData, pstImageInfo->nWidth, pstImageInfo->nHeight);
        srcImage = cv::Mat(pstImageInfo->nHeight, pstImageInfo->nWidth, CV_8UC3, pData);
        cv::cvtColor(srcImage, srcImage, cv::COLOR_RGB2BGR);
    }
    else
    {
    
    
        /* Bayer 格式转换mat格式的方法:
        1. 使用相机句柄销毁前 调用 MV_CC_ConvertPixelType 将PixelType_Gvsp_BayerRG8 等Bayer格式转换成 PixelType_Gvsp_BGR8_Packed
        2. 参考上面 将BGR转换为 mat格式
        */

        printf("Unsupported pixel format\n");
        return false;
    }

    if (NULL == srcImage.data)
    {
    
    
        printf("Creat Mat failed.\n");
        return false;
    }

    try
    {
    
    
        // ch:保存Mat图片 | en:Save converted image in a local file
        cv::imwrite("Image_Mat.bmp", srcImage);
    }
    catch (cv::Exception& ex)
    {
    
    
        fprintf(stderr, "Exception in saving mat image: %s\n", ex.what());
    }
    return true;
}



class MVS_camera_client {
    
    

public:
    int nRet = MV_OK;
    void* handle = NULL;
    unsigned char* pData = NULL;
    unsigned int nPayloadSize;
    MV_FRAME_OUT_INFO_EX stImageInfo = {
    
     0 };
    //获取所有的相机
    MV_CC_DEVICE_INFO_LIST Get_MVS_camera() {
    
    
        MV_CC_DEVICE_INFO_LIST stDeviceList;
        memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
        int nRet = MV_OK;
        // ch:设备枚举 | en:Enum device
        nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
        if (MV_OK != nRet)
        {
    
    
            printf("相机列表获取失败! nRet [0x%x]\n", nRet);
            exit(0);
        }

        // ch:显示设备信息 | en:Show devices
        if (stDeviceList.nDeviceNum > 0)
        {
    
    
            for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
            {
    
    
                printf("[device %d]:\n", i);
                MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
                if (NULL == pDeviceInfo)
                {
    
    
                    break;
                }
                PrintDeviceInfo(pDeviceInfo);
            }
            return stDeviceList;
        }
        else
        {
    
    
            printf("没有找到相机!\n");
            exit(0);
        }

    }

    //初始化相机信息, 默认选用第0个相机
    void init_camera(unsigned int nIndex = 0) {
    
    
        MV_CC_DEVICE_INFO_LIST stDeviceList = Get_MVS_camera();
        // ch:创建设备句柄 | en:Create handle
        nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
        if (MV_OK != nRet)
        {
    
    
            printf("Create Handle fail! nRet [0x%x]\n", nRet);
            return;
        }

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

        // ch:探测最佳Packet大小(只支持GigE相机) | en:Detection network optimal package size(It only works for the GigE camera)
        if (MV_GIGE_DEVICE == stDeviceList.pDeviceInfo[nIndex]->nTLayerType)
        {
    
    
            int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
            if (nPacketSize > 0)
            {
    
    
                // 设置Packet大小
                nRet = MV_CC_SetIntValue(handle, "GevSCPSPacketSize", nPacketSize);
                if (MV_OK != nRet)
                {
    
    
                    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 as off
        nRet = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
        if (MV_OK != nRet)
        {
    
    
            printf("Set Trigger Mode fail! nRet [0x%x]\n", nRet);
            return;
        }

        // ch:获取图像大小 | en:Get payload size
        MVCC_INTVALUE stParam;
        memset(&stParam, 0, sizeof(MVCC_INTVALUE));
        nRet = MV_CC_GetIntValue(handle, "PayloadSize", &stParam);
        if (MV_OK != nRet)
        {
    
    
            printf("Get PayloadSize fail! nRet [0x%x]\n", nRet);
            return;
        }
        nPayloadSize = stParam.nCurValue;

        // ch:初始化图像信息 | en:Init image info

        memset(&stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
        pData = (unsigned char*)malloc(sizeof(unsigned char) * (nPayloadSize));
        if (NULL == pData)
        {
    
    
            printf("Allocate memory failed.\n");
            return;
        }
        memset(pData, 0, sizeof(pData));

    }

    //进行拍照
    cv::Mat take_photos() {
    
    
        cv::Mat res;
        nRet = MV_CC_StartGrabbing(handle);
        if (MV_OK != nRet)
        {
    
    
            printf("Start Grabbing fail! nRet [0x%x]\n", nRet);
            return res;
        }

        // ch:获取一帧图像,超时时间1000ms | en:Get one frame from camera with timeout=1000ms
        nRet = MV_CC_GetOneFrameTimeout(handle, pData, nPayloadSize, &stImageInfo, 1000);
        if (MV_OK == nRet)
        {
    
    
            printf("Get One Frame: Width[%d], Height[%d], FrameNum[%d]\n",
                stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
        }
        else
        {
    
    
            printf("Get Frame fail! nRet [0x%x]\n", nRet);
            return res;
        }

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

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

        // ch:数据转换 | en:Convert image data
        bool bConvertRet = false;
        bConvertRet = Convert2Mat(res, &stImageInfo, pData);
        return res.clone();//返回clone对象,防止句柄释放后出现bug
    }

    //销毁句柄
    void destory() {
    
    
        // ch:销毁句柄 | en:Destroy handle
        if (handle)
        {
    
    
            MV_CC_DestroyHandle(handle);
            handle = NULL;
        }

        // ch:释放内存 | en:Free memery
        if (pData)
        {
    
    
            free(pData);
            pData = NULL;
        }
    }
};

int main()
{
    
    
    MVS_camera_client camera;
    camera.init_camera();
    cv::Mat img = camera.take_photos();
    camera.destory();

    system("pause");
    return 0;
}

3.4 Configuration item extraction

include目录: $(MVCAM_COMMON_RUNENV)\Includes;inc;E:\Lib\opencv454\build\include;

lib目录:
$(MVCAM_COMMON_RUNENV)\Libraries\win64;lib;E:\Lib\opencv454\build\x64\vc15\lib;

Additional dependencies: MvCameraControl.lib;opencv_world454.lib;

4. Configure MVS for self-built projects

4.1 Environment configuration

Create a new c++ project in vs2019, set the run configuration point to Release|x64, and then right-click on the project name.
Insert image description here

Click Properties in the pop-up list to enter property configuration and perform the following configurations
Insert image description here

Insert image description here

4.2 Code writing

Click on the source file and add a new item
Insert image description here
Then add the complete code in 3.3 to "source.cpp"
and add the main function code Change to the following:

int main()
{
    
    
    MVS_camera_client camera;
    camera.init_camera();
    cv::Mat img = camera.take_photos();
    camera.destory();//相机句柄销毁后,所拍摄的图像也被销毁了

    cv::imshow("mat", img);
    cv::waitKey();


    system("pause");
    return 0;
}


4.3 Operation effect

The photos taken at this time are exactly the same as those set by the analog camera, indicating that the program was developed successfully and the analog camera was used successfully!
Insert image description here

Guess you like

Origin blog.csdn.net/m0_74259636/article/details/134792880