0029-在OpenCV環境下做導向濾波的程式碼
阿新 • • 發佈:2018-11-16
前邊提到的均值濾波、中值濾波和高斯濾波,都屬於各向同性濾波,它們對待噪聲和影象的邊緣資訊都採取一樣的態度,結果,噪聲被磨平的同時,影象中具有重要地位的邊緣、紋理和細節也同時被抹平了,這是我們所不希望看到的。為了解決這個問題,人們陸續提出了一些演算法來把影象邊緣和噪聲區別對待,比如雙邊濾波和導向濾波,本文介紹如何使用opencv做影象的導向濾波。
先來說下導向濾波的大致思路。在導向濾波中,要對影象p進行濾波而得到影象q,需要一個引導影象I,類似的原理有點像直方圖匹配,直方圖匹配詳見博文https://blog.csdn.net/lehuoziyuan/article/details/84066102,其實就是根據引導影象I的特徵去設定濾波器。導向濾波在影象增強、HDR壓縮、影象摳圖及影象去霧等場景中都有應用。
具體的導向濾波的原理大家可參見博文http://blog.csdn.net/baimafujinji/article/details/74750283,我這裡就不多敘述了。
導向濾波的程式碼如下:
影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注!
程式碼中用到的影象下載連結:http://pan.baidu.com/s/1c2IrDZy 密碼:dqbl
//opencv版本:OpenCV3.0 //VS版本:VS2013 //Author:qxsf321.net #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgproc/types_c.h> #include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui_c.h> #include <time.h> #include <iostream> using namespace cv; using namespace std; //導向濾波器 Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps); int main() { Mat srcImage = imread("Gauss_noise.jpg"); if (srcImage.empty()) { cout << "讀入圖片錯誤!" << endl; system("pause"); return -1; } //進行通道分離 vector<Mat>vSrcImage, vResultImage; split(srcImage, vSrcImage); Mat resultMat; for (int i = 0; i < 3; i++) { //分通道轉換成浮點型資料 Mat tempImage; vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0); Mat p = tempImage.clone(); //分別進行導向濾波 Mat resultImage = guidedfilter(tempImage, p, 4, 0.01); vResultImage.push_back(resultImage); } //通道結果合併 merge(vResultImage, resultMat); imshow("原影象", srcImage); imshow("導向濾波後圖像", resultMat); waitKey(0); return 0; } Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps) { //轉換源影象資訊 srcImage.convertTo(srcImage, CV_64FC1); srcClone.convertTo(srcClone, CV_64FC1); int NumRows = srcImage.rows; int NumCols = srcImage.cols; Mat boxResult; //下面按照步驟進行導向濾波操作 ///////////////////////////////////////////////////////////// //步驟一:計算均值 boxFilter(Mat::ones(NumRows, NumCols, srcImage.type()), boxResult, CV_64FC1, Size(r, r)); //生成導向均值mean_I Mat mean_I; boxFilter(srcImage, mean_I, CV_64FC1, Size(r, r)); //生成原始均值mean_P Mat mean_P; boxFilter(srcClone, mean_P, CV_64FC1, Size(r, r)); //生成互相關均值mean_IP Mat mean_IP; boxFilter(srcImage.mul(srcClone), mean_IP, CV_64FC1, Size(r, r)); Mat cov_IP = mean_IP - mean_I.mul(mean_P); //生成自相關均值mean_II Mat mean_II; //應用盒濾波計算相關均值 boxFilter(srcImage.mul(srcImage), mean_II, CV_64FC1, Size(r, r)); //步驟二:計算相關係數 Mat var_I = mean_II - mean_I.mul(mean_I); Mat var_IP = mean_IP - mean_I.mul(mean_P); //步驟三:計算引數係數a,b Mat a = cov_IP / (var_I + eps); Mat b = mean_P = a.mul(mean_I); //步驟四:計算係數a,b的均值 Mat mean_a; boxFilter(a, mean_a, CV_64FC1, Size(r, r)); mean_a = mean_a / boxResult; Mat mean_b; boxFilter(b, mean_b, CV_64FC1, Size(r, r)); mean_b = mean_b / boxResult; //步驟五:生成輸出矩陣 Mat resultMat = mean_a.mul(srcImage) + mean_b; return resultMat; }
執行結果截圖如下:
程式碼說明:
在上面的程式碼中,導向圖I就是原圖本身,大家可以修改程式碼換一張圖片試試。