|
- # Tencent is pleased to support the open source community by making ncnn available.
- #
- # Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
- #
- # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- # in compliance with the License. You may obtain a copy of the License at
- #
- # https://opensource.org/licenses/BSD-3-Clause
- #
- # Unless required by applicable law or agreed to in writing, software distributed
- # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- # CONDITIONS OF ANY KIND, either express or implied. See the License for the
- # specific language governing permissions and limitations under the License.
-
- import numpy as np
-
-
- def xywh2xyxy(x):
- # Convert nx4 boxes from [x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right
- y = np.zeros_like(x)
- y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
- y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
- y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
- y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
- return y
-
-
- def xyxy2xywh(x):
- # Convert nx4 boxes from [x1, y1, x2, y2] to [x, y, w, h] where xy1=top-left, xy2=bottom-right
- y = np.zeros_like(x)
- y[:, 0] = (x[:, 0] + x[:, 2]) / 2 # x center
- y[:, 1] = (x[:, 1] + x[:, 3]) / 2 # y center
- y[:, 2] = x[:, 2] - x[:, 0] # width
- y[:, 3] = x[:, 3] - x[:, 1] # height
- return y
-
-
- def make_grid(nx=20, ny=20):
- xv1, yv1 = np.meshgrid(np.arange(nx), np.arange(ny))
- z1 = np.stack((xv1, yv1), 2).reshape((1, ny, nx, 2)).astype(np.float32)
- return z1
-
-
- def sigmoid(x):
- return 1 / (1 + np.exp(-x))
-
-
- def softmax(x):
- max_value = np.max(x, axis=-1)
- x -= max_value.reshape((x.shape[0], 1))
- x = np.exp(x)
- sum_value = np.sum(x, axis=-1)
- x /= sum_value.reshape((x.shape[0], 1))
- return x
-
-
- def iou_of(boxes0, boxes1, eps=1e-5):
- """Return intersection-over-union (Jaccard index) of boxes.
-
- Args:
- boxes0 (N, 4): ground truth boxes.
- boxes1 (N or 1, 4): predicted boxes.
- eps: a small number to avoid 0 as denominator.
- Returns:
- iou (N): IoU values.
- """
- overlap_left_top = np.maximum(boxes0[..., :2], boxes1[..., :2])
- overlap_right_bottom = np.minimum(boxes0[..., 2:], boxes1[..., 2:])
-
- overlap_area = area_of(overlap_left_top, overlap_right_bottom)
- area0 = area_of(boxes0[..., :2], boxes0[..., 2:])
- area1 = area_of(boxes1[..., :2], boxes1[..., 2:])
- return overlap_area / (area0 + area1 - overlap_area + eps)
-
-
- def area_of(left_top, right_bottom):
- """Compute the areas of rectangles given two corners.
-
- Args:
- left_top (N, 2): left top corner.
- right_bottom (N, 2): right bottom corner.
-
- Returns:
- area (N): return the area.
- """
- hw = np.clip(right_bottom - left_top, 0.0, None)
- return hw[..., 0] * hw[..., 1]
-
-
- def nms(boxes, scores, iou_threshold, top_k=-1, candidate_size=200):
- """
-
- Args:
- box_scores (N, 5): boxes in corner-form(x1, y1, x2, y2) and probabilities.
- iou_threshold: intersection over union threshold.
- top_k: keep top_k results. If k <= 0, keep all the results.
- candidate_size: only consider the candidates with the highest scores.
- Returns:
- picked: a list of indexes of the kept boxes
- """
-
- picked = []
- indexes = np.argsort(scores)
- indexes = indexes[-candidate_size:]
- while len(indexes) > 0:
- current = indexes[-1]
- picked.append(current)
- if 0 < top_k == len(picked) or len(indexes) == 1:
- break
-
- current_box = boxes[current, :]
- indexes = indexes[:-1]
- rest_boxes = boxes[indexes, :]
- iou = iou_of(
- rest_boxes,
- np.expand_dims(current_box, axis=0),
- )
- indexes = indexes[iou <= iou_threshold]
-
- return picked
|