圖像的特徵點檢測-Opencv實現

1.基本概念

特徵點:
可以理解爲區別於其它部分或物體的地方。根據特徵應該能準確、唯一地識別出對應目標。 例如在一堆青蘋果中,有幾個紅蘋果。那麼紅色就是可以準確識別出紅蘋果的有效特徵。人眼對特徵的識別通常是在一個局部的小區域或小窗口完成的。 如果在各個方向上移動這個特徵的小窗口,窗口內區域的灰度發生了較大的變化,那麼就認爲在窗口內遇到了特徵點。
特徵檢測:
在一幅圖像上滑動比較,如果無論往哪個方向移動,窗口內容變化都很大,那麼這個地方一定是角點。 如果沿某一方向無明顯變化,沿另一方向變化很大,說明很有可能是邊緣。如果無論哪個方向都沒有變化,則可能是內部或外部的面狀目標。
特徵描述:
在一幅圖中找到特徵後,我們自然希望在其它圖中也找到同樣的特徵。因此我們需要對特徵進行描述。

2. 角點

2種角點的定義:
1.角點可以是兩個邊緣的交點
2.角點是鄰域內具有兩個主方向的特徵點(主方向是法曲率取極值的方向,可參考微分幾何)
在圖像中,角點是重要特徵,角點在保留圖像重要特徵的同時, 可以有效減少信息數據量,使其信息含量很高,有效提高了計算速度。這也就是爲什麼在做兩幅影像的匹配配準之前, 需要先對圖像提取特徵點(角點)的原因。這樣也使實時處理成爲可能。 因此說角點在三維場景重建、運動估計、目標跟蹤、目標識別、圖像配準與匹配等領域有着非常重要的作用。

檢測角點的算法

1.Moravec角點檢測算子
在圖像上取一個w×w的滑動窗口(如3×3),不斷移動這個窗口, 依次計算在8個方向上的灰度變化V(上、下、左、右以及四個對角)。 V會有三種情況:
如果窗口中的圖像是平坦的,那麼灰度變化不大
如果窗口中的圖像是邊緣,那麼在沿邊緣時變化不大,在垂直於邊緣時變化較大
如果窗口中的圖像是角點,那麼沿任何方向,灰度變化都很大
而V可以用以下公式表示:
V(x,y)=x,y(Ix+u,y+vIx,y)2V(x,y)=\sum_{x,y}(I_{x+u,y+v}-I_{x,y})^2

2.Harris角點檢測算子
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述
注意:
1.R值較大且爲正數時,爲角點。R值較大且爲負數時,爲邊緣。R值較小時,爲平坦區域。 在判斷角點時,對角點響應函數R進行閾值處理,提取局部極大值,當R大於閾值時,認爲是角點。
2.Ix,IyI_x,I_y用sobel算子計算。
3.Shi-Tomasi角點檢測算子
與Harris算子不同之處在於打分函數R。
在Harris算子中,打分函數如下:
R=det(M)k(trace(M))2R=det(M)−k(trace(M))^2
但在Shi-Tomasi算子中對其進行了改進,變成了如下形式:
R=min(λ1,λ2)R=min(λ_1,λ_2)
對得分進行閾值判斷,超過閾值即認爲是角點。只有當λ1和λ2都大於最小值時,才被認爲是角點。

3. 實現

實現Harris角點檢測算子

函數:cv2.cornerHarris(輸入圖像,角點檢測鄰域的大小,Sobel求導時使用的窗口大小,角點檢測參數k)
返回:R

import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams["font.family"] = "SimHei"#直接修改配置字典,設置默認字體
img = cv2.imread("E:/ruanjianDM/jupyternoerbookDM/Opencv3/data/boniu.png")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 由於Harris算子需要float32的輸入圖像,因此轉換一下數據格式
gray = np.float32(gray)

# 調用Harris算子
R = cv2.cornerHarris(gray, 2, 3, 0.04)

# 0.01是人爲設定的閾值,值越小,角點越多
img[R > 0.01 * R.max()] = [0, 255, 255]

plt.subplot(121),plt.imshow(R, cmap='gray')
plt.title("R灰度圖像")
plt.subplot(122),plt.imshow(img[:,:,::-1])
plt.title("角點檢測圖像")

在這裏插入圖片描述

實現Shi-Tomasi角點檢測算子

函數:cv2.goodFeaturesToTrack(圖像,檢測角點的數目N,角點質量,角點間的最短距離)
返回:獲取圖像中N個最好的角點。
根據這些信息,函數就能在圖像上找到角點。所有低於質量水平的角點都會被忽略。 然後再把合格角點按角點質量進行降序排列。 函數會採用角點質量最高的那個角點(排序後的第一個), 然後將它附近(最小距離之內)的角點都刪掉。按這樣的方式最後返回N個最佳角點。

# coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams["font.family"] = "SimHei"#直接修改配置字典,設置默認字體
img = cv2.imread("E:/ruanjianDM/jupyternoerbookDM/Opencv3/data/boniu.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 調用Shi-Tomasi角點檢測算子
corners = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10)

# 將浮點型數據轉成int型,否則無法繪製
corners = np.int0(corners)

for i in corners:
    # 將每一項拆開,在重新拼成一個元組
    x, y = i.ravel() #將1x1x2變成1x2
    # 在圖上繪製角點,爲了更好顯示,設置半徑爲2
    cv2.circle(img, (x, y), 2, (0, 255, 255), -1)
plt.imshow(img[:,:,::-1])

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章