Esempio n. 1
0
def rescale(image, xscale=(0.5,1.5), yscale=(0.5,1.5), fill_color=None, p=1):
    """Apply scaling on the x or y axis to input data.
    
    Args:
        image: a PIL instance.
        xscale: if int or float, width expansion and contraction, xscale should be positive.
                if tuple or list, randomly picked in the interval `[xscale[0], xscale[1])`.
        yscale: if int or float, height expansion and contraction, yscale should be positive.
                if tuple or list, randomly picked in the interval `[yscale[0], yscale[1])`.
        fill_color: int or str or tuple or la.image.RGBMode, rgb color.
        p: probability that the image does this. Default value is 1.
    Return:
        a PIL instance.
    """
    if np.random.uniform()>p:
        return image
    if isinstance(xscale, (list, tuple)):
        xscale = np.random.uniform(xscale[0], xscale[1])
    if isinstance(yscale, (list, tuple)):
        yscale = np.random.uniform(yscale[0], yscale[1])
    fill_color = _fill_color(image, fill_color)
    size = [int(image.size[0]*xscale), int(image.size[1]*yscale)]
    size1 = [min(image.size[0], size[0]), min(image.size[1], size[1])]
    box1 = [int(size[0]/2-size1[0]/2), int(size[1]/2-size1[1]/2)]
    box1 = box1 + [box1[0]+size1[0], box1[1]+size1[1]]
    box2 = [int(image.size[0]/2-size1[0]/2), int(image.size[1]/2-size1[1]/2)]
    box2 = box2 + [box2[0]+size1[0], box2[1]+size1[1]]
    image2 = Image.new(image.mode, image.size, fill_color)
    image2.paste(image.resize(size).crop(box1), box2)
    return image2
Esempio n. 2
0
def mask_box(image, boxes, fill='inner', color=None, p=1):
    """Fill color inside or outside a rectangular area.
    
    Args:
        image: a PIL  instance.
        boxes: box axis with same [[x1,y1,x2,y2],...]
        fill: 'inner' or 'outer', color fill position.
        color: str or tuple or la.image.RGBMode, rgb color, box line color.
        p: probability that the image does this. Default value is 1.
    Returns:
        a PIL  instance.
    """
    if np.random.uniform() > p:
        return image
    if isinstance(boxes[0], int):
        boxes = [boxes]
    color = _fill_color(image, color)
    if fill == 'inner':
        image1 = image.copy()
        for i in boxes:
            image1.paste(
                Image.new(image.mode, (i[2] - i[0], i[3] - i[1]), color=color),
                (i[0], i[1]))
    else:
        image1 = Image.new(image.mode, image.size, color=color)
        for i in boxes:
            image1.paste(image.crop(i), (i[0], i[1]))
    return image1
Esempio n. 3
0
def shear(image, xoffset=(-90, 90), yoffset=None, fill_color=None, p=1):
    """Apply affine shear on the image.
    
    Args:
        image: a PIL instance.
        xoffset: int or list ot tuple, The horizontal degrees, xoffset in [-360,360].
                 if tuple or list, randomly picked in the interval `[xoffset[0], xoffset[1])`
        yoffset: int or list ot tuple, The vertical degrees, yoffset in [-360,360]. 
                 If omitted, both distances are set to the same value.
                 if tuple or list, randomly picked in the interval `[yoffset[0], yoffset[1])`
        fill_color: int or str or tuple or la.image.RGBMode, rgb color. 
        p: probability that the image does this. Default value is 1.
    Returns:
        a PIL instance.
    """
    if np.random.uniform()>p:
        return image
    if isinstance(xoffset, (list, tuple)):
        xoffset = np.random.uniform(xoffset[0], xoffset[1])
    if yoffset is None:
        yoffset = xoffset
    elif isinstance(yoffset, (list, tuple)):
        yoffset = np.random.uniform(yoffset[0], yoffset[1])
    fill_color = _fill_color(image, fill_color)
    return affine(image, angle=(0,0), center=(0.5,0.5), translate=(0, 0), scale=1., 
                  shear=(xoffset, yoffset), fill_color=fill_color, p=1)
Esempio n. 4
0
def translate(image, xoffset=(-0.5,0.5), yoffset=None, fill_color=None, p=1):
    """Returns a translate copy of this image. 
    
    Args:
        image: a PIL instance.
        xoffset: [-1, 1], int or float, width offset.
                 if list or tuple, randomly picked in the interval `[xoffset[0], xoffset[1])`.
        yoffset: [-1, 1], int or float, height offset.
                 if list or tuple, randomly picked in the interval `[yoffset[0], yoffset[1])`.
        fill_color: int or str or tuple or la.image.RGBMode, rgb color.
        p: probability that the image does this. Default value is 1.
    Returns:
        A PIL instance.
    """
    if np.random.uniform()>p:
        return image
    if isinstance(xoffset, (list, tuple)):
        xoffset = np.random.uniform(xoffset[0], xoffset[1])
    if yoffset is None:
        yoffset = xoffset
    elif isinstance(yoffset, (list, tuple)):
        yoffset = np.random.uniform(yoffset[0], yoffset[1])
    xoffset = int(image.size[0]*xoffset)
    yoffset = int(image.size[1]*yoffset)
    fill_color = _fill_color(image, fill_color)
    return rotate(image, angle=0, expand=0, center=None, translate=(xoffset, yoffset), fillcolor=fill_color)
Esempio n. 5
0
def mask(image, size, max_num, random=True, color=None, p=1):
    """Draws a mask.
    
    Args:
        image: a PIL instance.
        size: list or tuple, mask size, [height, width]. if int, transform [size, size].
        max_num: int, max mask number.
                 if tuple or list, randomly picked in the interval `[max_num[0], max_num[1])`.
        random: bool, whether the mask position is random.
        color: str or tuple or la.image.RGBMode, rgb color, mask fill color.
        p: probability that the image does this. Default value is 1.
    returns: 
        a PIL instance.
    """
    if np.random.uniform() > p:
        return image
    if isinstance(max_num, (list, tuple)):
        max_num = int(np.random.uniform(max_num[0], max_num[1]))
    if isinstance(size, (int, float)):
        size = [int(size), int(size)]
    image2 = image.copy()
    draw = ImageDraw.Draw(image2)
    if random:
        for i in range(max_num):
            axis = (np.random.randint(0, image.width - size[1]),
                    np.random.randint(0, image.height - size[0]))
            axis = [axis, (axis[0] + size[1], axis[1] + size[0])]
            color1 = _fill_color(image, color)
            draw.rectangle(axis, fill=color1, width=0)
    else:
        width_num = min(int(image.width / size[1] * 0.6), int(max_num**0.5))
        height_num = min(int(max_num / width_num),
                         int(image.height / size[0] * 0.6))
        width_pix = int((image.width - width_num * size[1]) / (width_num + 1))
        height_pix = int(
            (image.height - height_num * size[0]) / (height_num + 1))
        for i in range(width_num):
            for j in range(height_num):
                axis = [
                    width_pix * (i + 1) + size[1] * i,
                    height_pix * (j + 1) + size[0] * j,
                    width_pix * (i + 1) + size[1] * (i + 1),
                    height_pix * (j + 1) + size[0] * (j + 1)
                ]
                color1 = _fill_color(image, color)
                draw.rectangle(axis, fill=color1, width=0)
    return image2
Esempio n. 6
0
def draw_keypoints(image,
                   keypoints,
                   connectivity=None,
                   point_width=3,
                   line_width=2,
                   point_color=None,
                   line_color=None):
    """Draws Keypoints on given RGB image.
    
    Args:
        image: a PIL instance.
        keypoints: list of shape (num_instances, K, 2) the K keypoints location for each of the N instances,
                   in the format [x, y].
        connectivity: A List of tuple where, each tuple contains pair of keypoints to be connected.
        point_width: Integer denoting radius of keypoint.
        line_width: Integer denoting width of line connecting keypoints.
        point_color: str or tuple or la.image.RGBMode, rgb color, key points color.
        line_color: str or tuple or la.image.RGBMode, rgb color, line color.
    Returns:
        a PIL instance.
    """
    image2 = image.copy()
    draw = ImageDraw.Draw(image2)
    if isinstance(keypoints[0][0], (int, float)):
        keypoints = [keypoints]
    for kpt_id, kpt_inst in enumerate(keypoints):
        for inst_id, kpt in enumerate(kpt_inst):
            x1 = kpt[0] - point_width
            x2 = kpt[0] + point_width
            y1 = kpt[1] - point_width
            y2 = kpt[1] + point_width
            point_color = _fill_color(image, point_color)
            draw.ellipse([x1, y1, x2, y2],
                         fill=point_color,
                         outline=None,
                         width=0)
        if connectivity:
            for connection in connectivity:
                start_pt_x = kpt_inst[connection[0]][0]
                start_pt_y = kpt_inst[connection[0]][1]
                end_pt_x = kpt_inst[connection[1]][0]
                end_pt_y = kpt_inst[connection[1]][1]
                color = _fill_color(image, line_color)
                draw.line(((start_pt_x, start_pt_y), (end_pt_x, end_pt_y)),
                          fill=color,
                          width=line_width)
    return image2
Esempio n. 7
0
def draw_line(image, axis, width=1, color=None):
    """Draws a line.
    
    Args:
        image: a PIL instance.
        axis: Sequence of either 2-tuples like [(x, y), (x, y), ...] or numeric values like [x, y, x, y, ...].
        width: int, the line width, in pixels.
        color: str or tuple or la.image.RGBMode, rgb color, line color.
    returns: 
        a PIL instance.
    """
    image2 = image.copy()
    draw = ImageDraw.Draw(image2)
    axis = list(itertools.chain.from_iterable(axis)) if isinstance(
        axis[0], (list, tuple)) else axis
    for i in range(int(len(axis) / 2 - 1)):
        line = [axis[i * 2], axis[i * 2 + 1], axis[i * 2 + 2], axis[i * 2 + 3]]
        color1 = _fill_color(image, color)
        draw.line(line, fill=color1, width=width)
    return image2
Esempio n. 8
0
def stripe(image, width=4, mode=1, color=None, p=1):
    """vertically and horizontally line apply to image.
    
    Args:
        image: a numpy array.
        width: int, line spacing width.
        mode: 0 is vertically and 1 is horizontally.
        color: int or list, line color.
        p: probability that the image does this. Default value is 1.
    returns: 
        a numpy array.
    """
    if np.random.uniform() > p:
        return image
    image1 = image.copy()
    color = _fill_color(image1, color)
    if mode:
        image1[::width, :] = color
    else:
        image1[:, ::width] = color
    return image1
Esempio n. 9
0
def perspective(image, distortion_scale, fill_color=None, p=1):
    """Performs a random perspective transformation of the given image with a given probability. 

    Args:
        image: a PIL instance.
        distortion_scale: float, argument to control the degree of distortion and ranges from 0 to 1.
        fill_color: int or str or tuple or la.image.RGBMode, rgb color.
        p: probability that the image does this. Default value is 1.
    Returns:
        a PIL instance.
    """
    if np.random.uniform()>p:
        return image
    (width, height) = image.size
    half_height = height // 2
    half_width = width // 2
    topleft = [np.random.randint(0, distortion_scale*half_width+1), 
               np.random.randint(0, distortion_scale*half_height+1)]
    topright = [np.random.randint(width - distortion_scale * half_width- 1, width),
                np.random.randint(0, distortion_scale * half_height + 1)]
    botright = [np.random.randint(width - distortion_scale * half_width - 1, width),
                np.random.randint(height - distortion_scale * half_height - 1, height)]
    botleft = [np.random.randint(0, distortion_scale * half_width + 1),
               np.random.randint(height - distortion_scale * half_height - 1, height)]
    
    startpoints = [[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]]
    endpoints = [topleft, topright, botright, botleft]
    
    a_matrix = np.zeros([2 * len(startpoints), 8])
    for i, (p1, p2) in enumerate(zip(endpoints, startpoints)):
        a_matrix[2 * i, :] = np.array([p1[0], p1[1], 1, 0, 0, 0, -p2[0] * p1[0], -p2[0] * p1[1]])
        a_matrix[2 * i + 1, :] = np.array([0, 0, 0, p1[0], p1[1], 1, -p2[1] * p1[0], -p2[1] * p1[1]])

    b_matrix = np.array(startpoints, dtype=np.float32).flatten()
    coeffs = np.linalg.lstsq(a_matrix, b_matrix, rcond=None)[0].tolist()
    fill_color = _fill_color(image, fill_color)
    return image.transform(image.size, Image.Transform.PERSPECTIVE, coeffs, 
                           Image.Resampling.NEAREST, fillcolor=fill_color)
Esempio n. 10
0
def draw_point(image, points, size=0, color=None):
    """Draws a point.
    
    Args:
        image: a PIL instance.
        points: Sequence of either 2-tuples like [(x, y), (x, y), ...] or numeric values like [x, y, x, y, ...].
        size: point size.
        color: str or tuple or la.image.RGBMode, rgb color, point color.
    returns: 
        a PIL instance.
    """
    image2 = image.copy()
    draw = ImageDraw.Draw(image2)
    point = list(itertools.chain.from_iterable(points)) if isinstance(
        points[0], (list, tuple)) else points
    for i in range(int(len(point) / 2)):
        axis = list(
            itertools.product(
                range(int(point[i * 2] - size), int(point[i * 2] + size + 1)),
                range(int(point[i * 2 + 1] - size),
                      int(point[i * 2 + 1] + size + 1))))
        color1 = _fill_color(image, color)
        draw.point(axis, color1)
    return image2
Esempio n. 11
0
def draw_box(image, boxs, fill_color=None, line_color=None, width=1):
    """Draws a polygon.
    
    The polygon outline consists of straight lines between the given coordinates, 
    plus a straight line between the last and the first coordinate.
    
    Args:
        image: a PIL instance.
        boxs: If it is a single sample, like [(x1, y1), (x2, y2), ...] or like [x1, y1, x2, y2, ...].
              If there are multiple samples, like [[(x1, y1), (x2, y2), ...]] or like [[x1, y1, x2, y2, ...]].
              special, like [(x1, y1), (x2, y2)] or like [x1, y1, x2, y2], draw a rectangle from the top left to the bottom right.
              special, like [x,y], or like [[x,y]], Translate into [x, x, y, y], draw a rectangle from the top left to the bottom right.
        fill_color: str or tuple or la.image.RGBMode, rgb color, box fill color.
        line_color: str or tuple or la.image.RGBMode, rgb color, box line color.
        width: box line width.
    returns: 
        a PIL instance.
    """
    image2 = image.copy()
    draw = ImageDraw.Draw(image2)
    if isinstance(boxs[0], (int, float)):
        if len(boxs) == 2:
            boxs = [[
                min(boxs),
                min(boxs),
                min(boxs),
                max(boxs),
                max(boxs),
                max(boxs),
                max(boxs),
                min(boxs)
            ]]
        elif len(boxs) == 4:
            boxs = [[
                min(boxs[0], boxs[2]),
                min(boxs[1], boxs[3]),
                max(boxs[0], boxs[2]),
                min(boxs[1], boxs[3]),
                max(boxs[0], boxs[2]),
                max(boxs[1], boxs[3]),
                min(boxs[0], boxs[2]),
                max(boxs[1], boxs[3])
            ]]
        elif len(boxs) % 2 == 0:
            boxs = [boxs]
        else:
            raise ValueError('boxs axis error')
    elif isinstance(boxs[0], (list, tuple)):
        if len(boxs) == 1 and len(boxs[0]) == 2 and isinstance(
                boxs[0][0], (int, float)):
            boxs = [[
                min(boxs[0]),
                min(boxs[0]),
                min(boxs[0]),
                max(boxs[0]),
                max(boxs[0]),
                max(boxs[0]),
                max(boxs[0]),
                min(boxs[0])
            ]]
        elif len(boxs) == 2 and len(boxs[0]) == 2:
            boxs = [boxs[0][0], boxs[0][1], boxs[1][0], boxs[1][1]]
            boxs = [[
                min(boxs[0], boxs[2]),
                min(boxs[1], boxs[3]),
                max(boxs[0], boxs[2]),
                min(boxs[1], boxs[3]),
                max(boxs[0], boxs[2]),
                max(boxs[1], boxs[3]),
                min(boxs[0], boxs[2]),
                max(boxs[1], boxs[3])
            ]]
        elif len(boxs) > 2 and len(boxs[0]) == 2:
            boxs = [[j for i in boxs for j in i]]
        else:
            boxs = [
                list(itertools.chain.from_iterable(i)) if isinstance(
                    i[0], (list, tuple)) else i for i in boxs
            ]
            for i in boxs:
                if len(i) % 2 != 0 or len(i) < 6:
                    raise ValueError('boxs axis error')
    else:
        raise ValueError('boxs axis error')
    for i in boxs:
        if isinstance(fill_color, dict):
            fill_color = fill_color['mode']
        line_color1 = _fill_color(image, line_color)
        draw.polygon(i, fill=fill_color, outline=line_color1, width=width)
    return image2
Esempio n. 12
0
def rotate(image, angle, expand=False, center=(0.5,0.5), translate=(0,0), fill_color=None, p=1):
    """Returns a rotated copy of this image. 
    
    This method returns a copy of this image, rotated the given number of degrees counter clockwise around its centre.
    
    Args:
        image: a PIL instance.
        angle: In degrees counter clockwise, angle in [-180, 180].
               if int or float, rotation angle.
               if list or tuple, randomly picked in the interval `[angle[0], angle[1])` value.
        expand: if true, expands the output image to make it large enough to hold the entire rotated image. 
                if false, make the output image the same size as the input image. 
                Note that the expand flag assumes rotation around the center and no translation.
                if value is None, then the function is random.
        center: center of rotation, xaxis and yaxis in [0,1], default is the center of the image.
                if int or float, xaxis=yaxis,
                if 2-tuple, (xaxis, yaxis), 
                if 4-tuple, xaxis in (center[0], center[1]) and yaxis in (center[2], center[3]).
        translate: post-rotate translation, xoffset and yoffset in [-1,1], see la.image.translate method.
                   if int or float, xoffset=yoffset,
                   if 2-tuple, (xoffset, yoffset), 
                   if 4-tuple, xoffset in (translate[0], translate[1]) and  yoffset in (translate[2], translate[3]).
        fill_color: color for area outside, int or str or tuple or la.image.RGBMode, rgb color.
        p: probability that the image does this. Default value is 1.
    Returns:
        A PIL instance.
    """
    if np.random.uniform()>p:
        return image
    if isinstance(angle, (list, tuple)):
        angle = np.random.uniform(angle[0], angle[1])
    if expand is None:
        expand = np.random.choice([True, False])
        
    if isinstance(center, (int, float)):
        center = (int(center*image.size[0]), int(center*image.size[1]))
    elif isinstance(center, (list, tuple)):
        if len(center)==2:
            center = (int(center[0]*image.size[0]), int(center[1]*image.size[1]))
        elif len(center)==4:
            center = (int(np.random.uniform(center[0], center[1])*image.size[0]), 
                      int(np.random.uniform(center[2], center[3])*image.size[1]))
        else:
            raise ValueError('`center` value format error.')
    else:
        raise ValueError('`center` value format error.')
    
    if isinstance(translate, (int, float)):
        translate = (int(translate*image.size[0]), int(translate*image.size[1]))
    elif isinstance(translate, (list, tuple)):
        if len(translate)==2:
            translate = (int(translate[0]*image.size[0]), int(translate[1]*image.size[1]))
        elif len(translate)==4:
            translate = (int(np.random.uniform(translate[0], translate[1])*image.size[0]), 
                         int(np.random.uniform(translate[2], translate[3])*image.size[1]))
        else:
            raise ValueError('`translate` value format error.')
    else:
        raise ValueError('`translate` value format error.')
    
    fill_color = _fill_color(image, fill_color)
    return image.rotate(angle, resample=Image.Resampling.NEAREST, expand=expand, 
                        center=center, translate=translate, fillcolor=fill_color)
Esempio n. 13
0
def affine(image, angle=(-180, 180), center=(0.5,0.5), translate=(0, 0), scale=1., shear=(0,0), fill_color=None, p=1):
    """Apply affine transformation on the image.
    
    Args:
        image: a PIL instance.
        angle: int or float, rotation angle in degrees between -180 and 180. Set to 0 to deactivate rotations.
               if list or tuple, randomly picked in the interval `[angle[0], angle[1])`.
        center: center of rotation, xaxis and yaxis in [0,1], default is the center of the image.
                if int or float, xaxis=yaxis,
                if 2-tuple, (xaxis, yaxis), 
                if 4-tuple, xaxis in (center[0], center[1]) and yaxis in (center[2], center[3]).
        translate: post-rotate translation, xoffset and yoffset in [-1,1], see la.image.translate method.
                   if int or float, xoffset=yoffset,
                   if 2-tuple, (xoffset, yoffset), 
                   if 4-tuple, xoffset in (translate[0], translate[1]) and  yoffset in (translate[2], translate[3]).
        scale: float, scaling factor interval, should be positive.
               if list or tuple, randomly picked in the interval `[scale[0], scale[1])`.
        shear: Range of degrees to select from, xoffset and yoffset in [-360,360]. 
               if int or float, xoffset=yoffset,
               if 2-tuple, (xoffset, yoffset), 
               if 4-tuple, xoffset in (shear[0], shear[1]) and  yoffset in (shear[2], shear[3]).
        fill_color: int or str or tuple or la.image.RGBMode, rgb color. 
        p: probability that the image does this. Default value is 1.
    Returns:
        a PIL instance.
    """
    if np.random.uniform()>p:
        return image
    if isinstance(angle, (list, tuple)):
        angle = np.random.uniform(angle[0], angle[1])
        
    if isinstance(center, (int, float)):
        cx, cy = (int(center*image.size[0]), int(center*image.size[1]))
    elif isinstance(center, (list, tuple)):
        if len(center)==2:
            cx, cy = (int(center[0]*image.size[0]), int(center[1]*image.size[1]))
        elif len(center)==4:
            cx = int(np.random.uniform(center[0], center[1])*image.size[0])
            cy = int(np.random.uniform(center[2], center[3])*image.size[1])
        else:
            raise ValueError('`center` value format error.')
    else:
        raise ValueError('`center` value format error.')
    
    if isinstance(translate, (int, float)):
        tx, ty = int(translate*image.size[0]), int(translate*image.size[1])
    elif isinstance(translate, (list, tuple)):
        if len(translate)==2:
            tx, ty = int(translate[0]*image.size[0]), int(translate[1]*image.size[1])
        elif len(translate)==4:
            tx = int(np.random.uniform(translate[0], translate[1])*image.size[0])
            ty = int(np.random.uniform(translate[2], translate[3])*image.size[1])
        else:
            raise ValueError('`translate` value format error.')
    else:
        raise ValueError('`translate` value format error.')
        
    if isinstance(scale, (list, tuple)):
        scale = np.random.uniform(scale[0], scale[1])
    if scale <= 0.0:
        raise ValueError("Argument scale should be positive")

    if isinstance(shear, (int, float)):
        shear = (shear, shear)
    elif isinstance(shear, (list, tuple)):
        if len(shear)==4:
            shear = (np.random.uniform(shear[0], shear[1]), np.random.uniform(shear[2], shear[3]))
        elif len(shear)!=2:
            raise ValueError('`translate` value format error.')
    else:
        raise ValueError('`translate` value format error.')
    
    rot = math.radians(angle)
    sx = math.radians(shear[0])
    sy = math.radians(shear[1])

    a = math.cos(rot - sy) / math.cos(sy)
    b = -math.cos(rot - sy) * math.tan(sx) / math.cos(sy) - math.sin(rot)
    c = math.sin(rot - sy) / math.cos(sy)
    d = -math.sin(rot - sy) * math.tan(sx) / math.cos(sy) + math.cos(rot)

    matrix = [d, -b, 0.0, -c, a, 0.0]
    matrix = [x / scale for x in matrix]
    matrix[2] += matrix[0] * (-cx - tx) + matrix[1] * (-cy - ty)
    matrix[5] += matrix[3] * (-cx - tx) + matrix[4] * (-cy - ty)
    matrix[2] += cx
    matrix[5] += cy
    fill_color = _fill_color(image, fill_color)
    return image.transform(image.size, Image.Transform.AFFINE, matrix, 
                           Image.Resampling.NEAREST, fillcolor=fill_color)