1. 程式人生 > >均值濾波&高斯濾波&中值濾波

均值濾波&高斯濾波&中值濾波

均值濾波

均值濾波是一種線性濾波器,處理思路也很簡單,就是將一個視窗區域中的畫素計算平均值,然後將視窗中計算得到的均值設定為錨點上的畫素值。 該演算法有優點在於效率高,思路簡單。同樣,缺點也很明顯,計算均值會將影象中的邊緣資訊以及特徵資訊“模糊”掉,會丟失很多特徵。

計算均值濾波時可以採用很多優化手段,例如使用積分圖的方法對影象進行預處理,處理過後的影象可以通過O(1)的時間複雜度獲取視窗區域中的畫素和。如果使用並行以及SSE指令集來進行加速,效果會更快。

下面程式碼使用簡單的卷積方案來實現,既然是計算視窗區域中的畫素和,即使用如下卷積核即可。影象的邊界部分採用padding操作處理。另外,得到的錨點畫素值要進行歸一化,即除以視窗尺寸大小。 (3)

kernel=[111111111] kernel=\left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{matrix} \right] \tag{3}

void MeanFilter(const Mat &src, Mat &dst, int ksize)//均值濾波
{
	CV_Assert(ksize % 2 == 1);

	int
*kernel = new int[ksize*ksize]; for (int i = 0; i < ksize*ksize; i++) kernel[i] = 1; Mat tmp; int len = ksize / 2; tmp.create(Size(src.cols + len, src.rows + len), src.type());//新增邊框 dst.create(Size(src.cols, src.rows), src.type()); int channel = src.channels(); uchar *ps = src.data; uchar *
pt = tmp.data; for (int row = 0; row < tmp.rows; row++)//新增邊框的過程 { for (int col = 0; col < tmp.cols; col++) { for (int c = 0; c < channel; c++) { if (row >= len && row < tmp.rows - len && col >= len && col < tmp.cols - len) pt[(tmp.cols * row + col)*channel + c] = ps[(src.cols * (row - len) + col - len) * channel + c]; else pt[(tmp.cols * row + col)*channel + c] = 0; } } } uchar *pd = dst.data; pt = tmp.data; for (int row = len; row < tmp.rows - len; row++)//卷積的過程 { for (int col = len; col < tmp.cols - len; col++) { for (int c = 0; c < channel; c++) { short t = 0; for (int x = -len; x <= len; x++) { for (int y = -len; y <= len; y++) { t += kernel[(len + x) * ksize + y + len] * pt[((row + x) * tmp.cols + col + y) * channel + c]; } } pd[(dst.cols * (row - len) + col - len) * channel + c] = saturate_cast<ushort> (t/(ksize*ksize));//防止資料溢位ushort是16為資料 } } } delete[] kernel; }

高斯濾波

高斯濾波是一種線性濾波,是常用的一種濾波演算法,利用二維高斯函式的分佈方式來對影象進行平滑。 高斯濾波的優點可以集中在高斯函式的特點上來看 首先,二維高斯函式是旋轉對稱的,在各個方向上平滑程度相同,不會改變原影象的邊緣走向。 第二,高斯函式是單值函式,高斯卷積核的錨點為極值,在所有方向上單調遞減,錨點畫素不會受到距離錨點較遠的畫素影響過大,保證了特徵點和邊緣的特性。 第三,在頻域上,濾波過程中不會被高頻訊號汙染。

濾波過程中使用的高斯函式如下: G(x,y)=12πσ2ex2+y22σ2 G(x,y)=\frac{1}{2{\pi}{\sigma}^2}e^{-\frac{x^2+y^2}{2{\sigma}^2}} 在構建卷積核後,要將該卷積核歸一化處理,也就是將整個高斯卷積核中的值累加,並將卷積核中的每個值除以累加值。 所以,在編寫程式的過程中,前面的12πσ2\frac{1}{2{\pi}{\sigma}^2}部分由於除法會被約去,直接計算ex2+y22σ2e^{-\frac{x^2+y^2}{2{\sigma}^2}}即可。 另外,高斯的卷積核並不一定都是對稱的,即x方向的方差與y方向的方差可能會不同,這裡因具體要求而議,程式中使用的計算公式為: e(ix)2+(jy)22σxσye^{-\frac{(i-x)^2+(j-y)^2}{2{\sigma}_x{\sigma}_y}} 其中,x和y表示卷積核的中心,即錨點,i和j表示卷積核中的各個位置。

下面程式使用上面的高斯函式直接運算,效能並不突出,若想提高程式效能可以使用下面兩種方法。

第一種,如果瞭解卷積神經網路的話其實第一個方法很好想,在谷歌的inception 模型中,構建一個3×3的卷積層使用的是1×3與3×1的兩個方向上的卷積層來代替的,不但實現了同樣的效果,而且還減少了引數。同樣,在計算二維高斯核函式時使用同樣的原理,將兩個方向的卷積核分開計算,即分別計算x方向與y方向的卷積。計算開銷會大大減少。

第二種,如果瞭解數值分析,高斯函式是可以用其它函式逼近的思路來處理。有人提出了這樣的一篇論文解決了這個問題 “Recursive implementation of the Gaussian filter” 即使用遞迴迭代的方法來逼近高斯函式,效率極高。

以上兩種方法在配合sse指令以及平行計算以後,效率會有大幅度提升。

//方差可調節
void MyGaussFilter(const Mat &src, Mat &dst, int ksize, double sigmaX, double sigmaY = 0)
{
	CV_Assert(ksize % 2 == 1);

	if (fabs(sigmaY) < 1e-5)
		sigmaY = sigmaX;

	double *kernel = new double[ksize*ksize];
	int center = ksize / 2;
	double sum = 0;
	for (int i = 0; i < ksize; i++)
	{
		for (int j = 0; j < ksize; j++)
		{
			kernel[i * ksize + j] = exp(-(i - center)*(i - center) / (2 * sigmaX*sigmaX) - (j - center)*(j - center) / (2 * sigmaY*sigmaY));
			sum += kernel[i*ksize + j];
		}
	}
	for (int i = 0; i < ksize; i++)
	{
		for (int j = 0; j < ksize; j++)
		{
			kernel[i*ksize + j] /= sum;
		}
	}
	Mat tmp;
	int len = ksize / 2;
	tmp.create(Size(src.cols + len, src.rows + len), src.type());//新增邊框
	dst.create(Size(src.cols, src.rows), src.type());


	int channel = src.channels();
	uchar *ps = src.data;
	uchar *pt = tmp.data;

	for (int row = 0; row < tmp.rows; row++)//新增邊框的過程
	{
		for (int col = 0; col < tmp.cols; col++)
		{
			for (int c = 0; c < channel; c++)
			{
				if (row >= len && row < tmp.rows - len && col >= len && col < tmp.cols - len)
					pt[(tmp.cols * row + col)*channel + c] = ps[(src.cols * (row - len) + col - len) * channel + c];
				else
					pt[(tmp.cols * row + col)*channel + c] = 0;
			}
		}
	}

	uchar *pd = dst.data;
	pt = tmp.data;
	for (int row = len; row < tmp.rows - len; row++)//卷積的過程
	{
		for (int col = len; col < tmp.cols - len; col++)
		{
			for (int c = 0; c < channel; c++)
			{
				short t = 0;
				for (int x = -len; x <= len; x++)
				{
					for (int y = -len; y <= len; y++)
					{
						t += kernel[(len + x) * ksize + y + len] * pt[((row + x) * tmp.cols + col + y) * channel + c];
					}
				}

				pd[(dst.cols * (row - len) + col - len) * channel + c] = saturate_cast<ushort> (t);//防止資料溢位ushort是16為資料
			}
		}
	}
	delete[] kernel;
}

中值濾波

中值濾波是一種非線性濾波,在處理脈衝噪聲以及椒鹽噪聲時效果極佳,能夠有效的保護好影象的邊緣資訊。

中值濾波的處理思路很簡單,取卷積核當中所覆蓋畫素中的中值作為錨點的畫素值即可。

如果按照遍歷所有畫素,再對卷積核中的畫素排序取中值,那麼時間複雜度會很高,需要對中值濾波進行改進。

中值濾波的改進實際上很是很好想的,無非就是一個滑動視窗取中值的問題,每次向右滑動的過程中等於在視窗中新新增新增一列視窗畫素,同時減去一列視窗畫素,考慮維護這個視窗中的畫素資訊變化即可。

這裡面使用huang演算法,該思路是這個人提出來的,演算法思路如下:

在計算中值的辦法中,不使用排序,而是使用畫素直方圖,也就是記錄畫素值的雜湊。首先設定閾值threshold,這個threshold就是視窗的中心位置,即ksize×ksize/2+1,kisze為視窗尺寸。

每次在計算中值的過程中,從小到大累加畫素直方圖的值,如果該值大於等於,此時對應的畫素值就是中值了。

例如ksize=3的視窗如下: (3)[121235254] \left[ \begin{matrix} 1 &amp; 2 &amp; 1 \\ 2 &amp; 3 &amp; 5 \\ 2 &amp; 5 &amp; 4 \end{matrix} \right] \tag{3}

對該視窗中的值計算畫素直方圖如下,threshold=3×3/2+1=5 1:2(表示畫素值為1的有2個) 2:3 3:1 4:1 5:2

因為2+3≥5,所以中值為2

每次滑動視窗的過程中,如果視窗在第一列,那麼直接計算直方圖。否則向右移動,在直方圖中減去左側離開視窗中畫素,在右側新增進入視窗中的畫素。

此外,也可以讓視窗按照蛇形來移動,這樣也會避免每次視窗在第一列時需要重新計算的問題。

void AddSultPapperNoise(const Mat &src, Mat &dst,int num)//新增椒鹽噪聲
{
	dst = src.clone();
	uchar *pd=dst.data;
	int row, col, cha;
	srand((unsigned)time(NULL));
	while (num--)
	{
		row = rand() % dst.rows;
		col = rand() % dst.cols;
		cha = rand() % dst.channels();
		pd[(row*dst.cols + col)*dst.channels() + cha] = 0;
	}
}


int GetMediValue(const int histogram[], int thresh)//計算中值
{
	int sum = 0;
	for (int i = 0; i < (1 << 16); i++)
	{
		sum += histogram[i];
		if (sum >= thresh)
			return i;
	}
	return (1 << 16);
}

void MyFastMediFilter(const Mat &src, Mat &dst, int ksize)
{
	CV_Assert(ksize % 2 == 1);

	Mat tmp;
	int len = ksize / 2;
	tmp.create(Size(src.cols + len, src.rows + len), src.type());//新增邊框
	dst.create(Size(src.cols, src.rows), src.type());


	int channel = src.channels();
	uchar *ps = src.data;
	uchar *pt = tmp.data;
	for (int row = 0; row < tmp.rows; row++)//新增邊框的過程
	{
		for (
            
           

相關推薦

5.5 影象濾波均值、各項異性濾波

5.5.1 均值濾波 均值濾波是一種經常用到的平滑方法,其對應的模板各個畫素的值為1。在VTK中沒有直接實現均值濾波的類,但是我們可以通過影象卷積運算來實現。卷積運算通過vtkImageConvolve類實現。通過vtkImageConvolve類,只需要設定相應的卷積模板,便可以

Python3+OpenCV學習筆記(四):影象濾波基礎(均值、雙邊)

OpenCV中還可以在影象上進行繪圖操作,由於資料都比較完善,所以附上鍊接,自行參悟。 好了,進入正題。在一張影象,在資料儲存或傳輸的過程中,或多或少都會引入噪聲,常見的影象噪聲如高斯噪聲、瑞利噪聲、椒鹽噪聲等,可參加連結:數字影象噪聲 為了避免噪聲對影象資訊進行干擾或

opencv學習(二十三)之方框、均值、雙邊濾波綜合比較

/* *本程式的目的旨在對前面介紹的濾波器進行一個比較 *對比每種濾波器的濾波效果和耗時 *除雙邊濾波外其他濾波器kernel均是5*5或5 *對於雙邊濾波器取其直徑典型值30 *sigmaColor和sigmaSpace的值均由直徑計算而來 */

Opencv2.4學習::濾波(2)濾波

濾波系列: 均值濾波 中值濾波 高斯濾波 雙邊濾波  中值濾波 C++: void medianBlur(InputArray src, OutputArray dst, int ksize) InputArray src: 輸入影象,影象為1、3、4

opencv-11-濾波及自適應濾波

## 開始之前 在上一篇我們實現了讀取噪聲影象, 然後 進行三種形式的均值濾波得到結果, 由於我們自己寫的均值濾波未作邊緣處理, 所以效果有一定的下降, 但是總體來說, 我們得到的結果能夠說明我們的演算法執行之後得到的影象噪聲更低, 影象更清晰. 但是也會造成影象的模糊, 導致部分細節丟失. 在這一章中,我們

opencv3 圖片模糊操作-均值濾波 濾波 濾波 雙邊濾波

empty size mage point ima could not key image ace #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using

方框濾波/均值濾波/濾波/濾波/雙邊濾波

線性鄰域濾波 “平滑處理“(smoothing)也稱“模糊處理”(bluring),是一項簡單且使用頻率很高的影象處理方法。平滑處理的用途有很多,最常見的是用來減少影象上的噪點或者失真。在涉及到降低影象解析度時,平滑處理是非常好用的方法。 線性濾波器:線性濾波器經常用於剔除輸入訊

均值濾波&濾波&濾波

均值濾波 均值濾波是一種線性濾波器,處理思路也很簡單,就是將一個視窗區域中的畫素計算平均值,然後將視窗中計算得到的均值設定為錨點上的畫素值。 該演算法有優點在於效率高,思路簡單。同樣,缺點也很明顯,計算均值會將影象中的邊緣資訊以及特徵資訊“模糊”掉,會丟失很多特

基於MATLAB影象處理的濾波均值濾波以及濾波的實現與對比

基於MATLAB影象處理的中值濾波、均值濾波以及高斯濾波的實現與對比 作者:lee神 1.背景知識 中值濾波法是一種非線性平滑技術,它將每一畫素點的灰度值設定為該點某鄰域視窗內的所有畫素點灰度值的中值. 中值濾波是基於排序統計理論的一種能有效抑制噪聲的非線性訊號處

opencv實現影象鄰域均值濾波濾波濾波

void CCVMFCView::OnBlurSmooth()//鄰域均值濾波 { IplImage* in; in = workImg; IplImage* out = cvCreateImage(cvGetSize(in),IPL_DEPTH_8U,workImg-&g

[Python影象處理] 四.影象平滑之均值濾波、方框濾波濾波濾波

該系列文章是講解Python OpenCV影象處理知識,前期主要講解影象入門、OpenCV基礎用法,中期講解影象處理的各種演算法,包括影象銳化運算元、影象增強技術、影象分割等,後期結合深度學習研究影象識別、影象分類應用。希望文章對您有所幫助,如果有不足之處,還請

( 二 )影象的空間域增強_椒鹽噪聲_空域均值濾波

1,實驗原理 影象增強是數字影象處理的基本內容之一,其目的是根據應用需要突出影象中的某些“有用”資訊,削弱或去除不需要的資訊,以改善影象的視覺效果,或突出影象的特徵,便於計算機處理。影象增強可以在空間域進行,也可以在頻率域中進行。 空間域濾波主要利用空間模板進行,如3*3

椒鹽噪聲 濾波 噪聲 均值濾波

椒鹽噪聲用中值濾波比較好 原因是:1.椒鹽噪聲是幅值近似相等但是隨機的分佈在不同位置,圖中既有汙染的點,也有乾淨的點。      2.圖中噪聲的均值不為零,所以不適合均值濾波。      3.圖中有乾淨的點也有汙染的點,所以中值濾波可以用乾淨的點代替汙染的點。 中值濾波缺點

python+opencv均值濾波濾波濾波,雙邊濾波

濾波演算法主要包括均值濾波,高斯濾波,中值濾波和雙邊濾波。 每種演算法都有自己的特點,建議從原理上了解每種演算法的優缺點。上圖給出簡潔版的總結。 以下是程式碼: import numpy as

Python OpenCV _4初級濾波均值濾波濾波濾波

Python OpenCV這個初級影象處理系列是參考他人的文章寫的,有些地方做了一些改動,沒有太多理論,側重程式碼實現,主要目的是將這些基本操作程式碼系統地梳理一遍,也是為了以後能快速查詢。 理論就不說了,直接上程式碼和效果圖 原圖 一,均值濾波 程式碼:

OpenCV計算機視覺學習(4)——影象平滑處理(均值濾波濾波濾波,雙邊濾波

如果需要處理的原圖及程式碼,請移步小編的GitHub地址   傳送門:請點選我   如果點選有誤:https://github.com/LeBron-Jian/ComputerVisionPractice   “平滑處理”(smoothing)也稱“模糊處理”(bluring),是一項簡單且使用頻率很高的影象

(Gaussian)濾波(Median)濾波與雙邊(Bilateral)濾波的特點

影象預處理過程中,常常會遇到類似這樣問題:有沒有一個“好”的演算法?例如,有沒有一個好的邊緣檢測演算法,或者有沒有一個好的濾波演算法?但通常來說,沒有一個演算法能夠滿足通用性要求,每個演算法都有各自的特點。因此,對於這類問題,最先要問的是:我要解決什麼問題,為什

【影象處理】影象濾波去噪聲——均值濾波濾波、對稱均值濾波 低通濾波 濾波(opencv)

①觀察灰度分佈來描述一幅影象成為空間域,觀察影象變化的頻率被成為頻域。  ②頻域分析:低頻對應區域的影象強度變化緩慢,高頻對應的變化快。低通濾波器去除了影象的高頻部分,高通濾波器去除了影象的低頻部分。 (1)低通濾波  ①栗子: #include <iostream> #include &l

VC++濾波\中濾波實現影象模糊處理

一、演算法 高斯模糊演算法 詳見:高斯模糊,基本思想就是利用高斯函式,將一個座標點的所有鄰域的加權平均值設定為這些點的顏色值。 中值濾波演算法就更簡單了:將一個座標點的所有鄰域的平均值設定為這些點的畫素值。 二、演算法的程式碼實現 高斯函式: 使用巨集定義來替換: #de

均值濾波濾波,最大最小濾波

fin proc repeat 效果 mod ava rom static 包含 http://blog.csdn.net/fastbox/article/details/7984721 討論如何使用卷積作為數學工具來處理圖像,實現圖像的濾波,其方法包含以下幾種,均值 濾波