ytfeng's picture
fix: set backend and target in init (#293)
3c4ef91
from itertools import product
import numpy as np
import cv2 as cv
class LPD_YuNet:
def __init__(self, modelPath, inputSize=[320, 240], confThreshold=0.8, nmsThreshold=0.3, topK=5000, keepTopK=750, backendId=0, targetId=0):
self.model_path = modelPath
self.input_size = np.array(inputSize)
self.confidence_threshold=confThreshold
self.nms_threshold = nmsThreshold
self.top_k = topK
self.keep_top_k = keepTopK
self.backend_id = backendId
self.target_id = targetId
self.output_names = ['loc', 'conf', 'iou']
self.min_sizes = [[10, 16, 24], [32, 48], [64, 96], [128, 192, 256]]
self.steps = [8, 16, 32, 64]
self.variance = [0.1, 0.2]
# load model
self.model = cv.dnn.readNet(self.model_path)
# set backend and target
self.model.setPreferableBackend(self.backend_id)
self.model.setPreferableTarget(self.target_id)
# generate anchors/priorboxes
self._priorGen()
@property
def name(self):
return self.__class__.__name__
def setBackendAndTarget(self, backendId, targetId):
self.backend_id = backendId
self.target_id = targetId
self.model.setPreferableBackend(self.backend_id)
self.model.setPreferableTarget(self.target_id)
def setInputSize(self, inputSize):
self.input_size = inputSize
# re-generate anchors/priorboxes
self._priorGen()
def _preprocess(self, image):
return cv.dnn.blobFromImage(image)
def infer(self, image):
assert image.shape[0] == self.input_size[1], '{} (height of input image) != {} (preset height)'.format(image.shape[0], self.input_size[1])
assert image.shape[1] == self.input_size[0], '{} (width of input image) != {} (preset width)'.format(image.shape[1], self.input_size[0])
# Preprocess
inputBlob = self._preprocess(image)
# Forward
self.model.setInput(inputBlob)
outputBlob = self.model.forward(self.output_names)
# Postprocess
results = self._postprocess(outputBlob)
return results
def _postprocess(self, blob):
# Decode
dets = self._decode(blob)
# NMS
keepIdx = cv.dnn.NMSBoxes(
bboxes=dets[:, 0:4].tolist(),
scores=dets[:, -1].tolist(),
score_threshold=self.confidence_threshold,
nms_threshold=self.nms_threshold,
top_k=self.top_k
) # box_num x class_num
if len(keepIdx) > 0:
dets = dets[keepIdx]
return dets[:self.keep_top_k]
else:
return np.empty(shape=(0, 9))
def _priorGen(self):
w, h = self.input_size
feature_map_2th = [int(int((h + 1) / 2) / 2),
int(int((w + 1) / 2) / 2)]
feature_map_3th = [int(feature_map_2th[0] / 2),
int(feature_map_2th[1] / 2)]
feature_map_4th = [int(feature_map_3th[0] / 2),
int(feature_map_3th[1] / 2)]
feature_map_5th = [int(feature_map_4th[0] / 2),
int(feature_map_4th[1] / 2)]
feature_map_6th = [int(feature_map_5th[0] / 2),
int(feature_map_5th[1] / 2)]
feature_maps = [feature_map_3th, feature_map_4th,
feature_map_5th, feature_map_6th]
priors = []
for k, f in enumerate(feature_maps):
min_sizes = self.min_sizes[k]
for i, j in product(range(f[0]), range(f[1])): # i->h, j->w
for min_size in min_sizes:
s_kx = min_size / w
s_ky = min_size / h
cx = (j + 0.5) * self.steps[k] / w
cy = (i + 0.5) * self.steps[k] / h
priors.append([cx, cy, s_kx, s_ky])
self.priors = np.array(priors, dtype=np.float32)
def _decode(self, blob):
loc, conf, iou = blob
# get score
cls_scores = conf[:, 1]
iou_scores = iou[:, 0]
# clamp
_idx = np.where(iou_scores < 0.)
iou_scores[_idx] = 0.
_idx = np.where(iou_scores > 1.)
iou_scores[_idx] = 1.
scores = np.sqrt(cls_scores * iou_scores)
scores = scores[:, np.newaxis]
scale = self.input_size
# get four corner points for bounding box
bboxes = np.hstack((
(self.priors[:, 0:2] + loc[:, 4: 6] * self.variance[0] * self.priors[:, 2:4]) * scale,
(self.priors[:, 0:2] + loc[:, 6: 8] * self.variance[0] * self.priors[:, 2:4]) * scale,
(self.priors[:, 0:2] + loc[:, 10:12] * self.variance[0] * self.priors[:, 2:4]) * scale,
(self.priors[:, 0:2] + loc[:, 12:14] * self.variance[0] * self.priors[:, 2:4]) * scale
))
dets = np.hstack((bboxes, scores))
return dets