计算机视觉:Bag of words算法实现图像识别与搜索
計算機視覺:bag of words算法實現圖像識別與搜索
- 原理
- 綜述
- 基礎流程
- 結果與解析
- 數據集
- 結果與解析
- 總結
- 源代碼
- 出現的錯誤及解決方案
原理
綜述
Bag of words,顧名思義,就是單詞袋模型。這里的“單詞”指代我們在圖像數據庫中所提取出的“圖像特征”,每個特征就是一個單詞,如下圖所示。我們主要通過匹配圖像中出現單詞頻率“最像”的圖像,為其匹配圖像。通過獲取到的單詞直方圖,計算其與數據庫中圖像的歐氏距離,規定一定閾值內的圖像為其所匹配到的圖像,最終實現圖像識別與搜索。
基礎流程
1.特征提取
如下圖所示,提取數據圖像中的每個特征點即sift特征點。
2.學習 “視覺詞典”
將所有提取到的特征點進行歸類,獲得“單詞”,將所有的單詞整合為一份“視覺詞典”
3.數據量化
針對所輸入的圖片數據特征集,根據所得到的視覺詞典對其進行量化
4.詞頻統計
將輸入的圖片數據轉化為視覺單詞的頻率直方圖
5.聚類
對圖像進行聚類,可以使用K-means算法
首先隨機初始化 K 個聚類中心,接著對應每個特征,根據距離關系賦值給某個中心/類別,再對每個類別,根據其對應的特征集重新計算聚類中心,重復該過程直值算法收斂,完成聚類。
在聚類過程中,可以通過給定輸入圖像的BOW直方圖, 在數據庫中查找 k 個最近鄰的圖像,可以根據這k個近鄰圖像的分類標簽,進行投票獲得分類結果。
結果與解析
數據集
本文所用數據集為實地拍攝的廈門市各自然景區與博物館場景圖片數據,經Photoshop處理統一格式為 500X376大小的JPG圖片,共130張,部分圖片數據如下圖
經過特征提取等處理后生成的數據庫如下圖,用于記錄圖片數據的名稱,特征匹配值地址等數據
結果與解析
通過該算法,我們實現了輸入一張圖片找到數據集中多張與其類似的圖片。
所得結果如下圖所示,其中第一張圖片為輸入圖片,2至5張為匹配后所得到的圖片,從圖中可以看出其成功匹配出了多張該沙灘的圖片,但是也會出現最后一張麗龜標本圖所示毫不相干的圖片。這是由于該算法應用sift特征取過程中可能會出現錯誤的特征匹配,而在后續進行圖片搜索,進行特征直方圖對比過程中就會出現錯配。但由于只是局部錯配,因此在進行重排后其特征匹配的比率會低于像第二張圖片這樣與輸入圖片相似的圖片數據。
同時,打開訓練數據集,我們會發現里面有多張該沙灘的圖片,但是卻未能夠進行正確的匹配,對于這一點我還有一些疑惑,個人覺得可能是由于沙灘的特征比較難提取,角點較少,且無法提取到關鍵區域的特征點多導致。
接著通過匹配灰鯨標本圖片,并輸入9張類似圖片。可以發現所匹配的圖像基本都是準確的,或是像最后幾張圖一般輪廓大致相似的圖片,出現少量差別較大圖片原因如上文所述。而對于下圖所示出現輪廓相似的圖片。個人認為是由于在將特征識別并匯入詞典時都是應用灰度圖的形式,因此可能會將不同顏色的特征單詞識別為同一個單詞,從而造成的特征匹配錯誤。
總結
| 問題 | 原因 | 解決方案 |
|---|---|---|
| 大差異圖像錯配 | sift特征識別問題 | |
| 相似圖像未匹配 | 圖像景物單一,特征重復 | |
| 同輪廓圖像錯配 | 灰度圖問題 | 改為RGB格式詞典 |
源代碼
1.生成詞匯表
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
from PCV.imagesearch import imagesearch
from PCV.geometry import homography
from sqlite3 import dbapi2 as sqlite#獲取圖像列表
imlist = get_imlist('datasets/')
nbr_images = len(imlist)
#獲取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]#提取文件夾下圖像的sift特征
for i in range(nbr_images):sift.process_image(imlist[i], featlist[i])#生成詞匯
voc = vocabulary.Vocabulary('ukbenchtest')
voc.train(featlist, 888, 10) # 使用k-means算法在featurelist里邊訓練處一個詞匯# 注意這里使用了下采樣的操作加快訓練速度# 將描述子投影到詞匯上,以便創建直方圖
#保存詞匯
# saving vocabulary
with open('BOW/vocabulary.pkl', 'wb') as f:pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)
2.生成數據庫
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
from PCV.imagesearch import imagesearch
from PCV.geometry import homography
from sqlite3 import dbapi2 as sqlite # 使用sqlite作為數據庫#獲取圖像列表
imlist = get_imlist('datasets/')
nbr_images = len(imlist)
#獲取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]# load vocabulary
#載入詞匯
with open('BOW/vocabulary.pkl', 'rb') as f:voc = pickle.load(f)
#創建索引
indx = imagesearch.Indexer('testImaAdd.db',voc) # 在Indexer這個類中創建表、索引,將圖像數據寫入數據庫
indx.create_tables() # 創建表
# go through all images, project features on vocabulary and insert
#遍歷所有的圖像,并將它們的特征投影到詞匯上
for i in range(nbr_images)[:888]:locs,descr = sift.read_features_from_file(featlist[i])indx.add_to_index(imlist[i],descr) # 使用add_to_index獲取帶有特征描述子的圖像,投影到詞匯上# 將圖像的單詞直方圖編碼存儲
# commit to database
#提交到數據庫
indx.db_commit()con = sqlite.connect('testImaAdd.db')
print (con.execute('select count (filename) from imlist').fetchone())
print (con.execute('select * from imlist').fetchone())
3.圖像搜索
# -*- coding: utf-8 -*-
#使用視覺單詞表示圖像時不包含圖像特征的位置信息
import pickle
from PCV.localdescriptors import sift
from PCV.imagesearch import imagesearch
from PCV.geometry import homography
from PCV.tools.imtools import get_imlist# load image list and vocabulary
#載入圖像列表
#imlist = get_imlist('E:/Python37_course/test7/first1000/')
imlist = get_imlist('datasets/')
nbr_images = len(imlist)
#載入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]#載入詞匯
'''with open('E:/Python37_course/test7/first1000/vocabulary.pkl', 'rb') as f:voc = pickle.load(f)'''
with open('BOW/vocabulary.pkl', 'rb') as f:voc = pickle.load(f)src = imagesearch.Searcher('testImaAdd.db',voc)# Searcher類讀入圖像的單詞直方圖執行查詢# index of query image and number of results to return
#查詢圖像索引和查詢返回的圖像數
q_ind = 0
nbr_results = 130# regular query
# 常規查詢(按歐式距離對結果排序)
res_reg = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]] # 查詢的結果
print ('top matches (regular):', res_reg)# load image features for query image
#載入查詢圖像特征進行匹配
q_locs,q_descr = sift.read_features_from_file(featlist[q_ind])
fp = homography.make_homog(q_locs[:,:2].T)# RANSAC model for homography fitting
#用單應性進行擬合建立RANSAC模型
model = homography.RansacModel()
rank = {}
# load image features for result
#載入候選圖像的特征
for ndx in res_reg[1:]:try:locs,descr = sift.read_features_from_file(featlist[ndx]) except:continue#locs,descr = sift.read_features_from_file(featlist[ndx]) # because 'ndx' is a rowid of the DB that starts at 1# get matchesmatches = sift.match(q_descr,descr)ind = matches.nonzero()[0]ind2 = matches[ind]tp = homography.make_homog(locs[:,:2].T)# compute homography, count inliers. if not enough matches return empty list# 計算單應性矩陣try:H,inliers = homography.H_from_ransac(fp[:,ind],tp[:,ind2],model,match_theshold=4)except:inliers = []# store inlier countrank[ndx] = len(inliers)# sort dictionary to get the most inliers first
# 對字典進行排序,可以得到重排之后的查詢結果
sorted_rank = sorted(rank.items(), key=lambda t: t[1], reverse=True)
res_geom = [res_reg[0]]+[s[0] for s in sorted_rank]
print ('top matches (homography):', res_geom)# 顯示查詢結果
imagesearch.plot_results(src,res_reg[:6]) #常規查詢
imagesearch.plot_results(src,res_geom[:6]) #重排后的結果
出現的錯誤及解決方案
https://blog.csdn.net/qq_43605229/article/details/117608008
總結
以上是生活随笔為你收集整理的计算机视觉:Bag of words算法实现图像识别与搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 照相机模型与增强现实(相机标定)
- 下一篇: 计算机视觉:Bag of words算法