Programming 3
Image Filtering and Edge Detection
1.denoise.cpp: write a program code to run Gaussian, Mean, and Median filters for one image.
Gaussian Filter(高斯濾波器):
使用高斯函數作為權值,將像素周圍的值進行加權平均,權值越高,像素的貢獻越大,因此高斯濾波器可以更好地保留圖像細節。高斯濾波器對於消除高斯噪聲效果良好。
Mean Filter(均值濾波器):
使用相鄰像素的平均值來取代每個像素,因此平均濾波器可以有效地平滑圖像,但是會使圖像細節模糊。
Median Filter(中值濾波器):
使用相鄰像素的中值來取代每個像素。這種方法通常比均值濾波器更好地消除機器或隨機噪聲,並且能夠保留圖像邊緣和細節。
原圖尺寸480*270。
image。
1.將影像讀取為灰階影像並顯示。
2.對影像進行高斯濾波處理,kernel 分別設定為 3x3 , 7x7 , 11x11 並顯示,目的為觀察 kernel 大小對結果的影響。
sigma 均為 5。
3.對影像進行均值濾波處理,kernel 分別設定為 3x3 , 7x7 , 11x11 並顯示,目的為觀察 kernel 大小對結果的影響。
4.對影像進行中值濾波處理,kernel 分別設定為 3x3 , 7x7 , 11x11 並顯示,目的為觀察 kernel 大小對結果的影響。
Gaussian Filter 3x3。
7x7。
11x11。
Mean Filter 3x3。
7x7。
11x11。
Median Filter 3x3。
7x7。
11x11。
結果分析:
以相同影像去做不同方式的模糊濾波處理得到的結果中,kernel 使用越大會有越模糊的效果,而其中高斯及均值濾波的效果比較接近,而中值濾波在 kernel 為 11x11 時,部分邊緣已經丟失,所以在做中值濾波時,如果需要保留影像內較細的邊緣或細節時,要避免設定過大的 kernel 。
將 Gaussian Filter 的 kernel 固定為 3x3 ,改變 simga 的值分別為 1、3、9 並顯示,目的為觀察參數 simga 對高斯濾波結果的影響。
kernel 3x3,simga=1。
kernel 3x3,simga=9。
觀察 sigma 為 1 和 9 時發現並沒有太大的不同,這也許是 kernel 過小導致。
kernel 7x7,simga=1。
kernel 7x7,simga=9。
將 kernel 改為 7x7 時,就有明顯的改變,影像顯得更模糊了。
高斯濾波中的 sigma 是控制高斯函數的標準差,用來控制模糊的程度。
當 sigma 值越大時,高斯分佈曲線的寬度就越大,對應的高斯濾波核的大小就越大,從而產生更明顯的模糊效果。而當 sigma 值較小時,則高斯分佈曲線的寬度就較窄,對應的高斯濾波核的大小就較小,從而產生較弱的模糊效果。
通常情況下,kernel size 的大小是由 sigma 決定的,kernel_size = 2 * (int)(3 * sigma) + 1。
改變邊緣填充方式,將邊緣補充的像素填入常數 0 黑色,目的為觀察不同的邊緣補充選擇對結果的影響,使用這個方法出現了黑邊的現象。
BORDER_CONSTANT:用常數填充邊緣。
BORDER_REPLICATE:用邊緣像素填充邊緣。
BORDER_REFLECT:對邊緣進行鏡像反轉填充。
BORDER_WRAP:對邊緣進行循環填充。
BORDER_REFLECT_101:與BORDER_REFLECT類似,但邊緣像素不會被重複。
將之前在 Program1 對 car.jpg 做的兩張 salt and pepper 影像分別也做上述三種濾波處理,參數也參照以上參數設定。
salt_and_pepper 2%。
salt_and_pepper 4%。
Gaussian Filter 3x3。
7x7。
11x11。
Mean Filter 3x3。
7x7。
11x11。
Median Filter 3x3。
7x7。
11x11。
結果分析:
觀察結果發現在處理 salt and pepper 雜訊時,均值濾波比高斯濾波和中值濾波更有效,salt and pepper 雜訊在圖像中引入極端的值,0 和 255,而均值濾波可以平均化這些極端值,使圖像更平滑。
相比之下,高斯濾波可能會使圖像變得模糊,而中值濾波可能會無法處理極端值,導致圖像仍然存在噪點。
對於 salt and pepper 雜訊,均值濾波通常是最好的選擇。
接著我們使用 salt and pepper 4% 的影像,觀察三種濾波 kernel 在3x3的效果。
Gaussian Filter 3x3。
Mean Filter 3x3。
Median Filter 3x3。
結果分析:
Median Filter 的去雜訊效果還是非常好,不過可以發現有一點點極端雜訊殘留,相對 Gaussian Filter 和 Mean Filter,將雜訊極端值變得平滑一些,但大部分的雜訊還是存在的。
2.edge_detection: write a program code to run Sobel and Laplacian filters.
Sobel Filter :
Sobel是一種常見的邊緣檢測算法,它基於對圖像的微分運算來檢測圖像中的邊緣。該算法的基本原理是對圖像使用一個3x3的遮罩或卷積核進行水平和垂直方向上的運算 (如右圖),然後將其結果相加以得出邊緣強度。
Sobel算法的優點是可以快速且準確地檢測邊緣。由於只考慮了相鄰像素之間的關係,因此計算速度非常快。但是,它對噪聲比較敏感,還可能會產生一些假的邊緣,因此需要進一步的後處理,如非最大值抑制、雙閾值分割等,來提高邊緣檢測的準確度。
Laplacian Filter :
Laplacian是一種圖像處理算法,可以檢測圖像中的邊緣和紋理。
它的原理基於二階微分算子,通過計算圖像的二階導數,可以檢測圖像中的變化率,即圖像上的邊緣和紋理。
Laplacian算子是一種離散算子,可以在空間中定位圖像的二階導數,並且在一定程度上可以抑制圖像的噪聲。它將每個像素周圍的8個鄰域像素的加權平均值減去中心像素的值,得到一個數值。這個數值可以表示該像素的曲率,如果該像素周圍有邊緣或紋理,則該值會比較大,否則該值會比較小。通過對圖像中的所有像素應用Laplacian算子,可以得到一個新的圖像,其中每個像素的值都代表了該像素周圍的曲率。因此,Laplacian算子可以被用來檢測圖像中的邊緣和紋理。
在Laplacian算子的運用中,需要注意它對噪聲的敏感性。由於Laplacian算子對噪聲也有一定的響應,因此在使用時,需要先對圖像進行平滑處理,以減少噪聲對算法的干擾。另外,Laplacian算子還可以與其他算子結合使用,如Sobel算子、Canny算子等,以實現更精確的邊緣檢測。
原影像 480x270。
讀取原影像為灰階模式 image。
這段程式碼使用 OpenCV 中的 Sobel 函數來計算一個圖像在水平方向Sobel X 和垂直方向 Sobel Y 的邊緣強度變化導數,目的是強化邊緣。
函數中,參數 1,0 代表 X 方向,0,1則代表Y方向,3 是 kernel 尺寸 3x3,0.4是 Sobel 算子的縮放因子,用於控制邊緣的強度,而128是加法常數,用於平移像素值。
它的原理是基於圖像的微分運算,通過計算圖像中每個像素點的梯度值,來識別出邊緣。
X方向。
Y方向。
將Y方向的縮放因子改為 0.1 ,強度明顯減弱。
將 X 方向的平移像素質改為 0。
當圖像中存在平移增強時,這些增強區域的梯度值會明顯高於周圍的像素,這樣就會導致整體梯度值的增加。如果沒有平移增強的情況下,梯度值就會比較平均,因此總體梯度強度會較低。
將 X 方向 Sobel 以 7x7 的 kernel操作,0.4的縮放因子,128的平移增強。
此結果發現出現太多多餘的邊緣,連平的路面都產生邊緣,疑似縮放因子設定太大導致。
縮放因子0.01。
縮放因子0.001。
調整後發現,kernel 加大時的邊緣結果會比較粗,這是因為覆蓋的範圍較大,但相對雜訊(路面)會比較少一點。
分別計算 Sobel 算子對 X 方向和 Y 方向的運算結果,再透過絕對值函數取得其絕對值,最後加總兩個運算結果,得到一個代表邊緣強度的影像。
使用 minMaxLoc 函數找出這個影像中最小和最大的像素值,分別存入 sobmin 和 sobmax 變數中,並輸出。這樣做的目的是為了將 Sobel 運算後的影像進行歸一化處理,以方便後續的影像處理。
sobel 的範圍為 0~1428。
將 sobel 轉換成CV_8U 型態目的為顯示,接著進行兩次閥值分別為225與200的 threshold 達到二值化影像的結果,不同閥值會影響最終邊緣的結果。
在進行 CV_16S 型態轉換成 CV_8U 型態時,像素值的範圍從原本的 [-32768, 32767] 映射到 [0,255]。所以在進行型態轉換時,需要進行縮放以防止像素值超過255,同時又要讓像素值盡量分布在0到255的範圍內,這裡的 -255./sobmax 就是縮放係數。
另外,因為sobel算子是將邊緣梯度的絕對值當成輸出值,所以sobel影像的像素值範圍會在0到某一個正數之間,sobmax就是這個正數的值。
因此,-255./sobmax的目的是讓 sobelImage 中的最大值為255,最小值為0,同時根據sobelImage 中的像素值範圍分布進行平移強化。
Sobel Image
Binary Sobel Image (225)。
Binary Sobel Image (200)。
結果分析:
在實現上,Sobel算子使用一個3x3的卷積核對圖像進行遍歷,對每個像素點計算出其水平方向和垂直方向的梯度值,進而得到梯度強度和梯度方向。梯度強度反映了像素值變化的大小,而梯度方向則描述了變化方向。
通過對梯度強度進行二值化處理,可以將圖像中的邊緣區域提取出來,從而達到圖像分割、目標檢測等目的。
Sobel 還存在一些問題,如對於曲線和直線的檢測效果不同,對於像素值變化較緩和的區域容易出現誤判等。
將影像進行 Laplacian 操作,以CV_8U型態,kernel size 設定 1 為 3x3,縮放因子為 1,以及 128 的平移增強。
Laplacian Image。
使用 LaplacianZC 類別定義的一個名為 computeLaplacian 的函式,用來計算拉普拉斯濾波後的影像,並返回一個cv::Mat型態的影像。在這個函式中,參數 setAperture 用來設定拉普拉斯濾波器的大小,預設為3,這邊設定為7。最終輸出的影像儲存在flap中。
使用 minMaxLoc 找出 flap 中最大及最小值。
透過 getLaplacianImage 函式生成拉普拉斯濾波後的影像並輸出。
Laplacian Image (7x7)。
在影像中擷取 12x12 的矩形範圍,這個範圍包含了邊緣在內,目的為觀察邊緣強化前後的變化。
將 window 範圍以白色矩形繪製並顯示。
Original Image with window
window。
包含邊緣。
Image values : 下一步驟中輸出的 window 像素值,可以觀察到與影像相同位置有梯度存在。
從原始影像及 Laplacian Image (7x7) 中輸出剛剛設定矩形位置所有像素值。
從剛剛取得的 Laplacian value range 最小最大值得知範圍[-96948,74104],為了方便顯示及觀察,將數值除以 100 輸出。
從 flap 影像中的矩形範圍發現類似邊緣的區間。
使用 laplacian 物件的 getZeroCrossings 函式,來檢測拉普拉斯變換後的影像中,是否有零交叉(Zero Crossing)的位置,這些位置表示著影像的邊緣。函式的輸入是經過拉普拉斯變換後的影像,輸出是一個二值影像,其中值為 255 表示零交叉的位置,值為 0 則表示其他位置。
將結果的 window 範圍除 255 輸出,目的是讓數值變成 1 和 0,如右圖。
影像輸出255-zeros,黑色的地方代表邊緣。
包含了非常多雜訊。
1代表邊緣。
使用 pyrDown 產生一層高斯下採樣金字塔,將其結果再使用 pyrUp 產生一層拉普拉斯上採樣金字塔。
高斯金字塔是一種多尺度圖像表示方法,它將原始圖像不斷縮小,形成一系列尺度不同但保留了圖像主要特徵的圖像,每個尺度都對應一幅圖像。這種方法可用於圖像的分割、邊緣檢測、特徵提取等多種圖像處理和計算機視覺應用中。高斯金字塔的生成依賴於圖像的高斯模糊操作,因此在金字塔的上層,圖像越來越模糊,分辨率越來越低。高斯金字塔常常和拉普拉斯金字塔一起使用,以進行圖像的區域增強和邊緣檢測。
拉普拉斯金字塔是由高斯金字塔中的每一層圖像和其上一層圖像的差值所構成的一種金字塔結構。每一層圖像都會進行上採樣(即放大)以便與上一層圖像進行差值,所以它也被稱為拉普拉斯上採樣金字塔。拉普拉斯金字塔通常用於圖像增強、邊緣檢測等應用中,能夠突出圖像中的細節特徵,從而使圖像更加清晰、鮮明。
對於以上兩種操作一開始無法理解他們之間相對尺寸關係,所以我輸出影像尺寸確認,下採樣就是一半尺寸,上採樣就是兩倍尺寸,最後的結果和一開始的影像尺寸相同。
Rescaled Image。
rescaled 是下採樣後的輸入影像,image 是原始輸入影像,而 subtract 函數的作用是將 rescaled 和 image 相減,生成差異影像 dog,用來捕捉影像中的高頻細節信息。因此,DoG 影像中的像素值表示該像素在高斯金字塔不同層之間的差異程度,而這種差異可以被視為高頻細節。
差異中幾乎是屬於高頻內容。
最後將差異結果使用 getZeroCrossings 產生出二值化影像。
許多明顯的邊緣,也存在細微的高頻訊號。
結果分析:
Laplacian濾波器可以用於邊緣檢測,它會產生邊緣的二次導數,而邊緣的位置是二次導數為零的地方。
Laplacian濾波器產生的圖像可以用於尋找圖像中的零交錯點,這些點是圖像中的邊緣。
零交錯點的檢測可以通過在 Laplacian 圖像中尋找正值與負值相鄰的像素來實現,改善邊緣檢測的結果,可以用於在圖像中檢測出更細微的邊緣。
3.canny_detector: write a program code to run the Canny edge detector by OpenCV.
Canny 邊緣檢測器由 John F. Canny 於 1986 年開發。也被許多人稱為最佳檢測器,Canny 算法旨在滿足三個主要標準:
低錯誤率:意味著只檢測存在的邊緣。
良好的定位:必須最小化檢測到的邊緣像素和實際邊緣像素之間的距離。
最小響應:每個邊緣只有一個檢測器響應。
讀取影像 car.jpg 為灰階模式,設定兩個閥值50及150,目的是接下來進行 Canny 檢測並顯示。
原圖灰階模式。
Canny檢測後的結果。
當使用Canny邊緣檢測時,每個像素的梯度大小都會與高閥值和低閥值進行比較,可以分成以下三種情況:
像素梯度值大於高閥值:該像素被認為是邊緣點,會被保留。
像素梯度值小於低閥值:該像素被認為不是邊緣點,會被排除。
像素梯度值介於低閥值和高閥值之間:這些像素將被保留作為邊緣點的候選,但必須符合連通性的條件,也就是說,只有當該像素與高閥值的邊緣像素相鄰時,才會被認為是邊緣點。如果該像素未與高閥值的邊緣像素相鄰,則將被排除。
相鄰的像素(adjacent)。
接著我在使用Canny檢測之前加入了高司濾波器,目的是為了減少雜訊,並且將Canny檢測後的結果反白顯示,及黑線為檢測之邊緣。
高司濾波後的影像。
Canny 檢測後的邊緣。
Canny 邊緣檢測方法的優點包括:
准確性高:Canny檢測器通常能夠產生准確的邊緣,因為它使用了多階段過程來檢測邊緣。此外,由於Canny邊緣檢測器是一種基於梯度的方法,它能夠檢測出圖像中較強的邊緣,因此產生的邊緣通常比其他方法更具代表性。
適用性廣:Canny邊緣檢測方法可用於各種圖像處理應用,例如物體偵測、圖像分割、圖像識別等。
低誤檢率:Canny邊緣檢測方法的誤檢率相對較低,因為它通常能夠將圖像中的噪聲濾除,並且只檢測真正的邊緣。
Canny 邊緣檢測方法的缺點包括:
計算成本高:由於Canny邊緣檢測方法需要進行多次圖像處理運算,因此它的計算成本相對較高。
雜訊敏感度高:Canny邊緣檢測方法對圖像中的雜訊非常敏感,並且通常需要對圖像進行預處理來減少雜訊的影響。
參數敏感度高:Canny邊緣檢測方法需要適當的閾值設置才能產生最佳的邊緣檢測結果,因此需要根據不同的圖像進行調整參數。
結果分析:
使用高斯濾波之後的影像再進行Canny檢測,可以更有效的找出主要邊緣,忽略掉一些細小邊緣,如最後結果中在路面上的線條只剩下標線,以及路邊的樹原本的細微邊緣也消失了,而再沒有高斯濾波的情況下這些細節都是存在的,但還是需要以實際應用情況選擇要不要保留這些內容而做不同的流程安排。
原灰階影像的 Canny 檢測。
經過高斯濾波後的 Canny 檢測。
Open Source Computer Vision Canny Edge Detector.Generated on Fri Apr 14 2023 for OpenCV by doxygen 1.8.13.