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

本文接上次的博客海康威视工业相机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 

#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   
#include   
#include   
#include   
#include   
#include   
#include   
#include   

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 
#include 
#include 
#include 
#include 

#include
#include
#include
#include

#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 

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

PcbDetectv3.cpp

#include "PcbDetectv3.h"
#include 
#include 

#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 
#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);
	}
}

效果

(因为放假回家相机没带回来,这里只看下界面效果)
海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)_第1张图片

你可能感兴趣的