對圖像的濾波和平滑是出來數字圖像處理和計算機視覺非常重要的一個步驟,那么什么是濾波呢?濾波用編程語言到底是怎么實現的呢?效果怎么樣?本人打算學習opencv有關濾波的源碼,進一步加強圖像處理的實踐能力。
首先我們利用opencv中常見的4種濾波算法函數來實現濾波功能,讓大家有個感性的認識。這4中濾波分別是均值濾波,高斯濾波,中值濾波,雙邊濾波。利用opencv2.3.1的參考手冊中關於opencv中濾波的介紹,我這里采用的是VS2010+opencv2.3.1,新建了一個filter_test控制台工程。
其源碼和注釋如下:
//包含圖像處理和界面處理的頭文件
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
//采用cv命名空間和標准命名空間
using namespace std;
using namespace cv;
//定義全局變量
int DELAY_CAPTION=1500; //顯示標題時延時至少1.5s
int DELAY_BLUR=100; //顯示每次濾波時延時0.1s
int MAX_KERNEL_LENGTH=31;//最大的濾波核長度為31
Mat src,dst;
char window_name[]="Filter Demo 1:";
//函數說明
int display_caption(char *caption);
int display_dst(int delay);
//主函數
int main(int argc, _TCHAR* argv[])
{
namedWindow(window_name,CV_WINDOW_AUTOSIZE);//建立一個窗口
//將lena圖片讀寫到矩陣src
src=imread("../images/lena.jpg",1);
//將Origin Image單詞顯示在dst圖片中,並在窗口中顯示1.5s
if(display_caption("Origin Image")!=0){return 0;}
dst=src.clone();//將lena圖片復制到dst矩陣中,並顯示出來,1.5s
if(display_dst(DELAY_CAPTION)!=0){return 0;}
/*利用均值濾波
其中矩陣濾波的函數原型為void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT)
其中src為濾波前圖像矩陣,dst為濾波后圖像矩陣,ksize為濾波矩形核,anchor為定標點,如果采用的是Point(-1,-1)則默認為核的中心點,borderType為邊緣模式的展開
其濾波公式為:
也就是利用ksize個像素求平均值而已,很容易理解*/
if(display_caption("Homogeneous Blur")!=0){return 0;}//顯示Homogeneous Blur單詞1.5s
for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)
{
blur(src,dst,Size(i,i),Point(-1,-1));//采用均值濾波函數
if(display_dst(DELAY_BLUR)!=0){return 0;}
}
//高斯濾波,和上面類似
if(display_caption("Gaussian Blur")!=0){return 0;}
for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)
{
GaussianBlur(src,dst,Size(i,i),0,0);
if(display_dst(DELAY_BLUR)!=0){return 0;}
}
//中值濾波,和上面類似
if(display_caption("Median Blur")!=0){return 0;}
for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)
{
medianBlur(src,dst,i);
if(display_dst(DELAY_BLUR)!=0){return 0;}
}
//雙邊濾波,和上面類似
if(display_caption("Bilateral Blur")!=0){return 0;}
for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)
{
bilateralFilter(src,dst,i,i*2,i/2);
if(display_dst(DELAY_BLUR)!=0){return 0;}
}
//按任意鍵停止
display_caption("End:Press a key!");
waitKey(0);
return 0;
}
//中間顯示標題,沒有按鍵觸發時返回0
int display_caption(char *caption)
{
dst=Mat::zeros(src.size(),src.type());
//opencv2.3.1中往圖片上加字用putText函數,大家一看就應該知道參數是什么意思了
putText(dst,caption,Point(src.cols/4,src.rows/2),CV_FONT_HERSHEY_COMPLEX,1, Scalar(255,255,255));
imshow(window_name,dst);
//延時1.5s,注意在c++中是waitKey,該函數參數如果是非正數的話就直接停止在該位
//置等待按鍵觸發,否則延時至少參數時長ms
int c=waitKey(DELAY_CAPTION);
if(c>=0){return -1;}
return 0;
}
//顯示濾波后的圖片,沒有按鍵觸發時返回0
int display_dst(int delay)
{
imshow(window_name,dst);
int c=waitKey(delay);
if(c>=0){return -1;}
else return 0;
}
對於具體的這4種濾波的具體算法,大家可以自己查看源代碼,有時間我也會去具體學習的,今天這個其實沒什么內在的東西,主要是讓大家對濾波有個宏觀的認識,已經對開發環境熟悉一下而已。
在看源代碼過程中有看不懂的函數可以在一下2個網站上查看,其中第一個網站非常全
Opencv2.3后的版本英文幫助文件網頁:http://opencv.itseez.com/index.html
中文網頁:http://www.opencv.org.cn/index.php/Template:Doc
原圖像:
濾波后圖像: