I'd like to change a pixel and for some reason this isn't working.
from PIL import Image
import numpy
im = Image.open("art\\PlanetX#1.25.png")
a = numpy.asarray(im)
img = Image.fromarray(a)
pixels = img.load()
pixels[0, 0] = (255, 0, 0, 255)
What should happen is the top left corner of the PNG should be set as red. I get the ValueError: Image is readonly error.
If you want to change just a few odd pixels, you can use the rather slow putpixel() like this:
from PIL import Image
# Create blue 30x15 image
im = Image.new('RGB',(30,15),color='blue')
# Change single pixel at 10,0 to red
im.putpixel((10,0),(255,0,0))
Alternatively, you can convert the entire image to a Numpy array and make many more changes, much faster with Numpy functions:
from PIL import Image
import numpy as np
# Create blue 30x15 image
im = Image.new('RGB',(30,15),color='blue')
# Convert to Numpy array
na = np.array(im)
# Change single pixel at 10,0 to green
na[0,10] = (0,255,0)
# Change whole row to red
na[3] = (255,0,0)
# Change whole column to yellow
na[:,8] = (255,255,0)
# Convert back to PIL Image and save
Image.fromarray(na).save('result.png')
Related
I'm trying to understand how image is stored as RGB value
I just realized image that has been read by cv2.imread() method is just bunch of numbers especially RGB number stored in numpy.ndarray for every pixel when I check with builtin function type()
import cv2
im = cv2.imread('./rgb.png', cv2.IMREAD_UNCHANGED)
print(type(im)) # Output: numpy.ndarray
But I still don't know what representation of each index in that array
To understand it, I want make 3col * 4row image manually with numpy.ndarray
I expect image where:
first column filled with red (255,0,0)
second column filled with green (0,255,0)
third column filled with blue (0,0,255)
for all rows!
Using numpy.ndarray declaration that stored in a variable for example im and successfully saved according what I expect
im = np.ndarray('What should I fill in here?')
cv2.imwrite('success.jpg',im)
See if this helps. I create an empty numpy array, then I fill each quadrant with a solid color:
import numpy as np
from PIL import Image
im = np.zeros( (480,640,3), dtype=np.uint8 )
im[:240,:320,:] = (255,0,0)
im[:240,320:,:] = (0,255,0)
im[240:,:320,:] = (0,0,255)
im[240:,320:,:] = (255,255,255)
print(im.shape)
p = Image.fromarray(im)
p.save('x.jpg')
Output:
I have found some examples on this site. I would like to create, example 6. Can you help?
Create, as a numpy array, the image of the napkin. The squares have a size of 10×10. You may use the command numpy tile. Save the resulting image to a file.
In a standard grayscale image, black pixels are 0, gray pixels are 128, and white ones are 255:
import numpy as np
import matplotlib.pyplot as plt
# first create one 20 x 20 tile
a1 = np.zeros((20,20), dtype=int)
a1[10:20,0:10] = a1[0:10,10:20] = 128
a1[10:20,10:20] = 255
# fill the whole 100 x 100 area with the tiles
a = np.tile(a1, (5,5))
# plot and save
plt.imshow(a, 'Greys_r')
plt.savefig('pattern.png')
You could do this:
from PIL import Image
import numpy as np
# Make grey 2x2 image
TwoByTwo = np.full((2,2), 128, np.uint8)
# Change top-left to black, bottom-right to white
TwoByTwo[0,0] = 0
TwoByTwo[1,1] = 255
# Tile it
tiled = np.tile(TwoByTwo, (5,5))
# Make into PIL Image, rescale in size and save
Image.fromarray(tiled).resize((100,100), Image.NEAREST).save('result.png')
I want to make the visible part of image more transparent, but also do not change the alpha-level of fully-transparent background.
Here's the image:
and I do it like this:
from PIL import Image
img = Image.open('image_with_transparent_background.png')
img.putalpha(128)
img.save('half_transparent_image_with_preserved_background.png')
And here is what I get: half_transparent_image_with_preserved_background.png
How do I achieve exactly what I want - so, without changing the background?
I think you want to make the alpha 128 anywhere it is currently non-zero:
from PIL import Image
# Load image and extract alpha channel
im = Image.open('moth.png')
A = im.getchannel('A')
# Make all opaque pixels into semi-opaque
newA = A.point(lambda i: 128 if i>0 else 0)
# Put new alpha channel back into original image and save
im.putalpha(newA)
im.save('result.png')
If you are happier doing that with Numpy, you can do:
from PIL import Image
import numpy as np
# Load image and make into Numpy array
im = Image.open('moth.png')
na = np.array(im)
# Make alpha 128 anywhere is is non-zero
na[...,3] = 128 * (na[...,3] > 0)
# Convert back to PIL Image and save
Image.fromarray(na).save('result.png')
I have an image like this:
and i want to transform the image so that the white space is rectified.
The desired output should look something like this:
Can you help me archive this?
You can do it like this...
Open input image, make greyscale and threshold into Numpy array
Make output image same size as input, but fully black
Iterate over the columns of the image, finding the first and last white pixel in each column. Copy that column of pixels to output image centred on the horizontal centreline
Save result
#!/usr/bin/env python3
from PIL import Image
import numpy as np
# Open wavy image and make greyscale
i = Image.open('wavy.jpg').convert('L')
# Make Numpy version of input image and threshold at 128
i = np.array(i)
i = np.where(i>128, np.uint8(255), np.uint8(0))
# Make Numpy version of output image - all black initially
o = np.zeros_like(i)
h, w = i.shape
# Process each column, copying white pixels from input image
# ... to output image centred on horizontal centreline
centre = h//2
for col in range(w):
# Find top and bottom white pixel in this column
whites = np.nonzero(i[:,col])
top = whites[0][0] # top white pixel
bot = whites[0][-1] # bottom white pixel
thk = bot - top # thickness of sandwich filling
# Copy those pixels to output image
startrow = centre - thk//2
o[startrow:startrow+thk,col] = i[top:bot,col]
Image.fromarray(o).save('result.png')
How can you display only a single color from a RGB image with OpenCV in python ?
The idea is to be able to print the image in a grey scale corresponding to the intensity of a certain color in the RGB spectrum.
You can either use split:
blue, green, red = cv2.split(img)
Or, as this is a costly operation in terms of time and you only need one of the channles (for instance, red) you can directly slice the original image like as follows:
red = img[:,:,2]
Which will return a greyscaled image where the brighter pixels are the ones that have higher red values in the original image.
Hope this helped!
# import usefull libraries
import numpy as np
import cv2
# Set global parameters
RED = 0
GREEN = 1
BLUE = 2
# Load the image
img_color = cv2.imread("fruits.jpg", flags=cv2.IMREAD_COLOR)
# Filter the image by desired color
img_color_filtered = np.asarray([y[RED] for x in img_color for y in x]).reshape((img_color.shape[:2]))
img = Image.open(f"./smoke/first/mistake_cat" + ".png")
data = np.array(img)
red, green, blue, alpha = data.T # Трансформируем матрицу и распаковываем
img_red = Image.fromarray(red)
img_green = Image.fromarray(green)
img_blue = Image.fromarray(blue)
img_alpha = Image.fromarray(alpha)