《DARK IMAGE ENHANCEMENT BASED ON PAIRWISE TARGET CONTRAST AND MULTI-SCALE DETAIL BOOSTING》 C++復現
阿新 • • 發佈:2019-01-07
論文連結
請google,一篇IEEE的論文,在查詢提升影象細節的時候看到一個部落格上對這個論文介紹,我下載不了論文,所幸那個博主給了論文的主要部分的圖片,可以到這個部落格檢視:https://blog.csdn.net/q781045982/article/details/78632955
演算法原理
核心就是,論文使用了Retinex方法類似的思路,使用了多個尺度的高斯核對原圖濾波,然後再和原圖做減法,獲得不同程度的細節資訊,然後通過一定的組合方式把這些細節資訊融合到原圖中,從而得到加強原圖資訊的能力。公式十分簡單,注意到第一個係數有點特殊操作,實現的話,直接看上面的圖片就很簡單實現了。具體為什麼這樣做可行,以及為什麼可行,就需要去查詢論文原文的介紹了,我暫時無法下載這個論文,如果有人有IEEE論文的下載渠道,不妨幫助一下我,不勝感激。
程式碼實現
void separateGaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma){ CV_Assert(src.channels()==1 || src.channels() == 3); //只處理單通道或者三通道影象 //生成一維的 double *matrix = new double[ksize]; double sum = 0; int origin = ksize / 2; for(int i = 0; i < ksize; i++){ double g = exp(-(i-origin) * (i-origin) / (2 * sigma * sigma)); sum += g; matrix[i] = g; } for(int i = 0; i < ksize; i++) matrix[i] /= sum; int border = ksize / 2; copyMakeBorder(src, dst, border, border, border, border, BORDER_CONSTANT); int channels = dst.channels(); int rows = dst.rows - border; int cols = dst.cols - border; //水平方向 for(int i = border; i < rows; i++){ for(int j = border; j < cols; j++){ double sum[3] = {0}; for(int k = -border; k<=border; k++){ if(channels == 1){ sum[0] += matrix[border + k] * dst.at<uchar>(i, j+k); }else if(channels == 3){ Vec3b rgb = dst.at<Vec3b>(i, j+k); sum[0] += matrix[border+k] * rgb[0]; sum[1] += matrix[border+k] * rgb[1]; sum[2] += matrix[border+k] * rgb[2]; } } for(int k = 0; k < channels; k++){ if(sum[k] < 0) sum[k] = 0; else if(sum[k] > 255) sum[k] = 255; } if(channels == 1) dst.at<Vec3b>(i, j) = static_cast<uchar>(sum[0]); else if(channels == 3){ Vec3b rgb = {static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2])}; dst.at<Vec3b>(i, j) = rgb; } } } //豎直方向 for(int i = border; i < rows; i++){ for(int j = border; j < cols; j++){ double sum[3] = {0}; for(int k = -border; k<=border; k++){ if(channels == 1){ sum[0] += matrix[border + k] * dst.at<uchar>(i+k, j); }else if(channels == 3){ Vec3b rgb = dst.at<Vec3b>(i+k, j); sum[0] += matrix[border+k] * rgb[0]; sum[1] += matrix[border+k] * rgb[1]; sum[2] += matrix[border+k] * rgb[2]; } } for(int k = 0; k < channels; k++){ if(sum[k] < 0) sum[k] = 0; else if(sum[k] > 255) sum[k] = 255; } if(channels == 1) dst.at<Vec3b>(i, j) = static_cast<uchar>(sum[0]); else if(channels == 3){ Vec3b rgb = {static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2])}; dst.at<Vec3b>(i, j) = rgb; } } } delete [] matrix; } Mat MultiScaleDetailBoosting(Mat src, int Radius){ int rows = src.rows; int cols = src.cols; Mat B1, B2, B3; separateGaussianFilter(src, B1, Radius, 1.0); separateGaussianFilter(src, B2, Radius*2-1, 2.0); separateGaussianFilter(src, B3, Radius*4-1, 4.0); float w1 = 0.5, w2 = 0.5, w3 = 0.25; Mat dst(rows, cols, CV_8UC3); for(int i = 0; i < rows; i++){ for(int j = 0; j < cols; j++){ for(int k = 0; k < 3; k++){ int D1 = src.at<Vec3b>(i, j)[k] - B1.at<Vec3b>(i, j)[k]; int D2 = B1.at<Vec3b>(i, j)[k] - B2.at<Vec3b>(i, j)[k]; int D3 = B2.at<Vec3b>(i, j)[k] - B3.at<Vec3b>(i, j)[k]; int sign = D1 > 0 ? 1 : -1; dst.at<Vec3b>(i, j)[k] = saturate_cast<uchar>((1 - w1*sign) * D1 - w2 * D2 + w3 * D3 + src.at<Vec3b>(i, j)[k]); } } } return dst; }
效果
原圖
演算法處理後的圖
順便吐槽一句,為啥csdn的圖片別人看到都是加水印的,太不友好了,看來需要研究一下如何正確去除水印了。