图像中缺少关键点

Missing keypoints from image

我正在尝试在图像上手动设置 22 个关键点,以便提取它们的特征。对于此任务,我使用我手动选择的坐标创建了一个关键点数组,并将向量作为参数传递给 orb.compute,然后它们分别绘制关键点。

我的问题是我在图像的不同部分设置了 22 个点,但它不会在图像中显示超过 14 个关键点。

这是我希望在哪些位置绘制 22 个关键点的示例:

实际发生了什么:

点从一张图片更改为另一张图片,但代码中的坐标才是最重要的,图片是我尝试做的事情和我得到的结果的说明性示例。

这是我的代码的可重现版本:

import pandas as pd
import skimage
import cv2
                imageList = skimage.io.imread("./a.png")  
                orb = cv2.ORB_create()
                key_points = [cv2.KeyPoint(65, 9, 10), <---- missing
                              cv2.KeyPoint(66, 12, 10), 
                              cv2.KeyPoint(62, 21, 10),
                              cv2.KeyPoint(60, 13, 10),
                              cv2.KeyPoint(67, 12, 10),
                              cv2.KeyPoint(107, 6, 10), <---- missing
                              cv2.KeyPoint(170, 10, 10),<---- missing 
                              cv2.KeyPoint(25, 60, 10), 
                              cv2.KeyPoint(60, 40, 10), 
                              cv2.KeyPoint(110, 35, 10), 
                              cv2.KeyPoint(170, 35, 10), 
                              cv2.KeyPoint(190, 60, 1), 
                              cv2.KeyPoint(30, 95, 10), <---- missing
                              cv2.KeyPoint(60, 80, 10), 
                              cv2.KeyPoint(100, 105, 10), 
                              cv2.KeyPoint(120, 105, 10),
                              cv2.KeyPoint(160, 180, 10), 
                              cv2.KeyPoint(185, 95, 10), 
                              cv2.KeyPoint(25, 160, 10), <---- missing
                              cv2.KeyPoint(55, 160, 10), 
                              cv2.KeyPoint(155, 160, 10), 
                              cv2.KeyPoint(185, 160, 10), <---- missing
                              cv2.KeyPoint(65, 200, 10), <----- missing
                              cv2.KeyPoint(83, 186, 10), 
                              cv2.KeyPoint(128, 186, 10), 
                              cv2.KeyPoint(157, 197, 10) <---- missing]
                kp, des = orb.compute(imageList, key_points)
                kparray = cv2.drawKeypoints(imageList, kp, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS); 
                cv2.imshow("Image", kparray)
                cv2.waitKey(0)

所以,出于某种原因,我设置了上面可以看到的所有这些 22 个点,但是当我 运行 我的代码时,它只显示 14 个,有些丢失了 我什至尝试在 cv2.drawKeyPoints 中打印 kp 参数以确保,即便如此:

[<KeyPoint 000002DF9DE83B40>, 
<KeyPoint 000002DF9DE83F90>, 
<KeyPoint 000002DF9DE83FC0>, 
<KeyPoint 000002DF9DE83F30>, 
<KeyPoint 000002DF9DE83DB0>, 
<KeyPoint 000002DFAB657030>, 
<KeyPoint 000002DFAB657B40>, 
<KeyPoint 000002DFAC1FED20>, 
<KeyPoint 000002DFAC1FE480>, 
<KeyPoint 000002DFAC1FEC90>, 
<KeyPoint 000002DFAC1FEDE0>, 
<KeyPoint 000002DFAC20D030>, 
<KeyPoint 000002DFAC20D060>, 
<KeyPoint 000002DFAC20D0C0>]

首先,为了理解问题,我不得不大幅减少提供的代码。它可能会阻止人们提供帮助。

此外,您写道:

when I run my code, it shows only 14, some are missing I even tried printing the kp parameter in cv2.drawKeyPoints to make sure, even so:

因此,据我了解,这不是 OpenCV 显示的问题,而是 ORB 能够计算的关键点的问题。

所以让我改一下你的问题:

In OpenCV why is ORB computation removing some keypoints. Here is minimal code to reproduce:

import skimage
import cv2

imageList = skimage.io.imread("./a.png")
orb = cv2.ORB_create()
key_points = [cv2.KeyPoint(65, 9, 10), cv2.KeyPoint(66, 40, 10)]
kp, des = orb.compute(imageList, key_points)
print(len(kp))

prints "1"

因此可能会找到答案in some other Whosebug questions

例如,改变阈值,改变了我的结果。

...
orb = cv2.ORB_create(edgeThreshold=1)
...
print(len(kp))

returns“2”

不幸的是,我不是 ORB 专家,因此如果改写您的问题以引起 ORB 专家而不是我的注意,您可能会得到更好的结果。

祝你好运。

我遇到过同样的难题,可以为您提供部分答案。 “部分”,因为它没有完全解释您提供的具体示例值:

来自compute()方法的docs

keypoints, descriptors = cv.Feature2D.compute( images, keypoints[, descriptors] )
[snip]
keypoints Input collection of keypoints. Keypoints for which a descriptor cannot be computed are removed. Sometimes new keypoints can be added, for example: SIFT duplicates keypoint with several dominant orientations (for each orientation).

(突出显示我的)。

那么现在为什么不能计算描述符呢?在 ORB 的情况下,我在源代码中找到的唯一可能的答案是:如果它们太靠近图像边界。事实上,在 orb.cpp :

KeyPointsFilter::runByImageBorder(keypoints, image.size(), edgeThreshold);

调用 KeyPoints 的方法,它只是删除比 edgeThreshold 更接近边距的所有内容,在您的情况下,这将是 ORB 的默认值 31。

这解释了为什么您的一些示例关键点丢失了,但它没有解释为什么例如第二个 cv2.KeyPoint(66, 12, 10) 仍然存在,因为它显然比 31 更接近边距。也许您的 OpenCV 版本中存在错误,或者我还没有完全理解发生了什么。

edgeThreshold 设置为 1 会有所帮助,因为它不会过滤掉任何点,除非它们紧贴边界,但是 我不建议这样做,因为描述符考虑了更远的数据(由参数 patchSize 控制),我不确定,但我认为如果这恰好包括图像之外的数据,那么 OpenCV 会接受任何发生的事情位于该内存地址。

所以我的建议是:如果你不能把你的关键点进一步移动到图像中,那么将patchSize设置为你可以容忍的最小的东西,并将edgeThreshold设置为一半加上一些余量。