Im trying to write a python script which will walk through a directory and traverse the all sub directories and if any jpg or png image has higher resolution than 2048*2048 then print out the name of those images. I am not able to traverse the sub-directories. Can anyone plz look into the code
import os
import matplotlib.image as plt
root_path = 'E:\newfolder'
img_list = os.listdir(root_path)
for img_name in img_list:
if img_name.endswith(('.png', '.jpg')):
img = plt.imread(root_path+'/'+img_name)
if img.shape[0] > 2048 and img.shape[1] > 2048:
print(root_path, img_name)
Here's a complete and tested solution that is similar to answers by #Paul and #BrainCity. You'll see that I prefer using small, clear functions, since these encourage reusable code.
You can do the image processing using matplotlib as you do in your question, but you need to install Pillow in order to handle .JPG images, since matplotlib only supports PNG natively. I prefer using Pillow directly unless you're already using matplotlib for other stuff.
from pathlib import Path
from PIL import Image
def print_high_res_images(directory: str):
root_path = Path(directory).resolve()
high_res_images = get_high_res_images(root_path)
if high_res_images:
print('High resolution images:')
for file_path in high_res_images:
print(file_path)
def get_high_res_images(root_path: Path) -> []:
return [path for path in root_path.rglob("*.*") if is_high_res_image(path)]
def is_high_res_image(file_path: Path) -> bool:
if is_image(file_path):
image = Image.open(file_path)
width, height = image.size
return width > 2048 and height > 2048
return False
def is_image(file: Path) -> bool:
return file.suffix.lower() in ['.png', '.jpg']
# Test our new function:
print_high_res_images(r'E:\newfolder')
If you're using Python 3.5+, you can use the pathlib module, and then use a recursive glob pattern to find all files in all subdirectories. Then, you filter the paths and retain only those whose suffix is .png or .jpg:
from pathlib import Path
for path in [path for path in Path("dir/to/images").rglob("*.*") if path.suffix.lower() in (".png", ".jpg")]:
# image = Image(path)
# if image dimensions greater than 2048 x 2048:
# print(path)
print(path) will print out the entire absolute path of the current image, but if you just want to print out the name, you can print(path.name), which will include the suffix (file extension). If you just want the name of the file without the extension, you can print(path.stem).
crawl subdirectory using os.walk
import os
import pathlib
from PIL import Image
def crawlImages(directory):
allowedExtensions = ['.jpg', '.png']
for root, dirs, files in os.walk(directory):
for f in files:
if pathlib.Path(f).suffix in allowedExtensions:
fileName = os.path.abspath(os.path.join(root, f))
image = Image.open(fileName)
width, height = image.size
# checking minimum image width and height
if width > 2400 and height > 2400:
print(fileName, width, height)
crawlImages('E:\\music')
Related
I have the following code that I thought would resize the images in the specified path But when I run it, nothing works and yet python doesn't throw any error so I don't know what to do. Please advise. Thanks
import cv2
import numpy as np
import os
from PIL import Image
def image_resize(folder):
images = []
num_images = 0
location = folder+"_"
for filename in os.listdir(folder):
img = cv2.imread(os.path.join(folder, filename))
if img is not None:
new_img = np.array(Image.fromarray(img).resize((200, 200), Image.ANTIALIAS)) # Resize the images to 50 X 50
images.append(new_img)
num_images += 1
cv2.imwrite("{}/{}".format(location, filename), new_img)
return None
image_resize("2S1")
image_resize("SLICY")
image_resize("BRDM-2")
image_resize("BTR-60")
image_resize("D7")
image_resize("T62")
image_resize("ZIL131")
image_resize("ZSU-23_4")
all image in folder: G:\sar
help me
It does not do anything because your for loop is not finding any files in the folder. You are never passing the "G:\sar" part of the file path.
I am running a code in python where I get images from input file, and create another folder as output and a file csv. The code that I run is as below:
# import the necessary packages
from PIL import Image
import argparse
import random
import shutil
import glob2
import uuid
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required = True,
help = "input directory of images")
ap.add_argument("-o", "--output", required = True,
help = "output directory")
ap.add_argument("-c", "--csv", required = True,
help = "path to CSV file for image counts")
args = vars(ap.parse_args())
# open the output file for writing
output = open(args["csv"], "w")
# loop over the input images
for imagePath in glob2.iglob(args["input"] + "/*/*.jpg"):
# generate a random filename for the image and copy it to
# the output location
filename = str(uuid.uuid4()) + ".jpg"
shutil.copy(imagePath, args["output"] + "/" + filename)
# there is a 1 in 500 chance that multiple copies of this
# image will be used
if random.randint(0, 500) == 0:
# initialize the number of times the image is being
# duplicated and write it to the output CSV file
numTimes = random.randint(1, 8)
output.write("%s,%d\n" % (filename, numTimes))
# loop over a random number of times for this image to
# be duplicated
for i in range(0, numTimes):
image = Image.open(imagePath)
# randomly resize the image, perserving aspect ratio
factor = random.uniform(0.95, 1.05)
width = int(image.size[0] * factor)
ratio = width / float(image.size[0])
height = int(image.size[1] * ratio)
image = image.resize((width, height), Image.ANTIALIAS)
# generate a random filename for the image and copy
# it to the output directory
adjFilename = str(uuid.uuid4()) + ".jpg"
shutil.copy(imagePath, args["output"] + "/" + adjFilename)
# close the output file
output.close()
After running the code I get only csv file, but I don't get output folder.
The way I run the code is:
python gather.py --input 101_ObjectCategories --output images --csv output.csv
Please can you help me how to solve the problem, because I need the output folder for next steps, running next functions.
I would recommend the following approach:
import os
from pathlib import Path
Path('path').mkdir(parents=True, exist_ok=True)
This works cross-platform and doesn't overwrite the directories if they already exist.
You should try the os module. It has a mkdir method that creates a directory based on the path you give it as a parameter.
import os
os.mkdir("path")
While most answers suggest using os.mkdir() I suggest you rather go for os.makedirs() which would recursively create all the missing folders in your path, which usually is more convinient.
import os
os.makedirs('foo/bar')
Docs: https://docs.python.org/3/library/os.html#os.makedirs
I am very new to Python. I just started today.
I am trying desperately to save an image to a fixed path, such as:
/Users/myname/Sites/Tester/images/
So if I have an image, called "1.jpg", it will be placed here:
/Users/myname/Sites/Tester/images/1.jpg
This is my script:
from PIL import Image
import tempfile
def set_image_dpi(file_path):
im = Image.open(file_path)
length_x, width_y = im.size
factor = min(1, float(1024.0 / length_x))
size = int(factor * length_x), int(factor * width_y)
im_resized = im.resize(size, Image.ANTIALIAS)
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
temp_filename = temp_file.name
im_resized.save(temp_filename, dpi=(300, 300))
return temp_filename
However, this saves the file in:
/var/folders/1n/hdyfv8z96v5_hcb9tsgvt7cr0000gn/T/tmp91rams5v.jpg
How can I do, so it will save in the path I specifies?
"MY_PATH / temp_filename"
No need for the tempfile module here, you just need to specify the path when calling .save():
from PIL import Image
import os
def set_image_dpi(file_path, save_folder):
im = Image.open(file_path)
length_x, width_y = im.size
factor = min(1, float(1024.0 / length_x))
size = int(factor * length_x), int(factor * width_y)
im_resized = im.resize(size, Image.ANTIALIAS)
save_path = os.path.join(save_folder,'test.png')
# creates path: C:\Users\User\Pictures\test.png
im_resized.save(save_path, dpi=(300, 300))
set_image_dpi('test.png','C:\\Users\\User\\Pictures')
I'm guessing your main problem is building the result path from the original path (something like /where/images/are/taken/from/1.jpg) and your destination directory (/Users/myname/Sites/Tester/images/). The methods in the os.path package can help (see https://docs.python.org/3/library/os.path.html):
import os
dest_dir = '/Users/myname/Sites/Tester/images/'
...
base = os.path.basename(file_path) # this will be '1.jpg'
dest_path = os.path.join(dest_dir, base) # this will be the full path
im_resized.save(dest_path)
As others have said in the comments, you don't need tempfile here.
Currently I am trying to crop all images inside a folder under the address of: C:\\Users\\xie\\Desktop\\tiff\\Bmp and then resave them into the same folder. Below is the code I am trying to experiment with, both run without error but does nothing. Also note I am using windows as platform.
Code 1:
from PIL import Image
import os.path, sys
path = "C:\\Users\\xie\\Desktop\\tiff\\Bmp"
dirs = os.listdir(path)
def crop():
for item in dirs:
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
imCrop = im.crop(30, 10, 1024, 1004)
imCrop.save(f + 'Cropped.bmp', "BMP", quality=100)
crop()
Code 2:
for f in os.listdir("C:\\Users\\xie\\Desktop\\tiff\\Bmp"):
for f in ("C:\\Users\\xie\\Desktop\\tiff\\Bmp"):
if f.endswith('.bmp'):
print (f, end=" ")
i = Image.open(f)
area = (30, 10, 1024, 1004)
cropped_i = i.crop(area)
cropped_i.show()
cropped_i.save('Cropped{}.bmp', "BMP", quality=100, optimize=True)
Thanks, any help or suggestions are greatly appreciated!
Code 1 : Corrected
This is your corrected code, you almost had it right, you have to join the path correctly, in your code you weren't adding a separator / between the path and the filename. by using os.path.join you can combine a directory path and a filename.
Furthermore, crop takes a tuple of 4, not 4 arguments.
from PIL import Image
import os.path, sys
path = "C:\\Users\\xie\\Desktop\\tiff\\Bmp"
dirs = os.listdir(path)
def crop():
for item in dirs:
fullpath = os.path.join(path,item) #corrected
if os.path.isfile(fullpath):
im = Image.open(fullpath)
f, e = os.path.splitext(fullpath)
imCrop = im.crop((30, 10, 1024, 1004)) #corrected
imCrop.save(f + 'Cropped.bmp', "BMP", quality=100)
crop()
This is more or less a rough version of code, I used with opencv, it should work the same for PIL also
import glob
import numpy as np
from PIL import Image
image_list = []
for filename in glob.glob('name_of_folder/*.jpg'):
im=Image.open(filename)
image_list.append(im)
a=0
c=[]
for i in range(0,len(image_list)):
#ur image cropping and other operations in here for each image_list[i]
c.append(image_list[i])
c[i].save()
files2 = [f for f in listdir(dstpath) if isfile(join(dstpath,f))]
for image in files2:
img = cv2.imread(os.path.join(dstpath,image))
equ = cv2.equalizeHist(img)
dstPath2 = join(dstpath,image)
cv2.imwrite(dstPath2,equ)
I have a folder consisting of grayscale images in jpg format but when I run my above code for Histogram equalization it gives me the above mentioned error. Pls help
imread load image in color mode by default. Try to use img = cv2.imread(your_image_path,cv2.IMREAD_GRAYSCALE) instead
#author: Quantum
"""
import cv2
import os
from os import listdir,makedirs
from os.path import isfile,join
path = r'' # Source Folder
dstpath = r'' # Destination Folder
try:
makedirs(dstpath)
except:
print ("Directory already exist, images will be written in asme folder")
# Folder won't used
files = [f for f in listdir(path) if isfile(join(path,f))]
for image in files:
try:
img = cv2.imread(os.path.join(path,image),cv2.IMREAD_GRAYSCALE)
**imgnew=cv2.equalizeHist(img)**
dstPath = join(dstpath,image)
cv2.imwrite(dstPath,imgnew)
except:
print ("{} is not converted".format(image))
All I did was added the histeq function while my files are converted to grayscale