正規化相互相関を用いた Harrisコーナー検出結果の対応点探索 (python) - end0tknr's kipple - 新web写経開発
画像処理 - vlfeatによるSIFT特徴点検出 - end0tknr's kipple - 新web写経開発
上記のエントリの続きです。
最も一致する特徴点への距離の比を双方向で比較する がポイントです
#!/usr/bin/python # -*- coding: utf-8 -*- from PIL import Image import numpy import matplotlib matplotlib.use('Agg') import matplotlib.pylab as plb import os #imname1 = 'crans_1_small.jpg' #imname2 = 'crans_2_small.jpg' imname1 = 'sf_view1.jpg' imname2 = 'sf_view2.jpg' #imname1 = 'climbing_1_small.jpg' #imname2 = 'climbing_2_small.jpg' SIFT_CMD = '/home/endo/local/vlfeat/sift' PROCESS_IMAGE_PARAMS = "--edge-thresh 10 --peak-thresh 5" def main(): im1 = numpy.array(Image.open(imname1).convert('L')) im2 = numpy.array(Image.open(imname2).convert('L')) # 特徴量検出 process_image(imname1,imname1 + '.sift') l1,d1 = read_features_from_file(imname1 + '.sift') process_image(imname2,imname2 + '.sift') l2,d2 = read_features_from_file(imname2 + '.sift') # 特徴量のマッチング matches = match_twosided(d1,d2) # マッチング結果の表示 plb.figure() plb.gray() plot_matches(im1,im2,l1,l2,matches) plb.savefig( '2_3_4.png' ) # 画像の特徴点を検出しfileに保存 def process_image(imagename,resultname,params=PROCESS_IMAGE_PARAMS): if imagename[-3:] != 'pgm': # pgmファイルを作成する im = Image.open(imagename).convert('L') imagename = 'tmp.pgm' im.save(imagename) cmmd = str(SIFT_CMD +" "+imagename+" --output="+resultname+ " "+params) os.system(cmmd) print 'processed sift to', resultname # SIFT特徴量を読み込んで行列形式で返す def read_features_from_file(filename): f = numpy.loadtxt(filename) return f[:,:4],f[:,4:] # 特徴点の配置と記述子 def match_twosided(desc1,desc2): """ 双方向対称バージョンのmatch() """ matches_12 = match(desc1,desc2) matches_21 = match(desc2,desc1) ndx_12 = matches_12.nonzero()[0] # 対称でないものは除去する for n in ndx_12: if matches_21[int(matches_12[n])] != n: matches_12[n] = 0 return matches_12 def match(desc1,desc2): """ 第1の画像の各記述子について、第2の画像の対応点を求める。 入力:desc1(第1の画像の記述子)、desc2(第2の画像の記述子)""" desc1 = numpy.array([d/numpy.linalg.norm(d) for d in desc1]) desc2 = numpy.array([d/numpy.linalg.norm(d) for d in desc2]) dist_ratio = 0.6 desc1_size = desc1.shape matchscores = numpy.zeros(desc1_size[0],'int') desc2t = desc2.T # あらかじめ転置行列を計算しておく for i in range(desc1_size[0]): dotprods = numpy.dot(desc1[i,:],desc2t) # 内積ベクトル dotprods = 0.9999*dotprods # 第2の画像の特徴点の逆余弦を求め、ソートし、番号を返す indx = numpy.argsort(numpy.arccos(dotprods)) # 最も近い近接点との角度が、2番目に近いもののdist_rasio倍以下か? if numpy.arccos(dotprods)[indx[0]]<dist_ratio * numpy.arccos(dotprods)[indx[1]]: matchscores[i] = int(indx[0]) return matchscores def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True): """ 対応点を線で結んで画像を表示する 入力: im1,im2(配列形式の画像)、locs1,locs2(特徴点座標) machescores(match()の出力)、 show_below(対応の下に画像を表示するならTrue)""" im3 = appendimages(im1,im2) if show_below: im3 = numpy.vstack((im3,im3)) plb.imshow(im3) cols1 = im1.shape[1] for i,m in enumerate(matchscores): if m>0: plb.plot([locs1[i][0],locs2[m][0]+cols1],[locs1[i][1],locs2[m][1]],'c') plb.axis('off') def appendimages(im1,im2): """ 2つの画像を左右に並べた画像を返す """ # 行の少ない方を選び、空行を0で埋める rows1 = im1.shape[0] rows2 = im2.shape[0] if rows1 < rows2: im1 = numpy.concatenate((im1,numpy.zeros((rows2-rows1,im1.shape[1]))),axis=0) elif rows1 > rows2: im2 = numpy.concatenate((im2,numpy.zeros((rows1-rows2,im2.shape[1]))),axis=0) # 行が同じなら、0で埋める必要はない return numpy.concatenate((im1,im2), axis=1) if __name__ == '__main__': main()
↑こう書くと↓こう表示されます