計算機視覺——基於bag of features的圖像檢索

1. 原理

1.1 Bag of features算法

Bag of features,簡稱Bof,中文翻譯爲“詞袋”,是一種用於圖像或視頻檢索的技術。而檢索就要進行比對。兩幅不同的圖像如何比對,比對什麼,這就需要提煉出每幅圖像中精練的東西出來進行比較。

1、Bag of features算法基礎流程
1、收集圖片,對圖像進行sift特徵提取。
在這裏插入圖片描述
2、從每類圖像中提取視覺詞彙,將所有的視覺詞彙集合在一起。
在這裏插入圖片描述
3、利用K-Means算法構造單詞表。
K-Means算法是一種基於樣本間相似性度量的間接聚類方法,此算法以K爲參數,把N個對象分爲K個簇,以使簇內具有較高的相似度,而簇間相似度較低。SIFT提取的視覺詞彙向量之間根據距離的遠近,可以利用K-Means算法將詞義相近的詞彙合併,作爲單詞表中的基礎詞彙,假定我們將K設爲3,那麼單詞表的構造過程如下:
在這裏插入圖片描述
4、針對輸入的特徵集,根據視覺詞典進行量化,把輸入圖像轉化成視覺單詞的頻率直方圖。
在這裏插入圖片描述
5、構造特徵到圖像的倒排表,通過倒排表快速索引相關圖像。
6、根據索引結果進行直方圖匹配。

1.2 K-means算法簡介

1.2.1 原理
k-means算法是一種聚類算法,所謂聚類,即根據相似性原則,將具有較高相似度的數據對象劃分至同一類簇,將具有較高相異度的數據對象劃分至不同類簇。聚類與分類最大的區別在於,聚類過程爲無監督過程,即待處理數據對象沒有任何先驗知識,而分類過程爲有監督過程,即存在有先驗知識的訓練數據集。

k-means算法中的k代表類簇個數,means代表類簇內數據對象的均值(這種均值是一種對類簇中心的描述),因此,k-means算法又稱爲k-均值算法。k-means算法是一種基於劃分的聚類算法,以距離作爲數據對象間相似性度量的標準,即數據對象間的距離越小,則它們的相似性越高,則它們越有可能在同一個類簇。數據對象間距離的計算有很多種,k-means算法通常採用歐氏距離來計算數據對象間的距離。

1.2.2 步驟
(1)從數據中選擇k個對象作爲初始聚類中心;
(2)計算每個聚類對象到聚類中心的距離來劃分;
(3)再次計算每個聚類中心;
(4)計算標準測度函數,之道達到最大迭代次數,則停止,否則,繼續操作。

2. 代碼

2.1sift特徵匹配

# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift

#獲取圖像列表
imlist = get_imlist('C:\Python\Pictrue\cgr/')
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, 1000, 10)
#保存詞彙
# saving vocabulary
with open('C:\Python\Pictrue\cgr/vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)
print 'vocabulary is:', voc.name, voc.nbr_words

2.2將得到的數據模型放入數據庫文件testImaAdd.db中

# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import imagesearch
from PCV.localdescriptors import sift
import sqlite3
from PCV.tools.imtools import get_imlist

# 獲取圖像列表
# imlist = get_imlist('E:/Python37_course/test7/first1000/')
imlist = get_imlist('C:\Python\Pictrue\cgr/')
nbr_images = len(imlist)
# 獲取特徵列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]

# load vocabulary
# 載入詞彙
'''with open('E:/Python37_course/test7/first1000/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)'''
with open('C:\Python\Pictrue\cgr//vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
# 創建索引
indx = imagesearch.Indexer('testImaAdd.db', voc)
indx.create_tables()
# go through all images, project features on vocabulary and insert
# 遍歷所有的圖像,並將它們的特徵投影到詞彙上

# for i in range(nbr_images)[:1000]:
for i in range(nbr_images)[:26]:
    locs, descr = sift.read_features_from_file(featlist[i])
    indx.add_to_index(imlist[i], descr)
# commit to database
# 提交到數據庫
indx.db_commit()

con = sqlite3.connect('testImaAdd.db')
print (con.execute('select count (filename) from imlist').fetchone())
print (con.execute('select * from imlist').fetchone())

2.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

# 載入圖像列表
imlist = get_imlist('C:\Python\Pictrue\cgr/')
nbr_images = len(imlist)
# 載入特徵列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]

# 載入詞彙
with open('C:\Python\Pictrue\cgr/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)

src = imagesearch.Searcher('testImaAdd.db', voc)

# 查詢圖像索引和查詢返回的圖像數
q_ind = 5
nbr_results = 20

# 常規查詢(按歐式距離對結果排序)
res_reg = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]]
print('top matches (regular):', res_reg)

# 載入查詢圖像特徵
q_locs, q_descr = sift.read_features_from_file(featlist[q_ind])
fp = homography.make_homog(q_locs[:, :2].T)

# 用單應性進行擬合建立RANSAC模型
model = homography.RansacModel()
rank = {}

# 載入候選圖像的特徵
for ndx in res_reg[1:]:
    locs, descr = sift.read_features_from_file(featlist[ndx])

    matches = sift.match(q_descr, descr)
    ind = matches.nonzero()[0]
    ind2 = matches[ind]
    tp = homography.make_homog(locs[:, :2].T)
    try:
        H, inliers = homography.H_from_ransac(fp[:, ind], tp[:, ind2], model, match_theshold=4)
    except:
        inliers = []
    rank[ndx] = len(inliers)

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])  # 重排後的結果

3. 實驗結果及分析

3.1實驗結果

sift特徵提取
在這裏插入圖片描述
生成數據模型vocabulary.pkl
在這裏插入圖片描述
將數據模型存放數據庫testImaAdd.db中
在這裏插入圖片描述
以數據庫中第一張圖爲檢索輸入,檢索與其特徵匹配前六的圖片
第一組:
在這裏插入圖片描述
與之匹配最高的是以下6張:
在這裏插入圖片描述
第二組:
在這裏插入圖片描述

3.2 實驗小結

在這次實驗中圖像的匹配還是比較成功,第一組實驗完全匹配,但是第二組實驗有一張圖片沒有匹配成功,說明可能在創建詞彙上,特徵描述相似,也可能是因爲數據集不夠大(本次只包含100張圖),造成了誤配。
1.使用k-means聚類,除了其K和初始聚類中心選擇的問題外,對於海量數據,輸入矩陣的巨大將使得內存溢出及效率低下。Kmeans聚類時間長,速度慢。
2.重排後的查詢結果會比常規查詢結果更爲準確些,重排用單應性進行擬合建立RANSAC模型,再導入候選圖像特徵進行排序查詢,常規查詢只是進行了簡單的索引和查詢,找到相似即可。
3.詞袋錶徵特徵的過程其實牽涉到量化的過程,這其實損失了特徵的精度,使精度低下。

4. 遇到的問題及解決方法

4.1 ‘module’ object has no attribute ‘process_image’
python文件的名稱不要與內置模塊重名,我把文件名和存放圖片的文件夾的名稱改掉後即可運行。

4.2 sqlite包缺省
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyopengl下載
在這裏插入圖片描述
我的電腦是windows10 64位,python版本是python2.7的就安裝python2.7的包,然後在cmd中先進入到指定文件夾緊接着輸入
pip install
就可以使用sqlite包了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章