在上一篇的文章中,使用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]。