原文作者:aircraft
原文地址:https://www.cnblogs.com/DOMLX/p/8763369.html
參考文獻----------OpenCV-Python-Toturial-中文版.pdf
參考博客----------http://www.bubuko.com/infodetail-2498014.html
不廢話進入主題:
角點是一類具有特定特征的點,角點也是處在一個無論框框往哪邊移動 框框內像素值都會變化很大的情況而定下來的點 可以這么去理解。。。。
如上圖有三個顏色的框框,如果我們對藍色框框進行移動,無論是水平 還是垂直的方向移動 都不會對框框內像素造成很大的變化。。。這種是內部區域
如果我們對黑色的框框進行移動,那么水平方向上移動 像素值是不會有什么太大的變化的 如果是垂直方向上移動那么就會變化很大 這種一般稱為邊緣區域
最后的重點 我們對紅色的框框進行移動 無論是往哪個方向進行偏移 都會對框框內的像素值 造成很大的變動 那么紅色框框 框住的區域的邊角點 我們就稱為角點
通過以上的幾句話 我們大家應該大概的理解了角點是什么意思了、、、、
就這樣一直說下去 解釋下去 肯定是比較枯燥的 大家估計都是想先看看這個cv2.cornerHarris()函數的作用是什么。。。那么我們就先來看看成果圖 在解釋過程
那些紅色的 綠色的就是通過我們函數圈出來的角點。。。
下面就解釋一下原理 后面會給出簡單的示例代碼
在 1988 年的文章《A CombinedCorner and Edge Detector》中就已經提出了焦點檢測的方法,被稱為Harris 角點檢測。他把這個簡單的想法轉換成了數學形式。將窗口向各個方向移動(u,v)然后計算所有差異的總和。表達式如下:
窗口函數可以是正常的矩形窗口也可以是對每一個像素給予不同權重的高斯窗口
角點檢測中要使 E (μ,ν) 的值最大。這就是說必須使方程右側的第二項的取值最大。對上面的等式進行泰勒級數展開然后再通過幾步數學換算(可以參考其他標准教材),我們得到下面的等式:
其中
這里 I x 和 I y 是圖像在 x 和 y 方向的導數。(可以使用函數 cv2.Sobel()
計算得到)。
然后就是主要部分了。他們根據一個用來判定窗口內是否包含角點的等式進行打分。
其中
? λ 1 和 λ 2 是矩陣 M 的特征值所以根據這些特征中我們可以判斷一個區域是否是角點,邊界或者是平面。
? 當 λ 1 和 λ 2 都小時,|R| 也小,這個區域就是一個平坦區域。
? 當 λ 1 ? λ 2 或者 λ 1 ? λ 2 ,時 R 小於 0,這個區域是邊緣
? 當 λ 1 和 λ 2 都很大,並且 λ 1 ~λ 2 中的時,R 也很大,(λ 1 和 λ 2 中的最小值都大於閾值)說明這個區域是角點。
可以用下圖來表示我們的結論:
cv2.cornerHarris()函數的返回值其實就是R值構成的灰度圖像 灰度圖像坐標會與原圖像對應 R值就是角點分數 當R值很大的時候 就可以認為這個點是一個角點
OpenCV 中的 Harris 角點檢測
Open 中的函數 cv2.cornerHarris() 可以用來進行角點檢測。參數如
下:
• img - 數據類型為 float32 的輸入圖像。
• blockSize - 角點檢測中要考慮的領域大小。
• ksize - Sobel 求導中使用的窗口大小
• k - Harris 角點檢測方程中的自由參數,取值參數為 [0,04,0.06].
python 實現代碼如下:
1 # -*- coding: utf-8 -*- 2 3 4 import cv2 5 import numpy as np 6 7 8 filename = 'chessboard5.jpg' 9 img = cv2.imread(filename) 10 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 11 gray = np.float32(gray) 12 13 # 輸入圖像必須是 float32 ,最后一個參數在 0.04 到 0.05 之間 14 dst = cv2.cornerHarris(gray,2,3,0.04) 15 16 #result is dilated for marking the corners, not important 17 dst = cv2.dilate(dst,None) 18 19 # Threshold for an optimal value, it may vary depending on the image. 20 img[dst>0.01*dst.max()]=[0,0,255] 21 22 cv2.imshow('dst',img) 23 if cv2.waitKey(0) & 0xff == 27: 24 cv2.destroyAllWindows()
dst = cv2.dilate(dst,None) 這段代碼是膨脹 提升后續圖像角點標注的清晰准確度 可有可無 也可以注釋掉
估計大家最有疑問的應該是:
img[dst>0.01*dst.max()]=[0,0,255]這段代碼是什么意思吧 dst>0.01*dst.max()這么多返回是滿足條件的dst索引值 根據索引值來設置這個點的顏色
這里是設定一個閾值 當大於這個閾值分數的都可以判定為角點 (好像說跟沒說一樣是吧)hhhh
在看上面我講的 這里的dst其實就是一個個角度分數R組成的 當 λ 1 和 λ 2 都很大,並且 λ 1 ~λ 2 中的時,R 也很大,(λ 1 和 λ 2 中的最小值都大於閾值)說明這個區域是角點。
那么這里為什么要大於0.01×dst.max()呢 注意了這里R是一個很大的值 我們選取里面最大的R 然后 只要dst里面的值大於百分之一的R的最大值 那么此時這個dst的R值也是很大的 可以判定他為角點
也不一定要0.01 可以根據圖像自己選取不過如果太小的話 可能會多圈出幾個不同的角點
代碼結果上面已經看過了 在放出來一次吧:

若有興趣交流分享技術,可關注本人公眾號,里面會不定期的分享各種編程教程,和共享源碼,諸如研究分享關於c/c++,python,前端,后端,opencv,halcon,opengl,機器學習深度學習之類有關於基礎編程,圖像處理和機器視覺開發的知識