I am using OpenCV to draw a rectangle on a binary image. My goal is to draw the rectangle on both the original image and its vertically flipped version. However, I encounter an issue when flipping the image using the slicing method. Here’s the code snippet I am using:
import cv2
import numpy as np
# Create a binary image
binary_image = np.zeros((100, 100), dtype=np.uint8)
cv2.rectangle(binary_image, (10, 10), (30, 30), (255), -1)
# Flip the image using slicing
flipped_slicing = binary_image[::-1]
# Try to draw a rectangle on the flipped image
cv2.rectangle(flipped_slicing, (10, 10), (30, 30), (255), -1)
# Flip the image using cv2.flip
flipped_cv2 = cv2.flip(binary_image, 0)
# Draw a rectangle on the flipped image
cv2.rectangle(flipped_cv2, (10, 10), (30, 30), (255), -1)
The issue is that cv2.rectangle
works perfectly on the image flipped with cv2.flip
, but it fails when using the slicing method [::-1]. I expected both methods to produce similar results. Can anyone explain why this difference occurs and how to resolve it?
flipped_slicing_method = binary_image[::-1]
flipped_cv = cv2.flip(binary_image, 0)
print(np.all(flipped_slicing_method==flipped_cv))
>> True
But when I run this code, I get an error.
cv2.rectangle(flipped_slicing_method, (0,0), (400, 400), 255,-1)
the Error is:
error: OpenCV(4.9.0) :-1: error: (-5:Bad argument) in function 'rectangle'
> Overload resolution failed:
> - Layout of the output array img is incompatible with cv::Mat
> - Expected Ptr<cv::UMat> for argument 'img'
> - Layout of the output array img is incompatible with cv::Mat
> - Expected Ptr<cv::UMat> for argument 'img'
A look at the flags attribute of the Numpy arrays, shows that slicing gives non contiguous data, and that the result does not own this data:
>>> flipped_slicing.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
>>> flipped_cv2.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
This is confirmed by the strides attributes:
>>> flipped_slicing.strides
(-100, 1)
>>> flipped_cv2.strides
(100, 1)
OpenCV can operate on non-contiguous arrays, but it requires the stride (called "step" in the documentation) to be non negative. So your code will work with positive slicing, but not with negative one, as you need for your flipping operation.