随笔 - 633,  文章 - 0,  评论 - 13,  阅读 - 48万
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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)
复制代码

 

posted on   大话人生  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2020-04-28 Vue -路由(Vue -Router)
2020-04-28 Vue常用的UI组件-Elment(PC端Vue组件库)(饿了么组件)(推荐)
2020-04-28 Vue常用的UI组件-ant-design-vue
2020-04-28 Vue常用的UI组件-Mint UI(移动端Vue组件库)(饿了么组件)
2020-04-28 Vue常用的UI组件-vant(轻量、可靠的移动端Vue组件库)(推荐)
点击右上角即可分享
微信分享提示