目标检测(一):目标框和锚框

目标检测(一):目标框和锚框1、什么是目标检测?目标检测(object detection)是计算机视觉的重要分支,在各个场景应用广泛。如我们在超市中的刷脸支付、在停车场的

大家好,欢迎来到IT知识分享网。

1、什么是目标检测?

目标检测(object detection)是计算机视觉的重要分支,在各个场景应用广泛。如我们在超市中的刷脸支付、在停车场的车牌识别、在自动驾驶中的车辆识别、在工业场景中的零件缺陷检测等都离不开目标检测。目标检测的主要任务是将图像中的目标框选出来,并识别是什么目标。

因此,目标检测主要解决的问题是:目标在哪?目标是什么?

目标检测(一):目标框和锚框

图1. 目标检测示意图

如图1所示,图像中包含两个人,若我们实现对 “人” 的目标检测,则需要将 “人” 的边界框选,并识别框选的目标是否是 “人”。

2、什么是目标框?

在目标检测中,通常使用目标框(bounding box)来描述目标的位置,目标框是矩形的。由矩形左上角的坐标(x1,y1)以及右下角的坐标(x2,y2)进行表示。另外,还可以采用边界框矩形的中心坐标(xc,yc)以及宽高(w,h)进行表示。

目标检测(一):目标框和锚框

图2. 目标检测示例图

如图2,图片中包含 “狗” 与 “猫” 两个目标。下面采用”左上-右下”,”中心-宽高”的方式进行表示。

(1)”左上-右下”转换为”中心-宽高”

def box_corner_to_center(boxes): """从(左上,右下)转换到(中间,宽度,高度)""" x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3] cx = (x1 + x2) / 2 cy = (y1 + y2) / 2 w = x2 - x1 h = y2 - y1 boxes = torch.stack((cx, cy, w, h), axis=-1) return boxes

(2)”中心-宽高”转换为”左上-右下”

def box_center_to_corner(boxes): """从(中间,宽度,高度)转换到(左上,右下)""" cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3] x1 = cx - 0.5 * w y1 = cy - 0.5 * h x2 = cx + 0.5 * w y2 = cy + 0.5 * h boxes = torch.stack((x1, y1, x2, y2), axis=-1) return boxes

(3)画出目标框(dog_bbox采用绿色,cat_bbox采用红色)

def bbox_to_rect(bbox, color): # 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式: # ((左上x,左上y),宽,高) return plt.Rectangle( xy=(bbox[0], bbox[1]), width=bbox[2]-bbox[0], height=bbox[3]-bbox[1], fill=False, edgecolor=color, linewidth=2) img = plt.imread('1.jpg') fig = plt.imshow(img) fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue')) fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red')) plt.show()

3、什么是锚框?

如图3,如果想要定位 “狗” 与 “猫” 的位置,直接的想法是在图像上生成大量不同形状、尺寸的检测区域,然后判断这些检测区域内是否包含目标。生成的这些检测区域称为锚框(anchor box)。

这里介绍一种生成方法:在每个像素位置处,生成不同比例、不同尺寸的锚框。

目标检测(一):目标框和锚框

图3. 锚框示意图

在图像中的每个像素处生成不同尺寸、不同比例的锚框。

  • 假设图像大小:
  • 生成的不同缩放比尺寸种类:
  • 生成的不同宽高比种类:
  • 则生成的总的锚框种类:
  • 因此每张图像上锚框个数:
  • 每个锚框在长度以及宽度上相对于原图长度与宽度相应的缩放比例为, 并定义锚框尺寸为,则有:
  • 锚框的宽度与长度方向比例:
  • 因此,可得:
  • 对上式进行归一化可得到:

因此,在每个像素位置处,根据锚框缩放比 s 与长宽比 r,可确定锚框。

目标检测(一):目标框和锚框

图4. 锚框生成图

锚框生成的代码如下:

import torch import matplotlib.pyplot as plt def multibox_prior(data, sizes, ratios): """生成以每个像素为中心具有不同形状的锚框""" in_height, in_width = data.shape[-2:] device, num_sizes, num_ratios = data.device, len(sizes), len(ratios) # 3, 3 boxes_per_pixel = (num_sizes + num_ratios - 1) # 每个像素的锚框数 size_tensor = torch.tensor(sizes, device=device) # list 转为 tensor ratio_tensor = torch.tensor(ratios, device=device) # 为了将锚点移动到像素的中心,需要设置偏移量。 # 因为一个像素的的高为1且宽为1,我们选择偏移我们的中心0.5 offset_h, offset_w = 0.5, 0.5 steps_h = 1.0 / in_height # 在y轴上缩放步长 steps_w = 1.0 / in_width # 在x轴上缩放步长 # 生成锚框的所有中心点 center_h = (torch.arange(in_height, device=device) + offset_h) * steps_h center_w = (torch.arange(in_width, device=device) + offset_w) * steps_w shift_y, shift_x = torch.meshgrid(center_h, center_w) shift_y, shift_x = shift_y.reshape(-1), shift_x.reshape(-1) # 生成“boxes_per_pixel”个高和宽, # 之后用于创建锚框的四角坐标(xmin,xmax,ymin,ymax) w = torch.cat((sizes[0] * torch.sqrt(in_height * ratio_tensor[:] / in_width), size_tensor[1:] * torch.sqrt(in_height * ratio_tensor[0] / in_width))) h = torch.cat((sizes[0] * torch.sqrt(in_width / ratio_tensor[:] / in_height), size_tensor[1:] * torch.sqrt(in_width / ratio_tensor[0] / in_height))) # 除以2来获得半高和半宽 anchor_manipulations = torch.stack((-w, -h, w, h)).T.repeat( in_height * in_width, 1) / 2 # 每个中心点都将有“boxes_per_pixel”个锚框, # 所以生成含所有锚框中心的网格,重复了“boxes_per_pixel”次 out_grid = torch.stack([shift_x, shift_y, shift_x, shift_y], dim=1).repeat_interleave(boxes_per_pixel, dim=0) output = out_grid + anchor_manipulations return output.unsqueeze(0) def bbox_to_rect(bbox, color): # 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式: # ((左上x,左上y),宽,高) return plt.Rectangle( xy=(bbox[0], bbox[1]), width=bbox[2] - bbox[0], height=bbox[3] - bbox[1], fill=False, edgecolor=color, linewidth=2) def show_bboxes(axes, bboxes, labels=None, colors=None): """显示所有边界框""" def _make_list(obj, default_values=None): if obj is None: obj = default_values elif not isinstance(obj, (list, tuple)): obj = [obj] return obj labels = _make_list(labels) colors = _make_list(colors, ['b', 'g', 'r', 'm', 'c']) for i, bbox in enumerate(bboxes): color = colors[i % len(colors)] rect = bbox_to_rect(bbox.detach().numpy(), color) axes.add_patch(rect) if labels and len(labels) > i: text_color = 'k' if color == 'w' else 'w' axes.text(rect.xy[0], rect.xy[1], labels[i], va='center', ha='center', fontsize=9, color=text_color, bbox=dict(facecolor=color, lw=0)) if __name__ == "__main__": img = plt.imread('1.jpg') h, w = img.shape[:2] X = torch.rand(size=(1, 3, h, w)) Y = multibox_prior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5]) boxes = Y.reshape(h, w, 5, 4) bbox_scale = torch.tensor((w, h, w, h)) fig = plt.imshow(img) show_bboxes(fig.axes, boxes[350, 450, :, :] * bbox_scale, ['s=0.75, r=1', 's=0.75, r=2', 's=0.75, r=0.5', 's=0.5, r=1', 's=0.25, r=1']) plt.show() 

欢迎点赞、评论、转发、收藏。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/46716.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信