c++gdal如何在大图像中截取小图像并获取其图像信息_【图像处理】OpenCV系列十 --- 边缘检测之Canny算子...
上一篇我們學習了圖像處理形態學相關知識點,相信大家學習之后已經對形態學有了足夠的理解了,那么接下來,我們一起來學習一下圖像處理中的邊緣檢測吧!我們將會重點學習邊緣檢測各種算子和濾波器 --- Canny算子,Sobel算子,Laplace算子以及Scharr濾波器,本篇我們將會學習Canny算子的原理與用法!
一、理論
邊緣檢測是圖像處理和計算機視覺中的基本問題,邊緣檢測的目的是標識數字圖像中亮度變化明顯的點;圖像屬性中的顯著變化通常反映了屬性的重要事件和變化。
這些包括
(i)深度上的不連續
(ii)表面方向不連續
(iii)物質屬性變化
(iv)場景照明變化
邊緣檢測是圖像處理和計算機視覺中,尤其是特征提取中的一個研究領域。
邊緣檢測的一般步驟
1)濾波:邊緣檢測的算法主要是基于圖像強度的一階和二階導數,但導數通常對噪聲很敏感,因此必須采用濾波器來改善與噪聲有關的邊緣檢測器的性能。常見的濾波方法主要有高斯濾波,即采用離散化的高斯函數產生一組歸一化的高斯核(具體見“高斯濾波原理及其編程離散化實現方法”一文),然后基于高斯核函數對圖像灰度矩陣的每一點進行加權求和;
2)增強:增強邊緣的基礎是確定圖像各點鄰域強度的變化值。增強算法可以將圖像灰度點鄰域強度值有顯著變化的點凸顯出來。在具體編程實現時,可通過計算梯度幅值來確定。
3)檢測:經過增強的圖像,往往鄰域中有很多點的梯度值比較大,而在特定的應用中,這些點并不是我們要找的邊緣點,所以應該采用某種方法來對這些點進行取舍。實際工程中,常用的方法是通過閾值化方法來檢測。
二、Canny算子
Canny邊緣檢測算子是John F.Canny于 1986 年開發出來的一個多級邊緣檢測算法。更為重要的是 Canny 創立了邊緣檢測計算理論(Computational theory ofedge detection),解釋了這項技術是如何工作的。Canny邊緣檢測算法以Canny的名字命名,被很多人推崇為當今最優的邊緣檢測的算法。
其中,Canny 的目標是找到一個最優的邊緣檢測算法,讓我們看一下最優邊緣檢測的三個主要評價標準:
- 低錯誤率: 標識出盡可能多的實際邊緣,同時盡可能的減少噪聲產生的誤報;
- 高定位性: 標識出的邊緣要與圖像中的實際邊緣盡可能接近;
- 最小響應: 圖像中的邊緣只能標識一次,并且可能存在的圖像噪聲不應標識為邊緣。
為了滿足這些要求 Canny 使用了變分法,這是一種尋找滿足特定功能的函數的方法。最優檢測使用四個指數函數項的和表示,但是它非常近似于高斯函數的一階導數。
(一)Canny算子的檢測步驟
1.灰度化
把彩色圖像變成灰度圖像,該部分是按照Canny算法通常處理的圖像為灰度圖,如果獲取的彩色圖像,那首先就得進行灰度化。以RGB格式的彩圖為例,通常灰度化采用的公式是:
Gray=0.299R+0.587G+0.114B;
2、高斯濾波
對圖像高斯濾波,圖像高斯濾波的實現可以用兩個一維高斯核分別兩次加權實現,也就是先一維X方向卷積,得到的結果再一維Y方向卷積。當然也可以直接通過一個二維高斯核一次卷積實現。也就是二維卷積模板,由于水平有限,只說二維卷積模板怎么算。
高斯濾波
模板中每一個點的高斯系數可以由上面的公式計算,這樣得到的是不是最終的模板呢?答案不是,需要歸一化,也即是每一個點的系數要除以所有系數之和,這樣才是最終的二維高斯模板。
這個里面有個小知識點,要想計算上面的系數,需要知道高斯函數的標準差σ (sigma),還需要知道選3x3還是5x5的模板,也就是模板要多大,實際應用的時候,這兩者是有關系的,根據數理統計的知識,高斯分布的特點就是數值分布在(μ—3σ,μ+3σ)中的概率為0.9974,也就是模板的大小其實就是6σ這么大就OK了,但是6σ可能不是奇數,因為我們一定要保證有核心。所以模板窗口的大小一般采用1+2ceil(3nSigma) ceil是向上取整函數,例如ceil(0.6)=1;
計算得到模板,那就是直接卷積就OK,卷積的意思就是圖像中的點附近的模板大小區域乘以高斯模板區域,得到的結果就是該點卷積后的結果。卷積的核心意義就是獲取原始圖像中像模板特征的性質。
3.計算梯度幅值和方向
圖像的邊緣可以指向不同方向,因此經典Canny算法用了四個梯度算子來分別計算水平,垂直和對角線方向的梯度。但是通常都不用四個梯度算子來分別計算四個方向。常用的邊緣差分算子(如Rober,Prewitt,Sobel)計算水平和垂直方向的差分Gx和Gy。這樣就可以如下計算梯度模和方向:
梯度模和方向
梯度角度θ范圍從弧度-π到π,然后把它近似到四個方向,分別代表水平,垂直和兩個對角線方向(0°,45°,90°,135°)。可以以±iπ/8(i=1,3,5,7)分割,落在每個區域的梯度角給一個特定值,代表四個方向之一。
這里選擇Sobel算子計算梯度,相對于其他邊緣算子,Sobel算子得出來的邊緣粗大明亮。
sobel算子
這里選擇Sobel算子計算梯度,相對于其他邊緣算子,Sobel算子得出來的邊緣粗大明亮。
4.非極大值抑制
非極大值抑制是進行邊緣檢測的一個重要步驟,通俗意義上是指尋找像素點局部最大值。沿著梯度方向,比較它前面和后面的梯度值進行了。
非極大值抑制
上圖中左右圖:g1、g2、g3、g4都代表像素點,很明顯它們是c的八領域中的4個,左圖中c點是我們需要判斷的點,藍色的直線是它的梯度方向,也就是說c要是局部極大值,它的梯度幅值M需要大于直線與g1g2和g2g3的交點,dtmp1和dtmp2處的梯度幅值。但是dtmp1和dtmp2不是整像素,而是亞像素,也就是坐標是浮點的,那怎么求它們的梯度幅值呢?線性插值,例如dtmp1在g1、g2之間,g1、g2的幅值都知道,我們只要知道dtmp1在g1、g2之間的比例,就能得到它的梯度幅值,而比例是可以靠夾角計算出來的,夾角又是梯度的方向。
寫個線性插值的公式:設g1的幅值M(g1),g2的幅值M(g2),則dtmp1可以很得到:
M(dtmp1)=wM(g2)+(1-w)M(g1)
其中w=distance(dtmp1,g2)/distance(g1,g2)
distance(g1,g2) 表示兩點之間的距離。實際上w是一個比例系數,這個比例系數可以通過梯度方向(幅角的正切和余切)得到。
右邊圖中的4個直線就是4個不同的情況,情況不同,g1、g2、g3、g4代表c的八領域中的4個坐標會有所差異,但是線性插值的原理都是一致的。
5.雙閾值的選取。
- 如果某一像素位置的幅值超過 高 閾值, 該像素被保留為邊緣像素。
- 如果某一像素位置的幅值小于 低 閾值, 該像素被排除。
- 如果某一像素位置的幅值在兩個閾值之間,該像素僅僅在連接到一個高于 高 閾值的像素時被保留。
- 對于Canny函數的使用,推薦的高低閾值比在2:1到3:1之間。
6、滯后邊界跟蹤
強邊緣點可以認為是真的邊緣。弱邊緣點則可能是真的邊緣,也可能是噪聲或顏色變化引起的。為得到精確的結果,后者引起的弱邊緣點應該去掉。通常認為真實邊緣引起的弱邊緣點和強邊緣點是連通的,而又噪聲引起的弱邊緣點則不會。所謂的滯后邊界跟蹤算法檢查一個弱邊緣點的8連通領域像素,只要有強邊緣點存在,那么這個弱邊緣點被認為是真是邊緣保留下來。
這個算法搜索所有連通的弱邊緣,如果一條連通的弱邊緣的任何一個點和強邊緣點連通,則保留這條弱邊緣,否則抑制這條弱邊緣。搜索時可以用廣度優先或者深度優先算法。
(二)OpenCV中API函數詳解
1、函數原型
void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)2、函數功能
Canny函數利用Canny算法來進行圖像的邊緣檢測。
3、參數詳解
- 第一個參數,InputArray類型的image,輸入圖像,即源圖像,填Mat類的對象即可,且需為單通道8位圖像;
- 第二個參數,OutputArray類型的edges,輸出的邊緣圖,需要和源圖片有一樣的尺寸和類型;
- 第三個參數,double類型的threshold1,第一個滯后性閾值;
- 第四個參數,double類型的threshold2,第二個滯后性閾值;
- 第五個參數,int類型的apertureSize,表示應用Sobel算子的孔徑大小,其有默認值3;
- 第六個參數,bool類型的L2gradient,一個計算圖像梯度幅值的標識,有默認值false。
4、實例
#include using namespace cv;int main(){ //載入原始圖 Mat src = imread("lena.png"); if (src.empty()) { printf("image error!"); return -1; } Mat src1 = src.clone(); //顯示原始圖 imshow("【原始圖】Canny邊緣檢測總結
以上是生活随笔為你收集整理的c++gdal如何在大图像中截取小图像并获取其图像信息_【图像处理】OpenCV系列十 --- 边缘检测之Canny算子...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang商城_Golang——简单是
- 下一篇: android要求图标格式,Androi