Cannot iterate over a file? - python

I want to know how to apply a function over a file of images and save each of them in a separate file. For one image it works successfully, but i cannot apply it to all images.
import glob
images = glob.glob('/Desktop/Dataset/Images/*')
for img in images:
img = np.array(Image.open(img))
output = 'Desktop/Dataset/Output'
MyFn(img = img,saveFile = output)

You did not define the sv value in your 2nd code snippet.
As the image will be overwrite, try this code:
import glob
images = glob.glob('/Desktop/Dataset/Images/*')
i = 0
for img in images:
i += 1 #iteration to avoid overwrite
img = np.array(Image.open(img))
output = 'Desktop/Dataset/Output'
MyFn(img = img + str(i),saveFile = output)

try to use the library os directly with
import os
entries = os.listdir('image/')
this will return a list of all the file into your folder

This is because you are not setting the sv value in your loop. You should set it to a different value at each iteration in order for it to write to different files.

Related

Saving images with different name in folder

I tried save images in folder like this, it saves different images but every next image have all names of previously images.
db = h5py.File('results/Results.h5', 'r')
dsets = sorted(db['data'].keys())
for k in dsets:
db = get_data()
imnames = sorted(db['data'].keys())
slika = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imwrite(f'spremljene_slike/ime_{imnames}.png', slika)
So i tried like this and it saves different names but only last generated picture is imwrited in folder, so different names - the same picture
NUM_IMG = -1
N = len(imnames)
global NUM_IMG
if NUM_IMG < 0:
NUM_IMG = N
start_idx,end_idx = 0,N #min(NUM_IMG, N)
**In different function:**
for u in range(start_idx,end_idx):
imname = imnames[u]
cv2.imwrite(f'spremljene_slike/ime_{imname}.png', imname)
Can someone help, I can't figure out.
I have script which generate images with rendered text and save it in .h5 file, and then from there I want to save this pictures with corresponding names in different folder.
Don't see how this works at all. On line 1 you define db=h5py.File(), then on line 4, you redefine it as db=get_data(). What is get_data()?
It's hard to write code without the schema. Answer below is my best-guess assuming your images are datasets in db['data'] and you want to use the dataset names (aka keys) as the image names.
with h5py.File('results/Results.h5', 'r') as db:
dsets = sorted(db['data'].keys())
for imname in dsets:
img_arr = db['data'][imname][()]
slika = cv2.cvtColor(img_arr, cv2.COLOR_BGR2RGB)
cv2.imwrite(f'spremljene_slike/ime_{imname}.png', slika)
That should be all you need to do. You will get 1 .png for each dataset named ime_{imname}.png (where imname is the matching dataset name).
Also, you can eliminate all of the intermediate variables (dsets, img_arr and slika). Compress the code above into a few lines:
with h5py.File('results/Results.h5', 'r') as db:
for imname in sorted(db['data'].keys()):
cv2.imwrite(f'spremljene_slike/ime_{imname}.png', \
cv2.cvtColor(db['data'][imname][()], cv2.COLOR_BGR2RGB))

Custom name for an opencv image (complex name)

hi I want to take a frame from the camera and save it in a folder 'images', I want the image to have name + current timestamp+.jpg , I'm getting error for typing it like this:
cv2.imwrite(os.path.join(path2 , rn), img)
where path2='images'
and rn=str(rightnow.strftime("%I:%M:%p"))
i get this error : could not find a writer for the specified extension in function 'cv::imwrite_'
how can I do it plz , I searched but didn't find an answer and I'm new to python, thanks in advance
The accepted answer is os specific.
What happens if you run the code in Windows?
Assume you have millions of code, are you going to change each slash / with \?
You should use os.path.sep instead of static slash declaration.
First, remove the : in strftime, you can use - or _ or nothing.
rn = str(rightnow.strftime("%I%M%p"))
Second, check whether the path exists, if it doesn't exist, create.
path3 = "".join([path2, os.path.sep, rn])
if not os.path.exists(path3):
os.mkdir(path3)
Third, create the image name
save = "".join([path3, os.path.sep, "image_name.png"])
If you are executing the statement inside the loop, you may use counter
counter += 1
save = "".join([path3, os.path.sep, "image_name{}.png".format(counter)])
Code:
import os
import cv2
from datetime import datetime
path2 = 'img2'
rightnow = datetime.now()
rn = str(rightnow.strftime("%I%M%p"))
img = cv2.imread("1.png")
path3 = "".join([path2, os.path.sep, rn])
if not os.path.exists(path3):
os.mkdir(path3)
save = "".join([path3, os.path.sep, "image_name.png"])
cv2.imwrite(save, img)
Try to change:
cv2.imwrite(os.path.join(path2 , rn), img)
to
cv2.imwrite(os.path.join(path2 , rn)+".jpg", img)

How to create variables for Facial_Recognition from database

I'm trying to be able to pull data from a database with a name and an image file name then put it into a face_recognition Python program. However, for the code that I'm using, the program learns the faces by calling variables with different names.
How can I create variables based on the amount of data that I have in the database?
What could be a better approach to solve this problem?
first_image = face_recognition.load_image_file("first.jpg")
first_face_encoding = face_recognition.face_encodings(first_image)[0]
second_image = face_recognition.load_image_file("second.jpg")
biden_face_encoding = face_recognition.face_encodings(second_image)[0]
You can use arrays instead of storing each image/encoding in an individual variable, and fill the arrays from a for loop.
Assuming you can change the filenames from first.jpg, second.jpg... to 1.jpg, 2.jpg... you can do this:
numberofimages = 10 # change this to the total number of images
images = [None] * (numberofimages+1) # create an array to store all the images
encodings = [None] * (numberofimages+1) # create an array to store all the encodings
for i in range(1, numberofimages+1):
filename = str(i) + ".jpg" # generate image file name (eg. 1.jpg, 2.jpg...)
# load the image and store it in the array
images[i] = face_recognition.load_image_file(filename)
# store the encoding
encodings[i] = face_recognition.face_encodings(images[i])[0]
You can then access eg. the 3rd image and 3rd encoding like this:
image[3]
encoding[3]
If changing image file names is not an option, you can store them in a dictionary and do this:
numberofimages = 3 # change this to the total number of images
images = [None] * (numberofimages+1) # create an array to store all the images
encodings = [None] * (numberofimages+1) # create an array to store all the encodings
filenames = {
1: "first",
2: "second",
3: "third"
}
for i in range(1, numberofimages+1):
filename = filenames[i] + ".jpg" # generate file name (eg. first.jpg, second.jpg...)
print(filename)
# load the image and store it in the array
images[i] = face_recognition.load_image_file(filename)
# store the encoding
encodings[i] = face_recognition.face_encodings(images[i])[0]

Downloaded Images does not set as background always?

I am trying to download some images from MomentumDash (for educational purpose only).
I have written the following python code:
import urllib
import os
import random
#Chooses an image between 1 to 14
choice=random.randint(01,14)
print choice
#Downloads images
a=urllib.urlretrieve("https://momentumdash.com/backgrounds/"+"%02d" % (choice,)+".jpg", str(choice)+".jpg")
print a #Tells the image
#Getting the location of the saved image
cwd = os.getcwd()
random=random.choice(os.listdir(cwd))
file =cwd+ '\\' +random
#Making the image to desktop image
import ctypes
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER , 0, file, 3)
The thing is the probability of this progrm to set a image is 1/7 ish.
Most of the times it gives a black background screen.
Where am I wrong?
Try the following. This ensures that the directory listing is filtered to give you only jpg files. A random entry is taken from these. Also os.path.join() is used to safely join your path and name together.
import urllib
import os
import random
import ctypes
#Chooses an image between 1 to 14
choice = random.randint(1, 14)
#Downloads images
download_name = "{:02}.jpg".format(choice)
a = urllib.urlretrieve("https://momentumdash.com/backgrounds/{}".format(download_name), download_name)
#Getting the location of the saved image
cwd = os.getcwd()
#Filter the list to only give JPG image files
image_files = [f for f in os.listdir(cwd) if os.path.splitext(f)[1].lower() == ".jpg"]
random_image = random.choice(image_files)
full_path = os.path.join(cwd, random_image)
#Making the image to desktop image
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER , 0, full_path, 3)
The list of files is filtered by using Python's list comprehension feature. This is a way of building a new list from an existing item. In this case it uses the optional if statement to only include files in the new list which have an extension of .jpg.
Try the following:
import urllib
import os
import random
import ctypes
# Set up an output folder
out_folder = os.path.join(os.getcwd(), 'Backgrounds')
# Make it if it doesn't exist
if not os.path.isdir(out_folder):
os.mkdir(out_folder)
# Loop through all values between 1 and 15
for choice in range(1,15):
#Downloads images
a = urllib.urlretrieve("https://momentumdash.com/backgrounds/" + "%02d" % (choice,)+".jpg",
os.path.join(out_folder, "{}.jpg".format(choice))
)
selected_wallpaper = random.choice(os.listdir(out_folder))
#Making the image to desktop image
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, os.path.join(out_folder, selected_wallpaper), 3)
This creates a folder called Backgrounds in your current working directory, saves all the images there and then picks one at random.

Correcting use of pool on python iterable

I'm trying to use multithreading.pool to compare images based on similarity. While I have code working on a single core, using a for loop or map() to iterate over the data, it's dreadfully slow on large groups of images. For that reason I've been trying to implement multiprocessing but I can't seem to get it right. My main question is why doesn't getssim() in the below code change the list?
The structure of the iterable looks something like this:
[[("images/000.jpg",np.ndarray),0.923],...]
Where the float is the simiarlity index of an image compared to the current image being tested. Here is the (somewhat abbreviated) non-working code:
import cv2
import glob
from skimage.measure import structural_similarity as ssim
import operator
import multiprocessing
def makeSimilarList(imagesdata):
simImgList = [] #list of images ordered by their similarity
while(imagesdata):
simImg = findSimilar(imagesdata)
simImgList.append(os.path.basename(simImg))
return simImgList
def getssim(imgd):
similarityIndex = ssim(img1,imgd[0][1])
print(similarityIndex) #this prints correctly
imgd[1] = similarityIndex
return imgd #this appears to have no effect
def findSimilar(imagesdata):
limg = imagesdata.pop()
global img1 #making img1 accessible to getssim, a bad idea!
img1 = limg[0][1]
p = multiprocessing.Pool(processes=multiprocessing.cpu_count(),maxtasksperchild=2)
p.map(getssim,imagesdata)
p.close()
p.join()
imagesdata.sort(key=operator.itemgetter(1))
return limg[0][0] #return name of image
images = [f for f in glob.glob(src + "*." + ftype)]
images.reverse()
imagesdata = [[(f,cv2.imread(f,0)),""] for f in images]
finalList = makeSimilarList(imagesdata)
with open("./simlist.txt", 'w') as f:
f.write('\n'.join(finalList))
Thanks for the help!!
You forgot to assign the result from multiprocessing.map to a variable. The key function should probably read
def findSimilar(imagesdata):
limg = imagesdata.pop()
global img1 # making img1 accessible to getssim, a bad idea!
img1 = limg[0][1]
p = multiprocessing.Pool(maxtasksperchild=2)
imagesdata = p.map(getssim, imagesdata)
p.close()
p.join()
imagesdata.sort(key=operator.itemgetter(1))
return limg[0][0] #return name of image
Since you don't give enough details, I could not test your code, but I think this was the crucial point.

Categories