argentum2f
argentum2f

Reputation: 5360

Python OpenCV drawing errors after manipulating array with numpy

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.

Upvotes: 8

Views: 9514

Answers (3)

Sri Chakra Kumar
Sri Chakra Kumar

Reputation: 46

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

Upvotes: 2

dwSun
dwSun

Reputation: 11

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

Upvotes: 1

rayryeng
rayryeng

Reputation: 104503

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

Upvotes: 10

Related Questions