程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python計算機視覺-圖像檢索和識別

編輯:Python

文章目錄

    • 原理解析
      • 1.1計算機視覺領域的圖像分類是什麼意思?
      • 1.2圖像分類要如何實現?
      • 1.3Bag-of-features算法和過程?
      • 1.4TF-IDF?
      • 1.5當前圖像分類中會遇到一些值得挑戰的問題?
    • 數據集
      • 處理
    • 代碼
      • **2.1**創建詞匯
      • 2.2 建立數據庫
      • 2.3在數據庫中搜索圖像
    • 運行結果

原理解析

1.1計算機視覺領域的圖像分類是什麼意思?

圖像分類,即通過圖像內容的不同將圖像劃分為不同的類別,
該技術二十世紀九十年代末提出,並命名為基於圖像內容的圖像分類(Content- Based ImageClassific- ation, CEIC)算法概念,
基於內容的圖像分類技術不需要對圖像的語義信息進行人工標注,
而是通過計算機提取圖像中所包含的特征,並對特征進行處理和分析,得出分類結果。

常用的圖像特征有 圖像顏色、紋理、灰度等信息。而圖像分類過程中,
提取的特征要求不容易受隨機因素干擾,特征的有效提取可提高圖像分類的精度。
特征提取完成後,選擇合適的算法創建圖像類型與視覺特征之間的關聯度,對圖像進行類別劃分。

圖像分類領域中,根據圖像分類要求,一般可以分為 場景分類和 目標分類兩類問題。
場景分類也可以稱為事件分類,場景分類是對 整幅圖像所代表的 整體信息進行分類,或者是對圖像中 所發生事件的總體描述。
目標分類(又稱為物體分類)是對圖像中 出現的目標 (物體)進行識別或分類。

1.2圖像分類要如何實現?

視覺詞袋模型( Bag-of-features )是當前計算機視覺領域中較為常用的圖像表示方法。
視覺詞袋模型來源於詞袋模型(Bag-of-words),詞袋模型最初被用在文本分類中,將文檔表示成特征矢量。它的基本思想是假定 對於一個文本,忽略其詞序和語法、句法, 僅僅將其看做是一些詞匯的集合, 而文本中的每個詞匯都是獨立的。簡單說就是講每篇文檔都看成一個袋子 (因為裡面裝的都是詞匯,
所以稱為詞袋,Bag of words即因此而來)然後看這個袋子裡裝的都是些什麼詞匯,將其分類。
如果文檔中豬、 馬、牛、羊、山谷、土地、拖拉機這樣的詞匯多些,而銀行、大廈、汽車、公園這樣的詞匯少些, 我們就傾向於判斷它是一 篇描繪鄉村的文檔,而不是描述城鎮的。
Bag of Feature也是借鑒了這種思路,只不過在圖像中,我們抽出的不再是一個個word, 而是 圖像的關鍵特征Feature,所以研究人員將它更名為Bag of Feature.Bag of Feature在檢索中的算法流程和分類幾乎完全一樣,唯一的區別在於,對於原始的BOF特征,也就是直方圖向量,我們引入TF_IDF權值。

1.3Bag-of-features算法和過程?

算法過程:
1)提取圖像特征
2)對特征進行聚類,得到一部視覺字典( visual vocabulary )
3)根據字典將圖片表示成向量(直方圖)
4)把輸入圖片轉化成視覺單詞的頻率直方圖

1)提取圖像特征
特征提取及描述主要是將一些 具有代表性且 區分性較強的 全局或局部特征從圖像中進行抽取,並對這些特征進行描述。
這些特征一般是類別之間差距比較 明顯的特征,可以將其與其他類別區分開,其次,這些特征還要求具有 較好的穩定性,能夠最大限度的在光照、視角、尺度、噪聲以及各種外在因素變化的情況下保持穩定,不受其影響。這樣即使在非常復雜的情況下,計算機也能通過這些穩定的特征很好的檢測與識別出這個物體。
特征提取最簡單且有效的方法就是 規則網格方法,
該方法采用均勻網格對圖像進行劃分,從而得到圖像的局部區域特征。
興趣點檢測方法是另一個有效的特征提取方法,興趣點檢測的基本思想是:
在人為判斷一幅圖像的類別時,首先捕捉到物體的整體輪廓特征,然後聚焦於物體與其他物體具有顯著特征區別的地方,最後判斷出圖像的類別。即通過該物體與其他物體 區別開的 顯著特征,進而判斷圖像的類別。
在提取完圖像的特征後,下一步就要應用特征描述子來對抽取的圖像特征進行描述,特征描述子所表示的特征向量一般在處理算法時會作為輸入數據,因此,如果描述子具有一定的判別性及可區分性,則該描述子會在後期的圖像處理過程中起著很大的作用。
其中,SIFT描述子是近年比較經典且被廣泛應用的一種描述子。
SIFT會從圖片上提取出很多特征點,每個特征點都是128維的向量,因此,如果圖片足夠多的話,我們會提取出一個巨大的特征向量庫。

2)訓練字典( visual vocabulary )

在上面提取完SIFT特征的步驟後,利用K-means聚類算法將提取的SIFT特征聚類生成視覺詞典。
K-means算法是度量樣本間相似性的一種方法,該算法設置參數為K,把N個對象分成K個簇,簇內之間的相似度較高,而簇間的相似度較低。聚類中心有K個,視覺詞典為K。構建視覺單詞的過程如圖所示。

提取完特征後,我們會采用一些 聚類算法對這些特征向量進行聚類。 最常用的聚類算法是k-means。
至於k-means中的k如何取,要根據具體情況來確定。另外,由於特征的數量可能非常龐大,這個聚類的過程也會非常漫長。聚類完成後,我們就得到了這k個向量組成的字曲,這k個向量有一個通 用的表達,叫visual word.

3)圖片直方圖表示
利用視覺詞典中的詞匯表示待分類圖像。計算每幅圖像中的SIFT特征到這K個視覺單詞的距離,
其中 距離最近的視覺單詞為該SIFT特征對應的視覺單詞。
通過統計每個單詞在圖像中出現的次數,將圖像表示成一個K維數值向量,
如圖所示,其中K=4,每幅圖像用直方圖進行描述。

4)訓練分類器
當我們得到每幅圖片的直方圖向量後,剩下的這一步跟以往的步驟是一樣的。
無非是數據庫圖片的向量以及圖片的標簽,訓練分類器模型。然後對需要預測的圖片,我們仍然按照上述方法,提取SIFT特征,再根據字典量化直方圖向量,用分類器模型對直方圖向量進行分類。當然,也可以直接根據 KNN 算法對直方圖向量做相似性判斷。

1.4TF-IDF?

TF-IDF(Term frequency-Inverse document frequency)是一種統計方法,用來評估特征詞的重要程度。根據TF-IDF公式,特征詞的權重與在 語料庫中出現的頻率有關,也與在文檔裡出現的頻率有關。傳統的TF-IDF公式如下:

TF-IDF用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨著它在文件中出現的次數成正比增加,但同時會隨著它在語料庫中出現的頻率成反比下降。就目前來說,如果一個 關鍵詞只在很少的網頁中出現,我們通過它就 容易鎖定搜索目標,它的 權重也就應該 大。反之如果一個詞在大量網頁中出現,我們看到它仍然 不是很清楚要找什麼內容,因此它應該 小。

1.5當前圖像分類中會遇到一些值得挑戰的問題?

圖像分類的目的是 通過圖像內容對一幅未知圖像進行分類。
但人類自身進行觀察時,由於人們對圖像的理解不同,偏重不同,不同的人也會產生不同的結果,
而且人為判斷一幅圖像的類別時,具有一定的主觀性。
而計算機是客觀的,它會通過一定的數據信息來判斷圖像的類別。
因此圖像分類是一個比較困難的問題,並且該問題很難達到完美,
現在的分類方法大多都是盡可能地將分類准確率繼續提高。
圖像分類過程中遇到的問題主要是由 圖像的類內變化、 圖像類間的語義差異和 語義鴻溝造成的。
1、類內差異。
所謂類內差異表示的是屬於同一類的圖像,由於各種原因,使圖像的內容呈現出多種變化。
類內差異主要包括: 視角差異、目標形變、光照差異、尺度差異、部分遮擋、復雜背景、同類異形等。

2、類間差異。
所謂類間差異指的是不同類別含有相同的底層特征,導致不同類別圖像分為同一類別。

3、語義鴻溝
長期的知識積累,人類可以通過對圖像高層次的抽象理解進而對語義的相似性進行判斷。
但計算機只能通過圖像底層的統計特征來判斷圖像類別,不具備人類 對圖像進行抽象和推理的能力,
導致計算機提取的圖像底層視覺特征獲取的圖像類別信息和人類對圖像的理解獲取的圖像類別信息不一致,造成“語義鴻溝”,
“語義鴻溝” 實際上就是圖像的 底層視覺特征與 高層語義信息之間的 客觀區別。

數據集

32張手機相片

處理

統一圖片大小

import cv2
from cv2 import imwrite
import numpy as np
import glob
images = glob.glob('./imaRetrieval/img/*.jpg') # 標定所用圖像
for fname in images:
img = cv2.imread(fname)
# img = cv2.resize(img, (640, 480), interpolation=cv2.INTER_AREA)
imwrite(fname,img)

代碼

2.1創建詞匯

對每張圖片生成相應的sift文件,及視覺詞匯,以便建立BOW模型。我所用的是圖像集為37張。如果需要增加圖像或減少只需要改代碼裡讀取訓練圖像的數量。要得到不同維度的量級,需要修改數據集訓練次數。

# -*- 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('./imaRetrieval/img/')
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, 30, 10)
#保存詞匯
# saving vocabulary
with open('./imaRetrieval/img/vocabulary.pkl', 'wb') as f:
pickle.dump(voc, f)
print('vocabulary is:', voc.name, voc.nbr_words)

2.2 建立數據庫

將上面得到的數據模型存放數據庫testImaAdd.db中,即運行下面代碼會生成一個testImaAdd.db數據庫文件。

# -*- codeing =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('./imaRetrieval/img/')
nbr_images = len(imlist)
# 獲取特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# load vocabulary
# 載入詞匯
with open('./imaRetrieval/img/vocabulary.pkl', 'rb') as f:
voc = pickle.load(f)
# 創建索引
indx = imagesearch.Indexer('./imaRetrieval/testImaAdd.db', voc)
indx.create_tables()
# go through all images, project features on vocabulary and insert
# 遍歷所有的圖像,並將它們的特征投影到詞匯上
for i in range(nbr_images)[:32]:
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在數據庫中搜索圖像

利用索引獲取候選圖像 + 用一幅圖像進行查詢 + 確定對比基准並繪制結果
建立好圖像的索引,就可以在數據庫中搜索相似的圖像了。這裡,使用BoW(詞袋模型)來表示整個圖像,這是通用的,可以應用於尋找相似的物體、相似的臉、相似的顏色等,它完全取決於圖像及所用的描述子。為了實現搜索,在Imagesearch.py中添加Searcher類。

# -*- codeing =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('./imaRetrieval/img/') # 存放數據集的路徑
nbr_images = len(imlist)
# 載入特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# 載入詞匯
with open('./imaRetrieval/img/vocabulary.pkl', 'rb') as f: # 存放模型的路徑
voc = pickle.load(f)
src = imagesearch.Searcher('./imaRetrieval/testImaAdd.db', voc)
# index of query image and number of results to return
# 查詢圖像索引和查詢返回的圖像數
q_ind =10
nbr_results = 4
# 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:]:
locs, descr = sift.read_features_from_file(featlist[ndx]) # because 'ndx' is a rowid of the DB that starts at 1
# get matches
# 獲取匹配數 # 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[:8]) # 常規查詢
imagesearch.plot_results(src, res_geom[:8]) # 重排後的結果

運行結果

最左邊為被選中查詢的圖片,每次四張。數據集很小(本人少拍照)僅圖一樂


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved