You don't necessarily have to convert the image to normalised floats. You have it in the correct shape (MxNx3) and in the correct range (0-255), but it must be of type np.uint8. From the documentation
X : array_like, shape (n, m) or (n, m, 3) or (n, m, 4)
Display the image in X to current axes. X may be a float array, a uint8 array or a PIL image. If X is an array, it can have the following shapes:
MxN – luminance (grayscale, float array only)
MxNx3 – RGB (float or uint8 array)
MxNx4 – RGBA (float or uint8 array)
However, your array data is in BGR format, so you need to reverse the third dimension to bring it to RGB format.
image = np.array(M, dtype=np.uint8)[...,::-1]
Another aspect that caught my attention is your definition of the data. The list of lists represents the rows first, so M actually has red/green in the first row and blue/black in the second. If you want the pixels in the order you stated them, i.e., red/blue and green/black, you have to transpose the rows with the columns.
image_transp = np.transpose(image, (1, 0, 2))
Now you can plot whichever image representation is the correct one (image or image_transp). For the latter, you get
plt.imshow(image_transp, interpolation='none')

I need to do the following:
-
Import an image.
-
Convert image to a 2D array of pixel values (rgb tuples, bytes, whatever it doesn't matter).
-
Manipulate that 2D array (needs to be 2D as I'm using a library that requires a 2D array of data).
-
Convert the newly changed 2D array back into an image.
-
Save the image.
Anyone know how I can accomplish this? PIL Image documentation has some functions to get data but it's all 1D arrays, and I'm not sure how to get them into 2D arrays and then re-convert it back into an image again.
how to convert array of pixel values to image for displaying using python and opencv,numpy - Stack Overflow
python - How to create image from a list of pixel values in Python3? - Stack Overflow
python - How to convert an image into an array of its raw pixel data? - Stack Overflow
Generate pixel image in Python from array - Stack Overflow
You don't necessarily have to convert the image to normalised floats. You have it in the correct shape (MxNx3) and in the correct range (0-255), but it must be of type np.uint8. From the documentation
X : array_like, shape (n, m) or (n, m, 3) or (n, m, 4)
Display the image in X to current axes. X may be a float array, a uint8 array or a PIL image. If X is an array, it can have the following shapes:
MxN – luminance (grayscale, float array only)
MxNx3 – RGB (float or uint8 array)
MxNx4 – RGBA (float or uint8 array)
However, your array data is in BGR format, so you need to reverse the third dimension to bring it to RGB format.
image = np.array(M, dtype=np.uint8)[...,::-1]
Another aspect that caught my attention is your definition of the data. The list of lists represents the rows first, so M actually has red/green in the first row and blue/black in the second. If you want the pixels in the order you stated them, i.e., red/blue and green/black, you have to transpose the rows with the columns.
image_transp = np.transpose(image, (1, 0, 2))
Now you can plot whichever image representation is the correct one (image or image_transp). For the latter, you get
plt.imshow(image_transp, interpolation='none')

The values of your RGB array must represent the desired color; the easiest is maybe to convert RGB values to floats in [0, 1]: (convert [0, 255] --> [0, 1])
import numpy
import matplotlib.pyplot as plt
randim_image1 = numpy.asarray([[(0., 0., 1.), (0., 1., 0.)], [(1., 0., 0.), (0., 0., 0.)]])
plt.imshow(image1, interpolation="none")

PIL and numpy are your friends here:
from PIL import Image
import numpy as np
pixels = [
[(54, 54, 54), (232, 23, 93), (71, 71, 71), (168, 167, 167)],
[(204, 82, 122), (54, 54, 54), (168, 167, 167), (232, 23, 93)],
[(71, 71, 71), (168, 167, 167), (54, 54, 54), (204, 82, 122)],
[(168, 167, 167), (204, 82, 122), (232, 23, 93), (54, 54, 54)]
]
# Convert the pixels into an array using numpy
array = np.array(pixels, dtype=np.uint8)
# Use PIL to create an image from the new array of pixels
new_image = Image.fromarray(array)
new_image.save('new.png')
EDIT:
A little fun with numpy to make an image of random pixels:
from PIL import Image
import numpy as np
def random_img(output, width, height):
array = np.random.random_integers(0,255, (height,width,3))
array = np.array(array, dtype=np.uint8)
img = Image.fromarray(array)
img.save(output)
random_img('random.png', 100, 50)
Haven't used PIL myself, but the best way of finding out is to open an actual image file using PIL. Then explore the API and objects involved with opening said image and look at how the pixel values are stored within the specific object pertaining to the API.
You can then construct a valid PIL image object using your extracted RGB values.
Edit: See the following post: How do I create an image in PIL using a list of RGB tuples?
Additional, accessing pixel values in PIL: https://pillow.readthedocs.io/en/4.3.x/reference/PixelAccess.html
You can do it with Pillow (PIL) library:
from PIL import Image
import numpy as np
path = 'image.png'
image = Image.open(path)
image = np.asarray(image)
Notice that returned arrays have a length of 4 because the ".png" format supports an additional Alpha channel (transparency), so it's RGBA. To get rid of this extra channel, you need to convert an image to RGB format first.
from PIL import Image
import numpy as np
path = 'image.png'
image = Image.open(path).convert('RGB')
image = np.asarray(image)
Read your image with opencv python.
Few things to notice:
- PIL a little bit more user friendly, but opencv will serve you really good if you do heavy image processing stuff
- If you are familar with numpy, I would suggest using opencv because behind the scence, opencv image is actually a numpy array
"""
pip install opencv-python
"""
import cv2
im = cv2.imread("test.png")
# Use this to if you read png image
im = cv2.cvtColor(im,cv2.COLOR_BGRA2RGB)
# Use this to if you read jpg image
# im = cv2.cvtColor(im,cv2.COLOR_BGR2RGB)
print(im[0,0])
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?