Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overlaying just black pixels from an image over another using Python Imaging Library

Tags:

python

H as my name suggests I am new to code, am working with Python and would really appreciate some help with using the Python Imaging Library to complete a task.

I have 2 bitmap images. The first image is of a color painting and the second contains just black and white pixels... I would like to develop a function that accepts two images as parameters to create a new image that is essentially the first image (the painting), with only the black pixels from the second image, overwritten on top of it. The second image is smaller than the first and the overwritten pixels need to be positioned in the center of the new image.

I have installed the PIL and have been able to use the following code to successfully display the first image using the following code:

import PIL
from PIL import Image

painting = Image.open("painting.bmp")
painting.show()

I have ruled out using .blend and .composite functions or the .multiply function from the ImageChops module, as the images are not the same size.

I believe I'll need to use either .getpixel / .putpixel or .getdata / .putdata to find the black pixels which are identified by tuple (0,0,0). Also PIL's crop and paste functions I'm thinking should help work out the 'region' from the painting to overwrite with the black pixels, and could help center the black pixels over the painting?

So i'm looking at something like this maybe...

def overwrite_black(image1, image2): 

image_1 = Image.open('painting.bmp') 
image_2 = Image.open('black_white.bmp') 
pixels = list(image_2.getdata())

for y in xrange(image_2.size[1]):
    for x in xrange(image_2.size[0]):
        if pixels ==(o,o,o):
          image_2.putdata(pixels((x,y),(0,0,0)))

image_2.save('painted.bmp')

Again, i'm new so go easy on me and any help would be greatly appreciated.

Cheers.

like image 284
NewBee Avatar asked Sep 19 '25 11:09

NewBee


1 Answers

Ok, here's an alternate solution that's far more general and extendable. There's two parts to it; firstly there's resizing (but not scaling) the smaller image to the dimensions of the larger one, and then there's taking that image and making it into an image that only consists of black or transparent pixels, which can be simply pasted onto the larger one, which then leaves us with what you want.

Resizing:

1: painting 2: original mask 3: resized

  1. Reference image
  2. Input mask
  3. Resized mask

That can be done with this center_resize() function:

def center_resize(smaller, (width, height)):
    resized = Image.new("RGB", (width, height), "white")
    smaller_w, smaller_h = smaller.size
    box = (width/2-smaller_w/2,
           height/2-smaller_h/2,
           width/2-smaller_w/2+smaller_w,
           height/2-smaller_h/2+smaller_h)
    resized.paste(smaller, box)
    return resized

Filtering:

This function is made to iterate through all the pixels in an image and set them to a specified colour, if they are a specified colour. (Otherwise they get set to a third specified color.) In this case we want to leave all black pixels black, but set all other to a fully transparent black. To do that you would input this:

pixel_filter(image, condition=(0, 0, 0), true_colour=(0, 0, 0, 255), false_colour=(0, 0, 0, 0))

... and it would return a filtered image.

def pixel_filter(image, condition, true_colour, false_colour):
    filtered = Image.new("RGBA", image.size)
    pixels = list(image.getdata())
    for index, colour in enumerate(pixels):
        if colour == condition:
            filtered.putpixel((index%image.size[1],index/image.size[1]), true_colour)
        else:
            filtered.putpixel((index%image.size[1],index/image.size[1]), false_colour)
    return filtered

Now in your case, we can apply these to the B&W image, and simply paste it onto the main image.

mask = center_resize(mask, painting.size)
mask = pixel_filter(mask, (0, 0, 0), (0, 0, 0, 255), (0, 0, 0, 0))

painting.paste(mask, (0, 0), mask)
painting.show()

Output:

output

See if this code is useful—pull it apart and use what you want!

like image 179
Jollywatt Avatar answered Sep 21 '25 02:09

Jollywatt