Python/PIL Resize all images in a folder
Question:
I have the following code that I thought would resize the images in the specified path
But when I run it, nothing works and yet python doesn’t throw any error so I don’t know what to do. Please advise. Thanks.
from PIL import Image
import os, sys
path = ('C:UsersMaxxiecolorcomplete')
def resize():
for item in os.listdir(path):
if os.path.isfile(item):
im = Image.open(item)
f, e = os.path.splitext(item)
imResize = im.resize((200,200), Image.ANTIALIAS)
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
resize()
Answers:
#!/usr/bin/python
from PIL import Image
import os, sys
path = "/root/Desktop/python/images/"
dirs = os.listdir( path )
def resize():
for item in dirs:
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
imResize = im.resize((200,200), Image.ANTIALIAS)
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
resize()
Your mistake is belong to full path of the files. Instead of item must be path+item
In case you want to keep the same aspect ratio of the image you can use this script.
from PIL import Image
import os, sys
path = "/path/images/"
dirs = os.listdir( path )
final_size = 244;
def resize_aspect_fit():
for item in dirs:
if item == '.DS_Store':
continue
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
size = im.size
ratio = float(final_size) / max(size)
new_image_size = tuple([int(x*ratio) for x in size])
im = im.resize(new_image_size, Image.ANTIALIAS)
new_im = Image.new("RGB", (final_size, final_size))
new_im.paste(im, ((final_size-new_image_size[0])//2, (final_size-new_image_size[1])//2))
new_im.save(f + 'resized.jpg', 'JPEG', quality=90)
resize_aspect_fit()
Expanding on the great solution of @Sanjar Stone
for including subfolders and also avoid DS warnings you can use the glob library:
from PIL import Image
import os, sys
import glob
root_dir = "/.../.../.../"
for filename in glob.iglob(root_dir + '**/*.jpg', recursive=True):
print(filename)
im = Image.open(filename)
imResize = im.resize((28,28), Image.ANTIALIAS)
imResize.save(filename , 'JPEG', quality=90)
John Ottenlips’s solution created pictures with black borders on top/bottom i think because he used
Image.new("RGB", (final_size, final_size))
which creates a square new image with the final_size as dimension, even if the original picture was not a square.
This fixes the problem and, in my opinion, makes the solution a bit clearer:
from PIL import Image
import os
path = "C:/path/needs/to/end/with/a/"
resize_ratio = 0.5 # where 0.5 is half size, 2 is double size
def resize_aspect_fit():
dirs = os.listdir(path)
for item in dirs:
if item == '.jpg':
continue
if os.path.isfile(path+item):
image = Image.open(path+item)
file_path, extension = os.path.splitext(path+item)
new_image_height = int(image.size[0] / (1/resize_ratio))
new_image_length = int(image.size[1] / (1/resize_ratio))
image = image.resize((new_image_height, new_image_length), Image.ANTIALIAS)
image.save(file_path + "_small" + extension, 'JPEG', quality=90)
resize_aspect_fit()
This code just worked for me to resize images..
from PIL import Image
import glob
import os
# new folder path (may need to alter for Windows OS)
# change path to your path
path = 'yourpath/Resized_Shapes' #the path where to save resized images
# create new folder
if not os.path.exists(path):
os.makedirs(path)
# loop over existing images and resize
# change path to your path
for filename in glob.glob('your_path/*.jpg'): #path of raw images
img = Image.open(filename).resize((306,306))
# save resized images to new folder with existing filename
img.save('{}{}{}'.format(path,'/',os.path.split(filename)[1]))
For those that are on Windows:
from PIL import Image
import glob
image_list = []
resized_images = []
for filename in glob.glob('YOURPATH\*.jpg'):
print(filename)
img = Image.open(filename)
image_list.append(img)
for image in image_list:
image = image.resize((224, 224))
resized_images.append(image)
for (i, new) in enumerate(resized_images):
new.save('{}{}{}'.format('YOURPATH\', i+1, '.jpg'))
Heavily borrowed the code from @Sanjar Stone. This code work well in Windows OS.
Can be used to bulky resize the images and assembly back to its corresponding subdirectory.
Original folder with it subdir:
..DATAORI-DIR
├─Apolo
├─Bailey
├─Bandit
├─Bella
New folder with its subdir:
..DATANEW-RESIZED-DIR
├─Apolo
├─Bailey
├─Bandit
├─Bella
Gist link: https://gist.github.com/justudin/2c1075cc4fd4424cb8ba703a2527958b
from PIL import Image
import glob
import os
# new folder path (may need to alter for Windows OS)
# change path to your path
ORI_PATH = '..DATAORI-DIR'
NEW_SIZE = 224
PATH = '..DATANEW-RESIZED-DIR' #the path where to save resized images
# create new folder
if not os.path.exists(PATH):
os.makedirs(PATH)
# loop over existing images and resize
# change path to your path
for filename in glob.glob(ORI_PATH+'**/*.jpg'): #path of raw images with is subdirectory
img = Image.open(filename).resize((NEW_SIZE,NEW_SIZE))
# get the original location and find its subdir
loc = os.path.split(filename)[0]
subdir = loc.split('\')[1]
# assembly with its full new directory
fullnew_subdir = PATH+"/"+subdir
name = os.path.split(filename)[1]
# check if the subdir is already created or not
if not os.path.exists(fullnew_subdir):
os.makedirs(fullnew_subdir)
# save resized images to new folder with existing filename
img.save('{}{}{}'.format(fullnew_subdir,'/',name))
Expanded the answer of Andrei M. In order to only change the height of the picture and automatically size the width.
from PIL import Image
import os
path = "D:/.../.../.../resized/"
dirs = os.listdir(path)
def resize():
for item in dirs:
if item == '.jpg':
continue
if os.path.isfile(path+item):
image = Image.open(path+item)
file_path, extension = os.path.splitext(path+item)
size = image.size
new_image_height = 190
new_image_width = int(size[1] / size[0] * new_image_height)
image = image.resize((new_image_height, new_image_width), Image.ANTIALIAS)
image.save(file_path + "_small" + extension, 'JPEG', quality=90)
resize()
If you want to resize any image from a folder where without images files, other files also exist, then you can try this:
from genericpath import isdir
from PIL import Image
import os, sys
path = "C://...//...//....//...//"
save_path = "C://...//..//...//...//"
images = os.listdir(path)
if not os.path.isdir(save_path):
os.makedirs(save_path)
for image in images:
image_path = os.path.join(path, image)
iamge_save_path = os.path.join(save_path, image)
if image.split(".")[1] not in ["jpg", "png"]:
continue
if os.path.exists(image_path):
im = Image.open(image_path)
image_resized = im.resize((224,224))
image_resized.save(iamge_save_path, quality=90)
# print("saved")
Safer to use pathlib
As jwal commented on a similar question, use the object-oriented counterparts for os
of pathlib
:
p = Path('images')
to define the path instance (here as directory relative to current)
Path.iterdir()
to find files in the path instance
Path.absolute()
to get the absolute-path for file-IO functions
Path.joinpath(*other)
to add subfolders or filenames
Path.mkdir(parents=True, exist_ok=True)
Path.name
to return the basename of the file (like picture.png
)
from pathlib import Path
# folder = 'images'
# new_dimension = (width, height)
def resize(folder, new_dimension, new_subdir):
images_folder = Path(folder)
for child in images_folder.iterdir():
print("Found image:", child)
image_path = child.absolute()
image = Image.open(image_path)
resized_image = image.resize() # could also add Image.ANTIALIAS
# create if the subdir not exists
subdir = images_folder.join(new_subdir)
if not subdir.exists():
subdir.mkdir(parents=True, exist_ok=True)
to_path = subdir.joinpath(child.name) # join adds the path-separators
print("Saving resized to:", to_path)
resized_image.save(to_path) # could also add save-options like 'JPEG', quality=90
I have the following code that I thought would resize the images in the specified path
But when I run it, nothing works and yet python doesn’t throw any error so I don’t know what to do. Please advise. Thanks.
from PIL import Image
import os, sys
path = ('C:UsersMaxxiecolorcomplete')
def resize():
for item in os.listdir(path):
if os.path.isfile(item):
im = Image.open(item)
f, e = os.path.splitext(item)
imResize = im.resize((200,200), Image.ANTIALIAS)
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
resize()
#!/usr/bin/python
from PIL import Image
import os, sys
path = "/root/Desktop/python/images/"
dirs = os.listdir( path )
def resize():
for item in dirs:
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
imResize = im.resize((200,200), Image.ANTIALIAS)
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
resize()
Your mistake is belong to full path of the files. Instead of item must be path+item
In case you want to keep the same aspect ratio of the image you can use this script.
from PIL import Image
import os, sys
path = "/path/images/"
dirs = os.listdir( path )
final_size = 244;
def resize_aspect_fit():
for item in dirs:
if item == '.DS_Store':
continue
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
size = im.size
ratio = float(final_size) / max(size)
new_image_size = tuple([int(x*ratio) for x in size])
im = im.resize(new_image_size, Image.ANTIALIAS)
new_im = Image.new("RGB", (final_size, final_size))
new_im.paste(im, ((final_size-new_image_size[0])//2, (final_size-new_image_size[1])//2))
new_im.save(f + 'resized.jpg', 'JPEG', quality=90)
resize_aspect_fit()
Expanding on the great solution of @Sanjar Stone
for including subfolders and also avoid DS warnings you can use the glob library:
from PIL import Image
import os, sys
import glob
root_dir = "/.../.../.../"
for filename in glob.iglob(root_dir + '**/*.jpg', recursive=True):
print(filename)
im = Image.open(filename)
imResize = im.resize((28,28), Image.ANTIALIAS)
imResize.save(filename , 'JPEG', quality=90)
John Ottenlips’s solution created pictures with black borders on top/bottom i think because he used
Image.new("RGB", (final_size, final_size))
which creates a square new image with the final_size as dimension, even if the original picture was not a square.
This fixes the problem and, in my opinion, makes the solution a bit clearer:
from PIL import Image
import os
path = "C:/path/needs/to/end/with/a/"
resize_ratio = 0.5 # where 0.5 is half size, 2 is double size
def resize_aspect_fit():
dirs = os.listdir(path)
for item in dirs:
if item == '.jpg':
continue
if os.path.isfile(path+item):
image = Image.open(path+item)
file_path, extension = os.path.splitext(path+item)
new_image_height = int(image.size[0] / (1/resize_ratio))
new_image_length = int(image.size[1] / (1/resize_ratio))
image = image.resize((new_image_height, new_image_length), Image.ANTIALIAS)
image.save(file_path + "_small" + extension, 'JPEG', quality=90)
resize_aspect_fit()
This code just worked for me to resize images..
from PIL import Image
import glob
import os
# new folder path (may need to alter for Windows OS)
# change path to your path
path = 'yourpath/Resized_Shapes' #the path where to save resized images
# create new folder
if not os.path.exists(path):
os.makedirs(path)
# loop over existing images and resize
# change path to your path
for filename in glob.glob('your_path/*.jpg'): #path of raw images
img = Image.open(filename).resize((306,306))
# save resized images to new folder with existing filename
img.save('{}{}{}'.format(path,'/',os.path.split(filename)[1]))
For those that are on Windows:
from PIL import Image
import glob
image_list = []
resized_images = []
for filename in glob.glob('YOURPATH\*.jpg'):
print(filename)
img = Image.open(filename)
image_list.append(img)
for image in image_list:
image = image.resize((224, 224))
resized_images.append(image)
for (i, new) in enumerate(resized_images):
new.save('{}{}{}'.format('YOURPATH\', i+1, '.jpg'))
Heavily borrowed the code from @Sanjar Stone. This code work well in Windows OS.
Can be used to bulky resize the images and assembly back to its corresponding subdirectory.
Original folder with it subdir:
..DATAORI-DIR
├─Apolo
├─Bailey
├─Bandit
├─Bella
New folder with its subdir:
..DATANEW-RESIZED-DIR
├─Apolo
├─Bailey
├─Bandit
├─Bella
Gist link: https://gist.github.com/justudin/2c1075cc4fd4424cb8ba703a2527958b
from PIL import Image
import glob
import os
# new folder path (may need to alter for Windows OS)
# change path to your path
ORI_PATH = '..DATAORI-DIR'
NEW_SIZE = 224
PATH = '..DATANEW-RESIZED-DIR' #the path where to save resized images
# create new folder
if not os.path.exists(PATH):
os.makedirs(PATH)
# loop over existing images and resize
# change path to your path
for filename in glob.glob(ORI_PATH+'**/*.jpg'): #path of raw images with is subdirectory
img = Image.open(filename).resize((NEW_SIZE,NEW_SIZE))
# get the original location and find its subdir
loc = os.path.split(filename)[0]
subdir = loc.split('\')[1]
# assembly with its full new directory
fullnew_subdir = PATH+"/"+subdir
name = os.path.split(filename)[1]
# check if the subdir is already created or not
if not os.path.exists(fullnew_subdir):
os.makedirs(fullnew_subdir)
# save resized images to new folder with existing filename
img.save('{}{}{}'.format(fullnew_subdir,'/',name))
Expanded the answer of Andrei M. In order to only change the height of the picture and automatically size the width.
from PIL import Image
import os
path = "D:/.../.../.../resized/"
dirs = os.listdir(path)
def resize():
for item in dirs:
if item == '.jpg':
continue
if os.path.isfile(path+item):
image = Image.open(path+item)
file_path, extension = os.path.splitext(path+item)
size = image.size
new_image_height = 190
new_image_width = int(size[1] / size[0] * new_image_height)
image = image.resize((new_image_height, new_image_width), Image.ANTIALIAS)
image.save(file_path + "_small" + extension, 'JPEG', quality=90)
resize()
If you want to resize any image from a folder where without images files, other files also exist, then you can try this:
from genericpath import isdir
from PIL import Image
import os, sys
path = "C://...//...//....//...//"
save_path = "C://...//..//...//...//"
images = os.listdir(path)
if not os.path.isdir(save_path):
os.makedirs(save_path)
for image in images:
image_path = os.path.join(path, image)
iamge_save_path = os.path.join(save_path, image)
if image.split(".")[1] not in ["jpg", "png"]:
continue
if os.path.exists(image_path):
im = Image.open(image_path)
image_resized = im.resize((224,224))
image_resized.save(iamge_save_path, quality=90)
# print("saved")
Safer to use pathlib
As jwal commented on a similar question, use the object-oriented counterparts for os
of pathlib
:
p = Path('images')
to define the path instance (here as directory relative to current)Path.iterdir()
to find files in the path instancePath.absolute()
to get the absolute-path for file-IO functionsPath.joinpath(*other)
to add subfolders or filenamesPath.mkdir(parents=True, exist_ok=True)
Path.name
to return the basename of the file (likepicture.png
)
from pathlib import Path
# folder = 'images'
# new_dimension = (width, height)
def resize(folder, new_dimension, new_subdir):
images_folder = Path(folder)
for child in images_folder.iterdir():
print("Found image:", child)
image_path = child.absolute()
image = Image.open(image_path)
resized_image = image.resize() # could also add Image.ANTIALIAS
# create if the subdir not exists
subdir = images_folder.join(new_subdir)
if not subdir.exists():
subdir.mkdir(parents=True, exist_ok=True)
to_path = subdir.joinpath(child.name) # join adds the path-separators
print("Saving resized to:", to_path)
resized_image.save(to_path) # could also add save-options like 'JPEG', quality=90