为什么 RANSAC 不适用于我的代码?
Why is RANSAC not working for my code?
我正在尝试找到 2 个图像之间的基本矩阵,然后使用 RANSAC 对它们进行变换。我首先使用 SIFT 检测关键点,然后应用 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
而当我按照 link: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html 中的教程进行操作时,代码运行没有错误。
感谢任何帮助!
你没有注意或不理解他们在解释什么。我建议您阅读 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 只是找到了整洁的关键点及其描述符。与第二张图片相比,它们不会自动出现。我们需要自己做。 this tutorial 中清楚地解释了 SIFT 真正做的事情。有疑问的时候画!或打印。 SIFT 实际给出的结果应该是相当明显的。在脚本开头取消注释 matplotlib
import。
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)
现在我们可以在两个图像中创建点列表并计算透视变换。同样,CV 不会照看孩子,如果没有至少 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]])
这似乎在情理之中。
已发布评论的答案,无法放入其他评论。
他们做的事情和我们做的完全一样,只是更明确一点。要查看会发生什么,您需要密切关注您发布的 link:
中的以下几行
- 第 244-255 行定义了可用算法的名称
- 第 281-284 行 select 检测器、描述符和匹配器算法
- 第 289-291 行实例化检测器、描述符和匹配器算法
- 在第 315 行找到第一个图像关键点
- 在第 316 行计算了第一个图像关键点描述符
- 在第 328 行找到第二个图像关键点
- 在第 329 行计算第二个图像关键点描述符
- 第 330 行第一和第二图像关键点和描述符匹配
- 然后完成一些透视变换
我们做完全相同的事情 -> 首先我们找到关键点并计算它们的描述符,然后我们匹配它们。他们找到关键点,然后计算描述符(2 行),但在 python 中,ALG.detectAndCompute
方法已经 returns 关键点和描述符,因此不需要像他们那样单独调用。检查一下,在 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 和规范汉明作为距离度量。参见 ORB tutorial and BFMatcher tutorial。
我只是将 SIFT 检测器和描述符计算器与 FlannBasedMatcher 一起使用,这是唯一的区别。其他步骤相同
我正在尝试找到 2 个图像之间的基本矩阵,然后使用 RANSAC 对它们进行变换。我首先使用 SIFT 检测关键点,然后应用 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
而当我按照 link: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html 中的教程进行操作时,代码运行没有错误。
感谢任何帮助!
你没有注意或不理解他们在解释什么。我建议您阅读 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 只是找到了整洁的关键点及其描述符。与第二张图片相比,它们不会自动出现。我们需要自己做。 this tutorial 中清楚地解释了 SIFT 真正做的事情。有疑问的时候画!或打印。 SIFT 实际给出的结果应该是相当明显的。在脚本开头取消注释 matplotlib
import。
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)
现在我们可以在两个图像中创建点列表并计算透视变换。同样,CV 不会照看孩子,如果没有至少 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]])
这似乎在情理之中。
已发布评论的答案,无法放入其他评论。
他们做的事情和我们做的完全一样,只是更明确一点。要查看会发生什么,您需要密切关注您发布的 link:
中的以下几行- 第 244-255 行定义了可用算法的名称
- 第 281-284 行 select 检测器、描述符和匹配器算法
- 第 289-291 行实例化检测器、描述符和匹配器算法
- 在第 315 行找到第一个图像关键点
- 在第 316 行计算了第一个图像关键点描述符
- 在第 328 行找到第二个图像关键点
- 在第 329 行计算第二个图像关键点描述符
- 第 330 行第一和第二图像关键点和描述符匹配
- 然后完成一些透视变换
我们做完全相同的事情 -> 首先我们找到关键点并计算它们的描述符,然后我们匹配它们。他们找到关键点,然后计算描述符(2 行),但在 python 中,ALG.detectAndCompute
方法已经 returns 关键点和描述符,因此不需要像他们那样单独调用。检查一下,在 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 和规范汉明作为距离度量。参见 ORB tutorial and BFMatcher tutorial。
我只是将 SIFT 检测器和描述符计算器与 FlannBasedMatcher 一起使用,这是唯一的区别。其他步骤相同