Python OpenCV matchTemplate с маскированием - найденные совпадения во всех местах - PullRequest
1 голос
/ 03 июля 2019

Проблема: Результаты, которые я получаю от matchTemplate, указывают, что у меня есть совпадения в каждом местоположении со значением 1.0.

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

Код:

def template_match(filename=base_name,
                   img_folder=trn_imgs_path,
                   templates=['wet_install.png',
                              'wet_install_cleaned.png',
                              'wet_install_tag.png',
                              'wet_install_tag_cleaned.png'],
                   template_path=template_path,
                   threshold=0.8,
                   save_dir=save_dir):
    ''' 
    Perform template matching on an input image using a few templates.
    It draws bounding boxes on a copy of the original image. 

    Args:
        filename (str): name of the file with the .svg extension
        img_folder (str): path to folder containing the images
        templates (list): list of template filenames to match against
        template_path (str): path to folder containing the templates
        threshold (float): the threshold for a match from template matching
        save_dir (str): path to folder to save results
    '''
    print('Working on file: {}.png'.format(filename))

    # load the original BGR image
    img_rgb  = cv2.imread(img_folder + filename + '.png')[5143:5296, 15169:15368] # TODO(mtu): Don't keep these indices here!
    img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
    img_gray = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 115, 1)

    # loop over each template
    colors = [(0,0,255), (0,255,0), (255,255,0), (255,0,255)]
    for itemp in range(len(templates)):
        template_name = templates[itemp]
        print('Using Template: {}'.format(template_name))

        # load the template as grayscale and get its width and height
        template = cv2.imread(template_path + '{}'.format(template_name), 0)
        height, width = template.shape[:2]

        template  = cv2.adaptiveThreshold(template, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 115, 1)
        temp_mask = cv2.adaptiveThreshold(template, 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 115, 1)

        # do template matching using grayscale image and find points above theshold
        results = cv2.matchTemplate(image=img_gray, templ=template, method=cv2.TM_CCORR_NORMED, mask=temp_mask)
        loc = np.where(results >= threshold)

        # draw rectangles on points above threshold on RGB image
        for pt in zip(*loc[::-1]):
            cv2.rectangle(img_rgb, pt, (pt[0] + width, pt[1] + height), colors[itemp%len(colors)], 5)

    # save the file with bounding boxes drawn on
    filename = save_dir + '{}_found.png'.format(filename) 
    print('Saving bounding boxes to: {}'.format(filename))
    cv2.imwrite(filename, img_rgb)

Комментарии:

1 Ответ

0 голосов
/ 04 июля 2019

Инвертирование img_gray и template исправило ошибку.

Метрика сравнения, которую я использовал, была cv2.TM_CCORR_NORMED. Это работает, беря скалярное произведение img_gray и template, где двоичный массив NumPy temp_mask имеет значение 1.

В моем образце изображения я хотел сопоставить черные пиксели в template с черными пикселями в img_gray, однако значение пикселя для черного составляет 0. Таким образом, точечное произведение в месте, которое я хотел обнаружить, было низким.

Инвертируя img_gray и template, я сопоставляю белые пиксели в template с белыми пикселями в img_gray. Так как у белого есть значение пикселя 255, точечное произведение белого на белый, шаблон на изображение, становится высоким в месте, которое я хочу обнаружить.

...