Ask Your Question

Revision history [back]

Changing channel ordering in OpenCV prevents rectangle being drawn

I have written some code to create a black image, and then draw a red square in the top-left corner:

import cv2
import numpy as np

x = np.zeros([100, 100, 3], dtype=np.float32)
print(x.shape)
cv2.rectangle(x, (0, 0), (50, 50), (0, 0, 255), -1)
cv2.imwrite('x.png', x)

This saves the following image:

enter image description here

And it prints out the shape of x to be (100, 100, 3). This is all as expected.

However, for reasons I won't explain now, the image actually arrives in a different format. Rather than the channel order being [y, x, colour], which is what OpenCV requires, it arrives as [colour, y, x]. Therefore, I need to change the channel ordering.

So my final code is:

import cv2
import numpy as np

y = np.zeros([3, 100, 100], dtype=np.float32)
y = np.moveaxis(y, 0, 2)
print(y.shape)
cv2.rectangle(y, (0, 0), (50, 50), (0, 0, 255), -1)
cv2.imwrite('y.png', y)

However, this just saves a black image:

enter image description here

But it prints out the shape of y to be (100, 100, 3), i.e. the same as x. And the code below this print out line is effectively the same in both cases. So both images are identical (both are float32 NumPy arrays with zeros everywhere, of dimensions (100, 100, 3)).

So why does changing the channel ordering cause OpenCV to fail at drawing the rectangle, when the images should be identical in these two cases?

Changing channel ordering in OpenCV prevents rectangle being drawn

I have written some code to create a black image, and then draw a red square in the top-left corner:

import cv2
import numpy as np

x = np.zeros([100, 100, 3], dtype=np.float32)
print(x.shape)
cv2.rectangle(x, (0, 0), (50, 50), (0, 0, 255), -1)
cv2.imwrite('x.png', x)

This saves the following image:

enter image description here

And it prints out the shape of x to be (100, 100, 3). This is all as expected.

However, for reasons I won't explain now, the image actually arrives in a different format. Rather than the channel order being [y, x, colour], which is what OpenCV requires, it arrives as [colour, y, x]. Therefore, I need to change the channel ordering.

So my final code is:

import cv2
import numpy as np

y = np.zeros([3, 100, 100], dtype=np.float32)
y = np.moveaxis(y, 0, 2)
print(y.shape)
cv2.rectangle(y, (0, 0), (50, 50), (0, 0, 255), -1)
cv2.imwrite('y.png', y)

However, this just saves a black image:

enter image description here

But it prints out the shape of y to be (100, 100, 3), i.e. the same as x. And the code below this print out line is effectively the same in both cases. So both images are identical (both are float32 NumPy arrays with zeros everywhere, of dimensions (100, 100, 3)).

So why does changing the channel ordering cause OpenCV to fail at drawing the rectangle, when the images should be identical in these two cases?