81

I have searched for similar questions, but haven't found anything helpful as most solutions use older versions of OpenCV.

I have a 3D numpy array, and I would like to display and/or save it as a BGR image using OpenCV (cv2).

As a short example, suppose I had:

import numpy, cv2
b = numpy.zeros([5,5,3])

b[:,:,0] = numpy.ones([5,5])*64
b[:,:,1] = numpy.ones([5,5])*128
b[:,:,2] = numpy.ones([5,5])*192

What I would like to do is save and display b as a color image similar to:

cv2.imwrite('color_img.jpg', b)
cv2.imshow('Color image', b)
cv2.waitKey(0)
cv2.destroyAllWindows()

This doesn't work, presumably because the data type of b isn't correct, but after substantial searching, I can't figure out how to change it to the correct one. If you can offer any pointers, it would be greatly appreciated!

3
  • 2
    Thanks for the comment @beaker! However, the issue in that question is that the poster forgot an argument in imshow(). My issue is that imshow/ imwrite won't take the numpy array as created above. Commented Oct 31, 2014 at 20:08
  • Do you want to save it as BGR or RGB? The title and question have both. Commented Oct 31, 2014 at 20:27
  • @jmanring220 Yes, but the answers still show how to convert a numpy array to a mat. Commented Oct 31, 2014 at 21:02

7 Answers 7

58

You don't need to convert NumPy array to Mat because OpenCV cv2 module can accept NumPyarray. The only thing you need to care for is that {0,1} is mapped to {0,255} and any value bigger than 1 in NumPy array is equal to 255. So you should divide by 255 in your code, as shown below.

img = numpy.zeros([5,5,3])

img[:,:,0] = numpy.ones([5,5])*64/255.0
img[:,:,1] = numpy.ones([5,5])*128/255.0
img[:,:,2] = numpy.ones([5,5])*192/255.0

cv2.imwrite('color_img.jpg', img)
cv2.imshow("image", img)
cv2.waitKey()
Sign up to request clarification or add additional context in comments.

4 Comments

can you please explain why do we multiply by 64, 128 and 192
oh I got it, I think that are just the values that should be in the rgb positions.
If someone might need to invert the color channels: cv2.imshow("color_img.jpg", input[..., ::-1] * 255)
so clear! it is helpful for me
25

You are looking for scipy.misc.toimage:

import scipy.misc
rgb = scipy.misc.toimage(np_array)

It seems to be also in scipy 1.0, but has a deprecation warning. Instead, you can use pillow and PIL.Image.fromarray

5 Comments

This doesn't seem to exist in scipy 0.18.0
The question is asking about approach using OPEN-CV.
Yes. And still my answer is useful for 9 people.
This was actually what I was looking for, I have a numpy array from opencv and I want to show it in the pysimpleui, where it requires a proper image.
12

The images c, d, e , and f in the following show colorspace conversion they also happen to be numpy arrays <type 'numpy.ndarray'>:

import numpy, cv2
def show_pic(p):
        ''' use esc to see the results'''
        print(type(p))
        cv2.imshow('Color image', p)
        while True:
            k = cv2.waitKey(0) & 0xFF
            if k == 27: break 
        return
        cv2.destroyAllWindows()

b = numpy.zeros([200,200,3])

b[:,:,0] = numpy.ones([200,200])*255
b[:,:,1] = numpy.ones([200,200])*255
b[:,:,2] = numpy.ones([200,200])*0
cv2.imwrite('color_img.jpg', b)


c = cv2.imread('color_img.jpg', 1)
c = cv2.cvtColor(c, cv2.COLOR_BGR2RGB)

d = cv2.imread('color_img.jpg', 1)
d = cv2.cvtColor(c, cv2.COLOR_RGB2BGR)

e = cv2.imread('color_img.jpg', -1)
e = cv2.cvtColor(c, cv2.COLOR_BGR2RGB)

f = cv2.imread('color_img.jpg', -1)
f = cv2.cvtColor(c, cv2.COLOR_RGB2BGR)


pictures = [d, c, f, e]

for p in pictures:
        show_pic(p)
# show the matrix
print(c)
print(c.shape)

See here for more info: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor

OR you could:

img = numpy.zeros([200,200,3])

img[:,:,0] = numpy.ones([200,200])*255
img[:,:,1] = numpy.ones([200,200])*255
img[:,:,2] = numpy.ones([200,200])*0

r,g,b = cv2.split(img)
img_bgr = cv2.merge([b,g,r])

Comments

9

This is due to the fact that cv2 uses the type "uint8" from numpy. Therefore, you should define the type when creating the array.

Something like the following:

import numpy
import cv2

b = numpy.zeros([5,5,3], dtype=numpy.uint8)
b[:,:,0] = numpy.ones([5,5])*64
b[:,:,1] = numpy.ones([5,5])*128
b[:,:,2] = numpy.ones([5,5])*192

Comments

7

If anyone else simply wants to display a black image as a background, here e.g. for 500x500 px:

import cv2
import numpy as np

black_screen  = np.zeros([500,500,3])
cv2.imshow("Simple_black", black_screen)
cv2.waitKey(0)

Comments

4

The size of your image is not sufficient to see in a naked eye. So please try to use atleast 50x50

import cv2 as cv
import numpy as np

black_screen = np.zeros([50,50,3])

black_screen[:, :, 2] = np.ones([50,50])*64/255.0
cv.imshow("Simple_black", black_screen)
cv.waitKey(0)
cv.displayAllWindows()

Comments

0
img = np.ones((1080, 720, 3), dtype=np.uint8) * 255

creates white image, the dtype you have to use is np.uint8.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.