画像局所記述子 - Harris Corner 検出器
はじめに
実践コンピュータビジョンに書かれているものを自分の整理のために、まとめたものです。また、他の言語で書き直することで理解も深まるので、今回はSwiftで書き直したいと思います。(まだ、未完記事です)
画像の局所記述子とは
画像間の対応づけをするために使われる。 そのなかでも一番簡単なHarrisコーナー検出器について書きたいと思います。
Harrisコーナー検出器
判別関数
以下の関数が判別関数である。
- 微分係数を計算する
- Harris行列の成分を計算する
- 判別式と対角成分(判別関数)を計算する
閾値を超えるコーナー候補を調べる
次に、判別関数によって各ピクセルのHarris行列を求めた画像と、Thersholdを使って、コーナーを
画像にプロットする。
1. 閾値を超えるコーナー候補を見つける
2. 候補の座標をとる
3. 候補の値を得る
4. 候補をソートする
5. 許容する点の座標を配列に格納する
6. 最小距離を考慮しながら、最良の点を得る
実装
インポートするライブラリ
from scipy.ndimage import filters # 微分係数を求めるために使用 import numpy as np from matplotlib import pyplot as plt
判別関数によって出力された値を返す
def compute_harris_response(img, sigma=3): """ グレイスケール画像の各ピクセルについて Harrisコーナー検出器の応答関数を定義する :param img: グレイスケール画像 :param sigma: :return: Harris画像 https://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy.ndimage.filters.gaussian_filter.html """ # 微分係数 img_x = np.zeros(img.shape) filters.gaussian_filter(img, (sigma, sigma), (0, 1), img_x) img_y = np.zeros(img.shape) filters.gaussian_filter(img, (sigma, sigma), (0, 1), img_y) # Harris行列の成分を計算する Wxx = filters.gaussian_filter(img_x * img_x, sigma) Wxy = filters.gaussian_filter(img_x * img_y, sigma) Wyy = filters.gaussian_filter(img_y * img_y, sigma) # 判別式と対角成分(判別関数)を計算する Wdet = Wxx * Wyy - Wxy * 2 Wtr = Wxx + Wyy return Wdet / Wtr
Harris応答画像からコーナーを返す
def get_harris_points(harris_img, min_dist=10, threshold=0.1): """ :param harris_img: ハリス画像 :param min_dist: コーナーや画像今日から分離する最小ピクセル数(値範囲が謎)、おそらく[0,1] :param threshold: コーナー候補を絞るための閾値(値範囲が謎) :return: 最小距離を考慮した、最良の座標配列 """ # 閾値を超えるコーナー候補を見つける corner_threshold = harris_img.max() * threshold harris_img_t = (harris_img > corner_threshold) * 1 # 候補の座標をとる # ここの演算がよくわからん.. coords = np.array(harris_img_t.nonzero()).T # 候補の値を得る candidate_values = [harris_img[c[0], c[1]] for c in coords] # 候補をソートする index = np.argsort(candidate_values) # 許容する点の座標を配列に格納する allowed_locations = np.zeros(harris_img.shape) allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1 # 最小距離を考慮しながら、最良の点を得る filtered_coords = [] for i in index: if allowed_locations[coords[i, 0], coords[i,1]] == 1: filtered_coords.append(coords[i]) allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist), (coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0 return filtered_coords
ついでにプロットする関数
def plot_harris_points(image, filtered_coords): """ :param image: グレイスケール画像 :param filtered_coords: 点の描画 """ plt.figure() plt.gray() plt.imshow(image) plt.plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*') plt.axis('off') plt.show()
画像間の対応づけ
ここは後日...
Swiftでやってみる
ここは後日...