首頁 > 軟體

OpenCV角點檢測的實現範例

2022-03-28 13:01:02

Harris 角點檢測演演算法

1. 角點

角點是水平方向、垂直方向變化都很大的畫素。

角點檢測演演算法的基本思想: 

        使用一個固定視窗在影象上進行任意方向上的滑動,比較滑動前與滑動後兩種情況,視窗中的畫素灰度變化程度,如果存在任意方向上的滑動,都有著較大灰度變化,那麼我們可以認為該視窗中存在角點。

        目前,角點檢測演演算法還不是十分完善,許多演演算法需要依賴大量的訓練集和冗餘資料來防止和減少錯誤的特徵的出現。對於角點檢測演演算法的重要評價標準是:其對多幅影象中相同或者相似特徵的檢測能力,並且能夠應對光照變化、或者影象旋轉等影響。

關於角點的具體描述可以有幾種:

  • 一階導數(即灰度的梯度)的區域性最大所對應的畫素點;
  • 兩條及兩條以上邊緣的交點;
  • 影象中梯度值和梯度方向的變化速率都很高的點; 
  • 角點處的一階導數最大,二階導數為零,指示物體邊緣變化不連續的方向。                                                                                     

三類角點檢測演演算法:

  • 基於二值影象的角點檢測;
  • 基於輪廓曲線的角點檢測;
  • 基於灰度影象的角點檢測:基於梯度、基於模板和基於模板和梯度組合三類方法;常見的基於模板的角點檢測演演算法有:Kitchen-Rosenfeld角點檢測演演算法,Harris角點檢測演演算法,KLT角點檢測演演算法及SUSAN角點檢測演演算法。基於模板的方法主要是考慮畫素領域點灰度的變化,即亮度的變化。

2. 流程

(1)找出角點
用高斯運算元求出畫素水平方向和垂直方向的梯度dx, dy,–> 對梯度的平方dxdx ,dydy, dxdy濾波得到Wxx ,Wxy,Wyy --> 在求的(WxxWyy - Wxy**2)/(Wxx + Wyy)作為候選角點。

(2)篩選角點
根據閾值篩選角點–> 取得角點的座標 -->根據角點座標得到角點所在的行 --> 在角點周圍,刪除掉其他角點。–> result

(3)標記角點

3. 實現

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters

## 1.找出角點
### 1.1 步驟:img求導 --> imx ,imy 濾波-->Wxx ,Wxy,Wyy --> (Wxx*Wyy - Wxy**2)/(Wxx + Wyy)
def compute_harris_response(img,sigma=3):
    # 求梯度
    imgx,imgy  = np.zeros(img.shape),np.zeros(img.shape)
    filters.gaussian_filter(img,(sigma,sigma),(0,1),imgx)
    filters.gaussian_filter(img,(sigma,sigma),(1,0),imgy) # [260,263]
    # 對梯度進行高斯濾波
    wxx = filters.gaussian_filter(imgx**2,sigma)
    wyy = filters.gaussian_filter(imgy**2,sigma) # [260,263]
    wxy = filters.gaussian_filter(imgx*imgy,sigma)# [260,263]
    ## 求行列式和跡
    wdet = wxx*wyy -wxy**2
    wtr = wxx + wyy
    return  wdet/wtr

## 2 篩選角點
### 2.1 步驟:根據閾值篩選角點--> 取得角點的座標 -->根據角點座標得到角點所在的行  -->
# --> 在角點周圍,刪除掉其他角點
def get_harris_points(harri,min_dist=4,threshold=0.1):
    corner_thre = harri.max()*threshold  # 角點閾值
    mask = (harri > corner_thre)*1  # 取出大於閾值的點為候選角點
    cords = np.array(mask.nonzero()).T  # 取候選角點的座標

    values = [harri[i[0],i[1]] for i in cords]  # 候選角點的值
    cls = np.argsort(values)     # 對角點排序得到排序後的序列號,序列號也是候選角點所在的行

    loc = np.zeros(harri.shape)   # 劃出可行性區域
    loc[min_dist:-min_dist,min_dist:-min_dist] = 1

    re_cords = []
    for i in cls:  # 篩選角點。先取出角點,角點周圍的點不再取出
        if loc[cords[i,0],cords[i,1]] == 1 :
            re_cords.append(cords[i])
            loc[cords[i,0]-min_dist:cords[i,0]+min_dist,cords[i,1]-min_dist:cords[i,1]+min_dist]=0
    return re_cords

def plot_harri(img,cords):
    plt.figure()
    plt.gray()
    plt.imshow(img)
    plt.plot([i[1] for i in cords],[i[0] for i in cords],'.')
    plt.axis('off')
    plt.show()

## 3 測試
if __name__ == '__main__':
    img = np.array(Image.open('luna.png').convert('L'))
    harri = compute_harris_response(img)
    re_cords = get_harris_points(harri)
    plot_harri(img,re_cords)

到此這篇關於OpenCV角點檢測的文章就介紹到這了,更多相關OpenCV角點檢測內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com