2012-06-20 7 views
8

Opencv'yi python ile kullanmaya çalışıyorum. Opencv 2.4 C++ sürümünde bir kodlayıcı (SIFT, SURF veya ORB) eşleme kodu yazdım. Bu kodu python ile opencv'ye dönüştürmek istiyorum. C++ 'da opencv işlevlerinin nasıl kullanılacağı hakkında bazı belgeler buldum ama python'daki opencv işlevinin çoğunu nasıl kullanacağımı bulamadım. İşte benim python kodum ve şu anki problemim, python'da opencv C++ 'nin "drawMatches" ini nasıl kullanacağımı bilmem. Ben cv2.DRAW_MATCHES_FLAGS_DEFAULT buldum ama nasıl kullanacağımı bilmiyorum. İşte eşleşen kullanarak ORB tanımlayıcıların benim python kodu: Satır "img_matches = cv2.DRAW_MATCHES_FLAGS_DEFAULT (IM2, keypoints2, IM4, keypoints4, raw_matches)" ninPython'da opencv modülü kullanarak tanımlayıcı eşleştirmesi nasıl yapılır

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

Hata mesajı

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

Ben geçirdi çok zaman arama belgeleri ve python ile opencv işlevlerini kullanma örnekleri. Ancak, çok sinirliyim çünkü python'da opencv fonksiyonlarını kullanmayla ilgili çok az bilgi var. Herhangi biri bana python'daki opencv modülünün her işlevini nasıl kullanacağımın belgelerini bulabileceğimi öğretirse son derece yararlı olacaktır. Zamanını ve yardımını takdir ediyorum.

cevap

2

Hata mesajında ​​DRAW_MATCHES_FLAGS_DEFAULT, "long" yazıyor. Bir işlev değil, cv2 modülü tarafından tanımlanan bir sabittir. Ne yazık ki, istediğiniz fonksiyon, 'drawMatches' sadece OpenCV'nin C++ arayüzünde var.

+0

Teşekkür !! – user1433201

14

Python'daki özellik eşleşmesini aşağıdaki gibi görselleştirebilirsiniz. Scipy kütüphanesinin kullanılmasına dikkat edin. Ben de sadece OpenCV Python arabirimi kullanır ve ben scipy kullanmak vermedi şey kendimi yazdım

# 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

Kodunuzu çalıştırırken 66. satırda bir hata alıyorum, '' TypeError: tamsayı argümanı bekleniyor, float''' – gilbertbw

+0

@ wall-e anonim bir kullanıcı sadece mesajınızı düzenledi, kırılmadıklarını kontrol etmek isteyebilir – OGHaza

+0

görünüm [: h1,: w1,:] = img1 ValueError: şekil dizisini (322,518) şekle (322,518,3) biçiminde yayınlayamadı. – Giuseppe

9

. drawMatches, OpenCV 3.0.0'ın bir parçasıdır ve şu anda kullanmakta olduğum OpenCV 2'nin bir parçası değildir. Partiye geç kalmış olmama rağmen, işte benim yeteneğimin en iyisine drawMatches taklit eden kendi uygulamam.

Kendi resimlerimi, birinin kameralı biri olduğu yerde, diğerinin de aynı görüntüyü sağladığını ancak saat yönünün tersine 55 derece döndürdüm.

Yazdıklarımın temel dayanağı, çıktıların görüntülerinin her ikisini de yerleştirmek için satırların miktarının maksimum iki görüntü olduğu ve sütunların yalnızca özet olduğu çıkış RGB görüntüsünü ayırmamdır. her iki sütunun birlikte. Her görüntüyü karşılık gelen noktalara yerleştiriyorum, ardından eşleşen tüm anahtar noktalarının bir döngüsünden geçiyorum. İki görüntü arasında hangi anahtar noktaların eşleştiğini ayıkladım, daha sonra (x,y) koordinatlarını ayıkladım. Sonra tespit edilen konumların her birine daireler çiziyorum, sonra bu çemberleri birbirine bağlayan bir çizgi çiziyorum.

İkinci görüntüdeki algılanan anahtar noktanın kendi koordinat sistemine göre olduğunu unutmayın. Bunu son çıktı görüntüsüne yerleştirmek isterseniz, sütun koordinatının ilk görüntüdeki sütun sayısıyla dengelenmesi gerekir, böylece sütun koordinatı çıktı görüntüsünün koordinat sistemine göre olur .Ben OpenCV 's kullanılan

enter image description here

enter image description here

:

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

bu işte kullanılan iki görüntülerdir, çalıştığını göstermek için: Fazla uzatmadan

Anahtar noktalarını tespit etmek için ORB dedektörü, ve normalleştirilmiş Hamming mesafesini, ikili bir tanımlayıcı olduğu için benzerlik için mesafe ölçümü olarak kullandı. Bu itibarla:

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

En fazla bu resimdir: Cevabınız için

enter image description here

+0

Hii @ rayryeng'e gönderdiğim orjinal versiyona geri dönmek zorunda kaldım. Yukarıdaki kodu çalıştırmaya çalıştığımda, Traceback (en son çağrı son) alıyorum : Dosya "orb1.py", satır 33, dışarı [: satır1,: cols1 ,:] = np.dstack ([img1, img1, img1]) ValueError: giriş dizisini şekilden (900) yayınlayamadı , 1440,9) Şekle (900, 1440,3) –

+2

@ BhushanPatil - Fonksiyonun dokusunu okuyun ** dikkatlice **. Gri tonlamalı görüntüler gerektirir. ** RGB ** görüntüleri kullanıyorsunuz. Fonksiyonu kullanmadan önce görüntüleri gri tonlamaya dönüştürmeniz gerekir. Basit bir çağrı 'cv2.cvtColor' yeterli olmalıdır:' img = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY) 'çalışacaktır. Lütfen bir dahaki sefere kullanmadan önce fonksiyonun belgelerini okuyunuz. Bu, tüm geliştiricilerin bir başkasının kodunu kullanırken öğrenmesi gereken standart bir beceridir. – rayryeng