2012-06-20 8 views
8

Ich versuche, opencv mit Python zu verwenden. Ich schrieb einen Deskriptor (SIFT, SURF oder ORB) passender Code in C++ Version von opencv 2.4. Ich möchte diesen Code mit Python in opencv konvertieren. Ich habe einige Dokumente darüber gefunden, wie opencv-Funktionen in C++ zu verwenden sind, aber viele der opencv-Funktionen in Python konnte ich nicht finden, wie man sie benutzt. Hier ist mein Python-Code, und mein aktuelles Problem ist, dass ich nicht weiß, wie man "drawMatches" von opencv C++ in Python verwendet. Ich habe cv2.DRAW_MATCHES_FLAGS_DEFAULT gefunden, aber ich weiß nicht, wie ich es benutzen soll. Hier ist mein Python-Code passender mit ORB-Deskriptoren:Wie zu visualisieren, Deskriptor mit OpenCV-Modul in 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); 

Fehlermeldung der Zeile "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 

Ich verbrachte viel Zeit suchen Dokumentation und Beispiele für die Verwendung von opencv-Funktionen mit Python. Ich bin jedoch sehr frustriert, da es sehr wenig Informationen über die Verwendung von opencv-Funktionen in Python gibt. Es wird sehr hilfreich sein, wenn mir jemand beibringen kann, wo ich die Dokumentation finde, wie man jede Funktion des opencv-Moduls in Python benutzt. Ich schätze deine Zeit und Hilfe.

Antwort

2

Wie die Fehlermeldung sagt, ist DRAW_MATCHES_FLAGS_DEFAULT vom Typ 'lang'. Es ist eine durch das cv2-Modul definierte Konstante, keine Funktion. Unglücklicherweise existiert die gewünschte Funktion 'drawMatches' nur in der C++ - Schnittstelle von OpenCV.

+0

Vielen Dank für Ihre Antwort !! – user1433201

14

können Sie die Feature-Übereinstimmung in Python wie folgt visualisieren. Beachten Sie die Verwendung von SCIPY-Bibliothek.

# 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

Beim Ausführen Ihres Codes bekomme ich einen Fehler in Zeile 66, '' 'TypeError: Integer-Argument erwartet, bekam float''' – gilbertbw

+0

@ wall-e ein anonymer Benutzer hat gerade Ihren Beitrag bearbeitet, könnte prüfen, ob er nicht kaputt ist – OGHaza

+0

view [: h1,: w1,:] = img1 ValueError: konnte kein Array von Shape (322,518) in Shape senden (322,518,3) – Giuseppe

9

ich auch selbst etwas geschrieben habe, dass nur die OpenCV Python-Schnittstelle verwendet und ich habe nicht scipy verwenden. drawMatches ist Teil von OpenCV 3.0.0 und ist nicht Teil von OpenCV 2, was ich gerade verwende. Auch wenn ich zu spät zur Party komme, hier ist meine eigene Implementierung, die drawMatches nach besten Kräften nachahmt.

Ich habe meine eigenen Bilder zur Verfügung gestellt, wo man von einem Kameramann ist, und der andere ist das gleiche Bild, aber um 55 Grad gegen den Uhrzeigersinn gedreht. Die Grundvoraussetzung dessen, was ich geschrieben habe, ist, dass ich ein RGB-Ausgabebild zuteile, wobei die Anzahl der Zeilen das Maximum der beiden Bilder ist, um beide Bilder in das Ausgabebild zu bringen und die Spalten sind einfach die Summe von beiden Spalten zusammen. Ich platziere jedes Bild an den entsprechenden Stellen und führe dann eine Schleife mit allen übereinstimmenden Schlüsselpunkten durch. Ich extrahiere, welche Schlüsselpunkte zwischen den beiden Bildern übereinstimmen, extrahiere dann ihre (x,y) Koordinaten. Ich zeichne dann Kreise an jedem der erkannten Stellen und zeichne dann eine Linie, die diese Kreise verbindet.

Bedenken Sie, dass der erkannte Schlüsselpunkt im zweiten Bild in Bezug auf sein eigenes Koordinatensystem ist. Wenn Sie dies in das endgültige Ausgabebild einfügen möchten, müssen Sie die Spaltenkoordinate um die Anzahl der Spalten aus dem ersten Bild versetzen, so dass die Spaltenkoordinate in Bezug auf das Koordinatensystem des Ausgabebilds ist .

Ohne weitere Umschweife:

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() 

Um zu zeigen, dass dies funktioniert, sind hier die beiden Bilder, die ich verwendet:

enter image description here

enter image description here

I OpenCV die verwendet ORB-Detektor zur Erkennung der Schlüsselpunkte, und benutzte die normierte Hamming-Distanz als Abstandsmaß für die Ähnlichkeit, da dies ein binärer Deskriptor ist. Als solche:

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]) 

Dies ist das Bild, das ich bekommen:

enter image description here

+0

Hii @rayryeng Wenn ich versuche, über Code zu laufen, bekomme ich Traceback (letzten Anruf zuletzt) : Datei "orb1.py", Zeile 33, in aus [: rows1,: cols1 ,:] = np.dstack ([img1, img1, img1]) ValueError: konnte kein Eingabearray von Shape (900 , 1440,9) in Form (900,1440,3) –

+2

@BhushanPatil - Lesen Sie den Docstring der Funktion ** sorgfältig **. Es erfordert Graustufenbilder. Sie verwenden ** RGB ** -Bilder. Sie müssen die Bilder in Graustufen konvertieren, bevor Sie die Funktion verwenden. Ein einfacher Aufruf 'cv2.cvtColor' sollte ausreichen:' img = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY) 'wird funktionieren. Bitte lesen Sie die Dokumentation der Funktion, bevor Sie sie das nächste Mal benutzen. Dies ist eine Standard-Fähigkeit, die alle Entwickler lernen müssen, wenn sie den Code von jemand anderem verwenden. – rayryeng

Verwandte Themen