海康威视工业相机使用

需要用摄像头,而实验室只有一个海康威视的MV-CA013-20GC(另一个大恒的更难搞),拿工业相机当普通相机用是不是有点暴殄天物了。

1. 相机接线

工业相机一般都需要独立供电,12v接上相机的正负极,另外网口接上电脑或交换机Lan口,建议使用千兆网口,不然帧率跟不上(也可以使用网口转usb3.0).

2.客户端使用

官网下载下面两个软件安装,一个是客户端,另一个是开发运行环境。

打开软件如图所示

软件会自动搜索可连接的设备,查找到设备后修改相机的ip,连接上相机,然后就可以调节参数了。这里如果画面很黑,首先调小相机的光圈,增大进光量,开启自动曝光与自动增益、伽马校正。如果使用的百兆网口会出现帧率低的情况,这里要么就更换千兆网口,要么将图像类型设置为mono8.

3.sdk的二次开发

进入到安装目录下有一个Development文件夹,里面有头文件和库文件以及各种语言的开发说明和demo。

这里以C++为例(VS2019)

大致流程如下,具体实现请参考文档和demo

首先新建项目,将开发需要的头文件和库文件拷出来放到项目文件中,注意库文件有32和64之分。在属性里面配置头文件和库文件。如图所示

示例代码,先捕获摄像头图像,再用opencv显示

#include "MvCameraControl.h"
#include "opencv2/opencv.hpp"

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string>

using namespace std;

bool printDeviceInfo(MV_CC_DEVICE_INFO* hk_device);
bool hk2cv(MV_FRAME_OUT_INFO_EX* hk_imginfo, unsigned char* data, cv::Mat &src_img);


int main(int argv, char** argc) {


	int ret = MV_OK;
	void* handle = NULL;

	MV_CC_DEVICE_INFO_LIST hk_devices;
	memset(&hk_devices, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
	ret = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &hk_devices);
	if (ret != MV_OK) {
		cout << "enum devices faild!" << endl;
		return -1;
	}
	if (hk_devices.nDeviceNum > 0) {
		MV_CC_DEVICE_INFO* hk_camera = hk_devices.pDeviceInfo[0];
		if (printDeviceInfo(hk_camera) == false) {
			return -1;
		}
    }
    else {
        cout << "no device found" << endl;
        return -1;
    }

    ret = MV_CC_CreateHandle(&handle, hk_devices.pDeviceInfo[0]);
    if (ret != MV_OK) {
        return -1;
    }
    ret = MV_CC_OpenDevice(handle);
    if (ret != MV_OK) {
        return -1;
    }

    ret = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
    if (ret != MV_OK) {
        return -1;
    }

    MVCC_INTVALUE hk_param;
    memset(&hk_param, 0, sizeof(MVCC_INTVALUE));
    ret = MV_CC_GetIntValue(handle, "PayloadSize", &hk_param);
    if (ret != MV_OK) {
        return -1;
    }
    unsigned int payload_size = hk_param.nCurValue;

    // load config
    ret = MV_CC_FeatureLoad(handle, "FeatureFile.ini");
    if (ret != MV_OK){
        cout << "loading config file faild" << endl;
        return -1;
    }


    // save config
   /* ret = MV_CC_FeatureSave(handle, "FeatureFile.ini");
    if (ret != MV_OK) {
        return -1;
    }*/

    // start grabbing images
    ret = MV_CC_StartGrabbing(handle);
    if (ret != MV_OK) {
        cout << "grab image failed!" << endl;
        return -1;
    }
    MV_FRAME_OUT_INFO_EX hk_imginfo;
    memset(&hk_imginfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
    unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (payload_size));
    if (data == NULL) {
        return -1;
    }
    cv::Mat src_img;
    while (!(_kbhit() && _getch() == 0x1b)) {
        ret = MV_CC_GetOneFrameTimeout(handle, data, payload_size, &hk_imginfo, 1000);
        if (ret != MV_OK) {
            free(data);
            data = NULL;
            return -1;
        }
        if (hk2cv(&hk_imginfo, data, src_img) == false) {
            continue;
        }
        cv::imshow("test", src_img);
        cv::waitKey(30);
    }
    // stop grap image
    ret = MV_CC_StopGrabbing(handle);
    if (ret != MV_OK) {
        return -1;

    }
    // close device
    ret = MV_CC_CloseDevice(handle);
    if (ret != MV_OK) {
        return -1;

    }
    ret = MV_CC_DestroyHandle(handle);
    if (ret != MV_OK) {
        return -1;

    }
    system("pause");
    return 0;
}

bool printDeviceInfo(MV_CC_DEVICE_INFO* hk_device) {
    if (NULL == hk_device)
    {
        printf("The Pointer of hk_device is NULL!\n");
        return false;
    }
    if (hk_device->nTLayerType == MV_GIGE_DEVICE)
    {
        int nIp1 = ((hk_device->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
        int nIp2 = ((hk_device->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
        int nIp3 = ((hk_device->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
        int nIp4 = (hk_device->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);

        // print current ip and user defined name
        printf("CurrentIp: %d.%d.%d.%d\n", nIp1, nIp2, nIp3, nIp4);
        printf("UserDefinedName: %s\n\n", hk_device->SpecialInfo.stGigEInfo.chUserDefinedName);
    }
    else if (hk_device->nTLayerType == MV_USB_DEVICE)
    {
        printf("UserDefinedName: %s\n", hk_device->SpecialInfo.stUsb3VInfo.chUserDefinedName);
        printf("Serial Number: %s\n", hk_device->SpecialInfo.stUsb3VInfo.chSerialNumber);
        printf("Device Number: %d\n\n", hk_device->SpecialInfo.stUsb3VInfo.nDeviceNumber);
    }
    else
    {
        printf("Not support.\n");
    }

    return true;
}

bool hk2cv(MV_FRAME_OUT_INFO_EX* hk_imginfo, unsigned char* data, cv::Mat& src_img) {
    cv::Mat cv_img;
    if (hk_imginfo->enPixelType == PixelType_Gvsp_Mono8){
        cv_img = cv::Mat(hk_imginfo->nHeight, hk_imginfo->nWidth, CV_8UC1, data);
    }else if (hk_imginfo->enPixelType == PixelType_Gvsp_RGB8_Packed){

        
        for (unsigned int j = 0; j < hk_imginfo->nHeight; j++){
            for (unsigned int i = 0; i < hk_imginfo->nWidth; i++){
                unsigned char red = data[j * (hk_imginfo->nWidth * 3) + i * 3];
                data[j * (hk_imginfo->nWidth * 3) + i * 3] = data[j * (hk_imginfo->nWidth * 3) + i * 3 + 2];
                data[j * (hk_imginfo->nWidth * 3) + i * 3 + 2] = red;
            }
        }
        cv_img = cv::Mat(hk_imginfo->nHeight, hk_imginfo->nWidth, CV_8UC3, data);
    }else{
        printf("unsupported pixel format\n");
        return false;
    }

    if (cv_img.data == NULL){
        return false;
    }
    cv_img.copyTo(src_img);
    return true;
}

因为每次断电后都要重新设置,这里我取了一个巧,先用客户端配置好参数,然后保存参数,以后每次运行只要加载参数就行了。如果运行提示没有找到dll文件,那么就是你runtime运行环境没有安装,或者没有将安装路径添加到系统环境变量。

正如开头所说的,只是拿来当普通摄像头用,所以代码很简单,后面有机会再深入研究。

猜你喜欢

转载自blog.csdn.net/qq_34935373/article/details/111768841