2

I am trying to perform some image pre-processing for a Python/OpenCV application I am working on. I have a very simple function which loads an image from the file, and resizes it to a certain size:

def get_im(path):
    img = cv2.imread(path, cv2.IMREAD_COLOR)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img, (IMG_ROW, IMG_COL))
    img = np.array(img)
    img = img.astype('float32')
    img /= 255
    return img

While this resizes my images, when it does so it alters the aspect ratio of the image. How can I (preferably using OpenCV) scale the images to fit within a certain size (IMG_ROW, IMG_COL) without altering the aspect ratio?

Derek Brown
  • 4,232
  • 4
  • 27
  • 44

1 Answers1

3

I was able to find a solution based on previous solutions for C++:

# Resize
border_v = 0
border_h = 0
if (IMG_COL/IMG_ROW) >= (img.shape[0]/img.shape[1]):
    border_v = int((((IMG_COL/IMG_ROW)*img.shape[1])-img.shape[0])/2)
else:
    border_h = int((((IMG_ROW/IMG_COL)*img.shape[0])-img.shape[1])/2)
img = cv2.copyMakeBorder(img, border_v, border_v, border_h, border_h, cv2.BORDER_CONSTANT, 0)
img = cv2.resize(img, (IMG_ROW, IMG_COL))

Here is what is going on:

  • Compare the aspect ratio of the input image to the target image to determine whether borders should be added on the vertical (v) or horizontal (h) axis using the if statement.
  • (taking for example the vertical case), I compute the height of an image with the same aspect ratio as the target image, but with width equal to the input image using the formula (IMG_COL/IMG_ROW)*img.shape[1].
  • I then subtract the actual height of the image to determine how large the borders need to be.
  • Finally, divide by two (as border is added top/bottom or left/right) and call cv2.copyMakeBorder, this creates an image with the target aspect ratio with black bars "filling in" the difference between the aspect ratios.

Example (Input -> Output)

Derek Brown
  • 4,232
  • 4
  • 27
  • 44