Local Color Correction 區域性顏色較正論文C++復現
阿新 • • 發佈:2019-01-07
前言
偶然見到了這篇paper,雖然之前復現的一些paper已經可以較好的處理低照度下的色彩恢復,然而在光度強度很大的情況下怎麼恢復還不清楚,並且如果出現圖片中既有很亮的部分,又有很暗的部分,又不知道怎麼處理了。這篇paper,正式為了解決這一問題,他的局步顏色矯正,和He KaiMing的暗通道去霧有相似的想法,值得借鑑。
演算法原理
首先對與太亮和太暗的影象,我們可以使用Gamma校正來提高對比度。
圖片表示:較暗影象,Gamma係數為0.5的Gamma校正,直方圖均衡化
代表原始影象,Gamma係數為0.5,2.5,0.75,1.5的Gamma校正影象
使用Gamma校正後可以提高影象的動態範圍,實際上作者講這麼多實際是要說,如果當影象既有較亮又有較暗的區域時,如果僅僅使用一個Gamma矯正輸出的影象效果反而會變差,這是因為Gamma矯正是全域性的方法,某一部分相近的畫素將被對映到相同的灰度值,並沒有考慮待到畫素鄰域的資訊。對於普通的過亮和過暗的影象,當影象的平均灰度大於127.5使用 ,對影象的亮度進行抑制;當影象的灰度資訊均值小於127.5時使用 對影象亮度進行增強。這裡我們假設影象用無符號8bit表示,那麼 。在既有較暗又有較亮的區域的影象中,全域性Gamma失效,這時候作者就提出了利用影象鄰域的資訊,進行Gamma矯正。對較暗的區域進行增加亮度,對較亮的區域降低亮度。區域性顏色校正的方法可以根據鄰域內畫素的灰度值情況,把統一輸入畫素值,對映成不同水平的畫素灰度值。
演算法步驟
- 根據輸入影象計算出掩膜影象
- 結合輸入影象和掩模影象計算出最終結果
掩膜影象一般根據彩色影象各個通道的影象灰度值獲得。假設RGB影象各個通道的畫素灰度值為R,G,B,則掩膜影象可以表示為 ,之後對掩膜影象進行高斯濾波: ,高斯濾波時,選取較大值進行濾波,以保證對比度不會沿著邊緣方向過度減小。上述的輸出結果表明:影象哪部分需要提亮,哪部分需要減暗。最後輸出影象為: ,如果掩膜影象大於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;
}
效果
所有的圖片均為未處理和處理後的順序