def apply_quasicrystal(self): """ Create a background with quasicrystal (https://en.wikipedia.org/wiki/Quasicrystal) """ width = Random.random_int(self._width_range[0], self._width_range[1]) height = Random.random_int(self._height_range[0], self._height_range[1]) image = np.zeros((height, width, 3), dtype=np.uint8) rotation_count = Random.random_int(10, 20) y_vec = np.arange(start=0, stop=width, dtype=np.float32) x_vec = np.arange(start=0, stop=height, dtype=np.float32) grid = np.meshgrid(y_vec, x_vec) y_matrix = np.reshape(np.asarray(grid[0]) / (width - 1) * 4 * math.pi - 2 * math.pi, (height, width, 1)) x_matrix = np.reshape(np.asarray(grid[1]) / (height - 1) * 4 * math.pi - 2 * math.pi, (height, width, 1)) y_matrix_3d = np.repeat(y_matrix, rotation_count, axis=-1) x_matrix_3d = np.repeat(x_matrix, rotation_count, axis=-1) rotation_vec = np.arange(start=0, stop=rotation_count, dtype=np.float32) rotation_vec = np.reshape(rotation_vec, newshape=(1, 1, rotation_count)) for k in range(3): frequency = Random.random_float(0, 1) * 30 + 20 # frequency phase = Random.random_float(0, 1) * 2 * math.pi # phase r = np.hypot(x_matrix_3d, y_matrix_3d) a = np.arctan2(y_matrix_3d, x_matrix_3d) + (rotation_vec * math.pi * 2.0 / rotation_count) z = np.cos(r * np.sin(a) * frequency + phase) z = np.sum(z, axis=-1) c = 255 - np.round(255 * z / rotation_count) c = np.asarray(c, dtype=np.uint8) image[:, :, k] = c return image
def logic(self, block_group, next_block) -> bool: gbl = block_group.group_box[0] gbt = block_group.group_box[1] gbr = block_group.group_box[2] gbb = block_group.group_box[3] if gbr - next_block.outer_width < gbl or gbb - next_block.outer_height < gbt: return False x = Random.random_int(gbl, gbr - next_block.outer_width, seed=self.seed) y = Random.random_int(gbt, gbb - next_block.outer_height, seed=self.seed) next_block.locate_by_outter(x, y) is_out = self.check_is_out(block_group=block_group, block=next_block) has_overlap = self.check_has_overlap(block_group=block_group, block=next_block) is_ok = not is_out and not has_overlap if is_ok: return True return False
def gen_one_box(): l = Random.random_int(0, w) t = Random.random_int(0, h) r = int(l + min_w * Random.random_float(1, 3)) b = int(t + min_h * Random.random_float(1, 2)) box = (l, t, r, b) if r > w or b > h: return None return box
def __init__(self): self.COLOR_TRANSPARENT = (0, 0, 0, 0) self.COLOR_HALF_TRANSPARENT = (0, 0, 0, 55) self.COLOR_RED = (255, 0, 0, 255) self.COLOR_GREEN = (0, 255, 0, 255) self.COLOR_BLUE = (0, 0, 255, 255) self.COLOR_BLACK = (0, 0, 0, 255) self.COLOR_WHITE = (255, 255, 255, 255) self.GET_RANDOM_COLOR = lambda: ( Random.random_int(0, 255), Random.random_int(0, 255), Random.random_int(0, 255), 255)
def auto_gen_next_img(self, width, height, strategy, bg_img, block_list): """ 自动生成下一个文本贴图 :return: """ from service import text_provider text = "".join(text_provider.gen.__next__()) fp = self.next_font_path() if isinstance(strategy, HorizontalStrategy): orientation = TYPE_ORIENTATION_VERTICAL elif isinstance(strategy, VerticalStrategy): orientation = TYPE_ORIENTATION_HORIZONTAL elif isinstance(strategy, HorizontalFlowStrategy): orientation = TYPE_ORIENTATION_HORIZONTAL elif isinstance(strategy, VerticalFlowStrategy): orientation = TYPE_ORIENTATION_VERTICAL elif isinstance(strategy, CustomizationStrategy1): if block_list: orientation = TYPE_ORIENTATION_HORIZONTAL else: orientation = TYPE_ORIENTATION_VERTICAL else: orientation = Random.random_choice_list([ TYPE_ORIENTATION_VERTICAL, TYPE_ORIENTATION_HORIZONTAL, TYPE_ORIENTATION_HORIZONTAL ]) v = min(width, height) # 设置字体大小 font_size = Random.random_int(v // 20, v // 10) font_size = self.font_min_size if font_size < self.font_min_size else font_size # 剔除不存在的文字 text = "".join(filter(lambda c: font_tool.check(c, font_path=fp), text)) if len(text) >= 2: # 生成文本图片 align = Random.random_choice_list( [TYPE_ALIGN_MODEL_B, TYPE_ALIGN_MODEL_T, TYPE_ALIGN_MODEL_C]) text_img = self.gen_text_img(text, font_size=font_size, border_width=self.char_border_width, border_color=self.char_border_color, color=self.get_fontcolor(bg_img), orientation=orientation, align_mode=align, font_path=fp) return text_img
def get_generator(self, bg_img_conf): """ generator :param bg_img_conf: :return: """ gen_probability = [] all_generator = [] for item in bg_img_conf: t = item['type'] probability = float(item['probability']) if t == 'from_dir': bg_img_dir = item['dir'] img_path_list = [os.path.join(bg_img_dir, img) for img in os.listdir(bg_img_dir) if ('.DS' not in img)] dir_img_gen = DirImageGen(img_path_list) all_generator.append(dir_img_gen) elif t == 'from_generate': width_range = eval(item['width_range']) height_range = eval(item['height_range']) gauss_img_gen = GenrateGaussImage(width_range=width_range, height_range=height_range) all_generator.append(gauss_img_gen) gen_probability.append(probability) value_list = gen_probability len_gen = len(all_generator) while True: index = Random.random_choice(list(value_list)) if index <= len_gen and all_generator[index]: np_img = all_generator[index].get_next.__next__() np_img = np_img[..., ::-1] img = Image.fromarray(np_img, mode='RGB') yield img
def get_generator(self, corpus_list): _all_generator = [] gen_probability_list = [] for corpus in corpus_list: gen_probability_list.append(float(corpus['probability'])) with open(corpus['path'], 'r') as fp: if corpus['type'] == 'line': data = fp.readlines() data = self._replace_useless(data) generator = RandomCorpusGen(data, eval(corpus['len_range'])) _all_generator.append(generator) elif corpus['type'] == 'word': data = fp.readline() data = self._replace_useless(data) generator = RandomCharacterGen(list(data), eval(corpus['len_range'])) _all_generator.append(generator) while True: index = Random.random_choice(gen_probability_list) if _all_generator[index]: yield _all_generator[index].get_next.__next__()
def get_fontcolor(self, bg_img): """ get font color by mean :param bg_img: :return: """ char_common_color_list = self.char_common_color_list if Random.random_float( 0, 1 ) <= self.use_char_common_color_probability and char_common_color_list: return eval(Random.random_choice_list(char_common_color_list)) else: image = np.asarray(bg_img) lab_image = cv2.cvtColor(image, cv2.COLOR_RGB2Lab) bg = lab_image[:, :, 0] l_mean = np.mean(bg) new_l = Random.random_int( 0, 127 - 80) if l_mean > 127 else Random.random_int(127 + 80, 255) new_a = Random.random_int(0, 255) new_b = Random.random_int(0, 255) lab_rgb = np.asarray([[[new_l, new_a, new_b]]], np.uint8) rbg = cv2.cvtColor(lab_rgb, cv2.COLOR_Lab2RGB) r = rbg[0, 0, 0] g = rbg[0, 0, 1] b = rbg[0, 0, 2] return (r, g, b, 255)
def __init__(self, font_file_dir, text_img_output_dir, text_img_info_output_dir, font_min_size, use_char_common_color_probability, char_common_color_list, char_border_width, char_border_color, seed=time.time()): """ 初始化文本图片生成器 :param font_file_dir: 字体文件目录 :param text_img_output_dir: 文本图片输出目录 :param text_img_info_output_dir: 文本图片数据输出目录 :param font_min_size: 文本字体大小的最小值 :param use_char_common_color_probability :param char_common_color_list :param char_border_width: 字符边框的宽度 :param char_border_color: 字符边框的颜色 :param seed: """ os.makedirs(text_img_output_dir, exist_ok=True) os.makedirs(text_img_info_output_dir, exist_ok=True) if not seed: seed = time.time() self.font_file_list = list_font_path(font_file_dir) self._font_index = 0 self.text_img_output_dir = text_img_output_dir self.text_img_info_output_dir = text_img_info_output_dir self.font_min_size = font_min_size self.use_char_common_color_probability = use_char_common_color_probability self.char_common_color_list = char_common_color_list self.char_border_width = char_border_width self.char_border_color = char_border_color Random.shuffle(self.font_file_list, seed)
def __init__(self, font_file_dir, text_img_output_dir, text_img_info_output_dir, font_min_size, font_max_size, use_char_common_color_probability, char_common_color_list, char_border_width, char_border_color, auto_padding_to_ratio=0.0, seed=time.time()): """ 初始化文本图片生成器 :param font_file_dir: 字体文件目录 :param text_img_output_dir: 文本图片输出目录 :param text_img_info_output_dir: 文本图片数据输出目录 :param font_min_size: 文本字体大小的最小值 :param use_char_common_color_probability :param char_common_color_list :param char_border_width: 字符边框的宽度 :param char_border_color: 字符边框的颜色 :param auto_padding_to_ratio: 自动padding到指定的比例 <=0 代表不自动padding (水平排布是 w/h 竖直排布是 h/w) :param seed: """ os.makedirs(text_img_output_dir, exist_ok=True) os.makedirs(text_img_info_output_dir, exist_ok=True) if not seed: seed = time.time() self.font_file_list = list_font_path(font_file_dir) self._font_index = 0 self.text_img_output_dir = text_img_output_dir self.text_img_info_output_dir = text_img_info_output_dir self.font_min_size = font_min_size self.font_max_size = font_max_size self.use_char_common_color_probability = use_char_common_color_probability self.char_common_color_list = char_common_color_list self.char_border_width = char_border_width self.char_border_color = eval(char_border_color) if type(char_border_color) is str else char_border_color self.auto_padding_to_ratio = auto_padding_to_ratio Random.shuffle(self.font_file_list, seed)
def pick(strategy_list) -> Strategy: """ 选择一个策略 :return: """ strategy_values = [] for strategy in strategy_list: strategy_values.append(float(strategy['probability'])) index = Random.random_choice(list(strategy_values)) strategy_name = strategy_list[index]['name'] strategy = get_strategy_by_name(strategy_name) log.info("pick strategy: {strategy}".format(strategy=strategy_name)) return strategy
def _gen_block(self, strategy: Strategy): """ 生成一个block :return: """ rotate_angle = Random.random_int(self.rotate_angle_range[0], self.rotate_angle_range[1]) block = self.next_block_generator.auto_gen_next_img_block(width=self.width, height=self.height, strategy=strategy, bg_img=self.bg_img, block_list=self.block_list, rotate_angle=rotate_angle, ) return block
def _get_next_batch(self): """ :return: """ seek = 0 while True: batch_size = Random.random_int(self._len_range[0], self._len_range[1]) if len(self._character_seq) - seek < batch_size: for i in range(len(self._character_seq) - seek): self._character_seq.insert(0, self._character_seq[-1]) del self._character_seq[-1] random.shuffle(self._character_seq) seek = 0 ret_character_seq = self._character_seq[seek:seek + batch_size] len_seq = len(ret_character_seq) if random.randint(0, 6) >= 4 and 7 < len_seq < 13: ret_character_seq.insert(random.randint(2, len_seq - 1), ' ') yield ''.join(ret_character_seq) seek += batch_size
def apply_gauss_blur(self, ks=None): """ :param ks: guass kernal window size :return: """ bg_high = Random.random_float(220, 255) bg_low = bg_high - Random.random_float(1, 60) width = Random.random_int(self._width_range[0], self._width_range[1]) height = Random.random_int(self._height_range[0], self._height_range[1]) img = np.random.randint(bg_low, bg_high, (height, width)).astype(np.uint8) if ks is None: ks = [7, 9, 11, 13] k_size = Random.random_choice_list(ks) sigmas = [0, 1, 2, 3, 4, 5, 6, 7] sigma = 0 if k_size <= 3: sigma = Random.random_choice_list(sigmas) img = cv2.GaussianBlur(img, (k_size, k_size), sigma) return img
def _random_crop(self, char_str): seek = Random.random_int(0, len(char_str) - self._len_range[1]) char_str = char_str[seek:seek + self._len_range[1]] return char_str
def _get_random(self): while True: seek = Random.random_int(0, self._corpus_length - 1) yield self._character_seq[seek]