YCrCb颜色空间与肤色检测

YCrCb也称为YUV,主要用于优化彩色视频信号的传输。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。
其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;
而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。

YCrCb颜色空间在做肤色检测上有很好的效果,比HSV颜色空间要好一些
查阅一些网上的资料得知,正常黄种人的Cr分量大约在140 ~ 175之间,Cb分量大约在100 ~ 120之间。

OpenCV中RGB转YCrCb的函数:
cvtColor(inputImage, outputImage, CV_BGR2YCrCb);

效果如下:


对比.JPG

这个受光线环境的影响还是挺大的,并不是特别完美的算法。当然可能还要加点滤波程序,比如中值滤波什么的,效果更好一些

代码如下:

#include "stdafx.h"  
#include   
#include   

#include   
#include   
#include   
#include   
#include   

using namespace std;
using namespace cv;

extern int ex;

vector get_YCrCb(Mat image);

int main()
{
    VideoCapture cap(0);

    if (!cap.isOpened())
    {
        cout << endl << "没有检测到摄像头" << endl;
        return -1;
    }
    namedWindow("result");
    namedWindow("frame");
    Mat frame, tmp;
    Mat result;
    Mat Y, Cr, Cb;
    vector channels;
    bool stop = false;
    while (!stop)
    {

        cap >> frame;                     //读取视频帧  
        frame.copyTo(tmp);          
                
        channels=get_YCrCb(tmp); //转换颜色空间并分割颜色通道
        Y = channels.at(0);
        Cr = channels.at(1);
        Cb = channels.at(2);


        //初始化Mat类型的变量 result
        result.create(frame.rows, frame.cols, CV_8UC1); //CV_8UC1为单通道类型

        //遍历图像,将符合阈值范围的像素设置为255,其余为0
        for (int j = 1; j < Y.rows - 1; j++)
        {      //ptr< uchar>(j)[i]是第j行的第i个元素,也就是j行i列的像素点
            uchar* currentCr = Cr.ptr< uchar>(j);  
            uchar* currentCb = Cb.ptr< uchar>(j);
            uchar* current = result.ptr< uchar>(j);
            for (int i = 1; i < Y.cols - 1; i++)
            {
                if ((currentCr[i] > 137) && (currentCr[i] < 175) && (currentCb[i] > 100) && (currentCb[i] < 118))
                    current[i] = 255; //满足条件为白
                else
                    current[i] = 0; //否则为黑
            }
        }


/*
        void cv::putText(
            cv::Mat& img, // 待绘制的图像  
            const string& text, // 待绘制的文字  
            cv::Point origin, // 文本框的左下角  
            int fontFace, // 字体 (如cv::FONT_HERSHEY_PLAIN)  
            double fontScale, // 尺寸因子,值越大文字越大  
            cv::Scalar color, // 线条的颜色(RGB)  
            int thickness = 1, // 线条宽度  
            int lineType = 8, // 线型(4邻域或8邻域,默认8邻域)  
            bool bottomLeftOrigin = false // true='origin at lower left'  
        );*/
        string text = "Press ESC to exit";
        putText(frame, text, Point(frame.cols / 2, frame.rows / 2), FONT_HERSHEY_PLAIN, 2, Scalar(0, 255, 255), 2, 8, 0);

        imshow("frame", frame);
        imshow("result", result);



        if (waitKey(30) == 27)
            break;
        
    }

    return 0;
}


vector get_YCrCb(Mat image) { //转换颜色空间并分割颜色通道
    vector threeChannels;

    cvtColor(image, image, CV_BGR2YCrCb);
    split(image, threeChannels);

    return threeChannels;
}

你可能感兴趣的:(YCrCb颜色空间与肤色检测)