Creating an RGB picture in Python with OpenCV from a randomized array - python

I want to create a RGB image made from a random array of pixel values in Python with OpenCV/Numpy setup.
I'm able to create a Gray image - which looks amazingly live; with this code:
import numpy as np
import cv2
pic_array=np.random.randint(255, size=(900,800))
pic_array_8bit=slika_array.astype(np.uint8)
pic_g=cv2.imwrite("pic-from-random-array.png", pic_array_8bit)
But I want to make it in color as well. I've tried converting with cv2.cvtColor() but it couldnt work.
The issue might be in an array definition or a missed step. Couldn't find a similar situation... Any help how to make a random RGB image in color, would be great.
thanks!

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

Related

cv2.read or Image from PIL changes PNG image color

Seems like cv2.imread() or Image.fromarray() is changing original image color to a bluish color. What i am trying to accomplish is to crop the original png image and keep the same colors but the color changes. Not sure how to revert to original color. Please help! ty
`
# start cropping logic
img = cv2.imread("image.png") # import cv2
crop = img[1280:, 2250:2730]
cropped_rendered_image = Image.fromarray(crop) #from PIL import Image
cropped_rendered_image.save("newImageName.png")
`
tried this and other fixes but no luck yet
https://stackoverflow.com/a/50720612/13206968
There is no "changing" going on. It's simply a matter of channel order.
OpenCV natively uses BGR order (in numpy arrays)
PIL natively uses RGB order
Numpy doesn't care
When you call cv.imread(), you're getting BGR data in a numpy array.
When you repackage that into a PIL Image, you are giving it BGR order data, but you're telling it that it's RGB, so PIL takes your word for it... and misinterprets the data.
You can try telling PIL that it's BGR;24 data. See https://pillow.readthedocs.io/en/stable/handbook/concepts.html
Or you can use cv.cvtColor() with the cv.COLOR_BGR2RGB flag (because you have BGR and you want RGB). For the opposite direction, there is the cv.COLOR_RGB2BGR flag.

cv2 in Python crashes when I try to open a 4 level CMYK numpy array

import numpy as np
from PIL import Image
import cv2
with Image.open("image.png") as im:
im = im.convert("CMYK")# not a true CMYK conversion here
im.show(title="image")
img = np.array(im)
#cv2.imshow('image', img)
I need to view a CMYK file hopefully using OpenCV and read pixel values in the CMYK space. I tried to load an image, convert it to CMYK(just 4 color levels) and view it using cv2. Note, I have cv2* commented out because it will cause Python to crash and OpenCv will need to be reinstalled. Will OpenCv allow me to view a (x, x, 0:3).uint8 numpy array? If so, throw me a line.
My solution was simple. I forgot the following:
cv2.waitKey(0)
cv2.destroyAllWindows()

The dimension of the array of an image is 3D not 2D as it is in the Python course

In my python course, the instructor uploads a greyscale picture of himself and reads it on Python with the following code:
import numpy as np
import math
from PIL import Image
from IPython.display import display
im = Image.open("chris.tiff")
array = np.array(im)
print(array.shape)
and he gets
(200,200)
When I write the code and run my own image, with the exact same extension "tiff", I get a 3-dimensional array. I was told it's because my image was colored and so the third entry is for RBG. So I used a greyscale photo just like he did but I still obtain a 3D array, why?
Any help is greatly appreciated, thank you
EDIT
For extra clarity, the array I get for my greyscale image with tiff extension is
(3088, 2316, 4)
Your photo appears to be grey, but actually, it has the three channels based on the posted shape.
So, you need to convert it to greyscale using the following line:
im = Image.open("chris.tiff").convert('L')

PIL image to array and back

EDIT: Sorry, the first version of the code was bullshit, I tried to remove useless information and made a mistake. Problem stays the same, but now it's the code I actually used
I think my problem is probably very basic but I cant find a solution. I basically just wanted to play around with PIL and convert an image to an array and backward, then save the image. It should look the same, right? In my case the new image is just gibberish, it seems to have some structure but it is not a picture of a plane like it should be:
def array_image_save(array, image_path ='plane_2.bmp'):
image = Image.fromarray(array, 'RGB')
image.save(image_path)
print("Saved image: {}".format(image_path))
im = Image.open('plane.bmp').convert('L')
w,h = im.size
array_image_save(np.array(list(im.getdata())).reshape((w,h)))
Not entirely sure what you are trying to achieve but if you just want to transform the image to a numpy array and back, the following works:
from PIL import Image
import numpy as np
def array_image_save(array, image_path ='plane_2.bmp'):
image = Image.fromarray(array)
image.save(image_path)
print("Saved image: {}".format(image_path))
im = Image.open('plane.bmp')
array_image_save(np.array(im))
You can just pass a PIL image to np.array and it takes care of the proper shaping. The reason you get distorted data is because you convert the pil image to greyscale (.convert('L')) but then try to save it as RGB.

Python: How to write a single channel png file from numpy array?

I want to write a single channel png image from a numpy array in python?
In Matlab that would be
A = randi(100,100,255)
imwrite(uint8(A),'myFilename.png','png');
I saw exampels using from PIL import Image and Image.fromarray() but they are for jpeg and 3-channel pngs only it appears...
I already found the solution using opencv, I will post it here. Hopefully it will shorten someone else's searching...
Here is a solution using opencv / cv2
import cv2
myImg = np.random.randint(255, size=(200, 400)) # create a random image
cv2.imwrite('myImage.png',myImg)
PIL's Image.fromarray() automatically determines the mode to use from the datatype of the passed numpy array, for example for an 8-bit greyscale image you can use:
from PIL import Image
import numpy as np
data = np.random.randint(256, size=(100, 100), dtype=np.uint8)
img = Image.fromarray(data) # uses mode='L'
This however only works if your array uses a compatible datatype, if you simply use data = np.random.randint(256, size=(100, 100)) that can result in a int64 array (typestr <i8), which PIL can't handle.
You can also specify a different mode, e.g. to interpret a 32bit array as an RGB image:
data = np.random.randint(2**32, size=(100, 100), dtype=np.uint32)
img = Image.fromarray(data, mode='RGB')
Internally Image.fromarray() simply tries to guess the correct mode and size and then invokes Image.frombuffer().
The image can then be saved as any format PIL can handle e.g: img.save('filename.png')
You might want not to utilise OpenCV for simple image manipulation. As suggested, use PIL:
im = Image.fromarray(arr)
im.save("output.png", "PNG")
Have you tried this? What has failed here that led you to concluding that this is JPEG-only?

Categories

Resources