作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

开发环境

操作系统:Windows 10 1903 18362.778
相机型号:IMAGING SOURCE DMK 33G274
相机软件:ic_setup_3.4.0.2744,gigecam_setup_3.7.1.4512
软件版本:Qt 5.12.8, vs2017 Community
通信方式:GigE - 千兆以太网通信协议

驱动与SDK

开发包和驱动下载地址
提取码:34mt

安装驱动和开发包完成之后,可以找到以下2个目录:

  1. C:\ProgramData\Microsoft\Windows\Start Menu\Programs\IC Imaging Control 3.4
  • 1 - 开发文档;
  • 2 - 示例程序源代码;
  • 其他 - 可运行的示例程序;
  1. C:\Users\60455\Documents\IC Imaging Control 3.4
  • classlib - 程序开发的头文件和库文件;
  • redist - 发行包;
  • samples - 程序源代码(和刚才目录下的源代码是相同的);

映美精相机介绍

映美精相机实时显示图像比较简单,因为SDK中提供了封装好的函数可以直接调用,如下所示:
bool startLive( bool show_videowindow = true );
show_videowindow 设置为true就是启用实时视频窗口,设置为false仅用于图片抓取
我们只需要提供一个窗口的句柄就可以实时显示图像了。

这里先介绍一个叫 FrameHandlerSink 的东西,这是设计采集图像的模式,一共有两种模式:

  1. snap采图模式
    在snap模式下,到达接收器的所有帧都显示给 IFrameFilter,然后复制到 MemBufferCollection 中。之后调用 GrabberListener 的 frameReady 事件;
  2. grab采集模式
    在grab模式下,所有帧都呈现给 IFrameFilter。如果没有挂起任何快照作业,则 IFrameFilter::transform 中的目标帧为0,并且不会调用 frameReady 事件。
    当快照作业挂起时,会在 MemBuffer 中传递缓冲区,当 IFrameFilter::transform 返回true时,MemBuffer 将在 GrabberListener 中的 frameReady 事件中显示;

我们主要来看一下如何使用映美精相机来处理每一帧的数据,映美精相机处理每一帧数据有以下两种方法:

  1. 继承 DShowLib::GrabberListener 类,重新实现 frameReady 这个函数。frameReady 函数就是用来处理图像的,每当相机内存中有图片时,相机就会调用 GrabberListener 中的 frameReady 函数;
  2. 自己通过定时器定时获取图片,可以使用 getLastAcqMemBuffer() 函数获取最新的图片数据;

方法一步骤如下:

  • 添加新的侦听器对象
    m_Grabber.addListener( this, GrabberListener::eALL );

  • 设置采集模式
    m_Sink->setSnapMode( true ); // true为snap采图模式,false为grab采集模式

  • 重写 frameReady 函数
    virtual void frameReady(Grabber &caller, smart_ptr<MemBuffer> pBuffer, DWORD FrameNumber) override;

  • 调用 startLive 开启实时模式
    m_Grabber.startLive(true);

  • 调用 snapImages 抓取图片
    m_Sink->snapImages( 1, 2000 ); // 抓取一张图片,每次调用 snapImages() 之后,就会触发 Listener 中的 frameReady()

我的代码(博主使用的是方法二)

实现功能:相机图像的实时显示,并且可以在需要的时候获取当前帧数据,用于分析或者保存

首先需要在pro中配置头文件和库文件

CONFIG += debug_and_releaseINCLUDEPATH += $$PWD/classlib/include/windows {CONFIG(debug, debug|release) {CONFIG += consolecontains(DEFINES, WIN64) {LIBS += -L$$PWD/classlib/x64/debug/ -lTIS_UDSHL11d_x64} else {LIBS += -L$$PWD/classlib/win32/debug/ -lTIS_UDSHL11d_x64}} else {contains(DEFINES, WIN64) {LIBS += -L$$PWD/classlib/x64/release/ -lTIS_UDSHL11d_x64} else {LIBS += -L$$PWD/classlib/win32/release/ -lTIS_UDSHL11d_x64}}
}

自定义相机基类 Camera

#ifndef CAMERA_H
#define CAMERA_H#include <QObject>
#include <QImage>
#include <QTimer>
#include <QMutex>#include <opencv2/opencv.hpp>class Camera : public QObject
{Q_OBJECTpublic:enum CameraType {Basler = 1,                     // 巴斯勒相机IC_Imaging,                     // 映美精相机MV,                             // 海康威视相机Virtual                         // 虚拟相机};explicit Camera(CameraType type = Basler) : m_type(type) {}virtual void initCamera() = 0;      // 初始化相机virtual void destroyCamera() = 0;   // 销毁相机virtual void openCamera() = 0;      // 打开相机virtual void closeCamera() = 0;     // 关闭相机virtual void startWork() = 0;       // 开始工作virtual void stopWork() = 0;        // 停止工作virtual cv::Mat takeAPic() = 0;     // 获取当前图像void start() { m_timer.start(); }void stop() { m_timer.stop(); }void setInterval(int time) { m_timer.setInterval(time); }CameraType getCameraType() { return m_type; }signals:void updateImage(QImage image);protected:CameraType m_type;QMutex m_mutex;QTimer m_timer;
};#endif // CAMERA_H

自定义 BICCameraControl 相机控制类

#ifndef BICCAMERACONTROL_H
#define BICCAMERACONTROL_H#include "../camera.h"
#include <tisudshl.h>
#include "Grabber.h"
using namespace _DSHOWLIB_NAMESPACE;#define NUM_BUFFERS 10class BICCameraControl : public Camera
{Q_OBJECT
public:explicit BICCameraControl(Camera::CameraType type = Camera::CameraType::IC_Imaging);virtual void initCamera() override;virtual void destroyCamera() override;virtual void openCamera() override;virtual void closeCamera() override;virtual void startWork() override;virtual void stopWork() override;virtual cv::Mat takeAPic() override;void showDialog();double getExposure();public slots:void updateFrame();protected:DShowLib::Grabber m_Grabber;DShowLib::FrameHandlerSink::tFHSPtr m_Sink;
};#endif // BICCAMERACONTROL_H
#include "biccameracontrol.h"
#include "globalfun.h"BICCameraControl::BICCameraControl(Camera::CameraType type) : Camera(type)
{try {DShowLib::InitLibrary();atexit(DShowLib::ExitLibrary);} catch (DShowLib::Error &e) {qDebug() << "InitLibrary error: " + QString::fromStdString(e.toString());}m_timer.setInterval(GlobalValue::cam_itl);connect(&m_timer, &QTimer::timeout, this, &BICCameraControl::updateFrame);
}void BICCameraControl::initCamera()
{try {m_Sink = DShowLib::FrameHandlerSink::create( FrameTypeInfoArray::createRGBArray(), NUM_BUFFERS );m_Sink->setSnapMode( true );// Apply the sink to the grabber.m_Grabber.setSinkType( m_Sink );} catch (DShowLib::Error &e) {qDebug() << "initCamera error: " + QString::fromStdString(e.toString());}
}void BICCameraControl::destroyCamera()
{try {stopWork();closeCamera();} catch (DShowLib::Error &e) {qDebug() << "destroyCamera error: " + QString::fromStdString(e.toString());}
}void BICCameraControl::openCamera()
{// Check if a device is open.if ( m_Grabber.isDevOpen() ) {return;}if (m_Grabber.getAvailableVideoCaptureDevices()->size() == 0) {return;}try {Grabber::tVidCapDevListPtr pVidCapDevList = m_Grabber.getAvailableVideoCaptureDevices();if( pVidCapDevList == 0 || pVidCapDevList->empty() ){qDebug() << "No device available !";return;}// Open camera from serial number. The device does not work when using USB connection in this way.
//        __int64 num;
//        pVidCapDevList->at(0).getSerialNumber(num);
//        m_Grabber.openDev(num);// Open camera from device name.std::string deviceName = pVidCapDevList->at(0).getName();m_Grabber.openDev(deviceName);m_Grabber.setVideoFormat(dstringa(GlobalValue::cam_fmt.toLatin1().data()));m_Grabber.setFPS(GlobalValue::cam_fps);} catch (DShowLib::Error &e) {qDebug() << "openCamera error: " + QString::fromStdString(e.toString());}
}void BICCameraControl::closeCamera()
{// Check if a device is open.if ( !m_Grabber.isDevOpen() ) {return;}try {// Closes the currently active video capture device.m_Grabber.closeDev();} catch (DShowLib::Error &e) {qDebug() << "closeCamera error: " + QString::fromStdString(e.toString());}
}void BICCameraControl::startWork()
{// Check if live mode is on.if ( m_Grabber.isLive() ) {return;}// Check if there is a valid device.if ( !m_Grabber.isDevValid() ) {return;}try {// Start the live video. Set true to enable the live video window, false to grab only.m_Grabber.startLive(false);m_timer.start();} catch (DShowLib::Error &e) {qDebug() << "startWork error: " + QString::fromStdString(e.toString());}
}void BICCameraControl::stopWork()
{// Check if live mode is on.if ( !m_Grabber.isLive() ) {return;}try {// Stop live mode.m_Grabber.stopLive();m_timer.stop();} catch (DShowLib::Error &e) {qDebug() << "stopWork error: " + QString::fromStdString(e.toString());}
}cv::Mat BICCameraControl::takeAPic()
{// Check if live mode is on.if ( !m_Grabber.isLive() ) {return cv::Mat();}QMutexLocker locker(&m_mutex);try {m_Sink->snapImages( 1, 1000 );smart_ptr<MemBuffer> pBuffer = m_Sink->getLastAcqMemBuffer();QImage image(static_cast< uchar* >( pBuffer->getPtr() ),int( pBuffer->getSize().cx ),int( pBuffer->getSize().cy ),QImage::Format_RGB32);QImage retImage = image.mirrored(false, true);cv::Mat mat = GlobalFun::convertQImageToMat(retImage);return mat.clone();} catch (DShowLib::Error &e) {qDebug() << "takeAPic error: " + QString::fromStdString(e.toString());return cv::Mat();}
}void BICCameraControl::showDialog()
{if ( m_Grabber.isDevOpen() && m_Grabber.isLive() ) {m_Grabber.stopLive();m_timer.stop();std::thread th([=](){ m_Grabber.showDevicePage(); });th.join();GlobalValue::cam_fps = m_Grabber.getFPS();GlobalValue::cam_fmt = QString::fromStdString(m_Grabber.getVideoFormat().toString());qDebug() << "FPS: " + QString::number(GlobalValue::cam_fps);qDebug() << "Format: " + GlobalValue::cam_fmt;m_Grabber.startLive(false);m_timer.start();m_Grabber.showVCDPropertyPage();GlobalValue::cam_exp = getExposure() * 1000;qDebug() << "Exposure: " + QString::number(GlobalValue::cam_exp);}
}double BICCameraControl::getExposure() {tIVCDPropertyItemsPtr pItems = m_Grabber.getAvailableVCDProperties();if( pItems != 0 ){tIVCDPropertyItemPtr pExposureItem = pItems->findItem( VCDID_Exposure );tIVCDPropertyElementPtr pExposureValueElement = pExposureItem->findElement( VCDElement_Value );tIVCDAbsoluteValuePropertyPtr m_pExposureAbsoluteValue;if( pExposureValueElement != 0 ){pExposureValueElement->getInterfacePtr( m_pExposureAbsoluteValue );}if( m_pExposureAbsoluteValue != 0 ){return m_pExposureAbsoluteValue->getValue();}}return 0.033;
}void BICCameraControl::updateFrame()
{QMutexLocker locker(&m_mutex);try {m_Sink->snapImages( 1, 1000 );smart_ptr<MemBuffer> pBuffer = m_Sink->getLastAcqMemBuffer();QImage image(static_cast< uchar* >( pBuffer->getPtr() ),int( pBuffer->getSize().cx ),int( pBuffer->getSize().cy ),QImage::Format_RGB32);emit updateImage(image.mirrored(false, true));} catch (DShowLib::Error &e) {qDebug() << "updateFrame error: " + QString::fromStdString(e.toString());}
}

其他请参考

  • Qt调用工业相机之巴斯勒相机
  • Qt调用工业相机之海康威视相机

Qt调用工业相机之映美精相机相关推荐

  1. Qt调用MATLAB

    Qt调用MATLAB 生成的dll经验分享 由于项目需要将生成的数据转成C3D运动捕捉格式,目前无C++转换算法,有MATLAB算法,考虑到C++重新码算法的时间,选择了将MATLAB算法直接转成C+ ...

  2. QT调用C#写的Dll

    QT调用C#写的Dll 参见: https://blog.csdn.net/weixin_42420155/article/details/81060945 C#写的dll是没有dllMain入口函数 ...

  3. Qt调用word 例子

    Qt调用word 例子 Getting Microsoft Word Object to SaveAs #include <QtGui> #include <QAxObject> ...

  4. linux python qt 安装目录,Linux 下QT调用Python库文件 以及Linux 安装Python3.8开发环境 问题...

    最近想运用linux系统下Qt来实现c++ 与python的混合编程,linux系统会自带python2.7版本或者python3.5版本(深度linux). Qt调用python文件需要在pro文件 ...

  5. QT调用C++写的Dll

    C#写的dll是没有dllMain入口函数的,是一种中间语言,需要.Net运行时进行做本地化工作,因此如果要调用C#写的dll,需要依赖.Net运行时,然而Qt中还无法直接调用.Net运行时,最好的方 ...

  6. QT 调用 DLL 的三种方法

    Qt调用DLL方法一:使用Win32 API h文件 typedef bool (CALLBACK* SetKeyBoardHook)(HWND); HINSTANCE hDLL; // Handle ...

  7. Qt 调用MATLAB引擎混合编程

    0.前言 C/C++调用MATLAB有三个方式:调用dll文件.调用exe可执行程序和调用Engin引擎. 第一种方式利用MATLAB Coder 将MATLAB代码生成C/C++代码和相关动态链接库 ...

  8. Qt 调用Python引擎混合编程

    0.前言 使用Qt和Python做混合编程,充分发挥Qt GUI的图形化框架优势和Python数据处理的计算能力.复杂的计算可用到Python众多三方库,将Python需要执行的功能写成py文件,做成 ...

  9. qt调用mysql调用了存储过_Qt调用Server SQL中的存储过程

    Server SQL中的存储过程如下: CREATE procedure PINSERTPC @pcnum int, @pcname varchar(50), @pctype int, @ipaddr ...

  10. win10环境下VTK7.1的编译和Qt调用VTK的详细教程二(VS2013编译支持Qt的VTK库)

    本文主要用于编译支持Qt的VTK库,重点在于编译VTK库,供Qt调用. 第1步:新建一个文件夹:vtkDir 第2步:在该文件夹下新建两个文件夹vtk_bin.vtk_src 第3步:将下载好的VTK ...

最新文章

  1. 迅雷“星域”打通最后一公里重新定义CDN
  2. 《直播疑难杂症排查》之三:首开慢
  3. 数据结构与算法(二):堆,大根堆,小根堆,堆排序,比较器详解
  4. Hyper-V Server共享VHDX
  5. VS2015新建C++工程时,Object reference not set to an instance of an object
  6. linux中ssh启动报错,Linux(Ubuntu18)中启动ssh时的报错
  7. linux修改可用的最大进程数量和可打开的最大文件数
  8. 终于找到中文版JDK1.8-API了~
  9. 2.4 Python 模块的使用安装导入
  10. java监听键盘事件(控制台输出按键信息)
  11. linux内核驱动摄像头图片,详解linux 摄像头驱动编写
  12. 考研二战日记——第二天 高数第一章第二节:数列的极限
  13. 如何将密切好友的微信聊天记录恢复到自己的微信中
  14. break 和continue 区别以及用法。
  15. 公网ip和域名是干嘛的?域名由谁管理的?
  16. 【手写源码-设计模式11】-享元模式-基于打麻将场景
  17. 雷哥爱财,取之有道:4个月取了4000块
  18. nwjs自动更新 node-webkit-updater
  19. 二十五、Flink + Uber AthenaX 平台化实践
  20. 空洞卷积dilated conv

热门文章

  1. 会计新规给保险业带来的影响
  2. U盘修复,U盘量产教程(以台电晶彩NCU,容量为32G的U盘为实例)by aser
  3. PHP课程设计《PHP网上购物系统的设计与实现》
  4. ruby 之watir
  5. java char类型 unicode字符集 utf-8字符编码
  6. vue省市区遍历数据
  7. C语言新手入门成长帖(1)
  8. linux数据库安装
  9. ElasticJob‐Lite:作业监听器
  10. 切换IP软件,切换电脑手机IP如此简单