|
|
@@ -19,7 +19,6 @@ from typing import Union
|
|
|
import cv2
|
|
|
import numpy as np
|
|
|
import pyclipper
|
|
|
-from shapely.geometry import Polygon
|
|
|
|
|
|
from ....utils import logging
|
|
|
from ...utils.benchmark import benchmark
|
|
|
@@ -197,25 +196,39 @@ class DetResizeForTest:
|
|
|
class NormalizeImage:
|
|
|
"""normalize image such as substract mean, divide std"""
|
|
|
|
|
|
- def __init__(self, scale=None, mean=None, std=None, order="chw", **kwargs):
|
|
|
+ def __init__(self, scale=None, mean=None, std=None, order="chw"):
|
|
|
super().__init__()
|
|
|
if isinstance(scale, str):
|
|
|
scale = eval(scale)
|
|
|
- self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
|
|
|
+ self.order = order
|
|
|
+
|
|
|
+ scale = scale if scale is not None else 1.0 / 255.0
|
|
|
mean = mean if mean is not None else [0.485, 0.456, 0.406]
|
|
|
std = std if std is not None else [0.229, 0.224, 0.225]
|
|
|
|
|
|
- shape = (3, 1, 1) if order == "chw" else (1, 1, 3)
|
|
|
- self.mean = np.array(mean).reshape(shape).astype("float32")
|
|
|
- self.std = np.array(std).reshape(shape).astype("float32")
|
|
|
+ self.alpha = [scale / std[i] for i in range(len(std))]
|
|
|
+ self.beta = [-mean[i] / std[i] for i in range(len(std))]
|
|
|
|
|
|
def __call__(self, imgs):
|
|
|
"""apply"""
|
|
|
|
|
|
- def norm(img):
|
|
|
- return (img.astype("float32") * self.scale - self.mean) / self.std
|
|
|
+ def _norm(img):
|
|
|
+ if self.order == "chw":
|
|
|
+ img = np.transpose(img, (2, 0, 1))
|
|
|
+
|
|
|
+ split_im = list(cv2.split(img))
|
|
|
+ for c in range(img.shape[2]):
|
|
|
+ split_im[c] = split_im[c].astype(np.float32)
|
|
|
+ split_im[c] *= self.alpha[c]
|
|
|
+ split_im[c] += self.beta[c]
|
|
|
+
|
|
|
+ res = cv2.merge(split_im)
|
|
|
|
|
|
- return [norm(img) for img in imgs]
|
|
|
+ if self.order == "chw":
|
|
|
+ res = np.transpose(res, (1, 2, 0))
|
|
|
+ return res
|
|
|
+
|
|
|
+ return [_norm(img) for img in imgs]
|
|
|
|
|
|
|
|
|
@benchmark.timeit
|
|
|
@@ -262,7 +275,8 @@ class DBPostProcess:
|
|
|
|
|
|
bitmap = _bitmap
|
|
|
height, width = bitmap.shape
|
|
|
-
|
|
|
+ width_scale = dest_width / width
|
|
|
+ height_scale = dest_height / height
|
|
|
boxes = []
|
|
|
scores = []
|
|
|
|
|
|
@@ -297,10 +311,10 @@ class DBPostProcess:
|
|
|
continue
|
|
|
|
|
|
box = np.array(box)
|
|
|
- box[:, 0] = np.clip(np.round(box[:, 0] / width * dest_width), 0, dest_width)
|
|
|
- box[:, 1] = np.clip(
|
|
|
- np.round(box[:, 1] / height * dest_height), 0, dest_height
|
|
|
- )
|
|
|
+ for i in range(box.shape[0]):
|
|
|
+ box[i, 0] = max(0, min(round(box[i, 0] * width_scale), dest_width))
|
|
|
+ box[i, 1] = max(0, min(round(box[i, 1] * height_scale), dest_height))
|
|
|
+
|
|
|
boxes.append(box)
|
|
|
scores.append(score)
|
|
|
return boxes, scores
|
|
|
@@ -318,6 +332,8 @@ class DBPostProcess:
|
|
|
|
|
|
bitmap = _bitmap
|
|
|
height, width = bitmap.shape
|
|
|
+ width_scale = dest_width / width
|
|
|
+ height_scale = dest_height / height
|
|
|
|
|
|
outs = cv2.findContours(
|
|
|
(bitmap * 255).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE
|
|
|
@@ -348,20 +364,21 @@ class DBPostProcess:
|
|
|
box, sside = self.get_mini_boxes(box)
|
|
|
if sside < self.min_size + 2:
|
|
|
continue
|
|
|
+
|
|
|
box = np.array(box)
|
|
|
+ for i in range(box.shape[0]):
|
|
|
+ box[i, 0] = max(0, min(round(box[i, 0] * width_scale), dest_width))
|
|
|
+ box[i, 1] = max(0, min(round(box[i, 1] * height_scale), dest_height))
|
|
|
|
|
|
- box[:, 0] = np.clip(np.round(box[:, 0] / width * dest_width), 0, dest_width)
|
|
|
- box[:, 1] = np.clip(
|
|
|
- np.round(box[:, 1] / height * dest_height), 0, dest_height
|
|
|
- )
|
|
|
boxes.append(box.astype(np.int16))
|
|
|
scores.append(score)
|
|
|
return np.array(boxes, dtype=np.int16), scores
|
|
|
|
|
|
def unclip(self, box, unclip_ratio):
|
|
|
"""unclip"""
|
|
|
- poly = Polygon(box)
|
|
|
- distance = poly.area * unclip_ratio / poly.length
|
|
|
+ area = cv2.contourArea(box)
|
|
|
+ length = cv2.arcLength(box, True)
|
|
|
+ distance = area * unclip_ratio / length
|
|
|
offset = pyclipper.PyclipperOffset()
|
|
|
offset.AddPath(box, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
|
|
|
try:
|
|
|
@@ -396,10 +413,10 @@ class DBPostProcess:
|
|
|
"""box_score_fast: use bbox mean score as the mean score"""
|
|
|
h, w = bitmap.shape[:2]
|
|
|
box = _box.copy()
|
|
|
- xmin = np.clip(np.floor(box[:, 0].min()).astype("int"), 0, w - 1)
|
|
|
- xmax = np.clip(np.ceil(box[:, 0].max()).astype("int"), 0, w - 1)
|
|
|
- ymin = np.clip(np.floor(box[:, 1].min()).astype("int"), 0, h - 1)
|
|
|
- ymax = np.clip(np.ceil(box[:, 1].max()).astype("int"), 0, h - 1)
|
|
|
+ xmin = max(0, min(math.floor(box[:, 0].min()), w - 1))
|
|
|
+ xmax = max(0, min(math.ceil(box[:, 0].max()), w - 1))
|
|
|
+ ymin = max(0, min(math.floor(box[:, 1].min()), h - 1))
|
|
|
+ ymax = max(0, min(math.ceil(box[:, 1].max()), h - 1))
|
|
|
|
|
|
mask = np.zeros((ymax - ymin + 1, xmax - xmin + 1), dtype=np.uint8)
|
|
|
box[:, 0] = box[:, 0] - xmin
|