Resize an image without distortion OpenCV
Solution 1
You may try below. The function will keep the aspect rate of the original image.
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
Here is an example usage.
image = image_resize(image, height = 800)
Hope this helps.
Solution 2
If you need to modify the image resolution and keep your aspect ratio use the function imutils (check documentation). something like this:
img = cv2.imread(file , 0)
img = imutils.resize(img, width=1280)
cv2.imshow('image' , img)
hope that helps, good luck !
Solution 3
Try this simple function in python that uses OpenCV. just pass the image and mention the size of square you want.
def resize_image(img, size=(28,28)):
h, w = img.shape[:2]
c = img.shape[2] if len(img.shape)>2 else 1
if h == w:
return cv2.resize(img, size, cv2.INTER_AREA)
dif = h if h > w else w
interpolation = cv2.INTER_AREA if dif > (size[0]+size[1])//2 else
cv2.INTER_CUBIC
x_pos = (dif - w)//2
y_pos = (dif - h)//2
if len(img.shape) == 2:
mask = np.zeros((dif, dif), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w] = img[:h, :w]
else:
mask = np.zeros((dif, dif, c), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w, :] = img[:h, :w, :]
return cv2.resize(mask, size, interpolation)
usage: squared_image=get_square(image, size=(28,28))
explanation: function takes input of any size and it creates a squared shape blank image of size image's height or width whichever is bigger. it then places the original image at the center of the blank image. and then it resizes this square image into desired size so the shape of original image content gets preserved.
hope , this will help you
Solution 4
The answer, provided by @vijay jha is too case specific. Also includes additional unnecessary padding. I propose fixed code below:
def resize2SquareKeepingAspectRation(img, size, interpolation):
h, w = img.shape[:2]
c = None if len(img.shape) < 3 else img.shape[2]
if h == w: return cv2.resize(img, (size, size), interpolation)
if h > w: dif = h
else: dif = w
x_pos = int((dif - w)/2.)
y_pos = int((dif - h)/2.)
if c is None:
mask = np.zeros((dif, dif), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w] = img[:h, :w]
else:
mask = np.zeros((dif, dif, c), dtype=img.dtype)
mask[y_pos:y_pos+h, x_pos:x_pos+w, :] = img[:h, :w, :]
return cv2.resize(mask, (size, size), interpolation)
The code resizes an image making it square and keeping aspect ration at the same time. Also the code is suitable for 3 channels (colored) images as well. Example of usage:
resized = resize2SquareKeepingAspectRation(img, size, cv2.INTER_AREA)
Solution 5
All other answers use pads to correct the aspect ratio which usually is very bad when you are trying to create standardized datasets for a neural network. Below is a simple implementation of a crop-and-resize that maintain the aspect ratio and does not create pads.
def crop_square(img, size, interpolation=cv2.INTER_AREA):
h, w = img.shape[:2]
min_size = np.amin([h,w])
# Centralize and crop
crop_img = img[int(h/2-min_size/2):int(h/2+min_size/2), int(w/2-min_size/2):int(w/2+min_size/2)]
resized = cv2.resize(crop_img, (size, size), interpolation=interpolation)
return resized
Example:
img2 = crop_square(img, 300)
Original:
Resized:
Tanmay Bhatnagar
Updated on July 05, 2022Comments
-
Tanmay Bhatnagar almost 2 years
I am using python 3 and latest version of openCV. I am trying to resize an image using the resize function provided but after resizing the image is very distorted. Code :
import cv2 file = "/home/tanmay/Desktop/test_image.png" img = cv2.imread(file , 0) print(img.shape) cv2.imshow('img' , img) k = cv2.waitKey(0) if k == 27: cv2.destroyWindow('img') resize_img = cv2.resize(img , (28 , 28)) cv2.imshow('img' , resize_img) x = cv2.waitKey(0) if x == 27: cv2.destroyWindow('img')
The original image is 480 x 640 (RGB therefore i passed the 0 to get it to grayscale)
Is there any way i could resize it and avoid the distortion using OpenCV or any other library perhaps? I intend to make a handwritten digit recogniser and i have trained my neural network using the MNIST data therefore i need the image to be 28x28.
-
Tanmay Bhatnagar almost 7 yearsWhat if I want to change the aspect ratio of the original image ? I want to get every image to 28x28 no matter its original dimensions.
-
thewaywewere almost 7 yearsThen, go straight to use
cv2.resize(image, (28,28), interpolation = inter)
. -
thewaywewere almost 7 years@TanmayBhatnagar could you also give me a vote up if my answer helps to solve your problem?
-
Tanmay Bhatnagar almost 7 yearsCould you please explain what interpolation is ? I know that it helps reduce the error that occurs due to resizing the image but how do we decide which technique to use ? Is it just hit and trial?
-
thewaywewere almost 7 years@TanmayBhatnagar you could refer to this tutorial on cv2.resize docs.opencv.org/3.0-beta/modules/imgproc/doc/….
-
Mitali Cyrus about 6 yearsjk is not defined
-
vijay jha about 6 yearsthank you @Mitali Cyrus for the bug report. i fixed that.
-
TheSHETTY-Paradise over 5 yearsRemember to input a numpy array of pixels rather than giving location of the image in that function
-
Cătălina Sîrbu about 4 yearsbut how to also modify the height ?
-
Andrei M. almost 4 yearsThis made the most sense for me.
-
MikeW over 3 yearsThe code modifies the height in keeping aspect ratio the same.
-
jtlz2 over 3 yearsRemove
self
..? -
Nurzhan Nogerbek over 3 yearsAt the moment, the square is colored black background. How to make a square box transparent background?
-
Alexey Antonenko over 3 years@NurzhanNogerbek, you might want to transform an image to RGBA format. A-channel is used to encode transparency.
-
Iulian Pinzaru almost 3 yearsI used it for Stylegan2-ada to resize to square images, thanks it worked awesome!