用MFC写的OpenCV小程序(2)

添加功能



接着上一篇,加入其它功能。

如图:


按照之前的添加方法,为每个Button添加如下代码:

之前的代码也有所改动:


在XxxDlg.h中添加:



添加的代码:

#include "cv.h"
#include "highgui.h"
#include "CvvImage.h"
#include <iostream>

using namespace std;

//为人脸检测功能添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
 
#ifdef _EiC
#define WIN32
#endif

static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;

需要手工添加的函数:



//添加声明
	void DrawPicToHDC(IplImage * img , UINT ID);
	// 读图像
	IplImage * ReadImage();
	// 将图像转为灰度图像
	IplImage * ImageGray();
	//人脸检测
	IplImage * detect_and_draw( IplImage* img );


在XxxDlg.cpp中,添加的代码有。

//添加代码
void CImageDemo1Dlg::DrawPicToHDC(IplImage *img, UINT ID)
{
	CDC *pDC = GetDlgItem(ID)->GetDC();
	HDC hDC= pDC->GetSafeHdc();
	CRect rect;
	GetDlgItem(ID)->GetClientRect(&rect);
	CvvImage cimg;
	cimg.CopyOf( img ); // 复制图片
	cimg.DrawToHDC( hDC, &rect ); // 将图片绘制到显示控件的指定区域内
	ReleaseDC( pDC );
}
//与上篇不同,这里将读图单独写为一个函数,以便之后的使用
IplImage * CImageDemo1Dlg::ReadImage()
{
	IplImage *img=NULL; //原始图像
	if(img) cvReleaseImage(&img);
	img = cvLoadImage("lena.jpg",1); //显示图片
	return img;
}

void CImageDemo1Dlg::OnBnClickedBopen()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage *img=NULL; //原始图像
	//if(img) cvReleaseImage(&img);
	//img = cvLoadImage("lena.jpg",1); //显示图片
	img = ReadImage();
	DrawPicToHDC(img, IDC_STATIC);  
	cvReleaseImage(&img);

}

//对图像做高斯平滑处理
void CImageDemo1Dlg::OnBnClickedBsmooth()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * out = NULL;
	out = ReadImage();
	cvSmooth(out,out,CV_GAUSSIAN, 7,7);
	DrawPicToHDC(out, IDC_STATIC); 
	cvReleaseImage(&out);
}


// 膨胀
void CImageDemo1Dlg::OnBnClickedBerode()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * out = NULL;
	out = ReadImage();
	cvErode(out,out,0,1);
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
}

// 腐蚀
void CImageDemo1Dlg::OnBnClickedBdilate()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * out = NULL;
	out = ReadImage();
	cvDilate(out,out,0,1);
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
}

// 自适应阈值化
void CImageDemo1Dlg::OnBnClickedBthreshold()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * Igray = ImageGray();
	cvAdaptiveThreshold(Igray, Igray, 255, 
		CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 3, 5);
	DrawPicToHDC(Igray, IDC_STATIC);
	cvReleaseImage(&Igray);
}


// Sobel 导数
void CImageDemo1Dlg::OnBnClickedBsobel()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * out = NULL;
	out = ReadImage();
	cvSobel(out,out,0,1,3);
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
}

// 拉普拉斯
void CImageDemo1Dlg::OnBnClickedBlaplace()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * out = NULL;
	out = ReadImage();
	cvLaplace(out,out,7);
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
}

// canny算子
void CImageDemo1Dlg::OnBnClickedBcanny()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	IplImage* out = cvCreateImage(  
        cvGetSize(img),IPL_DEPTH_8U,  
        1); // Canny只接受单通道图像  
	cvCanny(img, out, 50, 150, 3);
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
	cvReleaseImage(&img);
}

// 图像卷积
void CImageDemo1Dlg::OnBnClickedBfilter()
{
	// TODO: 在此添加控件通知处理程序代码
	float ke[9] = {1.0, -2.0, 1.0,  
                  2.0, -4.0, 2.0,  
                  1.0, -2.0, 1.0  
            };  
    CvMat km;  
    km = cvMat(3,3, CV_32FC1,ke); 
	IplImage * out = ReadImage();
    cvFilter2D(out, out, &km, cvPoint(-1,-1));
	DrawPicToHDC(out, IDC_STATIC);
	cvReleaseImage(&out);
}

//直方图均衡化
void CImageDemo1Dlg::OnBnClickedBequalhist()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	int i;  
    IplImage* pImageChannel[4] = {0, 0, 0, 0};  
    IplImage* pImage = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);  
    for(i = 0; i < img->nChannels; i++)  
    {  
        pImageChannel[i] = cvCreateImage(cvGetSize(img), img->depth,1);  
    }  
    //信道分离  
    cvSplit(img, pImageChannel[0], pImageChannel[1], pImageChannel[2],pImageChannel[3]);  
    for(i = 0; i<pImage->nChannels; i++)  
    {  
        //直方图均衡化  
        cvEqualizeHist(pImageChannel[i], pImageChannel[i]);  
    }  
    //信道组合  
    cvMerge(pImageChannel[0],pImageChannel[1], pImageChannel[2],pImageChannel[3], pImage);  
      
    // 释放资源  
    for( i = 0; i < img->nChannels; i++ )  
    {  
        if ( pImageChannel[i] )  
        {  
            cvReleaseImage( &pImageChannel[i] );  
            pImageChannel[i] = 0;  
        }  
    }
	//
	DrawPicToHDC(pImage, IDC_STATIC);
}

// 输出彩色图像的直方图
void CImageDemo1Dlg::OnBnClickedBhist()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	IplImage* hsv = cvCreateImage(cvGetSize(img), 8, 3);  
      
    IplImage* h_plane = cvCreateImage(cvGetSize(img), 8, 1);  
    IplImage* s_plane = cvCreateImage(cvGetSize(img), 8, 1);  
    IplImage* v_plane = cvCreateImage(cvGetSize(img), 8, 1);  
    IplImage* planes[] = {h_plane, s_plane};  
  
    int h_bins = 16,s_bins = 8;  
    int hist_size[] = {h_bins, s_bins};  
      
    // H分量的变化范围  
    float h_ranges[] = {0,180};  
    // S分量的变化范围  
    float s_ranges[] = {0,255};  
    float* ranges[] = {h_ranges, s_ranges};  
      
    //将图像转换到HSV颜色空间  
    cvCvtColor(img,hsv, CV_BGR2HSV);  
    cvCvtPixToPlane(hsv, h_plane, s_plane, v_plane, 0);  
  
    //创建直方图  
    CvHistogram* hist = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);  
    // 根据H,S两个平面数据统计直方图  
    cvCalcHist(planes,hist, 0,0);  
  
    //获取直方图统计的最大值和最小值,用于动态显示直方图  
    float max_value;  
    cvGetMinMaxHistValue(hist, 0, &max_value, 0, 0);  
  
    //设置直方图显示图像  
    int height = 240;  
    int width = (h_bins*s_bins*6);  
    IplImage* hist_img = cvCreateImage(cvSize(width, height), 8, 3);  
    cvZero(hist_img);  
  
    //用来进行HSV到RGB颜色转换的临时图像  
    IplImage* hsv_color = cvCreateImage(cvSize(1,1), 8,3);  
    IplImage* rgb_color = cvCreateImage(cvSize(1,1), 8, 3);  
    int bin_w = width/(h_bins*s_bins);  
    for(int h = 0; h < h_bins; h++)  
    {  
        for(int s = 0; s < s_bins; s++)  
        {  
            int i = h*s_bins+s;  
            //获得直方图中的统计次数,计算显示在图中的高度  
            float bin_val = cvQueryHistValue_2D(hist, h, s);  
            int intensity = cvRound(bin_val*height/max_value);  
  
            //获取当前直方图代表的颜色,转换成RGB用于绘制  
            cvSet2D(hsv_color, 0, 0, cvScalar(h*180.f/h_bins, s*255.f/s_bins, 255,0));  
            cvCvtColor(hsv_color, rgb_color,CV_HSV2BGR);  
            CvScalar color = cvGet2D(rgb_color, 0, 0);  
  
            cvRectangle(hist_img, cvPoint(i*bin_w, height),  
                cvPoint((i+1)*bin_w, height - intensity),   
                color, -1, 8, 0);  
        }  
    } 
	//
	DrawPicToHDC(hist_img, IDC_STATIC);
	cvReleaseImage(&img);
	cvReleaseImage(&hsv);
	cvReleaseImage(&h_plane);
	cvReleaseImage(&s_plane);
	cvReleaseImage(&v_plane);
	cvReleaseImage(&hsv_color);
	cvReleaseImage(&rgb_color);
	cvReleaseImage(&hist_img);
}

// 将图像转换为灰度图像
IplImage * CImageDemo1Dlg::ImageGray()
{
	IplImage * img = ReadImage();
	IplImage * Igray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvCvtColor(img, Igray, CV_RGB2GRAY);
	cvReleaseImage(&img);
	return Igray;
}

// 输出灰度图像
void CImageDemo1Dlg::OnBnClickedBgray()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * Igray = ImageGray();
	DrawPicToHDC(Igray, IDC_STATIC);
}

// 透视变换
void CImageDemo1Dlg::OnBnClickedBperspective()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	CvPoint2D32f srcQuad[4], dstQuad[4];  
    CvMat* warp_matrix = cvCreateMat(3,3, CV_32FC1);  
    IplImage *dst;  
    dst = cvCloneImage(img);  
    dst->origin = img->origin;  
    cvZero(dst);  
    srcQuad[0].x = 0;  
    srcQuad[0].y = 0;  
    srcQuad[1].x = img->width -1;  
    srcQuad[1].y = 0;  
    srcQuad[2].x = 0;  
    srcQuad[2].y = img->height -1;  
    srcQuad[3].x = img->width -1;  
    srcQuad[3].y = img->height -1;  
  
    dstQuad[0].x = img->width*0.05;  
    dstQuad[0].y = img->height*0.33;  
    dstQuad[1].x = img->width*0.9;  
    dstQuad[1].y = img->height*0.25;  
    dstQuad[2].x = img->width*0.2;  
    dstQuad[2].y = img->height*0.7;  
    dstQuad[3].x = img->width*0.8;  
    dstQuad[3].y = img->height*0.9;  
  
    cvGetPerspectiveTransform(  
        srcQuad,   
        dstQuad,  
        warp_matrix  
        );  
    cvWarpPerspective(img, dst, warp_matrix);  
	//
	DrawPicToHDC(dst, IDC_STATIC);
	cvReleaseImage(&dst);
}


// 仿射变换
void CImageDemo1Dlg::OnBnClickedBaffine()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	CvPoint2D32f srcTri[3], dstTri[3];  
    CvMat* rot_mat = cvCreateMat(2,3, CV_32FC1);  
    CvMat* warp_mat = cvCreateMat(2,3,CV_32FC1);  
  
    IplImage* dst = cvCloneImage(img);  
    dst->origin = img->origin;  
    cvZero(dst);  
    srcTri[0].x = 0;  
    srcTri[0].y = 0;  
    srcTri[1].x = img->width-1;  
    srcTri[1].y = 0;  
    srcTri[2].x = 0;  
    srcTri[2].y = img->height-1;  
  
    dstTri[0].x = img->width * 0.0;  
    dstTri[0].y = img->height * 0.33;  
    dstTri[1].x = img->width * 0.85;  
    dstTri[1].y = img->height * 0.25;  
    dstTri[2].x = img->width * 0.15;  
    dstTri[2].y = img->height * 0.7;  
  
    cvGetAffineTransform(srcTri, dstTri, warp_mat);   // 计算仿射矩阵  
    cvWarpAffine(img, dst, warp_mat);  
    cvCopy(dst, img);  
  
    // 计算旋转矩阵  
    CvPoint2D32f center = cvPoint2D32f(  
        img ->width/2,  
        img ->height/2  
        );  
    double angle = -50.0;  
    double scale = 0.6;  
    cv2DRotationMatrix(center, angle, scale, rot_mat);  
    cvWarpAffine(img, dst, rot_mat); 
	//
	DrawPicToHDC(dst, IDC_STATIC);
	cvReleaseImage(&dst);

}

//霍夫线变换
void CImageDemo1Dlg::OnBnClickedBhoughline()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	IplImage* dst = cvCreateImage(cvGetSize(img), 8, 1);  
    IplImage* color_dst = cvCreateImage(cvGetSize(img), 8, 3);  
    CvMemStorage* storage = cvCreateMemStorage(0);  
    CvSeq* lines = 0;  
    cvCanny(img, dst, 50, 200, 3);  
    cvCvtColor(dst, color_dst, CV_GRAY2BGR);  
    lines = cvHoughLines2(dst, storage, CV_HOUGH_PROBABILISTIC,1, CV_PI/180,80,30,10);  
    int i;  
    for(i = 0; i<lines->total; i++)  
    {  
        CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);  
        cvLine(color_dst, line[0], line[1], CV_RGB(255,0,0), 3, 8);  
    }
	//
	DrawPicToHDC(color_dst, IDC_STATIC);
	cvReleaseImage(&dst);
	cvReleaseImage(&color_dst);
}



void CImageDemo1Dlg::OnBnClickedBhoughcircles()
{
	// TODO: 在此添加控件通知处理程序代码
	IplImage * img = ReadImage();
	IplImage* dst = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);  
    cvCvtColor(img,dst,CV_RGB2GRAY);  
    CvMemStorage* storage = cvCreateMemStorage(0);  
    cvSmooth(dst,dst,CV_GAUSSIAN, 5,5);  
    CvSeq* circle = cvHoughCircles(dst, storage, CV_HOUGH_GRADIENT, 2, img->width/10);  
  
    for(int i = 0; i < circle->total; i++)  
    {  
        float* p = (float*) cvGetSeqElem(circle, i);  
        CvPoint pt = cvPoint(cvRound(p[0]), cvRound(p[1]));  
        cvCircle(dst, pt, cvRound(p[2]), CV_RGB(255,255,255));  
    }  
	//
	DrawPicToHDC(dst, IDC_STATIC);
	cvReleaseImage(&dst);
}


// 关闭窗口
void CImageDemo1Dlg::OnBnClickedBclose()
{
	// TODO: 在此添加控件通知处理程序代码
	CImageDemo1Dlg::OnCancel();
}


//检测人脸并标记
IplImage * CImageDemo1Dlg::detect_and_draw(IplImage * img)
{
	double scale=1.2; 
    static CvScalar colors[] = { 
        {{0,0,255}},{{0,128,255}},{{0,255,255}},{{0,255,0}}, 
        {{255,128,0}},{{255,255,0}},{{255,0,0}},{{255,0,255}} 
    };//Just some pretty colors to draw with

	IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1); 
    IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1); 
    cvCvtColor(img,gray, CV_BGR2GRAY); 
    cvResize(gray, small_img, CV_INTER_LINEAR);

    cvEqualizeHist(small_img,small_img); //直方图均衡

    //Detect objects if any 
    // 
    cvClearMemStorage(storage); 
    double t = (double)cvGetTickCount(); 
    CvSeq* objects = cvHaarDetectObjects(small_img, cascade, storage, 1.1, 2, 
                               0/*CV_HAAR_DO_CANNY_PRUNING*/, 
                               cvSize(30,30));

    t = (double)cvGetTickCount() - t; 
    //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );

    //Loop through found objects and draw boxes around them 
    for(int i=0;i<(objects? objects->total:0);++i) 
    { 
        CvRect* r=(CvRect*)cvGetSeqElem(objects,i); 
        cvRectangle(img, cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), colors[i%8]); 
    } 
    for( int i = 0; i < (objects? objects->total : 0); i++ ) 
    { 
        CvRect* r = (CvRect*)cvGetSeqElem( objects, i ); 
        CvPoint center; 
        int radius; 
        center.x = cvRound((r->x + r->width*0.5)*scale); 
        center.y = cvRound((r->y + r->height*0.5)*scale); 
        radius = cvRound((r->width + r->height)*0.25*scale); 
        cvCircle( img, center, radius, colors[i%8], 3, 8, 0 ); 
    }
	//cvShowImage("result",img);
	return img;
}

// 人脸检测
const char* cascade_name =
    "haarcascade_frontalface_alt.xml";

void CImageDemo1Dlg::OnBnClickedBface()
{
	// TODO: 在此添加控件通知处理程序代码
	cascade_name = "E:\\Program Files (x86)\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml"; 
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); 
	storage = cvCreateMemStorage(0); 
	IplImage* image = ReadImage();
	
	image = detect_and_draw(image);

	DrawPicToHDC(image, IDC_STATIC);

}


测试功能如下图:

人脸检测功能



拉普拉斯算子:



自适应阈值:


直方图均衡化:



彩色图像直方图:



这里不在一一尝试。



  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值