Matorx视频采集卡开发及使用(三)

一、 前言

本文初始目的为购买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文件介绍请参考网址:https://www.cnblogs.com/riasky/archive/2013/12/03/3455541.html
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);
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值