# -*- coding: utf-8 -*- import numpy as np import os import math from PIL import Image from . import io from . import utils from . import general_funcs as funcs from .IE import IE from .inproc_520 import inproc_520_flow from .inproc_720 import inproc_720_flow DEFAULT = None default = { 'color':{ 'type':'float', }, 'crop':{ 'type':'float', 'align_w_to_4':False, }, 'resize':{ 'type':'float', }, 'pad':{ 'type':'float', }, 'similarity_transform':{ 'type':'float', }, 'warpAffine':{ 'type':'float', } } def set_default_as_520(): """ Set some default parameter as 520 setting Settings ---------- color.type = '520' crop.type = '520' crop.align_w_to_4 = True resize.type = '520' pad.type = '520' warpAffine.type = 'fx' """ global default default['color']['type'] = '520' default['crop']['type'] = '520' default['crop']['align_w_to_4'] = True default['resize']['type'] = '520' default['pad']['type'] = '520' default['similarity_transform']['type'] = 'fx' default['warpAffine']['type'] = 'fx' return def set_default_as_720(): """ Set some default parameter as 720 setting Settings ---------- color.type = '720' crop.type = '720' crop.align_w_to_4 = True resize.type = '720' pad.type = '720' warpAffine.type = 'fx' """ global default default['color']['type'] = '720' default['crop']['type'] = '720' default['crop']['align_w_to_4'] = True default['resize']['type'] = '720' default['pad']['type'] = '720' default['similarity_transform']['type'] = 'fx' default['warpAffine']['type'] = 'fx' return def set_default_as_IE(): """ Set some default parameter as IE setting Settings ---------- color.type = 'IE' crop.type = 'IE' crop.align_w_to_4 = False resize.type = 'IE' pad.type = 'IE' warpAffine.type = 'IE' """ global default default['color']['type'] = 'IE' default['crop']['type'] = 'IE' default['crop']['align_w_to_4'] = False default['resize']['type'] = 'IE' default['pad']['type'] = 'IE' default['similarity_transform']['type'] = 'fx' default['warpAffine']['type'] = 'IE' return def set_default_as_floating(): """ Set some default parameter as floating setting Settings ---------- color.type = 'float' crop.type = 'float' crop.align_w_to_4 = False resize.type = 'float' pad.type = 'float' warpAffine.type = 'float' """ global default default['color']['type'] = 'float' default['crop']['type'] = 'float' default['crop']['align_w_to_4'] = False default['resize']['type'] = 'float' default['pad']['type'] = 'float' default['similarity_transform']['type'] = 'float' default['warpAffine']['type'] = 'float' return def set_default_as_floating_pillow(): """ Set some default parameter as floating setting Settings ---------- color.type = 'float' crop.type = 'float' crop.align_w_to_4 = False resize.type = 'bilinear_pillow' pad.type = 'float' warpAffine.type = 'float' """ global default default['color']['type'] = 'float' default['crop']['type'] = 'float' default['crop']['align_w_to_4'] = False default['resize']['type'] = 'bilinear_pillow' default['pad']['type'] = 'float' default['similarity_transform']['type'] = 'float' default['warpAffine']['type'] = 'float' return def print_info_on(): """ turn print infomation on. """ pass def print_info_off(): """ turn print infomation off. """ pass def load_image(image): """ load_image function load load_image and output as rgb888 format np.array Parameters ---------- image : np.ndarray / str Input, can be np.array or image file path Returns ---------- out : np.ndarray Output image in rgb888 format. Examples ---------- """ if isinstance(image, np.ndarray): pass elif isinstance(image, str): image = Image.open(image) if image.mode == "I": image = np.array(image) else: image = image.convert("RGB") image = np.array(image).astype('uint8') assert isinstance(image, np.ndarray) return image def load_bin(image, fmt=None, size=None, output_fmt='RGB', order=None, **kwargs): """ load_bin function load bin file and output as rgb888 format np.array Parameters ---------- image : str, Bin file path. fmt : str "rgb888" / "yuv444" / "ycbcr444" / "yuv422" / "ycbcr422" / "rgb565" size : tuple 1x2 array, (image_w, image_h). order : int image order. Returns ---------- out : np.ndarray Output image in rgb888 format. Examples: ---------- >>> image_data = kp.load_bin(image,'rgb565',(raw_w,raw_h)) """ assert isinstance(size, tuple) assert isinstance(fmt, str) image = io.load_bin(input_file=image, src_w=size[0], src_h=size[1], image_fmt=fmt, order=order) image = funcs.color_convert(image, input_fmt=fmt, output_fmt=output_fmt) return image def load_hex(image, fmt=None, size=None, output_fmt='RGB', **kwargs): """ load_hex function load hex file and output as rgb888 format np.array Parameters ---------- image : str Hex file path. fmt : str "rgb888" / "yuv444" / "ycbcr444" / "yuv422" / "ycbcr422" / "rgb565" size : tuple 1x2 array, (image_w, image_h). Returns ---------- out : np.ndarray Output image in rgb888 format. Examples: ---------- >>> image_data = kp.load_hex(image,'rgb565',(raw_w,raw_h)) """ assert isinstance(size, tuple) assert isinstance(fmt, str) image = io.load_hex(input_file=image, src_w=size[0], src_h=size[1], image_fmt=fmt) image = funcs.color_convert(image=image, input_fmt=fmt, output_fmt=output_fmt) return image def dump_image(image, output, file_fmt='txt', image_fmt='rgb888', order=None, **kwargs): """ dump_image function dump txt, bin or hex, default is txt image format as following format: RGB888, RGBA8888, RGB565, NIR, YUV444, YCbCr444, YUV422, YCbCr422, default is RGB888 Parameters ---------- image : np.ndarray / str Input image, can be np.array or image file path. output : str Dump file path file_fmt : str "bin" / "txt" / "hex", set dump file format, default is txt image_fmt : str RGB888 / RGBA8888 / RGB565 / NIR / YUV444 / YCbCr444 / YUV422 / YCbCr422, default is RGB888 Examples: ---------- >>> kp.dump_image(image_data,out_path,fmt='bin') """ if isinstance(image, str): image = load_image(image=image) assert isinstance(image, np.ndarray) ## if input is 1 dimension, dump directly if(len(image.shape) == 1): io.pack_image(image=image, file=output, pack_fmt=file_fmt) return ## make sure input dimension more than 2 assert (len(image.shape) >= 2) ## detect input channel, to decide input image format ## hint, if channel = 3, it assume input as RGB888 if (len(image.shape) == 2): source_format = 'L' if (image.shape[2] == 4): source_format = 'RGBA8888' else: source_format = 'RGB888' ## color_convert image = funcs.color_convert(image=image, input_fmt=source_format, output_fmt=image_fmt) ## reorder image_pack = io.reorder_image(image=image, image_fmt=image_fmt, order=order) ## pack_image io.pack_image(image=image_pack, file=output, pack_fmt=file_fmt) return def convert(image, out_fmt='RGB888', source_fmt='RGB888', type=DEFAULT, thread='', **kwargs): """ color convert Parameters ---------- image : np.ndarray Input image. out_fmt : str "rgb888" / "rgba8888" / "nir" / "rgb565" / "yuv" / "ycbcr" / "yuv422" / "yuv420" / "ycbcr422" source_fmt : str "rgb888" / "rgba8888" / "nir" / "rgb565" / "yuv" / "ycbcr" / "yuv422" / "yuv420" / "ycbcr422" type : str 'float' / '520' / '720' / 'IE' Returns ---------- out : np.ndarray Examples ---------- >>> output_image = kp.convert(image=input_image, out_fmt='RGB888', source_fmt='YCbCr422') """ ## if set DEFAULT if type is DEFAULT: type = default['color']['type'] if type.lower() in ['ie']: ie = IE(thread=thread) image = ie.color(image=image, input_fmt=source_fmt, output_fmt=out_fmt) else: # float, 520, 720 image = funcs.color_convert(image=image, input_fmt=source_fmt, output_fmt=out_fmt) return image def get_crop_range(image, box, align_w_to_4=DEFAULT, adjust_crop_box_by_ar=False, cut_boundary=True, rounding_type=0,**kwargs): """ get exact crop box according different setting Parameters ---------- box: tuple 1x4 array, (x0, y0, x1, y1). align_w_to_4 : bool Crop length in w direction align to 4 or not, default False. adjust_crop_box_by_ar: bool According box width and ar(crop_h/crop_w) to adjust bbox height, default False. cut_boundary : bool cut over boundary bbox or not, default True. rounding_type: int 0 -> x0,y0 take floor, x1,y1 take ceil; 1 -> all take rounding. Returns ---------- out : tuple 1x4 array, (x0, y0, x1, y1), new crop box. Examples ---------- >>> image_data = kp.get_crop_range((272,145,461,341), align_w_to_4=True, pad_square_to_4=True) (272, 145, 460, 341) """ assert isinstance(image, np.ndarray) assert image.ndim >= 2 assert isinstance(box, list) | isinstance(box, tuple) assert len(box) == 4 ## if set DEFAULT if align_w_to_4 is DEFAULT: align_w_to_4 = default['crop']['align_w_to_4'] ## rounding box = funcs.rounding_crop_box(box=box,rounding_type=rounding_type) ## calculate ar before align to 4 ar_before_align_w_to_4 = 1.0*( box[3]-box[1] ) / ( box[2]-box[0] ) ## align w to 4 if align_w_to_4: box = funcs.align_crop_box_w_to_4(box=box,w=image.shape[1]) ## adjust crop box by ar if adjust_crop_box_by_ar: box = funcs.adjust_crop_box_by_ar(box=box,ar=ar_before_align_w_to_4) if cut_boundary: w_ori=image.shape[1] h_ori=image.shape[0] x0 = np.clip(box[0],0,w_ori) x1 = np.clip(box[2],0,w_ori) y0 = np.clip(box[1],0,h_ori) y1 = np.clip(box[3],0,h_ori) box = [x0,y0,x1,y1] return [int(box[0]),int(box[1]),int(box[2]),int(box[3])] def crop(image, box, type=DEFAULT, align_w_to_4=DEFAULT, pad_square_to_4=False, rounding_type=1, thread='',**kwargs): """ crop function specific crop range by box Parameters ---------- image : np.ndarray Input image. box : tuble 1x4 array, (x0, y0, x1, y1). type : str 'float' / '520' / '720' / 'IE' align_w_to_4 : bool Crop length in w direction align to 4 or not, default False. pad_square_to_4: bool Pad to square(align 4) or not, default False. rounding_type: int 0 -> x0,y0 take floor, x1,y1 take ceil; 1 -> all take rounding. Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.crop(image_data,(272,145,461,341), align_w_to_4=True) >>> image_data = kp.crop(image_data,(272,145,461,341), pad_square_to_4=True) """ assert isinstance(image, np.ndarray) assert image.ndim >= 2 assert isinstance(box, list) | isinstance(box, tuple) assert len(box) == 4 ## if set DEFAULT if type is DEFAULT: type = default['crop']['type'] if align_w_to_4 is DEFAULT: align_w_to_4 = default['crop']['align_w_to_4'] ## rounding box = funcs.rounding_crop_box(box=box,rounding_type=rounding_type) ## align w to 4 if align_w_to_4: box = funcs.align_crop_box_w_to_4(box=box,w=image.shape[1]) ## pad box to square if pad_square_to_4: box = funcs.pad_crop_box_to_square(box=box) ## crop if type.lower() in ['ie']: ie = IE(thread=thread) image = ie.crop(image=image, box=box) else: ## float, 520, 720 image = funcs.crop(image=image, box=box) return image def crop_center(image, range=None, type=DEFAULT, align_w_to_4=DEFAULT, pad_square_to_4=False, rounding_type=0, thread='',**kwargs): """ crop function center crop by range Parameters ---------- image : np.ndarray Input image range : tuple 1x2 array, (crop_w, crop_h). type : str 'float' / '520' / '720' / 'IE' align_w_to_4 : bool Crop length in w direction align to 4 or not, default False. pad_square_to_4: bool Pad to square(align 4) or not, default False. rounding_type: int 0 -> x0,y0 take floor, x1,y1 take ceil; 1 -> all take rounding. Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.crop_center(image_data,(102,40), align_w_to_4=True) >>> image_data = kp.crop_center(image_data,(102,40), pad_square_to_4=True) """ assert isinstance(image, np.ndarray) assert image.ndim >= 2 assert isinstance(range, list) | isinstance(range, tuple) assert len(range) == 2 ## if set DEFAULT if type is DEFAULT: type = default['crop']['type'] if align_w_to_4 is DEFAULT: align_w_to_4 = default['crop']['align_w_to_4'] ## calcuate crop box box = funcs.calcuate_crop_box_center(image_w=image.shape[1], image_h=image.shape[0], crop_w=range[0], crop_h=range[1]) ## rounding box = funcs.rounding_crop_box(box=box,rounding_type=rounding_type) ## align w to 4 if align_w_to_4: box = funcs.align_crop_box_w_to_4(box=box,w=image.shape[1]) ## pad box to square if pad_square_to_4: box = funcs.pad_crop_box_to_square(box=box) ## crop if type.lower() in ['ie']: ie = IE(thread=thread) image = ie.crop(image=image, box=box) else: ## float, 520, 720 image = funcs.crop(image=image, box=box) return image def crop_corner(image, range=None, type=DEFAULT, align_w_to_4=DEFAULT, pad_square_to_4=False, rounding_type=0, thread='',**kwargs): """ crop function corner crop by range Parameters ---------- image : np.ndarray Input image range : tuple 1x2 array, (crop_w, crop_h). type : str 'float' / '520' / '720' / 'IE' align_w_to_4 : bool Crop length in w direction align to 4 or not, default False. pad_square_to_4: bool Pad to square(align 4) or not, default False. rounding_type: int 0 -> x0,y0 take floor, x1,y1 take ceil; 1 -> all take rounding. Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.crop_corner(image_data,(102,40), align_w_to_4=True) >>> image_data = kp.crop_corner(image_data,(102,40), pad_square_to_4=True) """ assert isinstance(image, np.ndarray) assert image.ndim >= 2 assert isinstance(range, list) | isinstance(range, tuple) assert len(range) == 2 ## if set DEFAULT if type is DEFAULT: type = default['crop']['type'] if align_w_to_4 is DEFAULT: align_w_to_4 = default['crop']['align_w_to_4'] ## calcuate crop box box = funcs.calcuate_crop_box_corner(crop_w=range[0], crop_h=range[1]) ## rounding box = funcs.rounding_crop_box(box=box,rounding_type=rounding_type) ## align w to 4 if align_w_to_4: box = funcs.align_crop_box_w_to_4(box=box,w=image.shape[1]) ## pad box to square if pad_square_to_4: box = funcs.pad_crop_box_to_square(box=box) ## crop if type.lower() in ['ie']: ie = IE(thread=thread) image = ie.crop(image=image, box=box) else: ## float, 520, 720 image = funcs.crop(image=image, box=box) return image def calculate_keep_ratio_size(tar_size, ori_size, type=DEFAULT, pad_mode=None): """ resize function calculate the resize when keep ratio Parameters ---------- tar_size : tuple / list 1x2 array, (tar_size_w, tar_size_h) ori_size : tuple / list 1x2 array, (ori_size_w, ori_size_h) type : str 'float' / '520' / '720' / 'IE' pad_mode : str 'center' / 'corner', if set type = 720, the pad_mode must be given Returns ---------- out : list [resize_w, resize_h] """ ## if set DEFAULT if type is DEFAULT: type = default['resize']['type'] return funcs.calculate_keep_ratio_size(tar_size=tar_size, ori_size=ori_size, platform_type=type, pad_mode=pad_mode) def resize(image, size, keep_ratio=True, zoom=True, type=DEFAULT, return_float=False, pad_mode=None, tile_size=None,**kwargs): """ resize function resize type can be float / bilinear / bilinear_pillow / bilicubic / cv2 as floating type, fixed / 520 / 720 / IE as fixed type. 520 / 720 type has add some function to simulate 520 / 720 behavior. Parameters ---------- image : np.ndarray Input image size: tuple 1x2 array, (input_w, input_h) keep_ratio : bool Keep_ratio or not, default True zoom : bool Enable resize can zoom image or not, default True type : str 'float'='bilinear' / 'bilinear_pillow' / '520' / '720' / 'IE' / 'bilicubic' / 'cv2' / 'fixed' pad_mode : str 'center' / 'corner', if set type = 720 & keep_ratio = True, the pad_mode must be given return_float : bool return resize image as float type or not, default False Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.resize(image_data,size=(56,56),type='fixed',info_out=info) """ assert isinstance(image, np.ndarray) ## if set DEFAULT if type is DEFAULT: type = default['resize']['type'] ori_size = (image.shape[1], image.shape[0]) ## calcuate keep ratio size if keep_ratio: size = funcs.calculate_keep_ratio_size(tar_size=size, ori_size=ori_size, platform_type=type, pad_mode=pad_mode) ## if not allow zoom, return if not zoom: if (size[0] > ori_size[0]) or (size[1] > ori_size[1]): return image ## resize if type.lower() in ['float', 'bilinear']: image = funcs.resize_bilinear_vectorized(image=image, size=size, return_float=return_float) elif type.lower() in ['bilinear_pillow']: image = funcs.resize_bilinear(image=image, size=size) elif type.lower() in ['bicubic']: image = funcs.resize_bicubic(image=image, size=size) elif type.lower() in ['cv2']: image = funcs.resize_cv2(image=image, size=size) elif type.lower() in ['fixed']: image = funcs.resize_fixed(image=image, size=size, platform_type='general') elif type.lower() in ['520', 'fixed_520']: image = funcs.resize_fixed(image=image, size=size, platform_type='520') elif type.lower() in ['720', 'fixed_720']: image = funcs.resize_fixed(image=image, size=size, platform_type='720') elif type.lower() in ['ie']: ie = IE() image = ie.resize(image=image, size=size, tile_size=tile_size) elif type.lower() in ['test']: image = funcs.resize_test(image=image, size=size) elif type.lower() in ['c']: image = funcs.resize_bilinear_c(image=image, size=size) elif type.lower() in ['ie_sim']: image = funcs.resize_IE_sim(image=image, size=size) else: image = funcs.resize_bilinear_vectorized(image=image, size=size, return_float=return_float) return image def calculate_pad_length_center(tar_size, ori_size, type=DEFAULT, **kwargs): """ pad function calculate the padding lehth for pad 2 sides(center) Parameters ---------- tar_size : tuple / list 1x2 array, (tar_size_w, tar_size_h) ori_size : tuple / list 1x2 array, (ori_size_w, ori_size_h) type : str 'float' / '520' / '720' / 'IE' Returns ---------- out : list [pad_l, pad_r, pad_t, pad_b] """ ## if set DEFAULT if type is DEFAULT: type = default['pad']['type'] return funcs.calculate_pad_length_center(tar_size=tar_size, ori_size=ori_size) def calculate_pad_length_corner(tar_size, ori_size, type=DEFAULT, **kwargs): """ pad function calculate the padding lehth for pad 2 sides(corner) Parameters ---------- tar_size : tuple / list 1x2 array, (tar_size_w, tar_size_h) ori_size : tuple / list 1x2 array, (ori_size_w, ori_size_h) type : str 'float' / '520' / '720' / 'IE' Returns ---------- out : list [pad_l, pad_r, pad_t, pad_b] """ ## if set DEFAULT if type is DEFAULT: type = default['pad']['type'] return funcs.calculate_pad_length_corner(tar_size=tar_size, ori_size=ori_size) def pad(image, pad_l=0, pad_r=0, pad_t=0, pad_b=0, pad_val=0, type=DEFAULT, hw_limit=False, thread='',**kwargs): """ pad function specific left, right, top and bottom pad size. Parameters ---------- image : np.ndarray Input image pad_l : int Pad size from left, default 0 pad_r : int Pad size form right, default 0 pad_t : int Pad size from top, default 0 pad_b : int Pad size form bottom, default 0 pad_val : float The value of pad, , default 0 type : str 'float' / '520' / '720' / 'IE' hw_limit : bool turn on the hw limit or not, if true, the max pad length for each side will take 127 for 520 type, 255 for 720 type, default is False Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.pad(image_data,20,40,20,40,-0.5) """ assert isinstance(image, np.ndarray) assert isinstance(pad_l, int) assert isinstance(pad_r, int) assert isinstance(pad_t, int) assert isinstance(pad_b, int) ## if set DEFAULT if type is DEFAULT: type = default['pad']['type'] if type.lower() in ['520']: if pad_l > 127: if hw_limit: pad_l = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_r > 127: if hw_limit: pad_r = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_t > 127: if hw_limit: pad_t = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_b > 127: if hw_limit: pad_b = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") elif type.lower() in ['720']: if pad_l > 255: if hw_limit: pad_l = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_r > 255: if hw_limit: pad_r = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_t > 255: if hw_limit: pad_t = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_b > 255: if hw_limit: pad_b = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") else: ## float, ie pass ## image = funcs.pad(image=image, pad_l=pad_l, pad_r=pad_r, pad_t=pad_t, pad_b=pad_b, pad_val=pad_val) return image def pad_center(image, size, pad_val=0, type=DEFAULT, hw_limit=False, thread='',**kwargs): """ pad function center pad with pad size. Parameters ---------- image : np.ndarray Input image size : tuple, 1x2 array, (padded_size_w, padded_size_h) pad_val : float The value of pad, default is 0 type : str 'float' / '520' / '720' / 'IE' hw_limit : bool turn on the hw limit or not, if true, the max pad length for each side will take 127 for 520 type, 255 for 720 type, default is False Returns: ---------- out : np.ndarray Examples: ---------- >>> image_data = kp.pad_center(image_data,size=(56,56),pad_val=-0.5) """ assert isinstance(image, np.ndarray) assert isinstance(size, list) | isinstance(size, tuple) assert len(size) >= 2 ## if set DEFAULT if type is DEFAULT: type = default['pad']['type'] ## calcuate pad length pad_l,pad_r,pad_t,pad_b = funcs.calculate_pad_length_center(tar_size=size, ori_size=(image.shape[1],image.shape[0])) if type.lower() in ['520']: if pad_l > 127: if hw_limit: pad_l = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_r > 127: if hw_limit: pad_r = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_t > 127: if hw_limit: pad_t = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_b > 127: if hw_limit: pad_b = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") elif type.lower() in ['720']: if pad_l > 255: if hw_limit: pad_l = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_r > 255: if hw_limit: pad_r = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_t > 255: if hw_limit: pad_t = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_b > 255: if hw_limit: pad_b = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") else: ## float, ie pass ## image = funcs.pad(image=image, pad_l=pad_l, pad_r=pad_r, pad_t=pad_t, pad_b=pad_b, pad_val=pad_val) return image def pad_corner(image, size, pad_val=0, type=DEFAULT, hw_limit=False ,thread='',**kwargs): """ pad function corner pad with pad size. Parameters ---------- image : np.ndarray Input image size : tuple 1x2 array, (padded_size_w, padded_size_h) pad_val : float The value of pad, default is 0 type : str 'float' / '520' / '720' / 'IE' hw_limit : bool turn on the hw limit or not, if true, the max pad length for each side will take 127 for 520 type, 255 for 720 type, default is False Returns: ---------- out : np.ndarray Examples: ---------- >>> image_data = kp.pad_corner(image_data,size=(56,56),pad_val=-0.5) """ assert isinstance(image, np.ndarray) assert isinstance(size, list) | isinstance(size, tuple) assert len(size) >= 2 ## if set DEFAULT if type is DEFAULT: type = default['pad']['type'] ## calcuate pad length pad_l,pad_r,pad_t,pad_b = funcs.calculate_pad_length_corner(tar_size=size, ori_size=(image.shape[1],image.shape[0])) if type.lower() in ['520']: if pad_l > 127: if hw_limit: pad_l = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_r > 127: if hw_limit: pad_r = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_t > 127: if hw_limit: pad_t = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") if pad_b > 127: if hw_limit: pad_b = 127 print("Error: Pad value larger than 127 is not supported in inproc_520\n") elif type.lower() in ['720']: if pad_l > 255: if hw_limit: pad_l = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_r > 255: if hw_limit: pad_r = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_t > 255: if hw_limit: pad_t = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") if pad_b > 255: if hw_limit: pad_b = 255 print("Error: Pad value larger than 255 is not supported in inproc_720\n") else: ## float, ie pass ## image = funcs.pad(image=image, pad_l=pad_l, pad_r=pad_r, pad_t=pad_t, pad_b=pad_b, pad_val=pad_val) return image def norm(image,scale=256.,bias=-0.5, thread='',**kwargs): """ norm function x = (x/scale - bias) Parameters ---------- image : np.ndarray Input image scale : float / 1x3 array Default = 256 bias : float / 1x3 array Default = -0.5 Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.norm(image_data) >>> image_data = kp.norm(image_data,bias=[0.485, 0.456, 0.406], scale=[0.229, 0.224, 0.225]) """ assert isinstance(image, np.ndarray) image = funcs.norm(image=image, scale=scale, bias=bias) return image def inproc_520(image,return_float=False,raw_fmt=None,raw_size=None,npu_size=None,crop_box=None,pad_mode=None,resize_size=None,pad_length=None,norm='kneron', gray=False, rotate=0, radix=8, bit_width=8, round_w_to_16=True, NUM_BANK_LINE=32,BANK_ENTRY_CNT=512,MAX_IMG_PREPROC_ROW_NUM=511,MAX_IMG_PREPROC_COL_NUM=256,pad_limit_on=True,**kwargs): """ inproc_520 python simulator Parameters ---------- image : np.ndarray / string Image input, can be image file, bin or hex file return_float : bool If False, return RGBA fix format If True, return RGB float format default = False raw_fmt : string If image is raw file, set the raw fmt raw_size : tuple (src_w, src_h) npu_size : tuple (target_w, target_h) crop_box : tuple (x1, y1, x2, y2), will skip crop if set None pad_mode : int 0: pad 2 sides, 1: pad 1 side, 2: no pad. default = 0 pad_val : int norm : str Norm mode, default = 'kneron' rotate: int 0 / 1(90 degree) / 2(180 degree), default = 0 radix : int Default = 8 bit_width : int Default = 8 round_w_to_16 : bool Default = True gray : bool Default = False pad_limit_on : bool turn on the hw pad limit(up to 255 pre side) or not, default = True(on) Returns ---------- out : np.ndarray Examples ---------- >>> image_data = kp.inproc_520(image_data,npu_size=(56,56),crop_box=(272,145,460,341),pad_mode=1) """ return inproc_520_flow( image=image, return_float=return_float, raw_fmt=raw_fmt, raw_size=raw_size, npu_size=npu_size, crop_box=crop_box, pad_mode=pad_mode, resize_size=resize_size, pad_length=pad_length, norm=norm, gray=gray, rotate=rotate, radix=radix, bit_width=bit_width, round_w_to_16=round_w_to_16, NUM_BANK_LINE=NUM_BANK_LINE, BANK_ENTRY_CNT=BANK_ENTRY_CNT, MAX_IMG_PREPROC_ROW_NUM=MAX_IMG_PREPROC_ROW_NUM, MAX_IMG_PREPROC_COL_NUM=MAX_IMG_PREPROC_COL_NUM) def inproc_720(image,return_float=False,raw_fmt=None,raw_size=None ,npu_size=None, crop_box=None, pad_mode=None, resize_size=None, pad_length=None, matrix=None, bias=None, shift_1_bit=False, sub_128=False, radix=8, pad_limit_on=True,**kwargs): """ inproc_720 python simulator Parameters ---------- image : np.ndarray / string Image input, can be image file, bin or hex file return_float : bool If False, return RGBA fix format If True, return RGB float format default = False raw_fmt : string If image is raw file, set the raw fmt raw_size : tuple (src_w, src_h) npu_size : tuple (target_w, target_h) crop_box : tuple (x1, y1, x2, y2), will skip crop if set None pad_mode : int 0: pad 2 sides, 1: pad 1 side, 2: no pad. default = 0 matrix : list / tuple Matirx for the matrix operator, must be a list/tuple for 9 elements, default = [256,0,0,0,256,0,0,0,256] bias : list / tuple Bias for the matrix operator, must be a list/tuple for 3 elements, default = [0,0,0] shift_1_bit : bool Shift 1 bit for the matrix operator, default = False sub_128 : bool Sub 128 for the matrix operator, default = False radix : int default = 8 pad_limit_on : bool turn on the hw pad limit(up to 255 pre side) or not, default = True(on) Returns ---------- out : np.ndarray Examples ---------- >>> image = './w512xh375_rgb565.raw' >>> image_data = kp.inproc_720(image,raw_fmt='rgb565',raw_size=(512,375),npu_size=(416,416),pad_mode=1) """ return inproc_720_flow( image=image, return_float=return_float, raw_fmt=raw_fmt, raw_size=raw_size, npu_size=npu_size, crop_box=crop_box, pad_mode=pad_mode, resize_size=resize_size, pad_length=pad_length, matrix=matrix, bias=bias, shift_1_bit=shift_1_bit, sub_128=sub_128, radix=radix, pad_limit_on=pad_limit_on) def bit_match(data1, data2, dump_file = None,**kwargs): """ bit_match function check data1 is equal to data2 or not. Parameters ---------- data1: np.ndarray / str Can be array or txt/bin file. data2: np.array / str Can be array or txt/bin file. Returns ---------- out1: bool Is match or not out2: np.array If not match, save the position for mismatched data Examples ---------- >>> result, mismatched = kp.bit_match(data1,data2) """ if isinstance(data1, str): if os.path.splitext(data1)[1] == '.bin': data1 = np.fromfile(data1, dtype='uint8') elif os.path.splitext(data1)[1] == '.txt': data1 = np.loadtxt(data1) assert isinstance(data1, np.ndarray) if isinstance(data2, str): if os.path.splitext(data2)[1] == '.bin': data2 = np.fromfile(data2, dtype='uint8') elif os.path.splitext(data2)[1] == '.txt': data2 = np.loadtxt(data2) assert isinstance(data2, np.ndarray) data1 = data1.reshape((-1,1)) data2 = data2.reshape((-1,1)) if dump_file != None: text_file = open(dump_file, "w") if not(len(data1) == len(data2)): print('error len') if dump_file != None: text_file.write('error len\n') text_file.close() return False, np.zeros((1)) else: ans = abs(data2 - data1) if len(np.where(ans>0)[0]) > 0: print('error') if dump_file != None: text_file.write('error\n') for i in range(len(np.where(ans>0)[0])): j = np.where(ans>0)[0][i] info = 'index: {}, {}, {}\n'.format(j, data1[j],data2[j]) text_file.write(info) text_file.close() return False, np.where(ans>0)[0] else: print('pass') if dump_file != None: text_file.write('pass') text_file.close() return True, np.zeros((1)) def similarity_transform(dst_vec, src_vec, type=DEFAULT): """ Estimate N-D similarity transformation with or without scaling. Set type as float to use python umeyama function. Set type as fx to use C code function. Parameters ---------- src_vec(landmark in fr) : list / tuple / nd.array MxN array for Source coordinates. MxN must = 10 dst_vec(src in fr) : list / tuple / nd.array MxN array for Destination coordinates. MxN must = 10 type : str 'float' / 'fx' Returns ------- out: (2, 3) np.array Examples: ------- >>> landmarks = (294, 185, 365, 169, 324, 199, 310, 252, 362, 243) >>> src_vec = np.array((30.2946, 51.6963, 65.5318, 51.5014, 48.0252, 71.7366, 33.5493, 92.3655, 62.7299, 92.2041)) >>> matrix = kp.similarity_transform(src_vec, landmarks, type='fx') """ assert isinstance(src_vec, list) | isinstance(src_vec, tuple) | isinstance(src_vec, np.ndarray) assert isinstance(dst_vec, list) | isinstance(dst_vec, tuple) | isinstance(dst_vec, np.ndarray) src_size = np.array(src_vec).size dst_size = np.array(dst_vec).size assert src_size == dst_size assert src_size%2 == 0 ## if set DEFAULT if type is DEFAULT: type = default['warpAffine']['type'] ## fx if type.lower() in ['fx']: src_vec = np.array(src_vec).reshape((src_size)).tolist() dst_vec = np.array(dst_vec).reshape((dst_size)).tolist() ret, out = utils.similarity_transform(src_vec, dst_vec) ## float else: src_vec = np.array(src_vec).reshape((src_size//2,2)) dst_vec = np.array(dst_vec).reshape((dst_size//2,2)) out = utils.umeyama(src_vec, dst_vec, True)[0:2,:] return np.array(out).reshape((2,3)) def warpAffine(image, Matrix, warp_size, type=DEFAULT, thread='',**kwargs): """ warpAffine function that using fixed, IE or OpenCV behavior Set type as float to use cv2.warpAffine function. Set type as fx to use C code function. Set type as IE to use IE C model. Parameters ---------- image : np.ndarray Matrix : tuple / list / np.ndarray 2x3 array for [R|T] matrix. warp_size : tuple / list type : str 'float' / 'fx' / '520' / '720' / 'IE' Returns ------- out: np.array Examples: ------- >>> m = kp.similarity_transform(src_vec, landmarks) >>> warp_size = (112,112) >>> image_data = kp.warpAffine(image_data,Matrix=m,warp_size=image_size,type='fx') """ assert isinstance(image, np.ndarray) assert isinstance(warp_size, list) | isinstance(warp_size, tuple) assert len(warp_size) == 2 assert isinstance(Matrix, list) | isinstance(Matrix, tuple) | isinstance(Matrix, np.ndarray) assert np.array(Matrix).size == 6 Matrix = np.array(Matrix).reshape((2,3)) ## if set DEFAULT if type is DEFAULT: type = default['warpAffine']['type'] ## if type.lower() in ['fx','520', '720']: ret, image = utils.warpAffine_so(image=image, Matrix=Matrix, warp_size=warp_size) elif type.lower() in ['ie']: ie = IE(thread=thread) image = ie.dewarping(image=image, matrix=Matrix, dst_size=warp_size) else: ## float import cv2 image = cv2.warpAffine(image, Matrix, (warp_size[0], warp_size[1]), flags=cv2.INTER_LINEAR, borderValue=0.0) return image