How would i choose a random image from a directory? Python - python

My program's goal is to take a random png image and places it against another random image. So far i have it so it gets the image, pastes it onto another, and saves it and would like to get it to be random.
from PIL import Image
from PIL import ImageFilter
France = Image.open(r"C:\Users\Epicd\Desktop\Fortnite\France.png")
FranceRGB = France.convert('RGB')
Crimson_Scout = Image.open(r"C:\Users\Epicd\Desktop\Fortnite\Crimson_Scout.png")
FranceRGB.paste(Crimson_Scout, box=(1,1), mask=Crimson_Scout)
FranceRGB.save(r"C:\Users\Epicd\Desktop\Fortnite\Pain1.png")

The easiest way to do this would be to list the files in a directory, and choose randomly from the given paths. Something like this:
import os
import random
random.choice(os.listdir("/path/to/dir"))
It would probably be smart to add in some logic to ensure you are filtering out directories, and only accepting files with specific extension (pbg, jpg, etc)

You can use os.listdir to get a list of the paths of all the items in a directory. Then use the random class to select items from that list.

You can pick 2 random *.png files from the working directory like this:
import glob
import random
all_pngs = glob.glob("./*.png")
randPng1 = random.choice(all_pngs)
randPng2 = random.choice(all_pngs)
print randPng1
print randPng2
Then you can these two variables(randPng1 andrandPng2) instead of the hardcoded paths to your images.
If randomly picking the same png twice is not what you want, then you need to remove the randPng1 element from the all_pngs array, before getting the second random element from the array.

You can use random.choice and os.walk for that task.
The code for picking an image would something like this:
import os
import random
path = "path/to/your/images.png"
images = []
# This will get each root, dir and file list in the path specified recursively (like the "find" command in linux, but separating files, from directories, from paths).
# root is the full path from your specified path to the the directory it is inspecting
# dirs is a list containing all the directories found in the current inspecting directory
# files is a list containing all the files found in the current inspecting directory
for root, dirs, files in os.walk(path):
# This will filter all the .png files in case there is something else in the directory
# If your directory only has images, you can do this:
# images = files
# instead of filtering the '.png' images with the for loop
for f in files:
if f[-4:] == '.png':
images.append(f)
print(random.choice(images))

Related

How to find the first image in a folder?

What I want to achieve is to get the first item in a folder that is a jpg or png image without having to scan the whole folder.
path = os.getcwd()
#List of folders in the path
folders = next(os.walk(path))[1]
#Get the first element
folders_walk = os.walk(path+'\\'+ folder)
firts = next(folders_walk) [2][0]
With this code I get the first element of the folder, but this may or may not be an image. Any advice?
Not sure what you mean by "without having to scan the entire folder". You could use glob(), but that would still scan the entire directory to match the regex.
Anyway, see a solution below. Can easily modify if you don't want a recursive search (as below) / want a different criterion to determine if a file is an image.
import os
search_root_directory = os.getcwd()
# Recursively construct list of files under root directory.
all_files_recursive = sum([[os.path.join(root, f) for f in files] for root, dirs, files in os.walk(search_root_directory)], [])
# Define function to tell if a given file is an image
# Example: search for .png extension.
def is_an_image(fpath):
return os.path.splitext(fpath)[-1] in ('.png',)
# Take the first matching result. Note: throws StopIteration if not found
first_image_file = next(filter(is_an_image, all_files_recursive))
Note that the above will be much more efficient (in the recursive case) if sum() (which pre-computes the entire list of files) is omitted and instead a list of files is handled in is_an_image (but the code is less clear that way).

How can i get all png's from a file including the png's in subdirectories

So essentially I want to give the program a folder and it would append a tuple (image directory, image name) to an array. and the program should loop through ALL of the png's including the images in the subdirectories of the given folder and even their subdirectories (There are a lot of subdirectories)
so I want the end result to be a long array that contains tuples with the directory and name of the image
import glob
for image_path in glob.iglob(image_folder_path + '**/*.png', recursive=True):
#do what you want with image_path

Hidden dot underscore ._ before name of image files in a directory while reading them using glob

I am trying to read images from a directory.
The directory has images named like-
person1_bacteria_1.jpeg
person1_bacteria_2.jpeg
person2_bacteria_3.jpeg
I am trying to grab these images using glob function.
images = images_directory.glob('*.jpeg')
The problem is, while I print the directory of the files I have just read, I found that some of the files have dot underscore (._) before them.
For example-
dir/._person1_bacteria_2.jpeg
I checked the image files in the directory again and again but there was no image name with ._ before it.
How do I avoid reading files whose name have dot underscore (._) before it?
I am running this in an windows machine.
I think this files are just thumbnail files. if you look with os.path.getsize(filename) you can probably confirm this hypothesis.
The reason you don't see this files is that they are probably marked as hidden files.
Try to configure your windows explorer such, that it shows all files. ( https://support.microsoft.com/en-us/help/14201/windows-show-hidden-files )
If glob.glob produces results with unexpected filenames, you can filter them with the following code using a comprehension list with a condition filter
import os
import glob
images = glob.glob(os.path.join(os.getcwd(), '*.jpeg'))
images = [image for image in images if not os.path.basename(image).startswith('._')]
If the directory contains files starting with dot glob won’t be matched by default. globe returns a list, you can write this code to add both normal files and hidden ones:
import glob
images = glob.glob('*.jpeg') + glob.glob('.*.jpeg')
UPDATE: If you want to exclude files that starts with ._ you can use this pattern:
images = glob.glob("[!._]*.jpeg")

Using random and shutil to move files in loop in python

I have a small problem. I am trying to move 20x500 images in 20 predefined folders. I can make this work with just 500 random images and I have identified the problem; I draw 500 random files, move them and then it tries doing it again but since it doesn't update the random list, it fails when it reaches an image that it thinks is part of the random group but it has already been moved and thus fails. How do I "update" the random list of files so that it doesn't fail because I move stuff? The code is:
import os
import shutil
import random
folders = os.listdir(r'place_where_20_folders_are')
files = os.listdir(r'place_where_images_are')
string=r"string_to_add_to_make_full_path_of_each_file"
folders=[string+s for s in folders]
for folder in folders:
for fileName in random.sample(files, min(len(files), 500)):
path = os.path.join(r'place_where_images_are', fileName)
shutil.move(path, folder)
I think the problem in your code is that the random.sample() method leaves the original files list unchanged. Because of this you have a chance of getting the same filename twice, but as you already moved it before you will have an error.
Instead of using sample you could use this snippet:
files_to_move = [files.pop(random.randrange(0, len(files))) for _ in range(500)]
This will pop (thus removing) 500 random files from the files list and save them in files_to_move. As you repeat this, the files list becomes smaller.
This answer was inspired by this answer to the question Random Sample with remove from List.
This would be used like this:
import os
import shutil
import random
folders = os.listdir(r'place_where_20_folders_are')
files = os.listdir(r'place_where_images_are')
string=r"string_to_add_to_make_full_path_of_each_file"
folders=[string+s for s in folders]
for folder in folders:
files_to_move = [files.pop(random.randrange(0, len(files))) for _ in range(500)]
for file_to_move in files_to_move:
path = os.path.join(r'place_where_images_are', file_to_move)
shutil.move(path, folder)
I would start by making a list of random sample first and then pass it for moving in different location, and removing my list by using random libraries remove() , or just clearing/deleting/popping the list itself before the loop starts again.
Hope its helps.

How can I open a series of files (PNGs) from a specified directory (randomly) using Python?

I have a folder in a specified directory containing several PNGs that need to be opened randomly. I can't seem to get random.shuffle to work on the folder. I have thus far been able to print the contents, but they need to also be randomized so when they are opened, the sequence is unique.
Here's my code:
import os, sys
from random import shuffle
for root, dirs, files in os.walk("C:\Users\Mickey\Desktop\VisualAngle\sample images"):
for file in files:
if file.endswith(".png"):
print (os.path.join(root, file))
This returns a list of the images in the folder. I'm thinking maybe I could somehow randomize the output from print and then use open. I have so far failed. Any ideas?
I have a folder in a specified directory containing several PNGs. You don't need and should not be using os.path.walk searching a specific directory, it would also potentially add files from other subdirectories which would give you incorrect results. You can get a list of all png's using glob and then shuffle:
from random import shuffle
from glob import glob
files = glob(r"C:\Users\Mickey\Desktop\VisualAngle\sample images\*.png")
shuffle(files)
glob will also return the full path.
You could also use os.listdir to search the specific folder:
pth = r"C:\Users\Mickey\Desktop\VisualAngle\sample images"
files = [os.path.join(pth,fle) for fle in os.listdir(pth) if fle.endswith(".png")]
shuffle(files)
To open:
for fle in files:
with open(fle) as f:
...
You can create first the list of png filenames and then shuffle:
import os
from random import shuffle
dirname = r'C:\Users\Mickey\Desktop\VisualAngle\sample images'
paths = [
os.path.join(root, filename)
for root, dirs, files in os.walk(dirname)
for filename in files
if filename.endswith('.png')
]
shuffle(paths)
print paths

Categories