什么是轮廓近似?

Contourapproximation使用Ramer-Douglas-Peucker(RDP)算法,旨在通过减少给定阈值的顶点来简化折线。通俗地说,我们采用一条曲线并减少其顶点数量,同时保留其大部分形状。我将在这里给出算法的粗略概念。给定曲线的起点和终点,算法将首先找到距离连接两个参考点的线最大距离的顶点。让我们将其称为max_point。如果max_point距离小于阈值,我们会自动忽略起点和终点之间的所有顶点,使曲线成为一条直线。如果max_point超出阈值,我们将递归重复该算法,现在将其max_point作为参考之一,并重复检查过程。

假如,我们要开发一个自动导航的机器人,在机器人导航的过程中,必然会搜集大量的路径数据,进而指导机器人的前进,但是很多时候,路径上的拐点很多,这就加大了计算的负担,如何能尽可能地保留原始路径数据,又可以降低大量的计算,这就需要路径的一些估算,这就要使用到本次的路径轮廓近似原理。


原始路径


轮廓近似后的图片

实现轮廓近似原理
在阈值图像中找到最大的轮廓cnts=((),_EXTERNAL,_APPROX_SIMPLE)在输出图像上绘制轮廓的形状,计算边界框,并显示轮廓中的点数output=()(output,[c],-1,(0,255,0),3)(x,y,w,h)=(c)text="original,num_pts={}".format(len(c))(output,text,(x,y-5),_HERSHEY_SIMPLEX,0.5,(0,255,0),1)print("[INFO]{}".format(text))("OriginalContour",output)(0)

使用OpenCV的findContours函数,我们可以挑选出给定图像中所有可能的轮廓,我们使用了RETR_EXTERNAL参数,它只返回可用轮廓的单一表示,使用的另一个参数是CHAIN_APPROX_SIMPLE。这将删除单个链线连接中的许多顶点,这些顶点本质上是冗余的。然后我们从轮廓数组中抓取最大的轮廓,并使用drawContours函数把外框形状画出来。


外框轮廓

(0.001,0.05,10):peri=(c,True)approx=(c,eps*peri,True)output=()(output,[approx],-1,(0,255,0),3)text="eps={:.4f},num_pts={}".format(eps,len(approx))(output,text,(x,y-5),_HERSHEY_SIMPLEX,0.5,(0,255,0),1)print("[INFO]{}".format(text))("ApproximatedContour",output)(0)

我们需要一个valueeps,它将作为测量顶点的阈值,利用此阈值进行轮廓近似计算的参数

在第2行,使用计算轮廓的周长函数。然后我们使用该函数,启动轮廓近似过程(第3行)。eps×peri乘积值充当近似精度,通过遍历不同的eps,进行轮廓的近似计算。

通过运行代码,我们可以看出,随着eps值不断增加,其轮廓顶点数不断减少,直到顶点数量不再减少为止,这表明轮廓近似算法确实有效。

[INFO]original,num_pts=402[INFO]eps=0.0010,num_pts=30[INFO]eps=0.0064,num_pts=25[INFO]eps=0.0119,num_pts=18[INFO]eps=0.0173,num_pts=15[INFO]eps=0.0228,num_pts=14[INFO]eps=0.0282,num_pts=10[INFO]eps=0.0337,num_pts=7[INFO]eps=0.0391,num_pts=6[INFO]eps=0.0446,num_pts=5[INFO]eps=0.0500,num_pts=5


轮廓近似原理图

当然,在应用中,我们需要找到合适的eps的值,以便在保证轮廓精度的情况下,降低计算的成本。