OPENCV影象處理(二):模糊
模糊是基本的影象處理方法。
在介紹這兩種方法之前先來介紹兩種常見的噪聲:
椒鹽噪聲
椒鹽噪聲是由影象感測器,傳輸通道,解碼處理等產生的黑白相間的亮暗點噪聲。椒鹽噪聲分為兩種即胡椒噪聲和鹽噪聲,胡椒噪聲是黑色的,屬於低灰度噪聲,鹽噪聲是白色的,屬於高灰度噪聲,一般兩種噪聲同時出現,呈現在影象上就是黑白雜點。去除椒鹽噪聲最常用的演算法是中值濾波。
高斯噪聲
高斯噪聲是一種隨機噪聲,其幅度的統計規律服從高斯分佈(正態分佈),去高斯噪聲最常用的演算法是高斯濾波。
而這些噪聲出現在圖片上某一點時都是比較突兀的,如出現椒鹽噪聲時,圖片中突然某一點的會突然變成0或255,一般與噪聲周圍的灰度值有較大的差值,所以影象在去噪時一般都是用周圍畫素的灰度值經過一定的運算元來改變這點畫素上較為突兀的灰度值,但缺陷是對原來正常的畫素點的灰度值也會產生影響使圖片變得;
在影象處理時,灰度圖片一般會被視為一個矩陣,而影象上的每一畫素所代表的灰度值被視為矩陣中相應位置中的元素,如一幅100×100畫素的黑色灰度圖片就可以視為100×100的一個矩陣,矩陣中的每一個元素都為0;對影象進行處理也可以視為對這個矩陣進行處理。
在銳化和模糊時,會用到一些模板,這些模板是一個小如3×3,5×5的矩陣,用來與原影象進行處理產生新的影象,如在均值濾波時常用的模板
均值濾波:
用如的模板對圖片的每一畫素和其相鄰畫素組成的領域進行進行卷積處理,卷積的結果進行歸一處理,結果為這一區域灰度值的平均值,用灰度值的平均值替代這一點畫素的原灰度值。 均值濾波計算速度快,但會使影象變得較為模糊。因為手機無法像單反改變光圈來改變景深情況下(HTC的M8有專門的景深攝像頭除外),其他的都是利用演算法對背景進行模糊處理。
公式
其中s表示處理畫素點與周圍畫素形成的一塊區域;
//均值濾波
uchar junzhi(uchar* fx,int cols)
{
int model[3][3] = { { 1, 1 , 1 },
{ 1, 1, 1 },
{ 1, 1, 1 }};
uchar dir;
dir =( *(fx - cols - 1)*model[0][0] + *(fx - cols)*model[0][1] + *(fx -cols + 1)*model[0][2] +
*(fx - 1)*model[1][0] + *(fx)*model[1][1] + *(fx + 1)*model[1][2] +
*(fx + cols + 1)*model [2][0] + *(fx + cols)*model[2][1] + *(fx + cols+ 1)*model[2][2])/9;
return dir;
}
處理後效果:
中值濾波:
用模板進行處理,並用區域中的中值替代這一點的畫素值:
模板:
公式:
其中S是畫素所在的領域;
實現程式碼:
//中值濾波
uchar zhongzhi(uchar *fx, int cols)
{
uchar model[9];
uchar temp;
model[0] = *(fx - cols - 1);
model[1] = *(fx - cols);
model[2] = *(fx - cols + 1);
model[3] = *(fx - 1);
model[4] = *(fx);
model[5] = *(fx + 1);
model[6] = *(fx + cols - 1);
model[7] = *(fx + cols);
model[8] = *(fx + cols + 1);
for (int i = 8; i >-1; i--)
{
for (int j = 0; j < i; j++)
{
if (model[i] < model[j])
{
temp = model[i];
model[i] = model[j];
model[j] = temp;
}
}
}
return model[4];
}
處理效果:
明顯右邊白框中黑點減少了;
高斯濾波:
主要原理是根據高斯函式獲得相應的濾波模板矩陣,再用這個矩陣去處理影象,對高斯噪聲有較好的模糊作用;
根據二維高斯公式:
在根據每一點與中心點的位置可以得到其權重矩陣
由於正態方差為1,
根據公式進行計算後得到的矩陣再進行歸一化處理後可以得到模板矩陣:
程式碼:
//gaoshi
uchar gauss(uchar* fx, int cols)
{
int model[3][3] = { { 1, 2, 1 },
{ 2, 4, 2 },
{ 1, 2, 1 } };
uchar dir;
dir = (*(fx - cols - 1)*model[0][0] + *(fx - cols)*model[0][1] + *(fx - cols + 1)*model[0][2] +
*(fx - 1)*model[1][0] + *(fx)*model[1][1] + *(fx + 1)*model[1][2] +
*(fx + cols + 1)*model[2][0] + *(fx + cols)*model[2][1] + *(fx + cols + 1)*model[2][2]) / 16;
return dir;
}
與opencv中的高斯濾波效果比較:
main函式:
#include<opencv2\opencv.hpp>
#include<stdio.h>
#include<cv.h>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\core\core.hpp>
#include<iostream>
#include<Windows.h>
using namespace cv;
using namespace std;
void filtering(Mat src, Mat dir)
{
int mn=0;
uchar* psrc = (uchar*)src.data;
uchar* pdir = (uchar*)dir.data;
psrc = psrc + src.cols+1;
pdir = pdir + src.cols+ 1;
for (int i = 1; i < src.rows-1; i++)
{
for (int j = 1; j < src.cols - 1; j++)
{
*(pdir) =junzhi(psrc, src.cols);//自己要用的濾波
psrc++;
pdir++;
}
}
}
void main()
{
Mat src = imread("5.tif",0);
imshow("src", src);
Mat dir(src.rows, src.cols, CV_8UC1);
filtering(src, dir);
imshow("dir", dir);
//GaussianBlur(src, dir,Size(3,3), 0, 0);
//imshow("gauss", dir);
waitKey();
}
由於筆者能力有限,其中會有錯誤,歡迎提出