将图像与列表Python进行比较

2024-09-27 00:21:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在与一个程序斗争,我读过很多关于在python中使用图像的信息,但我没有得到我的程序工作。在

我正在做一个识别卡片的程序。我有一个所有卡片的“数据库”,每个卡片都在不同的jpg文件中。所以我们试着把我们想知道的卡片和所有可能的卡片进行比较。那么更相似的卡片就是我要找的卡片。我试过几种不同的代码,但没有人能正确地完成他的工作。在

def get_card(image1path):
    from PIL import Image
    import math
    import os
    import operator
    __docstring__ = "compare two image files"
    h1 = Image.open(image1path).resize((40,55)).histogram()
    best=99999999
    for root,dirs,files in os.walk("cards"):
        for file in [f for f in files]:
            list=(os.path.join(root, file))
            h2 = Image.open(list).resize((40,55)).histogram()
            rms = math.sqrt(reduce(operator.add, map(lambda a,b: (a-b)**2, h1, h2))/len(h1))
            print "RMS = "+str(rms)+"  and the picture is:"+list
            if rms<best:
                best=rms
                card=(os.path.join(file)).split(".")[0]

    return card

image1path="C:\\8d.jpg" #eight of diamonds.
card=get_card(image1path)
print card

问题是它不能正常工作,因为在比较了每张卡的RMS值与所有的RMS值后,有一些错误的卡得到了最好的RMS标点。所以识别卡不是钻石的八分之一。在

我该怎么做??如果你需要的话,我用别的话来解释,就说出来。在

非常感谢


Tags: inimageimport程序forosfilescard
1条回答
网友
1楼 · 发布于 2024-09-27 00:21:57

通过查看正在比较的图像,您实际上不希望使用RMSE等度量。原因是因为所有的图像在“RMSE意义上”是相似的,或者甚至对于更精细的度量,这些度量并不关心图像中存在的基本关系。以下是你自己举的一些例子:

enter image description hereenter image description hereenter image description hereenter image description hereenter image description here

在你的例子中,基本的关系是:颜色(也可以区分黑桃、红桃、钻石和梅花牌)和形状度量。所以,通过检测卡片的颜色,搜索空间就减少了,剩下的就是辨别卡片顶部的数字了。加上连接元件的数量和欧拉数,搜索进一步受到限制。现在剩下的是区分:“9”和“6”、“4”、大号或“A”;“3”和“J”、“2”、“5”或“7”;“8”和“10”被解决,前者是由于欧拉数,后者是由于其连接的组件的数量(这一切都假设卡是唯一的,否则你继续寻找最相似的卡)。这里要做的最简单的事情是计算每个剩余形状之间的Hausdorff距离,如果您在问题中添加更多的考虑,则可能会失败。在

这里是一个简单化的实现,它考虑了这些点并适用于所有给定的输入。它需要一个图像和一个目录来查找要比较的图像。每一步都可以改进。在

import sys
import numpy
from scipy.ndimage import morphology, label, find_objects
from PIL import Image

COLORS = range(4)
RED, GREEN, BLUE, BLACK = COLORS

def card_color(img):
    im = img.load()
    width, height = img.size
    black, blue, green, red = 0, 0, 0, 0
    for x in xrange(width):
        for y in xrange(height):
            r, g, b = im[x, y]
            if r > 200 and g > 200 and b > 200:
                # "white", ignore
                continue

            if r > 200 and g < 100 and b < 100:
                red += 1
            elif r < 100 and g < 100 and b > 200:
                blue += 1
            elif r < 50 and g < 50 and b < 50:
                black += 1
            elif r < 100 and g > 120 and b < 50: # dark green
                green += 1
    return max(zip((black, blue, green, red), COLORS))

def euler_number(img, conn=4):
    im = img.load()
    width, height = img.size

    c1, c2, c3 = 0, 0, 0
    for x in xrange(width - 1):
        for y in xrange(height - 1):
            s = (im[x,y] + im[x+1,y] + im[x,y+1] + im[x+1,y+1]) / 255
            if s == 1:
                c1 += 1
            elif s == 2:
                if (im[x+1,y] and im[x,y+1]) or (im[x,y] and im[x+1,y+1]):
                    c3 += 1
            elif s == 3:
                c2 += 1
    if conn == 4:
        return (c1 - c2 + 2 * c3) / 4
    else: # 8
        return (c1 - c2 - 2 * c3) / 4

def carefully_binarize(img, color):
    if color == BLACK:
        img = img.convert('L')
    else:
        img = img.split()[color]
    width, height = img.size
    im = numpy.empty((height + 2, width + 2), dtype=numpy.uint8) # Padding
    im.fill(255)
    im[1:-1, 1:-1] = numpy.array(img)
    threshold = im.mean() - im.std()
    im[im <= threshold] = 1
    im[im > threshold] = 0
    # Discard small components.
    lbl, ncc = label(im)
    for i in xrange(1, ncc + 1):
        py, px = numpy.nonzero(lbl == i)
        if len(py) < 30:
            im[lbl == i] = 0
    return Image.fromarray(im * 255)

def discard_bottom(img, k=0.5):
    width, height = img.size
    im = numpy.array(img)
    limit = height * k
    lbl, ncc = label(im)
    for i, oslice in enumerate(find_objects(lbl)):
        srow, scol = oslice
        if srow.stop > limit:
            ncc -= 1
            im[srow.start:srow.stop, scol.start:scol.stop] = 0
    return Image.fromarray(im), ncc

def signature(img):
    # Assumption: a single connected component is present now.
    im = numpy.array(img)
    im = morphology.binary_fill_holes(im)
    im = morphology.binary_dilation(im) - im

    py, px = numpy.nonzero(im)
    return Image.fromarray(im.astype(numpy.uint8)*255), zip(py, px)

def hausdorff(a, b):
    dist = 0
    for ai in a:
        mindist = float('inf')
        for bi in b:
            chess = max(abs(ai[0]-bi[0]), abs(ai[1]-bi[1]))
            if chess < mindist:
                mindist = chess
        if mindist > dist:
            dist = mindist
    return dist

img1 = Image.open(sys.argv[1]).convert('RGB')
dirpath = sys.argv[2]

img1_color = card_color(img1)[1]
img1 = carefully_binarize(img1, img1_color)
img1_top, img1_top_ncc = discard_bottom(img1)
img1_top_en = euler_number(img1_top)

feature = [img1_color, img1_top_ncc, img1_top_en]

match = []
for fname in os.listdir(dirpath):
    try:
        img2 = Image.open(os.path.join(dirpath, fname)).convert('RGB')
    except IOError:
        print "Ignoring", fname
        continue

    if card_color(img2)[1] != feature[0]:
        continue

    img2 = carefully_binarize(img2, feature[0])
    img2_top, ncc = discard_bottom(img2)
    if ncc != feature[1]:
        continue
    en = euler_number(img2_top)
    if en != feature[2]:
        continue

    match.append((img2_top, os.path.join(dirpath, fname)))

if len(match) == 1:
    print "Here is your best match:", match[0][1]
else:
    img1_sig, sig1 = signature(img1_top)
    best_match = float('inf'), None
    for img2, fname in match:
        img2_sig, sig2 = signature(img2)
        dist = hausdorff(sig1, sig2)
        if dist < best_match[0]:
            best_match = dist, fname

    print "Best match:", best_match[1]

相关问题 更多 >

    热门问题