使用OpenCV和Python进行人脸识别(4)

  由于OpenCV人脸识别器接受标签为整数,因此我们需要定义整数标签和人物实际名称之间的映射,所以下面我定义了人员整数标签及其各自名称的映射。

  注意:由于我们尚未将标签0分配给任何人,因此标签0的映射为空。

#我们的训练数据中没有标签0,因此索引/标签0的主题名称为空 subjects = ["", "Ramiz Raja", "Elvis Presley"]

准备训练数据

  您可能想知道为什么要进行数据准备,对吗? 那么,OpenCV人脸识别器接受特定格式的数据。 它接受两个矢量,一个矢量是所有人的脸部,第二个矢量是每个脸部的整数标签,因此在处理脸部时,脸部识别器会知道该脸部属于哪个人。

  例如,如果我们有两个人和两个图像为每个人。

  PERSON-1 PERSON-2   img1 img1   img2 img2

  然后,准备数据步骤将生成以下面和标签向量。

  FACES LABELS   person1_img1_face 1   person1_img2_face 1   person2_img1_face 2   person2_img2_face 2

  准备数据步骤可以进一步分为以下子步骤。

  1、阅读培训数据文件夹中提供的所有主题/人员的文件夹名称。 例如,在本教程中,我们有文件夹名称:s1,s2。

  2、对于每个主题,提取标签号码。 你还记得我们的文件夹有一个特殊的命名约定吗? 文件夹名称遵循格式sLabel,其中Label是一个整数,代表我们已分配给该主题的标签。 因此,例如,文件夹名称s1表示主题具有标签1,s2表示主题标签为2等。 将在此步骤中提取的标签分配给在下一步中检测到的每个面部。

  3、阅读主题的所有图像,从每张图像中检测脸部。

  4、将添加到标签矢量中的具有相应主题标签(在上述步骤中提取)的每个脸部添加到脸部矢量。

#使用OpenCV用来检测脸部的函数 def detect_face(img): #将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #加载OpenCV人脸检测器,我正在使用的是快速的LBP #还有一个更准确但缓慢的Haar分类器 face_cascade = cv2.CascadeClassifier('opencv-files/lbpcascade_frontalface.xml') #让我们检测多尺度(一些图像可能比其他图像更接近相机)图像 #结果是一张脸的列表 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5); #如果未检测到面部,则返回原始图像 if (len(faces) == 0): return None, None #假设只有一张脸, #提取面部区域 (x, y, w, h) = faces[0] #只返回图像的正面部分 return gray[y:y+w, x:x+h], faces[0]

  我正在使用OpenCV的LBP人脸检测器。 在第4行,我将图像转换为灰度,因为OpenCV中的大多数操作都是以灰度进行的,然后在第8行使用cv2.CascadeClassifier类加载LBP人脸检测器。 在第12行之后,我使用cv2.CascadeClassifier类'detectMultiScale方法来检测图像中的所有面部。 在第20行中,从检测到的脸部我只挑选第一张脸部,因为在一张图像中只有一张脸部(假设只有一张醒目的脸部)。 由于detectMultiScale方法返回的面实际上是矩形(x,y,宽度,高度),而不是实际的面部图像,所以我们必须从主图像中提取面部图像区域。 所以在第23行我从灰色图像中提取人脸区域并返回人脸图像区域和人脸矩形。

  现在您已经有了一个面部检测器,您知道准备数据的4个步骤,那么您准备好编写准备数据步骤了吗?是吗?让我们来做它。

#该功能将读取所有人的训练图像,从每个图像检测人脸 #并将返回两个完全相同大小的列表,一个列表 # 每张脸的脸部和另一列标签 def prepare_training_data(data_folder_path): #------STEP-1-------- #获取数据文件夹中的目录(每个主题的一个目录) dirs = os.listdir(data_folder_path) #列表来保存所有主题的面孔 faces = [] #列表以保存所有主题的标签 labels = [] #让我们浏览每个目录并阅读其中的图像 for dir_name in dirs: #我们的主题目录以字母's'开头 #如果有的话,忽略任何不相关的目录 if not dir_name.startswith("s"): continue; #------STEP-2-------- #从dir_name中提取主题的标签号 #目录名称格式= slabel #,所以从dir_name中删除字母''会给我们标签 label = int(dir_name.replace("s", "")) #建立包含当前主题主题图像的目录路径 #sample subject_dir_path = "training-data/s1" subject_dir_path = data_folder_path + "/" + dir_name #获取给定主题目录内的图像名称 subject_images_names = os.listdir(subject_dir_path) #------STEP-3-------- #浏览每个图片的名称,阅读图片, #检测脸部并将脸部添加到脸部列表 for image_name in subject_images_names: #忽略.DS_Store之类的系统文件 if image_name.startswith("."): continue; #建立图像路径 #sample image path = training-data/s1/1.pgm image_path = subject_dir_path + "/" + image_name #阅读图像 image = cv2.imread(image_path) #显示图像窗口以显示图像 cv2.imshow("Training on image...", image) cv2.waitKey(100) #侦测脸部 face, rect = detect_face(image) #------STEP-4-------- #为了本教程的目的 #我们将忽略未检测到的脸部 if face is not None: #将脸添加到脸部列表 faces.append(face) #为这张脸添加标签 labels.append(label) cv2.destroyAllWindows() cv2.waitKey(1) cv2.destroyAllWindows() return faces, labels

我已经定义了一个函数,它将存储培训主题文件夹的路径作为参数。 该功能遵循上述的4个准备数据子步骤。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2b40b8935044a95fe850af38d3b55ef9.html