使用HOG+卡方距離的方法實現圖片檢索(python寫)
阿新 • • 發佈:2018-12-10
在上一篇的文章中,使用HOG特徵提取了圖片的特徵,本篇文章則加上卡方距離的方法實現相似圖片的檢索。
前言
使用150張圖片,包括airplane、beach、desert、island和sea_ice各50張圖片進行測試。
第一步,獲取圖片特徵
獲取150張圖片的特徵,並且儲存到index.csv資料夾中。首先開啟一個檔案,並將此檔案命名為getfeats.py。
#coding:utf-8
import numpy as np
from skimage.feature import hog
from PIL import Image
size = 256
#獲取圖片列表
def get_image_list(filePath,nameList):
img_list = []
for name in nameList:
temp = Image.open(filePath+name)
img_list.append(temp.copy())
temp.close()
return img_list
def get_feat(image_list,name_list,size):
i = 0
for image in image_list:
#print(name)
try:
#這裡是彩色圖片,所以是3
image = np.reshape(image, (size, size, 3))
#print(image)
except:
print (name_list[i])
continue
gray = rgb2gray(image)/255.0
#根據自己的資料集進行修改
fd = hog(gray, orientations=9, pixels_per_cell=[8 ,8], cells_per_block=[4,4], visualize=False, transform_sqrt=True,block_norm='L2-Hys')
fd = np.concatenate((fd, [name_list[i]]))
i = i+1
#print(fd)
output = open('index.csv', "a") #a是新增資料,如果是重新寫入用w
output.write("%s,%s\n" % (fd[-1], ",".join(fd[:-2])))
output.close()
#變為灰度圖片
def rgb2gray(im):
gray = im[:, :, 0]*0.2989+im[:, :, 1]*0.5870+im[:, :, 2]*0.1140
return gray
#獲得圖片名稱
def get_name_label(file_path):
#print(file_path)
name_list = []
label_list = []
with open(file_path) as f:
for line in f.readlines():
name_list.append(line.split(' ')[0])
label_list.append(line.split(' ')[1]) #此處對於此程式碼是多餘的,以後可能會用得上
#print(name_list,label_list)
return name_list,label_list
if __name__ == '__main__':
train_name,train_label = get_name_label('./image/train.txt')
train_image = get_image_list('./image/',train_name)
get_feat(train_image,train_name,size)
第二步,定義卡方距離
需要一個新的資料夾 ,將其命名為searcher.py。
#coding:utf-8
import getfeat
import numpy as np
import csv
def search( queryFeatures, limit = 5):
# initialize our dictionary of results
results = {}
# 開啟索引並進行讀取
with open('index.csv') as f:
# 初始化CSV閱讀器
reader = csv.reader(f)
# 迴圈遍歷索引中的每一行
for row in reader:
#解析影象ID和特徵,然後計算索引中的要素與查詢要素之間的卡方距離
features = [float(x) for x in row[1:]]
d = chi2_distance(features, queryFeatures)
#既然我們有兩個特徵向量之間的距離,我們可以更新結果字典
#關鍵詞是索引中的當前影象ID,值是我們剛剛計算的距離,
#索引中影象的“相似”程度是我們的查詢結果
results[row[0]] = d
#關閉閱讀器
f.close()
#對我們的結果進行排序,以便縮小距離(即更相關的影象位於列表的前面)。值越小,相似度越高
results = sorted([(v, k) for (k, v) in results.items()])
#返回我們(有限)的結果
return results[:limit]
def chi2_distance( histA, histB, eps = 1e-10):
#計算卡方距離
d = 0.5 * np.sum([((a - b) ** 2) / (a + b + eps)
for (a, b) in zip(histA, histB)])
#返回卡方距離
return d
第三步,將查詢圖片進行特徵提取
開啟一個檔案,將其命名為geatfeat.py.
#coding:utf-8
import numpy as np
from PIL import Image
from skimage.feature import hog
size = 256
#提取圖片特徵
def get_feat():
image = 'beach_001.jpg'
image = Image.open(image)
#image.show()
image = np.reshape(image, (size, size, 3))
#print(image)
gray = rgb2gray(image)/255.0
#這句話可以根據自己的圖片集進行修改
fd = hog(gray, orientations=9, pixels_per_cell=[8,8], cells_per_block=[4,4], visualize=False, transform_sqrt=True,block_norm='L2-Hys')
#print(fd)
return fd
#變為灰度圖片
def rgb2gray(im):
gray = im[:, :, 0]*0.2989+im[:, :, 1]*0.5870+im[:, :, 2]*0.1140
return gray
if __name__ == '__main__':
get_feat()
第四步,進行圖片檢索
建立第四個檔案,命名為search.py。
#coding:utf-8
import searcher
import cv2
import getfeat
queryFeatures = getfeat.get_feat()
#print(queryFeatures)
results = searcher.search(queryFeatures)
#顯示查詢影象
image = 'beach_001.jpg'
Query = cv2.imread(image)
cv2.imshow('Query',Query)
for (score, resultID) in results:
#載入結果影象並顯示它
result = cv2.imread("image" + "/" + resultID)
cv2.imshow("Result", result)
cv2.waitKey(0)
print(score)
print(resultID)
結果
由於圖片的數量較少,所以結果只返回了5張。後續將新增資料集進行重新實驗,並且調整相關的引數看能否提高檢索的精度。
如有什麼問題或者需要資料集,可與小編進行聯絡,郵箱:[email protected]。