Rishi
Rishi

Reputation: 2027

Different background for same image but different size

I have some product images. The background of these images is white. Now, in my website I want to use the same image of different sizes in different places. The problem is that, since the color of the background of an image is white. But, the color of the background I need as a thumbnail is green. Similarly, as the main product image I want the background as light blue. Here is an image for example. link. You can see the background of this image is white. I want to use the same image as a thumbnail. I have written a code to generate thumbnails of images. But I want background as some other color. Can this be done with image processing preferably in python? Thank you.

Edit: I cannot comment on any answers do, cannot understand why. Please reply.

Upvotes: 2

Views: 480

Answers (1)

mmgp
mmgp

Reputation: 19221

This is simple to do if you can tolerate some ugly effects in the resulting image. If this image with the different background color will be shown as a downscaled version of the original image, then these effects might not be noticeable and all is good.

So here is the simple approach:

  • Flood fill from the pixel at (0, 0) assuming it is a background pixel (white in your example) and accept minor differences when performing the flood fill. The background pixels are replaced by transparent points.
  • The step above gives a mask, which you can, for example, perform erosion and gaussian filtering.
  • Paste the "flood-filled" image with the mask created above.

Here is what you can expect from this approach. Input image and then two transformations to different background colors.

enter image description here enter image description here enter image description here

import sys
import cv2
import numpy
from PIL import Image

def floodfill(im, grayimg, seed, color, tolerance=15):
    width, height = grayimg.size
    grayim = grayimg.load()
    start_color = grayim[seed]

    mask_img = Image.new('L', grayimg.size, 255)
    mask = mask_img.load()
    count = 0
    work = [seed]
    while work:
        x, y = work.pop()
        im[x, y] = color
        for dx, dy in ((-1,0), (1,0), (0,-1), (0,1)):
            nx, ny = x + dx, y + dy
            if nx < 0 or ny < 0 or nx > width - 1 or ny > height - 1:
                continue
            if mask[nx, ny] and abs(grayim[nx, ny] - start_color) <= tolerance:
                mask[nx, ny] = 0
                work.append((nx, ny))
    return mask_img

img = Image.open(sys.argv[1]).convert('RGBA')
width, height = img.size
img_p = Image.new('RGBA', (width + 20, height + 20), img.getpixel((0, 0)))
img_p.paste(img, (3, 3))
img = img_p
img_g = img.convert('L')
width, height = img.size

im = img.load()
mask = floodfill(im, img_g, (0, 0), (0, 0, 0, 0), 20)

mask = numpy.array(mask)
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
mask = cv2.erode(mask, se)
mask = cv2.GaussianBlur(mask, (9, 9), 3)
mask = Image.fromarray(mask)

result_bgcolor = (0, 0, 0, 255) # Change to match the color you wish.
result = Image.new('RGBA', (width, height), result_bgcolor)
result.paste(img_p, (0, 0), mask)

result.save(sys.argv[2])

Upvotes: 2

Related Questions