-
關于在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.txt
- 2.2 MvCamera.h
- 2.3 mythread.h
- 2.4 widget.h
- 2.5 main.cpp
- 2.6 MvCamera.cpp
- 2.7 mythread.cpp
- 2.8 widget.cpp
- 2.9 widget.ui
- 2.10 運行效果
1.關于CMake編譯工具與專案構建
(由于之前一直都沒用過CMake對專案進行管理,特別感謝這篇文章,寫的不錯,)https://mp.weixin.qq.com/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的撰寫
這篇博文寫的很詳細:https://blog.csdn.net/afei__/article/details/81201039
??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.h,MvCameraControl.h,MvErrorDefine.h,PixelType.h這幾個檔案,以滿足專案的需求,
②關于彩色和黑白的疑問
- ??之前在Windows環境下開發用的是海康的彩色相機,這次在Linux環境下用的是海康的黑白相機,我直接移植了之前的代碼并配置了相關環境,發現在Qt中通過QLabel顯示的影像和相機實際拍到的不一樣(QLabel中顯示的影像很模糊),一開始以為是彩色和黑白的區別,但通過保存影像的按鈕發現保存的圖片沒什么問題,那就是QLabel的顯示問題了,
后來查了下QImage影像格式解讀:(我也沒看懂哪里是灰度影像的格式)https://blog.csdn.net/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設定區間
參考:https://blog.csdn.net/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.cppWindows下的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 SHARED
main.cpp
widget.cpp
MvCamera.cpp
mythread.cpp
mythread.h
MvCamera.h
widget.h
widget.ui
)
else()
add_executable(aubo_camera
main.cpp
widget.cpp
MvCamera.cpp
mythread.cpp
mythread.h
MvCamera.h
widget.h
widget.ui
)
endif()
find_library(CAMERA_LIB libMvCameraControl.so libMvCameraControl.so.3.1.3.0 /home/aubo/MVS-2.1.0_x86_64_20201228/MVS/lib/64/)
find_path(MVS_PATH CameraParams.h MvCameraControl.h MvErrorDefine.h PixelType.h /home/aubo/MVS-2.1.0_x86_64_20201228/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 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);
//設定曝光時間
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_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
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_NUM 2
#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
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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 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;
//輸出像素格式 | 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;
}
//設定曝光時間
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==0
if (!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++):
https://blog.csdn.net/weixin_41965898/article/details/116801491
linux下qt封裝海康SDK(這個是安防相機的,up主提供了qt的原始碼):https://www.bilibili.com/video/BV1u64y1o76T?spm_id_from=333.1007.top_right_bar_window_history.content.click
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/397523.html
標籤:其他
