168 lines
6.9 KiB
Python
168 lines
6.9 KiB
Python
import numpy as np
|
|
import kneron_preprocessing as kp
|
|
import base.inference
|
|
import importlib
|
|
|
|
def preprocess_(image,
|
|
input_shape,
|
|
keep_ap=True,
|
|
upscale=False,
|
|
rectangle=None,
|
|
pad_center=False,
|
|
gray_scale=False,
|
|
crop_extend=None,
|
|
norm_std=256,
|
|
norm_bias=-0.5, **kwargs):
|
|
"""
|
|
preprocess includes color-converting, crop resize padding
|
|
example:
|
|
preprocess_(img, (224,224), keep_ap=True, rectangle=bbox, pad_center=True)
|
|
preprocess_(img, (224,224), keep_ap=False, rectangle=bbox, pad_center=False)
|
|
image: str
|
|
input_shape: model input shape (h, w)
|
|
keep_ap: bool if resize keep aspect ratio
|
|
upscale: when image smaller than target size, do upsampling
|
|
pad_center: bool, True padding center, False padding cornor
|
|
gray_scale: int, 0 for rgb, 1 for gray 1 channel, 2 for gray 3 channel
|
|
crop_extend: when keep aspect ratio, enlarge original bbox, If None it has same value as pad_center
|
|
rectangle: (xmin, ymin, w, h)
|
|
norm_std/norm_bias:
|
|
scalar: scale/bias for nomalization, default = (256, -0.5) [RGB/norm_std-bias][RGB/256-0.5]
|
|
array: (in general 1x3 array) perform RGB/std-bias in a channel-wise way
|
|
image: numpy.ndarray
|
|
dict: scale, w, h, real
|
|
rectangle: left top width height
|
|
padding: left right top bottom
|
|
mapping for postprocess
|
|
(x-padding[0])*scale[0]+rectangle[0]
|
|
(y-padding[2])*scale[1]+rectangle[1]
|
|
"""
|
|
if isinstance(image, str):
|
|
try:
|
|
image = kp.load_image(image)
|
|
except:
|
|
try:
|
|
image = kp.load_bin(image, **kwargs)
|
|
except:
|
|
print('input format error')
|
|
assert 0
|
|
else:
|
|
assert isinstance(image, np.ndarray) or isinstance(image, list)
|
|
image = np.asarray(image)
|
|
|
|
# get image original shape
|
|
h_inp, w_inp = input_shape
|
|
h_ori, w_ori = image.shape[:2]
|
|
h_ori2, w_ori2 = image.shape[:2]
|
|
# -------- Adjust bounding box and crop ---------
|
|
ar = 1.0*h_inp/w_inp
|
|
if crop_extend is None:
|
|
crop_extend = pad_center
|
|
if rectangle is not None:
|
|
left, top, width, height = rectangle[:4]
|
|
cx, cy = left + width / 2., top + height / 2.
|
|
if crop_extend and keep_ap:
|
|
width, height = max(width, (height / ar)), max(height, (width * ar))
|
|
x1, y1, x2, y2 = cx-width/2., cy-height/2., cx+width/2., cy+height/2.
|
|
else:
|
|
x1, y1, x2, y2 = left, top, left+width, top+height
|
|
# make sure rectangle inside image
|
|
# when rectangle outside iamge, crop both side
|
|
width = min([cx-x1, cx, x2-cx, w_ori-cx])*2
|
|
height = min([cy-y1, cy, y2-cy, h_ori-cy])*2
|
|
x1, y1, x2, y2 = int(cx - width / 2. + 0.5), int(cy - height / 2. + 0.5), int(cx + width / 2. + 0.5), int(
|
|
cy + height / 2. + 0.5)
|
|
# update rectangle passed to post
|
|
rectangle = [x1, y1, x2-x1, y2-y1]
|
|
image = kp.crop(image, box=(x1, y1, x2, y2), rounding_type=1)
|
|
if rectangle is None:
|
|
rectangle = [0, 0, w_ori2, h_ori2]
|
|
if len(image.shape)==0:
|
|
Warning("******************************************\n\
|
|
** Warning: INVALID box return black image**\n\
|
|
***********************************************")
|
|
print('box:', rectangle, ' w:', w_ori2, ' h:', h_ori2)
|
|
pre_info = {'scale': [1, 1],
|
|
'w_ori': w_ori,
|
|
'h_ori': h_ori,
|
|
'rectangle': rectangle,
|
|
'padding': [0, 0, 0, 0]}
|
|
if gray_scale == 0 or gray_scale == 2:
|
|
return np.zeros((1, h_inp, w_inp, 3)) + norm_bias, pre_info
|
|
else:
|
|
return np.zeros((1, h_inp, w_inp, 1)) + norm_bias, pre_info
|
|
# -------- calculate target size and do resize ---------
|
|
# IMPORTANT: update image size using crop image
|
|
h_ori, w_ori = image.shape[:2]
|
|
|
|
if keep_ap:
|
|
w_resize, h_resize = kp.calculate_keep_ratio_size((w_inp, h_inp), (w_ori, h_ori))
|
|
else:
|
|
w_resize, h_resize = w_inp, h_inp
|
|
if not upscale:
|
|
if w_resize > w_ori or h_resize > h_ori:
|
|
Warning('Cannot do upscale when upscale is False. Keep original size and do padding')
|
|
w_resize, h_resize = min(w_ori, w_resize), min(h_ori, h_resize)
|
|
|
|
if w_resize == w_ori and h_resize == h_ori:
|
|
resize_bypass = True
|
|
else:
|
|
resize_bypass = False
|
|
|
|
scale = [1.0 * w_ori / w_resize, 1.0 * h_ori / h_resize]
|
|
|
|
if not resize_bypass:
|
|
image = kp.resize(image, size=(w_resize, h_resize), keep_ratio=False)
|
|
|
|
# -------- calculate padding size for input and do padding ---------
|
|
if pad_center:
|
|
padding = kp.calculate_pad_length_center((w_inp, h_inp), (w_resize, h_resize))
|
|
else:
|
|
padding = kp.calculate_pad_length_corner((w_inp, h_inp), (w_resize, h_resize))
|
|
image = kp.pad(image, pad_l=padding[0], pad_r=padding[1], pad_t=padding[2], pad_b=padding[3], pad_val=0)
|
|
|
|
img_data = np.array(image).reshape((h_inp, w_inp, 3))
|
|
if gray_scale:
|
|
img_data = kp.convert(image=img_data, out_fmt='NIR')
|
|
img_data = img_data.reshape((h_inp, w_inp, 1))
|
|
if gray_scale == 2:
|
|
img_data = np.c_[img_data, img_data, img_data]
|
|
# img_data = kp.convert(image=img_data, source_fmt='NIR', out_fmt='RGB')
|
|
img_data = img_data[None]
|
|
img_data = kp.norm(img_data, scale=norm_std, bias=norm_bias)
|
|
return img_data, {'scale': scale,
|
|
'w_ori': w_ori2,
|
|
'h_ori': h_ori2,
|
|
'rectangle': rectangle,
|
|
'padding': padding}
|
|
|
|
|
|
def preprocess_hw(image, func=preprocess_, _type=0, **kwargs):
|
|
"""
|
|
:param image: str or np.ndarray image path or array
|
|
:param func: your preprocess function called by func(image, **kwargs)
|
|
:param _type: inference type
|
|
:param kwargs:
|
|
:return: image array after preprocess,
|
|
preinfo dict like aspect ratio
|
|
"""
|
|
if _type == base.inference.EMULATOR and kwargs["USER_CONFIG"]["pre"]["pre_mode"] != 'algorithm':
|
|
# FOR EMULATOR USE ONLY
|
|
# from python_flow.preprocess import preprocess_main
|
|
# config = kwargs.get("USER_CONFIG")
|
|
# img_data, pre_info = preprocess_main(config)
|
|
assert "USER_CONFIG" in kwargs
|
|
config = kwargs.get("USER_CONFIG")
|
|
team=config["pre"]["pre_mode"]
|
|
kwargs.update(config['pre'][team])
|
|
app_name = ".".join(str(config['flow']['app_folder']).split('/')[-2:])
|
|
function = f'{app_name}.sys.runners.src.'+config["pre"]["pre_type"]
|
|
module, function_name = function.rsplit(".", 1)
|
|
preprocess = importlib.import_module(module)
|
|
func = getattr(preprocess, function_name)
|
|
img_data, pre_info = func(image, **kwargs)
|
|
else:
|
|
# assert "USER_CONFIG" not in kwargs
|
|
img_data, pre_info = func(image, **kwargs)
|
|
return img_data, pre_info
|