Discarding alpha channel from images stored as Numpy arrays - python

I load images with numpy/scikit. I know that all images are 200x200 pixels.
When the images are loaded, I notice some have an alpha channel, and therefore have shape (200, 200, 4) instead of (200, 200, 3) which I expect.
Is there a way to delete that last value, discarding the alpha channel and get all images to a nice (200, 200, 3) shape?

Just slice the array to get the first three entries of the last dimension:
image_without_alpha = image[:,:,:3]

scikit-image builtin:
from skimage.color import rgba2rgb
from skimage import data
img_rgba = data.logo()
img_rgb = rgba2rgb(img_rgba)
https://scikit-image.org/docs/dev/user_guide/transforming_image_data.html#conversion-from-rgba-to-rgb-removing-alpha-channel-through-alpha-blending
https://scikit-image.org/docs/dev/api/skimage.color.html#rgba2rgb

Use PIL.Image to remove the alpha channel
from PIL import Image
import numpy as np
img = Image.open("c:\>path_to_image")
img = img.convert("RGB") # remove alpha
image_array = np.asarray(img) # converting image to numpy array
print(image_array.shape)
img.show()
If images are in numpy array to convert the array to Image use Image.fromarray to convert array to Image
pilImage = Image.fromarray(numpy_array)

Related

Numpy array not displaying color dimension of greyscale image after converting from PIL image

I'm trying to convert an RGB image to a greyscale image, then to a numpy array using the following code snippet:
img = Image.open("image1.png")
img = img.convert('L')
img = np.array(img, dtype='f')
print(img.shape)
The result is a numpy array of shape (128, 128). Is there anyway that I could convert a greyscale image to a numpy array so that it would have the color channel as well, i.e. the shape would be (128, 128, 1)?
Like #Mark mentioned in comments, add a dimension to the end if your array using newaxis:
img=img[...,None]
None will do similar as np.newaxis. It does not create a color, but adds a dimension similar to a single channel image.

How do I resize image but maintain features in the image? Python

I have an image that looks like this:
array.resize(20,20,3)
img = Image.fromarray(array, 'RGB')
img.save('my.png',quality=90)
img.show()
It is currently a 500x500x3 NumPy array. The underlying space is a 20x20 grid of cells and I want to resize the image so that each grid cell has entries in a 20x20x3 NumPy Array corresponding to it's RGB values instead of (500/20)*(500/20)*3 entries per cell.
The code above does not seem to work unfortunately as it seems to be giving more entries per cell than I expected although I am not 100% sure.
To resize image with pillow you can use Image.resize()
from PIL import Image
import urllib.request
import numpy as np
data = urllib.request.urlopen('https://i.stack.imgur.com/7bPlZ.png')
old_img = Image.open(data)
new_img = old_img.resize((20, 20))
new_img.save('my.png',quality=90)
new_img.show()
array = np.array(new_img)
print(array)
But resizing image you can create pixels with half-tones.
Maybe you should get values directly from numpy.array. You have solid colors so you could get single pixel from every cell - because every cell has size 25x25 so it could be:
new_array = old_array[::25,::25,:]
and then you don't have to convert to image.
And if you convert this array to image then it should be sharper than create with Image.resize.
from PIL import Image
import urllib.request
import numpy as np
data = urllib.request.urlopen('https://i.stack.imgur.com/7bPlZ.png')
old_img = Image.open(data)
old_array = np.array(old_img)
new_array = array[::25,::25,:]
print(new_array)
new_img = Image.fromarray(new_array)
new_img.save('my.png',quality=90)
new_img.show()
Try this
size = 20, 20
img = Image.fromarray(array, 'RGB')
img.thumbnail(size, Image.ANTIALIAS)
img.save('my.png',quality=90)
img.show()

How to change mode of image from RGB to Grayscale and reshape using numpy?

I want to change the mode to grayscale and reshape the image to 28x28 pixels.
So far I have done this.
from PIL import Image
import numpy as np
img = Image.open('image2.jpg')
print(img.format, img.size, img.mode)
ndarray = np.array(img)
[Image]

How to convert RGB PIL image to numpy array with 3 channels?

I am loading image with the following code
image = PIL.Image.open(file_path)
image = np.array(image)
It works, but the size of array appears to be (X, X, 4), i.e. it has 4 layers. I would like normal RGB layers. Is it possible?
UPDATE
I found that just removing 4th channel is unsufficcient. The following code was required:
image = PIL.Image.open(file_path)
image.thumbnail(resample_size)
image = image.convert("RGB")
image = np.asarray(image, dtype=np.float32) / 255
image = image[:, :, :3]
Why?
The fourth layer is the transparency value for image formats that support transparency, like PNG. If you remove the 4th value it'll be a correct RGB image without transparency.
EDIT:
Example:
>>> import PIL.Image
>>> image = PIL.Image.open('../test.png')
>>> import numpy as np
>>> image = np.array(image)
>>> image.shape
(381, 538, 4)
>>> image[...,:3].shape
(381, 538, 3)
As mentioned by other answers, some images are saved with a 4th channel.
To load image with just RGB channels without using numpy at all:
from PIL import Image
image = Image.open('../test.png').convert('RGB')

How to create a white image in Python?

Upon doing my homework, I stumbled across a problem concerning Python and image manipulation. I must say, using the Image lib is not an option. So here it is
from scipy.misc import imread,imsave
from numpy import zeros
imga = zeros([100,100,3])
h = len(imga)
w = len(imga[0])
for y in range(h):
for x in range(w):
imga[y,x] = [255,255,255]
imsave("Result.jpg",imga)
I would assume it makes my picture white, but it turns it black, and I have no idea why
It's not about the code (and I know it looks very ugly). Its just about the fact, that it is a black image.
Every color in an image is represented by one byte. So to create an image array, you should set it's dtype to uint8.
And, you don't need for-loop to set every elements to 255, you can use fill() method or slice index:
import numpy as np
img = np.zeros([100,100,3],dtype=np.uint8)
img.fill(255) # or img[:] = 255
Easy!
Check the below Code:
whiteFrame = 255 * np.ones((1000,1000,3), np.uint8)
255 is the color for filling the bytes.
1000, 1000 is the size of the image.
3 is the color channel for the image.
And unit8 is the type
Goodluck
Here's a simple way to create a white image with a python one liner.
$ python3 -c "from PIL import Image;Image.new('RGB', (1900, 1080), color = (255,255,255)).save('Img.jpg')"
This will create a white image with a width of 1900 and hight of 1080.
When creating imga, you need to set the unit type. Specifically, change the following line of code:
imga = zeros([100,100,3], dtype=np.uint8)
And, add the following to your imports:
import numpy as np
That gives a white image on my machine.
The headline is too broad and shows up at Google first. I needed a white image and used PIL and numpy. PILlow actually works well with numpy
import numpy as np
from PIL import Image
img = np.zeros([100,100,3],dtype=np.uint8)
img.fill(255) # numpy array!
im = Image.fromarray(img) #convert numpy array to image
im.save('whh.jpg')
Just regarding the headline of this question, I did need a white image as well as a pillow input. And the solutions presented here did not work for me.
Therefore here a different way to generate white images for other purposes:
from PIL import Image
img = Image.new('RGB', (200, 50), color = (255,255,255))
Size and color may be changed in the 2nd and 3rd parameter of the Image.new()-function.
And if you want to write something on this image or save it, this would be example code for this.
from PIL import ImageFont, ImageDraw
fnt = ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", 30)
ImageDraw.Draw(img).text((0,0), "hello world", font=fnt, fill=(0,0,0))
img.save('test.jpg')
# Create an array with a required colours
# The colours are given in BGR [B, G, R]
# The array is created with values of ones, the size is (H, W, Channels)
# The format of the array is uint8
# This array needs to be converted to an image of type uint8
selectedColor = [75, 19, 77] * np.ones((640, 480, 3), np.uint8)
imgSelectedColor = np.uint8(np.absolute(selectedColor))

Categories