Can't paste an image onto another image with PIL properly - python

I have this image:
that I'm trying to paste on to this one:
I want to get rid of the black background (so I'm assuming "make it transparent"?).
I tried applying a black mask, but
the result is this:
I'm not quite understanding how to use a mask properly.
I thought creating a black mask would get rid of the black portions.
from PIL import Image
image = Image.open(r'..jpg')
image_2 = Image.open(r'...jpg')
image_copy = image.resize((300,300)).copy() #fish image
mask=Image.new('L', (300,300), color=0)
position = ((200,100))
image_2.paste(image_copy, position, mask = mask)
image_2.save('testing_1.png')
EDIT: Playing around with the code a bit more I'm able to overlay the image onto the background,
but it still has the black background surrounding it.
I would like to get RID of the black background.

Related

How do I crop multiple images from one picture based on the background color?

So I have an image and I want to cut it up into multiple images to feed into OCR to read.
image example
I only want the messages with the white bubbles and exclude anything with the grey bubbles. I can't figure out how to make a loop to separate each white bubble.
import numpy as np
from PIL import ImageGrab, Image, ImageFilter
img = Image.open('test1.png').convert('RGB')
na = np.array(img)
orig = na.copy()
img = img.filter(ImageFilter.MedianFilter(3))
whiteY, whiteX = np.where(np.all(na==[255,255,255],axis=2))
top, bottom = whiteY[1], whiteY[-1]
left, right = whiteX[1], whiteX[-1]
You could try using the opencv threshold function, followed by the findContours function. This will, if you threshold the image correctly, give you the 'borders' of the bubbles above. Using that, you could then crop out each text bubble.
Here's a simple example of contours being used:
https://www.geeksforgeeks.org/find-and-draw-contours-using-opencv-python/
Otherwise if you'd like to understand better how the opencv functions I mentioned or those that are used in the article above, have a look at the opencv documentation.

How do I fix my image not being pasted correctly?

I am trying to crop a image into a circulor form (which works) and then pasting it to a white backround.
from PIL import Image,ImageFont,ImageDraw, ImageOps, ImageFilter
from io import BytesIO
import numpy as np
pfp = Image.open(avatar)
# cropping to circle
img=pfp.convert("RGB")
npImage=np.array(img)
h,w=img.size
alpha = Image.new('L', img.size,0)
draw = ImageDraw.Draw(alpha)
draw.pieslice([0,0,h,w],0,360,fill=255)
npAlpha=np.array(alpha)
npImage=np.dstack((npImage,npAlpha))
Image.fromarray(npImage).save('result.png')
background = Image.open('white2.png')
background.paste(Image.open('result.png'), (200, 200, h, w))
background.save('combined.png')
Heres what the cropped image looks like(It looks like it has a white background but that's it's transparent):
Cropped Image
But then when I paste it to the white background it changes to a square:
Pasted Image
Here is the original image I am working with:
Image
What you're doing is setting the Alpha of any pixel outside that circle to 0, so when you render it, it's gone, but that pixel data is still there. That's not a problem, but it important to know.
Problem
Your "white2.png" image does not have an alpha channel. Even if it's a PNG file, you have to add an alpha channel using your image editing tool. You can print("BGN:", background.getbands()), to see the channels it has. You'll see it says 'R','G','B', but no 'A'.
Solution 1
Replace your paste line with:
background.paste(pfp, (200, 200), alpha)
Here, we use the loaded in avatar as is, and the third argument is a mask which PIL figures out how to use to mask the image before pasting.
Solution 2
Give your white background image an alpha channel.
MS Paint doesn't do this. You have to use something else.
For GIMP, you simply right-click on the layer and click Add Alpha-channel.
Oh, and something worth noting.
Documentation for Paste.
See alpha_composite() if you want to combine images with respect to their alpha channels.

cv2.imread and cv2.imshow return all zeros and black image

I've create a *.png image using PPT.
I want to use cv2-python to read and show it. But the cv2.imshow gave me a total black image with nothing on it. This is my code,I just don't know where was wrong:
img = cv2.imread(r"C:/Users/.../Test_shapes.png")
print img.max(),img.shape
cv2.imshow('color_image',img)
cv2.waitKey()
p.s. the img.shape returns the correct shapes (881, 1803, 3). But img.max() returns 0.
Sorry, I don't have enough reputation to add images here. But with Matlab, my *.png could be successfully read and the max is 108.
This normally happens, when you draw some black lines, on a presumably white canvas. Most applications export PNG with transparent background, even if the visible canvas was white.
The result is that the image consists only of black pixels and transparent pixels. Those that are transparent, usually also have an RGB value of 0.0.0 -- so if we look only at the RGB values, everything is black.
E.g. in inkscape, you can put a white rectangle below your drawing to make the PNG exporter really save some white background.
Both, default cv2.imread("file.png", cv2.IMREAD_COLOR) and cv2.imread("file.png", cv2.IMREAD_GRAYSCALE) ignore transparency, and only see the RGB values. This is bad, as the RGB value of a fully transparent pixel is meaningless.
Only cv2.imread("file.png", cv.IMREAD_UNCHANGED) can access the transparency channel. We extract the alpha, invert it, and add it back to the image. This simulates alpha on a white background:
img = cv2.imread("file.png", cv.IMREAD_UNCHANGED)
if img.shape[2] == 4: # we have an alpha channel
a1 = ~img[:,:,3] # extract and invert that alpha
img = cv2.add(cv2.merge([a1,a1,a1,a1]), img) # add up values (with clipping)
img = cv2.cvtColor(img, cv2.COLOR_RGBA2RGB) # strip alpha channel
cv2.imshow('aa', img); cv2.waitKey(0); cv2.destroyAllWindows()
It seems cv2 is not friends with transparencies at all. Neither cv.add(), nor cv2.addWeighted() can apply an alpha channel easily.
Sorry, could not resist to dig out this unanswered zombie after 5 years. My solution works nicely, when there is only information in the alpha channel, and when information is in both, the rgb channels, and in the alpha channel.

PNG won't autocrop using image.getbbox()

I've been trying to get thisimage to automatically crop to the smallest size possible, removing the transparent bits around it. I can't just crop this image myself manually, as more things will be added on the image like this .
I've been using this code:
from PIL import Image, ImageChops
image=Image.open('headbase1.png')
image.load()
imageSize = image.size
imageBox = image.getbbox()
print(image.getbbox())
cropped=image.crop(imageBox)
cropped.save('headbase_end.png')
It does not crop out the transparency around it, and the bounding box is this (0, 0, 45, 45), which I do not think is right.
Thanks, VOT.
Edit, this does work: Automatically cropping an image with python/PIL with that image, however it refuses to work for my image. .
getbbox doesn't work on PNGs with alpha channels: image.mode == 'RGBA'
First remove the alpha channel and then obtain the bounding box. image.convert('RGB').getbbox()

PIL paste image with alpha appears faded

I am working with multiple images that I would like to stack on top of each other to create a single image. However, in working with them, I'm noticing that if the image already has transparency (alpha != 255), that part of the image appears faded. If there is no transparency, all is good.
I saved one of the images I was working with to a PNG and created a small bit of code that duplicates the problem. Essentially, I'm creating a new image with a transparent background and then pasting the image on top:
from PIL import Image
img=Image.new('RGBA', (946,627), (0,0,0,0))
overlayImage = Image.open('drawing.png')
img.paste(overlayImage, (0,0), overlayImage)
img.save('drawing-pasted.png')
When this completes, drawing-pasted.png looks like this:
But the original drawing (drawing.png) looked like this:
(Images cropped manually to show detail.) The original image circles fill color has an alpha value of 179.
Has anyone else encountered this, and what am I doing wrong?
Thanks much.
image = Image.open(file_path)
img1 = Image.open(file_path)
cords = (233.22)
image.paste(img1, cords, mask=img1)
image.save(path_where_you_want_to_save_final_image)
simply use this block of code
The background you are creating is black and fully transparent the original is blue but with an alpha of 179 so you have 2 pixels (0,0,0,0) and (0,0,255,179) assuming 100% blue - since you are pasting the image in it will be over the background so will use the alpha of the new image allowing (255-179)/255 or about 30% black. (N.B. The alpha of the background makes no difference since it is behind the new image)
You could use overlayImage.putalpha to set the alpha to 255 start from your image rather than a black background.

Categories