Local Color Correction 局部颜色较正论文C++复现

版权声明:蒟蒻博客,请随意转载,但请保留原地址。 https://blog.csdn.net/just_sort/article/details/84539295

前言

\quad 偶然见到了这篇paper,虽然之前复现的一些paper已经可以较好的处理低照度下的色彩恢复,然而在光度强度很大的情况下怎么恢复还不清楚,并且如果出现图片中既有很亮的部分,又有很暗的部分,又不知道怎么处理了。这篇paper,正式为了解决这一问题,他的局步颜色矫正,和He KaiMing的暗通道去雾有相似的想法,值得借鉴。

算法原理

首先对与太亮和太暗的图像,我们可以使用Gamma校正来提高对比度。
在这里插入图片描述图片表示:较暗图像,Gamma系数为0.5的Gamma校正,直方图均衡化
在这里插入图片描述代表较亮的原始图像,Gamma系数为2.5的Gamma校正,直方图均衡化
在这里插入图片描述代表原始图像,Gamma系数为0.5,2.5,0.75,1.5的Gamma校正图像

使用Gamma校正后可以提高图像的动态范围,实际上作者讲这么多实际是要说,如果当图像既有较亮又有较暗的区域时,如果仅仅使用一个Gamma矫正输出的图像效果反而会变差,这是因为Gamma矫正是全局的方法,某一部分相近的像素将被映射到相同的灰度值,并没有考虑待到像素邻域的信息。对于普通的过亮和过暗的图像,当图像的平均灰度大于127.5使用 γ > 1 \gamma >1 ,对图像的亮度进行抑制;当图像的灰度信息均值小于127.5时使用 γ < 1 \gamma <1 对图像亮度进行增强。这里我们假设图像用无符号8bit表示,那么 γ = 2 u 127.5 127.5 \gamma = 2^{\frac{u-127.5}{127.5}} 。在既有较暗又有较亮的区域的图像中,全局Gamma失效,这时候作者就提出了利用图像邻域的信息,进行Gamma矫正。对较暗的区域进行增加亮度,对较亮的区域降低亮度。局部颜色校正的方法可以根据邻域内像素的灰度值情况,把统一输入像素值,映射成不同水平的像素灰度值。

算法步骤

  • 根据输入图像计算出掩膜图像
  • 结合输入图像和掩模图像计算出最终结果
    掩膜图像一般根据彩色图像各个通道的图像灰度值获得。假设RGB图像各个通道的像素灰度值为R,G,B,则掩膜图像可以表示为 I = ( R + G + B ) / 3 I = (R + G + B) / 3 ,之后对掩膜图像进行高斯滤波: M ( x , y ) = ( G a u s s i a n ( 255 I ) ) ( x , y ) M(x,y) = (Gaussian*(255-I))(x,y) ,高斯滤波时,选取较大值进行滤波,以保证对比度不会沿着边缘方向过度减小。上述的输出结果表明:图像哪部分需要提亮,哪部分需要减暗。最后输出图像为: O u t p u t ( x , y ) = 255 ( I n p u t ( x , y ) 255 ) 2 128 M ( x , y ) 128 Output(x, y)=255(\frac{Input(x,y)}{255})^{2^{\frac{128-M(x,y)}{128}}} ,如果掩膜图像大于128,将得到一个大于1的指数,并对图像该点的亮度移植,反之增加亮度。如果等于128,则不改变该像素点亮度。

C++代码

Mat LCC(const Mat &src){
    int rows = src.rows;
    int cols = src.cols;
    int **I;
    I = new int *[rows];
    for(int i = 0; i < rows; i++){
        I[i] = new int [cols];
    }
    int **inv_I;
    inv_I = new int *[rows];
    for(int i = 0; i < rows; i++){
        inv_I[i] = new int [cols];
    }
    Mat Mast(rows, cols, CV_8UC1);
    for(int i = 0; i < rows; i++){
        uchar *data = Mast.ptr<uchar>(i);
        for(int j = 0; j < cols; j++){
            I[i][j] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i, j)[1]) / 3.0;
            inv_I[i][j] = 255;
            *data = inv_I[i][j] - I[i][j];
            data++;
        }
    }
    GaussianBlur(Mast, Mast, Size(41, 41), BORDER_DEFAULT);
    Mat dst(rows, cols, CV_8UC3);
    for(int i = 0; i < rows; i++){
        uchar *data = Mast.ptr<uchar>(i);
        for(int j = 0; j < cols; j++){
            for(int k = 0; k < 3; k++){
                float Exp = pow(2, (128 - data[j]) / 128.0);
                int value = int(255 * pow(src.at<Vec3b>(i, j)[k] / 255.0, Exp));
                dst.at<Vec3b>(i, j)[k] = value;
            }
        }
    }
    return dst;
}

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
所有的图片均为未处理和处理后的顺序

猜你喜欢

转载自blog.csdn.net/just_sort/article/details/84539295