Esempio n. 1
0
def adjust_bitmap_n_word_data_margins(bitmap,
                                      word_data,
                                      left_x,
                                      upper_y,
                                      right_x,
                                      lower_y,
                                      fill=(0, 0, 0, 0)):

    # Image
    initial_size = bitmap.size
    margins = [left_x, upper_y, right_x, lower_y]
    expansion_border_width = max(margins)
    # expand image equally in all directions by the largest margin, preparing it for cropping
    bitmap = ImageOps.expand(
        bitmap,
        border=
        expansion_border_width,  # expand it with a border with the width of the largest margin
        fill=fill
    )  # the fill of the border is transparent, i've used transparent black throughout the script
    expanded_size = bitmap.size
    # I won't take the time to explain the arithmetic below
    crop_coordinate_box = (
        expansion_border_width - left_x,  # upperLeftCorner_x
        expansion_border_width - upper_y,  # upperLeftCorner_y
        expanded_size[0] -
        (expansion_border_width - right_x),  # lowerRightCorner_x
        expanded_size[1] - (expansion_border_width - lower_y)
    )  # lowerRightCorner_y
    # crop the image with it's own class method
    bitmap = bitmap.crop(box=crop_coordinate_box)

    bounding_boxes = word_data_2_bounding_boxes(word_data)

    # Bounding Boxes
    bounding_boxes = map(
        lambda bbox:
        (vector_add(bbox[0], (left_x, 0)), vector_add(bbox[1], (left_x, 0))),
        bounding_boxes)
    bounding_boxes = list(
        map(
            lambda bbox:
            (vector_add(bbox[0],
                        (0, upper_y)), vector_add(bbox[1], (0, upper_y))),
            bounding_boxes))

    integrate_bounding_boxes_into_word_data(bounding_boxes, word_data)

    return bitmap, word_data
Esempio n. 2
0
def add_arc_noise(image,
                  n,
                  fill=None,
                  max_width=5,
                  min_length=4,
                  max_length=60):
    w, h = image.size
    noise = PIL.Image.new('RGBA', (w, h), color=(0, 0, 0, 0))
    draw = ImageDraw.Draw(noise)
    for i in range(n):
        origin_point = random_point_on_image((w, h))
        endpoint = vector_add(random_vector__pixels(min_length, max_length),
                              origin_point)
        bbox = (origin_point, endpoint)
        if fill == None:
            draw.arc(bbox,
                     start=randang(),
                     end=randang(),
                     fill=(randcol(), randcol(), randcol(), randcol()))
        else:
            draw.arc(bbox, start=randang(), end=randang(), fill=fill)
    image = PIL.Image.alpha_composite(image, noise)
    return image
Esempio n. 3
0
def string_2_word_sample(string,
                         max_rotation_angle=5,
                         margin__left_x=np.random.randint(-4, 30),
                         margin__upper_y=np.random.randint(-4, 30),
                         margin__right_x=np.random.randint(-4, 30),
                         margin__lower_y=np.random.randint(-4, 30),
                         open_close__factor=random.randint(-3, 1),
                         dilate_erode__factor=random.randint(-1, 1),
                         white_bg=False):
    fnt = random_font()
    max_char_w, max_char_h = fnt['max_char_size']
    font = fnt['font']
    img_w, img_h = 0, max_char_h  # we start with full height and zero width, the width is incremented letter by letter

    # Aquiring position data (letter center points and initial bounding boxes) for the string at hand
    letter_data = []
    for letter in string:
        data_dict = {}
        random_offset = np.random.randint(-6, 10)
        img_w += random_offset
        letter_w, letter_h = font.getsize(letter)
        letter_bbox = (
            (img_w, 0), (img_w + letter_w, letter_h)
        )  # this should include some randomization in the future
        letter_center = (img_w + letter_w / 2, img_h / 2)
        data_dict['char'] = letter
        data_dict['bounding_box'] = letter_bbox
        data_dict['center_point'] = letter_center
        letter_data.append(data_dict)
        img_w += letter_w

    # Creating a canvas to write the letters to
    img = Image.new(
        mode='RGBA',
        size=(img_w, img_h),
        color=(0, 0, 0, 0)  # transparent bg
    )
    img_draw = ImageDraw.Draw(img)

    # writing the characters to canvas
    for char_data in letter_data:
        img_draw.text(
            char_data['bounding_box'][0],
            char_data['char'],
            font=font,
            fill=(0, 0, 0, 255)  # black
        )

    rotation_angle = np.random.random() * max_rotation_angle * [
        -1, 1
    ][np.random.randint(2)]
    og_image_centerpoint = (img_w / 2, img_h / 2)
    # rotate the image
    img = img.rotate(
        angle=rotation_angle,
        center=og_image_centerpoint,
        expand=True,
        resample=PIL.Image.
        BICUBIC  # I looked at nearest, bilinear and bicubic and bicubic looks accurate and sharp, i like it best
    )
    img_w__new, img_h__new = img.size
    new_centerpoint = (img_w__new / 2, img_h__new / 2)  # after rotation
    centerpoints_delta_vector = vector_subtract(new_centerpoint,
                                                og_image_centerpoint)

    # rotating the character centerpoints (positions)
    rotated_centerpoints = map(
        lambda char_data: rotate_point(char_data['center_point'],
                                       og_image_centerpoint, rotation_angle),
        letter_data)
    # aligning the character centerpoints (positions) to the rotated and expanded image
    rotated_centerpoints = map(
        lambda point: vector_add(point, centerpoints_delta_vector),
        rotated_centerpoints)
    # offsettng the character centerpoints (positions) randomly to break uniformity
    rotated_centerpoints = map(
        lambda point: vector_add(point, random_vector__pixels(0, 2)),
        rotated_centerpoints)

    # create new bounding boxes from the new letter centers
    bounding_boxes = list(
        map(
            lambda p: point_2_squareBoundingBox(
                p, (max_char_h / 2) + np.random.randint(-2, 2)
            ),  # square radius is half the max char height plus some random padding (postive or negative)
            rotated_centerpoints))

    # Morphology adjustment (open, close, dilate and erode)
    img = morphology_ops(img,
                         open_close__factor=open_close__factor,
                         dilate_erode__factor=dilate_erode__factor)

    # Margins Adjustment
    img, bounding_boxes = adjust_bitmap_n_bounding_box_margins(img,
                                                               bounding_boxes,
                                                               margin__left_x,
                                                               margin__upper_y,
                                                               margin__right_x,
                                                               margin__lower_y,
                                                               fill=(0, 0, 0,
                                                                     0))

    img = add_line_noise(img,
                         np.random.randint(20, 60),
                         max_width=3,
                         min_length=2,
                         max_length=60)
    img = add_line_noise(img,
                         np.random.randint(2, 20),
                         max_width=6,
                         min_length=2,
                         max_length=500,
                         fill=(0, 0, 0, randcol()))

    # img = add_arc_noise(img, np.random.randint(60, 120), max_width=3, min_length=2, max_length=60)
    # img = add_arc_noise(img, np.random.randint(2, 60), max_width=6, min_length=2, max_length=500, fill=(0, 0, 0, randcol()))

    if white_bg:
        img = add_background(img, fill=(255, 255, 255, 255))
    else:
        bg_noise = noisey_background(bitmap_size=img.size,
                                     steps=12,
                                     noise_saturation=random.uniform(
                                         0.05, 0.93),
                                     noise_brightness=random.uniform(0.7, 1.8),
                                     noise_contrast=random.uniform(0.01, 0.6))

        grain = noiseyRGBBitmap(bitmap_size=img.size,
                                noise_saturation=random.uniform(0.05, 0.93),
                                noise_brightness=random.uniform(0.7, 1.8),
                                noise_contrast=random.uniform(0.01, 0.6),
                                alpha_value=255,
                                noise_size=1)

        img = PIL.Image.alpha_composite(bg_noise, img)
        img = PIL.Image.blend(img, grain, np.random.uniform(0.1, 0.8))

    image = img.convert('RGB')  # remove the alpha channel

    # Blur
    image = image.filter(ImageFilter.GaussianBlur(radius=np.random.randint(3)))

    # Contrast
    contrast = ImageEnhance.Contrast(image)
    image = contrast.enhance(random.uniform(0.2, 1))

    # Brightness
    brightness = ImageEnhance.Brightness(image)
    image = brightness.enhance(random.uniform(0.2, 1))

    # Saturation
    saturation = ImageEnhance.Color(image)
    image = saturation.enhance(random.uniform(0, 1))

    angle = rotation_angle

    return image, bounding_boxes, angle