opencv实现人脸识别中过曝光人脸图片处理

基本思路:

图像处理中,最常用的颜色空间是RGB模型,常用于颜色显示和图像处理,三维坐标的模型形式,非常容易被理解。而HSV模型,是针对用户观感的一种颜色模型,侧重于色彩表示,什么颜色、深浅如何、明暗如何。将RGB转换为HSV模型,H是色彩、S是深浅, S = 0时,只有灰度、V是明暗,表示色彩的明亮程度。为解决过曝光问题,我们拟在V分量上做统计处理。

将得到的人脸图像从RGB空间转换到HSV空间,同时在HSV空间的V分量上利用局部均值直方图指标进行判定,具体实现为:先去除噪声,在V(0-255)分量人脸图像采用8*8小窗口遍历整个图像,求得该窗口里像素的均值,若此均值在区间[55,240](可适当调整)外, 则认为该局部区域为过曝光区域,以此遍历整个V分量并统计过曝光区域个数,最终除以总的遍历次数得到最终评判指标,若该指标大于预先设定的阈值则认为该人脸图像为过曝光,反之,则为正常图像。

//HSV颜色空间上图像过曝光检测,如果图像过曝光,返回过曝光值
double overExposeDetect(Mat imgMat){
    Mat hsvSpaceImage;
    Mat hsvImageVChannels; 
    vector<Mat> channels;
    double thre = 0.175; //阈值

    if (imgMat.channels() != 1)
    {
        cvtColor(imgMat, hsvSpaceImage, CV_BGR2HSV); // hsv转换
    }else
    {
        hsvSpaceImage = imgMat.clone();
    }
    split(hsvSpaceImage, channels); // 分离颜色通道
    hsvImageVChannels = channels.at(2); // 得到V通道图像
    unsigned int step = 8; // 以8*8小窗口遍历V通道图像, V通道包含亮度信息
    uchar *pt;
    int imageOverExposeBlockNum = 0;
    int imageOverExposeBlocks = 0;
    unsigned int rowTraNum = hsvImageVChannels.rows/step * step;
    unsigned int colTraNum = hsvImageVChannels.cols/step * step;
    //遍历
    for (unsigned int i = 0; i < rowTraNum; i += step)
    {
        pt = hsvImageVChannels.ptr<uchar>(i);
        for (unsigned int j = 0; j < colTraNum; j += step)
        {
            Mat imageBlock = Mat(hsvImageVChannels, Rect(j, i, step, step));

            double mea = mean(imageBlock)[0]; // 求小矩形的均值

            if (mea > 233.0 || mea < 53.0)
            {
                //imageOverExposeBlockVec.push_back(Rect(j, i, step, step));
                //cout << "Mean: " << mea << endl;
                imageOverExposeBlockNum ++;
            }
            imageOverExposeBlocks ++;
        }

    }

    return imageOverExposeBlockNum/(double)imageOverExposeBlocks * 100;  //返回一个归一化到0-100之间的值

}

此方法缺陷:有些图片 不是过曝,但是非常灰暗(即计算出阈值在17.5以下的数),此方法无法筛选出,于是在方法最后加一条判断。

bool overExposeDetect2(Mat imgMat)
{
    Mat hsvSpaceImage;
    Mat hsvImageVChannels;
    vector<Mat> channels;
    double thre = 0.175; //阈值

    if (imgMat.channels() != 1)
    {
        cvtColor(imgMat, hsvSpaceImage,CV_BGR2HSV); // hsv转换
    }else
    {
        hsvSpaceImage = imgMat.clone();
    }
    split(hsvSpaceImage, channels); // 分离颜色通道
    hsvImageVChannels = channels.at(2); // 得到V通道图像

    unsigned int step = 8; // 以8*8小窗口遍历V通道图像
    uchar *pt;  
    int imageOverExposeBlockNum = 0;
    int imageOverExposeBlocks = 0;
    unsigned int rowTraNum = hsvImageVChannels.rows/step * step;
    unsigned int colTraNum = hsvImageVChannels.cols/step * step;
    //遍历
    for (unsigned int i = 0; i < rowTraNum; i += step)
    {
        pt = hsvImageVChannels.ptr<uchar>(i);
        for (unsigned int j = 0; j < colTraNum; j += step)
        {
            Mat imageBlock = Mat(hsvImageVChannels, Rect(j, i, step, step));            
            double mea = mean(imageBlock)[0]; // 求小矩形的均值
            if (mea > 233.0 || mea < 53.0)
            {
                imageOverExposeBlockNum ++;
            }
            imageOverExposeBlocks ++;
        }
    }
    if (imageOverExposeBlockNum/(double)imageOverExposeBlocks < thre)
     return 0;
    else
    {   
        return 1;
    }
}

以下为一张普通人脸与一张过曝光人脸图片过曝光指数对比:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq249356520/article/details/78864244