6

I want to blur a rectangle (with rounded corners) in an image using python pillow. I already found a way to blur only a certain part of a picture.

img = Image.open('assets/images/image.png')
x, y = 300, 1600

cropped_img = img.crop((x, y, 1000, 2600))

blurred_img = cropped_img.filter(ImageFilter.GaussianBlur(20))

img.paste(blurred_img, (x, y))

img.save('assets/images/new.png')
img.show()

Furthermore I found a method to add rounded corners on a rectangle(Transparency issues drawing a rectangle with rounded corners)

def round_corner(radius):
   corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0))
   draw = ImageDraw.Draw(corner)
   draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270)
   return corner

def round_rectangle(rectangle, radius):
   corner = round_corner(radius)
   rectangle.paste(corner, (0, 0))
   rectangle.paste(corner.rotate(90), (0, rectangle.size[1] - radius))
   rectangle.paste(corner.rotate(180), (rectangle.size[0] - radius,   rectangle.size[1] - radius))
   rectangle.paste(corner.rotate(270), (rectangle.size[0] - radius, 0))
   return rectangle

Unfortunately, I can't find a way to combine these two source codes so that they work.

My Example Image:example image

Fiver
  • 9,909
  • 9
  • 43
  • 63
Lucas
  • 75
  • 1
  • 7

1 Answers1

8

What you need to do, is essentially to create a mask for the Image.paste() that only pastes those parts of the blurred image that lie inside the rounded rectangle.

import PIL
from PIL import Image
from PIL import ImageFilter
from PIL import ImageDraw

# when using an image as mask only the alpha channel is important
solid_fill =  (50,50,50,255) 


def create_rounded_rectangle_mask(rectangle, radius):
    # create mask image. all pixels set to translucent
    i = Image.new("RGBA",rectangle.size,(0,0,0,0))

    # create corner
    corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0))
    draw = ImageDraw.Draw(corner)
    # added the fill = .. you only drew a line, no fill
    draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270, fill = solid_fill)

    # max_x, max_y
    mx,my = rectangle.size

    # paste corner rotated as needed
    # use corners alpha channel as mask

    i.paste(corner, (0, 0), corner)
    i.paste(corner.rotate(90), (0, my - radius),corner.rotate(90))
    i.paste(corner.rotate(180), (mx - radius,   my - radius),corner.rotate(180))
    i.paste(corner.rotate(270), (mx - radius, 0),corner.rotate(270))

    # draw both inner rects
    draw = ImageDraw.Draw(i)
    draw.rectangle( [(radius,0),(mx-radius,my)],fill=solid_fill)
    draw.rectangle( [(0,radius),(mx,my-radius)],fill=solid_fill)

    return i

Mask:

created mask

Apply the mask to your image:

img = Image.open('pic.jpg')

x, y = 300, 160 
radius = 75

cropped_img = img.crop((x, y, 600, 600))

# the filter removes the alpha, you need to add it again by converting to RGBA
blurred_img = cropped_img.filter(ImageFilter.GaussianBlur(20),).convert("RGBA")

# paste blurred, uses alphachannel of create_rounded_rectangle_mask() as mask 
# only those parts of the mask that have a non-zero alpha gets pasted
img.paste(blurred_img, (x, y), create_rounded_rectangle_mask(cropped_img,radius))

img.save('new2.png')
img.show()

I changed some dimensions and paths. Your code lacked the imports, I completed it to a minimal verifyable complete example.

Resulting Image, reduzed in size

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • 0 I have attempted the code above. However, despite assigning a radius of 100 when the object is round, I am receiving the following error. Is there a way to apply a blurred effect in a circular shape? (The lines should have been green, but unfortunately they were not.) img : https://i.stack.imgur.com/xUy1n.png – Abdullah Çiçekli Jan 17 '23 at 15:02
  • @Abdullah you need to create a mask that is circular and partly transparent and fully transparent every else where the circle does not apply. You seem to have a mix of circles and rectangles if I look a the picture. You can ask a new question, add your code, link to this question and hope that someone answers - I havent done PIL for some years now. – Patrick Artner Jan 18 '23 at 06:31