使用Matlab直接调用Microview相机接口

使用Matlab直接调用Microview相机接口

注意事项

  • 在win10平台上由于Microview相机64位SDK无法使用,因此只能使用32位Matlab,且启动Matlab时需用管理员权限运行

资源文件

  • MVCAPI.h
  • CommonDataType.h
  • MVCAPI.lib
  • MVCAPI.dll
  • MVParm.dll
  • MVBayerDec.dll

源代码

1、初始化相机

基本思路是在内存中保留一块内存区域用于存储和相机有关的配置信息和图像,C接口程序接受Matlab传来的参数,并初始化相机,将相机配置参数存入内存的堆区域,返回值为该内存区域的首地址,转为Int类型输出,Matlab程序只需持有该地址即可。

//mvc_init_camera.cpp

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include "MVCAPI.h"
#include "mex.h"

HANDLE*  m_phMVCs;
BYTE*   m_pRawDatas[5];
struct CapInfoStruct* m_pCapInfos;
int*    pplhs0;

void free_data(int camera_num);
void init_camera(int camera_num, int* pcamera_ids, int* pwidths, int* pheights, int* phOffs, int* pvOffs);
/***
*输入参数:五个行向量,分别是相机标号,每个相机获取图像的宽和高,图像的水平偏置和垂直偏置
*输出参数:n*3 矩阵
*       |相机标号1|m_hMVs指针|m_CapInfo指针|
*       |相机标号2|m_hMVs指针|m_CapInfo指针|
*       ...
***/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    int camera_num,i;
    int camera_ids[6];
    int widths[6];
    int heights[6];
    int hOffs[6];
    int vOffs[6];
    double *pInputs[5];

    //分别相机标号、宽、高、水平偏置、垂直偏置 (都是行向量)
    if(nrhs != 5) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_init_camera:nrhs",
                      "Five inputs required.");
    }
    //输出[相机标号,m_hMVs指针,m_CapInfo指针]
    if(nlhs != 1) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_init_camera:nlhs",
                          "One output required.");
    }

    camera_num = mxGetN(prhs[0]);

    for (i=0;i<5;++i){
        pInputs[i] = mxGetPr(prhs[i]);
    }
    for (i=0;i<camera_num;++i){
        camera_ids[i] = (int)(pInputs[0][i]);
        widths[i] = (int)(pInputs[1][i]);
        heights[i] = (int)(pInputs[2][i]);
        hOffs[i] = (int)(pInputs[3][i]);
        vOffs[i] = (int)(pInputs[4][i]);
        mexPrintf("camera: %d %d %d %d %d\n",camera_ids[i],widths[i],heights[i],hOffs[i],vOffs[i]);
    }

    m_phMVCs = (HANDLE*)malloc(camera_num*sizeof(HANDLE));
    memset(m_phMVCs,0,camera_num*sizeof(HANDLE));

    m_pCapInfos = (struct CapInfoStruct*)malloc(camera_num*sizeof(struct CapInfoStruct));
    memset(m_pCapInfos,0,camera_num*sizeof(struct CapInfoStruct));

    init_camera(camera_num,camera_ids,widths,heights,hOffs,vOffs);

    plhs[0] = mxCreateNumericMatrix(3,(mwSize)camera_num,mxINT32_CLASS,mxREAL);


    pplhs0 = (int*)mxGetData(plhs[0]);
    for (i=0;i<camera_num;++i){
        pplhs0[i*3+0] = camera_ids[i];
        pplhs0[i*3+1] = (int)(m_phMVCs+i);
        pplhs0[i*3+2] = (int)(m_pCapInfos+i);
    }

}

void init_camera(int camera_num, int* pcamera_ids, int* pwidths, int* pheights, int* phOffs, int* pvOffs){
    int nIndex=0;
    int rt;
    int RawDataSize;

    for (nIndex=0;nIndex<camera_num;++nIndex){
        RawDataSize = pwidths[nIndex]*pheights[nIndex];
        m_pRawDatas[nIndex]=(BYTE*)malloc(RawDataSize*sizeof(BYTE));
        memset(m_pRawDatas[nIndex],0,RawDataSize*sizeof(BYTE));

        struct CapInfoStruct *m_pCapInfo = m_pCapInfos+nIndex;
        memset(m_pCapInfo, 0, sizeof(struct CapInfoStruct));
        m_pCapInfo->Buffer = m_pRawDatas[nIndex];

        m_pCapInfo->Height = pheights[nIndex];
        m_pCapInfo->Width  = pwidths[nIndex];
        m_pCapInfo->HorizontalOffset = phOffs[nIndex];
        m_pCapInfo->VerticalOffset   = pvOffs[nIndex];
        m_pCapInfo->Exposure         = 1024;
        m_pCapInfo->Gain[0]          = 17;
        m_pCapInfo->Gain[1]          = 9;
        m_pCapInfo->Gain[2]          = 15;
        m_pCapInfo->Control          = 0;
        memset(m_pCapInfo->Reserved, 0, 8);
        m_pCapInfo->Reserved[0]    = 3;

        m_phMVCs[nIndex] = 0;
        mexPrintf("init camera: %d %d %d\n",pcamera_ids[nIndex],m_pCapInfo,&m_phMVCs[nIndex]);
        rt = MV_Usb2Init("MVC1000", pcamera_ids+nIndex, m_pCapInfo, m_phMVCs+nIndex);
        if(ResSuccess != rt)
        {
            free_data(nIndex+1);
            mexPrintf("rt:%d\n",rt);
            mexErrMsgTxt("Can not open USB camera");
        }

    }

    for (nIndex=0;nIndex<camera_num;++nIndex){
        MV_Usb2StartCapture(m_phMVCs[nIndex],TRUE);
    }

}

void free_data(int camera_num){
    for (int i=0;i<camera_num;++i){
        MV_Usb2Uninit(&m_phMVCs[i]);
        free(m_pRawDatas[i]);
    }
    free(m_phMVCs);
    free(m_pCapInfos);
}

2、获取图像

输入需要获取图像的相机Id,以及其对应的m_phMVCs指针地址即可,输出值为cell类型,每个单元中保存有一副图像。cell{image1,image2,image3,…}

//mvc_get_camera.cpp

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include "MVCAPI.h"
#include "mex.h"

HANDLE*  m_phMVCs;
struct CapInfoStruct* m_pCapInfos;
double*  pprhs0;
int* pprhs1;
BYTE* pImage;

/***
*输入参数:相机Id(行向量),m_phMVCs指针地址(行向量)
*输出参数:Matlab的Cell类型,每个单元存一副图像
***/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    int camera_num,image_num,i,j,h,w,num;
    int camera_ids[6];
    int image_ids[6];
    int im2ca[6] = {-1,-1,-1,-1,-1,-1 }; //图像序号转相机序号

    mxArray *pIms[6];
    mwSize dims[4];
    /*
     *[id   id   id
     * hMVC hMVC hMVC
     * Cap  Cap  Cap]
     */
    //相机ids、mvcMgr
    if(nrhs != 2) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_get_image:nrhs",
                      "Two inputs required.");
    }
    //输出图像结构体
    if(nlhs != 1) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_get_image:nlhs",
                          "One output required.");
    }
    image_num = mxGetN(prhs[0]);
    camera_num = mxGetN(prhs[1]);

    pprhs0 = mxGetPr(prhs[0]);
    pprhs1 = (int*)mxGetData(prhs[1]);

    for (i=0;i<camera_num;++i){
        camera_ids[i] = (int)(pprhs1[i*3]);
        //mexPrintf("camera: %d\n",camera_ids[i]);
    }

    for (i=0;i<image_num;++i){
        image_ids[i] = (int)(pprhs0[i]);
        //mexPrintf("image: %d\n",image_ids[i]);
    }

    m_phMVCs = (HANDLE*)pprhs1[1];
    m_pCapInfos = (struct CapInfoStruct*)pprhs1[2];

    for (i=0;i<image_num;++i){
        for (j=0;j<camera_num;++j){
            if (image_ids[i]==camera_ids[j]){
                MV_Usb2GetRawData(m_phMVCs[j],&m_pCapInfos[j]);
                im2ca[i] = j;
            }
        }
        if (im2ca[i]<0){
            mexErrMsgTxt("Camera id not exist");
        }
    }

    dims[0] = m_pCapInfos[0].Width;;
    dims[1] = m_pCapInfos[0].Height;;

    plhs[0] = mxCreateCellMatrix(1,image_num);
    for (i=0;i<image_num;++i){
        num = im2ca[i];
        w = m_pCapInfos[num].Width;
        h = m_pCapInfos[num].Height;
        pIms[i] = mxCreateNumericMatrix(w,h,mxUINT8_CLASS,mxREAL);
        pImage = (BYTE*)mxGetData(pIms[i]);
        memcpy(pImage,m_pCapInfos[num].Buffer,w*h);
        mxSetCell(plhs[0],i,pIms[i]);
    }

}

3、去初始化相机

需去初始化相机并释放内存空间

//mvc_uinit_camera.cpp

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include "MVCAPI.h"
#include "mex.h"

HANDLE*  m_phMVCs;
struct CapInfoStruct* m_pCapInfos;
int*    pplhs0;

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    int camera_num,i;
    int camera_ids[6];
    /*
     *[id   id   id
     * hMVC hMVC hMVC
     * Cap  Cap  Cap]
     */
    //[相机id、m_phMVCs、m_pCapInfos] 列向量
    if(nrhs != 1) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_uinit_camera:nrhs",
                      "One inputs required.");
    }
    //无输出
    if(nlhs != 0) {
        mexErrMsgIdAndTxt("MyToolbox:mvc_uinit_camera:nlhs",
                          "Zero output required.");
    }

    if(mxGetM(prhs[0]) != 3){
        mexErrMsgIdAndTxt("MyToolbox:mvc_uinit_camera:nlhs",
                          "Wrong Input.");
    }

    camera_num = mxGetN(prhs[0]);
    pplhs0 = (int*)mxGetData(prhs[0]);

    m_phMVCs = (HANDLE*)pplhs0[1];
    m_pCapInfos = (struct CapInfoStruct*)pplhs0[2];


    for (int i=0;i<camera_num;++i){
        free(m_pCapInfos[i].Buffer);
        MV_Usb2StartCapture(m_phMVCs[i],FALSE);
        MV_Usb2Uninit(&m_phMVCs[i]);
    }
    free(m_phMVCs);
    free(m_pCapInfos);
}

4、Matlab封装代码

%% MVCInitCamera.m
function mvcMgr = MVCInitCamera( camera_ids,widths,heights,hOffs,vOffs )
    if (size(camera_ids,1)~=1)
        error('camera_ids should be row vector');
    end
    camera_num = size(camera_ids,2);
    if (length(widths)==1)
        widths = ones(1,camera_num)*widths;
        heights = ones(1,camera_num)*heights;
        hOffs = ones(1,camera_num)*hOffs;
        vOffs = ones(1,camera_num)*vOffs;
    end
    if (camera_num~=size(widths,2) || camera_num~=size(heights,2) || camera_num~=size(hOffs,2) || camera_num~=size(vOffs,2))
        error('all the vector should be same size');
    end
    mvcMgr = mvc_init_camera(camera_ids,widths,heights,hOffs,vOffs );
end
%% MVCGetImage.m
function ims = MVCGetImage( camera_ids,mvcMgr )

ims = mvc_get_image(camera_ids,mvcMgr);
for i=1:length(ims)
    ims{i} = rot90(ims{i});
end

end
%% MVCUInitCamera.m
function MVCUInitCamera( mvcMgr )

mvc_uinit_camera(mvcMgr);

end

编译mex

mex -L. -lMVCAPI mvc_init_camera.cpp
mex -L. -lMVCAPI mvc_get_image.cpp
mex -L. -lMVCAPI mvc_uinit_camera.cpp

源码

源码可从我github仓库下载:https://github.com/liucc09/microview

发布了22 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/liucc09/article/details/51234073