Iou 的计算
我们先考虑一维的情况:令 \(A = [x_1,x_2], B = [y_1, y_2]\),若想要 \(A\) 与 \(B\) 有交集,需要满足如下情况:
简言之,要保证 \(A\) 和 \(B\) 的最大值中最小的那个减去它们中的最小值中最大的那个即可获得公共部分,代码实现如下:
class Anchor: def __init__(self, base_size=16): self.base_size = base_size # 滑动窗口的大小 if not base_size: raise ValueError("Invalid base_size: {}.".format(base_size)) self._anchor = np.array([1, 1, self.base_size, self.base_size]) - 1 @property def anchor(self): return self._anchor @anchor.setter def anchor(self, new_anchor): self._anchor = new_anchor @property def w(self): ''' 锚框的宽度 ''' return self.anchor[2] - self.anchor[0] + 1 @property def h(self): ''' 锚框的高度 ''' return self.anchor[3] - self.anchor[1] + 1 @property def size(self): ''' 锚框的面积 ''' return self.w * self.h @property def _whctrs(self): """ Return x center, and y center for an anchor (window). 锚框的中心坐标 """ x_ctr = self.anchor[0] + 0.5 * (self.w - 1) y_ctr = self.anchor[1] + 0.5 * (self.h - 1) return np.array([x_ctr, y_ctr]) @staticmethod def _coordinate(aspect, ctr): ''' 依据宽高组合计算锚框的坐标 ''' k = (aspect - 1) / 2 return np.concatenate([ctr - k, ctr + k], axis=1)
先创建一个可以用来做运算的计算器,然后在此基础上计算二维的 IoU,即
def iou(anchor, anchor1): A = Anchor() B = Anchor() A.anchor = anchor B.anchor = anchor1 T = np.stack([A.anchor, B.anchor]) xmin, ymin, xmax, ymax = np.split(T, 4, axis=1) w = xmax.min() - xmin.max() h = ymax.min() - ymin.max() I = w * h U = A.size + B.size - I return I / U
下面举一例子,并可视化:
img = np.ones((128 ,300, 3)) # 图片anchor = [ 12., 8., 195., 103.]anchor1 = [ 28., 8., 211., 103.]iou(anchor, anchor1)
最终结果为:
0.8151364126804707