opencv实时皮肤检测美颜相机

#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;

}
posted @ 2021-10-28 21:18  Night_Voyager-qaq  阅读(219)  评论(0)    收藏  举报
Live2D