你沒有注意或不明白他們在說什麼。我建議你閱讀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 tutorial和BFMatcher tutorial。
我只是用FlannBasedMatcher的SIFT檢測器和描述符計算器,這是唯一的區別。所有其他步驟都是相同的。
感謝您的回答,我想我能在使用RANSAC之前需要匹配的對嗎?我試圖在應用基本矩陣以計算回憶之後,在第一幅圖像中找出也在第二幅圖像中可見的關鍵點的數量。 (以下內容:https://github.com/kipr/opencv/blob/master/samples/cpp/detector_descriptor_matcher_evaluation.cpp) –
@ 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
請查看我的原始答案編輯,瞭解您發佈的代碼的細節。 – ljetibo