Как использовать NumPy для сравнения нескольких массивов и определения минимальных различий? - PullRequest
0 голосов
/ 29 ноября 2011

У меня есть набор массивов (20x40) со значениями от 0 до 255 (изображения в оттенках серого).

Мне нужно сравнить данный массив с набором из 10 других, которые используются в качестве ссылки, и выбрать тот, который ближе всего к данному изображению.

Я знаю, что это выглядит как OCR, но в этом случае OCR не может ничего хорошего.

Я уже пытался вычислить abs(x-y), но результаты были недостаточно хорошими.

Захват:

real

Справка:

reference

Ответы [ 2 ]

1 голос
/ 08 августа 2012

Я решал аналогичную проблему на bskyb с OCRing кадрами, взятыми из видеопотока.

В итоге я создал словарь координат для каждой цифры в изображении (x,y, w, h) и написал скрипт, который генерировалсотни этих цифр и сохранили их как маски.Затем один из тестировщиков выбрал лучшие маски (наименее искаженные) и сохранил их как 1.bmp для цифры 1, 2.bmb для цифры 2 ...

Нам нужно было создать 18 разных изображений для каждойцифра для поддержки различных разрешений, у нас есть aspect_ratios.Затем эти маски были загружены в словарь в начале процесса распознавания.Мы сохранили изображения в виде массива.

def load_samples(parent_dir=r'c:\masks'):
"""Loads the OCR samples of all digits of all possible variations into
memory.
"""
m = dict() # m is our map, a dict of lists of numpy arrays
for d in os.listdir(parent_dir):
    if not os.path.isdir(os.path.join(parent_dir, d)):
        continue
    m[d] = []
    for i in range(10): # 10 images [0..9]
        filename = os.path.join(parent_dir, d, '%d.bmp'%i)
        m[d].append(imread(filename))
return m 

Затем для каждого считываемого изображения мы делим его на цифры путем преобразования цифры в массив с нулями и сравнения ее со всеми масками, которые мы должны найти.ближайшее совпадение и выберите его на основе этого.digits_map - это то, что возвращается из описанных выше примеров загрузки.

def image2digit(image, digits_map, video_args):
"""Our home made OCR, we compare each image of digit with 10 images of all
possible digits [0..10] and return the closest match.
"""
def absdiff(img1, img2):
    func = numpy.vectorize(lambda a, b: abs(int(a)-int(b)))
    v = func(img1, img2)
    w = coordinates[video_args]['w']
    h = coordinates[video_args]['h']
    return numpy.sum(v)/(w*h) # takes the average

# convert the image to a numpy array
image_array = fromimage(image) # from scipy.misc
# compare it with all variations
scores = []
for (i, ir) in enumerate(digits_map[video_args]):
    scores.append(absdiff(ir, image_array))
# return the best match as a string
index = numpy.argmin(scores)
return str(index)

Это хорошо сработало для нас, за исключением некоторых искаженных кадров, где 6 обозначено как 5. Я экспериментирую с преобразованием изображений в шкалу серого перед сравнениемчтобы увидеть, помогает ли это с проблемой искаженных изображений.

0 голосов
/ 30 ноября 2011

Просто умножьте пиксели вместе, а затем возьмите сумму всех пикселей:

  • ((0,0) изображения 1 * (0,0) изображения 2) + ((0,1) изображения 1 * (0,1) изображения 2) + ...

Это похоже на взаимную корреляцию без смещения. ( scipy.signal.correlate )

Команда в numpy будет просто

sum(a * b)

Возможно, есть имя для этого, но я не знаю, что это такое.

Полагаю, вы будете сравнивать контрольные цифры одну за другой с измеренным изображением, чтобы увидеть, какая это цифра?

Вы должны сначала сравнить контрольные цифры с самими собой, чтобы выяснить, как выглядит идеальное совпадение, и нормализовать каждую из них, чтобы получить сходство. Несовершенное совпадение будет иметь значение меньше этого. Например:

0 1 3
1 2 3
2 0 0

будет производить 28 по сравнению с самим собой, но будет производить 25 по сравнению с

0 1 3
0 2 3
1 0 0

Таким образом, ваш матч будет 25/28 = 0,89. Итак, вы знаете, что второе изображение близко, но не то же самое

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...