After cropping and saving images, I found that there are many full black images (RGB = 0,0,0). I want to delete these images.
The followings are the codes I have tried:
import os, glob
from PIL import image
def CleanUp_images():
for filename in glob.glob('/Users/Xin/Desktop/TestFolder/*.jpg'):
im = Image.open(filename)
pix = list(im.getdata())
if pix == [(0,0,0)]:
os.remove(im)
CleanUp_images()
However, the above codes didn't work out
Can anyone give me a help?
With os.remove(im) you're passing an image object to os.remove which only accepts strings when you just have to do:
os.remove(filename)
filename is the absolute path to your file (thanks to glob), so it will work.
Also if pix == [(0,0,0)]: this isn't going to work because the list has more than 1 element, even if all elements are black pixels. What works is creating a set of rgb tuples. If there are only black pixels the set has a size of 1:
if set(pix) == {(0,0,0)}:
Related
As I am trying to create a gif file, the file has been created successfully but it is pixelating. So if anyone can help me out with how to increase resolution.
.Here is the code:-
import PIL
from PIL import Image
import NumPy as np
image_frames = []
days = np.arange(0, 12)
for i in days:
new_frame = PIL.Image.open(
r"C:\Users\Harsh Kotecha\PycharmProjects\pythonProject1\totalprecipplot" + "//" + str(i) + ".jpg"
)
image_frames.append(new_frame)
image_frames[0].save(
"precipitation.gif",
format="GIF",
append_images=image_frames[1:],
save_all="true",
duration=800,
loop=0,
quality=100,
)
Here is the Gif file:-
Here are the original images:-
image1
image2
iamge3
Updated Answer
Now that you have provided some images I had a go at disabling the dithering:
#!/usr/bin/env python3
from PIL import Image
# User editable values
method = Image.FASTOCTREE
colors = 250
# Load images precip-01.jpg through precip-12.jpg, quantize to common palette
imgs = []
for i in range(1,12):
filename = f'precip-{i:02d}.jpg'
print(f'Loading: {filename}')
try:
im = Image.open(filename)
pImage = im.quantize(colors=colors, method=method, dither=0)
imgs.append(pImage)
except:
print(f'ERROR: Unable to open {filename}')
imgs[0].save(
"precipitation.gif",
format="GIF",
append_images=imgs[1:],
save_all="true",
duration=800,
loop=0
)
Original Answer
Your original images are JPEGs which means they likely have many thousands of colours 2. When you make an animated GIF (or even a static GIF) each frame can only have 256 colours in its palette.
This can create several problems:
each frame gets a new, distinct palette stored with it, thereby increasing the size of the GIF (each palette is 0.75kB)
colours get dithered in an attempt to make the image look as close as possible to the original colours
different colours can get chosen for frames that are nearly identical which means colours flicker between distinct shades on successive frames - can cause "twinkling" like stars
If you want to learn about GIFs, you can learn 3,872 times as much as I will ever know by reading Anthony Thyssen's excellent notes here, here and here.
Your image is suffering from the first problem because it has 12 "per frame" local colour tables as well as a global colour table3. It is also suffering from the second problem - dithering.
To avoid the dithering, you probably want to do some of the following:
load all images and append them all together into a 12x1 monster image, and find the best palette for all the colours. As all your images are very similar, I think that you'll get away with generating a palette just from the first image without needing to montage all 12 - that'll be quicker
now palettize each image, with dithering disabled and using the single common palette
save your animated sequence of the palletised images, pushing in the singe common palette from the first step above
2: You can count the number of colours in an image with ImageMagick, using:
magick YOURIMAGE -format %k info:
3: You can see the colour tables in a GIF with gifsicle using:
gifsicle -I YOURIMAGE.GIF
I am new to python, so go easy on me! I am trying to apply a blur to every .bmp image in a folder. I am able to get the first half of the code to work, so the filter is applied to all the photos, but then I can't get it to re-save each image. I want to keep the original images, and add the new images to the folder. Here's what I have:
from PIL import Image from PIL import ImageFilter import os, fileinput, sys
##for every item in X folder that ends in X, apply a basic blur to the image##
for entry in os.scandir('/Users/kh'):
if entry.path.endswith('.bmp'):
img = Image.open(entry.path)
img = img.filter(ImageFilter.BoxBlur(2))
img.show()
##and then re-save each of those new images under a new filename##
# Split our original filename into name and extension
(name, extension) = os.path.splitext(filepath)
# Save with "_blur" added to the filename
img.save(name + '_blur' + extension)
# Save the image as a BMP
img.save(name + '.bmp')
I've tried a bunch of other stuff, but this code is the closest I've gotten. Thanks so much for your help.
I tried your code. I actually get:
NameError: name 'filepath' is not defined
because you have a filepath which should be entry.path:
(name, extension) = os.path.splitext(entry.path)
Besides this, your code works, except that you have both images blurred. The last line:
img.save(name + '.bmp')
is cleary not needed, it overwrites the original images with the blurred ones.
I am trying to resize all images in my samples folder and then save all the images back in the test folder. The code below resize the images but it doesn't save them into the destination folder "test". I fail to understand what is the problem and I have referred to all documentation and nothing can help me understand what goes wrong here.
import cv2
import glob
import os
from tqdm import tqdm
imgs = glob.glob('samples/*.jpg')
print('Images files:', imgs)
width = 100
height = 100
folder = 'test'
if not os.path.exists(folder):
os.makedirs(folder)
#Resizing & Saving
for img in tqdm(imgs):
pic = cv2.imread(img, cv2.IMREAD_UNCHANGED)
pic = cv2.resize(pic, (width, height))
cv2.imwrite(os.path.join(folder,img), pic)
print(img)
The script can read the images and resize them successfully, the only part is imwrite doesn't function as expected.
May be the special character. Try to change the name of the image.
I don't have reputation to add this idea as comment. I'm Sorry.
EDIT: Sorry, the first version of the code was bullshit, I tried to remove useless information and made a mistake. Problem stays the same, but now it's the code I actually used
I think my problem is probably very basic but I cant find a solution. I basically just wanted to play around with PIL and convert an image to an array and backward, then save the image. It should look the same, right? In my case the new image is just gibberish, it seems to have some structure but it is not a picture of a plane like it should be:
def array_image_save(array, image_path ='plane_2.bmp'):
image = Image.fromarray(array, 'RGB')
image.save(image_path)
print("Saved image: {}".format(image_path))
im = Image.open('plane.bmp').convert('L')
w,h = im.size
array_image_save(np.array(list(im.getdata())).reshape((w,h)))
Not entirely sure what you are trying to achieve but if you just want to transform the image to a numpy array and back, the following works:
from PIL import Image
import numpy as np
def array_image_save(array, image_path ='plane_2.bmp'):
image = Image.fromarray(array)
image.save(image_path)
print("Saved image: {}".format(image_path))
im = Image.open('plane.bmp')
array_image_save(np.array(im))
You can just pass a PIL image to np.array and it takes care of the proper shaping. The reason you get distorted data is because you convert the pil image to greyscale (.convert('L')) but then try to save it as RGB.
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