OpenCV图像增强(二)——Retinex图像增强
生活随笔
收集整理的這篇文章主要介紹了
OpenCV图像增强(二)——Retinex图像增强
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
1.Retinex圖像增強是一種高動態范圍圖像的新色調映射技術。而基礎理論是,物體的顏色是由物體對長波(紅色)、中波(綠色)、短波(藍色)光線的反射能力來決定的,而不是由反射光強度的絕對值來決定的,物體的色彩不受光照非均勻性的影響,具有一致性,即retinex是以色感一致性(顏色恒常性)為基礎的。不同于傳統的線性、非線性的只能增強圖像某一類特征的方法,Retinex可以在動態范圍壓縮、邊緣增強和顏色恒常三個方面達到平衡,因此可以對各種不同類型的圖像進行自適應的增強。
2.Retinex圖像增強包括兩個步驟,全局適應和人類視覺系統的局部自適應。在局部自適應過程中,這里使用引導濾波器代替原本的高斯濾波器以減少暈圈偽影。為了保證良好的再現和動態范圍壓縮,使用基于場景的亮度值的對比度增強因子。此外,引入自適應非線性偏移來處理對數函數的非線性強度。
3.導向濾波作為一種保邊濾波,可以運用在很多場合,比如美顏,去霧。
代碼實現
void ALTMRetinex(const Mat& src, Mat &dst, bool LocalAdaptation = false, bool ContrastCorrect = true) {Mat temp, src_gray;src.convertTo(temp, CV_32FC3);//灰度圖cvtColor(temp, src_gray, CV_BGR2GRAY);double LwMax;//得到最大值minMaxLoc(src_gray, NULL, &LwMax);Mat Lw_;const int num = src.rows * src.cols;//計算每個數組元素絕對值的自然對數cv::log(src_gray + 1e-3f, Lw_);//矩陣自然指數float LwAver = exp(cv::sum(Lw_)[0] / num);Mat Lg;log(src_gray / LwAver + 1.f, Lg);//矩陣除法cv::divide(Lg, log(LwMax / LwAver + 1.f), Lg);//局部自適應Mat Lout;if (LocalAdaptation){int kernelSize = floor(std::max(3, std::max(src.rows / 100, src.cols / 100)));Mat Lp, kernel = cv::getStructuringElement(MORPH_RECT, Size(kernelSize, kernelSize));cv::dilate(Lg, Lp, kernel);Mat Hg = guidedFilter(Lg, Lp, 10, 0.01f);double eta = 36;double LgMax;cv::minMaxLoc(Lg, NULL, &LgMax);Mat alpha = 1.0f + Lg * (eta / LgMax);Mat Lg_;cv::log(Lg + 1e-3f, Lg_);float LgAver = exp(cv::sum(Lg_)[0] / num);float lambda = 10;float beta = lambda * LgAver;cv::log(Lg / Hg + beta, Lout);cv::multiply(alpha, Lout, Lout);cv::normalize(Lout, Lout, 0, 255, NORM_MINMAX);}else{cv::normalize(Lg, Lout, 0, 255, NORM_MINMAX);}Mat gain(src.rows , src.cols, CV_32F);for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){float x = src_gray.at<float>(i, j);float y = Lout.at<float>(i, j);if (0 == x) gain.at<float>(i, j) = y;else gain.at<float>(i, j) = y / x;}}Mat bgr[3];cv::split(temp, bgr);if (ContrastCorrect){// 校正圖像對比度bgr[0] = (gain.mul(bgr[0] + src_gray) + bgr[0] - src_gray) *0.5f;bgr[1] = (gain.mul(bgr[1] + src_gray) + bgr[1] - src_gray) *0.5f;bgr[2] = (gain.mul(bgr[2] + src_gray) + bgr[2] - src_gray) *0.5f;}else{cv::multiply(bgr[0], gain, bgr[0]);cv::multiply(bgr[1], gain, bgr[1]);cv::multiply(bgr[2], gain, bgr[2]);}cv::merge(bgr, 3, dst);dst.convertTo(dst, CV_8UC3); }//導向濾波器Mat guidedFilter(cv::Mat& I, cv::Mat& p, int r, float eps){/*× GUIDEDFILTER O(N) time implementation of guided filter.×× - guidance image: I (should be a gray-scale/single channel image)× - filtering input image: p (should be a gray-scale/single channel image)× - local window radius: r× - regularization parameter: eps*/cv::Mat _I;I.convertTo(_I, CV_32FC1);I = _I;cv::Mat _p;p.convertTo(_p, CV_32FC1);p = _p;//因為opencv自帶的boxFilter()中的Size,比如9x9,我們說半徑為4r = 2 * r + 1;//mean_I = boxfilter(I, r) ./ N;cv::Mat mean_I;cv::boxFilter(I, mean_I, CV_32FC1, cv::Size(r, r));//mean_p = boxfilter(p, r) ./ N;cv::Mat mean_p;cv::boxFilter(p, mean_p, CV_32FC1, cv::Size(r, r));//mean_Ip = boxfilter(I.*p, r) ./ N;cv::Mat mean_Ip;cv::boxFilter(I.mul(p), mean_Ip, CV_32FC1, cv::Size(r, r));//cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch.cv::Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);//mean_II = boxfilter(I.*I, r) ./ N;cv::Mat mean_II;cv::boxFilter(I.mul(I), mean_II, CV_32FC1, cv::Size(r, r));//var_I = mean_II - mean_I .* mean_I;cv::Mat var_I = mean_II - mean_I.mul(mean_I);//a = cov_Ip ./ (var_I + eps); % Eqn. (5) in the paper;cv::Mat a = cov_Ip / (var_I + eps);//b = mean_p - a .* mean_I; % Eqn. (6) in the paper;cv::Mat b = mean_p - a.mul(mean_I);//mean_a = boxfilter(a, r) ./ N;cv::Mat mean_a;cv::boxFilter(a, mean_a, CV_32FC1, cv::Size(r, r));//mean_b = boxfilter(b, r) ./ N;cv::Mat mean_b;cv::boxFilter(b, mean_b, CV_32FC1, cv::Size(r, r));//q = mean_a .* I + mean_b; % Eqn. (8) in the paper;cv::Mat q = mean_a.mul(I) + mean_b;return q;}運行結果
結語
我這里使用的庫OpenCV版本是3.30,關于opencv學習,有興趣的看我之前發的博客,可以加之前博客后面給的興趣群。
總結
以上是生活随笔為你收集整理的OpenCV图像增强(二)——Retinex图像增强的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用python对比两个目录下的文件名差
- 下一篇: OpenCV图像增强(三)——自适应对数