Search code examples
python-3.xopencvphotobatching

Batching only reading/saving last image in folder


I am trying to add batching to a OpenCV python script I am making and I cannot for the life of me see what I am doing wrong. I am a beginner at this so its probably something stupid. In the end I want the script to read every image file in the current working directory of the script and then crop based on the face detect from openCV and output those cropped images with the same name to a folder inside the CWD. Right now all it does though is output the last image in the folder into the output folder. Any ideas from those who know what they are doing?

import cv2
import sys
import os.path
import glob

#Cascade path
cascPath = 'haarcascade_frontalface_default.xml'

# Create the haar cascade
faceCascade = cv2.CascadeClassifier(cascPath)

# Read Images
images = glob.glob('*.jpg')
for i in images:
    image = cv2.imread(i,1)

#Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Find face(s) using cascade
faces = faceCascade.detectMultiScale(
    gray,
    scaleFactor=1.1, #size of groups
    minNeighbors=5, #How many groups around are detected as face for it to be valid
    minSize=(300, 300) #Min size in pixels for face
)

# Outputs number of faces found in image
print('Found {0} faces!'.format(len(faces)))

# Places a rectangle on face (For debugging, wont be in crop version)
for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x+w, y+h), (255, 255, 255), 4)

# Resizes image to fit monitor and displayes it
imOut = cv2.resize(image, (750, 1142))
#cv2.imshow("Faces found", imS)
#cv2.waitKey(0)

#Saves image to output folder and creates folder if it doesnt exist
if not os.path.exists('output'):
    os.makedirs('output')
os.chdir('output')
cv2.imwrite(i, imOut)

Solution

  • There are multiple corrections I have made in the code

      1. You need the give the full path of the haarcascade_frontalface_default.xml

      For instance: in Unix system:

      cascPath = 'opencv/data/haarcascades/haarcascade_frontalface_default.xml'
      
      1. You shouldn't create directories during the loop. You should create it before the loop.
      if not os.path.exists('output'):
        os.makedirs('output')
      
      1. You don't need to change the directory to save the images. Just add the path before the image.
      img_name = "output/out_{}.png".format(c) # c is the counter  
      
      1. Indentation is important, otherwise, you might have difficulties.

    Example code:

    import cv2
    import os.path
    import glob
    
    # Cascade path
    cascPath = '/opencv/data/haarcascades/haarcascade_frontalface_default.xml'
    
    # Create the haar cascade
    faceCascade = cv2.CascadeClassifier(cascPath)
    
    if not os.path.exists('output'):
        os.makedirs('output')
    
    # Read Images
    images = glob.glob('images/*.jpg')
    for c, i in enumerate(images):
        image = cv2.imread(i, 1)
    
        # Convert to grayscale
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
        # Find face(s) using cascade
        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.1,  # size of groups
            minNeighbors=5,  # How many groups around are detected as face for it to be valid
            minSize=(300, 300)  # Min size in pixels for face
        )
    
        # Outputs number of faces found in image
        print('Found {0} faces!'.format(len(faces)))
    
        # Places a rectangle on face (For debugging, wont be in crop version)
        for (x, y, w, h) in faces:
            cv2.rectangle(image, (x, y), (x + w, y + h), (255, 255, 255), 4)
    
        if len(faces) > 0:
            # Resizes image to fit monitor and displayes it
            imOut = cv2.resize(image, (750, 1142))
            # cv2.imshow("Faces found", imS)
            # cv2.waitKey(0)
    
            # Saves image to output folder and creates folder if it doesnt exist
    
            # os.chdir('output')
            img_name = "output/out_{}.png".format(c)
            cv2.imwrite(img_name, imOut)
    

    Example output:

    enter image description here