I'm reading in an image with OpenCV, and trying to do something with it in numpy (rotate 90deg). Viewing the result with imshow
from matplotlib, it all seems to be working just fine - image is rotated. I can't use drawing methods from OpenCV on the new image, however. In the following code (I'm running this in a sagemath cloud worksheet):
%python
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os, sys
image = np.array( cv2.imread('imagename.png') )
plt.imshow(image,cmap='gray')
image = np.array(np.rot90(image,3) ) # put it right side up
plt.imshow(image,cmap='gray')
cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
plt.imshow(image,cmap='gray')
I get the following error on the cv2.rectangle()
command:
TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
The error goes away if I use np.array(np.rot90(image,4) )
instead (i.e. rotate it 360). So it appears that the change in dimensions is messing it up. Does OpenCV store the dimensions somewhere internally that I need to update or something?
EDIT: Adding image = image.copy()
after rot90()
solved the problem. See rayryeng's answer below.
Opencv appears to have issues drawing to numpy arrays that have the data type np.int64, which is the default data type returned by methods such as np.array and np.full: Show activity on this post. Just for the sake of completeness, it seems that many of us have used the solution of Etienne Perot above, minus .copy ().
When using OpenCV features in Python, we represent images as Numpy arrays. If we use the 8-bit integer representation, it is convenient to give the array type as uint8, but during arithmetic manipulations the arrays may eventually assume floating point types for representing real numbers.
In this tutorial, we will introduce how to read an image to numpy ndarray. Python pillow library also can read an image to numpy ndarray. We will prepare an image which contains alpha chanel. We will start to read it using python opencv. This image is (width, height)= (180, 220), the backgroud of it is transparent.
This is the first of a series of pratical examples of image processing in Python using OpenCV. We will se how simple it is to operate on image files. An image is a function f of two variables (e.g. x and y) which correspond to two spatial dimensions (height and width).
This is apparently a bug in the Python OpenCV wrapper. If you look at this question here: np.rot90() corrupts an opencv image, apparently doing a rotation that doesn't result back in the original dimensions corrupts the image and the OP in that post experiences the same error you are having. FWIW, I also experienced the same bug.... no idea why.
A way around this is to make a copy of the image after you rotate, and then show the image. This I can't really explain, but it seems to work. Also, make sure you call plt.show()
at the end of your code to show the image:
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os, sys
image = np.array( cv2.imread('imagename.png') )
plt.imshow(image,cmap='gray')
image = np.array(np.rot90(image,3) ) # put it right side up
image = image.copy() # Change
plt.imshow(image,cmap='gray')
cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
plt.imshow(image,cmap='gray')
plt.show() # Show image
I faced the same problem with numpy 1.11.2 and opencv 3.3.0. Not sure why, but this did the job for me. Before using cv2.rectangle, add the line below:
image1 = image1.transpose((1,0)).astype(np.uint8).copy()
Reference
Convert data type works for my problem. The image is of type np.int64 before the convert.
image = image.astype(np.int32) # convert data type
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With