Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 436
argentum2f Avatar asked May 14 '15 23:05

argentum2f


People also ask

Why won't OpenCV draw to NumPy arrays?

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 ().

What is the default array type for OpenCV images?

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.

How to read an image to NumPy ndarray in Python?

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.

What is image processing in Python using OpenCV?

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).


3 Answers

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
like image 82
rayryeng Avatar answered Sep 28 '22 02:09

rayryeng


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

like image 26
Sri Chakra Kumar Avatar answered Sep 28 '22 00:09

Sri Chakra Kumar


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
like image 20
dwSun Avatar answered Sep 28 '22 01:09

dwSun