oreillyの「実践コンピュータビジョン」写経の続き
SIFT特徴量検出の続きでもあります
画像処理 - vlfeatによるSIFT特徴点検出 - end0tknr's kipple - 新web写経開発
SIFT特徴点検出結果の対応点探索 (python) - end0tknr's kipple - 新web写経開発
密なSIFT(HOG : Histogram of Oriented Gradients ) とは
SIFT特徴量は、特徴点の周辺の勾配に対し、勾配ヒストグラムを算出しましたが、 HOGは、一定間隔で勾配ヒストグラムを算出します。
pythonでHOGを算出し、その座標を表示
#!/usr/local/bin/python # -*- coding: utf-8 -*- from PIL import Image import numpy import matplotlib matplotlib.use('Agg') import matplotlib.pylab as plb import os ## http://www.vlfeat.org/download/vlfeat-0.9.20.tar.gz SIFT_CMD = '/home/endo/local/vlfeat/sift' def main(): # 画像から「密なSIFT記述子(HOG)」を抽出し、fileに保存. process_image_dsift('empire.jpg', 'empire.sift', 90, 40, True) l,d = read_features_from_file('empire.sift') im = numpy.array(Image.open('empire.jpg')) plot_features(im,l,True) plb.savefig( '8_1_2.png' ) # 画像から「密なSIFT記述子(HOG)」を抽出し、fileに保存. # args size=特徴量size, steps=grid間隔, resize=画像resize用のタプル # force_orientation= True →最大の局所勾配の方向で記述子が正規化 # False→全て上向き def process_image_dsift(imagename, resultname, size=20, steps=10, force_orientation=False, resize=None): im = Image.open(imagename).convert('L') # file open後、グレースケール化 if resize != None: im = im.resize(resize) m, n = im.size if imagename[-3:] != 'pgm': im.save('tmp.pgm') # pgmファイルを作成 imagename = 'tmp.pgm' # frameを作成し一時fileに保存 scale = size / 3.0 x, y = numpy.meshgrid(range(steps, m, steps), range(steps, n, steps)) xx, yy = x.flatten(), y.flatten() frame = numpy.array([xx, yy, scale * numpy.ones(xx.shape[0]), numpy.zeros(xx.shape[0])]) numpy.savetxt('tmp.frame', frame.T, fmt='%03.3f') if force_orientation: cmmd = str(SIFT_CMD +" "+ imagename + " --output=" + resultname + " --read-frames=tmp.frame --orientations") else: cmmd = str(SIFT_CMD +" "+ imagename + " --output=" + resultname + " --read-frames=tmp.frame") os.system(cmmd) print 'processed', imagename, 'to', resultname # 特徴量を読込み行列形式で返す def read_features_from_file(filename): f = numpy.loadtxt(filename) return f[:, :4], f[:, 4:] # 特徴点の配置と記述子 # 画像を特徴量とともに描画。 # 入力:im(配列形式の画像),locs(各特徴量の座標とスケール、方向) def plot_features(im, locs, circle=False): def draw_circle(c, r): t = numpy.arange(0, 1.01, .01) * 2 * numpy.pi x = r * numpy.cos(t) + c[0] y = r * numpy.sin(t) + c[1] plb.plot(x, y, 'b', linewidth=2) plb.imshow(im) if circle: for p in locs: draw_circle(p[:2],p[2]) else: plb.plot(locs[:,0],locs[:,1],'ob') plb.axis('off') if __name__ == '__main__': main()
↑こう書くと、↓こう表示されます。(単に座標を表示しているので、全く面白くありませんが)