1. 簡介
角點:個人了解就是圖像中,帶角的那些點(也不一定是尖銳的,導數為0的極值點也行)。它通常具有旋轉不變性和光照不變性和視角不變性等優點,是圖像的重要特征之一。他具有如下特點:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90TUOVzZq50MFR1TxEFVlZDaywEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuUTNwIDM0IjMzIjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2. 算法整體思想:
算法的核心是利用局部視窗在圖像上進行移動,判斷灰階是否發生較大的變化。如果視窗内的灰階值(在梯度圖上)都有較大的變化,那麼這個視窗所在區域就存在角點。
這樣就可以将 Harris 角點檢測算法分為以下三步:
- 當視窗(局部區域)同時向 x (水準)和 y(垂直) 兩個方向移動時,計算視窗内部的像素值變化量 $E(x,y)$ ;
- 對于每個視窗,都計算其對應的一個角點響應函數 $R$;
- 然後對該函數進行門檻值處理,如果 $R > threshold$,表示該視窗對應一個角點特征。
3.opencv實作(python)
在opencv中有提供實作 Harris 角點檢測的函數 cv2.cornerHarris,我們直接調用的就可以,非常友善。
函數原型:
cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
對于每一個像素 (x,y),在 (blockSize x blockSize) 鄰域内,計算梯度圖的協方差矩陣 $M(x,y)$,然後通過上面第二步中的角點響應函數得到結果圖。圖像中的角點可以為該結果圖的局部最大值。
即可以得到輸出圖中的局部最大值,這些值就對應圖像中的角點。
參數解釋:
- src - 輸入灰階圖像,float32類型
- blockSize - 用于角點檢測的鄰域大小,就是上面提到的視窗的尺寸
- ksize - 用于計算梯度圖的Sobel算子的尺寸
- k - 用于計算角點響應函數的參數k,取值範圍常在0.04~0.06之間
具體python實作代碼:
"""
harris 角點檢測
從圖像中檢測屬于 角點 的點資訊
"""
import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
# 檢測器參數
block_size = 3 # 視窗尺寸大小
sobel_size = 3 # sobel算子尺寸大小
k = 0.06 # 用于計算相應角點R函數的k參數
image = cv.imread('data/fangzi_pic.png') # 你需要檢測的圖檔
print(image.shape)
height = image.shape[0]
width = image.shape[1]
channels = image.shape[2]
print("width: %s height: %s channels: %s" % (width, height, channels))
gray_img = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# modify the data type setting to 32-bit floating point
gray_img = np.float32(gray_img)
# 檢測角點
corners_img = cv.cornerHarris(gray_img, block_size, sobel_size, k)
# 膨脹處理,利于更友善的觀察角點形态
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
dst = cv.dilate(corners_img, kernel)
# 曬出那些不合适的角點,pix大于一定門檻值的認為是需要留下的角點
for r in range(height):
for c in range(width):
pix = dst[r, c]
# if pix > 0.05 * dst.max():
if pix > 0.1 * dst.max():
cv.circle(image, (c, r), 5, (0, 0, 255), 0) # 在圖上角點處畫小圓
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
檢測結果:
(1)原圖 -------------------->
(2) 檢測結果圖 --------------------->