I am trying to write a function that takes a pixel as a parameter and inverts each color in the pixel then return the new color values as a tuple. Help would be much appreciated Here is my current code:
IMAGE_URL = "https://codehs.com/uploads/c709d869e62686611c1ac849367b3245"
IMAGE_WIDTH = 280
IMAGE_HEIGHT = 200
image = Image(IMAGE_URL)
image.set_position(70, 70)
image.set_size(IMAGE_WIDTH, IMAGE_HEIGHT)
add(image)
#################################################
# Write your function here. Loop through each pixel
# and set each pixel to have a zero blue value.
#################################################
def remove_blue():
pass
# Give the image time to load
print("Removing Blue Channel ....")
print("Might take a minute....")
timer.set_timeout(remove_blue, 1000)
from PIL import Image
# open image
image = Image.open('pic.jpeg')
# show the image (optional)
image.show()
# load the image into memory
image_data = image.load()
# obtain sizes
height,width = image.size
# loop over and change blue value to 0
for loop1 in range(height):
for loop2 in range(width):
r,g,b = image_data[loop1,loop2]
image_data[loop1,loop2] = r,g,0
image.save('changed.jpeg')
The corresponding function would be
def remove_blue(image):
image = Image.open('pic.jpeg')
# show the image (optional)
image.show()
# load the image into memory
image_data = image.load()
# obtain sizes
height,width = image.size
# loop over and change blue value to 0
for loop1 in range(height):
for loop2 in range(width):
r,g,b = image_data[loop1,loop2]
image_data[loop1,loop2] = r,g,0
# return image
image.save('changed.jpeg')
Related
I am stuck trying to count the number of white pixels per row in a image.
i have tried this
img = cv2.imread("11.jpg") # Its our Image object
mask = np.uint8(np.where(img == 0, 1, 0))
row_counts = cv2.reduce(mask, 1, cv2.REDUCE_SUM, dtype=cv2.CV_32SC1) # type: ignore
#Data Collection
White_row = 224- row_counts # 224 is max pixels in row
So i made my own loop algorithm that loops through every pixel and checks the pixel intensity. The image is converted into grey scale.
img = Image.open("11.jpg")
img = img.convert("L") # convert to grayscale
pix = img.load()
width, height = img.size
print(width, height)
print(pix[91,134]) #Tester
White_row = [0] * height
for y in range(height):
for x in range(width):
if pix[x,y] > 235: # 235 is the threshold
White_row[y] += 1
Max_Width = np.max(White_row)
Mean_Width = np.mean(White_row)
print ("Max_Width: ", Max_Width)
print ("Mean_Width: ", Mean_Width)
How do I convert a list of 1D numbers to a bitmap image?
I tried the following but it seems it doesn't quite work.
from PIL import Image
def get_img():
img = Image.new('RGB', (255,255), "black") # Create a new black image
pixels = img.load() # Create the pixel map
width, height = img.size
for i in range(width): # For every pixel:
for j in range(height):
pixels[i,j] = (i, j, 100) # Set the colour accordingly
return pixels
display(get_img()) # <PixelAccess at 0x7fca63ded7d0>
PIL.Image has a function that takes a numpy array and converts it to an image: Image.from_array. You can use it to generate B&W, grayscale, RGB or RGBA images easily.
In you case, the cleanest way to build the image is:
import numpy as np
from PIL import Image
def get_img(width=255, height=255):
data = np.arange(width * height, dtype=np.int64).reshape((height, width))
img_data = np.empty((height, width, 3), dtype=np.uint8)
img_data[:, :, 0] = data // height
img_data[:, :, 1] = data % width
img_data[:, :, 2] = 100
return Image.fromarray(img_data)
display(get_img())
Result:
Note that although this way of building the data needs to go through the array 3 times, it is still faster than plain-python loops. For the default values of 255 by 255 images, it is almost 30 times faster.
from PIL import Image
from IPython.display import display
img = Image.new('RGB', (255,255), "black") # Create a new black image
list_of_pixels = list(img.getdata())
print(list_of_pixels)
im2 = Image.new(img.mode, img.size)
im2.putdata(list_of_pixels)
display(im2)
I wrote my own affine transformation code, but I want to save the new pixel coordinates I created to apply to the image I own, how can I do this. So how can I save the new pixel coordinate of an image to this image? Here is an example of the part I couldn't do in this code.
img = cv2.imread("high1.jpeg", 0)
new_pixel_coor = np.dot(coefficient_pixel_mat, unknown_parameters).astype(int)
a = len(new_pixel_coor) // 2
new_pixel_coor = new_pixel_coor.reshape((a, 2))
print("Pixel Coordinates", "\n", new_pixel_coor)
img2 = np.zeros((width, height, 3), dtype=np.uint)
# There is an error. I could not do anything to save image
for w in range(width):
for h in range(height):
img[w][h] = img2[new_pixel_coor]
# Show and save the image
cv2.imshow('OutputImage.jpg', img2)
cv2.imwrite('OutputImage.jpg', img2)
Here I use the PIL Library to read and manipulate images. I am confused, how to create a new image from the list of arrays containing binary pixel data, after being converted to binary images.
I have tried it, but the resulting image is of type RGB, not a binary image. The following is the code that I wrote:
from PIL import Image
import numpy as np
img = Image.open('data_train/ga.jpeg')
pixels = img.load()
width, height = img.size
all_pixels = []
for x in range(width):
for y in range(height):
hpixel = pixels[x, y]
img_gray = (0.2989 * hpixel[0]) + (0.5870 * hpixel[1]) + (0.1140 * hpixel[2])
if img_gray >= 110:
all_pixels.append('1')
else:
all_pixels.append('0')
data_isi = {'0': 0,
'1': 255}
data = [data_isi[letter] for letter in all_pixels]
img_new = Image.fromarray(data)
img_new.save('data_train/gabiner.jpeg')
Updated Answer
As you are required to use a for loop, you could go with something more like this:
#!/usr/bin/env python3
from PIL import Image
# Load image and get dimensions
img = Image.open('start.jpg').convert('RGB')
width, height = img.size
# Actually load input pixels, else PIL is too lazy
imi = img.load()
# List of result pixels
imo = []
for y in range(height):
for x in range(width):
R, G, B = imi[x, y]
gray = (0.2989 * R) + (0.5870 * G) + (0.1140 * B)
if gray >= 110:
imo.append(255)
else:
imo.append(0)
# Make output image and put output pixels into it
result = Image.new('L', (width,height))
result.putdata(imo)
# Save result
result.save('result.png')
Which turns this start image:
Into this result:
Original Answer
You appear to be converting the image to greyscale and thresholding at 110, which can be done much more simply, and faster, like this:
#!/usr/local/bin/python3
from PIL import Image
# Load image and make greyscale
im = Image.open('image.png').convert('L')
# Threshold to make black and white
thr = im.point(lambda p: p > 110 and 255)
# Save result
thr.save('result.png')
Im trying to use a specific gamma corrected grayscale implementation - Gleam to convert an images pixels to grayscale. How can i do this manually with PIL python?
def tau_gamma_correct(pixel_channel):
pixel_channel = pixel_channel**(1/2.2)
return pixel_channel
##param: rgb
##result: returns grayscale value
def gleam(rgb):
#convert rgb tuple to list
rgblist = list(rgb)
#gamma correct each rgb channel
rgblist[0] = tau_gamma_correct(rgblist[0])
rgblist[1] = tau_gamma_correct(rgblist[1])
rgblist[2] = tau_gamma_correct(rgblist[2])
grayscale = 1/3*(rgblist[0] + rgblist[1] + rgblist[2])
return grayscale
# get a glob list of jpg filenames
files = glob.glob('*.jpg')
for file in files:
file = open(file)
filename = file.name
image = Image.open(file)
pix = image.load()
width, height = image.size
#print(width,height)
for x in range(0, width):
for y in range(0, height):
rgb = pix[x,y]
#print(rgb)
# calc new pixel value and set to pixel
image.mode = 'L'
pix[x,y] = gleam(rgb)
image.save(filename + 'gray.gleam'+'.jpg')
file.close()
SystemError: new style getargs format but argument is not a tuple
It is still expecting the rgb tuple i think.
I found that i could just build another image:
import sys
import os
import glob
import numpy
from PIL import Image
def tau_gamma_correct(pixel_channel):
pixel_channel = pixel_channel**(1/2.2)
return pixel_channel
##param: rgb
##result: returns grayscale value
def gleam(rgb):
#convert rgb tuple to list
rgblist = list(rgb)
#gamma correct each rgb channel
rgblist[0] = tau_gamma_correct(rgblist[0])
print('gleamed red ' + str(rgblist[0]))
rgblist[1] = tau_gamma_correct(rgblist[1])
print('gleamed green ' + str(rgblist[1]))
rgblist[2] = tau_gamma_correct(rgblist[2])
print('gleamed blue ' + str(rgblist[0]))
grayscale = (rgblist[0] + rgblist[1] + rgblist[2])/3
print('grayscale '+ str(grayscale))
return grayscale
# get a glob list of jpg filenames
files = glob.glob('*.jpg')
for file in files:
file = open(file)
filename = file.name
image = Image.open(file)
pix = image.load()
width, height = image.size
new_image = Image.new('L', image.size)
#pixelmatrix = [width][height]
pixelmatrix = numpy.zeros((width, height))
#print(width,height)
for x in range(0, width):
for y in range(0, height):
rgb = pix[x,y]
print('current pixel value: '+str(rgb))
# calc new pixel value and set to pixel
#print(gleam(rgb))
gray = gleam(rgb)
print('changing to pixel value: '+str(gray))
pixelmatrix[x,y] = gray
new_image.save(filename + 'gray.gleam'+'.jpg')
new_image.putdata(pixelmatrix)
file.close()
The problem is that image.mode = 'L' doesn't actually change the type of the image, it just changes the attribute so it's no longer accurate. To change the mode of the image you need to make a new copy with image.convert('L').
Once you have an image in grayscale mode, it won't require a tuple for a pixel value anymore.
Seeing the SystemError: new style getargs format but argument is not a tuple error it seems that you need to return a tuple, which is represented as :
sample_tuple = (1, 2, 3, 4)
So we edit the gleam() function as:
def gleam(rgb):
#convert rgb tuple to list
rgblist = list(rgb)
#gamma correct each rgb channel
rgblist[0] = tau_gamma_correct(rgblist[0])
rgblist[1] = tau_gamma_correct(rgblist[1])
rgblist[2] = tau_gamma_correct(rgblist[2])
grayscale = 1/3*(rgblist[0] + rgblist[1] + rgblist[2])
return (grayscale, )
Keep in mind that while returning a single element tuple you need to represent as :
sample_tuple = (1, )
This is due to the fact that (4) == 4 but (4, ) != 4