一、 前言
本文初始目的为购买Matrox视频采集卡,用于采集Basker相机视频图像,接口为cameraLink。采集卡版本为ev-cl。系统环境为windows10系统,语言为C++,编译环境为QT Creater,厂家提供了VS2017下编译的程序,本文根据厂家提供的示例程序,改编为利用Mil库获取图像数据,由OpenCV库中Mat接收图像并进行格式转换,后将Mat转为QImage用于显示图像,达到Qt开发程序可以显示Matrox采集卡采集的视频图像。
二、 MIL SDK使用
如下图,Matrox软件安装好后再安装目录下可以看到以下文件,拷贝DLL、Include,Lib到项目目录下,并将此三个文件目录放到编译环境下,或者直接将此三个文件放到环境变量中。即可正常调用Mil的SDK。
(1)VS2017加入MIL SDK
点击项目->属性会弹出如下图所示,点击VC++目录,将include文件目录放入包含路径中,将Lib文件目录放入库目录中。
点击C/C++,将include文件目录,加入到附加包含目录中。
点击链接器,将Lib文件目录放到附加包含库目录中。
(2)Qt加入MIL SDK环境
打开项目后,点击左方项目选项卡。
选择所用的变异环境,点击Build。
找到构建环境,编辑环境,将Lib文件目录加到LIBPATH中,将Include文件目录加到INCLUDE中即可。
三、 VS2017显示采集卡获得的相机视频
本文为厂家提供的可实现显示相机视频的简单示例。
// HoleDEDlg.h : 头文件
//
#pragma once
/* 用户的处理功能钩住数据结构 */
typedef struct
{
MIL_ID MilDigitizer;
MIL_ID MilImageDisp;
MIL_INT ProcessedImageCount;
} HookDataStruct;
/* 线程参数结构 */
typedef struct ThreadParam
{
MIL_ID Id;
MIL_ID System;
MIL_ID OrgImage;
MIL_ID SrcImage;
MIL_ID DstImage;
MIL_ID ReadyEvent;
MIL_ID DoneEvent;
MIL_INT NumberOfIteration;
MIL_INT Radius;
MIL_INT Exit;
MIL_INT LicenseModules;
struct ThreadParam *SlaveThreadParam;
} THREAD_PARAM;
// CHoleDEDlg 对话框
class CHoleDEDlg : public CDialogEx
{
// 构造
public:
CHoleDEDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_HOLEDE_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
int m_I_state;
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedInit();
afx_msg void OnBnClickedStop();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
};
// HoleDEDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "HoleDE.h"
#include "HoleDEDlg.h"
#include "afxdialogex.h"
#include "Program.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//缓冲抓取队列中的图像数。
//通常,增加这个数字可以提供更好的实时抓取。
#define BUFFERING_SIZE_MAX 22
/* 用户的处理函数原型 */
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
/* 函数原型 */
//MIL_UINT32 MFTYPE TopThread(void *TPar);
MIL_UINT32 MFTYPE HandleThread(void *TPar);
//MIL_UINT32 MFTYPE BotRightThread(void *TPar);
void BalanceThreadScheduling();
/* 参数定义 */
MIL_ID MilApplication;
MIL_ID MilSystem;
MIL_ID MilDigitizer;
MIL_ID MilDisplay;
MIL_ID MilImageDisp;
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
MIL_INT MilGrabBufferListSize;
MIL_INT ProcessFrameCount = 0;
MIL_DOUBLE ProcessFrameRate = 0;
MIL_INT NbFrames = 0, n = 0;
HookDataStruct UserHookData;
//采集BUFFER
MIL_ID ModifiedBufferId;
//线程句柄
THREAD_PARAM Handle;
//表示位
MIL_BOOL CO = FALSE ;
//相机状态标识,0代表断开,1代表打开
int m_state = 0;
/* 获取的图像参数. */
MIL_INT BufSizeX;
MIL_INT BufSizeY;
MIL_INT BufSizeBand;
MIL_INT m = 1;
BYTE* m_AvsBuffer = NULL;
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CHoleDEDlg 对话框
CHoleDEDlg::CHoleDEDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CHoleDEDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CHoleDEDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CHoleDEDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_INIT, &CHoleDEDlg::OnBnClickedInit)
ON_BN_CLICKED(IDC_STOP, &CHoleDEDlg::OnBnClickedStop)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON1, &CHoleDEDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CHoleDEDlg::OnBnClickedButton2)
END_MESSAGE_MAP()
// CHoleDEDlg 消息处理程序
BOOL CHoleDEDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CHoleDEDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CHoleDEDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CHoleDEDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CHoleDEDlg::OnBnClickedInit()
{
OutputDebugString(L"初始化相机\r\n");
//手动分配 */
if (m_state == 0)
{
MappAlloc(M_DEFAULT, &MilApplication);
MsysAlloc(M_DEFAULT, M_SYSTEM_RADIENTEVCL, M_DEV0, M_DEFAULT, &MilSystem);
MdigAlloc(MilSystem, M_DEV0, MIL_TEXT("D:\\Basler.dcf"), M_DEFAULT, &MilDigitizer);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
m_state = 1;
/* 获取图像参数 */
MdigInquire(MilDigitizer, M_SIZE_X, &BufSizeX);
MdigInquire(MilDigitizer, M_SIZE_Y, &BufSizeY);
MdigInquire(MilDigitizer, M_SIZE_BAND, &BufSizeBand);
/* 分配显示的buffer */
MbufAllocColor(MilSystem, BufSizeBand, BufSizeX, BufSizeY, 8 + M_UNSIGNED,
(MilDigitizer ? M_IMAGE + M_DISP + M_GRAB /*+ M_ON_BOARD*/ + M_PROC : M_IMAGE + M_DISP + M_ON_BOARD),
&MilImageDisp);
m_AvsBuffer = new BYTE[BufSizeX * BufSizeY];
//线程分配//
/* 分配同步事件 */
MthrAlloc(MilSystem, M_EVENT, M_DEFAULT, M_NULL, M_NULL, &Handle.DoneEvent);
/* 初始化剩余的线程参数 */
Handle.System = MilSystem;
Handle.OrgImage = MilImageDisp;
Handle.NumberOfIteration = 0;
Handle.Radius = 0;
Handle.Exit = 0;
MdispSelectWindow(MilDisplay, MilImageDisp, GetDlgItem(IDC_DIS)->GetSafeHwnd());
MdispControl(MilDisplay, M_SCALE_DISPLAY, M_ENABLE);
/* 分配并清除抓取缓冲器。 */
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for (MilGrabBufferListSize = 0; MilGrabBufferListSize < BUFFERING_SIZE_MAX; MilGrabBufferListSize++)
{
MbufAlloc2d(MilSystem,
MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
8 + M_UNSIGNED,
M_IMAGE + M_GRAB + M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]);
if (MilGrabBufferList[MilGrabBufferListSize])
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
/* 释放缓冲区,为可能的临时缓冲区留出空间。 */
for (n = 0; n < 2 && MilGrabBufferListSize; n++)
{
MilGrabBufferListSize--;
MbufFree(MilGrabBufferList[MilGrabBufferListSize]);
}
//连续采集显示
//MdigGrabContinuous(MilDigitizer, MilImageDisp);
//停止连续采集显示
//MdigHalt(MilDigitizer);
/* 初始化用户的处理函数数据结构. */
UserHookData.MilDigitizer = MilDigitizer;
UserHookData.MilImageDisp = MilImageDisp;
UserHookData.ProcessedImageCount = 0;
//开启线程//
MthrAlloc(MilSystem, M_THREAD, M_DEFAULT, &HandleThread, &Handle, &Handle.Id);
/* 开始处理,在抓取帧的情况下调用处理函数。 */
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT, ProcessingFunction, &UserHookData);
}
SetWindowText(L"检测中");
}
void CHoleDEDlg::OnBnClickedStop()
{
//断开相机采图
if (m_state==1)
{
Handle.Exit = 1;
m_state = 0;
MthrWait(Handle.Id, M_THREAD_END_WAIT, M_NULL);
CO = FALSE;
//释放线程
MthrFree(Handle.Id);
//释放事件
MthrFree(Handle.DoneEvent);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);
/* 释放采集buffer */
while (MilGrabBufferListSize > 0)
{
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
}
//释放buffer
delete m_AvsBuffer;
m_AvsBuffer = NULL;
/* 释放默认值 */
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
SetWindowText(L"已停止工作");
}
}
/* 每次抓取缓冲区准备就绪时调用用户的处理函数 */
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
if (CO == FALSE)
{
OutputDebugString(L"1\r\n");
/* 取回抓取的缓冲器的MIL_ID. */
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId);
/* 增加帧数. */
UserHookDataPtr->ProcessedImageCount++;
//CString a ;
//a.Format(_T("%3d.bmp"),m++);
//MbufExport((MIL_TEXT_CHAR*)a.GetBuffer(0), M_BMP, ModifiedBufferId);
/* 向线程发出信号,表示采集已完成。 */
MthrControl(Handle.DoneEvent, M_EVENT_SET, M_SIGNALED);
OutputDebugString(L"2\r\n");
CO = TRUE;
}
BalanceThreadScheduling();
return 0;
}
/* 线程函数主体 */
MIL_UINT32 MFTYPE HandleThread(void *ThreadParameters)
{
THREAD_PARAM *TPar = (THREAD_PARAM *)ThreadParameters;
while (!TPar->Exit)
{
OutputDebugString(L"3\r\n");
/* 在继续之前,等待事件准备就绪 */
MthrWait(TPar->DoneEvent, M_EVENT_WAIT, M_NULL);
OutputDebugString(L"4zhuan\r\n");
MbufGet(ModifiedBufferId, m_AvsBuffer);
//显示
{
MbufCopy(ModifiedBufferId, MilImageDisp);
}
OutputDebugString(L"5\r\n");
/* 向上线程发出信号,表示处理的最后一部分已完成 */
MthrControl(TPar->DoneEvent, M_EVENT_SET, M_SIGNALED);
/* 为了获得更平滑的显示效果,可选的方法是让其他线程产生效果 */
/* 设置标志位开始采集 */
CO = FALSE;
}
CO = TRUE;
//退出线程之前,请确保所有命令都已执行
MthrWait(TPar->System, M_THREAD_WAIT, M_NULL);
return(1L);
}
/* 此功能用于提供更平滑的显示效果。它通过频繁地生成时间片来平衡每个线程的*迭代次数 */
void BalanceThreadScheduling()
{
MosSleep(0);
}
void CHoleDEDlg::OnTimer(UINT_PTR nIDEvent)
{
CDialogEx::OnTimer(nIDEvent);
}
void CHoleDEDlg::OnBnClickedButton1()
{
m_state = 1;
SetWindowText(L"检测继续中");
}
void CHoleDEDlg::OnBnClickedButton2()
{
m_state = 0;
SetWindowText(L"检测暂停状态");
}
以上代码,利用MFC开发,可以达到显示视频的目的。其中应注意的是程序中开启的线程为MIL库中方法创建的线程,而非C++调用windows接口创建线程。
MdigAlloc(MilSystem, M_DEV0, MIL_TEXT(“D:\Basler.dcf”), M_DEFAULT, &MilDigitizer);
此函数为读取DCF文件,获取相机参数配置,DCF文件介绍请参考网址:
MsysAlloc(M_DEFAULT, M_SYSTEM_RADIENTEVCL, M_DEV0, M_DEFAULT, &MilSystem);
此函数用于选择采集卡版本。
四、 QT开发
//matroxdriver.h
#ifndef MATROXDRIVER_H
#define MATROXDRIVER_H
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QImage>
#include "Mil.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
using namespace cv;
/* 用户的处理功能钩住数据结构 */
struct HookDataStruct
{
MIL_ID MilDigitizer;
MIL_ID MilImageDisp;
MIL_INT ProcessedImageCount;
} ;
/* 线程参数结构 */
struct THREAD_PARAM
{
MIL_ID Id;
MIL_ID System;
MIL_ID OrgImage;
MIL_ID SrcImage;
MIL_ID DstImage;
MIL_ID ReadyEvent;
MIL_ID DoneEvent;
MIL_INT NumberOfIteration;
MIL_INT Radius;
MIL_INT Exit;
MIL_INT LicenseModules;
struct ThreadParam *SlaveThreadParam;
} ;
//缓冲抓取队列中的图像数。
//通常,增加这个数字可以提供更好的实时抓取。
#define BUFFERING_SIZE_MAX 22
//采集BUFFER
static MIL_ID ModifiedBufferId;
//表示位
static MIL_BOOL CO = false ;
/* 参数定义 */
static MIL_ID MilApplication;
static MIL_ID MilSystem;
static MIL_ID MilDigitizer;
static MIL_ID MilDisplay;
static MIL_ID MilImageDisp;
static MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
static MIL_INT MilGrabBufferListSize;
static MIL_INT ProcessFrameCount = 0;
static MIL_DOUBLE ProcessFrameRate = 0;
static MIL_INT NbFrames = 0, n = 0;
static HookDataStruct UserHookData;
//线程句柄
static THREAD_PARAM Handle;
//相机状态标识,0代表断开,1代表打开
static int m_state = 0;
/* 获取的图像参数. */
static MIL_INT BufSizeX;
static MIL_INT BufSizeY;
static MIL_INT BufSizeBand;
static MIL_INT m = 1;
/* 函数原型 */
//MIL_UINT32 MFTYPE TopThread(void *TPar);
//MIL_UINT32 MFTYPE HandleThread(void *TPar);
//MIL_UINT32 MFTYPE BotRightThread(void *TPar);
//void BalanceThreadScheduling();
static unsigned char* m_AvsBuffer = nullptr;
class MatroxDriver:public QObject
{
Q_OBJECT
public:
MatroxDriver();
static MatroxDriver* pMatroxDriver;
/* 用户的处理函数原型 */
static MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
void send_PictureData(Mat data);
public slots:
void slot_OpenCamera();
void slot_CloseCamera();
signals:
void signal_PictureData(QImage data);
private:
//QThread *m_thread;
static MIL_UINT32 getCameraData(void *ThreadParameters);
bool m_StartGetPictuer = false;
void BalanceThreadScheduling();
};
#endif // MATROXDRIVER_H
//matroxdriver.CPP
#include "matroxdriver.h"
/* 用户的处理函数原型 */
//MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
MatroxDriver* MatroxDriver::pMatroxDriver = nullptr;
MatroxDriver::MatroxDriver()
{
pMatroxDriver = this;
//m_thread = new QThread;
//moveToThread(m_thread);
//m_thread->start();
qDebug()<<__FUNCTION__<<QThread::currentThreadId();
}
void MatroxDriver::slot_OpenCamera()
{
qDebug()<<__FUNCTION__<<QThread::currentThreadId();
if (m_state == 0)
{
MappAlloc(M_DEFAULT, &MilApplication);
MsysAlloc(M_DEFAULT, M_SYSTEM_RADIENTEVCL, M_DEV0, M_DEFAULT, &MilSystem);
MdigAlloc(MilSystem, M_DEV0, MIL_TEXT("D:\\Basler.dcf"), M_DEFAULT, &MilDigitizer);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
m_state = 1;
/* 获取图像参数 */
MdigInquire(MilDigitizer, M_SIZE_X, &BufSizeX);
MdigInquire(MilDigitizer, M_SIZE_Y, &BufSizeY);
MdigInquire(MilDigitizer, M_SIZE_BAND, &BufSizeBand);
/* 分配显示的buffer */
MbufAllocColor(MilSystem, BufSizeBand, BufSizeX, BufSizeY, 8 + M_UNSIGNED,
(MilDigitizer ? M_IMAGE + M_DISP + M_GRAB /*+ M_ON_BOARD*/ + M_PROC : M_IMAGE + M_DISP + M_ON_BOARD),
&MilImageDisp);
m_AvsBuffer = new unsigned char[BufSizeX * BufSizeY];
//线程分配//
/* 分配同步事件 */
MthrAlloc(MilSystem, M_EVENT, M_DEFAULT, M_NULL, M_NULL, &Handle.DoneEvent);
/* 初始化剩余的线程参数 */
Handle.System = MilSystem;
Handle.OrgImage = MilImageDisp;
Handle.NumberOfIteration = 0;
Handle.Radius = 0;
Handle.Exit = 0;
//MdispSelectWindow(MilDisplay, MilImageDisp, GetDlgItem(IDC_DIS)->GetSafeHwnd());
MdispControl(MilDisplay, M_SCALE_DISPLAY, M_ENABLE);
/* 分配并清除抓取缓冲器。 */
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for (MilGrabBufferListSize = 0; MilGrabBufferListSize < BUFFERING_SIZE_MAX; MilGrabBufferListSize++)
{
MbufAlloc2d(MilSystem,
MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
8 + M_UNSIGNED,
M_IMAGE + M_GRAB + M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]);
if (MilGrabBufferList[MilGrabBufferListSize])
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
/* 释放缓冲区,为可能的临时缓冲区留出空间。 */
for (n = 0; n < 2 && MilGrabBufferListSize; n++)
{
MilGrabBufferListSize--;
MbufFree(MilGrabBufferList[MilGrabBufferListSize]);
}
//连续采集显示
//MdigGrabContinuous(MilDigitizer, MilImageDisp);
//停止连续采集显示
//MdigHalt(MilDigitizer);
/* 初始化用户的处理函数数据结构. */
UserHookData.MilDigitizer = MilDigitizer;
UserHookData.MilImageDisp = MilImageDisp;
UserHookData.ProcessedImageCount = 0;
//开启线程//
MthrAlloc(MilSystem, M_THREAD, M_DEFAULT, &getCameraData, &Handle, &Handle.Id);
//m_StartGetPictuer = true;
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT,this->ProcessingFunction, &UserHookData);
/* 开始处理,在抓取帧的情况下调用处理函数。 */
}
}
/* 每次抓取缓冲区准备就绪时调用用户的处理函数 */
MIL_INT MFTYPE MatroxDriver::ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
qDebug()<<__FUNCTION__<<QThread::currentThreadId();
if (CO == false)
{
/* 取回抓取的缓冲器的MIL_ID. */
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId);
/* 增加帧数. */
UserHookDataPtr->ProcessedImageCount++;
//CString a ;
//a.Format(_T("%3d.bmp"),m++);
//MbufExport((MIL_TEXT_CHAR*)a.GetBuffer(0), M_BMP, ModifiedBufferId);
/* 向线程发出信号,表示采集已完成。 */
MthrControl(Handle.DoneEvent, M_EVENT_SET, M_SIGNALED);
CO = true;
}
pMatroxDriver->BalanceThreadScheduling();
return 0;
}
void MatroxDriver::send_PictureData(Mat data_Image)
{
qDebug()<<__FUNCTION__<<QThread::currentThreadId();
normalize(data_Image,data_Image,0,255,NORM_MINMAX,CV_8UC1);
transpose(data_Image, data_Image);
flip(data_Image, data_Image, 1);
QImage qImg = QImage((const unsigned char*)(data_Image.data), data_Image.cols, data_Image.rows, QImage::Format_Grayscale8);
emit signal_PictureData(qImg);
}
void MatroxDriver::slot_CloseCamera()
{
//断开相机采图
if (m_state==1)
{
Handle.Exit = 1;
m_state = 0;
MthrWait(Handle.Id, M_THREAD_END_WAIT, M_NULL);
CO = false;
//释放线程
MthrFree(Handle.Id);
//释放事件
MthrFree(Handle.DoneEvent);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);
/* 释放采集buffer */
while (MilGrabBufferListSize > 0)
{
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
}
//释放buffer
delete m_AvsBuffer;
m_AvsBuffer = NULL;
/* 释放默认值 */
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
}
}
MIL_UINT32 MatroxDriver::getCameraData(void *ThreadParameters)
{
THREAD_PARAM *TPar = (THREAD_PARAM *)ThreadParameters;
qDebug()<<__FUNCTION__<<QThread::currentThreadId();
while (!TPar->Exit)
{
/* 在继续之前,等待事件准备就绪 */
MthrWait(TPar->DoneEvent, M_EVENT_WAIT, M_NULL);
MbufGet(ModifiedBufferId, m_AvsBuffer);
Mat farme(BufSizeX,BufSizeY,CV_8UC1,m_AvsBuffer);
normalize(farme,farme,0,255,NORM_MINMAX,CV_8UC1);
transpose(farme,farme);
flip(farme, farme, 1);
QImage qImg = QImage((const unsigned char*)(farme.data), farme.cols, farme.rows, QImage::Format_Grayscale8);
emit pMatroxDriver->signal_PictureData(qImg);
//显示
// {
// MbufCopy(ModifiedBufferId, MilImageDisp);
// }
/* 向上线程发出信号,表示处理的最后一部分已完成 */
//MthrControl(TPar->DoneEvent, M_EVENT_SET, M_SIGNALED);
/* 设置标志位开始采集 */
CO = false;
}
CO = true;
//退出线程之前,请确保所有命令都已执行
MthrWait(TPar->System, M_THREAD_WAIT, M_NULL);
return (1L);
}
void MatroxDriver::BalanceThreadScheduling()
{
MosSleep(0);
}
// opencvdeal.h
#ifndef OPENCVDEAL_H
#define OPENCVDEAL_H
#include <QObject>
#include "matroxdriver.h"
#include <QImage>
#include <QPixmap>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
using namespace cv;
class OpencvDeal : public QObject
{
Q_OBJECT
public:
OpencvDeal();
MatroxDriver *m_MatroxDriver;
public slots:
void slot_StartGatherImage();
void slot_DealMatData(QImage qImg);
signals:
void signal_StartGatherImage();
void signal_ShowImage(QPixmap image);
};
#endif // OPENCVDEAL_H
//opencvdeal.CPP
#include "opencvdeal.h"
OpencvDeal::OpencvDeal()
{
m_MatroxDriver = new MatroxDriver();
connect(m_MatroxDriver,&MatroxDriver::signal_PictureData,this,&OpencvDeal::slot_DealMatData);
connect(this,&OpencvDeal::signal_StartGatherImage,m_MatroxDriver,&MatroxDriver::slot_OpenCamera);
}
void OpencvDeal::slot_StartGatherImage()
{
emit signal_StartGatherImage();
}
void OpencvDeal::slot_DealMatData(QImage qImg)
{
QPixmap showImage = QPixmap::fromImage(qImg);
emit signal_ShowImage(showImage);
}