系列文章目錄
第一章 Ubuntu22下OpenCV4.6.0+contrib模塊編譯安裝
第二章 ubuntu22下C++ kdevelop環(huán)境搭建:OpenCV示例
第三章 C++下OPENCV驅(qū)動(dòng)調(diào)用??礕igE工業(yè)相機(jī)
前言
在前兩章內(nèi)筆者詳細(xì)敘述了如何編譯以及加載opencv庫(kù),本文將從opencv出發(fā),在linux系統(tǒng)下利用??倒I(yè)攝像機(jī)的SDK完成基于??倒I(yè)相機(jī)的opencv開(kāi)發(fā)算法。
包含:
1.??倒I(yè)相機(jī)的驅(qū)動(dòng);
2.工業(yè)相機(jī)的幀格式轉(zhuǎn)換;
本文代碼庫(kù):https://gitee.com/C-Qiyao/gig-e_camera
一、??倒I(yè)相機(jī)
一切緣起筆者在實(shí)驗(yàn)室翻箱倒柜喜提一個(gè)師兄購(gòu)買(mǎi)的海康工業(yè) 相機(jī),遂對(duì)其進(jìn)行詳細(xì)了解,發(fā)現(xiàn)功能性相比普通攝像頭強(qiáng)不少。
產(chǎn)品頁(yè)面
筆者使用的??倒I(yè)相機(jī)的型號(hào)為MV-CE013-50GC,采用rj45的網(wǎng)線(xiàn)接口來(lái)輸出視頻數(shù)據(jù),并不會(huì)在系統(tǒng)設(shè)備上掛載video設(shè)備,所以需要調(diào)用??档尿?qū)動(dòng)來(lái)完成視頻幀的獲取。
二、MVS軟件安裝 攝像頭連接
MVS軟件是為支持海康機(jī)器視覺(jué)相機(jī)產(chǎn)品而開(kāi)發(fā)的軟件應(yīng)用程序,適用于所有??禉C(jī)器視覺(jué)面陣以及線(xiàn)陣相機(jī)產(chǎn)品。MVS內(nèi)我們主要配置攝像頭以及利用他的SDK進(jìn)行開(kāi)發(fā)。
1.安裝MVS
前往HIKROBOT網(wǎng)站下載對(duì)應(yīng)系統(tǒng)的MVS安裝包
在此筆者使用的是linux系統(tǒng)所以選擇linux系統(tǒng)的安裝包進(jìn)行下載
打開(kāi)下載得到的壓縮包,內(nèi)容如下:
我們使用的計(jì)算機(jī)為64位的X86架構(gòu),所以在此我們將后綴為x86_64的安裝包解壓出來(lái),筆者使用的是Debian系的ubuntu操作系統(tǒng),所以在此解壓對(duì)應(yīng)deb安裝包。
使用終端或者軟件安裝器安裝該deb包
安裝完成之后,讀者可能會(huì)發(fā)現(xiàn)并沒(méi)有在菜單內(nèi)找到MVS軟件的圖標(biāo),但是我們可以在/opt路徑下找到MVS的文件夾
qiyao@qiyao-Legion-Y9000X-IAH7:/opt$ ls
apps durapps ffmpeg-4.3.tar.gz nvidia zTools
clion deepin-wine6-stable ffmpeg MVS qqmusic
進(jìn)入MVS文件夾,啟動(dòng)MVS軟件
$ cd /opt/MVS/bin
$ ./MVS
成功打開(kāi)MVS界面
2.連接配置攝像頭
筆者使用的海康攝像頭采用rj45接口,查閱手冊(cè)得知需要使用千兆以太網(wǎng)標(biāo)準(zhǔn)進(jìn)行連接
設(shè)置網(wǎng)卡IP 修改有線(xiàn)網(wǎng)卡ipv4參數(shù)為以下內(nèi)容:
IP: 192.168.16.68
網(wǎng)關(guān): 192.168.16.1
DNS: 202.96.128.166
MTU: 9000
重啟MVS軟件,在設(shè)備列表里選中我們的網(wǎng)絡(luò)攝像機(jī),右鍵修改IP(在ip段內(nèi)隨意設(shè)置)
雙擊選中我們的相機(jī),開(kāi)啟相機(jī)采集
至此,相機(jī)和計(jì)算機(jī)之間的連接以及完成,接下來(lái)就需要進(jìn)行SDK的開(kāi)發(fā)了,同時(shí)我們?cè)诋?huà)面下部的帶寬部分也可以發(fā)現(xiàn),該相機(jī)的數(shù)據(jù)流巨大,確實(shí)需要依賴(lài)千兆網(wǎng)絡(luò)的支撐。
三、基于SDK的攝像頭C++開(kāi)發(fā)
1.拷貝SDK
筆者比較習(xí)慣kdevelop的開(kāi)發(fā),當(dāng)然也建議讀者選擇自己鐘意的IDE進(jìn)行軟件的開(kāi)發(fā),畢竟代碼才是核心,工具次之,對(duì)于狠人用文本編輯器也未嘗不可。
拷貝/opt/MVS目錄下的 include和lib文件夾到我們的項(xiàng)目文件夾內(nèi),與main.cpp同級(jí)
2.編輯cmakelist
本次項(xiàng)目我們需要使用到??禂z像頭SDK以及opencv庫(kù),筆者在此提供自己的cmakelist
# cmake needs this line
cmake_minimum_required(VERSION 3.1)
set(PROJECT_NAME1 "camera_class_project")
# Define project name
#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_BUILD_TYPE "Release")
set(PROJ_DIR "/home/qiyao/codes/camera_class")
#s設(shè)置自己的項(xiàng)目文件夾目錄,用以定位文件夾下的include'和lib
project(${PROJECT_NAME1})
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV library status:")
message(STATUS " config: ${OpenCV_DIR}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
link_directories("${PROJ_DIR}/lib/64")
include_directories("${PROJ_DIR}/include" "/usr/include/X11" "/usr/include")
link_libraries("${PROJ_DIR}/lib/64/libMvCameraControl.so")
add_compile_options(-std=c++11)
add_executable(${PROJECT_NAME1} main.cpp)
add_library(camera_class SHARED camera_class.cpp)
#target_link_libraries(${PROJECT_NAME1} PUBLIC )
# Link your application with OpenCV libraries
target_link_libraries(${PROJECT_NAME1} ${OpenCV_LIBS} )
target_link_libraries(${PROJECT_NAME1} -lX11)
target_link_libraries(${PROJECT_NAME1} libMvCameraControl.so)
target_link_libraries(${PROJECT_NAME1} camera_class)
3.編輯相機(jī)class
筆者將自己對(duì)相機(jī)的操作編寫(xiě)成了一個(gè)class類(lèi),方便自己的調(diào)用,讀者可以進(jìn)行參考
camera_class.h
#ifndef CAMERA_CLASS_H_INCLUDED
#define CAMERA_CLASS_H_INCLUDED
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "MvCameraControl.h"
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/video/video.hpp>
using namespace std;
using namespace cv;
class camera{
private:
void* handle;
bool g_bExit;
int nRet;
unsigned int g_nPayloadSize;
unsigned char *pDataForRGB;
MV_CC_DEVICE_INFO* pDeviceInfo;
MV_CC_DEVICE_INFO_LIST stDeviceList;
MVCC_INTVALUE stParam;
MV_FRAME_OUT stOutFrame;
MV_CC_PIXEL_CONVERT_PARAM CvtParam;
public:
camera();
void PrintDeviceInfo();
void close_cam();
void start_cam();
void get_pic(Mat * srcimg);
void re_iso();
};
#endif // CAMERA_CLASS_H_INCLUDED
camera_class.cpp
#include "camera_class.h"
camera::camera()
{
nRet = MV_OK;
handle = NULL;
g_bExit = false;
g_nPayloadSize = 0;
pDataForRGB = (unsigned char*)malloc(1280 *960 * 4 + 2048);
memset(&stParam, 0, sizeof(MVCC_INTVALUE));
CvtParam={0};
stOutFrame = {0};
memset(&stOutFrame, 0, sizeof(MV_FRAME_OUT));
}
void camera::start_cam()
{
memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
if (stDeviceList.nDeviceNum > 0)
{
for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
{
pDeviceInfo = stDeviceList.pDeviceInfo[i];
if (NULL == pDeviceInfo)
{
break;
}
PrintDeviceInfo();
}
}else{
cout<<"Find no Device"<<endl;
}
unsigned int nIndex = 0;
MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
MV_CC_OpenDevice(handle);
if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
{
int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
if (nPacketSize > 0)
{
MV_CC_SetIntValue(handle,"GevSCPSPacketSize",nPacketSize);
}else{
cout<<"Warning: Get Packet Size fail"<<endl;
}
}
MVCC_ENUMVALUE p={0};
MVCC_STRINGVALUE st;
MV_CC_GetStringValue(handle,"DeviceModelName",&st);
cout<<"DeviceModelName: "<<st.chCurValue<<endl;
MV_CC_GetStringValue(handle,"DeviceVersion",&st);
cout<<"DeviceVersion:\t"<<st.chCurValue<<endl;
MV_CC_GetEnumValue(handle,"DeviceScanType",&p);
if(p.nCurValue==0)
{
cout<<"DeviceScanType:\t"<<"Areascan"<<endl;
}else{
cout<<"DeviceScanType:\t"<<"Linescan"<<endl;
}
MV_CC_SetEnumValue(handle, "TriggerMode", 0);
MV_CC_SetEnumValue(handle, "PixelFormat", 0x0210001F);
MV_CC_SetEnumValue(handle, "GainAuto", 1);
MV_CC_SetFloatValue(handle, "Gamma", 0.8);
MV_CC_SetBoolValue(handle, "GammaEnable", 1);
MV_CC_SetEnumValue(handle, "BalanceWhiteAuto", 2);
MV_CC_SetEnumValue(handle, "ExposureAuto", 1);
MV_CC_GetIntValue(handle, "PayloadSize", &stParam);
g_nPayloadSize = stParam.nCurValue;
nRet = MV_CC_StartGrabbing(handle);
if (MV_OK == nRet)
cout<<"Start Grabbing !"<<endl;
cout<<"\nPress ESC to exit.\n";
}
void camera::PrintDeviceInfo()
{
if (NULL == pDeviceInfo)
{
cout<<"null point"<<endl;
}
if (pDeviceInfo->nTLayerType == MV_GIGE_DEVICE)
{
int nIp1 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
int nIp2 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
int nIp3 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
int nIp4 = (pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);
cout<<"IP:"<<nIp1<<"."<<nIp2<<"."<<nIp3<<"."<<nIp4<<endl;
}
}
void camera::close_cam()
{
int nRet = MV_CC_StopGrabbing(handle);
if (MV_OK == nRet)
cout<<"Stopped Grabbing !"<<endl;
}
void camera::get_pic(cv::Mat* srcimg)
{
MV_CC_GetImageBuffer(handle, &stOutFrame, 400);
CvtParam.enSrcPixelType=stOutFrame.stFrameInfo.enPixelType;
CvtParam.enDstPixelType=PixelType_Gvsp_RGB8_Packed;
CvtParam.nHeight=stOutFrame.stFrameInfo.nHeight;
CvtParam.nWidth=stOutFrame.stFrameInfo.nWidth;
CvtParam.nDstBufferSize=stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 4 + 2048;
CvtParam.pSrcData=stOutFrame.pBufAddr;
CvtParam.pDstBuffer=pDataForRGB;
CvtParam.nSrcDataLen=stOutFrame.stFrameInfo.nFrameLen;
MV_CC_ConvertPixelType(handle,&CvtParam);
*srcimg=Mat(stOutFrame.stFrameInfo.nHeight,stOutFrame.stFrameInfo.nWidth,CV_8UC3,pDataForRGB);
cvtColor(*srcimg,*srcimg,COLOR_RGB2BGR);
if(NULL != stOutFrame.pBufAddr)
{
MV_CC_FreeImageBuffer(handle, &stOutFrame);
}
}
void camera::re_iso()
{
MV_CC_SetEnumValue(handle, "BalanceWhiteAuto", 2);
MV_CC_SetEnumValue(handle, "ExposureAuto", 1);
}
4.主函數(shù)調(diào)用
main.cpp
#include <stdio.h>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/video/video.hpp>
#include <opencv2/opencv.hpp>
#include "camera_class.h"
int main()
{
Mat img;
int key;
camera cam;
cam.start_cam();
while(1)
{
cam.get_pic(&img);
imshow("test",img);
key=waitKey(1);
if(key==27)
{
cam.close_cam();
break;
}
}
}
可謂非常的簡(jiǎn)潔優(yōu)雅
四、測(cè)試驗(yàn)證
構(gòu)建編譯測(cè)試工程
達(dá)到預(yù)期目標(biāo),成功驅(qū)動(dòng)攝像機(jī)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-455746.html
總結(jié)
以上就是今天要講的內(nèi)容,本文介紹了linux下??礕igE相機(jī)在opencv下的使用,同時(shí)在代碼類(lèi)里包括了相機(jī)參數(shù)調(diào)整和幀格式的轉(zhuǎn)換操作,筆者有空再進(jìn)行詳細(xì)地闡述。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-455746.html
到了這里,關(guān)于C++下OPENCV驅(qū)動(dòng)調(diào)用??礕igE工業(yè)相機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!