第一章 Ubuntu22下OpenCV4.6.0+contrib模块编译安装
第二章 ubuntu22下C++ kdevelop环境搭建:OpenCV示例
第三章 C++下OPENCV驱动调用海康GigE工业相机
文章目录
在前两章内笔者详细叙述了如何编译以及加载opencv库,本文将从opencv出发,在linux系统下利用海康工业摄像机的SDK完成基于海康工业相机的opencv开发算法。
包含:
1.海康工业相机的驱动;
2.工业相机的帧格式转换;
本文代码库:https://gitee.com/C-Qiyao/gig-e_camera
一切缘起笔者在实验室翻箱倒柜喜提一个师兄购买的海康工业 相机,遂对其进行详细了解,发现功能性相比普通摄像头强不少。
产品页面

笔者使用的海康工业相机的型号为MV-CE013-50GC,采用rj45的网线接口来输出视频数据,并不会在系统设备上挂载video设备,所以需要调用海康的驱动来完成视频帧的获取。
MVS软件是为支持海康机器视觉相机产品而开发的软件应用程序,适用于所有海康机器视觉面阵以及线阵相机产品。MVS内我们主要配置摄像头以及利用他的SDK进行开发。
前往HIKROBOT网站下载对应系统的MVS安装包
在此笔者使用的是linux系统所以选择linux系统的安装包进行下载

打开下载得到的压缩包,内容如下:
我们使用的计算机为64位的X86架构,所以在此我们将后缀为x86_64的安装包解压出来,笔者使用的是Debian系的ubuntu操作系统,所以在此解压对应deb安装包。
使用终端或者软件安装器安装该deb包
安装完成之后,读者可能会发现并没有在菜单内找到MVS软件的图标,但是我们可以在/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
进入MVS文件夹,启动MVS软件
$ cd /opt/MVS/bin
$ ./MVS
成功打开MVS界面

笔者使用的海康摄像头采用rj45接口,查阅手册得知需要使用千兆以太网标准进行连接

设置网卡IP 修改有线网卡ipv4参数为以下内容:
IP: 192.168.16.68
网关: 192.168.16.1
DNS: 202.96.128.166
MTU: 9000
重启MVS软件,在设备列表里选中我们的网络摄像机,右键修改IP(在ip段内随意设置)

双击选中我们的相机,开启相机采集

至此,相机和计算机之间的连接以及完成,接下来就需要进行SDK的开发了,同时我们在画面下部的带宽部分也可以发现,该相机的数据流巨大,确实需要依赖千兆网络的支撑。
笔者比较习惯kdevelop的开发,当然也建议读者选择自己钟意的IDE进行软件的开发,毕竟代码才是核心,工具次之,对于狠人用文本编辑器也未尝不可。
拷贝/opt/MVS目录下的 include和lib文件夹到我们的项目文件夹内,与main.cpp同级
本次项目我们需要使用到海康摄像头SDK以及opencv库,笔者在此提供自己的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设置自己的项目文件夹目录,用以定位文件夹下的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)
笔者将自己对相机的操作编写成了一个class类,方便自己的调用,读者可以进行参考
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);
}
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;
}
}
}
可谓非常的简洁优雅
构建编译测试工程
达到预期目标,成功驱动摄像机

以上就是今天要讲的内容,本文介绍了linux下海康GigE相机在opencv下的使用,同时在代码类里包括了相机参数调整和帧格式的转换操作,笔者有空再进行详细地阐述。
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年