未验证 提交 9b4b7a67 编写于 作者: W Wei Shengyu 提交者: GitHub

Merge pull request #1746 from weisy11/deploy_v2

add det code
AlgoModule:
- preprocess:
- processor_type: data_processor
processor_name: image_processor
image_processors:
- ResizeImage:
size: [640, 640]
interpolation: 2
- NormalizeImage:
scale: 0.00392157
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
- ToRGB
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from algo_mod import build_algo_mod from processor.algo_mod import predictors, searcher
from searcher import build_searcher
from data_processor import build_data_processor
def build_processor(config): def build_processor(config):
processor_type = config.get("processor_type") processor_type = config.get("processor_type")
if processor_type == "algo_mod": processor_mod = locals()[processor_type]
return build_algo_mod(config) processor_name = config.get("processor_name")
elif processor_type == "searcher": return getattr(processor_mod, processor_name)
return build_searcher(config)
elif processor_type == "data_processor":
return build_data_processor(config)
else:
raise NotImplemented("processor_type {} not implemented.".format(processor_type))
class BaseProcessor(ABC): class BaseProcessor(ABC):
......
from .fake_cls import FakeClassifier from .. import BaseProcessor, build_processor
def build_algo_mod(config): class AlgoMod(BaseProcessor):
algo_name = config.get("algo_name") def __init__(self, config):
if algo_name == "fake_clas": self.pre_processor = build_processor(config["pre_processor"])
return FakeClassifier(config) self.predictor = build_processor(config["predictor"])
self.post_processor = build_processor(config["post_processor"])
def process(self, input_data):
input_data = self.pre_processor(input_data)
input_data = self.predictor(input_data)
input_data = self.post_processor(input_data)
return input_data
from .. import BaseProcessor from processor import BaseProcessor
class BBoxCropper(BaseProcessor): class BBoxCropper(BaseProcessor):
......
from functools import partial from functools import partial
import six
import math
import random
import cv2 import cv2
import numpy as np import numpy as np
import importlib import importlib
from PIL import Image from PIL import Image
import paddle
from utils import logger from utils import logger
from processor import BaseProcessor
class PreProcesser(object): class ImageProcessor(BaseProcessor):
def __init__(self, config): def __init__(self, config):
"""Image PreProcesser self.processors = []
for processor_config in config.get("image_processors"):
Args: name = list(processor_config)[0]
config (list): A list consisting of Dict object that describe an image processer operator. param = {} if processor_config[name] is None else processor_config[name]
""" op = locals()[name](**param)
super().__init__() self.processors.append(op)
self.ops = self.create_ops(config)
def process(self, input_data):
def create_ops(self, config): image = input_data["input_image"]
if not isinstance(config, list): for processor in self.processors:
msg = "The preprocess config should be a list consisting of Dict object." if isinstance(processor, BaseProcessor):
logger.error(msg) input_data["image"] = image
raise Exception(msg) input_data = processor.process(input_data)
mod = importlib.import_module(__name__)
ops = []
for op_config in config:
name = list(op_config)[0]
param = {} if op_config[name] is None else op_config[name]
op = getattr(mod, name)(**param)
ops.append(op)
return ops
def __call__(self, img, img_info=None):
if img_info:
for op in self.ops:
img, img_info = op(img, img_info)
return img, img_info
else: else:
for op in self.ops: image = processor(image)
img = op(img) return input_data
return img
class DecodeImage(object): class GetShapeInfo(BaseProcessor):
""" decode image """ def __init__(self):
pass
def __init__(self, to_rgb=True, to_np=False, channel_first=False): def process(self, input_data):
self.to_rgb = to_rgb input_image = input_data["input_image"]
self.to_np = to_np # to numpy image = input_data["image"]
self.channel_first = channel_first # only enabled when to_np is True input_data['im_shape'] = np.array(input_image.shape[:2], dtype=np.float32)
input_data['input_shape'] = np.array(image.shape[:2], dtype=np.float32)
input_data['scale_factor'] = np.array([image.shape[0] / input_image.shape[0],
image.shape[1] / input_image.shape[1]], dtype=np.float32)
def __call__(self, img, img_info=None):
if six.PY2: class ToTensor(BaseProcessor):
assert type(img) is str and len( def __init__(self, config):
img) > 0, "invalid input 'img' in DecodeImage" pass
else:
assert type(img) is bytes and len( def process(self, input_data):
img) > 0, "invalid input 'img' in DecodeImage" image = input_data["image"]
data = np.frombuffer(img, dtype='uint8') input_data["input_tensor"] = paddle.to_tensor(image)
img = cv2.imdecode(data, 1) return input_data
if self.to_rgb:
assert img.shape[2] == 3, 'invalid shape of image[%s]' % (
img.shape) class ToRGB:
def __init__(self):
pass
def __call__(self, img):
img = img[:, :, ::-1] img = img[:, :, ::-1]
return img
if self.channel_first:
img = img.transpose((2, 0, 1))
if img_info: class ToCHWImage:
img_info["im_shape"] = np.array(img.shape[:2], dtype=np.float32) def __init__(self):
img_info["scale_factor"] = np.array([1., 1.], dtype=np.float32) pass
return img, img_info
else: def __call__(self, img, img_info=None):
img = img.transpose((2, 0, 1))
return img return img
class UnifiedResize(object): class ResizeImage:
def __init__(self, interpolation=None, backend="cv2"): def __init__(self,
size=None,
resize_short=None,
interpolation=None,
backend="cv2"):
if resize_short is not None and resize_short > 0:
self.resize_short = resize_short
self.w = None
self.h = None
elif size is not None:
self.resize_short = None
self.w = size if type(size) is int else size[0]
self.h = size if type(size) is int else size[1]
else:
raise Exception("invalid params for ReisizeImage for '\
'both 'size' and 'resize_short' are None")
_cv2_interp_from_str = { _cv2_interp_from_str = {
'nearest': cv2.INTER_NEAREST, 'nearest': cv2.INTER_NEAREST,
'bilinear': cv2.INTER_LINEAR, 'bilinear': cv2.INTER_LINEAR,
...@@ -114,38 +122,12 @@ class UnifiedResize(object): ...@@ -114,38 +122,12 @@ class UnifiedResize(object):
self.resize_func = partial(_pil_resize, resample=interpolation) self.resize_func = partial(_pil_resize, resample=interpolation)
else: else:
logger.warning( logger.warning(
f"The backend of Resize only support \"cv2\" or \"PIL\". \"f{backend}\" is unavailable. Use \"cv2\" instead." f"The backend of Resize only support \"cv2\" or \"PIL\". \"f{backend}\" is unavailable. "
f"Use \"cv2\" instead."
) )
self.resize_func = cv2.resize self.resize_func = cv2.resize
def __call__(self, src, size): def __call__(self, img):
return self.resize_func(src, size)
class ResizeImage(object):
""" resize image """
def __init__(self,
size=None,
resize_short=None,
interpolation=None,
backend="cv2"):
if resize_short is not None and resize_short > 0:
self.resize_short = resize_short
self.w = None
self.h = None
elif size is not None:
self.resize_short = None
self.w = size if type(size) is int else size[0]
self.h = size if type(size) is int else size[1]
else:
raise Exception("invalid params for ReisizeImage for '\
'both 'size' and 'resize_short' are None")
self._resize_func = UnifiedResize(
interpolation=interpolation, backend=backend)
def __call__(self, img, img_info=None):
img_h, img_w = img.shape[:2] img_h, img_w = img.shape[:2]
if self.resize_short is not None: if self.resize_short is not None:
percent = float(self.resize_short) / min(img_w, img_h) percent = float(self.resize_short) / min(img_w, img_h)
...@@ -154,17 +136,11 @@ class ResizeImage(object): ...@@ -154,17 +136,11 @@ class ResizeImage(object):
else: else:
w = self.w w = self.w
h = self.h h = self.h
img = self._resize_func(img, (w, h)) img = self.resize_func(img, (w, h))
if img_info:
img_info["input_shape"] = img.shape[:2]
img_info["scale_factor"] = np.array(
[img.shape[0] / img_h, img.shape[1] / img_w]).astype("float32")
return img, img_info
else:
return img return img
class CropImage(object): class CropImage:
""" crop image """ """ crop image """
def __init__(self, size): def __init__(self, size):
...@@ -173,34 +149,25 @@ class CropImage(object): ...@@ -173,34 +149,25 @@ class CropImage(object):
else: else:
self.size = size # (h, w) self.size = size # (h, w)
def __call__(self, img, img_info=None): def __call__(self, img):
w, h = self.size w, h = self.size
img_h, img_w = img.shape[:2] img_h, img_w = img.shape[:2]
if img_h < h or img_w < w: if img_h < h or img_w < w:
raise Exception( raise Exception(
f"The size({h}, {w}) of CropImage must be greater than size({img_h}, {img_w}) of image. Please check image original size and size of ResizeImage if used." f"The size({h}, {w}) of CropImage must be greater than size({img_h}, {img_w}) of image. "
f"Please check image original size and size of ResizeImage if used."
) )
w_start = (img_w - w) // 2 w_start = (img_w - w) // 2
h_start = (img_h - h) // 2 h_start = (img_h - h) // 2
w_end = w_start + w w_end = w_start + w
h_end = h_start + h h_end = h_start + h
img = img[h_start:h_end, w_start:w_end, :] img = img[h_start:h_end, w_start:w_end, :]
if img_info:
img_info["input_shape"] = img.shape[:2]
# TODO(gaotingquan): im_shape is needed to update?
img_info["im_shape"] = np.array(img.shape[:2], dtype=np.float32)
return img, img_info
else:
return img return img
class NormalizeImage(object): class NormalizeImage:
""" normalize image such as substract mean, divide std
"""
def __init__(self, def __init__(self,
scale=None, scale=None,
mean=None, mean=None,
...@@ -210,9 +177,8 @@ class NormalizeImage(object): ...@@ -210,9 +177,8 @@ class NormalizeImage(object):
channel_num=3): channel_num=3):
if isinstance(scale, str): if isinstance(scale, str):
scale = eval(scale) scale = eval(scale)
assert channel_num in [ assert channel_num in [3, 4], \
3, 4 "channel number of input image should be set to 3 or 4."
], "channel number of input image should be set to 3 or 4."
self.channel_num = channel_num self.channel_num = channel_num
self.output_dtype = 'float16' if output_fp16 else 'float32' self.output_dtype = 'float16' if output_fp16 else 'float32'
self.scale = np.float32(scale if scale is not None else 1.0 / 255.0) self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
...@@ -224,12 +190,8 @@ class NormalizeImage(object): ...@@ -224,12 +190,8 @@ class NormalizeImage(object):
self.mean = np.array(mean).reshape(shape).astype('float32') self.mean = np.array(mean).reshape(shape).astype('float32')
self.std = np.array(std).reshape(shape).astype('float32') self.std = np.array(std).reshape(shape).astype('float32')
def __call__(self, img, img_info=None): def __call__(self, img):
if isinstance(img, Image.Image): assert isinstance(img, np.ndarray), "invalid input 'img' in NormalizeImage"
img = np.array(img)
assert isinstance(img,
np.ndarray), "invalid input 'img' in NormalizeImage"
img = (img.astype('float32') * self.scale - self.mean) / self.std img = (img.astype('float32') * self.scale - self.mean) / self.std
...@@ -244,25 +206,4 @@ class NormalizeImage(object): ...@@ -244,25 +206,4 @@ class NormalizeImage(object):
if self.order == 'chw' else np.concatenate( if self.order == 'chw' else np.concatenate(
(img, pad_zeros), axis=2)) (img, pad_zeros), axis=2))
img = img.astype(self.output_dtype) img = img.astype(self.output_dtype)
if img_info:
return img, img_info
else:
return img
class ToCHWImage(object):
""" convert hwc image to chw image
"""
def __init__(self):
pass
def __call__(self, img, img_info=None):
if isinstance(img, Image.Image):
img = np.array(img)
img = img.transpose((2, 0, 1))
if img_info:
return img, img_info
else:
return img return img
from .fake_cls import FakeClassifier
def build_algo_mod(config):
algo_name = config.get("algo_name")
if algo_name == "fake_clas":
return FakeClassifier(config)
from .. import BaseProcessor from processor import BaseProcessor
class FakeClassifier(BaseProcessor): class FakeClassifier(BaseProcessor):
......
# from bbox_cropper import
def build_data_processor(config):
return
from .. import BaseProcessor
class ImageReader(BaseProcessor):
def __init__(self):
pass
def process(self, input_data):
pass
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册