画像処理の数式を見て石になった時のための、金の針のサンプルコードになります。以下の処理について、実際OpenCVを使って実装してみます。
In [2]:
# enable showing matplotlib image inline
%matplotlib inline
IMAGE_PATH = "./images/cat.PNG"
MATCH_TARGET = "./images/face.PNG"
MATCH_AREA = "./images/office.PNG"
In [3]:
def harris(path):
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread(path)
grayed = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
grayed = np.float32(grayed)
# cv2.cornerHarris(src, blockSize, ksize, k)
# blockSize: 指定したサイズの領域(2なら、2*2の領域)の変化量を合計してMを計算
# ksize: Sobelフィルタのサイズ
# k: Rを計算するときのkの値。0.04~0.06くらい
R = cv2.cornerHarris(grayed, 2, 3, 0.04)
# 検出したコーナーを目立つようにするため、近傍の最大値を適用する(コーナーの範囲が大きくなるようなイメージ)
R = cv2.dilate(R, None)
# 閾値以上のコーナーの色を赤にする
img[R > 0.01 * R.max()] = [255, 0, 0]
plt.imshow(img)
harris(IMAGE_PATH)
In [5]:
def sift(path):
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread(path)
grayed = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create(nOctaveLayers=4, sigma=1.0)
points = sift.detect(grayed, None)
img = cv2.drawKeypoints(grayed, points, None)
plt.imshow(img)
sift(IMAGE_PATH)
拡大した猫のエッジもしっかり検出できているのが分かります。 ただ、octaveやsigmaといったパラメーターを結構いじってやらないとうまく検知できません。こうしたパラメーターを調整する際も、パラメーターが一体何を意味しているのかが分からないと調整できないと思うので、本文がそうした理解の参考になればと思います。
In [6]:
def sift_match(target, area):
import cv2
import numpy as np
import matplotlib.pyplot as plt
def read_as_gray(path):
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
return gray
img_target = read_as_gray(target)
img_area = read_as_gray(area)
sift = cv2.xfeatures2d.SIFT_create(nOctaveLayers=4)
# 特徴点の検出
kp_t, des_t = sift.detectAndCompute(img_target, None)
kp_a, des_a = sift.detectAndCompute(img_area, None)
# Brute-Forceでマッチング
bf = cv2.BFMatcher()
matches = bf.knnMatch(des_t, des_a, k=2)
# 良くマッチした点を表示
good = [m for m, n in matches if m.distance < 0.75 * n.distance]
matching = cv2.drawMatches(img_target, kp_t,img_area, kp_a, good, None, flags=2)
plt.imshow(matching)
sift_match(MATCH_TARGET, MATCH_AREA)
顔近辺はなんとなく一致しているかな・・・という気がしますが、似た色・場所があるとやはり間違ったりもするようです。