一、Harris角點檢測
原理:
角點特性:向任何方向移動變換都很大。
Chris_Harris 和 Mike_Stephens 早在 1988 年的文章《A CombinedCorner and Edge Detector》中就已經提出了焦點檢測的方法,被稱為Harris 角點檢測。將窗口向各個方向移動(u,v)然后計算所有差異的總合:表達式如下:
角點檢測中要使E(u,v)的值最大。這就是說必須使方程的第二項的取值最大。對上面的等式進行泰勒級數展開,然后再通過幾步數學換算(參考其他標准教材),我們得到下面的等式:
其中
這里 Ix 和 Iy 是圖像在 x 和 y 方向的導數(可以使用cv2.Sobel()計算得到)
根據一個用來判定窗口內是否包含角點的等式進行打分
其中
- λ1 和 λ 2 是矩陣M的特征值所以根據這些特征中我們可以判斷一個區域是否是一個角點、邊界或是平面
- 當λ1 和 λ 2都小時,|R| 也小,這個區域就是一個平坦區域
- 當 λ 1 ≫ λ 2 或者 λ 1 ≪ λ 2時,R小於0,這個區域是邊緣
- 當 λ 1 和 λ 2 都很大,並且 λ 1 ~λ 2 中的時,R 也很大,(λ 1 和 λ 2 中最小值都大於閾值),說明這個區域是角點
用下圖來表示我們的結論:
所以Harris 角點檢測的結果是一個由角點分數構成的灰度圖像。選取適當的閾值對結果進行二值化,我們就檢測到了圖像中的角點。
OpenCV中的角點檢測
使用 cv2.cornerHarris(),參數如下:
img:數據類型為float32的輸入圖像(灰度圖)
blockSize:角點檢測中要考慮的領域大小
ksize:Sobel求導中使用的窗口大小
k:Harris角點檢測方程中的自由參數,取值參數為[0.04,0.06]
import cv2 import numpy as np img = cv2.imread('blox.jpg') # 1. Harris角點檢測基於灰度圖 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 2. Harris角點檢測 dst = cv2.cornerHarris(gray, 2, 3, 0.04) # 腐蝕一下,便於標記 dst = cv2.dilate(dst, None) # 角點標記為紅色 img[dst > 0.01 * dst.max()] = [0, 0, 255] cv2.imwrite('blox-RedPoint.png', img) cv2.imshow('dst', img) cv2.waitKey(0)
二、Shi-Tomasi角點檢測 & 適合於跟蹤的圖像特征
Shi-Tomasi 角點檢測是在Harris角點檢測上進行了修改。我們知道Harris角點檢測的打分公式為:
但 Shi-Tomasi 使用的打分函數為:
如果打分查過閾值,我們就認為它是一個角點,我們可以把它繪制到 λ 1 ~λ 2 空間中,就會得到下圖:
從這幅圖中,我們可以看出只有當λ 1 和 λ 2 都大於最小值時,才被認為是角點(綠色區域)
OpenCV使用cv2.goodFeatureToTrack()。這個函數可以幫我們使用Shi-Tomasi方法獲取圖像中的N個最好的角點。
image : 輸入灰度圖
maxCorners:想要檢測的角點數目
qualityLevel:設置角點的最低質量,0 到 1之間。低於這個數的所有角點都會被忽略
minDistance:兩個角點之間的最短歐式距離
根據這些信息,函數就能在圖像上找到角點。所有低於質量水平的角點都會被忽略。然后再把合格角點按角點質量進行降序排列。函數會采用角點質量最高的那個角點(排序后的第一個),然后將它附近(最小距離之內)的角點都刪掉。按着這樣的方式最后返回 N 個最佳角點。
import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('blox.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Shi-Tomasi角點檢測 corners = cv2.goodFeaturesToTrack(gray, 20, 0.01, 10) corners = np.int0(corners) # 20 個角點坐標 for i in corners: # 壓縮至一維:[[62, 64]] -> [62, 64] x, y = i.ravel() cv2.circle(img, (x, y), 4, (0, 0, 255), -1) cv2.imwrite('Shi-Tomasi-corner.jpg', img) cv2.imshow('dst', img) cv2.waitKey(0)
這個函數很適合在目標跟蹤中使用
三、Harris和Shi-Tomasi的比較
import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('blox.jpg') imgShi, imgHarris = np.copy(img), np.copy(img) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 1. Shi-Tomasi角點檢測 # 優點:速度相比Harris有所提升,可以直接得到角點坐標 corners = cv2.goodFeaturesToTrack(gray, 20, 0.01, 10) corners = np.int0(corners) for i in corners: # 壓縮至一維:[[62, 64]] -> [62, 64] x, y = i.ravel() cv2.circle(imgShi, (x, y), 4, (0, 0, 255), -1) # 2. Harris角點檢測 dst = cv2.cornerHarris(gray, 2, 3, 0.04) # 腐蝕一下,便於標記 dst = cv2.dilate(dst, None) # 角點標記為紅色 imgHarris[dst > 0.01 * dst.max()] = [0, 0, 255] cv2.imwrite('compare.png', np.hstack((imgHarris, imgShi))) cv2.imshow('compare', np.hstack((imgHarris, imgShi))) cv2.waitKey(0)
左圖為Harris角點檢測結果,右圖為Shi-Tomasi結果。可以看出,Shi-Tomasi角點檢測的質量更高,數量也相對較少。一般情況下,Shi-Tomasi相比Harris速度有所提升,並且可以直接得到角點坐標。