• 人脸训练


    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,23...命名
        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)
  • 相关阅读:
    sublime text 安装json插件
    通过坐标系求覆盖物面积
    关于大数据入门的相关闲聊
    渡月橋 ~君 想ふ~
    数据库快照
    oracle 11g安装与使用
    IaaS、PaaS、SaaS介绍(非原创)
    Android项目模块化/组件化开发(非原创)
    开发人员必备的网络知识(非原创)
    公司常见管理系统介绍(非原创)
  • 原文地址:https://www.cnblogs.com/jingzaixin/p/16204617.html
Copyright © 2020-2023  润新知