# Python에서 sqlite를 이용한 BoVW 구현
# funMV, 2014.12
from numpy import *
import pickle
from pysqlite2 import dbapi2 as sqlite
import sift
import imagesearch
f = open("ukbench/first1000/list.txt",'r') # to access sub-directory
lines = f.readlines() # read all lines through line to line style
f.close()
imlist=[ 'ukbench/first1000/'+line[:-1] for line in lines] # to eliminate last character '\n'
nbr_images=len(imlist)
featlist=[ imlist[i][:-3]+'sift' for i in range(nbr_images)] # filename.sift in each line
# load vocabulary
with open('vocabulary.pkl','rb') as f:
voc = pickle.load(f)
# create db
con = sqlite.connect('test1.db') # 재 실행시, 반드시 test1.db를 지우고 돌려야 함
# 일단, 실행되면 hdd에 test1.db가 저장되기 때문
# create tables
con.execute('create table imlist(filename)')
con.execute('create table imwords(imid,wordid,vocname)')
con.execute('create table imhistograms(imid,histogram,vocname)')
# 다음 4개 명령은 없어도 실행되지만 좀 느려지는 것 같음
con.execute('create index im_idx on imlist(filename)')
con.execute('create index wordid_idx on imwords(wordid)')
con.execute('create index imid_idx on imwords(imid)')
con.execute('create index imidhist_idx on imhistograms(imid)')
con.commit()
# test db
locs, descr = sift.read_features_from_file(featlist[0])
# locs=2276x4, descr=2276x128
# For first image, 2277 features are there and they will be prjected to vw
imwords=voc.project(descr)
#voc.shape[0]=498: # of visual words
#imwords.shape=498의 히스토그램(보팅) 정보
#imwords: voting number of features per each word (histogram). some features among 2278 features
# are voted 7 times to first word, and 6 times for second words of vw, so on.
#array([ 7., 6., 2., 1., 5., 4., 4., 1., 0., 4., 2.,
# 3., 6., 1., 2., 4., 2., 0., 1., 9., 1., 1.,
# 2., 3., 0., 1., 7., 3., 2., 7., 3., 0., 5.,
# 17., 1., 3., 16., 6., 3., 8., 26., 11., 1., 10.,
# 3., 3., 4., 2., 2., 1., 2., 1., 2., 2., ...
nbr_words=imwords.shape[0] # 498
# 위는 test모드이고 여기서부터는 실제 모든 im의 feature들을 db에 삽입
# go through all images, project features on vocabulary and insert
for i in range(nbr_images)[:100]: # [0,1,2,...,98,99]
locs, descr = sift.read_features_from_file(featlist[i])
imname = imlist[i]
imwords=voc.project(descr)
nbr_words=imwords.shape[0]
# (1) 파일 이름을 db에 저장
cur=con.execute("insert into imlist(filename) values ('%s')" %imname)
imid = cur.lastrowid
# (2) 파일 이름 id - 각 word에 대한 voting 횟수 연계 저장
for j in range(nbr_words):
word = imwords[j]
con.execute("insert into imwords(imid,wordid,vocname) values (?,?,?)",
(imid,word,voc.name))
# (3) 파일이름 id와 히스토그램 전체 저장
con.execute("insert into imhistograms(imid,histogram,vocname) values (?,?,?)",
(imid,pickle.dumps(imwords),voc.name))
# 여기서 최종 결과를 저장하고 나가려면 commit를 해 주여야 함.
# con.commit()
# 다시 사용 시
# con=sqlite.connect('test1.db')
#
# Test for saved db
print con.execute('select count (filename) from imlist').fetchone()
# (100,), 100개의 im name이 저장
print con.execute('select * from imlist').fetchone()
# (u'ukbench/first1000/ukbench00000.jpg',)
##################################################
# 여기서 부터 저장된 db를 이용한 test
##################################################
# test할 query인 첫번째 im의 id, 히스토그램을 가져옴
im_id = con.execute("select rowid from imlist where filename='%s'" % imlist[0]).fetchone()
#im_id=(1,)
s = con.execute("select histogram from imhistograms where rowid='%d'" % im_id).fetchone()
h = pickle.loads(str(s[0])) # len(.)=498, histogram for word voting
#Using the index to get candidates
#locs, descr = sift.read_features_from_file(featlist[0])
#imwords=voc.project(descr)
#words=imwords.nonzero()[0] #voting이 하나라도 있는 words의 index
words=h.nonzero()[0]
#vw에 대한 histogram(bin수는 보팅 횟수가 0인 빈을 배제 후 vw의 갯수 만큼)
# words.shape=(455,)=[0,1,2,3,5,....]
# find candidates
candidates = []
for word in words:
# table imword에서 word id로 imid를 추출. 즉, 특정 word를 가진 모든 im의 id를 추출
# 즉, query im의 해당 word를 가지는 db내 모든 im의 id 리스트를 candidates에 저장
im_ids = con.execute("select distinct imid from imwords where wordid=%d"
% word).fetchall()
c = [i[0] for i in im_ids]
candidates += c
# len(candidates) = 1443
# take all unique words and reverse sort on occurrence
tmp = [(w,candidates.count(w)) for w in set(candidates)]
# candidates.count(1)=23, candidates.count(10)=15
# set(candidates)=[1,2,3,4,...,99,100]
# tmp=[(1, 23), (2, 23), (3, 19), (4, 26), (5, 11), (6, 13), (7, 14),
# (8, 11), (9, 28), (10, 15), (11, 14), (12, 30), (13, 10),.....
# (95, 27), (96, 31), (97, 19), (98, 16), (99, 18), (100, 17)]
tmp.sort(cmp=lambda x,y:cmp(x[1],y[1]))
tmp.reverse()
candi=[w[0] for w in tmp] # len(candi)=100
#candi=[43,77,44,42,78,79,...,21,84,83]
#필요한 것은 im의 id이므로 sort후 reverse해줌
matchscores=[]
for imid in candi:
s = con.execute("select histogram from imhistograms where rowid='%d'" % imid).fetchone()
cand_h = pickle.loads(str(s[0])) # histogram for word voting
cand_dist = sqrt( sum( voc.idf*(h-cand_h)**2 ) )
matchscores.append( (cand_dist,imid) )
matchscores.sort()
print matchscores[:10]
#[(0.0, 1), (60.812088499474271, 2), (61.547483004618186, 3), (92.620967753952812, 4),
# (100.59065889285603, 34), (107.76370948763174, 28), (108.27892205906744, 25),
# (109.39719124624605, 9), (110.33866766043165, 10), (110.77231202013482, 20)]
con.commit()
con.close()
2014년 11월 30일 일요일
Bag of Visual Words
Bag of Words의 요약:
# BoW를 이해하기 위한 Toy example
# BoW algorithm analysis
# 2013/06/28, 2014/12/03 개선
# by funmv
#
from PIL import Image
from pylab import *
import os
from numpy import *
from scipy.cluster.vq import *
import sift
import vocabulary
# 물체의 class는 3개이다 (즉, 0~3/4~7/8~11의 4개씩 동일 물체를 다른 자세에서 찍었음. 아래 그림 참조)
imlist = ['ukbench00000.jpg', 'ukbench00001.jpg', 'ukbench00002.jpg', 'ukbench00003.jpg', 'ukbench00004.jpg', 'ukbench00005.jpg', 'ukbench00006.jpg', 'ukbench00007.jpg', 'ukbench00008.jpg', 'ukbench00009.jpg', 'ukbench00010.jpg', 'ukbench00011.jpg']
nbr_images=len(imlist)
featlist=[ imlist[i][:-3]+'sift' for i in range(nbr_images)]
"""for i in range(nbr_images):
sift.process_image(imlist[i], featlist[i])
"""
descr = []
descr.append(sift.read_features_from_file(featlist[0])[1])
descriptors = descr[0]
# sift.read_features_from_file(featlist[i])[0]:
# list of [pixel coord of each feature point, scale, rotation angle] for i-image
# size: (# of feature point x 4) for i-th image
#
# sift.read_features_from_file(featlist[i])[1]:
# list of [feature values] for i-th image
# size: (# of feature point x 128) for i-th image
for i in arange(1, nbr_images):
descr.append(sift.read_features_from_file(featlist[i])[1])
descriptors = vstack((descriptors, descr[i])) # stack of vector
#len(descr[0]): number of feature points -> 2276
#len(descr[0][1]): size of 1st feature vector -> 128
voc, distortion = kmeans(descriptors[::10,:],3,1) # select one per 10 rows, 3개의 word를 뽑아냄
len(voc) #3, voc = 3x128
len(voc[0]) #3
len(voc[1]) #128
nbr_words = voc.shape[0] #3
# (# of images, bins of histogram(= # of words))
# = (12x3)
imwords=zeros((nbr_images, nbr_words))
print imwords
words, distance = vq(descr[0],voc) # vector quantization
# len(words)->2276
# words: index vector of the cluster that each feature involves
# [1, 2, 1, 0, 1, 2, ...]
#voca = vocabulary.Vocabulary('ukbenchtest')
for i in range(nbr_images): # def project
hist = zeros((nbr_words))
words, distance = vq(descr[i],voc)
# 현재 im에 대해 각 feature가 속하는 word의 index와 이 word까지의 거리가 리턴
# index를 이용하여 해당 word에 보팅하여 histogram을 만듬
for w in words:
hist[w] += 1
imwords[i] = hist
print imwords # degree that each im involve to each cluster
"""
0 1 2 : cluster index (word가 3개이니까 index는 2까지)
[[ 766. 461. 1049.]: 1st image의 histogram의 모양
[ 725. 451. 1020.]: 2nd image의 "
[ 671. 461. 1133.]: ...
[ 1101. 630. 1403.]
[ 260. 317. 409.]
[ 267. 308. 370.]
[ 283. 394. 476.]
[ 239. 331. 410.]
[ 1105. 468. 1317.]
[ 116. 191. 390.]
[ 122. 251. 439.]
[ 1183. 597. 1475.]]: 12번째 im의 histogram모양
12번째 이미지의 모든 특징 중에서 word 0에 속하는 것은 1183개, 1번 597개, 2번 1475개이다. 3경우 합하면 특징의 개수이다. 따라서 test영상의 특징에 대한 histogram을 그리고 위 12개 중에서 hist모양이 비슷한 것을 찾으면 그것이 해당 영상이다.
"""
다음의 코드에서 voc의 내용을 알 수 있음.
피드 구독하기:
글 (Atom)