在图像上搜索数据库中的对象

时间:2017-08-11 10:09:16

标签: image-processing computer-vision image-recognition pattern-recognition

假设我拥有数千个具有不同形式和大小(小于100 x 100px)的图像的数据库,并且保证每个图像只显示一个对象 - 符号,徽标,道路标志等。我想成为能够从互联网上获取任何图像(“my_image.jpg”)并回答问题“我的数据库中是否包含任何对象(对象可以调整大小,但没有变形)?” - 让我们说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时,这种循环和搜索将需要很长时间。当然,我可以稍微优化一下,但对于更大的图像,它仍然看起来像seppuku:

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:对不起我的英语:)

2 个答案:

答案 0 :(得分:1)

这看起来像是我的图像检索问题。但是,在您的情况下,您更感兴趣的是二进制YES / NO答案,它告诉输入图像(my_image.jpg)是否是数据库中存在的对象。

我可以建议的第一件事是你可以将所有图像(包括输入)的大小调整为固定大小,比如说100 x 100.但是如果某个图像中的某个对象非常小或存在于特定区域图像(例如,左上角)然后调整大小会使事情变得更糟。但是,从你的问题中不清楚这种情况有多大。

关于你找到对象位置的第二个问题,我认为你正在考虑这个,因为你的输入图像是大尺寸的,比如500 x 500?如果是这样,那么调整大小是更好的主意。但是,如果您问这个问题是因为对象局部定位到图像中的特定区域,那么我认为您可以计算出一个渐变图像,它将帮助您识别背景区域,如下所示:因为背景没有变化(完全白色),所以渐变值将是属于背景区域的像素为零。

我建议您阅读有关对象分类的基于视觉词袋(例如here)的方法,而不是计算和使用图像哈希。虽然您的目标不是对对象进行分类,但它会帮助您提出一种不同的方法来解决您的问题。

答案 1 :(得分:0)

毕竟我找到了对我来说非常好的解决方案,也许对其他人有用:

我使用SIFT来检测"最佳候选人"来自my_image:

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

如果结果&lt;接受,我几乎可以肯定答案是#34; GOT YOU!&#34; :)这个解决方案允许我在7分钟内将my_image与1000个对象进行比较。