| import argparse |
| import glob |
| import os |
|
|
| import cv2 as cv |
| import numpy as np |
|
|
| here = os.path.dirname(os.path.abspath(__file__)) |
| sz = 512 |
|
|
|
|
| def build_anchors(): |
| scales = [2.0 ** (i / 3.0) for i in range(3)] |
| aspects = [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)] |
| base = [] |
| for s in scales: |
| for aw, ah in aspects: |
| base.append((32.0 * s * aw, 32.0 * s * ah)) |
| anchors = [] |
| for lvl in range(5): |
| f = sz // (8 * 2 ** lvl) |
| step = 8 * 2 ** lvl |
| m = 2 ** lvl |
| for y in range(f): |
| for x in range(f): |
| cx = (x + 0.5) * step |
| cy = (y + 0.5) * step |
| for bw, bh in base: |
| anchors.append((cx, cy, bw * m, bh * m)) |
| return np.array(anchors, np.float32) |
|
|
|
|
| def main(): |
| parser = argparse.ArgumentParser(description="EfficientDet-D0 (ONNX) object detection demo") |
| parser.add_argument("--model", default=None) |
| parser.add_argument("--image", default=os.path.join(here, "example_outputs", "input_image.png")) |
| parser.add_argument("--output", default=os.path.join(here, "example_outputs", "output_image.png")) |
| parser.add_argument("--conf", type=float, default=0.4) |
| args = parser.parse_args() |
|
|
| model = args.model |
| if model is None: |
| found = glob.glob(os.path.join(here, "*.onnx")) |
| if not found: |
| raise SystemExit("no onnx, run convert_to_onnx.py") |
| model = found[0] |
|
|
| img = cv.imread(args.image) |
| if img is None: |
| raise SystemExit("could not read image: %s" % args.image) |
|
|
| anchors = build_anchors() |
| acx, acy, aw, ah = anchors[:, 0], anchors[:, 1], anchors[:, 2], anchors[:, 3] |
|
|
| net = cv.dnn.readNetFromONNX(model) |
| inp = cv.resize(cv.cvtColor(img, cv.COLOR_BGR2RGB), (sz, sz)) |
| net.setInput(inp[None].astype(np.uint8)) |
| res = net.forward(net.getUnconnectedOutLayersNames()) |
| box = next(a for a in res if a.shape[-1] == 4).reshape(-1, 4) |
| cls = next(a for a in res if a.shape[-1] != 4).reshape(box.shape[0], -1) |
|
|
| ycenter = box[:, 0] * ah + acy |
| xcenter = box[:, 1] * aw + acx |
| bh = np.exp(box[:, 2]) * ah |
| bw = np.exp(box[:, 3]) * aw |
| boxes = np.stack([xcenter - bw / 2, ycenter - bh / 2, xcenter + bw / 2, ycenter + bh / 2], 1) / sz |
|
|
| prob = 1.0 / (1.0 + np.exp(-cls)) |
| cid = prob.argmax(1) |
| scores = prob.max(1) |
|
|
| keep = scores > args.conf |
| boxes = boxes[keep] |
| scores = scores[keep] |
| cid = cid[keep] |
| order = scores.argsort()[::-1] |
| pick = [] |
| while order.size: |
| i = order[0] |
| pick.append(i) |
| xx1 = np.maximum(boxes[i, 0], boxes[order[1:], 0]) |
| yy1 = np.maximum(boxes[i, 1], boxes[order[1:], 1]) |
| xx2 = np.minimum(boxes[i, 2], boxes[order[1:], 2]) |
| yy2 = np.minimum(boxes[i, 3], boxes[order[1:], 3]) |
| iw = np.maximum(0, xx2 - xx1) |
| ih = np.maximum(0, yy2 - yy1) |
| inter = iw * ih |
| ai = (boxes[i, 2] - boxes[i, 0]) * (boxes[i, 3] - boxes[i, 1]) |
| aj = (boxes[order[1:], 2] - boxes[order[1:], 0]) * (boxes[order[1:], 3] - boxes[order[1:], 1]) |
| iou = inter / (ai + aj - inter + 1e-9) |
| order = order[1:][iou <= 0.6] |
|
|
| print("efficientdet-d0", len(pick), "detections") |
| h, w = img.shape[:2] |
| for i in pick: |
| x1, y1, x2, y2 = boxes[i] |
| print(int(cid[i]), round(float(scores[i]), 3), round(float(x1), 3), round(float(y1), 3), round(float(x2), 3), round(float(y2), 3)) |
| cv.rectangle(img, (int(x1 * w), int(y1 * h)), (int(x2 * w), int(y2 * h)), (0, 255, 0), 2) |
| cv.putText(img, "%d:%.2f" % (int(cid[i]), scores[i]), (int(x1 * w), int(y1 * h) - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) |
| cv.imwrite(args.output, img) |
| print("wrote", args.output) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|