您的位置:首页 > 运维架构

mfc使用opencv3.1

2016-08-06 08:16 441 查看
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了,效果如图

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mfc opencv vc