Made a gradient with PIL module, it turned out darker - python

I was trying to use the PIL module to make the colorpicker gradient
Like this.
I made a code to test out:
from PIL import Image
img = Image.new('HSV', (255,255), "white")
pix = img.load()
H = 0
for x in range(img.size[0]):
S =(int(100*(x/float(img.size[0])))) # A % of image width
for y in range(img.size[1]):
V = (int(100*(1-(y/float(img.size[1]))))) # A % of image height
pix[x,y] = (H,S,V)
img.show()
But my image turns out dark. What did I do wrong?

You are generating S and V values in the 0..100 range. However, I'm pretty sure that a PIL HSV image uses 0..255 values; in other words, you're only using the bottom 40% of the range.

Related

Optimising a transform of image with a given function using PIL?

I'm trying to transform a given image from a given coordinate to a coordinate on a given image.
I've written an example code using ImageDraw, but with size being 2000 it is too slow for my purpose.
from PIL import Image, ImageDraw
size = [size]
img = Image.new('RGB', (size,size), color = (255,200,100))
draw = ImageDraw.Draw(img)
pix = [pixel data]
for X in range(0,size):
for Y in range (0,size):
draw.point((X, Y), fill=pix[functionX(X),functionY(Y)])
I'm sure it could be done using PIL's funcions faster that my code.

Change colors of photos in PIL

So in my coursework, I am supposed to change the different variations of colors and get an image that looks like the example provided. I have gotten halfway there, but for the life of me cannot figure out how to get the colors to change, even a little bit. Even if the code runs without errors, the colors will not change
i've tried numpy arrays, editing the pixel color, etc. I can not get anything to work.
import PIL
from PIL import Image
from PIL import ImageEnhance
from PIL import ImageDraw
from PIL import ImageFont
fnt = ImageFont.truetype('readonly/fanwood-webfont.ttf', 75)
# read image and convert to RGB
image=Image.open("readonly/msi_recruitment.gif")
image=image.convert('RGB')
drawing_object = ImageDraw.Draw(image)
# build a list of 9 images which have different brightnesses
enhancer=ImageEnhance.Brightness(image)
images=[]
x = 1
for i in range(0, 10):
pixels = img.load()
print(image.size)
x += 1
z = x
if x%3 == 1 :
z = 9
drawing_object.rectangle((0,450,800,325), fill='black')
drawing_object.text((20,350),'channel intensity o 0.{}'.format(z), font=fnt, fill=(255,255,255))
elif x%3 == 0:
z = 5
drawing_object.rectangle((0,450,800,325), fill='black')
drawing_object.text((20,350),'channel intensity o 0.{}'.format(z), font=fnt, fill=(255,255,255))
else:
z = 1
drawing_object.rectangle((0,450,800,325), fill='black')
drawing_object.text((20,350),'channel intensity o 0.{}'.format(z), font=fnt, fill=(255,255,255))
images.append(enhancer.enhance(10/10))
## create a contact sheet from different brightnesses
first_image=images[0]
contact_sheet=PIL.Image.new(first_image.mode, (first_image.width*3,first_image.height*3))
x=0
y=0
for img in images:
# Lets paste the current image into the contact sheet
contact_sheet.paste(img, (x, y) )
# Now we update our X position. If it is going to be the width of the image, then we set it to 0
# and update Y as well to point to the next "line" of the contact sheet.
if x+first_image.width == contact_sheet.width:
x=0
y=y+first_image.height
else:
x=x+first_image.width
# resize and display the contact sheet
contact_sheet = contact_sheet.resize((int(contact_sheet.width/2),int(contact_sheet.height/2) ))
display(contact_sheet)
So in general you can use OpenCVs ColorMap to change colors in your image:
import cv2
img = cv2.imread(r"<IMAGE PATH>")
img = cv2.applyColorMap(img, cv2.COLORMAP_JET) # Change colors of image with predefined colormap
# Display the new image
cv2.imshow("img", img)
cv2.waitKey()
Now if you want to create your own colormap instead of using a predefined one in OpenCV you can do it with cv2.LUT() (OpenCV Documentation)
Example Input:
Example Output:
And here would be a quick example of how to change Gamma with this approach:
def adjust_gamma(img, gamma=1.0):
assert (img.shape[0] == 1)
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) *
255 for i in np.arange(0, 256)]).astype("uint8")
new_img = cv2.LUT(np.array(img, dtype=np.uint8), table)
return new_img
It looks like you have a typo in your loop:
for i in range(0, 10):
# if-elses
...
images.append(enhancer.enhance(10/10))
You're enhancing the image with a factor of 1.0 at each iteration, which according to the docs:
Adjust image brightness.
This class can be used to control the brightness of an image. An enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the original image.
Using z, which I suspect was your intention, will give you the tiers of brightness your comments describe:
for i in range(0, 10):
# if-elses
...
images.append(enhancer.enhance(z/10))
Edit: changed assumed value from i to z, based on the text you're writing.
I should also point out that you probably want to create a temp "watermark" image during the for-loop to apply the text/rectangle to. Since the ImageDraw objects modify the image in-place, you're applying the text on top of each other at each iteration, causing some weird text on the later images.

How to change the color of a pixel using PIL?

I was trying to change pixel of an image in python using this question. If mode is 0, it changes first pixel in top right corner of image to grey(#C8C8C8). But it doesn't change. There is not enough documentation about draw.point(). What is the problem with this code?
import random
from PIL import Image, ImageDraw
mode = 0
image = Image.open("dom.jpg")
draw = ImageDraw.Draw(image)
width = image.size[0]
height = image.size[1]
pix = image.load()
string = "kod"
n = 0
if (mode == 0):
draw.point((0, 0), (200, 200, 200))
if(mode == 1):
print(pix[0,0][0])
image.save("dom.jpg", "JPEG")
del draw
Is using PIL a must in your case? If not then consider using OpenCV (cv2) for altering particular pixels of image.
Code which alter (0,0) pixel to (200,200,200) looks following way in opencv:
import cv2
img = cv2.imread('yourimage.jpg')
height = img.shape[0]
width = img.shape[1]
img[0][0] = [200,200,200]
cv2.imwrite('newimage.bmp',img)
Note that this code saves image in .bmp format - cv2 can also write .jpg images, but as jpg is generally lossy format, some small details might be lost. Keep in mind that in cv2 [0][0] is left upper corner and first value is y-coordinate of pixel, while second is x-coordinate, additionally color are three values from 0 to 255 (inclusive) in BGR order rather than RGB.
For OpenCV tutorials, including installation see this.

coordinate location based off pixel color

I am trying to get specific coordinates in an image. I have marked a red dot in the image at several locations to specify the coordinates I want to get. In GIMP I used the purist red I could find (HTML notation ff000). The idea was that I would iterate through the image until I found a pure shade of red and then print out the coordinates. I am using python and opencv to do so but I can't find any good tutorials (best I could find is this but it's not very clear...at least for me). Here is an example of the image I am dealing with.
I just want to know how to find the coordinates of the pixels with the red dots.
EDIT (added code):
import cv2
import numpy as np
img = cv2.imread('image.jpg')
width, height = img.shape[:2]
for i in range(0,width):
for j in range(0,height):
px = img[i,j]
I don't know what to do from here. I have tried code such as if px == [x,y,z] looking for color detection but that doesn't work.
You can do it with cv2 this way:
image = cv2.imread('image.jpg')
lower_red = np.array([0,0,220]) # BGR-code of your lowest red
upper_red = np.array([10,10,255]) # BGR-code of your highest red
mask = cv2.inRange(image, lower_red, upper_red)
#get all non zero values
coord=cv2.findNonZero(mask)
You can do this with PIL and numpy. I'm sure there is a similar implementation with cv2.
from PIL import Image
import numpy as np
img = Image.open('image.png')
width, height = img.size[:2]
px = np.array(img)
for i in range(height):
for j in range(width):
if(px[i,j,0] == 255 & px[i,j,1] == 0 & px[i,j,2] == 0):
print(i,j,px[i,j])
This doesn't work with the image you provided, since there aren't any pixels that are exactly (255,0,0). Something may have changed when it got compressed to a .jpg, or you didn't make them as red as you thought you did. Perhaps you could try turning off anti-aliasing in GIMP.

Python Imaging Library makes an image reddish

I have opened a grayscale image using the Python Imaging Library, copied every pixel value into another image variable of same size and saved it. Now when I open the new image with an image viewer it looks reddish. I have used the Image.new() method with and without the "white" and "black" arguments got the same reddish output.
My code:
from PIL import Image
import math
def run():
im = Image.open("hrabowski.jpg")
pix = im.load()
print im.size
# print pix[0, 1]
im2 = Image.new("RGB", (2400, 2400))
for i in range(im.size[0]):
for j in range(im.size[0]):
im2.putpixel((i, j), pix[i, j])
im2.save("hrabowski-2400-2400.jpg")
Original image (scaled down to 500 x 500):
Python output of my code (scaled down to 500 x 500):
Could anyone please tell me what I am doing wrong?
Your problem is that you want to create an RGB image which has three channels. Therefore one pixel value consists of three values and not only one (in your case use the gray value of the original image for each of the channels).
I have modified the code accordingly.
A side remark: I am almost sure that there is a better way to do what you want to achieve, there is usually no need to loop through single pixels, but I am not sure what you are after.
from PIL import Image
import math
def run():
im = Image.open("ZHiG0.jpg")
pix = im.load()
print im.size
# print pix[0, 1]
im2 = Image.new("RGB", (2400, 2400))
for i in range(im.size[0]):
for j in range(im.size[0]):
im2.putpixel((i, j), (pix[i, j],pix[i, j],pix[i, j]))
im2.save("ZHiG0-2400-2400.jpg")
run()

Categories

Resources