Resize images in python using PIL - python

I'm trying to resize a set of images, approximatively 366, so I created a script that I tested first on 3 and it was successful.
The issue is when I process the whole folder, it returns me this error :
resizeimage.imageexceptions.ImageSizeError: 'Image is too small, Image size : (275, 183), Required size : (399, 399)'
My script is supposed to iterate an entire folder, resize images then store the output files in another folder:
import os
from PIL import Image
from resizeimage import resizeimage
path = "/Users/sigc2sige/PycharmProjects/helloworld/photos"
size = (399, 399)
for file in os.listdir(path):
with open('/Users/sigc2sige/PycharmProjects/helloworld/photos/'+file, 'r+b') as f:
with Image.open(f) as image:
cover = resizeimage.resize_cover(image, size, Image.ANTIALIAS)
cover.save('/Users/sigc2sige/PycharmProjects/helloworld/photos_2/'+file, image.format)
I did use this instruction:
thumb = ImageOps.fit(image, size, Image.ANTIALIAS) but I believe that it crops images instead of resizing them.
If you have any ideas about how to solve this issue, it would be great.

Downsampling an image (making it smaller) is one thing, and upsampling (making it bigger) is another thing. If you want to downsample, ANTIALIAS is a good choice, if you want to upsample, there are other filters you could use.
import os
from PIL import Image
from resizeimage import resizeimage
path = "/Users/sigc2sige/PycharmProjects/helloworld/photos"
size = (399, 399)
for file in os.listdir(path):
with open('/Users/sigc2sige/PycharmProjects/helloworld/photos/'+file, 'r+b') as f:
with Image.open(f) as image:
if (image.size) >= size:
cover = resizeimage.resize_cover(image, size, Image.ANTIALIAS)
cover.save('/Users/sigc2sige/PycharmProjects/helloworld/photos_2/'+file, image.format)
else:
cover = image.resize(size, Image.BICUBIC).save('/Users/sigc2sige/PycharmProjects/helloworld/photos_2/'+file, image.format)

Related

Add white background and resize images in a folder

I want to add a white background to my transparant images (png) and resize them. The images are located in a folder. I need to do bulk work, not 1 image at the time.
I removed the background from the images first with rembg (works good) and now I want to change the images.
My code
import rembg
import glob
from pathlib import Path
from rembg import remove, new_session
session = new_session()
for file in Path(r'C:\test\images').glob('*.jpg'):
input_path = str(file)
output_path = str(file.parent / (file.stem + ".out.png"))
with open(input_path, 'rb') as i:
with open(output_path, 'wb') as o:
input = i.read()
output = remove(input, session=session)
o.write(output)
I do not know how to add the white backgroud and resize with python because I'm fairly new to this. Thank you in advance!
I think you want a helper function to do the work, something like:
from PIL import Image
import rembg
def process(session, image, *, size=None, bgcolor='white'):
"session is a rembg Session, and image is a PIL Image"
if size is not None:
image = image.resize(size)
else:
size = image.size
result = Image.new("RGB", size, bgcolor)
out = rembg.remove(image, session=session)
result.paste(out, mask=out)
return result
The idea being that you pass a rembg Session and a Pillow Image in and it will remove the background and flatten that image, resizing along the way.
As a working example, you could do something like:
from io import BytesIO
import requests
session = rembg.new_session("u2netp")
res = requests.get("https://picsum.photos/600")
res.raise_for_status()
with Image.open(BytesIO(res.content)) as img:
out = process(session, img, size=(256, 256), bgcolor='#F0E68C')
out.save("output.png")
For example, an input and output might be:
If you wanted to work with lots of files, your pathlib objects can be passed directly to Pillow:
from pathlib import Path
for path_in in Path(r'C:\test\images').glob('*.jpg'):
path_out = path_in.parent / f"{path_in.stem}-out.png"
# no point processing images that have already been done!
if path_out.exists():
continue
with Image.open(path_in) as img:
out = process(session, img, size=(256, 256), bgcolor='#F0E68C')
out.save(path_out)
Update: it's often worth adding a check into these loops so they can be rerun and not have to process everything again. If you really do want images to be re-processed then just delete *-out.png

How to put text on multiple images using python?

from PIL import Image, ImageDraw, ImageFont
import glob
import os
images = glob.glob("directory_path/*.jpg")
for img in images:
images = Image.open(img)
draw = ImageDraw.Draw(images)
font = ImageFont.load_default() #Downloaded Font from Google font
text = "Text on all images from directory"
draw.text((0,150),text,(250,250,250),font=font)
images.save(img)
I have to put text on all images , I have tried above code but its not working
This code worked for me just fine, but the text was hard to read because it was small and white. I did change directory_path to images and put my images in there. The images looked like this, the text is small and on the left side:
Here is the solution
from PIL import Image,ImageDraw,ImageFont
import glob
import os
images=glob.glob("path/*.jpg")
for img in images:
images=Image.open(img)
draw=ImageDraw.Draw(images)
font=ImageFont.load_default()
text="Whatever text"
draw.text((0,240),text,(250,250,250),font=font)
images.save(img)
one possible problem with the code may be that you are using the images variable for saving the list of images and also to iterate through the images.
Try this code, this will work for sure.
from PIL import Image, ImageDraw, ImageFont
import glob
import os
images = glob.glob("new_dir/*.jpg")
print(images)
for img in images:
image = Image.open(img)
draw = ImageDraw.Draw(image)
font = ImageFont.load_default() #Downloaded Font from Google font
text = "Text on all images from directory"
draw.text((0,150),text,fill = 'red' ,font=font)
image.save(img)

Where are images saved when creating images with Pillow in Python

In these lines of code, I create a small red image and save it as "new_image.png". But I can't find the saved image, where is it saved? And can I change the place where I want to save my image?
from PIL import Image
img = Image.new('RGB', (60, 30), color = 'red')
img.save("new_image.PNG")
I tested your code:
from PIL import Image
img = Image.new('RGB', (60, 30), color = 'red')
img.save("new_image.PNG")
It works well for me:
The reason may because your current work path is not as you thought.
See my answer here:
https://stackoverflow.com/a/66449241/12838403
If you don't specify a path, the image is saved in the same path as the python file generating the image
from PIL import Image
img = Image.new('RGB', (60, 30), color = 'red')
img.save("new_image.PNG")
To save image in a directory you specify, you can use
from PIL import Image
import os
image_path = "path/to/image"
image = image.save(f"{image_path}/image.png")
Note: If this directory does not exist, you would have to create it before saving your image in it.
from PIL import Image
import os
image_path = "path/to/image"
os.mkdir(image_path)
image = image.save(f"{image_path}/image.png")

How can I convert some png files to a video using OpenCV?

The file appears and when I open it it just closes. I'm on Linux Mint Cinnamon.
import cv2
import numpy as np
import glob
size = (500,500)
img_array = []
for filename in glob.glob('home/user/Desktop/Images/*.png'):
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
img_array.append(img)
out = cv2.VideoWriter('project.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
cvWaitKey(0)
Your code is fundamentally correct, but openCV video writing seems to be very sensitive to the machine environment, codecs etc.
As an alternative, you might consider the imageio library, for example:
import imageio
writer = imageio.get_writer('movie.mp4')
for img in img_array:
writer.append_data(img)
writer.close()
The examples are here.
Typo error: cvWaitKey(0) to cv2.waitKey(0)

ImageOps.fit is blurring my image

I'm using ImageOps to resize and center-crop uploaded avatar images. The problem is, when I try to upload an image that is already the desired size, the uploaded image is blurred.
The relevant code:
avatar_size = (59,59)
#resized_im = im.resize(avatar_size, Image.ANTIALIAS) #This works! But doesn't crop.
formatted_im = ImageOps.fit(im, avatar_size, Image.ANTIALIAS, centering=(0.5,0.5))
formatted_im.save('foo.jpg', 'JPEG', quality=95)
So, when I upload a 59x59px image, the resulting upload on the server is blurred. Tried googling, reading the docs, and experimenting, but can't figure this out. Thanks for the help.
It is probably the antialiasing which is causing the blur.
How about try:
avatar_size = (59,59)
method = Image.NEAREST if im.size == avatar_size else Image.ANTIALIAS
formatted_im = ImageOps.fit(im, avatar_size, method = method, centering = (0.5,0.5))
formatted_im.save('foo.jpg', 'JPEG', quality=95)

Categories