Resize an image without distortion OpenCV

132,480

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:

Original

Resized:

enter image description here

Share:
132,480
Tanmay Bhatnagar
Author by

Tanmay Bhatnagar

Updated on July 05, 2022

Comments

  • Tanmay Bhatnagar
    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
    Tanmay Bhatnagar almost 7 years
    What 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
    thewaywewere almost 7 years
    Then, go straight to use cv2.resize(image, (28,28), interpolation = inter).
  • thewaywewere
    thewaywewere almost 7 years
    @TanmayBhatnagar could you also give me a vote up if my answer helps to solve your problem?
  • Tanmay Bhatnagar
    Tanmay Bhatnagar almost 7 years
    Could 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
    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
    Mitali Cyrus about 6 years
    jk is not defined
  • vijay jha
    vijay jha about 6 years
    thank you @Mitali Cyrus for the bug report. i fixed that.
  • TheSHETTY-Paradise
    TheSHETTY-Paradise over 5 years
    Remember to input a numpy array of pixels rather than giving location of the image in that function
  • Cătălina Sîrbu
    Cătălina Sîrbu about 4 years
    but how to also modify the height ?
  • Andrei M.
    Andrei M. almost 4 years
    This made the most sense for me.
  • MikeW
    MikeW over 3 years
    The code modifies the height in keeping aspect ratio the same.
  • jtlz2
    jtlz2 over 3 years
    Remove self..?
  • Nurzhan Nogerbek
    Nurzhan Nogerbek over 3 years
    At the moment, the square is colored black background. How to make a square box transparent background?
  • Alexey Antonenko
    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
    Iulian Pinzaru almost 3 years
    I used it for Stylegan2-ada to resize to square images, thanks it worked awesome!