opencv实现人像优化


简介

  本篇是使用opencv,简单实现人像优化功能:美白、肤色、祛斑和磨皮。注:本篇所使用的图片来源自网络。

具体实现

总体框架

  1、使用到了之前教程中的opencv实现button控件,每个功能,对应一个控件选择,然后都分别使用一个Trackbar,来手动控制,对图片处理的强度。
首先打开两幅图片,一张是作为操作选项的背景图片img,另一张是我们需要处理的图片dst_img,接着在在img显示窗口上,进行button的初始化
ButtonShow操作。最后分别对背景图片img和操作图片dst_img绑定了鼠标操作函数,同时,当用户按下键值之后,就直接退出程序。
int main(int argc,char **argv){
	if(argc < 2){
		printf("Please input picture!!\n");
		return -1;	
	}
	memcpy(pic_name, argv[1], sizeof(argv[1]));
	img = imread(back_name,1);
	dst_img = imread(pic_name,1);
	imwrite(tmpPic, dst_img);
 
	ButtonShow();
	imshow(back_show, img);
	imshow(pic_show, dst_img);
	cvSetMouseCallback(back_show, on_mouse, NULL);
	cvSetMouseCallback(pic_show, pic_mouse, NULL);
	waitKey();
}

button响应

  鼠标点击button位置,响应对应的button操作,在之前的教程中已经讲过,这里不细讲了。主要看下,button被选择之后的具体响应操作。
首先需要注意:buttonFlag[buttonNum]用来保存button的当前状态,当某个button被选中之后,对应的buttonFlag被置为true,其他则被置为false。
在buttong响应函数on_button中,设置了当前button的选择状态。接着为对应选择的button创建了对应的Trackbar,Trackbar相关的初始化参数保存在
facePara中,同时关联好了,对应button功能被选择之后的操作函数:xxx_trackbar。
void on_button(int buttonNow, Mat dst_img){
	int i;
	char str[20];
 
	for(i=0; i<buttonNum; i++){
		if(i == buttonNow){
			buttonFlag[i] = true;
		}else{
			buttonFlag[i] = false;	
		}
	}
	switch(buttonNow){
		case 0:
			createTrackbar(buttonName[buttonNow], back_show, &facePara[buttonNow][0], facePara[buttonNow][1], dermabrasion_trackbar);
			break;
		case 1:
			createTrackbar(buttonName[buttonNow], back_show, &facePara[buttonNow][0], facePara[buttonNow][1], Whitening_trackbar);
			break;
		case 2:
			createTrackbar(buttonName[buttonNow], back_show, &facePara[buttonNow][0], facePara[buttonNow][1], complexion_trackbar);
			break;
		case 3:
			createTrackbar(buttonName[buttonNow], back_show, &facePara[buttonNow][0], facePara[buttonNow][1], qudou_trackbar);
			break;
		default:
			break;
	}
}

磨皮

  使用的方式很简单,就是直接对当前图像,使用cvSmooth做轻微的模糊处理。
void dermabrasion_trackbar(int pos, void *){
	dst_img = imread(tmpPic, 1);
	IplImage pI_1 = dst_img, pI_2; 
	CvScalar s1;
	int width = dst_img.rows;
	int height = dst_img.cols;	
	Mat src2 = cv::Mat(width, height, CV_8UC3, 1);
 
	pI_2 = src2;
	if(facePara[0][0]%2 ==0){
		facePara[0][0] += 1;
	}
	cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, facePara[0][0]);
 
	imwrite(tmpPic, src2);
	imshow(pic_show, src2);
}

美白

  直接根据用户拖动trackbar的强度facePara[1][0],来直接对图片增加亮度,进而改变皮肤的美白程度。
void Whitening_trackbar(int pos, void *){
	dst_img = imread(tmpPic, 1);
	IplImage pI_1 = dst_img;
	CvScalar s1;
	int light_now;
	int i, j;
	int width = dst_img.rows;
	int height = dst_img.cols;
 
	if(faceParaTmp[1] == -100){
		light_now = facePara[1][0] - 30;
		faceParaTmp[1] = facePara[1][0];
	}else{
		light_now = facePara[1][0] - faceParaTmp[1];
		faceParaTmp[1] = facePara[1][0];
	}
 
	for(i=0; i<width; i++){
		for(j=0; j<height; j++){
			s1 = cvGet2D(&pI_1, i, j);
			s1.val[0] = s1.val[0] + light_now;
			s1.val[1] = s1.val[1] + light_now;
			s1.val[2] = s1.val[2] + light_now;
			cvSet2D(&pI_1, i, j, s1);
		}
	}
	imwrite(tmpPic, dst_img);
	imshow(pic_show, dst_img);
}

肤色

  直接根据用户拖动trackbar的强度facePara[2][0],来直接对图片增减亮度,进而改变肤色的红润。
void complexion_trackbar(int pos, void *){
	dst_img = imread(tmpPic, 1);
	IplImage pI_1 = dst_img;
	CvScalar s1;
	int R_now;
	int i, j;
	int width = dst_img.rows;
	int height = dst_img.cols;
 
	if(faceParaTmp[2] == -100){
		R_now = facePara[2][0] - 15;
		faceParaTmp[2] = facePara[2][0];
	}else{
		R_now = facePara[2][0] - faceParaTmp[2];
		faceParaTmp[2] = facePara[2][0];
	}
	for(i=0; i<width; i++){
		for(j=0; j<height; j++){
			s1 = cvGet2D(&pI_1, i, j);
			s1.val[2] = s1.val[2] + (R_now * 2);
			cvSet2D(&pI_1, i, j, s1);
		}
	}
	imwrite(tmpPic, dst_img);                                                                                                        
	imshow(pic_show, dst_img);
}

祛斑

  这一步的实现和前面几步有些区别,这里使用到了前面教程:图像复原中使用的函数inpaint,来去除掉选中的斑点。
    1、首先是在button中选中:qudou。
    2、接着鼠标在目标图片上左键按下移动的时候,鼠标上会有一个小圆圈提示,把小圆圈移动到需要去除掉斑点的位置,放开鼠标左键。函数inpaint
便会开始根据小圆圈进行修复。
void doDermabrasion(Mat dst, int x, int y){
	Mat mat1;
	int width = dst.rows;  
	int height = dst.cols;
	mat1 = cv::Mat(width, height, CV_8UC1, cv::Scalar(0, 0, 0));
	circle(dst, Point(x, y), facePara[3][0], Scalar(100, 100, 100), -1);
	circle(mat1, Point(x, y), facePara[3][0], Scalar(255, 255, 255), -1);
	inpaint(dst, mat1, dst, 1, CV_INPAINT_TELEA);
}
 
void pic_mouse( int event, int x, int y, int flags, void* ustc){
	if(buttonFlag[3]){
		if(event == CV_EVENT_LBUTTONDOWN){
			flag_mouse = true;
			dst_img = imread(tmpPic, 1);
			circle(dst_img, Point(x, y), facePara[3][0], Scalar(100, 100, 100), -1);
			imshow(pic_show, dst_img);
		}else if(event == CV_EVENT_LBUTTONUP){
			flag_mouse = false;
			dst_img = imread(tmpPic, 1);
			doDermabrasion(dst_img, x, y);
			imshow(pic_show, dst_img);
			imwrite(tmpPic, dst_img);
		}else if((event == CV_EVENT_MOUSEMOVE) && (flag_mouse)){
			dst_img = imread(tmpPic, 1);
			circle(dst_img, Point(x, y), facePara[3][0], Scalar(100, 100, 100), -1);
			imshow(pic_show, dst_img);
		}
	}
}

效果演示

  对应的效果演示如下:
    优化前:
        
    优化后:
        

代码下载

     现在路径:http://download.csdn.net/detail/u011630458/8754741