海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)

2023-05-16

本文接上次的博客海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一),上个博客中并未用到QT,本文介绍项目内容及源码,供大家参考。

由于我的项目中是用海康相机作为拍照的一个中介,重点是在目标识别方向,请阅读源码时自动忽略。
如果对目标识别感兴趣,可以参考我的YOLO系列
https://blog.csdn.net/qq_45445740/category_9794819.html

目录

  • 1.说明
    • 1.1 环境配置
    • 1.2 背景说明
  • 2.源码
    • MvCamera.h
    • mythread.h
    • PcbDetectv3.h
    • main.cpp
    • PcbDetectv3.cpp
    • MvCamera.cpp
    • mythread.cpp
    • 效果

1.说明

1.1 环境配置

关于我在VS中的软件版本及相关的环境配置,请移步
海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一)(里面有详细的软硬件介绍)

1.2 背景说明

简单介绍下我的项目需求
通过相机对物体拍照,后进行目标识别,并返回识别目标的准确位置。这里相机采用海康威视工业相机,人机交互界面选择QT。
界面功能介绍:搜索当前相机的信号,相机可进行图像的连续采集或触发式采集。

2.源码

MvCamera.h

/************************************************************************/
/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用                */
/************************************************************************/

#ifndef _MV_CAMERA_H_
#define _MV_CAMERA_H_

#include "MvCameraControl.h"
#include <string.h>

#ifndef MV_NULL
#define MV_NULL    0
#endif

#include"opencv2/opencv.hpp"
#include"opencv2/imgproc/types_c.h"
using namespace cv;

class CMvCamera
{
public:
    CMvCamera();
    ~CMvCamera();

    // ch:获取SDK版本号 | en:Get SDK Version
    static int GetSDKVersion();

    // ch:枚举设备 | en:Enumerate Device
    static int EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList);

    // ch:判断设备是否可达 | en:Is the device accessible
    static bool IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode);

    // ch:打开设备 | en:Open Device
    int Open(MV_CC_DEVICE_INFO* pstDeviceInfo);

    // ch:关闭设备 | en:Close Device
    int Close();

    // ch:判断相机是否处于连接状态 | en:Is The Device Connected
    bool IsDeviceConnected();

    // ch:注册图像数据回调 | en:Register Image Data CallBack
    int RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser), void* pUser);

    // ch:开启抓图 | en:Start Grabbing
    int StartGrabbing();

    // ch:停止抓图 | en:Stop Grabbing
    int StopGrabbing();

    // ch:主动获取一帧图像数据 | en:Get one frame initiatively
    int GetImageBuffer(MV_FRAME_OUT* pFrame, int nMsec);

    // ch:释放图像缓存 | en:Free image buffer
    int FreeImageBuffer(MV_FRAME_OUT* pFrame);

    // ch:主动获取一帧图像数据 | en:Get one frame initiatively
    int GetOneFrameTimeout(unsigned char* pData, unsigned int* pnDataLen, unsigned int nDataSize, MV_FRAME_OUT_INFO_EX* pFrameInfo, int nMsec);

    // ch:显示一帧图像 | en:Display one frame image
    int DisplayOneFrame(MV_DISPLAY_FRAME_INFO* pDisplayInfo);

    // ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image cache nodes in SDK
    int SetImageNodeNum(unsigned int nNum);

    // ch:获取设备信息 | en:Get device information
    int GetDeviceInfo(MV_CC_DEVICE_INFO* pstDevInfo);

    // ch:获取GEV相机的统计信息 | en:Get detect info of GEV camera
    int GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT* pMatchInfoNetDetect);

    // ch:获取U3V相机的统计信息 | en:Get detect info of U3V camera
    int GetU3VAllMatchInfo(MV_MATCH_INFO_USB_DETECT* pMatchInfoUSBDetect);

    // ch:获取和设置Int型参数,如 Width和Height,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    // en:Get Int type parameters, such as Width and Height, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    //int GetIntValue(IN const char* strKey, OUT MVCC_INTVALUE_EX* pIntValue);
    int GetIntValue(IN const char* strKey, OUT unsigned int* pnValue);
    int SetIntValue(IN const char* strKey, IN int64_t nValue);

    // ch:获取和设置Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    // en:Get Enum type parameters, such as PixelFormat, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    int GetEnumValue(IN const char* strKey, OUT MVCC_ENUMVALUE* pEnumValue);
    int SetEnumValue(IN const char* strKey, IN unsigned int nValue);
    int SetEnumValueByString(IN const char* strKey, IN const char* sValue);

    // ch:获取和设置Float型参数,如 ExposureTime和Gain,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    // en:Get Float type parameters, such as ExposureTime and Gain, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    int GetFloatValue(IN const char* strKey, OUT MVCC_FLOATVALUE* pFloatValue);
    int SetFloatValue(IN const char* strKey, IN float fValue);

    // ch:获取和设置Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    // en:Get Bool type parameters, such as ReverseX, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    int GetBoolValue(IN const char* strKey, OUT bool* pbValue);
    int SetBoolValue(IN const char* strKey, IN bool bValue);

    // ch:获取和设置String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件UserSetSave
    // en:Get String type parameters, such as DeviceUserID, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    int GetStringValue(IN const char* strKey, MVCC_STRINGVALUE* pStringValue);
    int SetStringValue(IN const char* strKey, IN const char* strValue);

    // ch:执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
    // en:Execute Command once, such as UserSetSave, for details please refer to MvCameraNode.xlsx file under SDK installation directory
    int CommandExecute(IN const char* strKey);

    // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
    int GetOptimalPacketSize(unsigned int* pOptimalPacketSize);

    // ch:注册消息异常回调 | en:Register Message Exception CallBack
    int RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType, void* pUser), void* pUser);

    // ch:注册单个事件回调 | en:Register Event CallBack
    int RegisterEventCallBack(const char* pEventName, void(__stdcall* cbEvent)(MV_EVENT_OUT_INFO* pEventInfo, void* pUser), void* pUser);

    // ch:强制IP | en:Force IP
    int ForceIp(unsigned int nIP, unsigned int nSubNetMask, unsigned int nDefaultGateWay);

    // ch:配置IP方式 | en:IP configuration method
    int SetIpConfig(unsigned int nType);

    // ch:设置网络传输模式 | en:Set Net Transfer Mode
    int SetNetTransMode(unsigned int nType);

    // ch:像素格式转换 | en:Pixel format conversion
    int ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM* pstCvtParam);

    // ch:保存图片 | en:save image
    int SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam);

    // ch:保存图片为文件 | en:Save the image as a file
    int SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM* pstParam);

    //设置是否为触发模式
    int setTriggerMode(unsigned int TriggerModeNum);

    //设置触发源
    int setTriggerSource(unsigned int TriggerSourceNum);

    //软触发
    int softTrigger();

    //读取buffer
    int ReadBuffer(cv::Mat& image);

public:
    void* m_hDevHandle;
    unsigned int     m_nTLayerType;

public:
    unsigned char* m_pBufForSaveImage;         // 用于保存图像的缓存
    unsigned int    m_nBufSizeForSaveImage;

    unsigned char* m_pBufForDriver;            // 用于从驱动获取图像的缓存
    unsigned int    m_nBufSizeForDriver;

};

#endif//_MV_CAMERA_H_
#pragma once

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include "QThread"
#include "MvCamera.h"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <vector>  
#include <string>  
#include <algorithm>  
#include <iostream>  
#include <iterator>  
#include <stdio.h>  
#include <stdlib.h>  
#include <ctype.h>  

using namespace std;
using namespace cv;

class MyThread :public QThread
{
	Q_OBJECT

public:
	MyThread();
	~MyThread();

	void run();
	void getCameraPtr(CMvCamera* camera);
	void getImagePtr(Mat* image);
	void getCameraIndex(int index);

signals:
	void mess();
	void Display(const Mat* image, int index);

private:
	CMvCamera* cameraPtr = NULL;
	cv::Mat* imagePtr = NULL;
	int cameraIndex = NULL;
	int TriggerMode;
};

#endif // MYTHREAD_H
#pragma once

PcbDetectv3.h

#pragma once
#include <QtWidgets/QWidget>
#include <QMessageBox>
#include <QCloseEvent>
#include <QSettings>
#include <QDebug>

#include<opencv2\opencv.hpp>
#include<opencv2\dnn.hpp>
#include<fstream>
#include<iostream>

#include "MvCamera.h"
#include "mythread.h"
#include "ui_PcbDetectv3.h"

using namespace std;
using namespace cv;
using namespace cv::dnn;

#define MAX_DEVICE_NUM   2

class PcbDetectv3 : public QWidget
{
    Q_OBJECT

public:
    PcbDetectv3(QWidget *parent = Q_NULLPTR);
      //~PcbDetectv3();

private:
    Ui::PcbDetectv3Class ui;

public:
	CMvCamera* m_pcMyCamera[MAX_DEVICE_NUM];         // 相机指针对象
	MV_CC_DEVICE_INFO_LIST m_stDevList;              // 设备信息列表结构体变量,用来存储设备列表
	cv::Mat* myImage_L = new cv::Mat();              //用于保存左相机图像的图像指针对象
	cv::Mat* myImage_R = new cv::Mat();              //用于保存右相机有图像的图像指针对象

	int devices_num;//设备数量

/*ch:按下控件操作 | en:Control operation*/
/* 槽函数声明*/
private slots:

	void OnBnClickedEnumButton();              // ch:按下查找设备按钮:枚举  
	void OnBnClickedOpenButton();               // ch:打开设备 | en:Open device
	void OnBnClickedCloseButton();              // ch:关闭设备 | en:Close Devices

	void Img_display();                        // ch:Qlable 显示图像
	void display_myImage_L(const Mat* imagePrt, int cameraIndex);
	void display_myImage_R(const Mat* imagePrt, int cameraIndex);

	/*ch:图像采集 | en:Image Acquisition*/
	void OnBnClickedContinusModeRadio();        // ch:连续模式 | en:Continus Mode
	void OnBnClickedTriggerModeRadio();         // ch:触发模式 | en:Trigger Mode
	void OnBnClickedStartGrabbingButton();      // ch:开始采集 | en:Start Grabbing
	void OnBnClickedStopGrabbingButton();       // ch:结束采集 | en:Stop Grabbing
	void OnBnClickedSoftwareOnceButton();       // ch:软触发一次 | en:Software Trigger Execute Once

	/*ch:图像保存 | en:Image Save*/
	void OnBnClickedSaveBmpButton();            // ch:保存bmp | en:Save bmp
	void OnBnClickedSaveJpgButton();            // ch:保存jpg | en:Save jpg

	/*使用权重进行读取识别*/
	void StartRecognize();
private:
	void OpenDevices();                    // ch:打开设备 | en:Open device
	void CloseDevices();                   // ch:关闭设备 | en:Close Device

public:
	//MyThread* myThread; //线程对象
	MyThread* myThread_LeftCamera = NULL;  //左相机线程对象
	MyThread* myThread_RightCamera = NULL; //右相机线程对象

//槽函数
private slots:
	/*ch:设置、获取参数操作 | en:Set and get parameters operation*/
	void SetTriggerMode(int m_nTriggerMode);                // ch:设置触发模式 | en:Set Trigger Mode
	int GetTriggerMode();

	//void SetExposureTime();              // ch:设置曝光时间 | en:Set Exposure Time
	int GetExposureTime();

	//void SetGain();                       // ch:设置增益 | en:Set Gain
	int GetGain();

	//void SetFrameRate();                  // ch:设置帧率 | en:Set Frame Rate
	int GetFrameRate();

	/*ch:图片保存 | en:Save Image*/
	void SaveImage();                     // ch:保存图片 | en:Save Image

	/*ch:自定义变量 | en:User Defined Variable*/

public:
	/*ch:状态 | en:Status*/
	bool  m_bOpenDevice;                        // ch:是否打开设备 | en:Whether to open device
	bool  m_bStartGrabbing;                     // ch:是否开始抓图 | en:Whether to start grabbing
	int   m_nTriggerMode;                       // ch:触发模式 | en:Trigger Mode
	int   m_bContinueStarted;                      // 开启过连续采集图像
	MV_SAVE_IAMGE_TYPE   m_nSaveImageType;      // ch:保存图像格式 | en:Save Image Type
};

main.cpp

#include "PcbDetectv3.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    PcbDetectv3 w;
    w.show();
    return a.exec();
}

PcbDetectv3.cpp

#include "PcbDetectv3.h"
#include <QWidget>
#include <QValidator>

#define TRIGGER_SOURCE  7
#define EXPOSURE_TIME   40000
#define FRAME           30
#define TRIGGER_ON      1
#define TRIGGER_OFF     0
#define START_GRABBING_ON   1
#define START_GRABBING_OFF  0
#define IMAGE_NAME_LEN          64

PcbDetectv3::PcbDetectv3(QWidget *parent): QWidget(parent)
{
    ui.setupUi(this);	

	/*按键使能初始化*/
	// 相机初始化控件
	ui.bntEnumDevices->setEnabled(true);
	ui.bntCloseDevices->setEnabled(false);
	ui.bntOpenDevices->setEnabled(false);
	// 图像采集控件
	ui.rbnt_Continue_Mode->setEnabled(false);
	ui.rbnt_SoftTigger_Mode->setEnabled(false);
	ui.bntStartGrabbing->setEnabled(false);
	ui.bntStopGrabbing->setEnabled(false);
	ui.bntSoftwareOnce->setEnabled(false);
	// 保存图像控件
	ui.bntSave_BMP->setEnabled(false);
	ui.bntSave_JPG->setEnabled(false);

	// 线程对象实例化
	myThread_LeftCamera = new MyThread;  //左相机线程对象
	myThread_RightCamera = new MyThread; //右相机线程对象
	// 图像指针实例化
	myImage_L = new cv::Mat();    // 图像指针实例化
	myImage_R = new cv::Mat();    // 图像指针实例化 

	// 初始化变量
	int devices_num = 0;
	int m_nTriggerMode = TRIGGER_ON;
	int m_bStartGrabbing = START_GRABBING_ON;
	int m_bContinueStarted = 0;
	MV_SAVE_IAMGE_TYPE m_nSaveImageType = MV_Image_Bmp;

	// 将线程的信号与槽进行绑定
	connect(myThread_LeftCamera, SIGNAL(Display(const Mat*, int)), this, SLOT(display_myImage_L(const Mat*, int)));
	connect(myThread_RightCamera, SIGNAL(Display(const Mat*, int)), this, SLOT(display_myImage_R(const Mat*, int)));
	// 相机初始化
	connect(ui.bntEnumDevices, SIGNAL(clicked()), this, SLOT(OnBnClickedEnumButton()));
	connect(ui.bntOpenDevices, SIGNAL(clicked()), this, SLOT(OnBnClickedOpenButton()));
	connect(ui.bntCloseDevices, SIGNAL(clicked()), this, SLOT(OnBnClickedCloseButton()));
	// 图像采集
	connect(ui.rbnt_Continue_Mode, SIGNAL(clicked()), this, SLOT(OnBnClickedContinusModeRadio()));
	connect(ui.rbnt_SoftTigger_Mode, SIGNAL(clicked()), this, SLOT(OnBnClickedTriggerModeRadio())); 
	connect(ui.bntStartGrabbing, SIGNAL(clicked()), this, SLOT(OnBnClickedStartGrabbingButton()));
	connect(ui.bntStopGrabbing, SIGNAL(clicked()), this, SLOT(OnBnClickedStopGrabbingButton()));
	connect(ui.bntSoftwareOnce, SIGNAL(clicked()), this, SLOT(OnBnClickedSoftwareOnceButton()));
	
	connect(ui.bntSave_BMP, SIGNAL(clicked()), this, SLOT(OnBnClickedSaveBmpButton()));	
	connect(ui.bntSave_JPG, SIGNAL(clicked()), this, SLOT(OnBnClickedSaveJpgButton()));     
}


/*************************************************** 定义槽函数 *************************************************** */
// ch:按下查找设备按钮:枚举 | en:Click Find Device button:Enumeration 
void PcbDetectv3::OnBnClickedEnumButton()
{
	memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));    // ch:初始化设备信息列表  
	int nRet = MV_OK;
	nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList);             // ch:枚举子网内所有设备,相机设备数量

	devices_num = m_stDevList.nDeviceNum;
	if (devices_num > 0)
	{
		ui.bntOpenDevices->setEnabled(true);// 设备数大于0,使能打开设备按键
	}
}

// 打开相机,开启相机
void PcbDetectv3::OpenDevices()
{
	int nRet = MV_OK;
	// 创建相机指针对象
	for (unsigned int i = 0, j = 0; j < m_stDevList.nDeviceNum; j++, i++)
	{
		m_pcMyCamera[i] = new CMvCamera;
		// 相机对象初始化
		m_pcMyCamera[i]->m_pBufForDriver = NULL;
		m_pcMyCamera[i]->m_pBufForSaveImage = NULL;
		m_pcMyCamera[i]->m_nBufSizeForDriver = 0;
		m_pcMyCamera[i]->m_nBufSizeForSaveImage = 0;
		m_pcMyCamera[i]->m_nTLayerType = m_stDevList.pDeviceInfo[j]->nTLayerType;

		nRet = m_pcMyCamera[i]->Open(m_stDevList.pDeviceInfo[j]); //打开相机
		//设置触发模式
		m_pcMyCamera[i]->setTriggerMode(TRIGGER_ON);
		//设置触发源为软触发
		m_pcMyCamera[i]->setTriggerSource(TRIGGER_SOURCE);
}

void PcbDetectv3::OnBnClickedOpenButton()
{
	// 使能 "开始采集" 按键
	//ui->bntStartGrabbing->setEnabled(true);
	ui.bntOpenDevices->setEnabled(false);
	ui.bntCloseDevices->setEnabled(true);
	ui.rbnt_Continue_Mode->setEnabled(true);
	ui.rbnt_SoftTigger_Mode->setEnabled(true);

	ui.rbnt_Continue_Mode->setCheckable(true);
	OpenDevices();
}

// ch:关闭设备 | en:Close Device
void PcbDetectv3::CloseDevices()
{
	for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
	{

		// 关闭线程、相机
		if (myThread_LeftCamera->isRunning())
		{
			myThread_LeftCamera->requestInterruption();
			myThread_LeftCamera->wait();
			m_pcMyCamera[0]->StopGrabbing();
			//myThread_LeftCamera->~MyThread();// 销毁线程

		}

		if (myThread_RightCamera->isRunning())
		{
			myThread_RightCamera->requestInterruption();
			myThread_RightCamera->wait();
			m_pcMyCamera[1]->StopGrabbing();
		}
		m_pcMyCamera[i]->Close();
	}

	// ch:关闭之后再枚举一遍 | en:Enumerate after close
	memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));    // ch:初始化设备信息列表  
	int devices_num = MV_OK;
	devices_num = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList);           // ch:枚举子网内所有设备,相机设备数量
}

// ch:按下关闭设备按钮:关闭设备 ,包含销毁句柄| en:Click Close button: Close Device
void PcbDetectv3::OnBnClickedCloseButton()
{
	ui.bntOpenDevices->setEnabled(true);
	ui.bntCloseDevices->setEnabled(false);
	// 图像采集控件
	ui.rbnt_Continue_Mode->setEnabled(false);
	ui.rbnt_SoftTigger_Mode->setEnabled(false);
	ui.bntStartGrabbing->setEnabled(false);
	ui.bntStopGrabbing->setEnabled(false);
	// 保存图像控件
	ui.bntSave_BMP->setEnabled(false);
	ui.bntSave_JPG->setEnabled(false);
	// 关闭设备,销毁线程
	CloseDevices();
}

// 开始连续采集图像
void PcbDetectv3::OnBnClickedStartGrabbingButton()
{
	m_bContinueStarted = 1; // 为触发模式标记一下,切换触发模式时先执行停止采集图像函数

	// 图像采集控件
	ui.bntStartGrabbing->setEnabled(false);
	ui.bntStopGrabbing->setEnabled(true);
	// 保存图像控件
	ui.bntSave_BMP->setEnabled(true);
	ui.bntSave_JPG->setEnabled(true);

	int camera_Index = 0;

	// 先判断什么模式,再判断是否正在采集
	if (m_nTriggerMode == TRIGGER_ON)
	{
		// ch:开始采集之后才创建workthread线程 | en:Create workthread after start grabbing
		for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
		{
			//开启相机采集
			m_pcMyCamera[i]->StartGrabbing();

			camera_Index = i;
			if (camera_Index == 0)
			{
				myThread_LeftCamera->getCameraPtr(m_pcMyCamera[0]); //线程获取左相机指针
				myThread_LeftCamera->getImagePtr(myImage_L);  //线程获取左图像指针
				myThread_LeftCamera->getCameraIndex(0); //左相机 Index==0

				if (!myThread_LeftCamera->isRunning())
				{
					myThread_LeftCamera->start();
					m_pcMyCamera[0]->softTrigger();
					m_pcMyCamera[0]->ReadBuffer(*myImage_L);//读取Mat格式的图像
				}

			}

			if (camera_Index == 1)
			{
				myThread_RightCamera->getCameraPtr(m_pcMyCamera[1]); //线程获取右相机指针
				myThread_RightCamera->getImagePtr(myImage_R);   //线程获取右图像指针
				myThread_RightCamera->getCameraIndex(1); //右相机 Index==1

				if (!myThread_RightCamera->isRunning())
				{
					myThread_RightCamera->start();
					m_pcMyCamera[1]->softTrigger();
					m_pcMyCamera[1]->ReadBuffer(*myImage_R);//读取Mat格式的图像
				}
			}
		}
	}
}

// ch:按下结束采集按钮 | en:Click Stop button
void PcbDetectv3::OnBnClickedStopGrabbingButton()
{
	ui.bntStartGrabbing->setEnabled(true);
	ui.bntStopGrabbing->setEnabled(false);
	for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
	{
		//关闭相机
		if (myThread_LeftCamera->isRunning())
		{
			m_pcMyCamera[0]->StopGrabbing();
			myThread_LeftCamera->requestInterruption();
			myThread_LeftCamera->wait();
		}
		if (myThread_RightCamera->isRunning())
		{
			m_pcMyCamera[1]->StopGrabbing();
			myThread_RightCamera->requestInterruption();
			myThread_RightCamera->wait();
		}
	}
}

void PcbDetectv3::Img_display()
{
}

void PcbDetectv3::display_myImage_L(const Mat* imagePrt, int cameraIndex)
{
	cv::Mat rgb;
	cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);

	判断是黑白、彩色图像
	QImage QmyImage_L;
	if (myImage_L->channels() > 1)
	{
		QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_RGB888);
	}
	else
	{
		QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_Indexed8);
	}

	QmyImage_L = (QmyImage_L).scaled(ui.label_camera_display->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
	//显示图像
	ui.label_camera_display->setPixmap(QPixmap::fromImage(QmyImage_L));
}


void PcbDetectv3::display_myImage_R(const Mat* imagePrt, int cameraIndex)
{
	cv::Mat rgb;
	cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);

	判断是黑白、彩色图像
	QImage QmyImage_R;
	if (myImage_R->channels() > 1)
	{
		QmyImage_R = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_RGB888);
	}
	else
	{
		QmyImage_R = QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_Indexed8);
	}

	QmyImage_R = (QmyImage_R).scaled(ui.label_detect_display->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
	//显示图像
	ui.label_detect_display->setPixmap(QPixmap::fromImage(QmyImage_R));
}


// ch:获取曝光时间 | en:Get Exposure Time
int PcbDetectv3::GetExposureTime(void)
{
	int i = 0;
	return i;
}

// ch:获取增益 | en:Get Gain
int PcbDetectv3::GetGain(void)
{
	int i = 0;
	return i;
}

// ch:获取帧率 | en:Get Frame Rate
int PcbDetectv3::GetFrameRate(void)
{
	int i = 0;
	return i;
}

// ch:获取触发模式 | en:Get Trigger Mode
int PcbDetectv3::GetTriggerMode(void)
{
	int i = 0;
	return 0;
}

// ch:设置触发模式 | en:Set Trigger Mode
void PcbDetectv3::SetTriggerMode(int m_nTriggerMode)
{
}

// ch:按下连续模式按钮 | en:Click Continues button
void PcbDetectv3::OnBnClickedContinusModeRadio()
{
	ui.bntStartGrabbing->setEnabled(true);

	m_nTriggerMode = TRIGGER_ON;
}

// ch:按下触发模式按钮 | en:Click Trigger Mode button
void PcbDetectv3::OnBnClickedTriggerModeRadio()
{
	if (m_bContinueStarted == 1) // 从连续采集模式已经正在采集的状态切换过来
	{
		OnBnClickedStopGrabbingButton();//先执行停止采集
	}

	ui.bntStartGrabbing->setEnabled(false);
	ui.bntSoftwareOnce->setEnabled(true);

	m_nTriggerMode = TRIGGER_OFF;
	for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
	{
		m_pcMyCamera[i]->setTriggerMode(m_nTriggerMode);
		//ui.label_Real_fps->setText("000");
	}
}

// ch:按下软触发一次按钮 | en:Click Execute button
void PcbDetectv3::OnBnClickedSoftwareOnceButton()
{
	// 保存图像控件
	ui.bntSave_BMP->setEnabled(true);
	ui.bntSave_JPG->setEnabled(true);

	if (m_nTriggerMode == TRIGGER_OFF)
	{
		int nRet = MV_OK;
		for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++)
		{
			//开启相机采集
			m_pcMyCamera[i]->StartGrabbing();

			if (i == 0)
			{
				nRet = m_pcMyCamera[i]->CommandExecute("TriggerSoftware");
				m_pcMyCamera[i]->ReadBuffer(*myImage_L);
				display_myImage_L(myImage_L, i);//左相机图像
				//m_pcMyCamera[i]->StopGrabbing();
			}
			if (i == 1)
			{			//开启相机采集
				nRet = m_pcMyCamera[i]->CommandExecute("TriggerSoftware");
				m_pcMyCamera[i]->ReadBuffer(*myImage_R);
				display_myImage_R(myImage_R, i);
				//m_pcMyCamera[i]->StopGrabbing();
			}
		}
	}
}

// ch:按下保存bmp图片按钮 | en:Click Save BMP button
void PcbDetectv3::OnBnClickedSaveBmpButton()
{
	m_nSaveImageType = MV_Image_Bmp;
	SaveImage();

}

// ch:按下保存jpg图片按钮 | en:Click Save JPG button
void PcbDetectv3::OnBnClickedSaveJpgButton()
{
	m_nSaveImageType = MV_Image_Jpeg;
	SaveImage();
}

// ch:保存图片 | en:Save Image
void PcbDetectv3::SaveImage()
{
	// ch:获取1张图 | en:Get one frame
	MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };
	memset(&stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
	unsigned int nDataLen = 0;
	int nRet = MV_OK;
	for (int i = 0; i < devices_num; i++)
	{
		// ch:仅在第一次保存图像时申请缓存,在 CloseDevice 时释放
		// en:Request buffer first time save image, release after CloseDevice
		if (NULL == m_pcMyCamera[i]->m_pBufForDriver)
		{
			unsigned int nRecvBufSize = 0;
			unsigned int nRet = m_pcMyCamera[i]->GetIntValue("PayloadSize", &nRecvBufSize);

			m_pcMyCamera[i]->m_nBufSizeForDriver = nRecvBufSize;  // 一帧数据大小
			m_pcMyCamera[i]->m_pBufForDriver = (unsigned char*)malloc(m_pcMyCamera[i]->m_nBufSizeForDriver);
		}

		nRet = m_pcMyCamera[i]->GetOneFrameTimeout(m_pcMyCamera[i]->m_pBufForDriver, &nDataLen, m_pcMyCamera[i]->m_nBufSizeForDriver, &stImageInfo, 1000);
		if (MV_OK == nRet)
		{
			// ch:仅在第一次保存图像时申请缓存,在 CloseDevice 时释放
			// en:Request buffer first time save image, release after CloseDevice
			if (NULL == m_pcMyCamera[i]->m_pBufForSaveImage)
			{
				// ch:BMP图片大小:width * height * 3 + 2048(预留BMP头大小)
				// en:BMP image size: width * height * 3 + 2048 (Reserved BMP header size)
				m_pcMyCamera[i]->m_nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;

				m_pcMyCamera[i]->m_pBufForSaveImage = (unsigned char*)malloc(m_pcMyCamera[i]->m_nBufSizeForSaveImage);

			}
			// ch:设置对应的相机参数 | en:Set camera parameter
			MV_SAVE_IMAGE_PARAM_EX stParam = { 0 };
			stParam.enImageType = m_nSaveImageType; // ch:需要保存的图像类型 | en:Image format to save;
			stParam.enPixelType = stImageInfo.enPixelType;  // 相机对应的像素格式 | en:Pixel format
			stParam.nBufferSize = m_pcMyCamera[i]->m_nBufSizeForSaveImage;  // 存储节点的大小 | en:Buffer node size
			stParam.nWidth = stImageInfo.nWidth;         // 相机对应的宽 | en:Width
			stParam.nHeight = stImageInfo.nHeight;          // 相机对应的高 | en:Height
			stParam.nDataLen = stImageInfo.nFrameLen;
			stParam.pData = m_pcMyCamera[i]->m_pBufForDriver;
			stParam.pImageBuffer = m_pcMyCamera[i]->m_pBufForSaveImage;
			stParam.nJpgQuality = 90;       // ch:jpg编码,仅在保存Jpg图像时有效。保存BMP时SDK内忽略该参数

			nRet = m_pcMyCamera[i]->SaveImage(&stParam);

			char chImageName[IMAGE_NAME_LEN] = { 0 };
			if (MV_Image_Bmp == stParam.enImageType)
			{
				if (i == 0)
				{
					/*sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_L.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);*/
					//sprintf_s(chImageName, IMAGE_NAME_LEN, "%03d_L.bmp", stImageInfo.nFrameNum);
					sprintf_s(chImageName, IMAGE_NAME_LEN, "current_image.bmp", stImageInfo.nFrameNum);
				}
				if (i == 1)
				{
					//sprintf_s(chImageName, IMAGE_NAME_LEN, "%03d_R.bmp", stImageInfo.nFrameNum);
					sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_R.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
				}

			}
			else if (MV_Image_Jpeg == stParam.enImageType)
			{
				if (i == 0)
				{
					//sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_L.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
					sprintf_s(chImageName, IMAGE_NAME_LEN, "current_image.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
				}
				if (i == 1)
				{
					sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d_R.bmp", stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nFrameNum);
				}
			}

			FILE* fp = fopen(chImageName, "wb");

			fwrite(m_pcMyCamera[i]->m_pBufForSaveImage, 1, stParam.nImageLen, fp);
			//ui->label_debug->setText("save imgs");
			fclose(fp);
		}
	}
}


/*目标识别*/
// 使用权重进行读取识别
void PcbDetectv3::StartRecognize()
{
	//---------------------------------------加载类别---------------------------------------
	ifstream classNamesFile("./model/classes.names"); //ifstream默认以输入方式打开文件

	vector<string> classNamesVec;
	if (classNamesFile.is_open())
	{
		string className = "";
		while (std::getline(classNamesFile, className))
			classNamesVec.push_back(className);
	}

	//---------------------------------------模型设置---------------------------------------
	String cfg = "./model/yolo-obj.cfg";
	String weight = "./model/yolo-obj_4000.weights";
	//模型读入
	dnn::Net net = readNetFromDarknet(cfg, weight);
	//预处理读取的图像,并将图像读入网络
	Mat frame = imread("./current_image.bmp");

	//imshow("src", frame);
	Mat inputBlob = blobFromImage(frame, 1.0 / 255, Size(608, 608), Scalar());
	net.setInput(inputBlob);

	//获取未连接输出层
	std::vector<String> outNames = net.getUnconnectedOutLayersNames();
	std::vector<Mat> outs;
	net.forward(outs, outNames);

	//---------------------------------------目标检测---------------------------------------
	//需要的变量
	float* data;
	Mat scores;

	vector<Rect> boxes;
	vector<int> classIds;
	vector<float> confidences;
	int centerX, centerY, width, height, left, top;

	float confidenceThreshold = 0.2; // 置信度设置
	double confidence;

	Point classIdPoint;

	//找出所有的目标及其位置
	for (size_t i = 0; i < outs.size(); ++i)
	{
		data = (float*)outs[i].data;
		for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
		{
			scores = outs[i].row(j).colRange(5, outs[i].cols);
			minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
			//minMaxLoc(src, minVal, maxVal, minLoc, maxLoc, mask)在一个数组中找到全局最小值和全局最大值
			if (confidence > confidenceThreshold)
			{
				centerX = (int)(data[0] * frame.cols);
				centerY = (int)(data[1] * frame.rows);
				width = (int)(data[2] * frame.cols);
				height = (int)(data[3] * frame.rows);
				left = centerX - width / 2;
				top = centerY - height / 2;

				classIds.push_back(classIdPoint.x);
				confidences.push_back((float)confidence);
				boxes.push_back(Rect(left, top, width, height));
			}
		}
	}

	vector<int> indices;
	NMSBoxes(boxes, confidences, 0.3, 0.2, indices);

	//---------------------------------------效果展示---------------------------------------
	Scalar rectColor, textColor; //box 和 text 的颜色
	Rect box, textBox;
	int idx; //类别索引
	String className;
	Size labelSize;

	QString show_text;
	show_text = QString::fromLocal8Bit("当前图像的尺寸:"); // QString与string的转化,解决中文乱码问题
	//show_text = "The pixel size of the current image: ";
	show_text.append(QString::number(frame.size().width)); //将int转换成QString
	show_text.append(QString::fromLocal8Bit("×"));
	show_text.append(QString::number(frame.size().height));
	show_text.append("\n");

	cout << "当前图像的尺寸:" << frame.size() << endl;

	for (size_t i = 0; i < indices.size(); ++i)
	{
		idx = indices[i];
		className = classNamesVec[classIds[idx]];

		labelSize = getTextSize(className, FONT_HERSHEY_SIMPLEX, 0.5, 1, 0);
		box = boxes[idx];
		textBox = Rect(Point(box.x - 1, box.y),
			Point(box.x + labelSize.width, box.y - labelSize.height));
		rectColor = Scalar(idx * 11 % 256, idx * 22 % 256, idx * 33 % 256);
		textColor = Scalar(255 - idx * 11 % 256, 255 - idx * 22 % 256, 255 - idx * 33 % 256);

		rectangle(frame, box, rectColor, 20, 8, 0);  // 20表示线宽
		rectangle(frame, textBox, rectColor, -1, 8, 0);
		putText(frame, className.c_str(), Point(box.x, box.y - 2), FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, 8);

		// API参考:https://blog.csdn.net/KYJL888/article/details/82217192
		cout << className << ":" << "width:" << box.width << ",height:" << box.height << ",center:" << (box.tl() + box.br()) / 2 << endl;

		show_text.append(QString::fromLocal8Bit(className.c_str())); //string转化成Qstring类型
		show_text.append(": width:");
		show_text.append(QString::number(box.width));
		show_text.append(", height:");
		show_text.append(QString::number(box.height));
		show_text.append(", center:");
		int center_x = (box.tl().x + box.br().x) / 2;
		show_text.append(QString::number(center_x));
		show_text.append(",");
		int center_y = (box.tl().y + box.br().y) / 2;
		show_text.append(QString::number(center_y));
		show_text.append("\n");
	}

	ui.label_show_results->setText(show_text);
	//imshow("dst", frame);
	//imwrite("test.bmp", frame);  // 保存图像

	Mat show_detect_img;
	cvtColor(frame, show_detect_img, COLOR_BGR2RGB);         // 图像格式转换
	QImage disImage = QImage((const unsigned char*)(show_detect_img.data), show_detect_img.cols, show_detect_img.rows, QImage::Format_RGB888);
	ui.label_detect_display->setPixmap(QPixmap::fromImage(disImage.scaled(ui.label_detect_display->size(), Qt::KeepAspectRatio)));
}

MvCamera.cpp

#include "MvCamera.h"
#include <opencv.hpp>
#include"opencv2/opencv.hpp"
#include"opencv2/imgproc/types_c.h"

CMvCamera::CMvCamera()
{
    m_hDevHandle = MV_NULL;
}

CMvCamera::~CMvCamera()
{
    if (m_hDevHandle)
    {
        MV_CC_DestroyHandle(m_hDevHandle);
        m_hDevHandle = MV_NULL;
    }
}

// ch:获取SDK版本号 | en:Get SDK Version
int CMvCamera::GetSDKVersion()
{
    return MV_CC_GetSDKVersion();
}

// ch:枚举设备 | en:Enumerate Device
int CMvCamera::EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList)
{
    return MV_CC_EnumDevices(nTLayerType, pstDevList);
}

// ch:判断设备是否可达 | en:Is the device accessible
bool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode)
{
    return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);
}

// ch:打开设备 | en:Open Device
int CMvCamera::Open(MV_CC_DEVICE_INFO* pstDeviceInfo)
{
    if (MV_NULL == pstDeviceInfo)
    {
        return MV_E_PARAMETER;
    }

    if (m_hDevHandle)
    {
        return MV_E_CALLORDER;
    }

    int nRet = MV_CC_CreateHandle(&m_hDevHandle, pstDeviceInfo);
    if (MV_OK != nRet)
    {
        return nRet;
    }

    nRet = MV_CC_OpenDevice(m_hDevHandle);
    if (MV_OK != nRet)
    {
        MV_CC_DestroyHandle(m_hDevHandle);
        m_hDevHandle = MV_NULL;
    }

    return nRet;
}

// ch:关闭设备 | en:Close Device
int CMvCamera::Close()
{
    if (MV_NULL == m_hDevHandle)
    {
        return MV_E_HANDLE;
    }

    MV_CC_CloseDevice(m_hDevHandle);

    int nRet = MV_CC_DestroyHandle(m_hDevHandle);
    m_hDevHandle = MV_NULL;

    return nRet;
}

// ch:判断相机是否处于连接状态 | en:Is The Device Connected
bool CMvCamera::IsDeviceConnected()
{
    return MV_CC_IsDeviceConnected(m_hDevHandle);
}

// ch:注册图像数据回调 | en:Register Image Data CallBack
int CMvCamera::RegisterImageCallBack(void(__stdcall* cbOutput)(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser), void* pUser)
{
    return MV_CC_RegisterImageCallBackEx(m_hDevHandle, cbOutput, pUser);
}

// ch:开启抓图 | en:Start Grabbing
int CMvCamera::StartGrabbing()
{
    return MV_CC_StartGrabbing(m_hDevHandle);
}

// ch:停止抓图 | en:Stop Grabbing
int CMvCamera::StopGrabbing()
{
    return MV_CC_StopGrabbing(m_hDevHandle);
}

// ch:主动获取一帧图像数据 | en:Get one frame initiatively
int CMvCamera::GetImageBuffer(MV_FRAME_OUT* pFrame, int nMsec)
{
    return MV_CC_GetImageBuffer(m_hDevHandle, pFrame, nMsec);
}

// ch:释放图像缓存 | en:Free image buffer
int CMvCamera::FreeImageBuffer(MV_FRAME_OUT* pFrame)
{
    return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);
}

// ch:主动获取一帧图像数据 | en:Get one frame initiatively
int     CMvCamera::GetOneFrameTimeout(unsigned char* pData, unsigned int* pnDataLen, unsigned int nDataSize, MV_FRAME_OUT_INFO_EX* pFrameInfo, int nMsec)
{
    if (NULL == pnDataLen)
    {
        return MV_E_PARAMETER;
    }

    int nRet = MV_OK;

    *pnDataLen = 0;

    nRet = MV_CC_GetOneFrameTimeout(m_hDevHandle, pData, nDataSize, pFrameInfo, nMsec);
    if (MV_OK != nRet)
    {
        return nRet;
    }

    *pnDataLen = pFrameInfo->nFrameLen;

    return nRet;
}


// ch:设置显示窗口句柄 | en:Set Display Window Handle
int CMvCamera::DisplayOneFrame(MV_DISPLAY_FRAME_INFO* pDisplayInfo)
{
    return MV_CC_DisplayOneFrame(m_hDevHandle, pDisplayInfo);
}

// ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image cache nodes in SDK
int CMvCamera::SetImageNodeNum(unsigned int nNum)
{
    return MV_CC_SetImageNodeNum(m_hDevHandle, nNum);
}

// ch:获取设备信息 | en:Get device information
int CMvCamera::GetDeviceInfo(MV_CC_DEVICE_INFO* pstDevInfo)
{
    return MV_CC_GetDeviceInfo(m_hDevHandle, pstDevInfo);
}

// ch:获取GEV相机的统计信息 | en:Get detect info of GEV camera
int CMvCamera::GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT* pMatchInfoNetDetect)
{
    if (MV_NULL == pMatchInfoNetDetect)
    {
        return MV_E_PARAMETER;
    }

    MV_CC_DEVICE_INFO stDevInfo = { 0 };
    GetDeviceInfo(&stDevInfo);
    if (stDevInfo.nTLayerType != MV_GIGE_DEVICE)
    {
        return MV_E_SUPPORT;
    }

    MV_ALL_MATCH_INFO struMatchInfo = { 0 };

    struMatchInfo.nType = MV_MATCH_TYPE_NET_DETECT;
    struMatchInfo.pInfo = pMatchInfoNetDetect;
    struMatchInfo.nInfoSize = sizeof(MV_MATCH_INFO_NET_DETECT);
    memset(struMatchInfo.pInfo, 0, sizeof(MV_MATCH_INFO_NET_DETECT));

    return MV_CC_GetAllMatchInfo(m_hDevHandle, &struMatchInfo);
}

// ch:获取U3V相机的统计信息 | en:Get detect info of U3V camera
int CMvCamera::GetU3VAllMatchInfo(MV_MATCH_INFO_USB_DETECT* pMatchInfoUSBDetect)
{
    if (MV_NULL == pMatchInfoUSBDetect)
    {
        return MV_E_PARAMETER;
    }

    MV_CC_DEVICE_INFO stDevInfo = { 0 };
    GetDeviceInfo(&stDevInfo);
    if (stDevInfo.nTLayerType != MV_USB_DEVICE)
    {
        return MV_E_SUPPORT;
    }

    MV_ALL_MATCH_INFO struMatchInfo = { 0 };

    struMatchInfo.nType = MV_MATCH_TYPE_USB_DETECT;
    struMatchInfo.pInfo = pMatchInfoUSBDetect;
    struMatchInfo.nInfoSize = sizeof(MV_MATCH_INFO_USB_DETECT);
    memset(struMatchInfo.pInfo, 0, sizeof(MV_MATCH_INFO_USB_DETECT));

    return MV_CC_GetAllMatchInfo(m_hDevHandle, &struMatchInfo);
}

// ch:获取和设置Int型参数,如 Width和Height,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
// en:Get Int type parameters, such as Width and Height, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int     CMvCamera::GetIntValue(IN const char* strKey, OUT unsigned int* pnValue)
{
    if (NULL == strKey || NULL == pnValue)
    {
        return MV_E_PARAMETER;
    }

    MVCC_INTVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_INTVALUE));
    int nRet = MV_CC_GetIntValue(m_hDevHandle, strKey, &stParam);
    if (MV_OK != nRet)
    {
        return nRet;
    }

    *pnValue = stParam.nCurValue;

    return MV_OK;
}


int CMvCamera::SetIntValue(IN const char* strKey, IN int64_t nValue)
{
    return MV_CC_SetIntValueEx(m_hDevHandle, strKey, nValue);
}

// ch:获取和设置Enum型参数,如 PixelFormat,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
// en:Get Enum type parameters, such as PixelFormat, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int CMvCamera::GetEnumValue(IN const char* strKey, OUT MVCC_ENUMVALUE* pEnumValue)
{
    return MV_CC_GetEnumValue(m_hDevHandle, strKey, pEnumValue);
}

int CMvCamera::SetEnumValue(IN const char* strKey, IN unsigned int nValue)
{
    return MV_CC_SetEnumValue(m_hDevHandle, strKey, nValue);
}

int CMvCamera::SetEnumValueByString(IN const char* strKey, IN const char* sValue)
{
    return MV_CC_SetEnumValueByString(m_hDevHandle, strKey, sValue);
}

// ch:获取和设置Float型参数,如 ExposureTime和Gain,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
// en:Get Float type parameters, such as ExposureTime and Gain, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int CMvCamera::GetFloatValue(IN const char* strKey, OUT MVCC_FLOATVALUE* pFloatValue)
{
    return MV_CC_GetFloatValue(m_hDevHandle, strKey, pFloatValue);
}

int CMvCamera::SetFloatValue(IN const char* strKey, IN float fValue)
{
    return MV_CC_SetFloatValue(m_hDevHandle, strKey, fValue);
}

// ch:获取和设置Bool型参数,如 ReverseX,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
// en:Get Bool type parameters, such as ReverseX, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int CMvCamera::GetBoolValue(IN const char* strKey, OUT bool* pbValue)
{
    return MV_CC_GetBoolValue(m_hDevHandle, strKey, pbValue);
}

int CMvCamera::SetBoolValue(IN const char* strKey, IN bool bValue)
{
    return MV_CC_SetBoolValue(m_hDevHandle, strKey, bValue);
}

// ch:获取和设置String型参数,如 DeviceUserID,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件UserSetSave
// en:Get String type parameters, such as DeviceUserID, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int CMvCamera::GetStringValue(IN const char* strKey, MVCC_STRINGVALUE* pStringValue)
{
    return MV_CC_GetStringValue(m_hDevHandle, strKey, pStringValue);
}

int CMvCamera::SetStringValue(IN const char* strKey, IN const char* strValue)
{
    return MV_CC_SetStringValue(m_hDevHandle, strKey, strValue);
}

// ch:执行一次Command型命令,如 UserSetSave,详细内容参考SDK安装目录下的 MvCameraNode.xlsx 文件
// en:Execute Command once, such as UserSetSave, for details please refer to MvCameraNode.xlsx file under SDK installation directory
int CMvCamera::CommandExecute(IN const char* strKey)
{
    return MV_CC_SetCommandValue(m_hDevHandle, strKey);
}

// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
int CMvCamera::GetOptimalPacketSize(unsigned int* pOptimalPacketSize)
{
    if (MV_NULL == pOptimalPacketSize)
    {
        return MV_E_PARAMETER;
    }

    int nRet = MV_CC_GetOptimalPacketSize(m_hDevHandle);
    if (nRet < MV_OK)
    {
        return nRet;
    }

    *pOptimalPacketSize = (unsigned int)nRet;

    return MV_OK;
}

// ch:注册消息异常回调 | en:Register Message Exception CallBack
int CMvCamera::RegisterExceptionCallBack(void(__stdcall* cbException)(unsigned int nMsgType, void* pUser), void* pUser)
{
    return MV_CC_RegisterExceptionCallBack(m_hDevHandle, cbException, pUser);
}

// ch:注册单个事件回调 | en:Register Event CallBack
int CMvCamera::RegisterEventCallBack(const char* pEventName, void(__stdcall* cbEvent)(MV_EVENT_OUT_INFO* pEventInfo, void* pUser), void* pUser)
{
    return MV_CC_RegisterEventCallBackEx(m_hDevHandle, pEventName, cbEvent, pUser);
}

// ch:强制IP | en:Force IP
int CMvCamera::ForceIp(unsigned int nIP, unsigned int nSubNetMask, unsigned int nDefaultGateWay)
{
    return MV_GIGE_ForceIpEx(m_hDevHandle, nIP, nSubNetMask, nDefaultGateWay);
}

// ch:配置IP方式 | en:IP configuration method
int CMvCamera::SetIpConfig(unsigned int nType)
{
    return MV_GIGE_SetIpConfig(m_hDevHandle, nType);
}

// ch:设置网络传输模式 | en:Set Net Transfer Mode
int CMvCamera::SetNetTransMode(unsigned int nType)
{
    return MV_GIGE_SetNetTransMode(m_hDevHandle, nType);
}

// ch:像素格式转换 | en:Pixel format conversion
int CMvCamera::ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM* pstCvtParam)
{
    return MV_CC_ConvertPixelType(m_hDevHandle, pstCvtParam);
}

// ch:保存图片 | en:save image
int CMvCamera::SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam)
{
    return MV_CC_SaveImageEx2(m_hDevHandle, pstParam);
}

// ch:保存图片为文件 | en:Save the image as a file
int CMvCamera::SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM* pstSaveFileParam)
{
    return MV_CC_SaveImageToFile(m_hDevHandle, pstSaveFileParam);
}


//设置是否为触发模式
int CMvCamera::setTriggerMode(unsigned int TriggerModeNum)
{
    //0:Off  1:On
    int tempValue = MV_CC_SetEnumValue(m_hDevHandle, "TriggerMode", TriggerModeNum);
    if (tempValue != 0){
        return -1;
    }
    else {
        return 0;
    }
}

//设置触发源
int CMvCamera::setTriggerSource(unsigned int TriggerSourceNum)
{
    //0:Line0  1:Line1  7:Software
    int tempValue = MV_CC_SetEnumValue(m_hDevHandle, "TriggerSource", TriggerSourceNum);
    if (tempValue != 0) {
        return -1;
    }
    else {
        return 0;
    }
}

// ************************************************************************************************
//发送软触发
int CMvCamera::softTrigger()
{
    int tempValue = MV_CC_SetCommandValue(m_hDevHandle, "TriggerSoftware");
    if (tempValue != 0)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}

//读取相机中的图像
//int ReadBuffer(cv::Mat &image);
//读取相机中的图像
int CMvCamera::ReadBuffer(cv::Mat& image)
{
    cv::Mat* getImage = new cv::Mat();
    unsigned int nRecvBufSize = 0;
    MVCC_INTVALUE stParam;
    memset(&stParam, 0, sizeof(MVCC_INTVALUE));
    int tempValue = MV_CC_GetIntValue(m_hDevHandle, "PayloadSize", &stParam);
    if (tempValue != 0)
    {
        return -1;
    }
    nRecvBufSize = stParam.nCurValue;
    unsigned char* pDate;
    pDate = (unsigned char*)malloc(nRecvBufSize);

    MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };
    tempValue = MV_CC_GetOneFrameTimeout(m_hDevHandle, pDate, nRecvBufSize, &stImageInfo, 500);
    if (tempValue != 0)
    {
        return -1;
    }
    m_nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;
    unsigned char* m_pBufForSaveImage;
    m_pBufForSaveImage = (unsigned char*)malloc(m_nBufSizeForSaveImage);


    bool isMono;
    switch (stImageInfo.enPixelType)
    {
    case PixelType_Gvsp_Mono8:
    case PixelType_Gvsp_Mono10:
    case PixelType_Gvsp_Mono10_Packed:
    case PixelType_Gvsp_Mono12:
    case PixelType_Gvsp_Mono12_Packed:
        isMono = true;
        break;
    default:
        isMono = false;
        break;
    }
    if (isMono)
    {
        *getImage = cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC1, pDate);
        //imwrite("d:\\测试opencv_Mono.tif", image);
    }
    else
    {
        //转换图像格式为BGR8
        MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
        memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));
        stConvertParam.nWidth = stImageInfo.nWidth;                 //ch:图像宽 | en:image width
        stConvertParam.nHeight = stImageInfo.nHeight;               //ch:图像高 | en:image height
        //stConvertParam.pSrcData = m_pBufForDriver;                  //ch:输入数据缓存 | en:input data buffer
        stConvertParam.pSrcData = pDate;                  //ch:输入数据缓存 | en:input data buffer
        stConvertParam.nSrcDataLen = stImageInfo.nFrameLen;         //ch:输入数据大小 | en:input data size
        stConvertParam.enSrcPixelType = stImageInfo.enPixelType;    //ch:输入像素格式 | en:input pixel format
        stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; //ch:输出像素格式 | en:output pixel format  适用于OPENCV的图像格式
        //stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed;   //ch:输出像素格式 | en:output pixel format
        stConvertParam.pDstBuffer = m_pBufForSaveImage;                    //ch:输出数据缓存 | en:output data buffer
        stConvertParam.nDstBufferSize = m_nBufSizeForSaveImage;            //ch:输出缓存大小 | en:output buffer size
        MV_CC_ConvertPixelType(m_hDevHandle, &stConvertParam);

        *getImage = cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC3, m_pBufForSaveImage);

    }
    (*getImage).copyTo(image);
    (*getImage).release();
    free(pDate);
    free(m_pBufForSaveImage);
    return 0;
}

mythread.cpp

#include "mythread.h"

MyThread::MyThread()
{
}

MyThread::~MyThread()
{
	terminate();
	if (cameraPtr != NULL)
	{
		delete cameraPtr;
	}
	if (imagePtr != NULL)
	{
		delete imagePtr;
	}
}

void MyThread::getCameraPtr(CMvCamera* camera)
{
	cameraPtr = camera;
}

void MyThread::getImagePtr(Mat* image)
{
	imagePtr = image;
}

void MyThread::getCameraIndex(int index)
{
	cameraIndex = index;
}

//void MyThread::get_TriggerMode(int m_nTriggerMode)
//{
//	TriggerMode = m_nTriggerMode;
//}

void MyThread::run()
{
	if (cameraPtr == NULL){
		return;
	}

	if (imagePtr == NULL){
		return;
	}

	while (!isInterruptionRequested())
	{
		std::cout << "Thread_Trigger:" << cameraPtr->softTrigger() << std::endl;
		std::cout << "Thread_Readbuffer:" << cameraPtr->ReadBuffer(*imagePtr) << std::endl;
		/*emit mess();*/
		emit Display(imagePtr, cameraIndex);//发送信号 img_display_label接收并显示
		msleep(30);
	}
}

效果

(因为放假回家相机没带回来,这里只看下界面效果)
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二) 的相关文章

  • OpenCV 错误:使用 COLOR_BGR2GRAY 函数时断言失败

    我在使用 opencv 时遇到了一个奇怪的问题 我在 jupyter 笔记本中工作时没有任何问题 但在尝试运行此 Sublime 时却出现问题 错误是 OpenCV错误 cvtColor中断言失败 深度 CV 8U 深度 CV 16U 深度
  • 如何自动更新Android Studio?

    我需要将 Android Studio 更新到 0 9 9 版本 但是当我按 下载 在更新信息对话框上 时 它会将我发送到此处 http developer android com sdk index html http developer
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • 无法在 Windows 7 机器中使用 OpenCV 2.4.3、Python 2.7 打开“.mp4”视频文件

    我目前正在进行一个涉及读取 mp4 视频文件的项目 我遇到的问题是它在Windows 7机器上使用Python 2 7 32位 OpenCV 2 4 3 cv2 pyd 代码片段如下 try video cv2 VideoCapture v
  • 使用 ffmpeg 或 OpenCV 处理原始图像

    看完之后维基百科页面 http en wikipedia org wiki Raw image format原始图像格式 是任何图像的数字负片 为了查看或打印 相机图像传感器的输出具有 进行处理 即转换为照片渲染 场景 然后以标准光栅图形格
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • ffmpeg AVFrame 到 opencv Mat 转换

    我目前正在开发一个使用 ffmpeg 解码接收到的帧的项目 解码后 我想将 AVFrame 转换为 opencv Mat 帧 以便我可以在 imShow 函数上播放它 我拥有的是字节流 我将其读入缓冲区 解码为 AVFrame f fope
  • 从图像坐标获取对象的世界坐标

    I have been following this http docs opencv org modules calib3d doc camera calibration and 3d reconstruction html docume
  • 如何去除给定图像中的噪声,使 ocr 输出完美?

    我已经对这个孟加拉文本图像进行了大津阈值处理 并使用 tesseract 进行 OCR 但输出非常糟糕 我应该应用什么预处理来消除噪音 我也想校正图像 因为它有轻微的倾斜 我的代码如下 import tesserocr from PIL i
  • 使用 C# 获取 ec2-instance 标签

    我不是开发人员 所以也许答案是有不同的解决方案 但我无法真正从 python 或其他东西翻译它 我尝试使用 AWS NET SDK 查找实例 然后获取实例的标签 我已经能够确定实例是否已启动并正在运行 我还了解了如何创建和删除标签 不在下面
  • 如何使用 Python 裁剪图像中的矩形

    谁能给我关于如何裁剪两个矩形框并保存它的建议 我已经尝试过这段代码 但效果不佳 import cv2 import numpy as np Run the code with the image name keep pressing spa
  • uri 警告中缺少端口:使用 Python OpenCV cv2.VideoCapture() 打开文件时出错

    当我尝试流式传输 ipcam 时 出现了如下所示的错误 tcp 000000000048c640 uri 中缺少端口 警告 打开文件时出错 build opencv modules videoio src cap ffmpeg impl h
  • Android SDK 管理器不工作

    启动 Eclipse 时我收到一条消息 This version of ADT requires Android SDK Tools revision 21 0 0 rc9 or above Current version is 10 0
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 在 Visual Studio 2012 中安装 OpenCV

    我正在尝试安装 OpenCV 来与 Visual Studio 一起使用 我使用的是2012Pro版本 但我认为它应该与vs10相同 我正在关注这个教程 http docs opencv org doc tutorials introduc
  • YOLOv8获取预测边界框

    我想将 OpenCV 与 YOLOv8 集成ultralytics 所以我想从模型预测中获取边界框坐标 我该怎么做呢 from ultralytics import YOLO import cv2 model YOLO yolov8n pt
  • OpenCV VideoWriter 未写入 Output.avi

    我正在尝试编写一段简单的代码来获取视频 裁剪视频并写入输出文件 系统设置 OS Windows 10 Conda Environment Python Version 3 7 OpenCV Version 3 4 2 ffmpeg Vers
  • 在 Visual Studio C++ 2008 中包含 dll

    有没有办法将 dll 包含在项目中 这样我就不必在编译后将这些 dll 与可执行文件放在同一文件夹中 这样我就可以用它们编译我的项目 这是否有可能 如果是 有人可以指导我 我的项目是一个 opencv 项目 有很多 dll 我必须包含在文件
  • Python:Urllib2 和 OpenCV

    我有一个程序 可以将图像保存在本地目录中 然后从该目录中读取图像 但我不想保存图像 我想直接从url读取它 这是我的代码 import cv2 cv as cv import urllib2 url http cache2 allposte
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho

随机推荐

  • 《FPGA学习》->点亮一颗LED灯

    x1f34e 与其担心未来 xff0c 不如现在好好努力 在这条路上 xff0c 只有奋斗才能给你安全感 你若努力 xff0c 全世界都会为你让路 大家刚开始接触硬件编程的话 xff0c 我想大多都是从点亮一颗LED灯开始 xff0c 学习
  • 《FPGA学习》->流水灯设计

    x1f34e 与其担心未来 xff0c 不如现在好好努力 在这条路上 xff0c 只有奋斗才能给你安全感 你若努力 xff0c 全世界都会为你让路 用verilog HDL语言设计一个FPGA的流水灯程序 xff0c 要求时序满足下图所示
  • 《FPGA学习》->多个按键控制LED灯

    x1f34e 与其担心未来 xff0c 不如现在好好努力 在这条路上 xff0c 只有奋斗才能给你安全感 你若努力 xff0c 全世界都会为你让路 本次项目任务 xff0c 利用开发板上的4个按键KEY1 xff0c KEY2 xff0c
  • 《FPGA学习》->呼吸灯

    x1f34e 与其担心未来 xff0c 不如现在好好努力 在这条路上 xff0c 只有奋斗才能给你安全感 你若努力 xff0c 全世界都会为你让路 呼吸灯 xff0c 简而言之就像人类呼吸一样 xff0c 有节奏的让LED灯从 xff1a
  • 《FPGA学习》->蜂鸣器播放

    x1f34e 与其担心未来 xff0c 不如现在好好努力 在这条路上 xff0c 只有奋斗才能给你安全感 你若努力 xff0c 全世界都会为你让路 蜂鸣器的发声原理由振动装置和谐振装置组成 xff0c 而蜂鸣器又分为无源他激型与有源自激型
  • 基于STM32的语音控制电机

    号外号外 单片机项目实战课程又更新了 炸弹 大家好 我是 朽木自雕i 一个闲暇时间用来敲敲代码 画画板子 焊焊电路 玩玩单片机 搞搞Linux 写写Blog记录成长的技术人er 很高兴再次见
  • ESP32单片机入门篇

    目录 一 ESP32单片机的基本概念 1 双核架构 2 Wi Fi和蓝牙功能 3 集成多种外设 4 支持多种操作系统 二 开发环境 1 Arduino IDE 2 ESP IDF 三 开发语言 四 注意事项 五 代码例程 xff08 1 x
  • 什么是死锁,产生死锁的原因及必要条件

    什么是死锁 xff1f 所谓死锁 xff0c 是指多个进程在运行过程中因争夺资源而造成的一种僵局 xff0c 当进程处于这种僵持状态时 xff0c 若无外力作用 xff0c 它们都将无法再向前推进 因此我们举个例子来描述 xff0c 如果此
  • ESP32红外控制舵机

    目录 一 ESP32红外解码 二 ESP32舵机控制 三 ESP32红外控制舵机 结语 ESP32作为一款功能强大的单片机 xff0c 常被应用于物联网 智能家居 智能硬件等领域 与其他单片机相比 xff0c ESP32具有更高的运行速度和
  • ESP32 OTA升级

    目录 一 ESP32 OTA升级原理 1 ESP32固件编译 2 固件的远程传输 二 基于ESP32HTTPUpdate库的OTA升级 1 硬件准备 2 软件实现 三 注意事项 1 升级文件大小限制 2 WiFi稳定性 3 固件版本号 结语
  • 基于ESP32的温湿度环境监测

    目录 一 传感器介绍 二 设计思路 三 电路连接 四 项目代码 五 注意事项 一 传感器介绍 SCH30 是一款温湿度一体化数字传感器 xff0c 采用CMOSens 技术 xff0c 提供出色的性能 可靠性和稳定性 它还具有超低能耗 xf
  • 小觅相机SDK安装与报错解决

    目录 安装小觅相机SDK1 下载SDK2 准备依赖3 编译代码出现问题 xff1a 报错 xff1a 原因 xff1a 解决方案 xff1a 4 编译安装ROS版本ROS的安装 5 配置 bashrc文件6 运行相机 最后顺利完成SDK安装
  • 基于51单片机和物联网的智能家居系统(ESP8266物联网模块)

    前言 该智能家居系统以 STC89C52单片机为控制核心 xff0c 结合 LCD1602 液晶显示屏 L298N电机驱动模块 光敏电阻 xff0c ESP8266WiFi模块 xff0c DS18B20温度计设计并实现了自动感光窗帘与居室
  • aarch64-linux-gnu-gcc交叉编译链工具

    aarch64 linux gnu gcc交叉编译工具链 安装编译可执行文件交叉编译 自己记录学习所用 安装 按下 CTRL 43 ALT 43 T打开控制台 xff0c 输入如下指令安装 span class token comment
  • CMakeLists.txt的创建和基本使用

    文章目录 1 简单介绍2 一个简单的例子3 将主函数及库函数一起编译4 带上外部库 学习记录所用 1 简单介绍 CMakeLists txt文件的编写比MakeFile文件的编写更加简单和容易理解 CMakeLists txt通过cmake
  • linux线程切换怎么实现

    Linux线程切换的实现涉及到操作系统的调度 和线程上下文 的切换 线程上下文包括程序计数器 xff08 PC xff09 和寄存器值 xff0c 以及线程的堆栈和堆栈指针等 操作系统通过调度器决定哪个线程将获得CPU时间片来执行 当一个线
  • PID实时无线调参

    今天实现了PID参数的实时无线整定 xff0c 记录一下历程 1 将CRC h CRC c usart2 c usart2 h等文件添加到STM32工程中 如下图 xff1a 2 其中 xff0c CRC h CRC c用于数据包的校验 x
  • 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一)

    最近在做一个项目 xff0c 涉及到工业相机 xff0c 需要对其进行二次开发 相机方面选择了海康威视 xff0c 网上关于海康威视工业相机SDK的开发资料很少 xff0c 官方文档里面虽然写的是支持C 43 43 开发的 xff0c 但其
  • FFmpeg源码分析:写音视频帧av_write_frame()

    FFmpeg在libavformat模块提供音视频的muxer封装与demuxer解封装 其中muxer封装文件包括avformat write header av write frame 和av write trailer 本文主要探讨a
  • 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)

    本文接上次的博客海康威视工业相机SDK二次开发 xff08 VS 43 Opencv 43 QT 43 海康SDK 43 C 43 43 xff09 xff08 一 xff09 xff0c 上个博客中并未用到QT xff0c 本文介绍项目内