Why is cv2.resize transposing the requested dimensions?

Viewed 917
            s1 = image.shape  # Image is an opencv2 image (ndarray)
            w,h,d = s1
            image_ = cv2.resize(image, (w*2, h*2), interpolation = cv2.INTER_CUBIC)
            s2 = image_.shape

In the above, I asked for output to resize to (960,1280), but I get (1280, 960).

What's up with that?

  image_ = cv2.resize(image, None, fx=2, fy=2, interpolation = cv2.INTER_CUBIC)

... works as expected. (No points for pointing this out).

enter image description here

Runnable example:

import cv2

def run():
    cap = cv2.VideoCapture(0)

    while cap.isOpened():
        success, image = cap.read()  # (480, 640, 3)
        if not success:
            print("Ignoring empty camera frame.")
            continue

        s1 = image.shape
        w, h, d = s1
        s2 = (w * 2, h * 2)
        image_ = cv2.resize(image, s2, interpolation=cv2.INTER_CUBIC)
        s3 = image_.shape
        cv2.imshow('Camera',
                   image_
                   )

        key = cv2.waitKey(5)
        if key & 0xFF == 27:
            break
    cap.release()


if __name__ == '__main__':
    run()

1 Answers

Based on OpenCV documentation:

img.shape returns (Height, Width, Number of Channels) where

  1. Height represents the number of pixel rows in the image or the number of pixels in > each column of the image array
  2. Width represents the number of pixel columns in the image or the number of pixels in each row of the image array.
  3. Number of Channels represents the number of components used to represent each pixel.

So resize in opencv should be happened like:

import cv2
 
cap = cv2.VideoCapture(0)
_, img = cap.read()
cap.release()
 
print('Original Dimensions : ',img.shape)
 
scale_percent = 60 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
  
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)

And your question regard why fx=2, fy=2 works as expected, based on this link, when no desired size if given, it computes the new dimensions based on fx and fy to compute the desired dsize:

  • FX: Scale factor along the horizontal axis. When it is 0, it is computed as (double)dsize.width/image.cols
  • FY: Scale factor along the vertical axis. When it is 0, it is computed as (double)dsize.height/image.rows

Desired_size_formula

To wrap up, I guess that's because in OpenCV C++ version, they have considered X in horizontal direction (columns) and Y in vertical direction (rows) and since CV2 is just a wrapping over OpenCV-C++ this mismatch happened for considering what is the first dimension and what is the second as we have in Numpy arrays.

Update HansHirse comment:

OpenCV is a C++ library with a dedicated cv::Mat class representing images. And, for example, for some cv::Mat image, image.size returns a cv::Size object, which has width and height in that order, such that dimension parameters (width, height) in several OpenCV functions are consistent to that. The Python API of OpenCV uses NumPy arrays, which uses row-major order by default, such that for some NumPy array image, image.shape will return height and width in that order. It's not an intentional design choice here.

Related