文章目錄
- 介紹
- 使用低通濾波器對圖像進行濾波
- 工作原理
- 均值濾波器(Mean Filter / Box Filter)
- 高斯濾波器(Gaussian Filter)
- 案例實現
- 通過濾波實現圖像的下采樣
- 工作原理
- 實現案例
- 插值像素值(Interpolating pixel values)
- 雙線性插值(Bilinear interpolation)
- 雙三次插值(Bicubic interpolation)
- 使用中值濾波器處理圖像
- 工作原理
- 案例實現
- 應用方向濾波器檢測邊緣
- 使用 Sobel 方向濾波器進行邊緣檢測
- 工作原理
- 案例實現
- 梯度算子(Gradient Operators)
- 高斯濾波器的導數(Gaussian derivatives)
- 圖像拉普拉斯變換
- 案例實現
- 使用拉普拉斯增強圖像對比度
- 高斯差分(Difference of Gaussians, DoG)
介紹
圖像是由不同的灰度(或顏色)模式組成的。圖像之間的區別在于它們的灰度分布不同。然而,還可以從另一個角度來分析圖像——觀察圖像中灰度值的變化。
一些圖像包含大面積幾乎恒定的亮度區域(例如藍天),而另一些圖像中的灰度值變化非常迅速(例如擁擠的小物體場景)。因此,觀察圖像中這些變化的頻率是表征圖像的另一種方式。這種視角被稱為頻率域(frequency domain),而通過觀察灰度分布來描述圖像的方式稱為空間域(spatial domain)。
頻率域分析將圖像分解為從最低到最高的頻率成分。圖像中亮度變化緩慢的區域僅包含低頻成分,而高頻成分則來源于亮度的快速變化。
如傅里葉變換或余弦變換,可以明確顯示圖像的頻率內容。由于圖像是二維的,它同時包含垂直方向和水平方向的頻率。
在頻率域分析框架下,濾波是一種增強(或保留)某些頻率帶、同時抑制其他頻率帶的操作。
低通濾波器(low-pass filter)會消除圖像的高頻成分;相反,高通濾波器(high-pass filter)會消除低頻成分。
使用低通濾波器對圖像進行濾波
低通濾波器是一種線性濾波器,其核心思想是用一個卷積核(kernel) 對圖像中的每個像素進行加權平均操作。
低通濾波器的主要作用是對圖像進行模糊和平滑。因為這種濾波器會抑制高頻成分,而高頻成分正是圖像邊緣處快速變化所對應的特征
OpenCV 提供了多種低通濾波方法,用于平滑圖像、去除噪聲、模糊細節。主要函數包括:
- cv::blur():均值濾波
- cv::GaussianBlur():高斯濾波
工作原理
均值濾波器(Mean Filter / Box Filter)
每個像素被替換為它周圍區域像素的平均值;
卷積核中所有權重相同(例如 3x3 均值濾波核如下):
函數:cv::blur() 或 cv::boxFilter();
效果:模糊圖像、去噪,但邊緣會變得模糊不清
高斯濾波器(Gaussian Filter)
使用一個服從高斯分布的卷積核;
中心像素權重最大,遠離中心的像素權重逐漸減小;
更好地保留邊緣信息;
函數:cv::GaussianBlur();
示例核大小:5x5,σ=1.5;
可分離計算:先水平方向,再垂直方向,提高效率;
像素的權重與其到中心像素的距離成反比。一維高斯函數的形式如下:
歸一化系數 A 的選取使得高斯曲線下的面積等于 1。σ(sigma)值控制了高斯函數的寬度。σ 越大,函數越平坦。
例如,在 σ = 0.5 時,計算區間 [-4, 0, 4] 上的一維高斯濾波器系數,得到如下結果:
[0.0 0.0 0.00026 0.10645 0.78657 0.10645 0.00026 0.0 0.0]
當 σ = 1.5 時,系數變為:
[0.0076 0.03608 0.1096 0.2135 0.2667 0.2135 0.1096 0.0361 0.0076]
這些系數可以通過調用 OpenCV 函數 cv::getGaussianKernel 得到:
cv::Mat gauss = cv::getGaussianKernel(9, sigma, CV_32F);
調用 cv::GaussianBlur() 時:
可指定核大小和 σ 值;
若將 σ 設為 0,則 OpenCV 自動根據核大小選擇合適的 σ;
若將核大小設為 cv::Size(0, 0),則自動根據 σ 計算核大小。
兩種 σ 值對應的高斯曲線如圖所示。高斯函數對稱的“鐘形”形狀使其成為濾波的理想選擇。
距離中心越遠的像素權重越低,從而使得像素之間的過渡更加平滑。這與均值濾波中遠離中心的像素可能引起當前平均值突變的情況形成對比。從頻率角度看,這意味著均值濾波并不能完全去除所有高頻成分。
要對圖像應用二維高斯濾波器,可以先對圖像的每一行應用一維高斯濾波器(用于濾除水平方向的高頻),然后再對圖像的每一列應用一維高斯濾波器(用于濾除垂直方向的高頻)。因為高斯濾波器是可分離濾波器(即二維核可以分解為兩個一維核)。OpenCV 中提供了 cv::sepFilter2D 函數用于實現一般的可分離濾波。也可以直接使用 cv::filter2D 應用一個二維核。一般來說,可分離濾波器由于所需乘法運算更少,因此計算效率更高。
在 OpenCV 中使用 cv::GaussianBlur 函數時,可以同時指定核的大小(第三個參數,必須為奇數)和 σ 值(第四個參數)。你也可以只設置 σ 值,讓 OpenCV 自動決定合適的核大小(此時核大小設為 0);或者反之,輸入核大小并設置 σ 為 0,OpenCV 將根據核大小自動確定最合適的 σ 值。
案例實現
#include <opencv2/opencv.hpp>int main() {// 讀取圖像(灰度圖)cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr << "無法加載圖像!" << std::endl;return -1;}cv::Mat blurResult, gaussianResult;// 均值濾波(Box Filter)cv::blur(image, blurResult, cv::Size(5, 5));// 高斯濾波cv::GaussianBlur(image, gaussianResult, cv::Size(5, 5), 1.5);// 顯示結果cv::imshow("Original", image);cv::imshow("Blur Result", blurResult);cv::imshow("Gaussian Result", gaussianResult);cv::waitKey(0);return 0;
}
#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 1. 讀取圖像(灰度圖)cv::Mat image = cv::imread(IMAGE_1, cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr << "無法加載圖像,請確認路徑是否正確!" << std::endl;return -1;}// 2. 定義高斯濾波參數int kernelSize = 5; // 核大小(必須為奇數)double sigma = 1.5; // 高斯標準差// 3. 應用高斯濾波cv::Mat filteredImage;cv::GaussianBlur(image, filteredImage, cv::Size(kernelSize, kernelSize), sigma);// 4. 可選:獲取并顯示一維高斯核(用于理解權重分布)cv::Mat gaussianKernel = cv::getGaussianKernel(kernelSize, sigma, CV_32F);std::cout << "一維高斯核(kernel size = " << kernelSize << ", sigma = " << sigma << "):\n" << gaussianKernel << std::endl;// 5. 顯示結果cv::imshow("Original Image", image);cv::imshow("Gaussian Filtered Image", filteredImage);// 等待按鍵關閉窗口cv::waitKey(0);cv::destroyAllWindows();return 0;
}
通過濾波實現圖像的下采樣
圖像經常需要調整大小(重采樣)。將圖像尺寸縮小的過程通常稱為下采樣,而放大則稱為上采樣。執行這些操作面臨的挑戰是盡可能保留圖像的視覺質量。為了實現這一目標,通常使用低通濾波器來去除高頻成分,防止出現混疊(aliasing)現象。
圖像中包含的高頻信息(如細節、邊緣)在縮小后無法被小尺寸圖像正確表示,從而產生空間混疊。
因此,在下采樣前應先應用低通濾波器。
工作原理
- 圖像縮小前必須進行低通濾波,以去除不能在小尺寸圖像中正確表示的高頻成分;
- 理論依據是 奈奎斯特-香農采樣定理:若將圖像縮小 N 倍,則可表示的頻率范圍也減少 N 倍;
- OpenCV 提供了封裝函數 cv::pyrDown() 和 cv::resize() 來簡化操作。
cv::Mat reduced;
cv::pyrDown(image, reduced); // 縮小為原來的一半
cv::pyrDown() 內部使用了一個 5x5 的高斯核進行濾波后再下采樣。
cv::Mat resized;
cv::resize(image, resized, cv::Size(image.cols / 4