本文作者:小嗷
微信公眾號:aoxiaoji
吹比QQ群:736854977
簡書鏈接:http://m.itdecent.cn/u/45da1fbce7d0
不在意時光的走,也不在意雨雪的停。如果你是一個房間中最聰明的人,那你一定是在一個錯誤的房間。
小嗷本來想寫中值濾波、雙邊濾波。
但是,小嗷心中就有個疑問:濾波濾波,到底我們要濾那些波,有沒有實際點案例?
為啥子要叫濾波,不能叫濾躁,或者濾什么鬼?
因為在傅里葉那篇(第13篇),小嗷就形成一個概念:無數個大小不一正弦波可以疊出一個圖像(既然正方形都可以疊出來,那么一個圖像應該也可以)
再者,通過傅里葉變換成頻域,過濾掉不想要的波形(就是根直線),小嗷就是這樣理解:濾波。
那么,什么情況要濾波?。?/p>
但是,喂喂(#`O′),線性濾波,我看來就是個模糊圖像而已,有個P用,除了裝逼還是有點用 --- 來自小嗷心中的反問
當然,小嗷不是正規(guī)軍出身,文化水平低,沒老師教。如果,某位大佬有更好的解釋,請QQ郵箱或者微信公眾號里,方便小嗷改正,別寫文章誤導別人。
那么先從制造噪聲開始,明天就利用濾波看看,效果如何?
本文你會找到以下問題的答案:
圖像噪聲
噪聲來源
常見噪聲介紹(高斯噪聲,泊松噪聲,乘性噪聲,椒鹽噪聲)
一、二階矩
功率譜密度
代碼簡單實現模擬噪聲
at()函數
rand()函數
2.1 圖像噪聲
噪聲在圖像上常表現為一引起較強視覺效果的孤立像素點或像素塊。一般,噪聲信號與要研究的對象不相關,它以無用的信息形式出現,擾亂圖像的可觀測信息。通俗的說就是噪聲讓圖像不清楚。
2.2 噪聲來源
1.圖像獲取過程中
兩種常用類型的圖像傳感器CCD和CMOS采集圖像過程中,由于受傳感器材料屬性、工作環(huán)境、電子元器件和電路結構等影響,會引入各種噪聲,如電阻引起的熱噪聲、場效應管的溝道熱噪聲、光子噪聲、暗電流噪聲、光響應非均勻性噪聲。
2.圖像信號傳輸過程中
由于傳輸介質和記錄設備等的不完善,數字圖像在其傳輸記錄過程中往往會受到多種噪聲的污染。另外,在圖像處理的某些環(huán)節(jié)當輸入的對象并不如預想時也會在結果圖像中引入噪聲。
簡單來說:工廠環(huán)節(jié) -> 運輸到客戶途中。
2.3 常見噪聲介紹
圖像常見噪聲基本上有以下四種,高斯噪聲,泊松噪聲,乘性噪聲,椒鹽噪聲。
下面五幅圖分別代表了,原圖,以及添加了高斯噪聲,泊松噪聲,乘性噪聲,椒鹽噪聲的圖像。
2.3.1 原圖

2.3.2 高斯噪聲(下圖)
高斯噪聲是指它的概率密度函數服從高斯分布(即正態(tài)分布)的一類噪聲。如果一個噪聲,它的幅度分布服從高斯分布,而它的功率譜密度又是均勻分布的,則稱它為高斯白噪聲。高斯白噪聲的二階矩不相關,一階矩為常數,是指先后信號在時間上的相關性。(什么是二階矩?什么是功率譜密度?)
產生原因:
1)圖像傳感器在拍攝時市場不夠明亮、亮度不夠均勻;
2)電路各元器件自身噪聲和相互影響;
3)圖像傳感器長期工作,溫度過高。
2.3.2.1 一、二階矩
數學上,“矩”是一組點組成的模型的特定的數量測度。 在力學和統(tǒng)計學中都有用到“矩”。
如果這些點代表“質量”,那么:
零階矩表示所有點的質量; 一階矩表示質心;
二階矩表示轉動慣量。
如果這些點代表“概率密度”,那么:
零階矩表示這些點的 總概率(也就是1);
一階矩表示 期望;
二階(中心)矩表示 方差;
三階(中心)矩表示 偏斜度;
四階(中心)矩表示 峰度;
這個數學上的概念和物理上的“矩”的概念關系密切。
參考網站:
https://en.wikipedia.org/wiki/Moment_%28mathematics%29
注意:(理解一下,就可以。大概以后處理一些不確定的概率問題,涉及統(tǒng)計學,需要詳解)
2.3.2.1 功率譜密度
波的功率頻譜???
功率
功率是指物體在單位時間內所做的功的多少,即功率是描述做功快慢的物理量。
功率譜是什么?(功率頻譜大概就是功率譜傅里葉變換之后的玩意,小嗷猜的)
生活中很多東西之間都依靠信號的傳播,信號的傳播都是看不見的,但是它以波的形式存在著,這類信號會產生功率,單位頻帶的信號功率就被稱之為功率譜。
(不懂什么是頻帶參考第21篇文章)
打個比方:這條路,1秒內通過的8個人。1次只能同時通過4個人。
那么1秒的功率是8個人,8/1=8;
再重新看這句話,把這類信號會產生功率(1秒內通過的8個人),單位頻帶(1次只能同時過4個人)的信號功率就被稱之為功率譜。
它可以顯示在一定的區(qū)域中信號功率隨著頻率變化的分布情況。
而頻譜也是相似的一種信號變化曲線,在科學的領域里,功率譜和頻譜有著一定的聯系,但是它們之間還是不一樣的,是有區(qū)別的。
功率譜密度
在頻譜分析中幅度和功率是由緊密聯系的兩個不同的物理量:
能量能表述為幅值的平方和,也能表述為功率在時間上的積分;
功率譜密度,是指用密度的概念表示信號功率在各頻率點的分布情況,是對隨機變量均方值的量度,是單位頻率的平均功率量綱;
也就是說,對功率譜在頻域上積分就可以得到信號的平均功率,而不是能量。能量譜密度是單位頻率的幅值平方和量綱,能量譜密度曲線下面的面積才是這個信號的總能量。
于是,功率譜、能量譜、幅值譜之間的緊密關系主要表述為:能量譜是功率譜密度函數在相位上的卷積,也是幅值譜密度函數的平方在頻率上的積分;功率譜是信號自相關函數的傅里葉變換,能量譜是信號本身傅立葉變換幅度的平方。
功率譜相關釋義:
盡管并非一定要為信號或者它的變量賦予一定的物理量綱,下面的討論中假設信號在時域內變化。上面能量譜密度的定義要求信號的傅里葉變換必須存在,也就是說信號平方可積或者平方可加。
一個經常更加有用的替換表示是功率譜密度(PSD),它定義了信號或者時間序列的功率如何隨頻率分布。這里功率可能是實際物理上的功率,或者更經常便于表示抽象的信號被定義為信號數值的平方,也就是當信號的負載為1歐姆(ohm)時的實際功率。
此瞬時功率(平均功率的中間值)可表示為:

由于平均值不為零的信號不是平方可積的,所以在這種情況下就沒有傅里葉變換。幸運的是維納-辛欽定理(Wiener-Khinchin theorem)提供了一個簡單的替換方法,如果信號可以看作是平穩(wěn)隨機過程,那么功率譜密度就是信號自相關函數的傅里葉變換。
功率譜和頻譜的區(qū)別
1、計算
功率譜的計算需要信號先做自相關,然后再進行FFT運算。
頻譜的計算則是將信號直接進行FFT就行了。
2、方式
功率譜是對信號研究,不過它是從能量的方面來對信號研究的。
而頻譜也是用來形容信號的,只是的表示方式變了,從時域轉變成了頻域表示,也就是說一種信號的表示方式不同而已。
功率譜與頻譜和的區(qū)別歸根結底就是信號、功率、能量三者之間的關聯。
3、定義
功率譜的定義是在有限信號的情況下,單位頻帶范圍內信號功率的變換狀況,功率隨頻率而變化,從而表現成為功率譜,它是專門對功率能量的可用有限信號進行分析所表現的能量。它含有頻譜的一些幅度信息,不過相位信息被舍棄掉了。
相比之下,頻譜極為不嚴格,主要是體現信號的平均變換,要求的只是一段時間平均量。
所以經常說在頻譜信號不同的情況下,它的功率譜很可能是一樣的。
4、性質
功率譜雖然過程是隨機的,但由于統(tǒng)計的是平均概念,就相當于平穩(wěn)的隨機過程,這個過程的功率譜則是一個確定性的函數。
而頻譜的樣本進行Fourier變換,盡管過程也是隨機的,但是對于這個隨機變化過程來說,頻譜形成的是隨機的頻域序列,函數不確定。
5、要求
功率譜和頻譜的功率極其幅度的概念也是有差別,并且它們的存在性要求也是不同的。功率譜的存在性要求變化收斂,而頻譜的存在性只要求了是否收斂。
功率譜和頻譜有相同的地方,并且有著聯系,可這些區(qū)別才是決定它們兩個用處的重要之處。功率譜和頻譜雖然都是對信號的研究,但是研究的方向不同,角度也不相同,并且它們的性質存在不同之處,功率譜的隨機性更差一點,比較嚴謹,有確定的函數支撐;而頻譜的要求更少一些,隨機性頗強,導致了它的信號變化,不過這也是它的研究價值所在。
內容來源:土巴兔
注意:(理解一下,就可以。大概以后處理一些不確定的概率問題,涉及統(tǒng)計學,需要詳解)
2.3.3 泊松噪聲(下圖)
泊松噪聲,就是符合泊松分布的噪聲模型,泊松分布適合于描述單位時間內隨機事件發(fā)生的次數的概率分布。
如某一服務設施在一定時間內受到的服務請求的次數,電話交換機接到呼叫的次數、汽車站臺的候客人數、機器出現的故障數、自然災害發(fā)生的次數、DNA序列的變異數、放射性原子核的衰變數等等
2.3.4 乘性噪聲(下圖)
乘性噪聲一般由信道不理想引起,它們與信號的關系是相乘,信號在它在,信號不在他也就不在。
2.3.5 椒鹽噪聲(下圖)
椒鹽噪聲,椒鹽噪聲又稱脈沖噪聲,它隨機改變一些像素值,是由圖像傳感器,傳輸信道,解碼處理等產生的黑白相間的亮暗點噪聲。
椒鹽噪聲往往由圖像切割引起。
圖像噪聲使圖像在獲取或是傳輸過程中收到隨機信號干擾,妨礙人們對圖像理解及分析處理的信號。很多時候將圖像噪聲看做多維隨機過程,因而描述噪聲的方法完全可以借用隨機過程的描述,也就是使用隨機過程的描述,也就是用它的高斯分布函數和概率密度分布函數。圖像噪聲的產生來自圖像獲取中的環(huán)境條件和傳感元器件自身的質量,圖像在傳輸過程中產生圖像噪聲的主要因素是所用的傳輸信道收到了噪聲的污染。
先簡單介紹一下相關API函數:
3.1 at()函數(在Mat)
at類中的at方法對于獲取圖像矩陣某點的RGB值或者改變某點的值很方便。
對于單通道的圖像,則可以使用:
如:XXX.at<uchar>(i, j)=255(因為單通道(灰度圖),由黑到白)
(坐標(i, j)上,像素點的值為白色)
對于多通道的圖像(BGR),如
img.at<Vec3b>(14,25) [0]= 25;//B
img.at< Vec3b >(14,25) [1]= 25;//G
img.at< Vec3b >(14,25 [2]= 25;//R
3.2 rand()函數
rand()函數是產生隨機數的一個隨機函數。
如:rand()%3是什么意思?
rand()是偽隨機數生成函數,%是模運算,這個表達式的作用是隨機生成012三個數字中的一個。
3.3 下面簡單寫寫兩種圖像噪聲,即椒鹽噪聲和高斯噪聲。
3.4 椒鹽噪聲是什么?
椒鹽噪聲也稱為脈沖噪聲,是圖像中經常見到的一種噪聲,它是一種隨機出現的白點或者黑點,可能是亮的區(qū)域有黑色像素或是在暗的區(qū)域有白色像素(或是兩者皆有)。鹽和胡椒噪聲的成因可能是影像訊號受到突如其來的強烈干擾而產生、類比數位轉換器或位元傳輸錯誤等。例如失效的感應器導致像素值為最小值,飽和的感應器導致像素值為最大值。
圖像模擬添加椒鹽噪聲是通過隨機獲取像素點并設置為高亮度點和低灰度點來實現的
即:隨機設置一些像素點為白色或者黑色。
圖像添加椒鹽噪聲的程序如下:
/
//利用程序給原圖像增加椒鹽噪聲
//圖象模擬添加椒鹽噪聲是通過隨機獲取像素點斌那個設置為高亮度點來實現的
1#include <cstdlib> 2#include <iostream> 3#include <opencv2\core\core.hpp> 4#include <opencv2\highgui\highgui.hpp> 5#include <opencv2\imgproc\imgproc.hpp> 6using namespace cv; 7using namespace std; 8Mat addSaltNoise(const Mat srcImage, int n); 9int main()10{ 11 Mat srcImage = imread("D://原圖.jpg");12 if (!srcImage.data)13 {14 cout << "讀入圖像有誤!" << endl;15 system("pause");16 return -1;17 }18 imshow("原圖像", srcImage);19 Mat dstImage = addSaltNoise(srcImage, 3000);20 imshow("添加椒鹽噪聲的圖像", dstImage);21 //存儲圖像 22 imwrite("salt_pepper_Image.jpg", dstImage);23 waitKey();24 return 0;25}26Mat addSaltNoise(const Mat srcImage, int n)27{28 //克隆一張一摸一樣的圖29 Mat dstImage = srcImage.clone();30 for (int k = 0; k < n; k++)31 {32 //隨機取值行33 //rand()是偽隨機數生成函數,%是模運算,這個表達式的作用是隨機生成012三個數字中的一個。34 int i = rand() % dstImage.rows;35 int j = rand() % dstImage.cols;36 //圖像通道判定 37 if (dstImage.channels() == 1)38 {39 dstImage.at<uchar>(i, j) = 255; //鹽噪聲 40 }41 else42 {43 dstImage.at<Vec3b>(i, j)[0] = 255;44 dstImage.at<Vec3b>(i, j)[1] = 255;45 dstImage.at<Vec3b>(i, j)[2] = 255;46 }47 }48 for (int k = 0; k < n; k++)49 {50 //隨機取值行列 51 int i = rand() % dstImage.rows;52 int j = rand() % dstImage.cols;53 //圖像通道判定 54 if (dstImage.channels() == 1)55 {56 dstImage.at<uchar>(i, j) = 0; //椒噪聲 57 }58 else59 {60 dstImage.at<Vec3b>(i, j)[0] = 0;61 dstImage.at<Vec3b>(i, j)[1] = 0;62 dstImage.at<Vec3b>(i, j)[2] = 0;63 }64 }65 return dstImage;66}
原圖
椒鹽圖
就是隨機分布黑白像素點
3.5 高斯噪聲(基于Box–Muller變換的正態(tài)隨機數生成方法)
根據Box-Muller變換原理,建設隨機變量U1、U2來自獨立的處于(0,1)之間的均勻分布,則經過下面兩個式子產生的隨機變量Z0,Z1服從標準高斯分布。
定理(Box-Muller變換):如果隨機變量U1和U2是IID的,且U1,U2 ~Uniform[0, 1],則
Z0和Z1獨立且服從標準正態(tài)分布。
如何來證明這個定理呢?這需要用到一些微積分中的知識,首先回憶一下二重積分化為極坐標下累次積分的方法:
假設現在有兩個獨立的標準正態(tài)分布 X~N(0,1) 和 Y~N(0,1),由于二者相互獨立,則聯合概率密度函數為
做極坐標變換,則x=Rcosθ,y=Rsinθ,則有
你可以看到這個結果可以看成是兩個概率分布的密度函數的乘積,其中一個可以看成是[0, 2π]上均勻分布,將其轉換為標準均勻分布則有θ ~Unif (0, 2π)=2π U2。
另外一個的密度函數為

則其累計分布函數CDF為
這個CDF函數的反函數可以寫成
根據逆變換采樣的原理,如果我們有個PDF為P(R)的分布,那么對齊CDF的反函數進行均勻采樣所得的樣本分布將符合P(R)的分布,而如果 u 是均勻分布的,那么 U1 = 1-u 也將是均勻分布的,于是用 U1 替換1-u,最后可得
結論得證。最后我們來總結一下利用Box-Muller變換生成符合高斯分布的隨機數的方法:
圖像添加高斯噪聲的程序如下:
1//給圖像添加高斯噪聲 2#include <cmath> 3#include <limits> 4#include <cstdlib> 5#include <iostream> 6#include <opencv2\core\core.hpp> 7#include <opencv2\highgui\highgui.hpp> 8using namespace cv; 9using namespace std;10double generateGaussianNoise(double m, double sigma);11Mat addGaussianNoise(Mat &srcImag);12int main()13{14 Mat srcImage = imread("D://3.jpg");15 if (!srcImage.data)16 {17 cout << "讀入圖片錯誤!" << endl;18 system("pause");19 return -1;20 }21 imshow("原圖像", srcImage);22 Mat dstImage = addGaussianNoise(srcImage);23 imshow("添加高斯噪聲后的圖像", dstImage);24 waitKey();25 return 0;26}27//生成高斯噪聲 28double generateGaussianNoise(double mu, double sigma)29{30 //定義小值 31 const double epsilon = numeric_limits<double>::min();32 static double z0, z1;33 static bool flag = false;34 flag = !flag;35 //flag為假構造高斯隨機變量X 36 if (!flag)37 return z1 * sigma + mu;38 double u1, u2;39 //構造隨機變量 40 do41 {42 u1 = rand() * (1.0 / RAND_MAX);43 u2 = rand() * (1.0 / RAND_MAX);44 } while (u1 <= epsilon);45 //flag為真構造高斯隨機變量 46 z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);47 z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);48 return z0*sigma + mu;49}50//為圖像添加高斯噪聲 51Mat addGaussianNoise(Mat &srcImag)52{53 Mat dstImage = srcImag.clone();54 int channels = dstImage.channels();55 int rowsNumber = dstImage.rows;56 int colsNumber = dstImage.cols*channels;57 //判斷圖像的連續(xù)性 58 if (dstImage.isContinuous())59 {60 colsNumber *= rowsNumber;61 rowsNumber = 1;62 }63 for (int i = 0; i < rowsNumber; i++)64 {65 for (int j = 0; j < colsNumber; j++)66 {67 //添加高斯噪聲 68 int val = dstImage.ptr<uchar>(i)[j] +69 generateGaussianNoise(2, 0.8) * 32;70 if (val < 0)71 val = 0;72 if (val>255)73 val = 255;74 dstImage.ptr<uchar>(i)[j] = (uchar)val;75 }76 }77 return dstImage;78}
效果圖

本人是抱著玩一玩的心態(tài),學習opencv(其實深度學習沒有外界說的這么高深,小嗷是白板,而且有工作在身并且于代碼無關)
大家可以把我的數學水平想象成初中水平,畢竟小嗷既不是代碼靠吃飯又不是靠數學吃飯,畢業(yè)N年
寫文章主要是為了后人少走點彎路,多交點朋友,一起學習
如果有好的圖像識別群拉我進去QQ:631821577
就我一個白板,最后還是成的,你們別怕,慢慢來把
分享可以無數次,轉載成自己文章QQ郵箱通知一下,未經授權請勿轉載。
QQ群:736854977
有什么疑問公眾號提問,下班或者周六日回答,ths
算算涉及知識:高數/矩陣分析/線性代數/統(tǒng)計學/OpenCV庫/C++或者PY
(今天不懂知識點,基本來自統(tǒng)計學。上學到工作,小嗷摸都沒摸統(tǒng)計學。)
慫的話,現在可以放棄。(當然,小嗷會每篇補一點相關的數學。)
線性代數網址(線性代數看視頻吧,少年):
http://open.163.com/special/opencourse/daishu.html
代碼鏈接:
https://pan.baidu.com/s/1BWts9jJGgY4Jm4xAa4-5XA
密碼:17kb
推薦文章:
無