This is my code. I have a learning problem. Gives the error
error: (-5:Bad argument) Empty training data was given. You'll need more than one sample to learn a model. in function 'train'.
I can't solve this problem. I can't find an explanation on how to fix it? Where can I read about the solution to this problem? My pictures have size 200x200, format .pgm.
import os
import cv2
import numpy as np
def read_images(path, image_size):
names = []
training_images, training_labels = [], []
label = 0
for dirname, subdirnames, filenames in os.walk(path):
for subdirname in subdirnames:
names.append(subdirname)
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
img = cv2.imread(os.path.join(subject_path, filename),
cv2.IMREAD_GRAYSCALE)
if img is None:
# The file cannot be loaded as an image.
# Skip it.
continue
img = cv2.resize(img, image_size)
training_images.append(img)
training_labels.append(label)
label = 1
training_images = np.asarray(training_images, np.uint8)
training_labels = np.asarray(training_labels, np.int32)
return names, training_images, training_labels
path_to_training_images = '/home/ace/OpenCV/cascades/A_M'# not properly. This is = '/home/ace/OpenCV/cascades/'
training_image_size = (200, 200)
names, training_images, training_labels = read_images(path_to_training_images, training_image_size)
model = cv2.face.EigenFaceRecognizer_create()
model.train(training_images, training_labels)
face_cascade = cv2.CascadeClassifier('/haarcascade_frontalface_default.xml')
camera = cv2.VideoCapture(2)
while (cv2.waitKey(1) == -1):
success, frame = camera.read()
if success:
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x w, y h), (255, 0, 0), 2)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
roi_gray = gray[x:x w, y:y h]
if roi_gray.size == 0:
# The ROI is empty. Maybe the face is at the image edge.
# Skip it.
continue
roi_gray = cv2.resize(roi_gray, training_image_size)
label, confidence = model.predict(roi_gray)
text = '%s, confidence=%.2f' % (names[label], confidence)
cv2.putText(frame, text, (x, y - 20),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('Face Recognition', frame)
CodePudding user response:
Although it seems a little bit odd that you use recursive walk
-function and then seperately list the subdirectories, your read_images
function works for me if I create a folder structure like this:
images/
- sub1/
- img1.png
- img2.png
- sub2/
- img3.png
- img4.png
The files are found and the return values are filled. Probably your folder structure differs from what your code expects.
You can try to debug your setup with some further print-statements like this:
def read_images(path, image_size):
names = []
training_images, training_labels = [], []
label = 0
for dirname, subdirnames, filenames in os.walk(path):
print(f"dirname={dirname}")
for subdirname in subdirnames:
print(f"- subdirname={subdirname}")
names.append(subdirname)
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
print(f" - filename={filename}")
img = cv2.imread(os.path.join(subject_path, filename),
cv2.IMREAD_GRAYSCALE)
if img is None:
# The file cannot be loaded as an image.
# Skip it.
continue
img = cv2.resize(img, image_size)
training_images.append(img)
training_labels.append(label)
label = 1
training_images = np.asarray(training_images, np.uint8)
training_labels = np.asarray(training_labels, np.int32)
return names, training_images, training_labels
Please check the output of those prints and compare it with your folder structure. If this doesn't help, please share the debug output and your folder structure with us. Please don't share it as comment but by updating your question!