从图像数据库中查找图像

时间:2017-09-28 22:35:34

标签: python opencv flann

我正在用Python中的OpenCV移动我的第一步 我想要做的是给出一个图像,从参考图像集合中找到它的“原始”图像。需要明确的是,查询图像是整个图像(卡片)的简单照片,因此情况并非“在照片中找到对象”,而是“只是”相似性测试。 我的最终数据库将非常大(约25 000张图像),但我开始在较小规模上进行一些测试(仅270张图像)。
识别工作完美,但速度很慢:迭代所有270个图像需要8秒钟。我能够通过将描述符保存到磁盘并加载它们来加速工作,而不是计算它们;无论如何它仍然很慢。

所以我开始使用FLANN:我得到了一些结果,但我的主要问题是找到匹配的图像。我得到了一大堆积分,但我不知道如何获取正确的图像 这是我的代码:

scanned = 'tests/temp_bw.png'
surf = cv2.xfeatures2d.SURF_create(400)
surf.setUpright(True)

img1 = cv2.imread(scanned, 0)
kp1, des1 = surf.detectAndCompute(img1, None)

FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)

des_all = None
for filename in os.listdir('images'):
    img2 = cv2.imread('images/' + filename, 0)
    kp2, des2 = surf.detectAndCompute(img2, None)
    if des_all is None:
        des_all = des2
    else:
        des_all = np.concatenate((des_all, des2))

flann = cv2.flann.Index()
print "Training..."
flann.build(des_all, index_params)
print "Matching..."
indexes, matches = flann.knnSearch(des1, 10)
# and now???

有关如何引用最相似图像的任何建议?

修改 这是des2

的形状
print des2.shape
(1731, 64)
(2144, 64)
(1811, 64)
(1649, 64)

这些是flann.knnSearch的返回值:

pprint(matches[0])
array([ 0.0463759], dtype=float32)

pprint(indexes[0])
array([249106], dtype=int32)

2 个答案:

答案 0 :(得分:1)

在构建des_all时,创建一个与描述符数量相同的列表,其中每个元素都是此描述符所来自的图像的索引。

获得匹配的功能后,您可以在列表中查找该功能所匹配的图像。然后您可以对哪个图像正确进行简单的多数投票,或者使用距离的倒数称重投票的重要性。

编辑:如果你这样修改你的for循环,你可以构建一个列表,其中包含生成了哪些图像的特征:

for index, filename in enumerate(os.listdir('images')):
    img2 = cv2.imread('images/' + filename, 0)
    kp2, des2 = surf.detectAndCompute(img2, None)
    indexList.extend([index]*des2.shape[0])

如果你通过多数投票进行投票,可以这样做(每个特征都投票给它匹配的图像,投票最多的图像获胜)

votes = indexList[indexes]
from collections import Counter
votes = Counter()
likelyMatch = votes.most_common()[0][0]

如果你想用匹配的距离来衡量,你应该记住matches中的距离是平方的,你应该取平方根。这些距离可以用作反向权重,以使每个特征以更高或更低的权重投票,具体取决于它的匹配程度。

答案 1 :(得分:0)

一种简单(并且非常古老,至少是20世纪80年代)的技术是从每个图像计算空间散列,然后匹配散列。例如:

http://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html

您可以非常快速地找到完全匹配。

找到近似匹配有点困难:你需要存储低分辨率哈希值,匹配那些,然后计算更大哈希值的汉明距离。

有很多实现,例如dhash是基于ImageMagick的Ruby gem:

https://github.com/maccman/dhash

您还可以比较直方图。它们具有在旋转下不变的优点。