Grady D
Grady D

Reputation: 2039

Python output repeats even though it should break

I have a script that is using OpenCV to find faces and if a face is not found it outputs "No faces found" but it never does anything else. It should look back up and ask for another image. Can anyone tell me why it just prints "No faces found" until I press CTRL+C?

def Crop(
    imagePattern,
    boxScale,
    outputimg,
    padding,
    ):
    happy = True
    imgList = glob.glob(imagePattern)
    while happy:
        if len(imgList) <= 0:
            return
        else:
            for img in imgList:
                pil_im = Image.open(img)
                cv_im = pil2cvGrey(pil_im)
                faces = DetectFace(cv_im, faceCascade)
                if faces:
                    n = 1
                    for face in faces:
                        croppedImage = imgCrop(pil_im, face[0],
                                padding, boxScale=boxScale)
                        (fname, ext) = os.path.splitext(img)
                        fname = os.path.basename(fname)
                        croppedImage.save(outputimg + '\\' + fname
                                + ' -c' + ext)
                        n += 1
                    print 'Cropping:', fname
                else:
                    print 'No faces found:', img
                    break

                            # Verify image
                            # savedPath = outputimg + '\\' + fname + ' -c' + ext
                            # verify = cv2.imread(savedPath, 0)
                            # cv2.imshow('Saved Image', verify)

                print 'Please open the file manually to view for now'
                print 'Are you happy with the final crop?'
                happyTest = raw_input('Enter y or n: ')
                happyTest = happyTest.strip()
                if happyTest == 'y':
                    happy = False
                elif happyTest == 'n':
                    padding = int(raw_input('Enter crop padding:'))
                else:
                    print 'Not a valid input'
    print 'Do you have more pictures to take?'
    again = raw_input('Enter y or n: ')
    if again == 'y':
        Webcam(webcam, padding, boxScale)
    else:
        print 'Closing application'
        time.sleep(3)
        raise SystemExit

Sorry for the confusion, I had a bad copy/paste due to me using tabs for my code.

EDIT: Thank you for letting me know about the mixing tabs and spaces but my issue is still the same. It also does not matter if I use a break or a continue. Do I need to use recursion and call the function again?

Upvotes: 0

Views: 100

Answers (4)

Anshul Goyal
Anshul Goyal

Reputation: 77007

You are using a break statement, which halts the for loop completely.

Instead, use a continue statement there to skip the current image and move on to the next one within the for loop.

Read more about break and continue here

Also, You are using tabs and spaces togather, which is causing the indentation of the blocks to be misaligned. While they look as if they are aligned all right, you will have nightmares debugging tab errors, so just change your editor settings to use a tab as 4 whitespaces.

EDIT

There are multiple issues in your code:

  1. You are checking for len(imgList)<=0 which is redundant as has already been pointed out in other answer.
  2. The happytest value that you take is taken for every img in imglist, yet only the one entered on the last run will affect the value of the happy variable.
  3. Because of #2 above, I am inclined to think that your original intent was to stop at any run during which the value of happy was False, which is definitely not happening right now.
  4. You are using capital letters and camel case both to begin the name of some functions and I am having a hard time figuring if something is a public class or another function.
  5. There are multiple external functions being referenced within the code, but I have not much clue of what they are supposed to do, and whether they actually do whatever they are supposed to do.

Upvotes: 3

jsbueno
jsbueno

Reputation: 110506

You have an extar break on your code -this version should work:

for img in imgList:
    pil_im=Image.open(img)
    cv_im=pil2cvGrey(pil_im)
    faces=DetectFace(cv_im,faceCascade)
    if faces:
        n=1
        for face in faces:
            croppedImage=imgCrop(pil_im, face[0], padding, boxScale=boxScale)
            fname,ext=os.path.splitext(img)
            fname = os.path.basename(fname)
            croppedImage.save(outputimg + '\\' + fname + ' -c' + ext)
            n+=1
        print 'Cropping:', fname
    else:
        print 'No faces found:', img

So, while it is true on the other answers and comments that you shpould not have the "break" inside the elsestatement - the problem you put forward in your question happens because you have that break at all: if the code reach that else block, it will just break out of the for img in imgList: loop and process nothing further.

besides that, I have fixed two other things in this code: indentation - in Python it is serious business, not "what works is fine". The recomendation is to use 4 spaces per block nesting - no more, no less, and never, never mix tabs and spaces. You have to configure that on your code editor preferences.

The other part of your code that is alien to Python is the verification prior to the loop if len(imgList)<=0: that is complettly superfluous in Python (not to mention the <= part): if the list lenght is zero (it can't be negative), the forstatement will try to pick the first item, and since it does not exist, the program will simply continue after the for block. Each level of indentation you reduce in your code is a bonus in readability. (The Zen of Python even reads "Flat is better than nested"). On the other hand, if in some other part of the code you really have to check if the lsit is empty,just do if imgList:, as sequences in Python have the nice property of having a False boolean value if they are empty, and True otherwise.

Upvotes: 0

Karl Knechtel
Karl Knechtel

Reputation: 61617

The break you have coded breaks out of the for img in imgList: loop, not the while happy: loop. And since the code you use to ask the user if the cropping is satisfactory, is inside that loop (and after the break), it never gets reached (and thus happy can never be set False).

Upvotes: 0

Luke Dinkler
Luke Dinkler

Reputation: 769

I don't know if this is the problem, but it is how you posted it anyway: Your commands after the else statement are not indented. Shouldn't it have given you an error?

Upvotes: 0

Related Questions