Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add border to an image with transparent background in Python Pillow Library

I am working with this image, which has a transparent background. enter image description here

If I use the following code:-

def add_border(input_image, output_image, border, color=0):
    img = Image.open(input_image)
    if isinstance(border, int) or isinstance(border, tuple):
        bimg = ImageOps.expand(img, border=border, fill=color)
    else:
        raise RuntimeError('Border is not an integer or tuple!')
    bimg.save(output_image)


if __name__ == '__main__':
    in_img = 'input/udit.png'
    add_border(in_img, output_image='udit_border.png',
               border=100, color="red")

This adds the border to the frame of the image.

I can find clear edges using the following code:-

from PIL import Image, ImageOps, ImageFilter
in_img = Image.open('input/udit.png')
image_with_edges = in_img.filter(ImageFilter.FIND_EDGES)

enter image description here

I was wondering, if I could draw a border across this edge and then join the two images to have a border on my image. But I couldn't find a way to do that. I want to change it into a sticker, so I am looking for something like the following image without bg.

enter image description here

like image 256
Udit Hari Vashisht Avatar asked Nov 30 '25 14:11

Udit Hari Vashisht


1 Answers

This approach works with OpenCV, where I just dilate the binary output from the alpha channel and stack the images on top of each other.

import cv2 as cv
import sys
import numpy as np


# Showing image on resized window
def show_image(name, image):
    cv.namedWindow(name, cv.WINDOW_NORMAL)
    cv.resizeWindow(name, 800, 800)
    cv.imshow(name, image)
    cv.waitKey(0)

# Adding a border as dilation will add pixels around the image
def add_uniform_border(img):
    return cv.copyMakeBorder(img, 100, 100, 100, 100, cv.BORDER_CONSTANT, value=[-255, 0, 0, 0])


# Applying dilation, choose kernel type as you want but elliptical worked best
def morph_image(img):
    # kernel = np.ones((20, 20), np.uint8)
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (30, 30))
    dilation = cv.dilate(img, kernel, iterations=1)
    return dilation


# Layering the dilated image onto the original image
def layer_image(img, dilate):
    layer = np.zeros(img.shape, dtype=np.uint8)
    alpha = np.expand_dims(img[:, :, 3], 2)
    alpha = np.repeat(alpha, 3, 2)
    alpha = alpha / 255

    layer[dilate == 255] = (255, 255, 255, 255)
    layer[:, :, 0:3] = layer[:, :, 0:3] * (1 - alpha) + alpha * img[:, :, 0:3]

    return layer


def main():
    img = sys.argv[1]
    img_color = cv.imread(img, cv.IMREAD_UNCHANGED)
    img_border = add_uniform_border(img_color)
    b, g, r, alpha = cv.split(img_border)
    img_dilate = morph_image(alpha)
    img_layer = layer_image(img_border, img_dilate)
    show_image('dilate', img_dilate)
    show_image('layer', img_layer)


if __name__ == "__main__":
    main()

Original Image: Original Image

Dilated Image: Dilated Image

Output Image: Output Image

Running the script

python sticker.py filepath.png
like image 112
rebatov Avatar answered Dec 03 '25 05:12

rebatov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!