renlianxunlian.py
#导入cv模块 import os import cv2 # from PIL import Image, ImageFont, ImageDraw import numpy as np import re import shutil #自动识别图片并进行分类 class autoRecognizeAndClassifyPic(object): def __init__(self,classifier_xml,): self.classifier_xml = classifier_xml #分类器xml文件 #加载分类器 def load_classifier(self): face_detect = cv2.CascadeClassifier(self.classifier_xml) return face_detect #获取人脸特征 def get_face_features(self,pic_gary): face_detect = self.load_classifier() # 打印灰度图像 # 第一个参数图片, # 第二个参数是每次 遍历图像缩放的倍数 # 第三个参数是检测5遍之后这个地方都有这个人脸才能确定出来 # 第四个参数就写默认0就行,是一个老函数相关的内容,不用管 # minsize,maxSize:意思就是在这个图片中人脸最小有多小,最大有多大,用来限制一个范围 # (100,100),(300,300),表示低于100,100的像素框中没有人脸,大于300,300的像素框中没有人脸 # faces = face_detect.detectMultiScale(pic_gary, 1.1, 5, 0, (100, 100), (300, 300)) faces = face_detect.detectMultiScale(pic_gary) return faces #获取当前文件的目录路径 def get_current_path(self): #获取当前文件目录 current_path = os.path.abspath(os.path.dirname(__file__)) print("current_path:") print(current_path) return current_path #创建根目录 def createdir(self, filedir,sp_fu = "\\"): filelist = filedir.split(sp_fu) # print(filelist) long = len(filelist) # print(long) zuhefiledir = filelist[0] for i in range(1, long): zuhefiledir = zuhefiledir + sp_fu + filelist[i] if os.path.exists(zuhefiledir): print("已经存在目录:%s" % zuhefiledir) else: os.mkdir(zuhefiledir) print("已经创建目录:%s" % zuhefiledir) # 先根据一张已知的图片做一个训练器 # 这组图片为一个人的多张图片 # 这组图的文件夹名字为人名 # 这组图中多个图片的名字以数字1,2,3...命名 def getImageAndLables_one_people(self,one_m_pic_path): one_people_info_list = [] #one_m_pic_path :已经知道图片路径,即母图集的路径,用来作为识别其他图片的参照 path = one_m_pic_path # 存储人脸数据 fasesSamples = [] # 存储姓名数据 ids = [] #使用正则分隔用多个分隔符 #多个分隔符之间用竖线 | 分隔 reming_pre_list = re.split(pattern="/|\\\\",string=str(one_m_pic_path)) print("reming_pre_list") print(reming_pre_list) #遍历循环reming_pre_list列表,并抽取非空的值作为新数列 reming_new_list的值 reming_new_list = [i for i in reming_pre_list if i.strip() != ""] print("reming_new_list") print(reming_new_list) #获取新数列中最后一项作为人名 name = reming_new_list[-1] print("name:") print(name) one_people_info_list.append(name) # 存储照片信息 imagePaths = [os.path.join(path, f) for f in os.listdir(path)] # 遍历列表中的图片 for imagePath in imagePaths: print("imagePath:") print(imagePath) # 打开图片,灰度化,PIL有九种不同模式:1-黑白照,L-灰度图(将图片划分为0到255个不同值,颜色越深,值越大),P,RGB.RGBA,CMYK,YCbCr,I,F # PIL_img = Image.open(imagePath).convert("L") # 读取图片 img = cv2.imread(imagePath) # 转为灰度 PIL_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图像转为数组,以黑白深浅 img_numpy = np.array(PIL_img, "uint8") # 图片每一个像素点变为数值,让计算机看得懂 print("img_numpy:") print(img_numpy) # 获取图片人脸特征 # faces = face_detector.detectMultiScale(img_numpy) faces = self.get_face_features(pic_gary=PIL_img) # 获取每张图片的id和姓名 print(os.path.split(imagePath)[1]) print(os.path.split(imagePath)[1].split('.')[0]) id = int(os.path.split(imagePath)[1].split('.')[0]) # 图片名字一定是一个数字类型的字符,否则会报错 # 预防无面容照片 for x, y, w, h in faces: ids.append(id) fasesSamples.append(img_numpy[y:y + h, x:x + w]) print("识别完图片%s"%imagePath) # 打印脸部特征 print("ids:", ids) one_people_info_list.append(ids) print("fs:", fasesSamples) one_people_info_list.append(fasesSamples) # 加载识别器 recognizer = cv2.face.LBPHFaceRecognizer_create() print("recognizer:") print(recognizer) # 训练 recognizer.train(fasesSamples, np.array(ids)) #获取当前文件目录 current_path = self.get_current_path() trainer_path = current_path+"\\trainer" print("trainer_path:") print(trainer_path) self.createdir(filedir=trainer_path,sp_fu="\\") train_file_name = "%s\\%s_trainer.yml" % (trainer_path,name) # 保存文件 recognizer.write(train_file_name) one_people_info_list.append(train_file_name) print("one_people_info_list:") print(one_people_info_list) return one_people_info_list #2.再根据这个训练器判断一张图片是不是有这张脸 #识别图片并将图片移动到分类文件夹中 # 准备识别的图片 #识别一张图片 def face_detect_one_img(self,one_img_path,one_trainer_yml,peopel_name): recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read(one_trainer_yml) # 读取图片 img = cv2.imread(one_img_path) # 转为灰度 pic_gary = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 加载分类器(加载面部分类器) # 获取面部特征 one_img_faces = self.get_face_features(pic_gary=pic_gary) print("%s图片的面部特征:" % one_img_path) print(one_img_faces) one_img_faces_len = len(one_img_faces) #一个图像上有几个框 print("one_img_faces_len:") print(one_img_faces_len) # # 将检测到的图像绘制一个框 # for i in range(0,one_img_faces_len): id_and_confidence_list = [] for x, y, w, h in one_img_faces: one_id_and_confidence_list = [] # 绘制矩形 # 第一个参数是画布或者图片,第二个参数是起点坐标和终点坐标 # color,颜色,使用RGB颜色, # thickness,矩形宽度,此处设置为1 cv2.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=2) # 绘制圆形 # 第一个参数是画布或者图片, # center,为圆心坐标 # radius,为半径 # color,颜色,使用RGB颜色, # thickness,矩形宽度,此处设置为1 cv2.circle(img, center=(x + w // 2, y + h // 2), radius=w // 2, color=(0, 255, 0), thickness=1) # # 显示 # cv2.imshow("result", img) # # 等待 # cv2.waitKey(0) # 等待按下按键 # 人脸识别 # 用同大小,或者接近大小去评分 pic_id, pic_confidence = recognizer.predict(pic_gary[y:y + h, x:x + h]) print("标签id:", pic_id, "置信评分:", pic_confidence) one_id_and_confidence_list.append(pic_id) one_id_and_confidence_list.append(pic_confidence) id_and_confidence_list.append(one_id_and_confidence_list) print("id_and_confidence_list:") print(id_and_confidence_list) #写入人名标签 for one_id_and_confidence in id_and_confidence_list: pic_id = one_id_and_confidence[0] pic_confidence = one_id_and_confidence[1] if pic_confidence > 80: for x, y, w, h in one_img_faces: cv_img = cv2.putText(img, "unknow", (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1) print("不能识别图片【%s】,标签id:%s,置信评分:%s" % (one_img_path,pic_id,pic_confidence)) else: for x, y, w, h in one_img_faces: cv_img=cv2.putText(img, peopel_name, (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 1) # 显示 # cv2.imshow("result", img) # 等待 cv2.waitKey(0) # 等待按下按键 cv2.imwrite(one_img_path,img) #保存图片 #获取所有置信评分 text_list = [] for one_id_and_confidence in id_and_confidence_list: pic_id = one_id_and_confidence[0] pic_confidence = one_id_and_confidence[1] text_one = "标签id:%s,置信评分:%s" % (pic_id, pic_confidence) text_list.append(text_one) global is_know_fage is_know_fage = False #设置识别标记为False for one_id_and_confidence in id_and_confidence_list: pic_id = one_id_and_confidence[0] pic_confidence = one_id_and_confidence[1] if pic_confidence <= 80: # 创建名字文件夹,并将图片移动到指定目录下 #创建分类文件夹 current_path = self.get_current_path() pics_classification_path = current_path + "//" + "pic_classify" #在分类文件下创建名字 peopel_pic_path = pics_classification_path + "//" + people_name #创建人名路径 self.createdir(filedir=peopel_pic_path, sp_fu="//") one_image_only_name = re.split(pattern="/|\\\\",string=str(one_img_path))[-1] print("one_image_only_name:") print(one_image_only_name) move_img_path = peopel_pic_path+"//"+one_image_only_name #将图片移动到当前目录 shutil.move(src=one_img_path, dst= move_img_path) cv2.imwrite(move_img_path, img) # 保存图片 #读取图片,并写入置信评分 self.wirte_text_to_pic_two_more_hang(text_list=text_list, pic_path=move_img_path) print("可以识别图片【%s】,标签id:%s,置信评分:%s" % (one_img_path, pic_id, pic_confidence)) is_know_fage = True break else: print("不能识别图片【%s】,标签id:%s,置信评分:%s" % (one_img_path,pic_id,pic_confidence)) continue print("is_know_fage:") print(is_know_fage) if not is_know_fage: #读取图片,并写入置信评分,但是需要把所有的评分都写上 self.wirte_text_to_pic_two_more_hang(text_list=text_list, pic_path=one_img_path) # 释放内存 cv2.destroyAllWindows() # 获取指定路径下所有指定后缀的文件 def get_all_file_path_list(self,file_dir,suffix='.jpg'): li = [] for root, dirs, files in os.walk(file_dir): print("files:") print(files) for file in files: if os.path.splitext(file)[1] == suffix: li.append(os.path.join(root, file)) print("li:") print(li) return li # 读取图片并写入文字 def wirte_text_to_pic_two(self,text, pic_path): print("text:") print(text) print("pic_path") print(pic_path) img1 = cv2.imread(pic_path, cv2.IMREAD_COLOR) pil_image = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)) w, h = pil_image.size font = ImageFont.truetype('simhei.ttf', 50, encoding="utf-8") color = (255, 10, 255) pos = (w / 8, h / 4 * 3) text = text draw = ImageDraw.Draw(pil_image) draw.text(pos, text, font=font, fill=color) cv_img = cv2.cvtColor(np.asarray(pil_image), cv2.COLOR_RGB2BGR) # cv2.imshow(pic_path, cv_img) # xianshi cv2.waitKey(0) cv2.imwrite(pic_path, cv_img) # 保存图片 # 读取图片并写入文字,写入多行 def wirte_text_to_pic_two_more_hang(self,text_list, pic_path): print("text_list:") print(text_list) print("pic_path") print(pic_path) img1 = cv2.imread(pic_path, cv2.IMREAD_COLOR) pil_image = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)) w, h = pil_image.size font = ImageFont.truetype('simhei.ttf', 50, encoding="utf-8") color = (255, 10, 255) text_list_len = len(text_list) for i in range(0,text_list_len): pos = (w / 8 , h / (text_list_len+1) *(i+1)) text = text_list[i] draw = ImageDraw.Draw(pil_image) draw.text(pos, text, font=font, fill=color) cv_img = cv2.cvtColor(np.asarray(pil_image), cv2.COLOR_RGB2BGR) # cv2.imshow(pic_path, cv_img) # xianshi cv2.waitKey(0) cv2.imwrite(pic_path, cv_img) # 保存图片 if __name__ == '__main__': classifier_xml = "D:/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml" arac = autoRecognizeAndClassifyPic(classifier_xml=classifier_xml) one_m_pic_path = "D:\\PycharmProjects\\cigenpic\\mother_pic\\wangxinyi" one_people_info_list = arac.getImageAndLables_one_people(one_m_pic_path=one_m_pic_path) file_dir = r"D:\PycharmProjects\cigenpic\shipic" all_img_picture_list = arac.get_all_file_path_list(file_dir=file_dir, suffix='.jpg') for one_img_path in all_img_picture_list: one_trainer_yml = one_people_info_list[3] people_name = one_people_info_list[0] arac.face_detect_one_img(one_img_path,one_trainer_yml,peopel_name=people_name)