图像色偏检测

色偏检测

1 CIE LAB空间

  • L分量用于表示像素的亮度,取值范围是[0,100],表示从纯黑到纯白;
  • a表示从红色到绿色的范围,取值范围是[-128,127];
  • b表示从黄色到蓝色的范围,取值范围是[-128,127]。


    图片.png

2 检测原理

通常存在色偏的图像,在a和b分量上的均值会偏离原点很远,方差也会偏小;通过计算图像在a和b分量上的均值和方差,就可评估图像是否存在色偏。

L分量的取值范围为[0,100],A和B分量都为[-128,127],为了与RGB颜色空间同一范围,OpenCV将L拉升至[0,255],把A,B位移至于[0,255],就可以同RGB颜色空间表达为同一个范围了。即使这样映射后,一般来说,LAB各分量的结果仍为浮点数,这个和RGB不同,但是在很多情况下,为了速度计效率,我们这需结果的取整部分,得到类似于RGB空间的布局。

  • 计算圆心位置:相当于计算均值,在计算过程中,要考虑将CIE Lab空间还原成(-127,124]范围(这样才能体现距离原点的距离);
  • 计算半径:相当于计算各点距离圆心的距离的均值,在计算半径时使用一个数组统计a,b的分布,也要记得将Lab空间还原;
  • 定义色差因子:色差值cast用于衡量图片色差的程度,色差值=圆心距中性点距离/半径,距中性点(均值)越大并且半径越小则色差程度越高。
    Mat BGRimg = imread("D:/20.jpg");
    Mat LABimg;
    cvtColor(BGRimg, LABimg, CV_BGR2Lab);
    float a = 0, b = 0;     // 用于记录a/b轴的平均值
    int HistA[256], HistB[256];     // 用于记录a/b轴每个色度的出现次数
    for (int i = 0; i < 256; i++)
    {
        HistA[i] = 0;
        HistB[i] = 0;
    }
    for (int i = 0; i < LABimg.rows; i++)
    {
        for (int j = 0; j < LABimg.cols; j++)
        {
            // 注意将Lab空间取值范围还原成(-127,127]
            a += (float(LABimg.at(i, j)[1]) - 128);
            b += (float(LABimg.at(i, j)[2]) - 128);
            // x表示在a轴的色度值
            int x = LABimg.at(i, j)[1];
            int y = LABimg.at(i, j)[2];
            HistA[x]++;
            HistB[x]++;
        }
    }
    // 计算圆心坐标/均值
    // da大于0,表示偏红;da小于0表示偏绿;db大于0,表示偏黄;db小于0表示偏蓝
    float da = a / float(LABimg.rows*LABimg.cols);
    float db = b / float(LABimg.rows*LABimg.cols);
    // 计算半径
    float ma = 0, mb = 0, r = 0;
    for (int i = 0; i < 256; i++)
    {
        ma += abs(i - 128 - da)*HistA[i];
        mb += abs(i - 128 - db)*HistB[i];
    }
    ma /= float(LABimg.cols*LABimg.rows);
    mb /= float(LABimg.cols*LABimg.rows);
    r = sqrt(ma * ma + mb * mb);
    float K = float(sqrt(da*da + db * db)) / float(r);
    cout << K << endl;

TODO

  • 半径太大有许多半径很大但是出现次数较少对结果影响很大 尝试忽略这些干扰点

你可能感兴趣的:(图像色偏检测)