数字图像处理(2) — 基于VC++环境的人脸美颜软件

开发环境:

VS2012+MFC+Opencv2.4.9

实验目的:

利用VC++实现人脸美化软件,要求:
1、具有人脸美化界面;
2、具有磨皮功能,参数可调;
3、具有美白功能,参数可调;

实验原理:

磨皮:滤波(均值滤波、高斯滤波、双边滤波)
融合:使用高反差保留进行图像融合
美白:使用图像增强—非掩蔽锐化

界面展示:

在这里插入图片描述

加载原始图片效果


在这里插入图片描述

磨皮效果


在这里插入图片描述

融合效果


在这里插入图片描述

美白效果


界面功能说明

在这里插入图片描述
控件类型:
MFCbutton:用于实现美颜软件的对应功能,该类型控件相比普通Button,可添加自定义背景图片。
Slider Ctrl:滑动条控件,用于控制美颜功能的参数效果。
Picture Ctrl:用于显示图像处理结果,本实验中添加了部分代码以实现自适应控件大小的效果。


程序流程图:

在这里插入图片描述

界面设计效果:

在这里插入图片描述
这里介绍一下如何给MFC Button添加背景图片
1.在资源管理器下的资源文件文件夹下找到“xxxx.rc”文件,双击打开。
在这里插入图片描述
2.右键Bitmap文件夹,选择“添加资源”,再选择“导入”,添加自定义的图片文件。
在这里插入图片描述
在这里插入图片描述
3.添加完成后,返回设计界面,在MFC Button控件属性下,指定上一步导入图片的标识符。
在这里插入图片描述

部分关键代码:

调用OpenCv库文件(这里我放在了"stdafx.h"文件下,也可以直接在xxxDlg.cpp文件下声明):

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>
#include<opencv2\opencv.hpp>

声明命名空间(如果不声明,在代码中使用OpenCv库函数时,需在前面添加"cv::")

using namespace cv;
using namespace std;

美白算法函数(由于时间关系,所以使用的这个算法效果比较一般,后续会尝试重写一下)

void light(Mat& srcImg,int alpha, int beta)
{
	for (int y = 0; y < srcImg.rows; y++)
	{
		for (int x = 0; x < srcImg.cols; x++)
		{
			for (int c = 0; c < 3; c++)
			{
				srcImg.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha*(srcImg.at<Vec3b>(y, x)[c]) + beta-50);
			}
		}
	}
}

在xxxDlg.cpp文件自动生成的OnInitDialog()函数下,添加以下代码以实现图片自适应控件大小的效果
其中IDC_ShowImg指向Picture Ctrl控件名称。

	namedWindow("view",WINDOW_AUTOSIZE);
	HWND hWnd = (HWND) cvGetWindowHandle("view");
	HWND hParent = ::GetParent(hWnd);
	::SetParent(hWnd, GetDlgItem(IDC_ShowImg1)->m_hWnd);
	::ShowWindow(hParent, SW_HIDE);

同样在OnInitDialog()函数下添加以下代码,实现设定滑动条控件范围和初始位置的效果。

	m_slider.SetRange(0,100);
	m_slider.SetPos(50);

在OnInitDialog()函数下添加以下代码,实现修改控件颜色和字体的效果

	m_font.CreatePointFont(120,"黑体");
	m_brush.CreateSolidBrush(RGB(0,255,0));
	number.SetFont(&m_font);
	m_btn1.SetFaceColor(RGB(0,0,0));
	m_btn2.SetFaceColor(RGB(0,0,0));
	m_btn3.SetFaceColor(RGB(0,0,0));
	m_btn4.SetFaceColor(RGB(0,0,0));
	m_btn5.SetFaceColor(RGB(0,0,0));
	m_btn6.SetFaceColor(RGB(0,0,0));

磨皮算法关键代码

void C人脸美颜软件Dlg::OnBnClickedButton3()
{
	/***********************声明变量**********************/
	Mat imagedst1;
	Mat imagedst2;
	/***********************磨皮处理**********************/
	int scale1 = m_slider.GetPos();
	input_image.copyTo(src);
	blur(src,imagedst1, Size(3, 3));									//均值滤波
	GaussianBlur(imagedst1, imagedst2, Size(3, 3), 0);					//高斯滤波
	bilateralFilter(imagedst2, dst1, (int)scale1*0.3, scale1, scale1);	//双边滤波
	/***********************显示结果**********************/
	CRect rect;  
	GetDlgItem(IDC_ShowImg1)->GetClientRect(&rect);  
	Rect dst(rect.left,rect.top,rect.right,rect.bottom);  
	resize(dst1,output_image,cv::Size(rect.Width(),rect.Height())); 
	index = 1;
	imshow("view", output_image);
}

融合算法关键代码

void C人脸美颜软件Dlg::OnBnClickedButton4()
{
	/***********************磨皮处理**********************/
	int scale1 = m_slider.GetPos();
	input_image.copyTo(dstI);
	dst1.copyTo(dstF);
	bilateralFilter(dstI, dstF, 10, 80, 80);		//双边滤波
	dstH=dstF-dstI+128;
	GaussianBlur(dstH, dstY, Size(5,5),0,0,0);		//高斯滤波得到Y 
	float OP=(float)(scale1*0.01);
	dstZ=dstI+(2*dstY-256)*OP;
	/***********************显示结果**********************/
	CRect rect;  
	GetDlgItem(IDC_ShowImg1)->GetClientRect(&rect);  
	Rect dst(rect.left,rect.top,rect.right,rect.bottom);  
	resize(dstZ,output_image,cv::Size(rect.Width(),rect.Height())); 
	imshow("view", output_image);
	index = 2;
}

美白算法关键代码

void C人脸美颜软件Dlg::OnBnClickedButton5()
{
	/***********************美白处理**********************/
	int scale1 = m_slider.GetPos();
	dstZ.copyTo(matResult);
	light(matResult, 1, scale1);  // 调整对比度与亮度,参数3为对比度,参数4为亮度 
	// 图像增强,使用非锐化掩蔽(Unsharpening Mask)方案。
	GaussianBlur(matResult, matFinal, cv::Size(0, 0), 9);
	addWeighted(matResult, 1.5, matFinal, -0.5, 0, matFinal);
	/***********************显示结果**********************/
	CRect rect;  
	GetDlgItem(IDC_ShowImg1)->GetClientRect(&rect);  
	Rect dst(rect.left,rect.top,rect.right,rect.bottom);  
	resize(matFinal,output_image,cv::Size(rect.Width(),rect.Height())); 
	imshow("view", output_image);
	index =3;
	// TODO: 在此添加控件通知处理程序代码
}

读取图片关键代码

void C人脸美颜软件Dlg::OnBnClickedMfcbutton8()
{
	// TODO: 在此添加控件通知处理程序代码
			CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT, 
		NULL, this);   
	if(dlg.DoModal() == IDOK)
	{
		picPath= dlg.GetPathName(); 
	}
	picpath=picPath.GetBuffer(0); 
	input_image = imread(picpath);	
	
	Mat imagedst;					
	CRect rect;
	GetDlgItem(IDC_ShowImg1)->GetClientRect(&rect);
	Rect dst(rect.left,rect.top,rect.right,rect.bottom);
	resize(input_image,imagedst,cv::Size(rect.Width(),rect.Height())); 
	imshow("view",imagedst);
}

保存图片关键代码

void C人脸美颜软件Dlg::OnBnClickedMfcbutton4()
{
	// TODO: 在此添加控件通知处理程序代码
		TCHAR szFilter[] = _T("JPG图片(*.jpg)|*.jpg|BMP图片(*.bmp)|*.bmp|PNG图片(*.png)|*.png|JPEG图片(*.jpeg)|*.jpeg|DIB图片(*dib)|*.dib|PBM图片(*.pbm)|*.pbm||");  
    CFileDialog fileDlg(FALSE, _T("jpg"), _T("New"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this);
    CString strFilePath;
    if (IDOK == fileDlg.DoModal())
    { 
        strFilePath = fileDlg.GetPathName();
    }
    vector<int> compression_params;
    string STDStr(CT2A(strFilePath.GetString()));
	imwrite(STDStr, output_image, compression_params);
}

滑动条处理事件关键代码(将滑动条位置的具体参数显示在界面中)

void C人脸美颜软件Dlg::OnNMCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult)		//滑动条处理事件
{

	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	//@TN
	CString str;
	str.Format("%d",m_slider.GetPos());
	GetDlgItem(IDC_ShowNum)->SetWindowTextA(str);

		//*pResult = 0;
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
}

界面优化部分代码(在MFC自动生成的OnCtlColor函数下编写,主要功能是修改部分控件的字体颜色和背景色,如静态文本和滑动条)

HBRUSH C人脸美颜软件Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	if(pWnd->GetDlgCtrlID() == IDC_ShowNum)
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor(RGB(0,0,0));

	}
	if(pWnd->GetDlgCtrlID() == IDC_mopi)
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor(RGB(0,0,0));

	}
	if(pWnd->GetDlgCtrlID() == IDC_rh)
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor(RGB(0,0,0));

	}
	if(pWnd->GetDlgCtrlID() == IDC_mb)
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor(RGB(0,0,0));

	}

	CRect ctrlRect;
	pWnd->GetClientRect(&ctrlRect);
	switch (pWnd->GetDlgCtrlID())
	{
		case IDC_SLIDER1:
		CBrush mybrush(RGB(0,0,0));
		pDC->FillRect(ctrlRect,&mybrush);
		mybrush.DeleteObject();
		pDC->SetBkMode(TRANSPARENT);
		hbr=(HBRUSH)GetStockObject(NULL_BRUSH); 
		break;
	}

	return hbr;


	// TODO:  在此更改 DC 的任何特性


	// TODO:  如果默认的不是所需画笔,则返回另一个画笔

}

部分全局变量声明(因为不是重点,所以放在最后)

String picpath;
CString picPath;   //定义图片路径变量

int index=0;

CBrush m_brush;
CFont m_font;

Mat input_image;
Mat output_image;
Mat mopi_image;
Mat src;
Mat imagedst1;
Mat imagedst2;
Mat dst1,dst2,dst1src;
Mat dst3(mopi_image.size(),CV_8UC3); //融合后的RGB三通道
Mat dstI,dstF,dstH,dstY,dstZ;
Mat matResult;
Mat matFinal;

心得体会:

这次大作业大概花了两周时间完成,在此之前并没有接触过MFC编程,所以很多代码都是参考上一届学长的博客,博客地址如下所示,在他的基础上改进了融合算法的效果,并对界面进行了优化。起初是想做一个类似美颜相机的效果,能够通过摄像头采集图像,但是对于OpenCv这方面知识的了解太少,所以只能作罢。
【图像处理】基于VC++的人脸美化的实现实践篇(含代码)
个人感觉本次大作业的难点在于OpenCV环境的配置,还有美白算法的编写。因为那段时间我在公司实习,用的是VS2019,在配置环境的时候遇到不少麻烦,所以最后改用旧电脑完成,具体配置方式可以参考我之前的博客。
OpenCV环境配置
至于美白算法,其实起初老师的PPT给出了一套实现方案,具体流程如下图所示,但是自己写到最后发现难度有点大,所以临时找了网上一套现成的方案,如果有空的话再去完善一下。
总体来说,用MFC开发图像处理的相关软件有点low,建议用C#的WinForm实现。
在这里插入图片描述
在这里插入图片描述

代码工程下载地址:

链接:
https://pan.baidu.com/s/1Q7bVtF5G5cAXuj1_7YhJHQ
提取码:4cp4

  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值