11 Replies - 524 Views - Last Post: 13 January 2020 - 10:06 AM Rate Topic: -----

#1 wantsToCode   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 25-February 19

Having trouble iterating with the for - loop

Posted 09 January 2020 - 08:11 AM

Could someone show me what I'm doing wrong with my for - loop? These functions use aws rekognition api to detect faces from pictures saved locally by another function. Everything goes fine (I get a response from aws etc) until it should save the images where faces are detected. It saves with the same filename over and over again, replacing the previous one. So instead of getting for example five different pictures, I end up getting one. Here's my code:


 
import boto3
from pathlib import Path
import os
import cv2
import io
from PIL import Image, ImageDraw, ExifTags, ImageColor
​
​
async def detect_faces(photo):
    image = Image.open(open(photo, 'rb'))
    stream = io.BytesIO()
    image.save(stream, format=image.format)
    image_binary = stream.getvalue()
​
    client = boto3.client('rekognition')
    response = client.detect_faces(
        Image={'Bytes': image_binary}, Attributes=['ALL'])
​
    draw = ImageDraw.Draw(image)
​
    print('Detected faces in ' + photo)
    currentpic = 0
    
    
    for face in response['FaceDetails']:
        print('Confidence: ' + str(face['Confidence']))
       
        box = face['BoundingBox']
        imgWidth, imgHeight = image.size
        left = imgWidth * box['Left']
        top = imgHeight * box['Top']
        width = imgWidth * box['Width']
        height = imgHeight * box['Height']
​
        print('Left: ' + '{0:.0f}'.format(left))
        print('Top: ' + '{0:.0f}'.format(top))
        print('Face Width: ' + "{0:.0f}".format(width))
        print('Face Height: ' + "{0:.0f}".format(height))
​
        points = (
            (left, top),
            (left + width, top),
            (left + width, top + height),
            (left, top + height),
            (left, top)
​
        )
        draw.line(points, fill='#00d400', width=2)
​
        # print(response)
​
        name = './results/pic' + str(currentpic) + '.jpg'
        print('Creating final pic.....' + name)
        image.save(name)
        currentpic += 1
​
    return len(response['FaceDetails'])
    
​
​
async def main():
    directory_in_str = './data'
    pathlist = Path(directory_in_str).glob('**/*.jpg')
​
    try:
        if not os.path.exists('results'):
            os.makedirs('results')
​
        # if not created then raise error
    except OSError:
        print('Error: Creating directory of data')
​
    for path in pathlist:
        # path is object not string
        path_in_str = str(path)
        # print(path_in_str)
        photo = path_in_str
​
        face_count = await detect_faces(photo)
        print("Faces detected: " + str(face_count))
​
​



Is This A Good Question/Topic? 0
  • +

Replies To: Having trouble iterating with the for - loop

#2 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6829
  • View blog
  • Posts: 28,315
  • Joined: 12-December 12

Re: Having trouble iterating with the for - loop

Posted 09 January 2020 - 08:32 AM

What name are they being saved as, results/pic0.jpg or results/pic4.jpg ?
Was This Post Helpful? 1
  • +
  • -

#3 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6829
  • View blog
  • Posts: 28,315
  • Joined: 12-December 12

Re: Having trouble iterating with the for - loop

Posted 09 January 2020 - 08:40 AM

With the statement

print('Creating final pic.....' + name)


does it print different values each time?
Was This Post Helpful? 1
  • +
  • -

#4 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 3038
  • View blog
  • Posts: 11,679
  • Joined: 03-December 12

Re: Having trouble iterating with the for - loop

Posted 09 January 2020 - 09:30 AM

I would think that you would want to use the variable in 'photo' not the integer of 'currentpic'?

name = './results/pic/{photo}.jpg'


Was This Post Helpful? 1
  • +
  • -

#5 wantsToCode   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 25-February 19

Re: Having trouble iterating with the for - loop

Posted 09 January 2020 - 10:02 AM

It saves pic0.jpg and overrides it with every round. Can't figure out what is wrong with that for-loop since it's giving the right results for every picture. To clarify this a bit: I have a function that saves images from a video. From the video I've used in this test case it saves six pictures. Four of those have faces. After the pics are saved locally I use aws api to detect faces from them and it should save the pics with faces (with bounding boxes). Code works fine until that saving part. First it jumps over the first two pics with no faces and saves the third one as 'pic0.jpg'. But after that it overrides the file with pics four, five and six.

Thank you @astonecipher, I will look at that when I get to my computer.
Was This Post Helpful? 0
  • +
  • -

#6 wantsToCode   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 25-February 19

Re: Having trouble iterating with the for - loop

Posted 10 January 2020 - 06:24 AM

Still struggling with this. As far as I can figure the problem shouldn't be with the
name = './results/pic' + str(currentpic) + '.jpg'
because I'm using it in the same way in another function without any problems. And since my code goes thorough every picture it receives from another function and saves a file 'pic0.jpg' correctly, the problem shouldn't be at saving either. So as far as I can understand, the problem must be in this for-loop:
 for face in response['FaceDetails']: 


I'll put my function responsible for producing the files I use in that 'detect_faces' function:

 import cv2
from imutils.video import FPS
import numpy as np
import argparse
import imutils
import os


async def take_snapshots(file):
	cascPath = "haarcascade_frontalface_default.xml"

	faceCascade = cv2.CascadeClassifier(cascPath)

	stream = cv2.VideoCapture(file)
	# fps = FPS().start()
	# stream.set(cv2.CAP_PROP_POS_MSEC)
	w = int(stream.get(cv2.CAP_PROP_FRAME_WIDTH))
	h = int(stream.get(cv2.CAP_PROP_FRAME_HEIGHT))
	fps = int(stream.get(cv2.CAP_PROP_FPS))
	frame_count = int(stream.get(cv2.CAP_PROP_FRAME_COUNT))
	duration = frame_count/fps
	

	print('fps = ' + str(fps))
	print('number of frames = ' + str(frame_count))
	print('duration (S) = ' + str(duration))
	minutes = int(duration/60)
	seconds = duration%60
	print('duration (M:S) = ' + str(minutes) + ':' + str(seconds))

	try:

		# creating a folder named data
		if not os.path.exists('data'):
			os.makedirs('data')

	# if not created then raise error
	except OSError:
		print('Error: Creating directory of data')

	# frame
	currentframe = 0

	# loop over frames from the video file stream
	while True:
		# grab the frame from the threaded video file stream
		(grabbed, frame) = stream.read()

		# if the frame was not grabbed, then we have reached the end
		# of the stream
		if not grabbed:
			break

		# resize the frame and convert it to grayscale (while still
		# retaining 3 channels)
		frame = imutils.resize(frame, width=980)
		frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
		frame = np.dstack([frame, frame, frame])
		faces = faceCascade.detectMultiScale(
							frame,
							scaleFactor=1.1,
							minNeighbors=4,
							minSize=(20, 20),
							maxSize=(40, 40),
							# flags=cv2.CASCADE_SCALE_IMAGE
					)

		for (x, y, w, h) in faces:
				# cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)
				if grabbed:
						
						name = './data/frame' + str(currentframe) + '.jpg'
						print('Creating...' + name)

						# writing the extracted images
						cv2.imwrite(name, frame)

						# increasing counter so that it will
						# show how many frames are created
						currentframe += 1

						if cv2.waitKey(1) & 0xFF == ord('q'):
								break

				else:
						break
		
		

	# do a bit of cleanup
	stream.release()
	cv2.destroyAllWindows()




Was This Post Helpful? 0
  • +
  • -

#7 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 3038
  • View blog
  • Posts: 11,679
  • Joined: 03-December 12

Re: Having trouble iterating with the for - loop

Posted 10 January 2020 - 06:29 AM

My understanding is the only issue is it overwriting the same image rather than creating a new file, correct?
Was This Post Helpful? 1
  • +
  • -

#8 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6829
  • View blog
  • Posts: 28,315
  • Joined: 12-December 12

Re: Having trouble iterating with the for - loop

Posted 10 January 2020 - 06:32 AM

You haven't answered my question, repeated here:

View Postandrewsw, on 09 January 2020 - 03:40 PM, said:

With the statement

print('Creating final pic.....' + name)


does it print different values each time?

The 'print' is a debugging statement, if it prints out five times it at least tells you that the loop is executed five times. If it only prints once then it seems that it is only finding, and attempting to save, a single picture.

I was also curious about your use of async; again, the print statement(s) output would possibly give a clue about this. (If there are async calls to save images it could possibly be that they interfere with each other, possibly causing a single write operation.)
Was This Post Helpful? 1
  • +
  • -

#9 wantsToCode   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 25-February 19

Re: Having trouble iterating with the for - loop

Posted 10 January 2020 - 07:58 AM

View Postastonecipher, on 10 January 2020 - 06:29 AM, said:

My understanding is the only issue is it overwriting the same image rather than creating a new file, correct?

Yes, that is my only problem at the moment.

View Postandrewsw, on 10 January 2020 - 06:32 AM, said:

You haven't answered my question, repeated here:

View Postandrewsw, on 09 January 2020 - 03:40 PM, said:

With the statement
print('Creating final pic.....' + name)
does it print different values each time?


It takes as a input all the pictures one by one and goes through them correctly. If I print the response I get a different response for every picture it iterates.
Was This Post Helpful? 0
  • +
  • -

#10 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 3038
  • View blog
  • Posts: 11,679
  • Joined: 03-December 12

Re: Having trouble iterating with the for - loop

Posted 10 January 2020 - 08:18 AM

You could always generate a dynamic name, something like using the timestamp or a number of other things like uuid.

import uuid 

print(str(uuid.uuid4()))

Was This Post Helpful? 1
  • +
  • -

#11 wantsToCode   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 25-February 19

Re: Having trouble iterating with the for - loop

Posted 13 January 2020 - 12:55 AM

View Postastonecipher, on 10 January 2020 - 08:18 AM, said:

You could always generate a dynamic name, something like using the timestamp or a number of other things like uuid.

import uuid 

print(str(uuid.uuid4()))


Thank you for your help, this solved my problem! I was sure there was something wrong with my loop, but it was this like you said from the beginning.
Was This Post Helpful? 0
  • +
  • -

#12 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 3038
  • View blog
  • Posts: 11,679
  • Joined: 03-December 12

Re: Having trouble iterating with the for - loop

Posted 13 January 2020 - 10:06 AM

View Postandrewsw, on 09 January 2020 - 09:40 AM, said:

With the statement

print('Creating final pic.....' + name)


does it print different values each time?

My thought was this was the issue, they just didn't know why it was the issue.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1