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()
Answer from bikz05 on Stack OverflowYou 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()
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
python - how to load a color image file as a numpy array? - Stack Overflow
python - Converting Numpy Array to OpenCV Array - Stack Overflow
numpy - Creating an RGB picture in Python with OpenCV from a randomized array - Stack Overflow
How to convert RGB array to image?
You can use newer OpenCV python interface (if I'm not mistaken it is available since OpenCV 2.2). It natively uses numpy arrays:
import cv2
im = cv2.imread("abc.tiff")
print(type(im))
result:
<type 'numpy.ndarray'>
PIL (Python Imaging Library) and Numpy work well together.
I use the following functions.
from PIL import Image
import numpy as np
def load_image( infilename ) :
img = Image.open( infilename )
img.load()
data = np.asarray( img, dtype="int32" )
return data
def save_image( npdata, outfilename ) :
img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
img.save( outfilename )
The 'Image.fromarray' is a little ugly because I clip incoming data to [0,255], convert to bytes, then create a grayscale image. I mostly work in gray.
An RGB image would be something like:
out_img = Image.fromarray( ycc_uint8, "RGB" )
out_img.save( "ycc.tif" )
Your code can be fixed as follows:
import numpy as np, cv
vis = np.zeros((384, 836), np.float32)
h,w = vis.shape
vis2 = cv.CreateMat(h, w, cv.CV_32FC3)
vis0 = cv.fromarray(vis)
cv.CvtColor(vis0, vis2, cv.CV_GRAY2BGR)
Short explanation:
np.uint32data type is not supported by OpenCV (it supportsuint8,int8,uint16,int16,int32,float32,float64)cv.CvtColorcan't handle numpy arrays so both arguments has to be converted to OpenCV type.cv.fromarraydo this conversion.- Both arguments of
cv.CvtColormust have the same depth. So I've changed source type to 32bit float to match the ddestination.
Also I recommend you use newer version of OpenCV python API because it uses numpy arrays as primary data type:
import numpy as np, cv2
vis = np.zeros((384, 836), np.float32)
vis2 = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
This is what worked for me...
import cv2
import numpy as np
#Created an image (really an ndarray) with three channels
new_image = np.ndarray((3, num_rows, num_cols), dtype=int)
#Did manipulations for my project where my array values went way over 255
#Eventually returned numbers to between 0 and 255
#Converted the datatype to np.uint8
new_image = new_image.astype(np.uint8)
#Separated the channels in my new image
new_image_red, new_image_green, new_image_blue = new_image
#Stacked the channels
new_rgb = np.dstack([new_image_red, new_image_green, new_image_blue])
#Displayed the image
cv2.imshow("WindowNameHere", new_rgbrgb)
cv2.waitKey(0)
RGB image is composed of three grayscale images. You can make three grayscale images like
rgb = np.random.randint(255, size=(900,800,3),dtype=np.uint8)
cv2.imshow('RGB',rgb)
cv2.waitKey(0)
First, you should define a random image data consisting of 3 channels using numpy as shown below-
import numpy as np
data = np.random.randint(0, 255, size=(900, 800, 3), dtype=np.uint8)
Now use, python imaging library as shown below-
from PIL import Image
img = Image.fromarray(data, 'RGB')
img.show()
You can also save the image easily using save function
img.save('image.png')
So I tried to convert a raw RGB array to an image with this simple code:
import numpy as np
from PIL import Image
Canvas = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 0], [0, 0, 0]])
img = Image.fromarray(Canvas, 'RGB')
img = img.save("canvas.png")
I have no idea how to set the size of the image as a resolution of 2x2 because this code does not create the correct resolution
The first pixel in Canvas should be red, second pixel should be green, the third and fourth pixels should be black
All I want is a 2x2 resolution image where the top-left pixel is red and the top-right pixel is green, then both bottom pixels should be black, but my code is just producing the wrong image resolution with the wrong pixel locations. What is the issue?
In your comment you specify that the red_arr, etc. are arrays of the range -4000 to 4000.
But if we take a look at the specifications of the Image.from_array modes, then we see that it expects a matrix of three bytes (values from zero to 255).
This is however not per se a problem: we can perform:
def rescale(arr):
arr_min = arr.min()
arr_max = arr.max()
return (arr - arr_min) / (arr_max - arr_min)
red_arr_b = 255.0 * rescale(red_arr)
green_arr_b = 255.0 * rescale(green_arr)
blue_arr_b = 255.0 * rescale(blue_arr)
arr[:,:,0] = red_arr_b
arr[:,:,1] = green_arr_b
arr[:,:,2] = blue_arr_b
img = Image.fromarray(arr.astype(int), 'RGB')
So first we rescale to a range 0 to 255, and then we feed that array to the PIL.
It is also possible that we want to scale red, green and blue the same way. In that case we can use:
def rescale(arr):
arr_min = arr.min()
arr_max = arr.max()
return (arr - arr_min) / (arr_max - arr_min)
arr[:,:,0] = red_arr
arr[:,:,1] = green_arr
arr[:,:,2] = blue_arr
arr = 255.0 * rescale(arr)
img = Image.fromarray(arr.astype(int), 'RGB')
Your np array should have data type as uint8:
arr = np.zeros((len(x), len(z), 3),dtype='uint8')
Essentially, PIL calls tobytes function on each strides of your arr and if they are of type int, extra bytes will be generated.
Here are the result of following piece of code with different data type.
import numpy as np
from PIL import Image
size=241
arr = np.zeros((size,size,3))
arr[:,:,0] = [[255]*size]*size
arr[:,:,1] = [[255]*size]*size
arr[:,:,2] = [[0]*size]*size
img = Image.fromarray(arr.astype(int), 'RGB')

import numpy as np
from PIL import Image
size=241
arr = np.zeros((size,size,3))
arr[:,:,0] = [[255]*size]*size
arr[:,:,1] = [[255]*size]*size
arr[:,:,2] = [[0]*size]*size
img = Image.fromarray(arr.astype('uint8'), 'RGB')

As suggested by others, if your original input are not in range (0,255), you will need to rescale them as well.
You can use newer OpenCV python interface (if I'm not mistaken it is available since OpenCV 2.2). It natively uses numpy arrays:
import cv2
im = cv2.imread("abc.tiff",mode='RGB')
print(type(im))
result:
<type 'numpy.ndarray'>
PIL (Python Imaging Library) and Numpy work well together.
I use the following functions.
from PIL import Image
import numpy as np
def load_image( infilename ) :
img = Image.open( infilename )
img.load()
data = np.asarray( img, dtype="int32" )
return data
def save_image( npdata, outfilename ) :
img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
img.save( outfilename )
The 'Image.fromarray' is a little ugly because I clip incoming data to [0,255], convert to bytes, then create a grayscale image. I mostly work in gray.
An RGB image would be something like:
out_img = Image.fromarray( ycc_uint8, "RGB" )
out_img.save( "ycc.tif" )
I did this on your camel image in Python/OpenCV to get two pixels. Channel values are not just 0 and 255.
import cv2
import numpy as np
# load image and get dimensions
img = cv2.imread("camel.jpg")
hh, ww = img.shape[:2]
# get pixel at x=0,y=0
px1 = img[0:1, 0:1]
# get pixel at center of image
hh2 = hh//2
ww2 = ww//2
px2 = img[hh2:hh2+1, ww2:ww2+1]
print(px1)
print(px2)
Results:
[[[0 0 0]]]
[[[129 0 193]]]
But you should be able to just print(img) or use Numpy to crop a region and print it.
Perhaps there is something wrong with your camel.jpeg image, but it gets fixed when saving and posting it. Try uploading the file you posted and see if it has the same issue.
I used Pillow for this and it worked perfectly fine
from PIL import Image
import numpy as np
img = Image.open('camel.jpeg')
img_array = np.array(img)
print(img_array.shape)
print(img_array)
Result
(1477, 1200, 3)
[[[105 159 206]
[106 160 207]
[106 160 207]
...
[215 215 217]
[215 215 217]
[216 216 218]]
[[105 159 206]
[106 160 207]
[106 160 207]
...
It works fine and as you can say the shape of img_array also matched with resolution of camel.jpeg
