#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
Mat ellipse_detect(Mat& src)
{
Mat img = src.clone();
Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);
//利用opencv自带的椭圆生成函数先生成一个肤色椭圆模型
ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);
Mat ycrcb_image;
Mat output_mask = Mat::zeros(img.size(), CV_8UC1);
cvtColor(img, ycrcb_image, 36); //首先转换成到YCrCb空间,CV_BGR2YCrCb=36
for (int i = 0; i < img.cols; i++) //利用椭圆皮肤模型进行皮肤检测
for (int j = 0; j < img.rows; j++)
{
Vec3b ycrcb = ycrcb_image.at<Vec3b>(j, i);
if (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0) //如果该落在皮肤模型椭圆区域内,该点就是皮肤像素点
output_mask.at<uchar>(j, i) = 255;
}
Mat detect;
img.copyTo(detect, output_mask); //返回肤色图
return detect;
}
Mat HSV_detector(Mat& src)
{
Mat hsv_image;//h色相,s饱和度,明度
int h = 0;
int s = 1;
int v = 2;
cvtColor(src, hsv_image, 40); //首先转换成到YCrCb空间,CV_BGR2HSV=40
Mat output_mask = Mat::zeros(src.size(), CV_8UC1);//8位无符号的单通道---灰度图片
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
uchar* p_mask = output_mask.ptr<uchar>(i, j);
uchar* p_src = hsv_image.ptr<uchar>(i, j);
if (p_src[h] >= 0 && p_src[h] <= 20 && p_src[s] >= 48 && p_src[v] >= 50)
{
p_mask[0] = 255;
}
}
}
Mat detect;
src.copyTo(detect, output_mask);
return detect;
}
Mat combine(Mat& src, Mat& ori)
{
Mat hsv_image;
Mat hsv_image1;
int h = 0;
int s = 1;
int v = 2;
cvtColor(src, hsv_image, 40); //首先转换成到YCrCb空间,CV_BGR2HSV=40
cvtColor(ori, hsv_image1, 40);
Mat output_mask = Mat::zeros(src.size(), CV_8UC1);
Mat output_mask1 = Mat::zeros(ori.size(), CV_8UC1);
for (int i = 0; i < ori.rows; i++)
{
for (int j = 0; j < ori.cols; j++)
{
uchar* p_mask = output_mask.ptr<uchar>(i, j);
uchar* p_src = hsv_image.ptr<uchar>(i, j);
uchar* p_mask1 = output_mask1.ptr<uchar>(i, j);
uchar* p_src1 = hsv_image1.ptr<uchar>(i, j);
if (p_src1[h] >= 0 && p_src1[h] <= 20 && p_src1[s] >= 48 && p_src1[v] >= 50)
{
p_mask[0] = p_mask1[0];
}
}
}
Mat detect;
src.copyTo(detect, output_mask);
return detect;
}
int main()
{
/*
//打开摄像头
VideoCapture cap(0);
//读取摄像头的帧
Mat matResult;
namedWindow("打开摄像头",1);//1代表autosize(自适应)
while(1)
{
Mat frame;
Mat pfframe;
Mat outframe;
//从cap中读取一帧到frame
cap>>frame;
imshow("原相机",frame);
pfframe=HSV_detector(frame);
imshow("皮肤检测",pfframe);
int bilateralFilterVal = 25; // 双边模糊系数
GaussianBlur(pfframe, pfframe, Size(3, 3), 0, 0); // 高斯模糊,消除椒盐噪声,高斯可以在平滑图像的同时保留总体灰度特征
imshow("运用高斯滤波后的效果",pfframe);
bilateralFilter(pfframe, matResult, bilateralFilterVal, 15, 15);//双边滤波用来磨皮
imshow("加上双边滤波的效果", matResult);
Mat result=frame(Rect(0,0,frame.cols,frame.rows));
Mat mask;
matResult.copyTo(mask);
matResult.copyTo(result, mask);
imshow("合成后的效果", frame);
outframe=combine(matResult,frame);
imshow("合成背景效果",outframe);
if(waitKey(1) == 27)//每一毫秒检测一次
break;
}
return 0;
*/
//图片美颜测试
Mat matResult;
Mat pfframe;
Mat frame = imread("2.jpeg");
imshow("原图", frame);
pfframe = HSV_detector(frame);
imshow("皮肤检测", pfframe);
int bilateralFilterVal = 30; // 双边模糊系数
GaussianBlur(pfframe, pfframe, Size(9, 9), 0, 0); // 高斯模糊,消除椒盐噪声,高斯可以在平滑图像的同时保留总体灰度特征
imshow("运用高斯滤波后的效果", pfframe);
bilateralFilter(pfframe, matResult, bilateralFilterVal, // 双边滤波整体磨皮
60, 15);
imshow("加上双边滤波的效果", matResult);
Mat result = frame(Rect(0, 0, frame.cols, frame.rows));
Mat mask;
matResult.copyTo(mask);
matResult.copyTo(result, mask);
imshow("合成后的效果", frame);
waitKey(0);
return 0;
}