コード例 #1
0
def change_seal_shape(PIL_page, text_bbox_list, char_bbox_list, split_vertical=False):
    np_seal = np.array(PIL_page, dtype=np.uint8)
    height_seal, width_seal = np_seal.shape

    margin = min(round(random.uniform(0.05, 0.1) * width_seal),
                 round(random.uniform(0.05, 0.1) * height_seal))

    height_bg = height_seal + 4 * margin
    width_bg = width_seal + 4 * margin
    np_background = np.zeros(shape=(height_bg, width_bg), dtype=np.uint8)

    # 确定印章坐标
    x1_seal = 2 * margin
    x2_seal = x1_seal + width_seal
    y1_seal = 2 * margin
    y2_seal = y1_seal + height_seal

    # 一半的概率阴阳印章
    if random.random() < 0.5:
        np_seal = reverse_image_color(np_img=np_seal)
        shadow_seal = True
    else:
        shadow_seal = False

    outline_width = int(margin / 2)

    np_seal, np_outline, text_bbox_list, char_bbox_list = round_corner(np_seal, outline_width, text_bbox_list, char_bbox_list, shadow_seal, split_vertical)

    if random.random() < 0.5 or not shadow_seal:  # 一半概率加边框,若是阳刻印章,则加上边框
        if not shadow_seal:
            np_outline = resize_img_by_opencv(np_outline, obj_size=(width_seal, height_seal))
        h_outline, w_outline = np_outline.shape
        w_margin = int((width_bg - w_outline)/2)
        h_margin = int((height_bg - h_outline)/2)
        np_background[h_margin:h_margin + h_outline, w_margin:w_margin + w_outline] |= np_outline

    PIL_page = Image.fromarray(np_seal)
    np_page, text_bbox_list, char_bbox_list = add_subpage_into_page(
        np_background, PIL_page, text_bbox_list, char_bbox_list, x1_seal, x2_seal, y1_seal, y2_seal
    )
        # PIL_page = Image.fromarray(np_page)
        # draw = ImageDraw.Draw(PIL_page)
        #
        # rect_line_width = int(margin / 2)
        # draw.rectangle([(x1_seal - margin, y1_seal - margin), (x2_seal + margin, y2_seal + margin)],
        #                fill=None, outline="white", width=rect_line_width)
        # np_page = np.array(PIL_page, dtype=np.uint8)

    np_page = reverse_image_color(np_img=np_page)
    PIL_page = Image.fromarray(np_page)

    return PIL_page, text_bbox_list, char_bbox_list
コード例 #2
0
def create_two_text_line(shape=(64, 1280), text_type="horizontal", edges=False):
    """训练双行文本的切分,既需要生成双行数据,也需要生成单行数据(不切分的情况)"""

    text_type = check_text_type(text_type)
    check_text_line_shape(shape, text_type)
    text_h, text_w = shape

    # 生成黑色背景
    np_text = np.zeros(shape=(text_h, text_w), dtype=np.uint8)

    # 随机确定是否画边框线
    if edges:
        np_text, margin_w, margin_h = draw_edges_around_text(np_text, text_type, line_type="double")
    else:
        margin_w, margin_h = 0, 0

    # 横向排列
    if text_type == "h":
        # 随机决定字符间距占行距的比例
        char_spacing = (random.uniform(0.0, 0.05), random.uniform(0.0, 0.2))  # (高方向, 宽方向)

        y1, y2 = margin_h, text_h - 1 - margin_h
        x = margin_w
        length = text_w - 2 * margin_w
        if random.random() < 0.7:
            # 生成两行汉字
            _, text1_bbox, text2_bbox, split_pos = generate_two_rows_chars(x, y1, y2, length, np_text, char_spacing)
        else:
            # 生成单行汉字
            _, text_bbox, _, _ = generate_one_row_chars(x, y1, y2, length, np_text, char_spacing)
            split_pos = [text_bbox[1], text_bbox[3]]

    # 纵向排列
    else:
        # 随机决定字符间距占列距的比例
        char_spacing = (random.uniform(0.0, 0.2), random.uniform(0.0, 0.05))  # (高方向, 宽方向)

        x1, x2 = margin_w, text_w - 1 - margin_w
        y = margin_h
        length = text_h - 2 * margin_h
        if random.random() < 0.7:
            # 生成两列汉字
            _, text1_bbox, text2_bbox, split_pos = generate_two_cols_chars(x1, x2, y, length, np_text, char_spacing)
        else:
            # 生成单列汉字
            _, text_bbox, _, _ = generate_one_col_chars(x1, x2, y, length, np_text, char_spacing)
            split_pos = [text_bbox[0], text_bbox[2]]

    np_text = reverse_image_color(np_img=np_text)
    PIL_text = Image.fromarray(np_text)

    # print(chinese_char_and_box_list)
    # print(len(chinese_char_and_box_list))
    # PIL_text.show()
    return PIL_text, split_pos
コード例 #3
0
def add_subpage_into_page(np_page, PIL_subpage, text_bbox_list, char_bbox_list, x1, x2, y1, y2, cover=False):
    np_subpage = np.array(PIL_subpage, dtype=np.uint8)
    np_subpage = reverse_image_color(np_img=np_subpage)
    if cover:  # 完全覆盖
        np_page[y1:y2, x1:x2] = np_subpage
    else:
        np_page[y1:y2, x1:x2] |= np_subpage

    bbox_list_list = [text_bbox_list, char_bbox_list]

    for bbox_list in bbox_list_list:
        for bbox in bbox_list:
            bbox[0] += x1
            bbox[1] += y1
            bbox[2] += x1
            bbox[3] += y1

    return np_page, text_bbox_list, char_bbox_list
コード例 #4
0
def create_mix_text_line(shape=(64, 1280), text_type="horizontal", edges=False):
    text_type = check_text_type(text_type)
    check_text_line_shape(shape, text_type)
    text_h, text_w = shape

    # 生成黑色背景
    np_text = np.zeros(shape=(text_h, text_w), dtype=np.uint8)

    # 随机确定是否画边框线
    if edges:
        np_text, margin_w, margin_h = draw_edges_around_text(np_text, text_type, line_type="mix")
    else:
        margin_w, margin_h = 0, 0

    # 横向排列
    if text_type == "h":
        # 随机决定字符间距占行距的比例
        char_spacing = (random.uniform(0.0, 0.05), random.uniform(0.0, 0.2))  # (高方向, 宽方向)

        # 生成单双行
        y1, y2 = margin_h, text_h - 1 - margin_h
        x = margin_w
        length = text_w - 2 * margin_w
        _, text_bbox_list, split_pos = generate_mix_rows_chars(x, y1, y2, length, np_text, char_spacing)

    # 纵向排列
    else:
        # 随机决定字符间距占列距的比例
        char_spacing = (random.uniform(0.0, 0.2), random.uniform(0.0, 0.05))  # (高方向, 宽方向)

        # 生成单双列
        x1, x2 = margin_w, text_w - 1 - margin_w
        y = margin_h
        length = text_h - 2 * margin_h
        _, text_bbox_list, split_pos = generate_mix_cols_chars(x1, x2, y, length, np_text, char_spacing)

    np_text = reverse_image_color(np_img=np_text)
    PIL_text = Image.fromarray(np_text)

    # print(chinese_char_and_box_list)
    # print(len(chinese_char_and_box_list))
    # PIL_text.show()

    return PIL_text, text_bbox_list, split_pos
コード例 #5
0
def round_corner(np_seal, line_width, text_bbox_list, char_bbox_list, shadow_seal, split_vertical=False):
    circle_d = min(np_seal.shape[0], np_seal.shape[1])  # 圆的直径

    # 画实心圆,用于遮挡印章
    np_circle = np.zeros(shape=(circle_d, circle_d), dtype=np.uint8)
    PIL_circle = Image.fromarray(np_circle)
    draw = ImageDraw.Draw(PIL_circle)
    draw.ellipse((0, 0, PIL_circle.size[0], PIL_circle.size[1]), fill="white", outline="white", width=line_width)
    np_circle = np.array(PIL_circle, dtype=np.uint8)

    # 画空心圆,用于边框
    np_corner = np.zeros(shape=(circle_d, circle_d), dtype=np.uint8)
    PIL_corner = Image.fromarray(np_corner)
    draw = ImageDraw.Draw(PIL_corner)
    draw.ellipse((0, 0, PIL_corner.size[0], PIL_corner.size[1]), fill=None, outline="white", width=line_width)
    np_corner = np.array(PIL_corner, dtype=np.uint8)

    # 画矩形边框
    np_outline = np.zeros(shape=(np_seal.shape[0], np_seal.shape[1]), dtype=np.uint8)
    PIL_outline = Image.fromarray(np_outline)
    draw = ImageDraw.Draw(PIL_outline)
    draw.rectangle((0, 0, PIL_outline.size[0], PIL_outline.size[1]), fill=None, outline="white", width=line_width)
    np_outline = np.array(PIL_outline, dtype=np.uint8)

    change_size_to_round = False
    change_shape_to_round = False
    if random.random() < 1/3 or split_vertical:  # 矩形切角(若有半阴半阳,则只做矩形)
        cut_corner = (0.15, 0.2)
    else:  # 圆形或椭圆形印章
        if random.random() < 0.5:
            cut_corner = (0.3, 0.5)
        else:
            cut_corner = (0.5, 0.5)
        if random.random() < 1/3:
            change_shape_to_round = True
        elif random.random() < 0.5 :
            change_size_to_round = True

    if change_size_to_round:
        seal_reshape = 0.8

        round_background = np.zeros(shape=np_seal.shape, dtype=np.uint8)
        new_width = int(np_seal.shape[1] * seal_reshape)
        new_height = int(np_seal.shape[0] * seal_reshape)

        np_seal = resize_img_by_opencv(np_seal, obj_size=(new_width, new_height))

        bbox_list_list = [text_bbox_list, char_bbox_list]
        for bbox_list in bbox_list_list:
            for bbox in bbox_list:
                bbox[0] *= seal_reshape
                bbox[1] *= seal_reshape
                bbox[2] *= seal_reshape
                bbox[3] *= seal_reshape

        x1_round_seal = int((round_background.shape[1] - new_width) / 2)
        x2_round_seal = x1_round_seal + new_width
        y1_round_seal = int((round_background.shape[0] - new_height) / 2)
        y2_round_seal = y1_round_seal + new_height

        if shadow_seal:
            np_seal = reverse_image_color(np_seal)

        # 把seal缩小后加入新背景(白变黑)
        PIL_seal = Image.fromarray(np_seal)
        np_seal, text_bbox_list, char_bbox_list = add_subpage_into_page(
            round_background, PIL_seal, text_bbox_list, char_bbox_list, x1_round_seal, x2_round_seal, y1_round_seal, y2_round_seal
        )

        if not shadow_seal:
            np_seal = reverse_image_color(np_seal)

    # 切出四个弧度角
    for x in (0, circle_d):
        for y in (0, circle_d):
            corner_x = random.randint(int(circle_d * cut_corner[0]), int(circle_d * cut_corner[1]))
            corner_y = random.randint(int(circle_d * cut_corner[0]), int(circle_d * cut_corner[1]))
            x1_in_seal = 1
            y1_in_seal = 1
            if x == 0:
                x1 = x
                x2 = x + corner_x
                x1_in_seal = 0
            else:
                x1 = x - corner_x
                x2 = x
            if y == 0:
                y1 = y
                y2 = y + corner_y
                y1_in_seal = 0
            else:
                y1 = y - corner_y
                y2 = y

            np_corner_circle = np_circle[y1:y2, x1:x2]
            left, right, top, low = find_min_bound_box(np_corner_circle)
            np_corner_circle = np_corner_circle[top:low + 1, left:right + 1]
            np_corner_circle = reverse_image_color(np_corner_circle)  # 留下的部分变为白色,即圆弧以外的部分

            if x1_in_seal != 0:
                x1_in_seal = np_seal.shape[1] - np_corner_circle.shape[1]
            if y1_in_seal != 0:
                y1_in_seal = np_seal.shape[0] - np_corner_circle.shape[0]
            if change_shape_to_round:
                np_seal = follow_the_shape(np_corner_circle, np_seal,
                                           x1_in_seal, x1_in_seal+np_corner_circle.shape[1],
                                           y1_in_seal, y1_in_seal+np_corner_circle.shape[0])

            np_seal[y1_in_seal:y1_in_seal+np_corner_circle.shape[0], x1_in_seal:x1_in_seal+np_corner_circle.shape[1]] |= np_corner_circle

            np_corner_line = np_corner[y1:y2, x1:x2]
            left, right, top, low = find_min_bound_box(np_corner_line)
            # if x1_in_seal != 0:
            #     x1_in_seal += line_width * 4
            # if y1_in_seal != 0:
            #     y1_in_seal += line_width * 4
            np_corner_line = np_corner_line[top:low + 1, left:right + 1]
            np_outline[y1_in_seal:y1_in_seal+np_corner_circle.shape[0],
                        x1_in_seal:x1_in_seal+np_corner_circle.shape[1]] = np_corner_line

    np_outline = resize_img_by_opencv(np_outline, obj_size=(np_seal.shape[1] + 4*line_width, np_seal.shape[0] + 4*line_width))

    return np_seal, np_outline, text_bbox_list, char_bbox_list
コード例 #6
0
def create_book_page_with_img(shape=(960, 540), text_type="horizontal"):
    text_type = check_text_type(text_type)

    # 黑色背景书页
    np_page = np.zeros(shape=shape, dtype=np.uint8)
    page_height, page_width = shape

    # 随机确定是否画边框线及行线
    draw = None
    if random.random() < 0.7:
        PIL_page = Image.fromarray(np_page)
        draw = ImageDraw.Draw(PIL_page)

    # 随机确定书页边框
    margin_w = round(random.uniform(0.01, 0.05) * page_width)
    margin_h = round(random.uniform(0.01, 0.05) * page_height)
    margin_line_thickness = random.randint(2, 6)
    line_thickness = round(margin_line_thickness / 2)
    if draw is not None:
        # 点的坐标格式为(x, y),不是(y, x)
        draw.rectangle(
            [(margin_w, margin_h),
             (page_width - 1 - margin_w, page_height - 1 - margin_h)],
            fill=None,
            outline="white",
            width=margin_line_thickness)

    # 记录下文本行的bounding-box
    text_bbox_records_list = []
    head_tail_list = []

    if text_type == "h":  # 横向排列

        # 随机确定文本的行数
        rows_num = random.randint(6, 10)
        row_h = (page_height - 2 * margin_h) / rows_num

        # y-coordinate划分行
        ys = [margin_h + round(i * row_h)
              for i in range(rows_num)] + [page_height - 1 - margin_h]

        # 画行线,第一条线和最后一条线是边框线,不需要画
        if draw is not None:
            for y in ys[1:-1]:
                draw.line([(margin_w, y), (page_width - 1 - margin_w, y)],
                          fill="white",
                          width=line_thickness)
            np_page = np.array(PIL_page, dtype=np.uint8)

        # 随机决定字符间距占行距的比例
        char_spacing = (random.uniform(0.02, 0.15), random.uniform(0.0, 0.2)
                        )  # (高方向, 宽方向)

        # 逐行生成汉字
        for i in range(len(ys) - 1):
            y1, y2 = ys[i] + 1, ys[i + 1] - 1
            x = margin_w + int(
                random.uniform(1.0, 1.5) * margin_line_thickness)
            row_length = page_width - x - margin_w
            if random.random() < 0.3:
                row_length = int(random.uniform(0.2, 1) * row_length)
                if draw is not None:
                    draw.line([(x, y1), (x, y2)],
                              fill="white",
                              width=line_thickness)
            _, text_bbox_list, _ = generate_mix_rows_chars(x,
                                                           y1,
                                                           y2,
                                                           row_length,
                                                           np_page,
                                                           char_spacing,
                                                           use_img=True)
            text_bbox_records_list.extend(text_bbox_list)
            if len(text_bbox_list) == 2:
                head_tail_list.extend([
                    (text_bbox_list[0][1], text_bbox_list[0][3]),
                    (text_bbox_list[1][1], text_bbox_list[1][3])
                ])
            else:
                min_y1 = min([_y1 for _x1, _y1, _x2, _y2 in text_bbox_list])
                max_y2 = max([_y2 for _x1, _y1, _x2, _y2 in text_bbox_list])
                head_tail_list.append((min_y1, max_y2))

        # 获取行之间的划分位置
        split_pos = [
            margin_h,
        ]
        for i in range(len(head_tail_list) - 1):
            y_cent = (head_tail_list[i][1] + head_tail_list[i + 1][0]) // 2
            split_pos.append(y_cent)
        split_pos.append(page_height - 1 - margin_h)

    else:  # 纵向排列

        # 随机决定文本的列数
        # cols_num = random.randint(6, 10)
        # cols_num = random.randint(18, 23)
        # cols_num = random.randint(14, 19)
        cols_num = random.randint(16, 20)
        col_w = (page_width - 2 * margin_w) / cols_num

        # x-coordinate划分列
        xs = [margin_w + round(i * col_w) for i in range(cols_num)] + [
            page_width - 1 - margin_w,
        ]

        # 画列线,第一条线和最后一条线是边缘线,不需要画
        if draw is not None:
            for x in xs[1:-1]:
                draw.line([(x, margin_h), (x, page_height - 1 - margin_h)],
                          fill="white",
                          width=line_thickness)
            np_page = np.array(PIL_page, dtype=np.uint8)

        # 随机决定字符间距占列距的比例
        char_spacing = (random.uniform(0.0, 0.2), random.uniform(0.02, 0.15)
                        )  # (高方向, 宽方向)

        ys = [0 for i in range(len(xs))]
        col_lengths = [0 for i in range(len(xs))]

        for i in range(len(xs) - 1, 0, -1):
            x1, x2 = xs[i - 1] + 1, xs[i] - 1
            ys[i] = margin_h + int(
                random.uniform(0.0, 1) * margin_line_thickness)
            col_lengths[i] = page_height - ys[i] - margin_h
            if random.random() < 0.3:
                col_lengths[i] = int(random.uniform(0.2, 1) * col_lengths[i])
                yy = col_lengths[i] + margin_h + margin_line_thickness
                if draw is not None:
                    draw.line([(x1, yy), (x2, yy)],
                              fill="white",
                              width=line_thickness)
                    np_page = np.array(PIL_page, dtype=np.uint8)
                    # Image.fromarray(np_page).show()

        # 逐列生成汉字,最右边为第一列
        for i in range(len(xs) - 1, 0, -1):
            x1, x2 = xs[i - 1] + 1, xs[i] - 1
            y = ys[i]
            col_length = col_lengths[i]
            _, text_bbox_list, _ = generate_mix_cols_chars(x1,
                                                           x2,
                                                           y,
                                                           col_length,
                                                           np_page,
                                                           char_spacing,
                                                           use_img=True)
            text_bbox_records_list.extend(text_bbox_list)

            if len(text_bbox_list) == 2:
                head_tail_list.extend([
                    (text_bbox_list[1][0], text_bbox_list[1][2]),
                    (text_bbox_list[0][0], text_bbox_list[0][2])
                ])
            else:
                min_x1 = min([_x1 for _x1, _y1, _x2, _y2 in text_bbox_list])
                max_x2 = max([_x2 for _x1, _y1, _x2, _y2 in text_bbox_list])
                head_tail_list.append((min_x1, max_x2))

        head_tail_list.reverse()  # 由于最右边为第一列,需要反转

        # 获取列之间的划分位置
        split_pos = [
            margin_w,
        ]
        for i in range(len(head_tail_list) - 1):
            x_cent = (head_tail_list[i][1] + head_tail_list[i + 1][0]) // 2
            split_pos.append(x_cent)
        split_pos.append(page_width - 1 - margin_w)

    # 将黑底白字转换为白底黑字
    np_page = reverse_image_color(np_img=np_page)
    PIL_page = Image.fromarray(np_page)

    # print(text_bbox_list)
    # print(len(text_bbox_list))
    # PIL_page.show()

    return PIL_page, text_bbox_records_list, split_pos