2012-06-20 7 views
8

Я пытаюсь использовать opencv с python. Я написал код описания дескриптора (SIFT, SURF или ORB) в версии на C++ opencv 2.4. Я хочу преобразовать этот код в opencv с помощью python. Я нашел несколько документов о том, как использовать opencv-функции в C++, но многие из opencv-функции в python я не мог найти, как их использовать. Вот мой код python, и моя текущая проблема в том, что я не знаю, как использовать «drawMatches» opencv C++ в python. Я нашел cv2.DRAW_MATCHES_FLAGS_DEFAULT, но я понятия не имею, как его использовать. Вот мой питон код совпадающих с помощью ORB дескрипторов:Как визуализировать сопоставление дескрипторов с использованием opencv-модуля в python

im1 = cv2.imread(r'C:\boldt.jpg') 
im2 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY) 
im3 = cv2.imread(r'C:\boldt_resize50.jpg') 
im4 = cv2.cvtColor(im3, cv2.COLOR_BGR2GRAY) 

orbDetector2 = cv2.FeatureDetector_create("ORB") 
orbDescriptorExtractor2 = cv2.DescriptorExtractor_create("ORB") 
orbDetector4 = cv2.FeatureDetector_create("ORB") 
orbDescriptorExtractor4 = cv2.DescriptorExtractor_create("ORB") 

keypoints2 = orbDetector2.detect(im2) 
(keypoints2, descriptors2) = orbDescriptorExtractor2.compute(im2,keypoints2) 
keypoints4 = orbDetector4.detect(im4) 
(keypoints4, descriptors4) = orbDescriptorExtractor4.compute(im4,keypoints4) 
matcher = cv2.DescriptorMatcher_create('BruteForce-Hamming') 
raw_matches = matcher.match(descriptors2, descriptors4) 
img_matches = cv2.DRAW_MATCHES_FLAGS_DEFAULT(im2, keypoints2, im4, keypoints4, raw_matches) 
cv2.namedWindow("Match") 
cv2.imshow("Match", img_matches); 

Сообщение об ошибке в строке "img_matches = cv2.DRAW_MATCHES_FLAGS_DEFAULT (im2, keypoints2, IM4, keypoints4, raw_matches)"

Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: 'long' object is not callable 

я провел много времени поисковой документации и примеры использования opencv-функций с python. Тем не менее, я очень расстроен, потому что очень мало информации об использовании opencv-функций в python. Это будет очень полезно, если кто-нибудь сможет научить меня, где я могу найти документацию о том, как использовать каждую функцию opencv-модуля в python. Я ценю ваше время и помощь.

ответ

2

Как говорится в сообщении об ошибке, DRAW_MATCHES_FLAGS_DEFAULT имеет тип «long». Это константа, определяемая модулем cv2, а не функцией. К сожалению, функция, которую вы хотите, 'drawMatches' существует только в интерфейсе C++ OpenCV.

+0

Спасибо за ответ !! – user1433201

14

Вы можете визуализировать соответствие функций в Python следующим образом. Обратите внимание на использование библиотеки scipy.

# matching features of two images 
import cv2 
import sys 
import scipy as sp 

if len(sys.argv) < 3: 
    print 'usage: %s img1 img2' % sys.argv[0] 
    sys.exit(1) 

img1_path = sys.argv[1] 
img2_path = sys.argv[2] 

img1 = cv2.imread(img1_path, cv2.CV_LOAD_IMAGE_GRAYSCALE) 
img2 = cv2.imread(img2_path, cv2.CV_LOAD_IMAGE_GRAYSCALE) 

detector = cv2.FeatureDetector_create("SURF") 
descriptor = cv2.DescriptorExtractor_create("BRIEF") 
matcher = cv2.DescriptorMatcher_create("BruteForce-Hamming") 

# detect keypoints 
kp1 = detector.detect(img1) 
kp2 = detector.detect(img2) 

print '#keypoints in image1: %d, image2: %d' % (len(kp1), len(kp2)) 

# descriptors 
k1, d1 = descriptor.compute(img1, kp1) 
k2, d2 = descriptor.compute(img2, kp2) 

print '#keypoints in image1: %d, image2: %d' % (len(d1), len(d2)) 

# match the keypoints 
matches = matcher.match(d1, d2) 

# visualize the matches 
print '#matches:', len(matches) 
dist = [m.distance for m in matches] 

print 'distance: min: %.3f' % min(dist) 
print 'distance: mean: %.3f' % (sum(dist)/len(dist)) 
print 'distance: max: %.3f' % max(dist) 

# threshold: half the mean 
thres_dist = (sum(dist)/len(dist)) * 0.5 

# keep only the reasonable matches 
sel_matches = [m for m in matches if m.distance < thres_dist] 

print '#selected matches:', len(sel_matches) 

# ##################################### 
# visualization of the matches 
h1, w1 = img1.shape[:2] 
h2, w2 = img2.shape[:2] 
view = sp.zeros((max(h1, h2), w1 + w2, 3), sp.uint8) 
view[:h1, :w1, :] = img1 
view[:h2, w1:, :] = img2 
view[:, :, 1] = view[:, :, 0] 
view[:, :, 2] = view[:, :, 0] 

for m in sel_matches: 
    # draw the keypoints 
    # print m.queryIdx, m.trainIdx, m.distance 
    color = tuple([sp.random.randint(0, 255) for _ in xrange(3)]) 
    cv2.line(view, (int(k1[m.queryIdx].pt[0]), int(k1[m.queryIdx].pt[1])) , (int(k2[m.trainIdx].pt[0] + w1), int(k2[m.trainIdx].pt[1])), color) 


cv2.imshow("view", view) 
cv2.waitKey() 
+0

При запуске кода я получаю сообщение об ошибке в строке 66, '' 'TypeError: целочисленный аргумент, ожидаемый, получил float''' – gilbertbw

+0

@ wall-e анонимный пользователь только что отредактировал ваше сообщение, возможно, захочет проверить, что он его не сломал – OGHaza

+0

view [: h1,: w1,:] = img1 ValueError: не удалось передать входной массив из формы (322,518) в форму (322,518,3) – Giuseppe

9

Я также написал что-то себе, что просто использует интерфейс OpenCV Python, и я не использовал scipy. drawMatches является частью OpenCV 3.0.0 и не является частью OpenCV 2, что я и сейчас использую. Несмотря на то, что я опаздываю на вечеринку, вот моя собственная реализация, которая изо всех сил имитирует drawMatches.

Я представил свои собственные изображения, где один из людей камеры, а другой - одно и то же изображение, но повернут на 55 градусов против часовой стрелки.

Основная предпосылка того, что я написал, заключается в том, что я выделяю выходное изображение RGB, где количество строк является максимальным из двух изображений для размещения обоих изображений на выходном изображении, а столбцы - просто суммирование обоих столбцов вместе. Я помещаю каждое изображение в их соответствующие пятна, а затем пробегаю по петле всех совпадающих ключевых точек. Я извлекаю, какие ключевые точки совпадают между двумя изображениями, затем извлекают их координаты (x,y). Затем я рисую круги в каждом из обнаруженных мест, затем нарисую линию, соединяющую эти круги вместе.

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

Без дальнейших церемоний:

import numpy as np 
import cv2 

def drawMatches(img1, kp1, img2, kp2, matches): 
    """ 
    My own implementation of cv2.drawMatches as OpenCV 2.4.9 
    does not have this function available but it's supported in 
    OpenCV 3.0.0 

    This function takes in two images with their associated 
    keypoints, as well as a list of DMatch data structure (matches) 
    that contains which keypoints matched in which images. 

    An image will be produced where a montage is shown with 
    the first image followed by the second image beside it. 

    Keypoints are delineated with circles, while lines are connected 
    between matching keypoints. 

    img1,img2 - Grayscale images 
    kp1,kp2 - Detected list of keypoints through any of the OpenCV keypoint 
       detection algorithms 
    matches - A list of matches of corresponding keypoints through any 
       OpenCV keypoint matching algorithm 
    """ 

    # Create a new output image that concatenates the two images together 
    # (a.k.a) a montage 
    rows1 = img1.shape[0] 
    cols1 = img1.shape[1] 
    rows2 = img2.shape[0] 
    cols2 = img2.shape[1] 

    out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8') 

    # Place the first image to the left 
    out[:rows1,:cols1,:] = np.dstack([img1, img1, img1]) 

    # Place the next image to the right of it 
    out[:rows2,cols1:cols1+cols2,:] = np.dstack([img2, img2, img2]) 

    # For each pair of points we have between both images 
    # draw circles, then connect a line between them 
    for mat in matches: 

     # Get the matching keypoints for each of the images 
     img1_idx = mat.queryIdx 
     img2_idx = mat.trainIdx 

     # x - columns 
     # y - rows 
     (x1,y1) = kp1[img1_idx].pt 
     (x2,y2) = kp2[img2_idx].pt 

     # Draw a small circle at both co-ordinates 
     # radius 4 
     # colour blue 
     # thickness = 1 
     cv2.circle(out, (int(x1),int(y1)), 4, (255, 0, 0), 1) 
     cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (255, 0, 0), 1) 

     # Draw a line in between the two points 
     # thickness = 1 
     # colour blue 
     cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (255, 0, 0), 1) 


    # Show the image 
    cv2.imshow('Matched Features', out) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows() 

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

enter image description here

enter image description here

Я использовал OpenCV-х Детектор ORB для обнаружения ключевых точек, и использовал нормированное расстояние Хэмминга как меру расстояния для сходства, так как это двоичный дескриптор. Таким образом:

import numpy as np 
import cv2 

img1 = cv2.imread('cameraman.png') # Original image 
img2 = cv2.imread('cameraman_rot55.png') # Rotated image 

# Create ORB detector with 1000 keypoints with a scaling pyramid factor 
# of 1.2 
orb = cv2.ORB(1000, 1.2) 

# Detect keypoints of original image 
(kp1,des1) = orb.detectAndCompute(img1, None) 

# Detect keypoints of rotated image 
(kp2,des2) = orb.detectAndCompute(img2, None) 

# Create matcher 
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) 

# Do matching 
matches = bf.match(des1,des2) 

# Sort the matches based on distance. Least distance 
# is better 
matches = sorted(matches, key=lambda val: val.distance) 

# Show only the top 10 matches 
drawMatches(img1, kp1, img2, kp2, matches[:10]) 

Это изображение я получаю:

enter image description here

+0

Hii @rayryeng Когда я пытаюсь запустить код выше, я получаю Traceback (последний последний звонок) : Файл «orb1.py», строка 33, в out [: rows1,: cols1 ,:] = np.dstack ([img1, img1, img1]) ValueError: не удалось передать входной массив из формы (900 , 1440,9) в форму (900,1440,3) –

+2

@BhushanPatil - внимательно прочитайте docstring функции ** **. Для этого требуются изображения в оттенках серого. Вы используете ** RGB ** изображения. Перед использованием функции вам необходимо преобразовать изображения в оттенки серого. Простой вызов 'cv2.cvtColor' должен быть достаточным:' img = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY) 'будет работать. Пожалуйста, сначала прочитайте документацию функции перед ее использованием в следующий раз. Это стандартный навык, который разработчики должны изучать при использовании чужого кода. – rayryeng