尽管您使用的是 ORB,但您仍然需要一种算法来从背景中分割绳索,或者至少需要一些技术来识别属于绳索并且与红点等距的图像块。有许多选项可供探索。
如果这是一个真实的应用程序,请将您的照明和成像视为单独的问题来解决,这一点很重要。这看起来有点像一个类的问题,而不是你将销售和支持的应用程序的问题,但你仍然应该考虑照明:
- 当光照水平降低时,您的算法是否仍然有效?
- 相机姿态相对于绳索所在表面的变化将如何影响检测?
- 如果您要检测“黑色”绳索,是否还需要该算法来检测不同颜色的绳索?脏绳子?不同背景的绳索?
由于您感兴趣的对象是绳索,因此您必须考虑适用于检测非刚性对象的一类算法。始终首先考虑最简单的解决方案!
连接组件
连接组件标记是一种传统的图像处理算法,仍然适合作为许多应用程序的起点。最后我知道,这是在 OpenCV 中作为 findContours() 实现的。这也可以称为“blob 查找”或其某种变体。
https://en.wikipedia.org/wiki/Connected-component_labeling
https://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours
根据光照的不同,在运行连接的组件之前,您可能需要采取不同的步骤来对图像进行二值化。首先,将彩色图像转换为灰度图像,这将大大简化任务。
- 尝试手动阈值,因为您可以快速测试多个值以查看效果。如果二值化不完全正确,请不要太沮丧 - 这通常可以通过预处理来解决。
- 如果手动阈值范围有效(例如 8 位灰度范围内的 52 - 76),则使用会自动为您计算阈值的算法:Otsu、基于熵的方法等都将提供可比性能。无论哪种技术效果最好,都可以进一步调整代码/算法以针对您的绳索应用进行优化。
- 如果阈值化和二值化不起作用——这对于你的绳索应用来说似乎不太可能,至少你是如何呈现它的——然后切换到基于梯度(基于边缘,基于能量)的思考技术。
但假设您可以将绳索从背景中分离出来,您仍然需要一种方法从 [绳索内] 的红点开始,然后向蓝点移动相等的距离。在讨论其他绳索分割方法之后再详细介绍。
注意:连接组件标签可以在不仅仅是对黑白图像进行二值化的场景中工作。如果您可以创建纹理字段或图像的其他一些 2D 表示,从而可以将黑色绳索与相对较浅的背景区分开来,则可以使用连通分量算法。 (寻找“更复杂”或“更现代”的算法不一定是正确的方法。)
在二值化图像中,可以嵌套 blob:在白色背景上可以有多个黑色 blob,其中一个或多个内部是白色 blob,内部是黑色 blob,等等。处理 OpenCV 的早期版本这还算不错。 (OpenCV 是一个不错的起点,也是许多人的接触点,但由于多种原因,它并不总是优于其他开源和商业软件包;尽管很受欢迎,但 OpenCV 存在一些问题。)
一旦您在 2D 数字图像中有一个“斑点”(像素的 4 连接区域),您就可以将该斑点视为一个对象,此时您有多种选择:
- 边缘跟踪:围绕 blob 的内部和外部边缘进行跟踪。据我回忆,OpenCV 确实(或至少应该)有一些相对简单的方法来获得优势。
- 将 blob 拆分为组件 blob,每个组件都可以单独处理
- 将 blob 转换为多边形
- ...
如果您有一个非刚性对象,则连接组件算法应该在尝试的技术列表中排名靠前。
布尔运算
一旦将绳索作为连接组件(甚至可能没有此组件),您就可以使用布尔图像操作来查找图像中蓝点处的点:
- 在数据中,甚至在图像中创建一个圆形区域
- 找到圆(环)和代表绳索的黑色区域的交点。使用您的原始图像,您应该有四个区域。
- 找到交叉区域的中心点。
您甚至可以在完全不使用连接组件的情况下尝试此操作,但使用连接组件作为解决方案的一部分可以使其更加健壮。
多边形简化
如果您有一个 blob,在您的应用程序中它将是一组连接的黑色像素,代表地板上的绳索,那么您可以考虑将此 blob 转换为一个或多个多边形以进行进一步处理。使用多边形有很多好处。
如果您只考虑绳索的外部边界,那么您可以看到定义边界的像素集代表一个多边形。它是一个有很多点的多边形,不是凸多边形,而是一个多边形。
为了简化多边形,可以使用 Ramer-Douglas-Puecker 等算法:
https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
一旦你有了一个简化的多边形,你可以尝试一些技术来从多边形中渲染有用的数据
三角剖分通常取决于初始条件,因此生成的三角剖分是针对不同的多边形(即绳索 -> 斑点 -> 多边形 -> 简化的多边形)。因此,在您的应用程序中,对暗绳区域进行三角测量,然后将一个三角形的中心连接到下一个最近三角形的中心可能会很有用。您还必须处理交叉口,例如绳索重叠。最终,这可以产生绳索的“骨架化”。说起来……
骨架化
如果绳索问题是作为课堂练习向你提出的,那么它可能是一个尝试骨架化的提示。你可以在这里阅读:
https://en.wikipedia.org/wiki/Topological_skeleton
骨架化和细化有自己的问题要解决,但你应该深入研究一下,看看这些问题本身。
中轴变换 (MAT) 是一个相关概念。长篇大论。
基于边缘的技术
有许多技术可以根据边缘强度、能量、熵等生成“边缘图像”。使它们变得健壮需要一点努力。如果您接受过图像处理方面的学术培训,您可能听说过 Harris、Sobel、Canny 和类似的处理方法——它们都不是灵丹妙药,但它们简单可靠,可以产生您需要的数据。
“边缘图像”由代表图像梯度强度 [有时是梯度方向] 的像素组成。人们可能会将此边缘图像称为其他东西,但重要的是概念。
然后您如何处理边缘数据完全是另一个主题。但是考虑边缘图像(或至少是对象边界)的一个原因是它减少了您的算法需要处理的信息量。
均值偏移(及相关)
回到连接组件部分中提到的分割,还有其他方法可以从背景中分割图形:K-means、均值偏移等。您可能不需要其中任何一个,但它们很整洁,值得学习。
笔画宽度变换
这是一种有趣的技术,用于从嘈杂的背景中提取文本。虽然它是为 OCR 设计的,但它也适用于绳索,因为绳索宽度相对恒定,绳索形状各不相同,还有交叉点等。
简而言之,您可以将 SWT 视为一种通过查找彼此反平行的渐变来查找“笔触”(粗线)的方法。在笔划(或线条)的任一侧,边缘渐变点垂直于对象边缘。笔划一侧的法线指向与笔划另一侧的法线方向相反的方向。通过过滤彼此一定距离内的像素梯度对,您可以隔离某些笔画 - 甚至可以自动隔离。对于您的示例,表示绳索边缘对的点集合将比其他点对更常见。
非刚性匹配
有一些匹配非刚性形状的技术,但它们不值得探索。如果您不熟悉我上面提到的任何技术,请先探索其中的一些,然后再尝试任何更高级的算法。
CNN、机器学习等
甚至不要将这些方法视为起点。
其他注意事项
如果这是用于工业、安全或其他用途的应用程序,您必须确定您的图像处理在所有环境因素下的工作情况。这不是一件容易的事,并且可以在实验室中“有效”的设置和实际可行的设置之间产生巨大的差异。
我希望这会有所帮助。如果我的困惑多于帮助,或者您想更详细地探索一些想法,请随时发表回复。虽然我试图触及一些常见的(ish)技术,但我没有提到解决这个问题的所有不同方法。
简单地说:一旦你有了骨架、点网络或任何代表绳索和红点(已识别特征)的简化数据集,一些技术可以找到蓝点处的项目:
- 对于骨架,沿着绳索的每个“分支”向外追踪,直到测地线距离或直线 2D 距离是您想要的距离 D。
- 要使用几何图形,请创建一个宽度为 1 - 2 像素的圆。找到那个圆和绳子的交点。找到圆和绳子的交点的中心点。 (上面也有描述。)
祝你好运!