Матч 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
расстояние. Ошибка всплывет.
Любая помощь буду признателен.
два изображения, которые я использовал для этого:
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")
-
создания объекта 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)
-
во время захвата и обработки кадры
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)