2017-03-01 24 views
0

我想找到2張圖片之間的基本矩陣,然後使用RANSAC對它們進行轉換。我先用SIFT檢測關鍵點,然後應用RANSAC:爲什麼RANSAC不能用於我的代碼?

img1 = cv2.imread("im0.png", 0) # queryImage 
img2 = cv2.imread("im1.png", 0) # trainImage 

    # Initiate SIFT detector 
sift = sift = cv2.xfeatures2d.SIFT_create() 

    # find the keypoints and descriptors with SIFT 
kp1, des1 = sift.detectAndCompute(img1, None) 
kp2, des2 = sift.detectAndCompute(img2, None) 

src = np.float32([points.pt for points in kp1]).reshape(-1, 1, 2) 
dst = np.float32([points.pt for points in kp2]).reshape(-1, 1, 2) 

H, masked = cv2.findHomography(src, dst, cv2.RANSAC, 5.0) 

然而,當我嘗試執行此,我只是得到一個錯誤,如下圖所示:

Traceback (most recent call last): 
File "sift2.py", line 29, in <module> 
M, mask = cv2.findHomography(src, dst, cv2.RANSAC, 5.0) 
cv2.error: /tmp/opencv3-20161119-29160-138ov36/modules/calib3d/src/fundam.cpp:349: error: (-215) src.checkVector(2) == dst.checkVector(2) in function findHomography 

而當我按照教程此鏈接:http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html,代碼無誤地運行。

任何幫助表示讚賞!

回答

0

你沒有注意或不明白他們在說什麼。我建議你閱讀full tutorials。您從未將SIFT在一張圖像中找到的關鍵點與SIFT在第二張圖像中找到的關鍵點進行匹配。

import cv2 
import numpy as np 
#import matplotlib.pyplot as plt 

#explicit is better than implicit cv2.IMREAD_GRAYSCALE is better than 0 
img1 = cv2.imread("img0.png", cv2.IMREAD_GRAYSCALE) # queryImage 
img2 = cv2.imread("img1.png", cv2.IMREAD_GRAYSCALE) # trainImage 
#CV doesn't hold hands, do the checks. 
if (img1 is None) or (img2 is None): 
    raise IOError("No files {0} and {1} found".format("img0.png", "img1.png")) 

# Initiate SIFT detector 
sift = cv2.xfeatures2d.SIFT_create() 

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

請確保您像檢查圖像一樣檢查SIFT。特別是如果你計劃編寫一個應用程序,因爲在舊的cv版本,它是cv2.SIFT()

現在問題的癥結在於SIFT只能找到整潔的關鍵點及其描述符。它們不會與第二張圖像進行自動比較。我們需要自己做。 SIFT真正做的是在this tutorial整齊地解釋。如有疑問畫畫!或打印。這應該是相當明顯的,SIFT實際上是這樣給出的。在腳本開始時取消註釋matplotlib導入。

tmp1 = cv2.drawKeypoints(img1, kp1) 
tmp2 = cv2.drawKeypoints(img2, kp2) 
plt.imshow(tmp1) 
plt.show() 
plt.imshow(tmp2) 
plt.show() 

這是實際比較圖像的部分。它通過關鍵點並根據一些距離計算比較最近k(2)個鄰居的描述符。在技​​術細節上有點模糊,但在this tutorial中整齊地解釋。這是你的例子中沒有的部分。

index_params = dict(algorithm = 0, trees = 5) 
search_params = dict(checks = 50) 
flann = cv2.FlannBasedMatcher(index_params, search_params) 

matches = flann.knnMatch(des1, des2, k=2) 
matches = np.asarray(matches) 

現在我們可以在圖像中創建點列表並計算透視變換。再次,簡歷沒有保姆,沒有至少4分就找不到視角 - 做檢查並且比CV更容易發現更好的錯誤。未來的自我會感恩。匹配返回爲元組列表[(a,aa), (b,bb)...],我們只需要單個字母(關鍵點),將列表轉換爲numpy數組並使用切片比使用for循環更快(如我在猜測,當有疑問 - 測試)。

if len(matches[:,0]) >= 4: 
    src = np.float32([ kp1[m.queryIdx].pt for m in matches[:,0] ]).reshape(-1,1,2) 
    dst = np.float32([ kp2[m.trainIdx].pt for m in matches[:,0] ]).reshape(-1,1,2) 

    H, masked = cv2.findHomography(src, dst, cv2.RANSAC, 5.0) 
else: 
    raise AssertionError("Can't find enough keypoints.") 

這對我的作品在OpenCV的2.4.9的示例圖像,我希望這是直接轉移到CV3但我不檢查的方式。對於他們的示例穀物圖像,我得到:

>>> H 
array([[ 4.71257834e-01, -1.93882419e-01, 1.18225742e+02], 
     [ 2.47062711e-02, 3.79364095e-01, 1.60925457e+02], 
     [ -1.21517456e-04, -4.95488261e-04, 1.00000000e+00]]) 

這似乎是合理的。


發表評論的答案不能適用於其他評論。

他們做的和我們做的事情完全一樣,他們對此更加明確。看你需要什麼發生密切關注以下線在你發佈的鏈接:

  • 線244-255定義可用的算法的名稱
  • 線281-284選擇探測器,描述符和匹配算法
  • 線289-291實例化檢測器,描述符和匹配算法上線
  • 315點第一圖像的關鍵點被發現
  • 上線316第一圖像關鍵點描述符計算
  • 線328b的第二圖像的關鍵點被發現在線
  • 329秒圖像關鍵點描述符上線計算
  • 330點的第一和第二圖像的關鍵點和描述符相匹配
  • 然後一些透視變換完成

我們完成同樣的事情 - >首先我們找到關鍵點並計算它們的描述符,然後我們匹配它們。他們找到關鍵點,然後計算描述符(2行),但在Python中,ALG.detectAndCompute方法已經返回關鍵點和描述符,因此不需要像他們那樣進行單獨的調用。檢查出來,在第一循環迭代時i=0這意味着i*4+n = n您有:

static const char* ddms[] = 
{ 
    "ORBX_BF", "ORB", "ORB", "BruteForce-Hamming", 
    // 0   1  2   3 
    //shortened for brevity 
     0 
    //4 
    .... 

這意味着

const char* name = ddms[i*4];    // --> ORBX_BF 
const char* detector_name = ddms[i*4+1]; // --> ORB 
const char* descriptor_name = ddms[i*4+2]; // --> ORB 
const char* matcher_name = ddms[i*4+3];  // --> BruteForce_Hamming 

..... // shortened 

Ptr<FeatureDetector> detector = FeatureDetector::create(detector_name); 
Ptr<DescriptorExtractor> descriptor = DescriptorExtractor::create(descriptor_name); 
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(matcher_name); 

相當於在Python

orb = cv2.ORB_create() 
detector = orb.detect # the pythonic way would be to just call 
descriptor = orb.compute # orb.detectAndCompute 
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) 

所以他們做了所有與我一樣的步驟,就是這樣的例子,除了他們使用ORB檢測器和描述符計算器和BruteForceMatcher與規範的Hamming作爲dist措施。見ORB tutorialBFMatcher tutorial

我只是用FlannBasedMatcher的SIFT檢測器和描述符計算器,這是唯一的區別。所有其他步驟都是相同的。

+0

感謝您的回答,我想我能在使用RANSAC之前需要匹配的對嗎?我試圖在應用基本矩陣以計算回憶之後,在第一幅圖像中找出也在第二幅圖像中可見的關鍵點的數量。 (以下內容:https://github.com/kipr/opencv/blob/master/samples/cpp/detector_descriptor_matcher_evaluation.cpp) –

+0

@ A.D'findHomography'需要兩組點。一個在src圖像上,一個在第二個圖像上。這些點需要對應。 src圖像中的第一個點需要指向第二個圖像中的第一個點。否則,如果您不確定是否檢出相同功能,則無法計算透視圖。 'RANSAC'就是算法試圖從所有可能的角度找到正確的角度的方式,而不是如何匹配src/dst點。請參閱http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=findhomography#findhomography – ljetibo

+0

請查看我的原始答案編輯,瞭解您發佈的代碼的細節。 – ljetibo

相關問題