目标轮廓提取之边界跟踪法
1引言上一篇我们介绍了目标轮廓提取法来提取目标轮廓,这一章节我们来介绍边界跟踪法。边界跟踪的定义为从图像中的一个边界点出发,然后根据某种判别准则搜索出下一个边界点,以此跟踪出目标边界。边界跟踪的一般步骤如下:1)确定边界的起始搜索点,起始点的选择很关键,对于某些图像,选择不同的起始点会导致不同的结果2)确定合适边界判别准则和搜索准则,判别准则主要用于判断一个点是不是边界点,搜索准则则知道如何搜索下一个边缘点。3)确定搜索的终止条件。
2算法原理边界跟踪算法原理:1)从左下角开始逐点扫描,当遇到边缘点时,则跟踪,直至跟后续点回到起始点(对于闭合线),或其后续点在没有新的后续点(对于非闭合线)为止。2)如果为非闭合线,则跟踪一侧后,需从起始点开始朝相反方向跟踪到另一尾点。3)如果不止一个后续点,则按上述连接准则选择距离最近的点为后续点,另一次近的后续点作为新的边缘跟踪起点另行跟踪。4)一条线跟踪完后,接着扫描到下一个未跟踪点,直到所有边缘都跟踪完毕。我们来举个栗子吧:上图为边界跟踪示意图,图中黑点表示边界点,白点为图像的内部点。
跟踪的初始点是最左下方的黑点(即最后一行的最左黑点),跟踪的初始方向设定为左上角45度。跟踪开始后,初始点沿初始跟踪方向检测该方向是否有黑点(检测距离为一个像素点),如果是,则保存初始点,将检测到的点作为新的初始点,同时在原来检测的基础上,逆时针旋转90度作为新的跟踪方向。如果不是目标点,则沿顺时针旋转45度,沿新跟踪方向继续检测,直到找到黑色像素,然后将跟踪方向逆时针旋转90作为新的跟踪方向。重复上面不断改变跟踪方向,直到找到新的边界点。找到新的边界点后,将旧的边界点保存,将新检测到的点作为新的初始点。这样不断重复上述过程,直到检测点回到最开始的检测点为止。注意:中心像素可以跟踪的方向有8个,对每个方向制定了方向编号以及偏移量,如下图所示。一般来说,通常选取图像的最左下角的像素点作为起点。
3Python实现读入彩色图像img_name="./20210812/sample3.png"img=cv2.imread(img_name)结果如下:2)彩色图像灰度化
gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)结果如下:3)图像二值化
defget_binary_img(img):#grayimgtobinimagebin_img=np.zeros(shape=(img.shape),dtype=np.uint8)h=img.shape[0]w=img.shape[1]foriinrange(h):forjinrange(w):bin_img[i][j]=255ifimg[i][j]>200else0returnbin_img#调用bin_img=get_binary_img(gray_img)结果如下:
4)边界跟踪参考上述原理,进行实现,代码如下:
#从左上角查找开始defget_left_up_start_pt(bin_img):h=bin_img.shape[0]w=bin_img.shape[1]find=0start_i=0start_j=0foriinrange(h):forjinrange(w):ifbin_img[i][j]==0:find=1start_i=istart_j=jbreakreturnfind,start_i,start_jdeftrace_contour(bin_img,find,start_i,start_j):contour_img=np.zeros(shape=(bin_img.shape),dtype=np.uint8)contour_img+=255iffind:contour_img[start_i][start_j]=0Direct=[(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1),(-1,0)]BeginDirect=0findstart=0cur_i=start_icur_j=start_jwhilefindstart==0:findpoint=0whilefindpoint==0:i=cur_i+Direct[BeginDirect][1]j=cur_j+Direct[BeginDirect][0]pixel=bin_img[i][j]ifpixel==0:findpoint=1cur_i=icur_j=jifcur_i==start_iandcur_j==start_j:findstart=1contour_img[cur_i][cur_j]=0BeginDirect-=1ifBeginDirect==-1:BeginDirect=7BeginDirect-=1ifBeginDirect==-1:BeginDirect=7else:BeginDirect+=1ifBeginDirect==8:BeginDirect=0returncontour_img#调用find,start_i,start_j=get_left_up_start_pt(bin_img)contour_img=trace_contour(bin_img,find,start_i,start_j)结果如下:
4总结通过上述简单步骤,我们实现了物体边界跟踪,相应的处理效果如下:
上图中左侧为原图,右侧为我们提取的物体边界跟踪效果图。
关注公众号《AI算法之道》,获取更多AI算法资讯。