OpenCV 距离变换中的像素索引
Posted
技术标签:
【中文标题】OpenCV 距离变换中的像素索引【英文标题】:Pixel-indexing in OpenCV's distance transform 【发布时间】:2014-10-17 09:05:41 【问题描述】:我想使用函数distanceTransform() 来查找非零像素到零像素的最小距离,以及最接近的零像素的位置。我调用该函数的第二个版本,并将 labelType 标志设置为 DIST_LABEL_PIXEL。一切正常,我得到了最近零像素的距离和索引。
现在我想将索引转换回像素位置,我认为索引会像 idx=(row*cols+col) 或类似的东西,但我不得不发现 OpenCV 只是在计算零像素和使用此计数作为索引。所以如果我得到 123 作为最近像素的索引,这意味着第 123 个零像素是最近的。
OpenCV 如何计算它们?可能是按行方式?
是否有将索引映射回位置的有效方法?显然,如果我知道 OpenCV 如何计算它们,我可以重新计算它们并跟踪计数和位置,但这似乎很愚蠢而且效率不高。
是否有充分的理由使用他们使用的索引?我的意思是,与使用绝对索引相比有什么优势吗?
提前致谢。
编辑:
如果你想明白我的意思,你可以运行这个:
Mat mask = Mat::ones(100, 100, CV_8U);
mask.at<uchar>(50, 50) = 0;
Mat dist, labels;
distanceTransform(mask, dist, labels, CV_DIST_L2, CV_DIST_MASK_PRECISE, DIST_LABEL_PIXEL);
cout << labels.at<int>(0,0) << endl;
您会看到所有标签都是 1,因为只有一个零像素,但是我应该如何使用该信息找到位置 (50,50)?
【问题讨论】:
【参考方案1】:零像素也被标记 - 它们将具有与它们最接近的非零像素相同的标签。
因此,您将拥有一个与源图像大小相同的二维标签数组。如果您检查源图像中的所有零像素,则可以从返回的二维数组中找到相关的标签。这可以让您通过匹配标签来找到与每个零像素相关联的非零像素。
如果你明白我的意思。
【讨论】:
是的,我明白了,这是有道理的,因为这些像素最接近它们自己。但这也需要对图像进行额外的传递以收集零像素的标签和位置。我根本看不到这相对于绝对索引的优势。无论如何,谢谢,我还没有考虑过,至少我不必自己计算它们。 @thomas 谢谢 - 您不需要对图像进行额外的传递,您可以在一次传递中构建像素到标签的映射。只需要对算法进行一些思考。 我之前没有说过,但是我想根据最近的零像素的值和距离为非零像素分配值(显然不在我用于距离的掩码中转换)。我虽然这可以一次性完成,比如“获取标签、计算位置、获取值、做一些数学运算、赋值”。现在我必须事先进行标签->位置映射传递,这使它成为除了我必须做的分配传递之外的第二次传递。 我试过了,你是对的。开销可能很小,因为我的图像最多为 640x480。该方法的总体运行时间平均为 0.0097 秒。无论如何,我仍然很好奇他们为什么不使用绝对索引。感谢您的想法和提示。 this link中的答案用代码解释了使用DIST_LABEL_PIXEL
时如何获取标签的位置信息。我希望它对其他人和我一样有帮助。【参考方案2】:
在python中你可以使用numpy来关联标签和坐标:
import cv2
import numpy as np
# create an image with two 0-lines
a = np.ones((100,100), dtype=np.uint8)
a[50,:] = 0
a[:,70] = 0
dt,lbl = cv2.distanceTransformWithLabels(a, cv2.DIST_L2, 3, labelType=cv2.DIST_LABEL_PIXEL)
# coordinates of 0-value pixels
xy = np.where(a==0)
# print label id and coordinate
for i in range(len(np.unique(lbl))):
print(i,xy[0][i], xy[1][i])
【讨论】:
以上是关于OpenCV 距离变换中的像素索引的主要内容,如果未能解决你的问题,请参考以下文章