持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
交并比基本概念
为了了解所提取候选区域的准确性,我们使用了一个名为“交并比” (Intersection over Union
, IoU
) 的度量,IoU
计算方式如下所示:
在上图中,蓝色框是标注的目标边界框,红色框是候选区域。计算候选区域的交并比为候选框和标注框的交集与候选框与标注框的并集的比。接下来,我们详细介绍并实现 IoU
的计算过程。
交并比的计算
根据以上 IoU
定义,编写 IoU
计算函数,如以下代码所示:
from copy import deepcopy
import numpy as np
import cv2
import matplotlib.pyplot as plt
import selectivesearch
def calc_iou(candidate, current_y, img_shape):
boxA = deepcopy(candidate)
boxB = deepcopy(current_y)
img1 = np.zeros(img_shape)
img1[int(boxA[1]):int(boxA[3]), int(boxA[0]):int(boxA[2])] = 1
img2 = np.zeros(img_shape)
img2[int(boxB[1]):int(boxB[3]), int(boxB[0]):int(boxB[2])] = 1
iou = np.sum(img1*img2) / (np.sum(img1) + np.sum(img2) - np.sum(img1*img2))
return iou
在函数中,我们将候选目标边界框,实际目标边界框和图像尺寸作为输入。在函数中,我们首先初始化了两个形状与图像尺寸相同的零值数组,并用值 1
覆盖候选目标区域和实际目标区域内的值。最后,我们计算了候选目标区域与实际目标区域的交并比。
导入需要计算的图像:
img = cv2.imread('4.png')
绘制图像并观察目标对象的实际位置:
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
从上图中可以看出,目标人物在 x
轴上大约从左下角 x=300
开始到 x=590
,在 y
轴上,其大约从 y=50
开始到 y=500
。因此,对象的实际位置是 (50, 50, 290, 500)
,使用的格式为 (xmin, ymin, xmax, ymax)
。
提取候选区域,方法与在使用选择性搜索生成候选区域中介绍的相同:
img_lbl, regions = selectivesearch.selective_search(img, scale=100, min_size=2500)
print(len(regions))
candidates = set()
for r in regions:
if r['rect'] in candidates:
continue
# 排除小于2500像素的区域
if r['size'] < 2500:
continue
x, y, w, h = r['rect']
candidates.add(r['rect'])
从 selectivesearch
方法提取的区域的格式为 (xmin, ymin, width, height)
。因此,在计算区域的 IoU
之前,应确保候选区域的位置和实际标记区域具有相同的格式,即 (xmin, ymin, xmax, ymax)
。
将 IoU
计算函数应用于加载的图像,该函数将实际对象区域和候选区域作为输入:
regions = list(candidates)
actual_bb = [300, 10, 590, 390]
iou = []
for i in range(len(regions)):
candidate = list(regions[i])
candidate[3] += candidate[1]
candidate[2] += candidate[0]
iou.append(calc_iou(candidate, actual_bb, img.shape))
确定与实际对象区域重叠度最高的候选区域:
index = np.argmax(iou)
# 打印相关信息
print(index)
print(iou[index])
我们在此加载的图像中,候选区域中交并比最高的区域索引为 4
,其值为 0.8862138765666049
,区域坐标为 (305, 29, 294, 370)
,格式为 (xmin, ymin, width, height)
。
最后,我们在图像中绘制实际边界框和候选边界框,我们必须将实际边界框的 (xmin, ymin, xmax, ymax)
格式转换为 (xmin, ymin, width, height)
:
max_region = list(regions[index])
actual_bb[2] -= actual_bb[0]
actual_bb[3] -= actual_bb[1]
添加具有最高 IoU
的候选边界框与真实边界框:
max_candidate_actual = [max_region, actual_bb]
最后,遍历前面的列表,并使用矩形框绘制图像中对象的实际区域和候选区域,其中实际区域使用红色表示,候选框使用蓝色表示:
import matplotlib.patches as mpatches
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
for i,(x, y, w, h) in enumerate(max_candidate_actual):
if(i==0):
rect = mpatches.Rectangle(
(x, y), w, h, fill=False, edgecolor='blue', linewidth=2)
ax.add_patch(rect)
else:
rect = mpatches.Rectangle(
(x, y), w, h, fill=False, edgecolor='red', linewidth=2)
ax.add_patch(rect)
plt.show()
经过以上步骤,我们就可以利用图像中对象的实际位置来计算每个候选区域的 IoU
,并可以获取具有最高 IoU
的候选区域,来定位图像中目标位置。