Getting TypeError: img should be PIL Image. Got <class 'NoneType'> when I use a custom transformation

I have been using my custom transformation namely FaceDetection which I added below. Now I am trying to apply it to another dataset which contains face images within the same format of the former (.png). What am I missing? When I do not use this transformation, I do not get any errors.

Your help is appreciated a lot.

Here is my custom transformation class, FaceDetection, based on OpenCV to detect the location of faces in the images:

class FaceDetection(object):

    def __init__(self):
        pass

    def __call__(self, frame):
        faceCascade = cv2.CascadeClassifier(cascPath)

        if frame is not None:
            gray = cv2.cvtColor(np.array(frame), cv2.COLOR_BGR2GRAY)

            faces = faceCascade.detectMultiScale(
                gray,
                scaleFactor=1.1,
                minNeighbors=5,
                minSize=(1, 1)
            )

            for (x, y, w, h) in faces:
                image_as_arr = np.array(frame)[y:y + w, x:x + h]
                return Image.fromarray(image_as_arr.astype('uint8'), 'RGB')

And here is the composition of my transformations:

data_transforms = transforms.Compose([
    FaceDetection(),
    transforms.Resize(48),
    transforms.Grayscale(num_output_channels=1),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5],
                         std=[0.5])
])

Finally, I apply it when I load the training dataset:
face_train_dataset = datasets.ImageFolder(root=DEST_PATH_TRAIN, transform=data_transforms)

It seems your custom transformation didn’t find any faces and thus didn’t return a valid PIL.Image.

I see but it works when I skip my custom transformation. So, the destination (DEST_PATH_TRAIN) should be a right path as the transformation does nothing related to the path of the images.

I think the face cascade doesn’t find any faces and this loop:

for (x, y, w, h) in faces:
    image_as_arr = np.array(frame)[y:y + w, x:x + h]
    return Image.fromarray(image_as_arr.astype('uint8'), 'RGB')

will be empty.
Since you don’t have any other return statement, your transformation will return None by default.
If you add an assert before the loop and check faces for a valid entry, you should see an exception.

1 Like

Just added a control in the case of not founding any faces in the image. Now works as expected. Thanks a lot for your guidance.

1 Like