【從零學習OpenCV 4】圖像中添加高斯噪聲

  • 2019 年 12 月 24 日
  • 筆記

經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》。為了更讓小夥伴更早的了解最新版的OpenCV 4,小白與出版社溝通,提前在公眾號上連載部分內容,請持續關注小白。

OpenCV 4中同樣沒有專門為圖像添加高斯噪聲的函數,對照在圖像中添加椒鹽噪聲的過程,我們可以根據需求利用能夠產生隨機數的函數來完成在圖像中添加高斯噪聲的任務。在OpenCV 4中提供了fill()函數可以產生均勻分佈或者高斯分佈(正態分佈)的隨機數,我們可以利用該函數產生符合高斯分佈的隨機數,之後在圖像中加入這些隨機數即可,我們首先了解該函數的使用方式,該函數的函數原型在代碼清單5-5中給出。

代碼清單5-5 fill()函數原型  1.  void cv::RNG::fill(InputOutputArray mat,  2.                         int  distType,  3.                         InputArray a,  4.                         InputArray b,  5.                         bool  saturateRange = false  6.                         )
  • mat:用於存放隨機數的矩陣,目前只支持低於5通道的矩陣。
  • distType:隨機數分佈形式選擇標誌,目前生成的隨機數支持均勻分佈(RNG::UNIFORM,0)和高斯分佈(RNG::NORMAL,1)。
  • a:確定分佈規律的參數。當選擇均勻分佈時,該參數表示均勻分佈的最小下限;當選擇高斯分佈時,該參數表示高斯分佈的均值。
  • b:確定分佈規律的參數。當選擇均勻分佈時,該參數表示均勻分佈的最大上限;當選擇高斯分佈時,該參數表示高斯分佈的標準差。
  • saturateRange:預飽和標誌,僅用於均勻分佈。

該函數用於生成指定分佈形式的隨機數填充矩陣,可以生成符合均勻分佈的隨機數和符合高斯分佈隨機數。函數的第一個參數輸入用於存儲生成隨機數的矩陣,但是矩陣的通道數必須小於等於4。第二個參數是選擇隨機數分佈形式的標誌,該函數目前只支持兩種分佈形式,分別是均勻分佈(RNG::UNIFORM,簡記0)和高斯分佈(RNG::NORMAL,簡記1)。函數的第三個和第四個參數為確定隨機數分佈規律的參數,第三個參數在均勻分佈時表示均勻分佈的最小下限,在高斯分佈時表示高斯分佈的均值;第四個參數在均勻分佈時表示均勻分佈的最大上限,在高斯分佈時表示高斯分佈的標準差。最後一個參數是預飽和標誌,僅用於均勻分佈,我們使用其默認式即可。需要注意的是該函數屬於OpenCV 4的RNG類,是一個非靜態成員函數,因此在使用的時候不能像使用正常函數一樣的直接使用,而需要首先創建一個RNG類的變量,之後通過訪問這個變量中函數進行調用這個函數,具體使用方式在代碼清單5-6中給出。

代碼清單5-6 RNG::fill()函數的使用  1.  cv::RNG rng;  2.  rng.fill(mat, RNG::NORMAL, 10, 20);

在圖像中添加高斯噪聲大致分為以下4個步驟:

Step1:首先需要創建一個與圖像尺寸、數據類型以及通道數相同的Mat類變量.

Step2:通過調用fill()函數在Mat類變量中產生符合高斯分佈的隨機數。

Step3:將原圖像和含有高斯分佈的隨機數矩陣相加。

Step4:得到添加高斯噪聲之後的圖像。

依照上述思想,在代碼清單5-7中給出了在圖像中添加高斯噪聲的示例程序,程序實現了對灰度圖像和彩色圖像添加高斯噪聲,在圖像中添加高斯噪聲的結果如圖5-8、圖5-9所示,由於高斯噪聲是隨機生成的,因此每次運行結果會有差異。

代碼清單5-7 myGaussNoise.cpp圖像中添加高斯噪聲  1.  #include <opencv2opencv.hpp>  2.  #include <iostream>  3.  4.  using namespace cv;  5.  using namespace std;  6.  7.  int main()  8. {  9.    Mat lena = imread("lena.png");  10.    Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);  11.    if (lena.empty()||equalLena.empty())  12.    {  13.      cout << "請確認圖像文件名稱是否正確" << endl;  14.      return -1;  15.    }  16.    //生成與原圖像同尺寸、數據類型和通道數的矩陣  17.    Mat lena_noise = Mat::zeros(lena.rows, lena.cols, lena.type());  18.    Mat equalLena_noise = Mat::zeros(lena.rows, lena.cols, equalLena.type());  19.    imshow("lena原圖", lena);  20.    imshow("equalLena原圖", equalLena);  21.    RNG rng; //創建一個RNG類  22.    rng.fill(lena_noise, RNG::NORMAL, 10, 20); //生成三通道的高斯分佈隨機數  23.    rng.fill(equalLena_noise, RNG::NORMAL, 15, 30); //生成三通道的高斯分佈隨機數  24.    imshow("三通道高斯噪聲", lena_noise);  25.    imshow("單通道高斯噪聲", equalLena_noise);  26.    lena = lena + lena_noise; //在彩色圖像中添加高斯噪聲  27.    equalLena = equalLena + equalLena_noise; //在灰度圖像中添加高斯噪聲  28.    //顯示添加高斯噪聲後的圖像  29.    imshow("lena添加噪聲", lena);  30.    imshow("equalLena添加噪聲", equalLena);  31.    waitKey(0);  32.    return 0;  33.  }

圖5-8 myGaussNoise.cpp程序中灰度圖添加高斯噪聲結果

圖5-9 myGaussNoise.cpp程序中彩色圖添加高斯噪聲結果