上篇文章,我们介绍了关于目标检测一些基础知识:边界框和锚框,以及使用python生成这些矩形框的方式。我们知道,在目标检测任务中,我们需要衡量锚框与边界框之间的重合度,这时候就需要引入交并比(Intersection of Union, IoU)这个概念了。
一、交并比我们可以很直观地想到,可以通过两个区域重叠的部分来衡量它们之间的相关性,或者重合度。重叠的部分越多,则相关性越强;反之,重叠的部分越少,它们之间的相关性就越弱。所以,我们从数学的集合概念里引入了交并比(IoU)这个概念。
关于集合,高中数学中就已经涉及到了。集合中有交集和并集两个概念。这两个概念可以通过下面两张图很直观地表现(上图为交集,下图为并集)。 如图,交集就指的是两个区域重合的部分,并集指的是两个区域包含的所有部分,而交并比就等于交集中的所有元素比并集中的所有元素,即: 对于两个矩形区域,如图: 可以看出,它们的交集区域的坐标为(xb1,yb1,xa2,ya2),一般情况下,两个矩形区域的交集区域坐标可以通过以下公式计算得到: 并集区域的面积为: 而并集部分的面积为两个区域面积之和减去其交集部分的面积,即: 其中: 最终的交并比为: 计算交并比的python代码如下: 定义计算交并比的函数:
#交并比计算 #输入参数依此为:第一个框的坐标、第二个框的坐标 def IoUofBox(pos1,pos2): #两个矩形区域坐标提取 xa1=pos1[0] ya1=pos1[1] xa2=pos1[2] ya2=pos1[3] xb1=pos2[0] yb1=pos2[1] xb2=pos2[2] yb2=pos2[3] # 交集区域坐标 xI1=max(xa1,xb1) yI1=max(ya1,yb1) xI2=min(xa2,xb2) yI2=min(ya2,yb2) # 交集区域面积 SI=max((xI2-xI1),0)*max((yI2-yI1),0) # 并集区域面积 SA=(xa2-xa1)*(ya2-ya1) SB=(xb2-xb1)*(yb2-yb1) SU=SA+SB-SI IoU=SI/SU return IoU我们简单来验证一下这个程序,先生成两个目标的边界框:
filename=/home/aistudio/work/DatasetId_158445_1619847762/7.jpeg file=imread(filename) pic=plt.imshow(file) #添加边界框坐标 bbox1=[656,178,1229,899] bbox2=[1549,178,1904,704] draw_rect(pic,bbox1,red) draw_rect(pic,bbox2,red)显示如下: 计算两个目标边界框的交并比,我们可以很直观地看出来,这两个目标边界框的交并比为0:
#添加边界框坐标 bbox1=[656,178,1229,899] bbox2=[1549,178,1904,704] # 验证交并比程序1 IoU1=IoUofBox(bbox1,bbox2) print(IoU is %.1f%IoU1)输出结果为: 再来计算同一个边界框相互之间的交并比,它应该为1
# 验证交并比程序2 IoU2=IoUofBox(bbox1,bbox1) print(IoU is %.1f%IoU2)运行结果为: 接下来,我们在目标‘4’周围产生一系列锚框,然后分别计算每个锚框与目标真实边界框的交并比。首先,我们产生一系列锚框。需要说明的是,我们在绘制锚框的函数里加入了绘制文字的部分,这是为了区分每个锚框,函数定义部分代码如下:
#定义绘制一些列锚框的函数 #输入参数依此为:需要加锚框的图像、中心坐标、尺寸系数、宽高比、图像的尺寸 def draw_abox(pic,c,l0,s,r,img_size): for scale in s: for ratio in r: # 锚框的尺寸 w=l0*scale*math.sqrt(ratio) h=l0*scale/math.sqrt(ratio) # 加入约束,防止锚框超出显示范围 img_h=img_size[0] img_w=img_size[1] x1=max(c[0]-w/2.0,0.0) y1=max(c[1]-h/2.0,0,0) x2=min(c[0]+w/2.0,img_w) y2=min(c[1]+h/2.0,img_w) abox=[x1,y1,x2,y2] # 绘制锚框以及文字信息 draw_rect(pic,abox,blue) plt.text(abox[0],abox[1],r=%.1f%ratio,color=blue,fontsize=8)绘制三个锚框:
#绘制锚框 img_size=file.shape; center=[942.5,538.5] l0=300 s=[2.0] r=[0.5,1,2] draw_abox(pic,center,l0,s,r,img_size)效果如下: 可以看到,r=1.0 的那个锚框与真实的边界框重合度最高,那么我们接下来分别计算一下真实框与每个锚框之间的交并比来验证一下。
# 验证交并比程序3 # 获取每个锚框的坐标,并计算交并比: for scale in s: for ratio in r: # 锚框的尺寸 w=l0*scale*math.sqrt(ratio) h=l0*scale/math.sqrt(ratio) # 加入约束,防止锚框超出显示范围 img_h=img_size[0] img_w=img_size[1] x1=max(center[0]-w/2.0,0.0) y1=max(center[1]-h/2.0,0,0) x2=min(center[0]+w/2.0,img_w) y2=min(center[1]+h/2.0,img_w) abox=[x1,y1,x2,y2] IoU=IoUofBox(bbox1,abox) print(IoU of r=%.1f is %.1f%(ratio,IoU))运行结果为:
本篇文章涉及到的所有代码如下:
import matplotlib.pyplot as plt from matplotlib.image import imread import matplotlib.patches as patches import matplotlib.axes import math #交并比计算 #输入参数依此为:第一个框的坐标、第二个框的坐标 def IoUofBox(pos1,pos2): #两个矩形区域坐标提取 xa1=pos1[0] ya1=pos1[1] xa2=pos1[2] ya2=pos1[3] xb1=pos2[0] yb1=pos2[1] xb2=pos2[2] yb2=pos2[3] # 交集区域坐标 xI1=max(xa1,xb1) yI1=max(ya1,yb1) xI2=min(xa2,xb2) yI2=min(ya2,yb2) # 交集区域面积 SI=max((xI2-xI1),0)*max((yI2-yI1),0) # 并集区域面积 SA=(xa2-xa1)*(ya2-ya1) SB=(xb2-xb1)*(yb2-yb1) SU=SA+SB-SI IoU=SI/SU return IoU #定义一个绘制矩形框的函数 #输入参数依此为:绘制的目标图像、矩形框的坐标以及框的颜色 def draw_rect(pic,pos,color): box=patches.Rectangle((pos[0],pos[1]),pos[2]-pos[0],pos[3]-pos[1],fill=False,edgecolor=color) axis=pic.axes axis.add_patch(box) #定义绘制一些列锚框的函数 #输入参数依此为:需要加锚框的图像、中心坐标、尺寸系数、宽高比、图像的尺寸 def draw_abox(pic,c,l0,s,r,img_size): for scale in s: for ratio in r: # 锚框的尺寸 w=l0*scale*math.sqrt(ratio) h=l0*scale/math.sqrt(ratio) # 加入约束,防止锚框超出显示范围 img_h=img_size[0] img_w=img_size[1] x1=max(c[0]-w/2.0,0.0) y1=max(c[1]-h/2.0,0,0) x2=min(c[0]+w/2.0,img_w) y2=min(c[1]+h/2.0,img_w) abox=[x1,y1,x2,y2] # 绘制锚框以及文字信息 draw_rect(pic,abox,blue) plt.text(abox[0],abox[1],r=%.1f%ratio,color=blue,fontsize=8) filename=/home/aistudio/work/DatasetId_158445_1619847762/7.jpeg file=imread(filename) pic=plt.imshow(file) #添加边界框坐标 bbox1=[656,178,1229,899] bbox2=[1549,178,1904,704] draw_rect(pic,bbox1,red) draw_rect(pic,bbox2,red) #绘制锚框 img_size=file.shape; center=[942.5,538.5] l0=300 s=[2.0] r=[0.5,1,2] draw_abox(pic,center,l0,s,r,img_size) # 验证交并比程序1 IoU1=IoUofBox(bbox1,bbox2) print(IoU is %.1f%IoU1) # 验证交并比程序2 IoU2=IoUofBox(bbox1,bbox1) print(IoU is %.1f%IoU2) # 验证交并比程序3 # 获取每个锚框的坐标,并计算交并比: for scale in s: for ratio in r: # 锚框的尺寸 w=l0*scale*math.sqrt(ratio) h=l0*scale/math.sqrt(ratio) # 加入约束,防止锚框超出显示范围 img_h=img_size[0] img_w=img_size[1] x1=max(center[0]-w/2.0,0.0) y1=max(center[1]-h/2.0,0,0) x2=min(center[0]+w/2.0,img_w) y2=min(center[1]+h/2.0,img_w) abox=[x1,y1,x2,y2] IoU=IoUofBox(bbox1,abox) print(IoU of r=%.1f is %.1f%(ratio,IoU))这和我们的观察结果一致。
到这里,我们已经掌握了关于目标检测的一些基础知识并实现了边界框、锚框的绘制以及交并比的计算。一些读者或许有疑问,如何得到锚框的输入参数呢?比如中心坐标。是的,机器一开始不可能直接得到目标的中心坐标。那么yolo算法是如何绘制锚框的呢?这个我会在之后的文章中为大家介绍。下篇文章,我将先为大家介绍如何读取我们已经导入的数据集,并教大家如何使用python来实现这个过程。
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:使用yolo3实现图片中的数字检测与识别(三):交并比介绍 https://www.yhzz.com.cn/a/12484.html