Convert multiples images into its negative with PIL - python

I want to read all the images in a folder and convert them into negatives of the same image
# Import library to work with Images
from PIL import Image
# Make negative pixel
def negatePixel(pixel):
return tuple([255-x for x in pixel])
#img_dir = "" # Enter Directory of all images
for i in range(1,130):
# Original Image
img = []
img = Image.open(str(i) + '.jpg')
# New clear image
new_img = Image.new('RGB', img.size)
# Get pixels from Image
data = img.getdata()
# Create map object consists of negative pixels
new_data = map(negatePixel, data)
# Put negative pixels into the new image
new_img.putdata(list(new_data))
# Save negative Image
new_img.save(str(i) + 'neg.jpg')
print ('saved image' + str(i))
I'm getting this error :
Traceback (most recent call last):
File "2.py", line 23, in <module>
new_img.putdata(list(new_data))
File "2.py", line 6, in negatePixel
return tuple([255-x for x in pixel])
TypeError: 'int' object is not iterable
I wrote the above programme to perform what I wanted it to, but it is striking an error. I'm new to programming and is there any idea how to solve this?

Your approach is not ideal. Firstly, you can do that much more simply with ImageMagick which is included in most Linux distros and is available for macOS and Windows. Just in Terminal, this will invert all files in the current directory:
magick mogrify -negate *.jpg
Or, if you want them saved in a directory called results:
mkdir results
magick mogrify -path results -negate *.jpg
If you want to stick to Python and PIL/Pillow, there is already a invert() function in its ImageOps module here:
#!/usr/local/bin/python3
from PIL import Image, ImageOps
# Load image
im = Image.open('image.jpg')
# Invert
result = ImageOps.invert(im)
# Save
result.save('result.jpg')
If you don't want to use the built-in invert(), you will be much better off using the point() function here:
#!/usr/local/bin/python3
from PIL import Image
# Load image
im = Image.open('image.jpg')
# Negate
result = im.point(lambda p: 255 -p)
# Save
result.save('result.jpg')
Note: In general, as soon as you start using a for loop, or getdata() with an image in Python, you have probably already gone wrong. You should use built-in library functions or Numpy really, else everything will be slo-o-o-o-o-o-w.

Related

Subtract 16 bit tiff image in python

I have two 16 bit tiff image, of which one is a background and I have to remove it from all the image. I use the following code, however I get the error saying
return image1._new(image1.im.chop_difference(image2.im))
ValueError: image has wrong mode
from PIL import Image, ImageChops
im1 = Image.open("main.tif")
im2 = Image.open("background.tif")
diff = ImageChops.difference(im2, im1)
diff.show()
when I check the mode using print(im1.mode) I get
I,16
I do not understand this error. Also, I don't know if Pillow is able to subtract 16 bit tiff images or not. I need help to resolve this error and get a subtracted image.
The two images are
main: main image
background image: background
I think I would do it like this:
#!/usr/bin/env python3
from PIL import Image
import numpy as np
# Open both images and make into Numpy arrays of signed 32-bit integers
main = np.array(Image.open('main.tif')).astype('int32')
back = np.array(Image.open('background.tif')).astype('int32')
# Calculate difference with saturation
diff = np.clip(main - back, 0, main.max())
# Revert to PIL Image and save
Image.fromarray(diff.astype(np.uint16)).save('result.tif')
If you stretch the contrast, you get:

Create, Modify, and Save an image in python 3.x

I'm currently making a program that renders information to a buffer, and I want to save the information as an image file of some sort to my working directory. I've seen some examples using PIL, but that library isn't supported for python 3.x. Are there better alternatives?
First uninstall PIL than install Pillow
its a PIL's clone which works on python 3.x.
from PIL import Image
img = Image.open("test1.jpg") #jpg, png, etc.
pix = img.load()
print img.size #Get the width and height of the image for iterating over
print pix[15,15] #Get the RGBA Value of the a pixel of an image
pix[15, 15] = value # Set the RGBA Value of the image (tuple)
img.save("out.jpg") # Saves the modified pixels to image

Using Image (PIL) to save the file marked a difference between 2 pictures

I am comparing 2 pictures and want to mark the difference and save it in a new file.
(Python 2.7 + Windows)
What I am doing is below:
from PIL import Image
from PIL import ImageChops
from PIL import ImageDraw
file1 = 'Animal Nov 2014.jpg'
file2 = ' Animal May 2014.jpg'
im1 = Image.open(file1)
im2 = Image.open(file2)
diff = ImageChops.difference(im1, im2).getbbox()
draw = ImageDraw.Draw(im2)
draw.rectangle(diff)
im2.save('file3.jpg')
when I save it to 'file3.jpg', it gives error:
IOError: cannot write mode P as JPEG
when I save it to 'file3.png', it gives error:
TypeError: an integer is required
How can I have it saved to a new file? Thanks.
please see the solution at PIL (Image) ValueError: Not a valid number of quantization tables. Should be between 1 and 4
The answer can be found in this thread: Getting "cannot write mode P as JPEG" while operating on JPG image
You need to convert the image to RGB mode.
In your case:
im2.convert('RGB').save('file3.jpg')

Python PIL For Loop to work with Multi-image TIFF

Each tiff file has 4 images in it. I do not wish to extract and save them if possible, I would just like to use a for loop to look at each of them. (Like look at the pixel [0,0] )and depending on what color it is in all 4 I will do something accordingly.
Is this possible using PIL?
If not what should I use.
Rather than looping until an EOFError, one can iterate over the image pages using PIL.ImageSequence (which effectively is equivalent as seen on the source code).
from PIL import Image, ImageSequence
im = Image.open("multipage.tif")
for i, page in enumerate(ImageSequence.Iterator(im)):
page.save("page%d.png" % i)
You can use the "seek" method of a PIL image to have access to the different pages of a tif (or frames of an animated gif).
from PIL import Image
img = Image.open('multipage.tif')
for i in range(4):
try:
img.seek(i)
print img.getpixel( (0, 0))
except EOFError:
# Not enough frames in img
break
Had to do the same thing today,
I followed #stochastic_zeitgeist's code, with an improvement (don't do manual loop to read per-pixel) to speed thing up.
from PIL import Image
import numpy as np
def read_tiff(path):
"""
path - Path to the multipage-tiff file
"""
img = Image.open(path)
images = []
for i in range(img.n_frames):
img.seek(i)
images.append(np.array(img))
return np.array(images)
Here's a method that reads a multipage tiff and returns the images as a numpy array
from PIL import Image
import numpy as np
def read_tiff(path, n_images):
"""
path - Path to the multipage-tiff file
n_images - Number of pages in the tiff file
"""
img = Image.open(path)
images = []
for i in range(n_images):
try:
img.seek(i)
slice_ = np.zeros((img.height, img.width))
for j in range(slice_.shape[0]):
for k in range(slice_.shape[1]):
slice_[j,k] = img.getpixel((j, k))
images.append(slice_)
except EOFError:
# Not enough frames in img
break
return np.array(images)
Thanks to the answers on this thread I wrote this python module for reading and operating on multipage tiff files: https://github.com/mpascucci/multipagetiff
It also allows to color-code the image stack "depth-wise" and make z-projections.
Hope it can help

How do I convert image path to image object I can use ImageChops on?

I'm trying to add all the .tiff files in a directory together using ImageChops, but I keep on getting the error 'IOError: cannot identify image file'. I thought it was just a problem with trying to use a file path instead of an image object, but similar codes in other places don't have this problem.
def imadd(): #subcommand
img1=Image.new('RGB',(2048, 2048))
img1.save("summation.tif")
for file in os.listdir(directoryname):
if fnmatch.fnmatch(file, '*.tif'):
im2 = Image.open("summation.tif", mode='r')
im3 = Image.open(os.path.join(directoryname, file))
finalimg = ImageChops.add(im2, im3, 1, 0)
finalimg.save("summation.tif")
By trail and error, all the parts work except:
im3 = Image.open(os.path.join(directoryname, file)).
I also tried using glob.glob(), but that still returns the same error.
While you can open and show 16 bit tiffs with PIL, ImageChops doesn't work. matplotlib and scipy have many more tools available.
Also im3 = Image.open(os.path.join(directoryname, file)) needs to be Image.open(unicode(os.path.join(directoryname, file)))

Categories

Resources