Матч BFMatcher в ошибке метания OpenCV

Я использую дескрипторы SURF для сопоставления изображений. Я планирую сопоставить данное изображение с базой данных изображений.

import cv2
import numpy as np
surf = cv2.xfeatures2d.SURF_create(400)

img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)

kp1,des1 = surf.detectAndCompute(img1,None)
kp2,des2 = surf.detectAndCompute(img2,None)


bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=True)
#I am planning to add more descriptors
bf.add(des1)

bf.train()

#This is my test descriptor
bf.match(des2)

ошибка bf.match это то, что я получаю следующую ошибку:

OpenCV Error: Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) in batchDistance, file /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp, line 3749
Traceback (most recent call last):
  File "image_match4.py", line 16, in <module>
    bf.match(des2)
cv2.error: /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp:3749: error: (-215) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function batchDistance

ошибка похожа на этой пост. Данное объяснение является неполным и неадекватным.Я хочу знать, как решить эту проблему. Я также использовал дескрипторы ORB с bfmatcher, имеющим NORM_HAMMING расстояние. Ошибка всплывет. Любая помощь буду признателен.

два изображения, которые я использовал для этого:

box.png

4 ответов


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

img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)

kp1,des1 = surf.detectAndCompute(img1,None)
kp2,des2 = surf.detectAndCompute(img2,None)


bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False)
matches = bf.match(des1,des2)

для поиска среди нескольких изображений

на add метод используется для добавления дескриптора нескольких тестовых изображений. Как только все дескрипторы индексируются, вы запускаете train метод построения базовой структуры данных (пример: KdTree, который будет использоваться для поиска в случае FlannBasedMatcher). Затем вы можете запустить match чтобы узнать, какое тестовое изображение ближе к которому запрос изображения. Вы можете проверить K-d_tree и посмотреть, как его можно использовать для поиска многомерных векторов(Surf дает 64-мерный вектор).

Примечание: BruteForceMatcher, как следует из названия, не имеет внутренней поисковой оптимизации структуры данных и, следовательно, имеет пустой метод поезда.

образец кода для множественного поиска изображений

import cv2
import numpy as np
surf = cv2.xfeatures2d.SURF_create(400)

# Read Images
train = cv2.imread('box.png',0)
test = cv2.imread('box_in_scene.png',0)

# Find Descriptors    
kp1,trainDes1 = surf.detectAndCompute(train, None)
kp2,testDes2  = surf.detectAndCompute(test, None)

# Create BFMatcher and add cluster of training images. One for now.
bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False) # crossCheck not supported by BFMatcher
clusters = np.array([trainDes1])
bf.add(clusters)

# Train: Does nothing for BruteForceMatcher though.
bf.train()

matches = bf.match(testDes2)
matches = sorted(matches, key = lambda x:x.distance)

# Since, we have index of only one training image, 
# all matches will have imgIdx set to 0.
for i in range(len(matches)):
    print matches[i].imgIdx

для выхода DMatch bf.матч, смотрите docs.

посмотреть полный пример здесь: Opencv3.0 docs.

Дополнительная Информация

OS: Mac.
Python: 2.7.10.
Opencv: 3.0.0-dev [если помните правильно, установлен с помощью brew].


я обнаружил, что получаю ту же ошибку. Потребовалось некоторое время, чтобы понять - некоторые из моих изображений были несколько невыразительными, поэтому никаких ключевых точек не было найдено, и detectAndCompute вернулся None для дескрипторов. Возможно, стоит проверить список дескрипторов для None элементы перед переходом в BFMatcher.add().


я получал ту же ошибку. Но в моем случае это было потому, что я использовал SIFT с cv2.NORM_HAMMING метрика в cv2.BFMatcher_create. Изменение метрики на cv2.NORM_L1 решается вопрос.

со ссылкой на документы за BFMatcher:

normType – один из NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 и L2 нормы являются предпочтительными вариантами для дескрипторов SIFT и SURF, NORM_HAMMING следует использовать с ORB, BRISK и BRIEF,NORM_HAMMING2 следует использовать с ОРБ, когда WTA_K==3 или 4 (см. ORB::ORB конструктор описание.)


Edit: версии, используемые Python 3.6, OpenCV 3.4.1

Я много боролся при подготовке программы, которая использует просеять или шар в зависимости от выбора пользователя. Наконец, я смог найти правильные параметры для BFMatcher на просеять и шар

import cv2
import numpy as np

# ask user whether to use SIFT or ORB
detect_by = input("sift or orb")
  1. создания объекта matcher и

    if detect_by == "sift":
        matcher = cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=False)
    
    elif detect_by is "orb":
        matcher = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=False)
    
  2. во время захвата и обработки кадры

    while there_is_frame_to_process:
        if detect_by is "sift":
            matches = matcher.knnMatch(np.asarray(gray_des, np.float32), np.asarray(target_des, np.float32), k=2)
    
        elif detect_by is "orb":
            matches = matcher.knnMatch(np.asarray(gray_des, np.uint8), np.asarray(target_des, np.uint8), k=2)