从图像数据库中搜索对象
Searching for objects from database on image
假设我的数据库包含数千张不同形式和大小(小于 100 x 100 像素)的图像,并且保证每张图像只显示一个对象 - 符号、徽标、路标等。我想能够从互联网上获取任何图像 ("my_image.jpg") 并回答问题 "Do my_image contains any object (object can be resized, but without deformations) from my database?" - 假设有 95% 的可靠性。简化 my_images 将有白色背景。
我正在尝试使用 imagehash (https://github.com/JohannesBuchner/imagehash),这将非常有帮助,但为了获得有益的结果,我认为我必须(几乎)计算 my_image 的每个可能的哈希值 - 原因我不知道 my_image:
上的对象大小和位置
hash_list = []
MyImage = Image.open('my_image.jpg')
for x_start in range(image_width):
for y_start in range(image_height):
for x_end in range(x_start, image_width):
for y_end in range(y_start, image_height):
hash_list.append(imagehash.phash(MyImage.\
crop(x_start, y_start, x_end, y_end)))
...然后尝试在数据库中找到类似的散列,但是当例如 image_width = image_height = 500 时,这个循环和搜索将花费很长时间。当然,我可以稍微优化一下,但对于更大的图像,它仍然看起来像切腹:
MIN_WIDTH = 30
MIN_HEIGHT = 30
STEP = 2
hash_list = []
MyImage = Image.open('my_image.jpg')
for x_start in range(0, image_width - MIN_WIDTH, STEP):
for y_start in range(0, image_height - MIN_HEIGHT, STEP):
for x_end in range(x_start + MIN_WIDTH, image_width, STEP):
for y_end in range(y_start + MIN_HEIGHT, image_height, STEP):
hash_list.append(...)
我想知道是否有一些很好的方法来定义 my_image 的哪些部分对计算哈希值有利 - 例如切割边缘看起来不是个好主意。也许有更简单的解决方法?如果程序能在最多 20 分钟内给出答案,那就太好了。如果有任何建议,我将不胜感激。
PS:对不起我的英语:)
对我来说,这看起来像是一个图像检索问题。但是,在您的情况下,您对二进制是/否答案更感兴趣,它告诉您输入图像 (my_image.jpg) 是否属于数据库中存在的对象。
我可以建议的第一件事是,您可以将所有图像(包括输入)的大小调整为固定大小,比如 100 x 100。但是如果某些图像中的对象非常小或存在于特定的图像区域(例如,左上角)然后调整大小会使事情变得更糟。但是,从您的问题中并不清楚这在您的情况下有多大可能。
关于你的第二个问题,找出物体的位置,我想你是在考虑这个,因为你的输入图像尺寸很大,比如 500 x 500?如果是这样,那么调整大小是更好的主意。但是,如果你问这个问题是因为对象定位到图像中的特定区域,那么我认为你可以计算一个梯度图像,这将帮助你如下识别背景区域:因为背景没有变化(完全白色)梯度值将是属于背景区域的像素为零。
与其计算和使用图像哈希,我建议您阅读基于视觉词袋(例如,here)的对象分类方法。虽然您的目标不是对对象进行分类,但它会帮助您想出不同的方法来解决您的问题。
毕竟我找到了对我来说非常好的解决方案,也许它对其他人有用:
我正在使用 SIFT 从 my_image 检测 "best candidates":
def multiscale_template_matching(template, image):
results = []
for scale in np.linspace(0.2, 1.4, 121)[::-1]:
res = imutils.resize(image, width=int(image.shape[1] * scale))
r = image.shape[1] / float(res.shape[1])
if res.shape[0] < template.shape[0] or res.shape[1] < template.shape[1];
break
## bigger correlation <==> better matching
## template_mathing uses SIFT to return best correlation and coordinates
correlation, (x, y) = template_matching(template, res)
coordinates = (x * r, y * r)
results.appent((correlation, coordinates, r))
results.sort(key=itemgetter(0), reverse=True)
return results[:10]
然后我正在计算哈希值的结果:
ACCEPTABLE = 10
def find_best(image, template, candidates):
template_hash = imagehash.phash(template)
best_result = 50 ## initial value must be greater than ACCEPTABLE
best_cand = None
for cand in candidates:
cand_hash = get_hash(...)
hash_diff = template_hash - cand_hash
if hash_diff < best_result:
best_result = hash_diff
best_cand = cand
if best_result <= ACCEPTABLE:
return best_cand, best_result
else:
return None, None
如果结果 < 可接受,我几乎可以肯定答案是 "GOT YOU!" :) 这个解决方案允许我在 7 分钟内将 my_image 与 1000 个对象进行比较。
假设我的数据库包含数千张不同形式和大小(小于 100 x 100 像素)的图像,并且保证每张图像只显示一个对象 - 符号、徽标、路标等。我想能够从互联网上获取任何图像 ("my_image.jpg") 并回答问题 "Do my_image contains any object (object can be resized, but without deformations) from my database?" - 假设有 95% 的可靠性。简化 my_images 将有白色背景。
我正在尝试使用 imagehash (https://github.com/JohannesBuchner/imagehash),这将非常有帮助,但为了获得有益的结果,我认为我必须(几乎)计算 my_image 的每个可能的哈希值 - 原因我不知道 my_image:
上的对象大小和位置hash_list = []
MyImage = Image.open('my_image.jpg')
for x_start in range(image_width):
for y_start in range(image_height):
for x_end in range(x_start, image_width):
for y_end in range(y_start, image_height):
hash_list.append(imagehash.phash(MyImage.\
crop(x_start, y_start, x_end, y_end)))
...然后尝试在数据库中找到类似的散列,但是当例如 image_width = image_height = 500 时,这个循环和搜索将花费很长时间。当然,我可以稍微优化一下,但对于更大的图像,它仍然看起来像切腹:
MIN_WIDTH = 30
MIN_HEIGHT = 30
STEP = 2
hash_list = []
MyImage = Image.open('my_image.jpg')
for x_start in range(0, image_width - MIN_WIDTH, STEP):
for y_start in range(0, image_height - MIN_HEIGHT, STEP):
for x_end in range(x_start + MIN_WIDTH, image_width, STEP):
for y_end in range(y_start + MIN_HEIGHT, image_height, STEP):
hash_list.append(...)
我想知道是否有一些很好的方法来定义 my_image 的哪些部分对计算哈希值有利 - 例如切割边缘看起来不是个好主意。也许有更简单的解决方法?如果程序能在最多 20 分钟内给出答案,那就太好了。如果有任何建议,我将不胜感激。
PS:对不起我的英语:)
对我来说,这看起来像是一个图像检索问题。但是,在您的情况下,您对二进制是/否答案更感兴趣,它告诉您输入图像 (my_image.jpg) 是否属于数据库中存在的对象。
我可以建议的第一件事是,您可以将所有图像(包括输入)的大小调整为固定大小,比如 100 x 100。但是如果某些图像中的对象非常小或存在于特定的图像区域(例如,左上角)然后调整大小会使事情变得更糟。但是,从您的问题中并不清楚这在您的情况下有多大可能。
关于你的第二个问题,找出物体的位置,我想你是在考虑这个,因为你的输入图像尺寸很大,比如 500 x 500?如果是这样,那么调整大小是更好的主意。但是,如果你问这个问题是因为对象定位到图像中的特定区域,那么我认为你可以计算一个梯度图像,这将帮助你如下识别背景区域:因为背景没有变化(完全白色)梯度值将是属于背景区域的像素为零。
与其计算和使用图像哈希,我建议您阅读基于视觉词袋(例如,here)的对象分类方法。虽然您的目标不是对对象进行分类,但它会帮助您想出不同的方法来解决您的问题。
毕竟我找到了对我来说非常好的解决方案,也许它对其他人有用:
我正在使用 SIFT 从 my_image 检测 "best candidates":
def multiscale_template_matching(template, image):
results = []
for scale in np.linspace(0.2, 1.4, 121)[::-1]:
res = imutils.resize(image, width=int(image.shape[1] * scale))
r = image.shape[1] / float(res.shape[1])
if res.shape[0] < template.shape[0] or res.shape[1] < template.shape[1];
break
## bigger correlation <==> better matching
## template_mathing uses SIFT to return best correlation and coordinates
correlation, (x, y) = template_matching(template, res)
coordinates = (x * r, y * r)
results.appent((correlation, coordinates, r))
results.sort(key=itemgetter(0), reverse=True)
return results[:10]
然后我正在计算哈希值的结果:
ACCEPTABLE = 10
def find_best(image, template, candidates):
template_hash = imagehash.phash(template)
best_result = 50 ## initial value must be greater than ACCEPTABLE
best_cand = None
for cand in candidates:
cand_hash = get_hash(...)
hash_diff = template_hash - cand_hash
if hash_diff < best_result:
best_result = hash_diff
best_cand = cand
if best_result <= ACCEPTABLE:
return best_cand, best_result
else:
return None, None
如果结果 < 可接受,我几乎可以肯定答案是 "GOT YOU!" :) 这个解决方案允许我在 7 分钟内将 my_image 与 1000 个对象进行比较。