Bag of Feature 圖像檢索

目錄

一、Bag of Feature介紹

1.1 Bag of Words 模型

1.2 Bag of Feature算法

1.3 Bag of Feature 算法步驟

1.3.1 特徵提取

1.3.2 構造“視覺單詞”

1.3.3 TF-IDF計算權重

二、Bag of Feature進行圖像檢索

2.1 SIFT提取特徵

2.2 圖像索引

2.3 搜索圖像

2.4 問題解決


Bag of Feature 是一種圖像特徵提取方法,它借鑑了文本分類的思路(Bag of Words),從圖像抽象出很多具有代表性的「關鍵詞」,形成一個字典,再統計每張圖片中出現的「關鍵詞」數量,得到圖片的特徵向量。

一、Bag of Feature介紹

1.1 Bag of Words 模型

「Bag of Words」 是文本分類中一種通俗易懂的策略。一般來講,如果我們要了解一段文本的主要內容,最行之有效的策略是抓取文本中的關鍵詞,根據關鍵詞出現的頻率確定這段文本的中心思想。比如:如果一則新聞中經常出現「iraq」、「terrorists」,那麼,我們可以認爲這則新聞應該跟伊拉克的恐怖主義有關。而如果一則新聞中出現較多的關鍵詞是「soviet」、「cuba」,我們又可以猜測這則新聞是關於冷戰的。

這裏所說的關鍵詞,就是「Bag of words」中的 words ,它們是區分度較高的單詞。根據這些 words ,我們可以很快地識別出文章的內容,並快速地對文章進行分類。

「Bag of Feature」也是借鑑了這種思路,只不過在圖像中,我們抽出的不再是一個個「word」,而是圖像的關鍵特徵「Feature」,所以研究人員將它更名爲「Bag of Feature」。

1.2 Bag of Feature算法

從對Bag of Words的介紹中,我們也可以看到,「Bag of Feature」的本質是提出一種圖像的特徵表示方法

按照「Bag of Feature」算法的思想,首先我們要找到圖像中的關鍵詞,而且這些關鍵詞必須具備較高的區分度。實際過程中,通常會採用「SIFT」特徵。

有了特徵之後,我們會將這些特徵通過聚類算法得出很多聚類中心。這些聚類中心通常具有較高的代表性,比如,對於人臉來說,雖然不同人的眼睛、鼻子等特徵都不盡相同,但它們往往具有共性,而這些聚類中心就代表了這類共性。我們將這些聚類中心組合在一起,形成一部字典(CodeBook)

對於圖像中的每個「SIFT」特徵,我們能夠在字典中找到最相似的聚類中心,統計這些聚類中心出現的次數,可以得到一個向量表示(或直方圖表示),如下面的圖片所示。這些向量就是所謂的「Bag」。這樣,對於不同類別的圖片,這個向量應該具有較大的區分度,在此基礎上,我們可以訓練出一些分類模型,並用其對圖片進行分類。

1.3 Bag of Feature 算法步驟

Bag of Feature用於圖像檢索的步驟:

  1. 對數據集做SIFT特徵提取
  2. 根據SIFT特徵提取結果,採用k-means算法對圖像庫中的特徵點進行訓練,生成類心,構造單詞表。
  3. 根據IDF原理,計算每個視覺單詞的權,生成Bof
  4. 對圖像進行檢索

1.3.1 特徵提取

對數據集裏的圖像進行SITF特徵提取,SIFT原理和之前的文章有詳細講解,這裏不再介紹。這些典型實例可以通 過分析訓練圖像集確定,並被視爲視覺單詞。所有這些視覺單詞構成的集合稱爲視覺詞彙,有時也稱爲視覺碼本。對於給定的問題、圖像類型,或在通常情況下僅需 呈現視覺內容,可以創建特定的詞彙。
實驗第一步是提取所有圖像的特徵,稱之爲“視覺詞彙”,將他們聚集在一起,此時他們還是未分類的。

1.3.2 構造“視覺單詞”

“視覺詞典(visual vocabulary)”的構造的過程就是一個圖像分類的過程。這裏我們用的圖像分類方法是K-means聚類方法。

K-means聚類步驟:

  1. 隨機初始化 K 個聚類中心
  2. 重複下述步驟直至算法收斂:
    對應每個特徵,根據距離關係賦值給某個中心/類別
    對每個類別,根據其對應的特徵集重新計算聚類中心

採用K-means算法的時候,我們需要自己設置分類數目,設置碼本數需要適當選擇,不能太少也不能太多:太少會導致視覺單詞無法覆蓋所有可能出現的情況;太多的話計算量大,容易過擬合。

1.3.3 TF-IDF計算權重

通過單詞計數來構建文檔直方圖向量v,從而建立文檔索引。由於每篇文檔長度不同,故除以直方圖總和將向量歸一化成單位長度。對於直方圖向量中的 每個元素,一般根據每個單詞的重要性來賦予相應的權重。通常,數據集(或語料庫)中一個單詞的重要性與它在文檔中出現的次數成正比,而與它在語料庫中出現的次數成反比。
最常用的權重是 tf-idf(term frequency-inverse document frequency,詞頻- 逆向文檔頻率 ),單詞 w 在文檔 d 中的詞頻是:

Alt

n_{w} 是單詞 w 在文檔 d 中出現的次數。爲了歸一化,將 nw 除以整個文檔中單詞的總數。
逆向文檔頻率爲:
Alt

|D| 是在語料庫D 中文檔的數目,分母是語料庫中包含單詞w 的文檔數d。將兩者 相乘可以得到矢量 v 中對應元素的 tf-idf 權重。

注意將不同圖像都具有的特徵對應的權重調小(不具備獨特的特徵),排除干擾。

二、Bag of Feature進行圖像檢索

實驗數據集:包含100張圖片,然後再拿一些圖像進行query,來找出庫中與之對應的圖像。下面顯示數據集的一部分

2.1 SIFT提取特徵

首先用SIFT提取圖像的特徵,並創建一個k爲150的詞彙表,保存整個詞彙對象以供後面使用,vocabulary.pkl包含了已經訓練好的詞彙。

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


# 獲取圖像列表
imlist = imtools.get_imlist('C:/Users/asus/Pictures/window/jiansuo/')
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, 150, 5)
# 保存詞彙
# saving vocabulary
with open('C:/Users/asus/Pictures/window/jiansuo/vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)
print('vocabulary is:', voc.name, voc.nbr_words)



進行SIFT特徵提取之後,在數據集中的顯示有對應的sift文件,如下:

2.2 圖像索引

我們需要創建表、索引和索引器,然後將圖像數據寫入數據庫中。在下面代碼中實現遍歷所有的圖像,並將其加入到索引中,提交到數據庫。

import pickle
from PCV.imagesearch import imagesearch
from PCV.tools import imtools
from PCV.localdescriptors import sift
from sqlite3 import dbapi2 as sqlite

# 獲取圖像列表
imlist = imtools.get_imlist('C:/Users/asus/Pictures/window/jiansuo/')
nbr_images = len(imlist)

# 獲取特徵列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]


# 載入詞彙
with open('C:/Users/asus/Pictures/window/jiansuo/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
# 創建索引
indx = imagesearch.Indexer('testImaAdd.db', voc)
# indx.create_tables()

# 遍歷所有的圖像,並將它們的特徵投影到詞彙上
for i in range(nbr_images)[:150]:
    locs, descr = sift.read_features_from_file(featlist[i])
    indx.add_to_index(imlist[i], descr)

# 提交到數據庫
indx.db_commit()

# 檢查數據庫中的內容
con = sqlite.connect('testImaAdd.db')
print(con.execute('select count (filename) from imlist').fetchone())
print(con.execute('select * from imlist').fetchone())
print(con.execute('select * from imlist').fetchall())

 提交數據庫之後可以查詢到數據庫中的內容如下:

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:/Users/asus/Pictures/window/jiansuo/')
nbr_images = len(imlist)
# 載入特徵列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]

# 載入詞彙
with open('C:/Users/asus/Pictures/window/jiansuo/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)

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

# 查詢圖像索引和查詢返回的圖像數
q_ind = 70
nbr_results = 10

# regular query
# 常規查詢(按歐式距離對結果排序)
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])  # because 'ndx' is a rowid of the DB that starts at 1
    # get matches
    matches = 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 count
    rank[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[:5])  # 常規查詢
imagesearch.plot_results(src, res_geom[:5])  # 重排後的結果

(1)檢索的圖片69.jpg 

檢索結果(上下兩圖分別爲常規查詢和重排後結果):

(2)圖片3.jpg

檢索結果:

分析:經過多次不同圖片的檢索結果,發現相比之下重排序之後的檢索明顯的檢索出來的圖像相似度比較高,在對圖像查詢相似的10個圖像列表中,要輸出最接近的五張圖片,重排後相似度較高的靠的比較前面輸出來的結果較好。但是兩種查詢的圖像都有可能是檢索出沒多大相似的圖像。檢查發現有一些相似圖片沒有達到輸出的五張,所以會混入其他不相似的圖,數據集可以做適當的修改,以減少結果的誤差。

 

2.4 問題解決

(1)實驗需要進行sift特徵匹配,所以實驗前應該把如下的兩個文件放到當前文件目錄下,否則會報錯。

(2)進行建立數據庫的操作時需要用到pysqlite,在官網沒有找到相應的WHL文件,其實python3 自帶了sqlite3庫,直接使用就可以。

 

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