今回はHarrisコーナー検出をやります。
今更ですが、チュートリアルサイトの順番通りでなく、多少飛ばしている部分もあります。
Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation
Harrisコーナー検出
理論はチュートリアルサイトに書いてある通りです。
今回はcv2.cornerHarris()
関数をさくっと試してみます。
画像は前回と同じ。
import cv2 img1 = cv2.imread('harupan_200317_1.jpg') img2 = cv2.imread('harupan_210402_1.jpg') img3 = cv2.imread('harupan_210402_2.jpg') img1 = cv2.resize(img1, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA) img2 = cv2.resize(img2, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA) img3 = cv2.resize(img3, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA) import numpy as np img123 = np.hstack((img1,img2,img3)) cv2.imshow('harupan', img123)
右の2つは同じ台紙を違う角度から撮影しているので、もしかしたらカメラの位置、角度の推定等できるかも。
いや、同じパターンがたくさんあるから難しいのか?
同じシールの検出等できるだろうか。
cv2.cornerHarris()
ではいくつかパラメータがありますが、チュートリアルサイトと同じ値でやってみます。
img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) img3_gray = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY) img1_harris = cv2.cornerHarris(img1_gray, 2, 3, 0.04) img2_harris = cv2.cornerHarris(img2_gray, 2, 3, 0.04) img3_harris = cv2.cornerHarris(img3_gray, 2, 3, 0.04)
結果は、元画像と同じサイズのndaray配列となります。
>>> type(img1_harris) <class 'numpy.ndarray'> >>> img1_harris.shape (403, 302)
特徴点を画像上に描画するとこんな感じ。
img1_cp = img1.copy() img2_cp = img2.copy() img3_cp = img3.copy() img1_cp[img1_harris > 0.01*img1_harris.max()] = [0,255,0] img2_cp[img2_harris > 0.01*img2_harris.max()] = [0,255,0] img3_cp[img3_harris > 0.01*img3_harris.max()] = [0,255,0] img123 = np.hstack((img1_cp, img2_cp, img3_cp)); cv2.imshow("Images", img123)
チュートリアルでは、検出点画像に膨張処理をして見やすくしていましたが、 今回はまずそのまま見てみました。細かい特徴点があるかもしれないので。
シールや台紙の細かい模様が特徴点として抽出されています。
よく見ると、台紙のコーナーも検出されているようです。
膨張処理をして表示してみます。
img1_harris = cv2.dilate(img1_harris, None) img2_harris = cv2.dilate(img2_harris, None) img3_harris = cv2.dilate(img3_harris, None) img1_cp[img1_harris > 0.01*img1_harris.max()] = [0,255,0] img2_cp[img2_harris > 0.01*img2_harris.max()] = [0,255,0] img3_cp[img3_harris > 0.01*img3_harris.max()] = [0,255,0] img123 = np.hstack((img1_cp, img2_cp, img3_cp)); cv2.imshow("Images", img123)
台紙のコーナーがちょっと分かりやすくなりました。
パラメータ変えてみる
シールの細かい文字しか特徴として出て来ませんでしたが、シールの点数のほうを 特徴として抽出できないだろうか。
cv2.cornerHarris
の引数の詳細を見てみましたが、blockSize
は使えなさそう。
特徴検出 — opencv 2.2 documentation
画像フィルタリング — opencv 2.2 documentation
ksize
を7にしてみたらどうだろう?
これはSobelフィルタのカーネルサイズになります。
カーネルサイズ3以外でのカーネルがどうなるのかというと、
以下のサイトにカーネルの取得方法が書かれていました。
cv2.getDerivKernels
関数を使えばいいようです。結果も書かれています。
このカーネルの感じからすると、細かい変化はならされるように思います。 カーネルサイズ変更は有効なのでは?
img1_harris = cv2.cornerHarris(img1_gray, 2, 7, 0.04) img2_harris = cv2.cornerHarris(img2_gray, 2, 7, 0.04) img3_harris = cv2.cornerHarris(img3_gray, 2, 7, 0.04) img1_harris = cv2.dilate(img1_harris, None) img2_harris = cv2.dilate(img2_harris, None) img3_harris = cv2.dilate(img3_harris, None) img1_cp = img1.copy() img2_cp = img2.copy() img3_cp = img3.copy() img1_cp[img1_harris > 0.01*img1_harris.max()] = [0,255,0] img2_cp[img2_harris > 0.01*img2_harris.max()] = [0,255,0] img3_cp[img3_harris > 0.01*img3_harris.max()] = [0,255,0] img123 = np.hstack((img1_cp, img2_cp, img3_cp)); cv2.imshow("Images", img123)
細か過ぎるパターンは特徴点としては検出されないようになっています。
一応期待通り。
ここまで
Harrisコーナー検出はこのへんにしておきます。
他にも特徴点抽出の方法が色々紹介されていたので、引き続きやってみようと思います。