Aruco 码精细化检测--参数说明

https://zhuanlan.zhihu.com/p/454475904

frame = np.array(img)
paras = cv2.aruco.DetectorParameters()
paras.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_SUBPIX
paras.cornerRefinementWinSize = 5

marker_corners_all, marker_ids_all, _ = cv2.aruco.detectMarkers(img, aruco_dict, parameters=paras)
aruco::detectMarkers(test_image, dictionary, corners, ids, parameters, rejectedCandidates);

结合检测过程,逐一介绍参数含义。

(1)阈值化

检测的第一步是输入图像的阈值化。阈值化过程由以下几个参数决定:

  • adaptiveThreshWinSizeMin,adaptiveThreshWinSizeMaxadaptiveThreshWinSizeStep

adaptiveThreshWinSizeMinadaptiveThreshWinSizeMax 参数代表选择的自适应阈值窗口大小(以像素为单位)间隔(具体参见Opencv的 threshold()函数)。

adaptiveThreshWinSizeStep表示窗口从adaptiveThreshWinSizeMin到adaptiveThreshWinSizeMax大小的增量。

例如,对于adaptiveThreshWinSizeMin=5,adaptiveThreshWinSizeMax=21,adaptiveThreshWinSizeStep=4,那么将会产生5个阈值化步骤,窗口大小分别为5, 9, 13, 17 和 21。在每个阈值化图像中,都会选出一些marker候选。

如果marker大小太大的话,较小的窗口大小可能会切割marker的边界,所以它将不会被检测到。另一方面,如果marker太小的话,较大的窗口大小也会有类似的效果。此外这一过程将会趋向于全局阈值,而失去了自适应的特性。最简单的例子是对adaptiveThreshWinSizeMin和adaptiveThreshWinSizeMax使用相同的值,这样就只会执行一次阈值化步骤。但是,最好还是使用一个范围的值作为窗口大小,虽然较多的阈值化步骤会在一定程度上降低性能。

缺省参数:adaptiveThreshWinSizeMin=3, adaptiveThreshWinSizeMax=23, adaptiveThreshWinSizeStep=10

  • double adaptiveThreshConstant这一参数表达了阈值状态下的常量(参见Opencv函数)。它的默认值是大多数例子下较好的情况。 默认值: 7

(2)轮廓滤波

阈值化之后,我们需要检测轮廓。我们并不会把所有的轮廓都当作是候选。在不同步骤中,我们通过滤波剔除一些不太可能是marker的轮廓。需要注意到,我们需要平衡检测的性能和效率。所有考虑到的轮廓都会在接下来的过程中做进一步处理,这通常产生了更高的计算消耗。所以,我们希望能够在这一阶段就丢弃错误的候选。另一方面,如果滤波的条件过于苛刻,事实上的marker轮廓可能会被错误地剔除。

  • double minMarkerPerimeterRatedouble maxMarkerPerimeterRate

这些参数决定了marker的最小值和最大值,具体来说,是最大最小marker的周长。它们并不是以绝对像素值作为单位,而是相对于输入图片的最大尺寸指定的。

例如,图像大小为640 x 480,最小相对marker周长为0.05的图像,将会产生一个最小周长640*0.05=32(像素)的marker,因为640是图像的最大尺寸。参数maxMarkerPerimeterRate 也是类似的。

如果minMarkerPerimeterRate太小,检测阶段性能会降低,因为会有更多的轮廓进入到接下来的阶段。这一弊端对于 maxMarkerPerimeterRate参数而言不是那么显著,因为小的轮廓数目通常要多于大的轮廓。选取minMarkerPerimeterRate值为0,就相当于考虑了图像中的所有轮廓,但是出于性能考虑这是不推荐的。

缺省值:minMarkerPerimeterRate=0.03, maxMarkerPerimeterRate = 4.0

  • double polygonalApproxAccuracyRate

我们对所有的候选进行多边形近似,只有近似结果为方形的形状才能通过测试。这一值决定了多边形近似产生的最大误差(参见approxPolyDP() 函数)。

这一参数是相对于候选长度的(像素上)。所以如果候选的周长为100像素,polygonalApproxAccuracyRate的值为0.04,那么最大的误差应当为100*0.04=5.4像素。

在大多例子中,缺省参数的表现已经很好了,但对高失真的图像,我们需要更大的误差值。

缺省值:0.05

  • double minCornerDistanceRate

同一张marker中每一对角的最小距离。这是相对于marker周长的值。像素的最小距离为Perimeter(周长)*minCornerDistanceRate.

缺省值: 0.05

  • double minMarkerDistanceRate

两张不同的marker之间的任一对角的最小距离。它表示相对于两个marker的最小标记周长。如果两个候选太接近,较小的一个被忽略。

缺省值:0.05

  • int minDistanceToBorder

marker角到图像边缘最小距离。部分图像边缘被遮挡的marker也能被正确地检测出来,如果遮挡部分比较小的话。但是,如果其中一个角被挡住了,返回的角通常在图像边界的一个错误的位置。

如果marker角的位置很重要的话,例如你想要做pose检测,最好舍弃掉那些离图像边缘太接近的角。否则就没有必要。

缺省值:3

(3)比特位提取

检测到候选后,需要分析每个候选的比特位,来确定它们是不是marker。在分析二进制编码之前,需要提取出比特位。为达到这个目的,将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。

以下是一个透视变换后的图像。

Aruco 码精细化检测--参数说明_第1张图片

接下来,图像被划分为网格,和marker位数相同。在每个单元格里,我们统计黑色和白色的个数,决定这个单元格的比特位。以下参数可以自定义这一过程:

Aruco 码精细化检测--参数说明_第2张图片

  • int markerBorderBits

这个参数指定了marker边界的宽度。这和每个比特位的大小相关。因此,值为2意味着边界的长度是两个内部比特位的长度。这个参数需要和你使用的Marker边界大小一致,边界的大小可以在绘制函数如 drawMarker()中设置。

缺省值:1

  • double minOtsuStdDev

这个参数决定了进行Otsu的最小标准差的像素值。如果偏差很低,可能意味着所有方形都是黑色的(或白色的),Otsu将不起作用。如果是这样的话,所有比特位都根据平均值大于还是小于128被设为0或者1。

缺省值:5.0 

  • int perpectiveRemovePixelPerCell

这个参数决定了透视变换后图像的像素数目(每个单元格,包含边界)。这是上图中红色正方形的大小。例如,假设我们在处理5x5比特位、边界为1比特位的marker。然后,每一个维度的单元格(比特位)的个数 为:5+2*1=7(边界需要被统计2次)。单元格总体大小为:7x7。

如果perpectiveRemovePixelPerCell的值为10,那么获取到的图像大小为10*7=70 -> 70x70 。这个参数选择更大的值可以提升比特位的提取过程(在某一程度上),但是它同样也降低了性能。

缺省值:4 

  • double perspectiveRemoveIgnoredMarginPerCell

当提取每个单元格的比特位时,需要统计黑色和白色的像素个数。一般而言,我们不推荐考虑单元格的所有像素。反之,最好忽略单元格的一些像素。原因在于,透视变换之后,单元格的颜色不会完全分离,白色的单元格可能会混入一些黑色的单元格(反之亦然)。因此,最好忽略这些像素,以避免错误的像素计数。例如以下图像。

Aruco 码精细化检测--参数说明_第3张图片

只考虑处在绿色正方形中的像素。我们可以在右边的图像中看到,最终的像素包含了邻域单元格更少的噪声。该参数指明了红色和绿色正方形之间的距离。参数值是相对于单元格整体的大小的。例如,如果单元格的大小为40像素,参数值为0.1,那么大小为40*0.1=4像素的边界将被剔除。这意味着每个单元格实际上要分析的像素大小为32x32,而不是40x40。

缺省值:0.13

4)Marker ID检测

比特位提取之后,接下来的步骤是检查提取的编码是否属于marker字典,有必要的话,还需要做错误检测步骤。

  • double maxErroneousBitsInBorderRate

marker边界的比特位应当是黑色的。这个参数指明了允许的边界出错比特位的个数。如边界可以出现的白色比特位的最大值。它的大小相对于marker中的比特位总数。

缺省值:0.35 

  • double errorCorrectionRate

每个marker字典有一位可以纠正的理论最大值(Dictionary.maxCorrectionBits)。但是,这个值可以由errorCorrectionRate 参数来修改。例如,如果允许纠正的比特位(对于使用的字典)数目为6, errorCorrectionRate的值为0.5,那么实际上最大的可以纠正的比特位个数为6*0.5=3。这一值对减少错误容忍率以避免错误的位置识别很有帮助。

缺省值:0.6

(5)角落细化

当我们检测完marker,并且验证了它们的id之后,最后要做的一步是在角落处的亚像素级的细化(参见OpenCV cornerSubPix())。注意,这一步是可选的,仅在我们对marker角位置的准确性要求很高时才有意义。例如,pose的检测。这一步骤很耗费时间,所以默认下是不做的。

  • bool doCornerRefinement

这个参数决定了是否要进行角落亚像素级细化过程,如果对角点的准确性要求不高,可以不进行这一过程。

缺省值:false 

  • int cornerRefinementWinSize

这个参数决定了亚像素级细化过程的窗口大小。较大的值可以产生窗口区域内比较靠近的图像角,marker角会移动到一个不同的错误的地方。除此之外这还会影响到性能。

缺省值:5 

  • int cornerRefinementMaxIterationsdouble cornerRefinementMinAccuracy

这两个值决定了亚像素级细化过程的结束条件。cornerRefinementMaxIterations指明了迭代的最大次数,cornerRefinementMinAccuracy 是结束这一过程前的最小错误值。

如果迭代次数过高,这会影响到性能。此外,如果太小的话,亚像素级细化就基本没有发挥作用。

缺省值:cornerRefinementMaxIterations=30, cornerRefinementMinAccuracy= 0.1

你可能感兴趣的:(计算机视觉,opencv,人工智能)