700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

时间:2020-09-29 01:26:40

相关推荐

Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

关于在Windows环境中对海康威视工业相机SDK进行二次开发的话,可以参考这两篇博客。

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

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

然后最近因为××原因,又要转到Linux环境下对海康威视工业相机的SDK进行二次开发使用,还是在虚拟机中搞的。。。

之前一直用的都是Visual Studio编译器,虽然有过Qt的界面开发经验,但都是借助VS中的Qt 设计师,这次在Ubuntu16.04系统中用Qt Creator进行开发,编译用CMake完成。

目录

1.关于CMake编译工具与项目构建1.1 C++程序编译过程1.2 Make和Makefile的关系1.3 CMake和CMakeLists的关系1.4 关于CMakeLists的编写 2.源码说明:①关于SDK的源码版本②关于彩色和黑白的疑问③关于Linux中的路径问题④关于曝光和增益的理解⑤在QLineEdit中使用setValidator设置区间 2.1 CMakeLists.txt2.2 MvCamera.h2.3 mythread.h2.4 widget.h2.5 main.cpp2.6 MvCamera.cpp2.7 mythread.cpp2.8 widget.cpp2.9 widget.ui2.10 运行效果

1.关于CMake编译工具与项目构建

(由于之前一直都没用过CMake对项目进行管理,特别感谢这篇文章,写的不错。)https://mp./s/WglXaNNDETKKu6zICRYswQ)

1.1 C++程序编译过程

编译分为四个过程:预处理阶段、编译阶段、汇编阶段、链接阶段。

预处理阶段:处理以#开头的指令,生成.i预编译文件。编译阶段:将源码的.cpp文件翻译成.s汇编代码。汇编阶段:将汇编代码.s翻译成机器指令.o文件。链接阶段:对于汇编阶段生成的.o文件,并不会立刻执行,因为可能出现在源码的.cpp文件中引用了另一个.cpp文件中的东西,则链接的目的就是将这些文件对应的目标文件连接成一个整体,从而生成可执行的程序.exe文件。

1.2 Make和Makefile的关系

当源文件比较多时,一般不适合直接通过gcc来编译代码,这时就需要一个自动化的编译工具。

Make(GNU Make)是一个自动化软件,用于将源代码文件编译为可执行的二进制文件从而完成自动化编译。Make工具编译的时候需要Makefile文件提供编译规则,Makefile定义了一系列的编译规则,包括编译的先后顺序,哪些文件需要重新编译等操作。

利用Make工具可以自动完成编译工作,如果修改了某几个源文件,则只重新编译这几个源文件。如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译极大地提高了开发效率,避免了不必要的重新编译。

1.3 CMake和CMakeLists的关系

简单来说,CMake强大在其是跨平台的项目管理工具,它能够输出各种Makefile文件或工程文件。例如,在Windows环境下它能生成Visual Studio的工程,在Linux环境下它会生成Makefile文件。也就是说,Cmake能够按照同一个抽象规则为各个编译器生成工程文件,从而忽略不同平台的差异,抽象成为一个一致的环境。

CMake命令的执行所按照的规则也就是由CMakeLists.txt文件编写的。

通过CMake工具可以读入所有源文件,自动生成Makefile。开发的基本流程如下:

编写源文件编写CMakeLists.txt由CMake根据CMakeLists.txt生成Makefile由Make根据Makefile,调用gcc生成可执行文件

1.4 关于CMakeLists的编写

这篇博文写的很详细:/afei__/article/details/8139

CMakeLists.txt的编写主要包含以下步骤

cmake_minimum_required(VERSION 2.8.0):用于指定cmake所需最低版本;project(Project):用于指定项目名称;include_directories():用于包含头文件目录;aux_source_directory(src dir_srcs):用于包含源文件目录;set(TEST_MATH):用于设置环境变量,编译用到的源文件全部都要放到这里;add_executable(${PROJECT_NAME} ${TEST_MATH}):用于添加要编译的可执行文件;target_link_libraries(${PROJECT_NAME} m):用于添加可执行文件所需要的库;

link_libraries和target_link_libraries的区别:

link_libraries是指定要链接的库文件路径。自己生成的库文件可以用该指令指定目录的路径以便工程能够找到。target_link_libraries是将目标文件与库文件进行链接,可以指定动态库/静态库,如果只提供库名称,系统会根据链接库目录搜索xxx.so 或者 xxx.a 文件;或者指定给出全路径。

资料参考:

CMAKE find_path和find_library命令的用法和解释

QT 使用cmakelist.txt 导入opencv

CMakeLists.txt添加opencv库注意事项

CMakeList.txt设置OpenCv路径

常用库(QT,PCL,OPENCV,EIGEN3等)的cmakelists.txt模板

2.源码

说明:

①关于SDK的源码版本

一开始我是直接复制的之前在Windows环境下开发的相关代码,经过几个SDK的源码对比,发现还是有一点不一样,有些API可能改名或者就没有了,如果某些功能你在Windows中能够实现,到了Linux环境中却实现不了了,可以修改CameraParams.hMvCameraControl.hMvErrorDefine.hPixelType.h这几个文件,以满足项目的需求。

②关于彩色和黑白的疑问

之前在Windows环境下开发用的是海康的彩色相机,这次在Linux环境下用的是海康的黑白相机,我直接移植了之前的代码并配置了相关环境,发现在Qt中通过QLabel显示的图像和相机实际拍到的不一样(QLabel中显示的图像很模糊),一开始以为是彩色和黑白的区别,但通过保存图像的按钮发现保存的图片没什么问题,那就是QLabel的显示问题了。

后来查了下QImage图像格式解读:(我也没看懂哪里是灰度图像的格式)/weixin_39485901/article/details/88047291

最后将QImage::Format_Indexed8改成了QImage::Format_RGB888,问题就解决了。(这里有个疑问,QImage::Format_RGB888 图像存储使用8-8-8 24位RGB格式,这里明显是彩色图像3个通道的,而黑白的海康威视工业相机我经过打印确认通道是1个,那为什么用QImage::Format_RGB888就可以呢???不理解,如有大佬知晓希望告知。)

③关于Linux中的路径问题

在设置背景图时,我默认Windows环境中的当前工程目录为相对路径,就想弄个图片作为背景图,发现不是同一个路径。比如我的项目名称是sdkCamera,则该工程项目的文件夹是build-sdkCamera-Desktop_Qt_5_12_9_GCC_64bit-Debug

④关于曝光和增益的理解

曝光和增益是直接控制传感器(CCD/CMOS)上读出来的数据,是要优先调节的,以调节曝光时间为主。在不过曝的前提下,增加曝光时间可以增加信噪比,使图像清晰。当然,对于很弱的信号,曝光也不能无限增加,因为随着曝光时间的增加,噪音也会积累, 曝光补偿就是增加拍摄时的曝光量。增益一般只是在信号弱,但不想增加曝光时间的情况下使用,一般相机增益都产生很大噪音。工业相机在不同增益时图像的成像质量不一样,增益越小,噪点越小;增益越大,噪点越多,特别是在暗处。数码相机的ISO就是这里说的增益,增大ISO,是增加感光器件对光的灵敏度。高感光度对低光照灵敏,同时对噪杂信号也灵敏,信噪比小,所以高感光度噪点也多(可利用图片软件的降噪功能减轻或去除)。

调节亮度增益说白了就是改变ISO,改变CMOS传感器的感光性能,但是会影响到画质。调节曝光补偿则是为了改变快门速度,不改变ISO不会影响画质。

⑤在QLineEdit中使用setValidator设置区间

参考:/qq78442761/article/details/80276764/

2.1 CMakeLists.txt

对于一个习惯了用Visual Studio编译器编程、调试、配置环境的人,一开始转到CMake,编写CMakeLists.txt文件时,我是一脸懵逼的,还要用Qt Creator进行调试编译。。。

有幸看了上面一些大佬写的关于CMakeLists.txt文件的编写,再对照当初在Visual Studio中的环境配置过程,慢慢的自己也配置成功了海康威视SDK和OpenCV。

Windows下的MVS配置

附加包含目录:D:MVS\MVS\Development\Includes

附加库目录:D:MVS\MVS\Development\Libraries\win64

附加依赖项:MvCameraControl.lib

工程项目添加:MvCamera.h、MvCamera.cpp

Windows下的OpenCV配置

包含目录:D:\opencv4.4\opencv\build\include\opencv2

D:\opencv4.4\opencv\build\include

库目录: D:\opencv4.4\opencv\build\x64\vc15\lib

链接器: opencv_world440d.lib

opencv_world440.lib

这是我的CMakeLists.txt源文件:

cmake_minimum_required(VERSION 3.5)project(aubo_camera LANGUAGES CXX)set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON)set(CMAKE_AUTOMOC ON)set(CMAKE_AUTORCC ON)set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)set( CMAKE_CXX_FLAGS "-std=c++11" )set(OpenCV_DIR /home/aubo/opencv-4.4.0/build)find_package( OpenCV 4 REQUIRED)include_directories( ${OpenCV_INCLUDE_DIRS} )# QtCreator supports the following variables for Android, which are identical to qmake Android variables.# Check http://doc.qt.io/qt-5/deployment-android.html for more information.# They need to be set before the find_package(Qt5 ...) call.#if(ANDROID)# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")# if (ANDROID_ABI STREQUAL "armeabi-v7a")# set(ANDROID_EXTRA_LIBS# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)# endif()#endif()find_package(Qt5 COMPONENTS Widgets REQUIRED)if(ANDROID)add_library(aubo_camera SHAREDmain.cppwidget.cppMvCamera.cppmythread.cppmythread.hMvCamera.hwidget.hwidget.ui)else()add_executable(aubo_cameramain.cppwidget.cppMvCamera.cppmythread.cppmythread.hMvCamera.hwidget.hwidget.ui)endif()find_library(CAMERA_LIB libMvCameraControl.so libMvCameraControl.so.3.1.3.0 /home/aubo/MVS-2.1.0_x86_64_2028/MVS/lib/64/)find_path(MVS_PATH CameraParams.h MvCameraControl.h MvErrorDefine.h PixelType.h /home/aubo/MVS-2.1.0_x86_64_2028/MVS/include)INCLUDE_DIRECTORIES(${MVS_PATH})target_link_libraries(aubo_camera PRIVATE Qt5::Widgets ${CAMERA_LIB} ${OpenCV_LIBS})

关于Linux环境下海康威视SDK的下载安装和OpenCV的源码编译,请移步于:

VMware虚拟机中Ubuntu16.04系统下通过MVS运行海康威视工业相机

VMware虚拟机中Ubuntu16.04系统下进行OpenCV4.4的安装编译

下面在CMakeList.txt中的文件安装目录根据自己的实际安装位置为准。

2.2 MvCamera.h

#ifndef MVCAMERA_H#define MVCAMERA_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"class CMvCamera{public:CMvCamera();~CMvCamera();// ch:获取SDK版本号 | en:Get SDK Versionstatic int GetSDKVersion();// ch:枚举设备 | en:Enumerate Devicestatic int EnumDevices(unsigned int nTLayerType,MV_CC_DEVICE_INFO_LIST *pstDevList);// ch:判断设备是否可达 | en:Is the device accessiblestatic bool IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,unsigned int nAccessMode);// ch:打开设备 | en:Open Deviceint Open(MV_CC_DEVICE_INFO *pstDeviceInfo);// ch:关闭设备 | en:Close Deviceint Close();// ch:判断相机是否处于连接状态 | en:Is The Device Connectedbool IsDeviceConnected();// ch:注册图像数据回调 | en:Register Image Data CallBackint RegisterImageCallBack(void(__stdcall *cbOutput)(unsigned char *pData,MV_FRAME_OUT_INFO_EX *pFrameInfo,void *pUser),void *pUser);// ch:开启抓图 | en:Start Grabbingint StartGrabbing();// ch:停止抓图 | en:Stop Grabbingint StopGrabbing();// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint GetImageBuffer(MV_FRAME_OUT *pFrame, int nMsec);// ch:释放图像缓存 | en:Free image bufferint FreeImageBuffer(MV_FRAME_OUT *pFrame);// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint GetOneFrameTimeout(unsigned char *pData, unsigned int *pnDataLen,unsigned int nDataSize,MV_FRAME_OUT_INFO_EX *pFrameInfo, int nMsec);// ch:显示一帧图像 | en:Display one frame imageint DisplayOneFrame(MV_DISPLAY_FRAME_INFO *pDisplayInfo);// ch:设置SDK内部图像缓存节点个数 | en:Set the number of the internal image// cache nodes in SDKint SetImageNodeNum(unsigned int nNum);// ch:获取设备信息 | en:Get device informationint GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo);// ch:获取GEV相机的统计信息 | en:Get detect info of GEV cameraint GetGevAllMatchInfo(MV_MATCH_INFO_NET_DETECT *pMatchInfoNetDetect);// ch:获取U3V相机的统计信息 | en:Get detect info of U3V cameraint 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// directoryint 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 directoryint 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// directoryint 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 directoryint 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// directoryint 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 CallBackint RegisterExceptionCallBack(void(__stdcall *cbException)(unsigned int nMsgType, void *pUser),void *pUser);// ch:注册单个事件回调 | en:Register Event CallBackint RegisterEventCallBack(const char *pEventName,void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser),void *pUser);// ch:强制IP | en:Force IPint ForceIp(unsigned int nIP, unsigned int nSubNetMask,unsigned int nDefaultGateWay);// ch:配置IP方式 | en:IP configuration methodint SetIpConfig(unsigned int nType);// ch:设置网络传输模式 | en:Set Net Transfer Modeint SetNetTransMode(unsigned int nType);// ch:像素格式转换 | en:Pixel format conversionint ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM *pstCvtParam);// ch:保存图片 | en:save imageint SaveImage(MV_SAVE_IMAGE_PARAM_EX *pstParam);// ch:保存图片为文件 | en:Save the image as a fileint SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM *pstParam);//设置是否为触发模式int setTriggerMode(unsigned int TriggerModeNum);//设置触发源int setTriggerSource(unsigned int TriggerSourceNum);//软触发int softTrigger();//读取bufferint ReadBuffer(cv::Mat &image);//设置曝光时间int setExposureTime(float ExposureTimeNum);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 // MVCAMERA_H

2.3 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_OBJECTpublic: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

2.4 widget.h

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QMessageBox>#include <QCloseEvent>#include <QSettings>#include "MvCamera.h"#include "mythread.h"#define MAX_DEVICE_NUM2#define TRIGGER_SOURCE7#define EXPOSURE_TIME40000#define FRAME 30#define TRIGGER_ON 1#define TRIGGER_OFF 0#define START_GRABBING_ON 1#define START_GRABBING_OFF 0#define IMAGE_NAME_LEN64QT_BEGIN_NAMESPACEnamespace Ui {class Widget;}QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();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;public:MyThread *myThread_Camera_show = NULL; //相机实时显示线程对象private slots:void on_pbn_enum_camera_clicked();void on_pbn_open_camera_clicked();void on_rdo_continue_mode_clicked();void on_rdo_softigger_mode_clicked();void on_pbn_start_grabbing_clicked();void on_pbn_stop_grabbing_clicked();void on_pbn_software_once_clicked();void display_myImage_L(const Mat *imagePrt, int cameraIndex);void on_pbn_close_camera_clicked();void on_pbn_save_BMP_clicked();void on_pbn_save_JPG_clicked();void on_le_set_exposure_textChanged(const QString &arg1);void on_le_set_gain_textChanged(const QString &arg1);public:// 状态bool m_bOpenDevice; // 是否打开设备bool m_bStartGrabbing;// 是否开始抓图int m_nTriggerMode; // 触发模式int m_bContinueStarted; // 开启过连续采集图像MV_SAVE_IAMGE_TYPE m_nSaveImageType; // 保存图像格式private:QString PrintDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo, int num_index);void OpenDevices();void CloseDevices();void SaveImage();private:Ui::Widget *ui;};#endif // WIDGET_H

2.5 main.cpp

#include "widget.h"#include <QApplication>int main(int argc, char *argv[]){QApplication a(argc, argv);Widget w;w.show();return a.exec();}

2.6 MvCamera.cpp

#include "MvCamera.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 Versionint CMvCamera::GetSDKVersion(){return MV_CC_GetSDKVersion();}// ch:枚举设备 | en:Enumerate Deviceint CMvCamera::EnumDevices(unsigned int nTLayerType,MV_CC_DEVICE_INFO_LIST *pstDevList){return MV_CC_EnumDevices(nTLayerType, pstDevList);}// ch:判断设备是否可达 | en:Is the device accessiblebool CMvCamera::IsDeviceAccessible(MV_CC_DEVICE_INFO *pstDevInfo,unsigned int nAccessMode){return MV_CC_IsDeviceAccessible(pstDevInfo, nAccessMode);}// ch:打开设备 | en:Open Deviceint 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 Deviceint 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 Connectedbool CMvCamera::IsDeviceConnected(){return MV_CC_IsDeviceConnected(m_hDevHandle);}// ch:注册图像数据回调 | en:Register Image Data CallBackint 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 Grabbingint CMvCamera::StartGrabbing(){return MV_CC_StartGrabbing(m_hDevHandle);}// ch:停止抓图 | en:Stop Grabbingint CMvCamera::StopGrabbing(){return MV_CC_StopGrabbing(m_hDevHandle);}// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint CMvCamera::GetImageBuffer(MV_FRAME_OUT *pFrame, int nMsec){return MV_CC_GetImageBuffer(m_hDevHandle, pFrame, nMsec);}// ch:释放图像缓存 | en:Free image bufferint CMvCamera::FreeImageBuffer(MV_FRAME_OUT *pFrame){return MV_CC_FreeImageBuffer(m_hDevHandle, pFrame);}// ch:主动获取一帧图像数据 | en:Get one frame initiativelyint 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 Handleint 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 SDKint CMvCamera::SetImageNodeNum(unsigned int nNum){return MV_CC_SetImageNodeNum(m_hDevHandle, nNum);}// ch:获取设备信息 | en:Get device informationint CMvCamera::GetDeviceInfo(MV_CC_DEVICE_INFO *pstDevInfo){return MV_CC_GetDeviceInfo(m_hDevHandle, pstDevInfo);}// ch:获取GEV相机的统计信息 | en:Get detect info of GEV cameraint 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 cameraint 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// directoryint 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// directoryint 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 directoryint 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// directoryint 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 directoryint 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// directoryint 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 CallBackint CMvCamera::RegisterExceptionCallBack(void(__stdcall *cbException)(unsigned int nMsgType, void *pUser),void *pUser){return MV_CC_RegisterExceptionCallBack(m_hDevHandle, cbException, pUser);}// ch:注册单个事件回调 | en:Register Event CallBackint 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 IPint 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 methodint CMvCamera::SetIpConfig(unsigned int nType){return MV_GIGE_SetIpConfig(m_hDevHandle, nType);}// ch:设置网络传输模式 | en:Set Net Transfer Modeint CMvCamera::SetNetTransMode(unsigned int nType){return MV_GIGE_SetNetTransMode(m_hDevHandle, nType);}// ch:像素格式转换 | en:Pixel format conversionint CMvCamera::ConvertPixelType(MV_CC_PIXEL_CONVERT_PARAM *pstCvtParam){return MV_CC_ConvertPixelType(m_hDevHandle, pstCvtParam);}// ch:保存图片 | en:save imageint 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:Onint 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:Softwareint 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 {//转换图像格式为BGR8MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0 };memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));stConvertParam.nWidth = stImageInfo.nWidth; // ch:图像宽 | en:image// widthstConvertParam.nHeight =stImageInfo.nHeight; // ch:图像高 | en:image height// stConvertParam.pSrcData = m_pBufForDriver; //ch:输入数据缓存 |// en:input data bufferstConvertParam.pSrcData =pDate; // ch:输入数据缓存 | en:input data bufferstConvertParam.nSrcDataLen =stImageInfo.nFrameLen; // ch:输入数据大小 | en:input data sizestConvertParam.enSrcPixelType =stImageInfo.enPixelType; // ch:输入像素格式 | en:input pixel formatstConvertParam.enDstPixelType =PixelType_Gvsp_BGR8_Packed; // ch:输出像素格式 | en:output pixel// format 适用于OPENCV的图像格式// stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed;//输出像素格式 | en:output pixel formatstConvertParam.pDstBuffer =m_pBufForSaveImage; // ch:输出数据缓存 | en:output data bufferstConvertParam.nDstBufferSize =m_nBufSizeForSaveImage; // ch:输出缓存大小 | en:output buffer sizeMV_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;}//设置曝光时间int CMvCamera::setExposureTime(float ExposureTimeNum){int tempValue =MV_CC_SetFloatValue(m_hDevHandle, "ExposureTime", ExposureTimeNum);if (tempValue != 0) {return -1;} else {return 0;}}

2.7 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::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); //发送信号lbl_camera_L接收并显示msleep(30);}}

2.8 widget.cpp

#include "widget.h"#include "./ui_widget.h"#include <stdio.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <fstream>#include <iostream>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);ui->lbl_camera_L->setPixmap(QPixmap("back_img.jpg"));ui->lbl_camera_L->setScaledContents(true);ui->lbl_camera_R->setPixmap(QPixmap("back_img.jpg"));ui->lbl_camera_R->setScaledContents(true);// 相机初始化控件ui->pbn_enum_camera->setEnabled(true);ui->pbn_open_camera->setEnabled(false);ui->pbn_close_camera->setEnabled(false);ui->cmb_camera_index->setEnabled(false);// 图像采集控件ui->rdo_continue_mode->setEnabled(false);ui->rdo_softigger_mode->setEnabled(false);ui->pbn_start_grabbing->setEnabled(false);ui->pbn_stop_grabbing->setEnabled(false);ui->pbn_software_once->setEnabled(false);// 参数控件ui->le_set_exposure->setEnabled(false);ui->le_set_gain->setEnabled(false);// 保存图像控件ui->pbn_save_BMP->setEnabled(false);ui->pbn_save_JPG->setEnabled(false);// 线程对象实例化myThread_Camera_show = new MyThread; //左相机线程对象// 初始化变量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_Camera_show, SIGNAL(Display(const Mat *, int)), this,SLOT(display_myImage_L(const Mat *, int)));// 曝光和增益的输入控件限制值QRegExp int_rx("100000|([0-9]{0,5})");ui->le_set_exposure->setValidator(new QRegExpValidator(int_rx, this));QRegExp double_rx("15|([0-9]{0,1}[0-5]{1,2}[\.][0-9]{0,1})");ui->le_set_gain->setValidator(new QRegExpValidator(double_rx, this));}Widget::~Widget(){delete ui;}void Widget::on_pbn_enum_camera_clicked(){memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));int nRet = MV_OK;nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &m_stDevList);devices_num = m_stDevList.nDeviceNum;if (devices_num == 0) {QString cameraInfo;cameraInfo =QString::fromLocal8Bit("暂无设备可连接,请检查设备是否连接正确!");ui->lbl_camera_messagee->setText(cameraInfo);}if (devices_num > 0) {QString cameraInfo;for (int i = 0; i < devices_num; i++) {MV_CC_DEVICE_INFO *pDeviceInfo = m_stDevList.pDeviceInfo[i];QString cameraInfo_i = PrintDeviceInfo(pDeviceInfo, i);cameraInfo.append(cameraInfo_i);cameraInfo.append("\n");ui->cmb_camera_index->addItem(QString::number(i));}ui->lbl_camera_messagee->setText(cameraInfo);ui->pbn_open_camera->setEnabled(true);ui->cmb_camera_index->setEnabled(true);}}QString Widget::PrintDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo, int num_index){QString cameraInfo_index;cameraInfo_index = QString::fromLocal8Bit("相机序号:");cameraInfo_index.append(QString::number(num_index));cameraInfo_index.append("\t\t");// 海康GIGE协议的相机if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE) {int nIp1 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >>24);int nIp2 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >>16);int nIp3 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >>8);int nIp4 =(pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);cameraInfo_index.append(QString::fromLocal8Bit("相机型号:"));std::string str_name =(char *)pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName;cameraInfo_index.append(QString::fromStdString(str_name));cameraInfo_index.append("\n");cameraInfo_index.append(QString::fromLocal8Bit("当前相机IP地址:"));cameraInfo_index.append(QString::number(nIp1));cameraInfo_index.append(".");cameraInfo_index.append(QString::number(nIp2));cameraInfo_index.append(".");cameraInfo_index.append(QString::number(nIp3));cameraInfo_index.append(".");cameraInfo_index.append(QString::number(nIp4));cameraInfo_index.append("\t");} else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE) {cameraInfo_index.append(QString::fromLocal8Bit("相机型号:"));std::string str_name =(char *)pstMVDevInfo->SpecialInfo.stUsb3VInfo.chModelName;cameraInfo_index.append(QString::fromStdString(str_name));cameraInfo_index.append("\n");} else {cameraInfo_index.append(QString::fromLocal8Bit("相机型号:未知"));}cameraInfo_index.append(QString::fromLocal8Bit("相机品牌:海康"));return cameraInfo_index;}void Widget::on_pbn_open_camera_clicked(){ui->pbn_open_camera->setEnabled(false);ui->pbn_close_camera->setEnabled(true);ui->rdo_continue_mode->setEnabled(true);ui->rdo_softigger_mode->setEnabled(true);ui->rdo_continue_mode->setCheckable(true);// 参数据控件ui->le_set_exposure->setEnabled(true);ui->le_set_gain->setEnabled(true);OpenDevices();}void Widget::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);//设置曝光时间,初始为40000,并关闭自动曝光模式m_pcMyCamera[i]->setExposureTime(EXPOSURE_TIME);m_pcMyCamera[i]->SetEnumValue("ExposureAuto",MV_EXPOSURE_AUTO_MODE_OFF);}}void Widget::on_rdo_continue_mode_clicked(){ui->pbn_start_grabbing->setEnabled(true);m_nTriggerMode = TRIGGER_ON;}void Widget::on_rdo_softigger_mode_clicked(){// 如果开始选择的连续模式,切换到触发模式之前,需要先停止采集if (m_bContinueStarted == 1) {on_pbn_stop_grabbing_clicked(); //先执行停止采集}ui->pbn_start_grabbing->setEnabled(false);ui->pbn_software_once->setEnabled(true);m_nTriggerMode = TRIGGER_OFF;for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {m_pcMyCamera[i]->setTriggerMode(m_nTriggerMode);}}void Widget::on_pbn_start_grabbing_clicked(){// 触发模式标记一下,切换触发模式时先执行停止采集图像函数m_bContinueStarted = 1;// 图像采集控件ui->pbn_start_grabbing->setEnabled(false);ui->pbn_stop_grabbing->setEnabled(true);// 保存图像控件ui->pbn_save_BMP->setEnabled(true);ui->pbn_save_JPG->setEnabled(true);int camera_Index = 0;// 先判断什么模式,再判断是否正在采集if (m_nTriggerMode == TRIGGER_ON) {// 开始采集之后才创建workthread线程for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {//开启相机采集m_pcMyCamera[i]->StartGrabbing();camera_Index = i;if (camera_Index == 0) {myThread_Camera_show->getCameraPtr(m_pcMyCamera[0]); //线程获取左相机指针myThread_Camera_show->getImagePtr(myImage_L); //线程获取左图像指针myThread_Camera_show->getCameraIndex(0); //左相机 Index==0if (!myThread_Camera_show->isRunning()) {myThread_Camera_show->start();m_pcMyCamera[0]->softTrigger();m_pcMyCamera[0]->ReadBuffer(*myImage_L); //读取Mat格式的图像}}}}}void Widget::on_pbn_stop_grabbing_clicked(){ui->pbn_start_grabbing->setEnabled(true);ui->pbn_stop_grabbing->setEnabled(false);for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {//关闭相机if (myThread_Camera_show->isRunning()) {m_pcMyCamera[0]->StopGrabbing();myThread_Camera_show->requestInterruption();myThread_Camera_show->wait();}}}void Widget::on_pbn_software_once_clicked(){// 保存图像控件ui->pbn_save_BMP->setEnabled(true);ui->pbn_save_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); //左相机图像}}}}void Widget::display_myImage_L(const Mat *imagePrt, int cameraIndex){cv::Mat rgb;cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);QImage QmyImage_L;QmyImage_L = QImage((const unsigned char *)(rgb.data), rgb.cols,rgb.rows, QImage::Format_RGB888);QmyImage_L = (QmyImage_L).scaled(ui->lbl_camera_L->size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation); //饱满填充//显示图像ui->lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L));}void Widget::CloseDevices(){for (unsigned int i = 0; i < m_stDevList.nDeviceNum; i++) {// 关闭线程、相机if (myThread_Camera_show->isRunning()) {myThread_Camera_show->requestInterruption();myThread_Camera_show->wait();m_pcMyCamera[0]->StopGrabbing();}m_pcMyCamera[i]->Close();}// 关闭之后再枚举一遍memset(&m_stDevList, 0,sizeof(MV_CC_DEVICE_INFO_LIST)); // 初始化设备信息列表int devices_num = MV_OK;devices_num =CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE,&m_stDevList); // 枚举子网内所有设备,相机设备数量}void Widget::on_pbn_close_camera_clicked(){ui->pbn_open_camera->setEnabled(true);ui->pbn_close_camera->setEnabled(false);// 图像采集控件ui->rdo_continue_mode->setEnabled(false);ui->rdo_softigger_mode->setEnabled(false);ui->pbn_start_grabbing->setEnabled(false);ui->pbn_stop_grabbing->setEnabled(false);ui->pbn_software_once->setEnabled(false);// 参数控件ui->le_set_exposure->setEnabled(false);ui->le_set_gain->setEnabled(false);// 保存图像控件ui->pbn_save_BMP->setEnabled(false);ui->pbn_save_JPG->setEnabled(false);// 关闭设备,销毁线程CloseDevices();ui->lbl_camera_messagee->clear();ui->lbl_camera_L->clear();ui->lbl_camera_R->clear();}void Widget::on_pbn_save_BMP_clicked(){m_nSaveImageType = MV_Image_Bmp;SaveImage();}void Widget::on_pbn_save_JPG_clicked(){m_nSaveImageType = MV_Image_Jpeg;SaveImage();}void Widget::SaveImage(){// 获取1张图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++) {// 仅在第一次保存图像时申请缓存,在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) {// 仅在第一次保存图像时申请缓存,在 CloseDevice 时释放if (NULL == m_pcMyCamera[i]->m_pBufForSaveImage) {// BMP图片大小:width * height * 3 + 2048(预留BMP头大小)m_pcMyCamera[i]->m_nBufSizeForSaveImage =stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;m_pcMyCamera[i]->m_pBufForSaveImage = (unsigned char *)malloc(m_pcMyCamera[i]->m_nBufSizeForSaveImage);}// 设置对应的相机参数MV_SAVE_IMAGE_PARAM_EX stParam = {0 };stParam.enImageType = m_nSaveImageType; // 需要保存的图像类型stParam.enPixelType = stImageInfo.enPixelType; // 相机对应的像素格式stParam.nBufferSize =m_pcMyCamera[i]->m_nBufSizeForSaveImage; // 存储节点的大小stParam.nWidth = stImageInfo.nWidth; // 相机对应的宽stParam.nHeight = stImageInfo.nHeight; // 相机对应的高stParam.nDataLen = stImageInfo.nFrameLen;stParam.pData = m_pcMyCamera[i]->m_pBufForDriver;stParam.pImageBuffer = m_pcMyCamera[i]->m_pBufForSaveImage;stParam.nJpgQuality = 90; // jpg编码,仅在保存Jpg图像时有效nRet = m_pcMyCamera[i]->SaveImage(&stParam);QString image_name;char chImageName[IMAGE_NAME_LEN] = {0 };if (MV_Image_Bmp == stParam.enImageType) {if (i == 0) {snprintf(chImageName, IMAGE_NAME_LEN,"Image_w%d_h%d_fn%d_L.bmp", stImageInfo.nWidth,stImageInfo.nHeight, stImageInfo.nFrameNum);image_name = "Image_w";image_name.append(QString::number(stImageInfo.nWidth));image_name.append("_h");image_name.append(QString::number(stImageInfo.nHeight));image_name.append("_fn");image_name.append(QString::number(stImageInfo.nFrameNum));image_name.append("_L.bmp");}if (i == 1) {snprintf(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) {snprintf(chImageName, IMAGE_NAME_LEN,"Image_w%d_h%d_fn%d_L.jpg", stImageInfo.nWidth,stImageInfo.nHeight, stImageInfo.nFrameNum);image_name = "Image_w";image_name.append(QString::number(stImageInfo.nWidth));image_name.append("_h");image_name.append(QString::number(stImageInfo.nHeight));image_name.append("_fn");image_name.append(QString::number(stImageInfo.nFrameNum));image_name.append("_L.jpg");}if (i == 1) {snprintf(chImageName, IMAGE_NAME_LEN,"Image_w%d_h%d_fn%03d_R.jpg", stImageInfo.nWidth,stImageInfo.nHeight, stImageInfo.nFrameNum);}}FILE *fp = fopen(chImageName, "wb");fwrite(m_pcMyCamera[i]->m_pBufForSaveImage, 1, stParam.nImageLen,fp);fclose(fp);ui->lbl_camera_R->setPixmap(QPixmap(image_name));ui->lbl_camera_R->setScaledContents(true);}}}void Widget::on_le_set_exposure_textChanged(const QString &arg1){//设置曝光时间QString str = ui->le_set_exposure->text(); // 读取int exposure_Time = str.toInt();for (int i = 0; i < devices_num; i++) {m_pcMyCamera[i]->SetEnumValue("ExposureAuto",MV_EXPOSURE_AUTO_MODE_OFF);m_pcMyCamera[i]->SetFloatValue("ExposureTime", exposure_Time);}}void Widget::on_le_set_gain_textChanged(const QString &arg1){QString str = ui->le_set_gain->text(); // 读取float gain = str.toFloat();for (int i = 0; i < devices_num; i++) {m_pcMyCamera[i]->SetEnumValue("GainAuto", 0);int nRet = m_pcMyCamera[i]->SetFloatValue("Gain", gain);}}

2.9 widget.ui

2.10 运行效果

参考:

海康Camera MVS Linux SDK二次开发封装ROS packge过程记录(c++):

/weixin_41965898/article/details/116801491

linux下qt封装海康SDK(这个是安防相机的,up主提供了qt的源码):/video/BV1u64y1o76T?spm_id_from=333.1007.top_right_bar_window_history.content.click

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。