Automate cropping with Pillow and python? - python-3.x

So I have a folder with 500+ images that need to be cropped. And I have searched and have manage to create this cut-and-paste script. But, for some reason it doesn't save the new image!? The terminal is just still, no errors no nothing.
from PIL import Image # import the Python Image processing Library
import os # To read the folder
directory_in_str = "/Users/hora/Downloads/Etik"
directory = os.fsencode(directory_in_str)
for file in os.listdir(directory):
filename = os.fsdecode(file)
if filename.endswith(".png"):
image = os.path.join(directory_in_str, filename)
imageObject = Image.open(image) # Create an Image object from an Image
cropped = imageObject.crop((1025,85,2340,2040)) # Crop the iceberg portion (top left x, top left y, bottom right x, bottom right y)
cropped.save("{}".format(filename+"_cropped"), 'png') # Save the cropped portion
continue
else:
continue
Im searching in a specific folder, and the cropped image should be saved with a filename_cropped.png. But not necessary, I have backups if something should go side-ways.
The expected result:
Loop through a folder
Crop all images ending with .png
And save the crop image with the previous filename but with extension
FILNAME_cropped.png
Done

Two issues regarding this line:
cropped.save("{}".format(filename+"_cropped"), 'png')
Your filename still contains the file extension.
You don't add a (new) file extension yourself.
Both issues result in some string xxx.png_cropped for your new file.
My suggestion to modify your code:
for file in os.listdir(directory):
filename = os.fsdecode(file)
if filename.endswith(".png"):
image = os.path.join(directory_in_str, filename)
filename, file_extension = os.path.splitext(filename) # <-- After reading, filename can be overwritten
imageObject = Image.open(image)
cropped = imageObject.crop((1025,85,2340,2040))
cropped.save("{}".format(filename+"_cropped.png"), 'png') # <-- Explicitly add .png to your filename
continue
else:
continue
Hope that helps!

add the directory path in saving the file.
directory_in_str = "/Users/hora/Downloads/Etik/"
cropped.save("{}".format(directory_in_str+filename+"_cropped"),'png')

Related

Converting multiple files in a directory into .txt format. But file names become Binary

So I am creating plagiarism software, for that, I need to convert .pdf, .docx,[enter image description here][1] etc files into a .txt format. I successfully found a way to convert all the files in one directory to another. BUT the problem is, this method is changing the file names
into binary values. I need to get the original file name which I am gonna need in the next phase.
**Code:**
import os
import uuid
import textract
source_directory = os.path.join(os.getcwd(), "C:/Users/syedm/Desktop/Study/FOUNDplag/Plagiarism-checker-Python/mainfolder")
for filename in os.listdir(source_directory):
file, extension = os.path.splitext(filename)
unique_filename = str(uuid.uuid4()) + extension
os.rename(os.path.join(source_directory, filename), os.path.join(source_directory, unique_filename))
training_directory = os.path.join(os.getcwd(), "C:/Users/syedm/Desktop/Study/FOUNDplag/Plagiarism-checker-Python/trainingdata")
for process_file in os.listdir(source_directory):
file, extension = os.path.splitext(process_file)
# We create a new text file name by concatenating the .txt extension to file UUID
dest_file_path = file + '.txt'
# extract text from the file
content = textract.process(os.path.join(source_directory, process_file))
# We create and open the new and we prepare to write the Binary Data which is represented by the wb - Write Binary
write_text_file = open(os.path.join(training_directory, dest_file_path), "wb")
# write the content and close the newly created file
write_text_file.write(content)
write_text_file.close()
remove this line where you rename the files:
os.rename(os.path.join(source_directory, filename), os.path.join(source_directory, unique_filename))
that's also not binary, but a uuid instead.
Cheers

Retrieve Images from different folders

I have a big folder and inside it has sub folders and i want to retrieve images from all those folders. How do i do it?
Second if i want to get dimensions of all those images how would i do that?
I have tried it with one folder and it is working fine. But i want to do it for multiple folders. I reading image dimensions of one folder from this code.
folder_images = "D:/DeepFashion/Category and Attribute Prediction/img/img"
size_images = dict()
for dirpath, _, filenames in os.walk(folder_images):
for path_image in filenames:
image = os.path.abspath(os.path.join(dirpath, path_image))
with Image.open(image) as img:
width, heigth = img.size
size_images[path_image] = {'width': width, 'heigth': heigth}
This code seems to be fine - the only problem with it being that if any of the files in the folder structure is not a proper image file, you will get an unhandled exception and the script will stop.
Since you are not reading the images in a lazy way, the is no reason to use the with command to get to the images - just change your code to:
folder_images = "D:/DeepFashion/Category and Attribute Prediction/img/img"
size_images = dict()
for dirpath, _, filenames in os.walk(folder_images):
for path_image in filenames:
image = os.path.abspath(os.path.join(dirpath, path_image))
try:
img = Image.open(image)
except OSError:
print("Not an image file: ", image)
width, heigth = img.size
size_images[path_image] = {'width': width, 'heigth': heigth}

How to change where the output directory where the new images go

I have a small query I'm hoping someone can help me out within Python 3. I am resizing a dataset of 10000 images to all be 1000x1000 in dimension before I do any pytorch analysis with it. I just wanted to ask how I change my code to save the outgoing images to a new folder I have created ''train_resized'' instead of the same folder as the original files as it is doing now when I run. Thanks
# Testing dataset
from PIL import Image
import os, sys
path = (r'G:\My Drive\CATSVDOGS2.0\test1\\')
dirs = os.listdir( path )
def resize():
for item in dirs:
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
imResize = im.resize((1000,1000), Image.ANTIALIAS)
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
resize()
In your line
imResize.save(f + ' resized.jpg', 'JPEG', quality=90)
you're setting the path when using the variable f, as f uses the path variable you defined. A quick way to set the path is to do something like:
imResize.save('G:\\My Drive\\Path\\To\\Folder\\' + item + ' resized.jpg', 'JPEG', quality=90)
of course specify the path to be whatever you want. Untested as I don't have Python installed on my work machine, but that is the general gist.

Python importing a batch of jpg images in files?

I'm trying to import a batch of images from a file to a new separate folder according to the images name for example; 1000_70.jpg --> folder 70 and 1200_71.jpg --> folder 71. However, when I ran the script it does nothing.
from PIL import Image
import glob
import os
folder='Desktop/n' # All jpegs are in this folder
imList=glob.glob(folder+'*.jpg') # Reading all images with .jpg
newfold = 'Desktop/n/l' # New folder path
for img in imList: # Loop
im = Image.open(img) # Opening image
fileName, fileExt = os.path.splitext(img) # Extract the filename and
# Extension from path
im.save(newfold+fileName+'*.jpg') #save the image to new folder from
#old folder
First of you want the filename of the image not the path, use split instead of splitext to remove the parent folder and than use splitext to remove the extension:
os.path.splitext("afdsasdf/fasdfa/fff.jpg")
=> ('afdsasdf/fasdfa/fff', '.jpg')
os.path.split("afdsasdf/fasdfa/fff.jpg")
=> ('afdsasdf/fasdfa', 'fff.jpg')
Second you remove the wildcare in *.jpg when saving the image. You need that wildcare with glob since you are selectioning multiple files.
Third you need to extract the second number in the filename (1000_70.jpg --> 70).
All toghether you should have something that look like this:
for img in imList:
im = Image.open(img)
filepath, filenameExt = os.path.split(img)
filename, fileExt = os.path.splitext(filenameExt)
folderNumber = filename.split("_")[1]
im.save("{}/{}/{}".format(newfold, folderNumber, filenameExt))

processing multiple images in sequence in opencv python

I am trying to build the code using python, for which I need to process at least 50 images. So how should I read the images one by one and process it. Is it possible using a loop and do i need to create a separate database for this or just saving all the images in separate file will do?
I have written some code may statisfy your requirement.
import glob
import os,sys
import cv2
## Get all the png image in the PATH_TO_IMAGES
imgnames = sorted(glob.glob("/PATH_TO_IMAGES/*.png"))
for imgname in imgnames:
## Your core processing code
res = propress(imgname)
## rename and write back to the disk
#name, ext = os.path.splitext(imgname)
#imgname2 = name+"_res"+ext
imgname2 = "_res".join(os.path.splitext(imgname))
cv2.imwrite(imgname2, res)
The task consists of following steps,
Having the images in a directory e.g. foo/
Getting the list of all images in the foo/ directory
Lopp over the list of images
3.1. img = cv2.imread(images(i),0)
3.2. ProcessImage(img) #Run an arbitrary function on the image
3.3. filename = 'test' + str(i) +'.png'
3.4. cv2.imwrite(filename, img)
End of the loop

Resources