Created
April 12, 2025 12:42
-
-
Save yuchen-xue/1420209043bf23ad846ed77b1caf8da5 to your computer and use it in GitHub Desktop.
Resize an image to a target width and height, while keeping the original height-width ratio. If the original height-width ratio is different from the target height-width ratio, fill the rest of the area with white pixels.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
from pathlib import Path | |
import cv2 | |
import numpy.typing as npt | |
def resize_white_fill(img: npt.NDArray, w_target: int, h_target: int) -> npt.NDArray: | |
"""Resize an image to a target width and height, while keeping the original | |
height-width ratio. If the original height-width ratio is different from | |
the target height-width ratio, fill the rest of the area with white pixels. | |
Args: | |
img (npt.NDArray): _Input image_ | |
w_target (int): _The desired width of the output image_ | |
h_target (int): _The desired height of the output image_ | |
Returns: | |
npt.NDArray: _The resized image with white pixels filling the rest of the area_ | |
""" | |
# Get the height-width ratio ("h-w ratio" for short) of the input image | |
h, w = img.shape[:2] | |
r = h / w | |
# If the input image has the identical h-w ratio as desired, simply | |
# resize this image as the given height and width, without further operations. | |
if r == h_target / w_target: | |
return cv2.resize(img, (w_target, h_target)) | |
# Below are the additional operations in case the input image has a different | |
# h-w ratio as desired. | |
elif int(w_target * r) < h_target: | |
# Suppose we resize the image so that it has the same width as the desired | |
# width, then we compare the new height with the desired height. If its | |
# height is smaller to the desired height. | |
w_new = w_target | |
h_new = int(w_new * r) | |
resized = cv2.resize(img, (w_new, h_new), interpolation=cv2.INTER_AREA) | |
# Fill the rest of the area along the height with white pixels | |
pad_height_top = int((h_target - h_new) / 2) | |
pad_height_bottom = h_target - h_new - pad_height_top | |
return cv2.copyMakeBorder( | |
resized, | |
top=pad_height_top, | |
bottom=pad_height_bottom, | |
left=0, | |
right=0, | |
borderType=cv2.BORDER_CONSTANT, | |
value=(255, 255, 255) | |
) | |
else: | |
# If the new height exceeds the desired height, we resize the image so that | |
# its height fit into the desired height instead. | |
h_new = h_target | |
w_new = int(h_new / r) | |
resized = cv2.resize(img, (w_new, h_new), interpolation=cv2.INTER_AREA) | |
# Fill the rest of the area along the width with white pixels | |
pad_width_left = int((w_target - w_new) / 2) | |
pad_width_right = w_target - w_new - pad_width_left | |
return cv2.copyMakeBorder( | |
resized, | |
top=0, | |
bottom=0, | |
left=pad_width_left, | |
right=pad_width_right, | |
borderType=cv2.BORDER_CONSTANT, | |
value=(255, 255, 255) | |
) | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description="Resize images to a target width\n" | |
"and height with white fill.") | |
parser.add_argument("--input", "-i", type=str, | |
help="Path to the input image.") | |
parser.add_argument("--output", "-o", type=str, | |
help="Path to the output image.") | |
parser.add_argument("--width", "-wt", type=int, | |
help="The desired width of the output image.") | |
parser.add_argument("--height", "-ht", type=int, | |
help="The desired height of the output image.") | |
args = parser.parse_args() | |
# Read the input image | |
img = cv2.imread(str(Path(args.input).resolve())) | |
# Resize the image | |
resized_img = resize_white_fill(img, args.width, args.height) | |
# Save the resized image | |
cv2.imwrite(str(Path(args.output).resolve()), resized_img) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment