Reputation: 165
So basically I have a directory with 180 images with different width and height and I would like to resize all images to 1280 by 720 here is the script which I am running
import sys
import os
import numpy as np
from os import walk
import cv2
# width to resize
width = int(sys.argv[1])
# height to resize
height = int(sys.argv[2])
# location of the input dataset
input_dir = sys.argv[3]
# location of the output dataset
out_dir = sys.argv[4]
if len(sys.argv) != 5:
print("Please specify width, height, input directory and output directory.")
sys.exit(0)
print("Working...")
# get all the pictures in directory
images = []
ext = (".jpeg", ".jpg", ".png")
for (dirpath, dirnames, filenames) in walk(input_dir):
for filename in filenames:
if filename.endswith(ext):
images.append(os.path.join(dirpath, filename))
for image in images:
img = cv2.imread(image, cv2.IMREAD_UNCHANGED)
h, w = img.shape[:2]
pad_bottom, pad_right = 0, 0
ratio = w / h
if h > height or w > width:
# shrinking image algorithm
interp = cv2.INTER_AREA
else:
# stretching image algorithm
interp = cv2.INTER_CUBIC
w = width
h = round(w / ratio)
if h > height:
h = height
w = round(h * ratio)
pad_bottom = abs(height - h)
pad_right = abs(width - w)
scaled_img = cv2.resize(img, (w, h), interpolation=interp)
padded_img = cv2.copyMakeBorder(
scaled_img,0,pad_bottom,0,pad_right,borderType=cv2.BORDER_CONSTANT,value=[0,0,0])
cv2.imwrite(os.path.join(out_dir, os.path.basename(image)), padded_img)
print("Completed!")
here is the command python2.7 $python resize_images.py 1280 720 '/home/train/images/bottle_1/' '/home/train/images/bottle_resize/'
which gives me error Working...
Traceback (most recent call last):
File "resize_images.py", line 46, in
h = round(w / ratio)
ZeroDivisionError: integer division or modulo by zero
Command for python3 $python3 resize_images.py 1280 720 '/home/train/images/bottle_1/' '/home/train/images/bottle_resize/'
in result to this command it only resizes one image without giving any errors or warnings. So what could be the reason its not resizing and padding the images if anyone can help me thanks
Upvotes: 0
Views: 6811
Reputation: 1
Here is a function using Pillow and Opencv which takes an image in numpy.ndarray format and outputs an image also in numpy.ndarray format with your desired height and width without changing aspect ratio and just apply padding. It does not matter which height and width your image has in the first place.
import numpy as np
from PIL import Image
import cv2
def resize_image(image, height, width):
image = Image.fromarray(np.uint8(image)).convert('RGB')
MAX_SIZE = (width, height)
image.thumbnail(MAX_SIZE)
image = np.asarray(image)
y_border = max(height - image.shape[0], 0)
x_border = max(width - image.shape[1], 0)
top = y_border // 2
bottom = y_border - top
left = x_border // 2
right = x_border - left
image = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT)
return image
you can use the function as follows:
image = resize_image(image, 320, 320)
print(image.shape)
plt.imshow(image)
Besides, if you want the function takes image_path as input instead of image in numpy format you can use this:
import numpy as np
from PIL import Image
import cv2
def resize_image(image_path, height, width):
image = Image.open(image_path)
MAX_SIZE = (width, height)
image.thumbnail(MAX_SIZE)
image = np.asarray(image)
y_border = max(height - image.shape[0], 0)
x_border = max(width - image.shape[1], 0)
top = y_border // 2
bottom = y_border - top
left = x_border // 2
right = x_border - left
image = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT)
return image
Upvotes: 0
Reputation: 30579
As I wrote in my comment above, the indentation is wrong: the for image in images
loop ends with the calculation of the ratio. Then you process just the last image in the images
list. Last has nothing to do with the file order in your folder, as walk
returns the files in arbitrary order.
Following is the code with correct indentation. It works perfectly:
import sys
import os
import numpy as np
from os import walk
import cv2
# width to resize
width = int(sys.argv[1])
# height to resize
height = int(sys.argv[2])
# location of the input dataset
input_dir = sys.argv[3]
# location of the output dataset
out_dir = sys.argv[4]
if len(sys.argv) != 5:
print("Please specify width, height, input directory and output directory.")
sys.exit(0)
print("Working...")
# get all the pictures in directory
images = []
ext = (".jpeg", ".jpg", ".png")
for (dirpath, dirnames, filenames) in walk(input_dir):
for filename in filenames:
if filename.endswith(ext):
images.append(os.path.join(dirpath, filename))
print(filename)
for image in images:
img = cv2.imread(image, cv2.IMREAD_UNCHANGED)
h, w = img.shape[:2]
pad_bottom, pad_right = 0, 0
ratio = w / h
if h > height or w > width:
# shrinking image algorithm
interp = cv2.INTER_AREA
else:
# stretching image algorithm
interp = cv2.INTER_CUBIC
w = width
h = round(w / ratio)
if h > height:
h = height
w = round(h * ratio)
pad_bottom = abs(height - h)
pad_right = abs(width - w)
scaled_img = cv2.resize(img, (w, h), interpolation=interp)
padded_img = cv2.copyMakeBorder(
scaled_img,0,pad_bottom,0,pad_right,borderType=cv2.BORDER_CONSTANT,value=[0,0,0])
cv2.imwrite(os.path.join(out_dir, os.path.basename(image)), padded_img)
print("Completed!")
Upvotes: 2