简介
本篇是使用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