基于MFC和OpenCV的图像处理小软件

Posted 爱折腾的猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于MFC和OpenCV的图像处理小软件相关的知识,希望对你有一定的参考价值。


1.软件界面:


本程序是基于MFC的单文档(SDI)程序,每次可以打开耽搁图片文件,可以保存,另存为图片文件。支持打开jpg,png,ico,bmp,jpeg等格式的图片。图片打开后的界面如下:


2.图片缩放:

通过滚动鼠标滚轮,可以调节图像的大小。默认是向上滚动鼠标滚轮为放大图片,向下滚动鼠标滚轮为缩小图片。当图片放大或者缩小到一定程度后在滑动鼠标滚轮会没有任何变化,因为图片过大的话会造成内存溢出,也就是不可能无限制的放大。下面是放大和缩小后的图片截图:


3.彩色图片灰度化

   点击图像处理菜单按钮,会出现下拉菜单->灰度化,->二值化。其中点击灰度化按钮可以对打开的彩色图像进行灰度化(如果打开的是灰度图像或者二值化后的图像,则不处理) 。下图是点击“灰度化“选项之后的截图:


也可以对灰度化后的图像进行缩放、保存或者另存为。

4.OTSU二值化

本程序利用OTSU算法对图像进行二值化,点击“图像处理”菜单下的“二值化”选项,可以对打开的彩色(或灰度)图像二值化。其中二值化阈值设置对话框如下:


可以手动调整阈值,也可以直接利用OTSU算法计算出的阈值。比如本次打开的图像的OSTU算法计算出的最佳阈值是98,一般阈值在0-255之间。点击“确定”按钮,程序会自动调用手动调整的阈值,点击“取消”按钮,程序会自动用最佳阈值处理图像。

最佳阈值(本次打开的图像时98)处理的结果截图:


手动设置阈值150(也可以是其他值)后的结果:

 

技术要点部分:

1.打开图像

首先,通过MFC向导生成SDI程序模板,如下图:

在CImageProcessDoc.cpp中添加打开图像的部分代码,如下:

BOOLCImageProcessDoc::OnOpenDocument(LPCTSTR lpszPathName)

    if(!CDocument::OnOpenDocument(lpszPathName))
        return FALSE;
   
    // TODO: Add your specialized creation codehere
    m_image.Load(lpszPathName);
    return TRUE;

保存图像的代码如下:

BOOLCImageProcessDoc::OnSaveDocument(LPCTSTR lpszPathName)

    // TODO: Add your specialized code hereand/or call the base class
    m_image.Save(lpszPathName);
    return true;

2.图像的缩放

图像的缩放其实是吐过控制视图显示的比例来进项缩放的,首先利用应用程序向导添加鼠标滚轮的消息响应事件:

BOOL CImageProcessView::OnMouseWheel(UINTnFlags, short zDelta, CPoint pt)

//TODO: Add your message handler code here and/or call default
 
if(zDelta> 0) //鼠标向上滚轮,放大图像

     if((scale+ 0.05)<4)
         scale+= 0.05;//每次增加0.05倍
elseif(zDelta<0)//鼠标向下滚轮,缩小图像

     if((scale- 0.05)>0)
         scale -= 0.05;//每次减少0.05倍
else
         returnCView::OnMouseWheel(nFlags, zDelta, pt);

 
Invalidate();
 
returnCView::OnMouseWheel(nFlags, zDelta, pt);

3.图像的二值化
图像的二值化主要是用到了opencv里面的cvCvtColor函数,可以很方便的对彩色图像进行二值化,需要在CImageProcessDoc类中利用应用程序向导添加如下函数:
voidCImageProcessDoc::OnImageprocessingGray()

    // TODO: Add your command handler code here
    IplImage* img;
    img=m_image.GetImage();
    IplImage* imgray =cvCreateImage(cvGetSize(img), 8, 1);
    cvCvtColor(img, imgray, CV_RGB2GRAY); //彩色图像灰度化
    m_image.CopyOf(imgray, 1);
    UpdateAllViews(NULL);

 

4.图像的二值化

    OTSU算法原理:1. OTSU算法原理简介

    对于一幅图像,设当前景与背景的分割阈值为t时,前景点占图像比例为w0,均值为u0,背景点占图像比例为w1,均值为u1。则整个图像的均值为u = w0*u0+w1*u1。建立目标函数g(t)=w0*(u0-u)^2+w1*(u1-u)^2,g(t)就是当分割阈值为t时的类间方差表达式。OTSU算法使得g(t)取得全局最大值,当g(t)为最大时所对应的t称为最佳阈值。OTSU算法又称为最大类间方差法。

实现二值化需要在CImageProcessDoc中添加以下两个功能函数(OtsuThreshold(IplImage *image)

OnImageprocessingThreshold()):

intCImageProcessDoc::OtsuThreshold(IplImage *image)

    assert(NULL != image);
 
    int width = image->width;
    int height = image->height;
    int x=0,y=0;
    int pixelCount[256];
    float pixelPro[256];
    int i, j, pixelSum = width * height,threshold = 0;
 
    uchar* data = (uchar*)image->imageData;
 
    //初始化
    for(i = 0; i < 256; i++)
    
        pixelCount[i] = 0;
        pixelPro[i] = 0;
    
 
    //统计灰度级中每个像素在整幅图像中的个数
    for(i = y; i < height; i++)
    
        for(j = x;j <width;j++)
        
             pixelCount[data[i *image->widthStep + j]]++;
        
    
 
 
    //计算每个像素在整幅图像中的比例
    for(i = 0; i < 256; i++)
    
        pixelPro[i] = (float)(pixelCount[i]) /(float)(pixelSum);
    
 
    //经典ostu算法,得到前景和背景的分割
    //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
    float w0, w1, u0tmp, u1tmp, u0, u1,u,deltaTmp, deltaMax = 0;
    for(i = 0; i < 256; i++)
    
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u =deltaTmp = 0;
 
        for(j = 0; j < 256; j++)
        
             if(j <= i) //背景部分
             
                 //以i为阈值分类,第一类总的概率
                 w0 += pixelPro[j];      
                 u0tmp += j * pixelPro[j];
             
             else       //前景部分
             
                 //以i为阈值分类,第二类总的概率
                 w1 += pixelPro[j];      
                 u1tmp += j * pixelPro[j];
             
        
 
        u0 = u0tmp / w0;     //第一类的平均灰度
        u1 = u1tmp / w1;     //第二类的平均灰度
        u = u0tmp + u1tmp;       //整幅图像的平均灰度
        //计算类间方差
        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 *(u1 - u)*(u1 - u);
        //找出最大类间方差以及对应的阈值
        if(deltaTmp > deltaMax)
          
             deltaMax = deltaTmp;
             threshold = i;
        
    
    //返回最佳阈值;
    return threshold;

//-----------------------------------------------------------------------
voidCImageProcessDoc::OnImageprocessingThreshold()

    // TODO: Add your command handler code here
    IplImage* img;
    img=m_image.GetImage();//由CImage类 返回一个IplImage* 指针,因为:IplImage*GetImage()  return m_img; ;
    IplImage* imgray =cvCreateImage(cvGetSize(img), 8, 1);
    cvCvtColor(img, imgray, CV_RGB2GRAY);
    IplImage* biImage =cvCreateImage(cvGetSize(imgray),8,1);
 
    //计算最佳阈值
    threshold = OtsuThreshold(imgray);
 
    AdjustThresholdDlg at;
    at.DoModal();
 
    //对图像二值化
    cvThreshold(imgray,biImage,threshold,255,CV_THRESH_BINARY);
    m_image.CopyOf(biImage, 1);
    UpdateAllViews(NULL);
 

 


PS:

Opencv1.0在VS2010中的配置:

参考如下网址:http://www.cnblogs.com/etsang/p/3165184.html


 

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于基于MFC和OpenCV的图像处理小软件的主要内容,如果未能解决你的问题,请参考以下文章

基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)

基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)

OpenCV与MFC实战之图像处理 样本采集小工具制作 c++MFC课程设计

基于SocketOpenCV和MFC实现的网络实时视频监控

基于MFC 对话框的 PCLVTK OPENCV岩体识别系统构建

如何使用线程通过 openCV 和 MFC 处理图像