mfc使用opencv3.1

来源:互联网 发布:通讯录软件哪个好 编辑:程序博客网 时间:2024/06/03 05:40

MFC配置opencv3.1.0的方法:

需要注意的一小点是,opencv3.1.0的平台集是vc12和vc14的并且下载里面的只有x64版本。mfc在显示图片的时候是4字节对齐的,所以要把opencv的的data数据进行对齐。

1.下载opencv3.1.0,网址为 http://opencv.org/,也建议在这个网站上下载。

2.双击后会解压opencv-3.1.0.exe,得到一个opencv的文件夹,并打开这个文件夹。从这个文件夹里找build文件夹下的include和x64文件夹,这两个文件夹需要复制出来。


3.打开vs2013,并新建一个单文档,并完成向导,个人是默认的向导。

4.将2中提到的那个两个文件夹复制到刚才的新建的单文档项目中。




5.在stdafx.h里添加如下代码进行lib的链接,链接的路径就是刚才复制x64的那个路径


可以看见路径在x64 v12 lib中,所以stadafx.h的代码可以写成


#ifndef ____OPENCV_USER____
#define ____OPENCV_USER____


#ifndef ____OPENCV_USER____
#define ____OPENCV_USER____


#include "include/opencv2/opencv.hpp"
#ifdef _WIN64
#pragma comment(lib,"x64/vc12/lib/opencv_world310.lib")
#endif
#endif // _WIN64


不过在此之前,要把程序调成x64的,因为提过的dll是x64的,如果需要x86的可以使用opencv2.4.13版或者自己编译一个x86的。


新建一个x64的活动解决方案平台并从win32复制过来。


6.在属性里面设置下包含目录



为了能让单文档显示图片,我新建了一个头文件和cpp去写opencv的函数如图。

//OpencvProc.h

#pragmaonce

#include"stdafx.h"

#include<vector>

#include<iostream>

#include"opencv2\core\mat.hpp"

#include"opencv2\opencv.hpp"

 

usingnamespacestd;

usingnamespacecv;

 

 

 

#ifndef____OPENCV_DEAL____

#define____OPENCV_DEAL____

 

classopencv

{

 

private:

    int            noOfCordinates;    //Number of elements in coordinate array

    Point          *cordinates;       //Coordinates arrayto store model points  

    int            modelHeight;       //Template height

    int            modelWidth;        //Template width

    double         *edgeMagnitude;    //gradient magnitude

    double         *edgeDerivativeX;  //gradient in X direction

    double         *edgeDerivativeY;  //radient in Y direction   

    Point          centerOfGravity;   //Center of gravity of template

    bool           modelDefined;

 

public:

    opencv();

    ~opencv();

    Matmat0;              //第一缓存图像

    Matmat1;              //第二缓存图像

    Matmat2;              //第三缓存图像

    Matmat3;              //第四缓存图像

    MatCameramat;         //用于摄像机图像缓存

    boolCameramatOK;      //取图片判断;

    uchar*mat_data0;  //由于图像问题需要四字节对齐,对应给mat

    uchar*mat_data1;  //由于图像问题需要四字节对齐,对应给mat1

    uchar*mat_data2;  //由于图像问题需要四字节对齐,对应给mat2

    uchar*mat_data3;  //由于图像问题需要四字节对齐,对应给mat3

 

    //原始图片

    Matm_RawImg;

    //处理后的图片

    Matm_ResultImg;

 

    voidLoadMatImg(stringstr);

    voidswapValue(uchar&a,uchar&b);        //交换值

 

    LPBITMAPINFOCreateMapInfo(constMat&src);//创建图像头

 

    boolBmpToMat(BITMAPINFO*bmpinfo,BYTE*imageData,Mat&dst);//bmp转mat

 

    CStringSaveImage(constMat&src1,CStringstr= L""); //保存图片

    CStringSaveImage(constMat&src1,CStringdir,CStringstr);

 

    floatProcessImg(Mat&src);

    floatProcessImg(Mat&src,Rectrect);

    voidConvert2GRAY(constMat&src,Mat&dst);

    voidConvert2BGR(constMat&src,Mat&dst);

    voidMonoInvert(Mat&src);                 //图像翻转一下

    boolCopyMatDataToMem(constMat&src,uchar**data);

    boolcvInit();

   

};

 

#endif

//opencvProc.cpp

#include"stdafx.h"

#include"opencvProc.h"

 

//注意图像训练的时候是否翻转!!!!!!

#pragmawarning(disable:4267)

 

floatopencv::ProcessImg(Mat&src,Rectrect)

{

    return1.0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

opencv::opencv()

:mat_data0(NULL)

,mat_data1(NULL)

,mat_data2(NULL)

,mat_data3(NULL)

{

    cvInit();

    CameramatOK=false;

}

 

boolopencv::cvInit()

{

    return true;

}

 

 

floatopencv::ProcessImg(Mat&src)

{

 

        return-1;

   

}

 

 

 

opencv::~opencv()

{

}

 

 

 

voidopencv::LoadMatImg(stringstr)

{

    mat0=imread(str,-1);

}

 

voidopencv::swapValue(uchar&a,uchar&b)

{

    a=a^b;

    b=a^b;

    a=a^b;

}

 

 

LPBITMAPINFOopencv::CreateMapInfo(constMat&src)

{

    BITMAPINFOHEADERBIH={40,1,1,1,8,0,0,0,0,0,0};

    LPBITMAPINFOlpBmi;

    int         wid,hei,bits,colors,i,depth,channels;

    RGBQUAD ColorTab[256];

    wid=src.cols;    hei=src.rows;

    if(CV_8UC1==src.type())

    {

        depth=8;channels=1;

    }

    elseif(CV_8UC3==src.type())

    {

        depth=8;channels=3;

    }

    elsereturnNULL;

    bits=depth*channels;

    if(bits>8)colors=0;

    elsecolors=1<<bits;

    lpBmi=(LPBITMAPINFO)malloc(40+4*colors);

    BIH.biWidth=wid;    BIH.biHeight=hei;

    BIH.biBitCount=(BYTE)bits;

    memcpy(lpBmi,&BIH,40);                  //  复制位图信息头

    if(bits==8){                          //  256 色位图

        for(i=0;i<256;i++) {               //  设置灰阶调色板

            ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE)i;

        }

        memcpy(lpBmi->bmiColors,ColorTab,1024);

    }

    return(lpBmi);

}

 

 

 

 

boolopencv::BmpToMat(BITMAPINFO*bmpinfo,BYTE*imageData,Mat&dst)

{

    try{

        if(!imageData)returnfalse;

        intsize=bmpinfo->bmiHeader.biWidth*bmpinfo->bmiHeader.biHeight; 

        dst.create(Size(bmpinfo->bmiHeader.biWidth,bmpinfo->bmiHeader.biHeight),CV_8UC1);

        memcpy(dst.data,(uchar*)imageData,size);

        returntrue;

    }

    catch(...)

    {

        returnfalse;

    }

}

 

CStringopencv::SaveImage(constMat&src1,CStringstr)

{

    //写在一起了供以后参考

    if(src1.empty())return L"";

   

    Matsrc=src1.clone();

    MonoInvert(src);//翻转图片

    //MonoInvert(src);

    //获取时间

    if(L""==str)

    {

        SYSTEMTIMEst;

        CStringstrDate,strTime;

        GetLocalTime(&st);

        strDate.Format(_T("%4d-%d-%d_"),st.wYear,st.wMonth,st.wDay);

        strTime.Format(_T("%d-%d-%d"),st.wHour,st.wMinute,st.wSecond);

        str=strDate+strTime;

    }

    //获取路径

    CStringAppPath;

    ::GetModuleFileName(GetModuleHandle(NULL),AppPath.GetBuffer(300),300);

    AppPath.ReleaseBuffer();

    AppPath=AppPath.Left(AppPath.ReverseFind('\\'));

    AppPath=AppPath+ L"\\"+ L"Image";

    CreateDirectory(AppPath,NULL);

    str=AppPath+ L"\\"+str+ L".bmp";

 

    //CString转成char*

    std::stringpstr=(LPCSTR)CStringA(str);

    imwrite(pstr,src);

    returnstr;

}

 

CStringopencv::SaveImage(constMat&src1,CStringdir,CStringstr)

{

    //写在一起了供以后参考

    if(src1.empty())return L"";

 

    Matsrc=src1.clone();

    MonoInvert(src);//翻转图片

    //MonoInvert(src);

    //获取时间

    if(L""==str)

    {

        SYSTEMTIMEst;

        CStringstrDate,strTime;

        GetLocalTime(&st);

        strDate.Format(_T("%4d-%d-%d_"),st.wYear,st.wMonth,st.wDay);

        strTime.Format(_T("%d-%d-%d"),st.wHour,st.wMinute,st.wSecond);

        str=strDate+strTime;

    }

    //获取路径

    CStringAppPath;

    ::GetModuleFileName(GetModuleHandle(NULL),AppPath.GetBuffer(300),300);

    AppPath.ReleaseBuffer();

    AppPath=AppPath.Left(AppPath.ReverseFind('\\'));

    AppPath=AppPath+ L"\\"+dir;

    CreateDirectory(AppPath,NULL);

    str=AppPath+ L"\\"+str+ L".bmp";

 

    std::stringpstr=(LPCSTR)CStringA(str);

    imwrite(pstr,src);

    returnstr;

}

 

 

 

 

voidopencv::Convert2GRAY(constMat&src,Mat&dst)

{

    if(CV_8UC3==src.type())

        cv::cvtColor(src,dst,CV_BGR2GRAY);

    else

        dst=src.clone();

}

 

voidopencv::Convert2BGR(constMat&src,Mat&dst)

{

    if(CV_8UC1==src.type())

        cv::cvtColor(src,dst,CV_GRAY2BGR);

    else

        dst=src.clone();

 

}

 

 

voidopencv::MonoInvert(Mat&src)

{

    size_twidthStep=src.step;

    size_trows=src.rows-1;

    for(size_tr=0;r<rows;r++,rows--)

        for(size_tstep=0;step<widthStep;step++)

        {

        src.data[r*widthStep+step]^=src.data[rows*widthStep+step];

        src.data[rows*widthStep+step]^=src.data[r*widthStep+step];

        src.data[r*widthStep+step]^=src.data[rows*widthStep+step];

        }

}

 

 

 

boolopencv::CopyMatDataToMem(constMat&src,uchar**data)

{

    //四字节对齐

    if(src.empty())returnfalse;

    if(*data)free(*data);

    size_theight=src.rows;

    size_tstep=src.step;

    size_toffset=0==src.step%4?0:4-src.step%4;

    size_tsize_i=(offset+src.step)*height;

    *data=(uchar*)malloc(size_i);

    if(NULL==*data)returnfalse;

    uchar*idata=src.data;

    uchar*ddata=*data;

    for(inth=0;h<height;h++)

    {

        memcpy(ddata,idata,step);

        ddata=ddata+step+offset;

        idata=idata+step;

    }

    returntrue;

}

 

 

然后在view.h文件里加入写好的如图

在riibon里面加上一个按钮

里面添加如下代码

   

    try{

        CFileDialogfileDlg(TRUE,(LPCTSTR)"BMP", L"",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, L"All Files(*.*)|*.*|位图文件 (*.bmp)|*.bmp||");//打开读取文件对话框

 

        if(fileDlg.DoModal()!=IDOK)return;

 

        Opencv.LoadMatImg((LPCSTR)CStringA(fileDlg.GetPathName()));                //读取图像,并载入到Mat类里面

 

        if(Opencv.mat0.empty()){AfxMessageBox(L"不能读取图片");return;}           //读取失败则返回

 

        Opencv.MonoInvert(Opencv.mat0);

 

        Opencv.m_RawImg=Opencv.mat0.clone();//原始图片

 

        Invalidate(TRUE);                                                          //重绘窗口

   

 

    }

    catch(...)

    {

        AfxMessageBox(L"文件路径读取错误");

    }

再在OnDraw里添加代码,注意要取消pDC的这个注释

voidCopencvView::OnDraw(CDC*pDC)

{

    CopencvDoc*pDoc=GetDocument();

    ASSERT_VALID(pDoc);

    if(!pDoc)

        return;

 

    // TODO: 在此处为本机数据添加绘制代码

    CRectrt;

    GetClientRect(&rt);

    intnWndWidth=rt.right-rt.left;

    intnWndHeight=rt.bottom-rt.top;

    uchar*pdata=NULL;

    if(Opencv.CopyMatDataToMem(Opencv.mat0,&pdata))

    {

 

        CDCdcMem;

        CBitmapbmp;//内存中承载临时图象的位图

        bmp.CreateCompatibleBitmap(pDC,rt.Width(),rt.Height());

        dcMem.CreateCompatibleDC(pDC);//依附窗口DC创建兼容内存DC

        //创建兼容位图(必须用pDC创建,否则画出的图形变成黑色)

        CBitmap*pOldBit=dcMem.SelectObject(&bmp);

        //按原来背景填充客户区,不然会是黑色

        HDC hDC=dcMem.GetSafeHdc();

        ::SetStretchBltMode(hDC,COLORONCOLOR);

 

        LPBITMAPINFOpBitmapInfo=Opencv.CreateMapInfo(Opencv.mat0);

        constintheight=Opencv.mat0.rows;

        constintwidth=Opencv.mat0.cols;

        ::StretchDIBits(hDC,

            0,//nWndWidth,

            0,//nWndHeight,

            nWndWidth,

            nWndHeight,

            0,

            0,

            width,

            height,

            (BYTE*)pdata,

            pBitmapInfo,

            DIB_RGB_COLORS,

            SRCCOPY

            );

        GetClientRect(&rt);

        hDC=pDC->GetSafeHdc();

        pDC->BitBlt(0,0,rt.Width(),rt.Height(),&dcMem,0,0,SRCCOPY);

 

        //将内存DC上的图象拷贝到前台

        //绘图完成后的清理

        dcMem.DeleteDC();    //删除DC

        bmp.DeleteObject();//删除位图

        free(pdata);

 

    }

}

最后生成程序就ok了,效果如图

 



0 0
原创粉丝点击