Python (creating a negative of this black and white image) - python

I am trying to create a negative of this black and white image. The opposite of white (255) is black (0) and vice versa. The opposite of a pixel with a value of 100 is 155.
I cannot use convert, invert, point, eval, lambda.
Here is my code but it doesnt work yet. Could you please let me know which part i am wrong.
def bw_negative(filename):
"""
This function creates a black and white negative of a bitmap image
using the following parameters:
filename is the name of the bitmap image
"""
#Create the handle and then create a list of pixels.
image = Image.open(filename)
pixels = list(image.getdata())
pixel[255] = 0
pixel[0] = 255
for i in range(255,0):
for j in range(0,255):
pixel[i] = j
print pixels[i]
image.putdata(pixels)
image.save ('new.bmp')

Python is an interpreted language, which has the advantage that you can use an interactive interpreter-session to try out things. Try to open the image file in an interactive session and look at the list you get from list(image.getdata()). Once you understand what that list contains, you can think about a way to invert the image.

Related

How to remove the empty images using python [duplicate]

Using the Python Imaging Library PIL how can someone detect if an image has all it's pixels black or white?
~Update~
Condition: Not iterate through each pixel!
if not img.getbbox():
... will test to see whether an image is completely black. (Image.getbbox() returns the falsy None if there are no non-black pixels in the image, otherwise it returns a tuple of points, which is truthy.) To test whether an image is completely white, invert it first:
if not ImageChops.invert(img).getbbox():
You can also use img.getextrema(). This will tell you the highest and lowest values within the image. To work with this most easily you should probably convert the image to grayscale mode first (otherwise the extrema might be an RGB or RGBA tuple, or a single grayscale value, or an index, and you have to deal with all those).
extrema = img.convert("L").getextrema()
if extrema == (0, 0):
# all black
elif extrema == (1, 1):
# all white
The latter method will likely be faster, but not so you'd notice in most applications (both will be quite fast).
A one-line version of the above technique that tests for either black or white:
if sum(img.convert("L").getextrema()) in (0, 2):
# either all black or all white
Expanding on Kindall:
if you look at an image called img with:
extrema = img.convert("L").getextrema()
It gives you a range of the values in the images. So an all black image would be (0,0) and an all white image is (255,255). So you can look at:
if extrema[0] == extrema[1]:
return("This image is one solid color, so I won't use it")
else:
# do something with the image img
pass
Useful to me when I was creating a thumbnail from some data and wanted to make sure it was reading correctly.
from PIL import Image
img = Image.open("test.png")
clrs = img.getcolors()
clrs contains [("num of occurences","color"),...]
By checking for len(clrs) == 1 you can verify if the image contains only one color and by looking at the second element of the first tuple in clrs you can infer the color.
In case the image contains multiple colors, then by taking the number of occurences into account you can also handle almost-completly-single-colored images if 99% of the pixles share the same color.
I tried the Kindall solution ImageChops.invert(img).getbbox() without success, my test images failed.
I had noticed a problem, white should be 255 BUT I have found white images where numeric extrema are (0,0).. why? See the update below.
I have changed Kindall second solution (getextrema), that works right, in a way that doesn't need image conversion, I wrote a function and verified that works with Grayscale and RGB images both:
def is_monochromatic_image(img):
extr = img.getextrema()
a = 0
for i in extr:
if isinstance(i, tuple):
a += abs(i[0] - i[1])
else:
a = abs(extr[0] - extr[1])
break
return a == 0
The img argument is a PIL Image object.
You can also check, with small modifications, if images are black or white.. but you have to decide if "white" is 0 or 255, perhaps you have the definitive answer, I have not. :-)
Hope useful
UPDATE: I suppose that white images with zeros inside.. may be PNG or other image format with transparency.

Swap Red and Blue Pixels of Image

I am trying to create a function that will allow me to swap every red and blue pixel of an image. However, when running the function, new image does not change or do the intended. So far, I am only trying to change the image to only blue filter to test the function.
from CSE8AImage import *
img = load_img('images/cat.jpg')
def complement(img):
for r in range(len(img)):
for c in range(len(img[r])):
pix = img[r][c]
img[r][c] = (0, 0, pix[2])
return img
save_img(img, 'complement_cat.jpg')
What you're doing in your code is simply setting the red and green pixels to 0(assuming it's RGB? I couldn't find anything about the CSE8AImage library outside of this page which perfectly matches your question). I will continue assuming it's in RGB.
What you should change in your code to make it work is simply change img[r][c] = (0,0,pix[2]) to img[r][c] = pix[[2,1,0]] as this is saying to reorder the pixels (RGB, index 0,1,2) to the new order (BGR, index 2,1,0).
A simpler way would just be to do the whole array at once:
def complement(img):
return img[:,:,[2,1,0]]
This will only work if you can index it like an array in python. Ignore this if this is not the case.

how to separate image using color channel in python?

Hello I want to separate an object based it's color into a new image using python PIL
but I don't quite get the gasp of it. I'm still new with python.
what I already done is a code from matlab and it works
G = imread('x.png');
L = G;
for i=1:217 #this is image height
for j=1:286 #this is image width
for k=1:3 #this is color RGB channel
if(L(i,j,2) < 174) #if green value is under 174
L(i,j,k) = L(i,j,k);
else
L(i,j,k) = 256; #change to white
end
if(L(i,j,3) < 174) #if blue value is under 174
L(i,j,k) = L(i,j,k);
else
L(i,j,k) = 256; #change to white
end
end
end
end
imshow(L)
Can I get a proper explanation about how you do it using python PIL ?
thank you very much
edit :
What I'm trying to do is something like this
https://imgur.com/6n1QCfR
Then the result is this
https://imgur.com/p99kN5p
Here is a very easy way to do it using PIL/Pillow:
#!/usr/bin/env python3
from PIL import Image
import numpy as np
# Load image and ensure it is RGB (not palette)
im = Image.open('circles.jpg').convert('RGB')
# Make into Numpy array so we can do fast, vectorised operations
na = np.array(im)
# Make a mask, which is True wherever Blue channel is high, False elsewhere - see #1 below
mBlueHi = na[...,2] >= 174
# Likewise for Green channel - see #2 below
mGreenHi = na[...,1] >= 174
# In our original image "na", anywhere the Green or Blue mask is set, make it white
na[mGreenHi | mBlueHi] = [255,255,255]
# Make back into PIL Image and save
Image.fromarray(na).save('result.png')
Note #1: The image is stored in a 3 dimensional array, height x width x RGB channels. Red is in channel 0, so it is na[:,:,0] and na[...,0] is shorthand for that same thing.
Note #2: Green is in the second channel starting from index 0, so the green pixels can be addressed using na[:,:,1] or equally na[...,1]
Note that JPEG is lossy and often a poor choice for intermediate files in image processing because it changes values to make files smaller. Consider using PNG which is lossless.

Creating image through input pixel values with the Python Imaging Library (PIL)

I'm wanting to work on an idea using images but I can't get it to write pixel values properly, it always just ends up grey with some pattern like artefacts, and no matter what I try, the artefacts change but the image remains grey.
Here's the basic code I have:
from PIL import Image
data = ""
for i in range( 128**2 ):
data += "(255,0,0),"
im = Image.fromstring("RGB", (128,128), data)
im.save("test.png", "PNG")
There is no information in http://effbot.org/imagingbook/pil-index.htm on how to format data, so I've tried using 0-1, 0-255, 00000000-111111111 (binary), brackets, square bracks, no brackets, extra value for alpha and changing RGB to RGBA (which turns it light grey but that's it), comma after, and no comma after, but absolutely nothing has worked.
For the record, I'm not wanting to just store a single colour, I'm just doing this to initially get it working.
The format string should be arranged like:
"RGBRGBRGBRGB..."
Where R is a single character indicating the red value of a particular pixel, and the same for G and B.
"But 255 is three characters long, how can I turn that into a single character?" you ask. Use chr to convert your numbers into byte values.
from PIL import Image
data = ""
for i in range( 128**2 ):
data += chr(255) + chr(0) + chr(0)
im = Image.fromstring("RGB", (128,128), data)
im.save("test.png", "PNG")
Result:
Alternative solution:
Using fromstring is a rather roundabout way to generate an image if your data isn't already in that format. Instead, consider using Image.load to directly manipulate pixel values. Then you won't have to do any string conversion stuff.
from PIL import Image
im = Image.new("RGB", (128, 128))
pix = im.load()
for x in range(128):
for y in range(128):
pix[x,y] = (255,0,0)
im.save("test.png", "PNG")

Cleaning an image to only black

I have an image.
I would like to go over that image, pixel by pixel, and any pixel that is not black should be turned to white. How do I do this?
(Python).
Thanks!
The most efficient way is to use the point function
def only_black(band):
if band > 0:
return 255
return 0
result = im.convert('L').point(only_black)
This is what the PIL documentation has to say about this:
When converting to a bilevel image
(mode "1"), the source image is first
converted to black and white.
Resulting values larger than 127 are
then set to white, and the image is
dithered. To use other thresholds, use
the point method.
You should use the point function, which exists specifically for this reason.
converter= ( (0,) + 255*(255,) ).__getitem__
def black_or_white(img):
return img.convert('L').point(converter)
You might want to check out the following library:
http://effbot.org/imagingbook/image.htm
Especially:
im.getpixel(xy) => value or tuple
and
im.putpixel(xy, colour)

Categories