影象特徵提取與描述
角點檢測
原理:
特性:向任何方向移動變化都很大
Harris 角點檢測
將視窗向各個方向移動(u,v)然後計算所有差異的總和,視窗函式可以是正常的矩形視窗也可以是對每一個畫素給予不同權重的高斯視窗。
角點檢測中要使E (u; v) 的值最大。這就是說必須使方程右側的第二項的取值最大。
詳情參考:https://docs.opencv.org/master/dc/d0d/tutorial_py_features_harris.html
所以Harris 角點檢測的結果是一個由角點分數構成的灰度影象
選取適當的閾值對結果影象進行二值化我們就檢測到了影象中的角點。我們將用一個簡單的圖片來演示一下。
Open 中的函式cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]]) → dst 可以用來進行角點檢測。引數如下:
Parameters:
src – Input single-channel 8-bit or floating-point image.
dst – Image to store the Harris detector responses. It has the typeCV_32FC1 and the same size assrc .
blockSize – Neighborhood size (see the details oncornerEigenValsAndVecs() ).
ksize – Aperture parameter for theSobel() operator.
k – Harris detector free parameter. See the formula below.
borderType – Pixel extrapolation method. SeeborderInterpolate() .
* img - 資料型別為float32 的輸入影象。
* blockSize - 角點檢測中要考慮的領域大小。
* ksize - Sobel 求導中使用的視窗大小
* k - Harris 角點檢測方程中的自由引數,取值引數為[0,04,0.06].
程式碼示例:
""" #!/usr/bin/env python # -*- coding:utf-8 -*- @desc:特徵提取和描述 """ import cv2 import numpy as np from matplotlib import pyplot as plt # Harris角點檢測 def harris_detection(file_path): file_name = file_path img = cv2.imread(file_name) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = np.float32(gray) # 輸入畫素必須是float32, 最後一個引數在0.04到0.05之間 dst = cv2.cornerHarris(gray, 2,3,0.04) # 用於標記角點 dst = cv2.dilate(dst, None) # 一個最優的閾值,依賴於圖片的變數 img[dst > 0.01*dst.max()] = [0,0,255] cv2.imshow('dst', img) if cv2.waitKey(0) & 0xff == 27: cv2.destroyAllWindows() # 亞畫素級精確度的Harris角點檢測 def sub_pix_corner_dectetion(file_path): file_name = file_path img = cv2.imread(file_name) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 獲取角點 gray = np.float32(gray) # 輸入畫素必須是float32, 最後一個引數在0.04到0.05之間 dst = cv2.cornerHarris(gray, 2, 3, 0.04) dst = cv2.dilate(dst, None) ret, dst = cv2.threshold(dst, 0.01*dst.max(), 255, 0) dst = np.uint8(dst) # 找到質心 ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst) # 定義停止迭代的標準,並重新定義角點 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001) # 返回值由角點座標組成的一個數組(而非影象) corners = cv2.cornerSubPix(gray, np.float32(centroids), (5, 5), (-1, -1), criteria) # 畫出角點 res = np.hstack((centroids, corners)) # np.int0 可以用來省略小數點後面的數字(非四五入)。 res = np.int0(res) img[res[:, 1], res[:, 0]] = [0, 0, 255] img[res[:, 3], res[:, 2]] = [0, 255, 0] cv2.imwrite(r'D:\workplace\data\opencv\subpixel5.png', img) # 改進 # Shi-Tomasi 角點檢測&&適合於跟蹤的影象特徵 def shi_tomasi_detection(file_path): img = cv2.imread(file_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(gray,25,0.01, 10) # corners = np.int0(corners) for i in corners: x, y = i.ravel() cv2.circle(img, (x, y), 3, (0, 255, 0), -1) plt.imshow(img) plt.show() if __name__ == '__main__': # file_path = r"D:\workplace\data\opencv\OIP-C.jfif" # harris_detection(file_path) # sub_pix_corner_dectetion(file_path) file_path1 = r"D:\workplace\data\opencv\20161113111710572.png" shi_tomasi_detection(file_path1)