opencv-人脸识别

 对https://blog.csdn.net/weixin_46291251/article/details/117996591这哥们代码的一些修改

import cv2
import numpy as np
import os
import shutil
import threading
import tkinter as tk
from PIL import Image, ImageTk

choice = 0

# 首先读取config文件,第一行代表当前已经储存的人名个数,接下来每一行是(id,name)标签和对应的人名
id_dict = {}  # 字典里存的是id——name键值对
Total_face_num = 999  # 已经被识别有用户名的人脸个数,

camera = cv2.VideoCapture(0)  # 摄像头
success, img = camera.read()  # 从摄像头读取照片
W_size = 0.1 * camera.get(3)
H_size = 0.1 * camera.get(4)



def init():  # 将config文件内的信息读入到字典中
    f = open('config.txt')
    global Total_face_num
    Total_face_num = int(f.readline())

    for i in range(int(Total_face_num)):
        line = f.readline()
        id_name = line.split(' ')
        id_dict[int(id_name[0])] = id_name[1]
    f.close()


init()

# 加载OpenCV人脸检测分类器Haar
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

# 准备好识别方法LBPH方法
recognizer = cv2.face.LBPHFaceRecognizer_create()

# 打开标号为0的摄像头
# camera = cv2.VideoCapture(0)  # 摄像头
# success, img = camera.read()  # 从摄像头读取照片
# W_size = 0.1 * camera.get(3)
# H_size = 0.1 * camera.get(4)

system_state_lock = 0  # 标志系统状态的量 0表示无子线程在运行 1表示正在刷脸 2表示正在录入新面孔。
# 相当于mutex锁,用于线程同步


'''
============================================================================================
以上是初始化
============================================================================================
'''


def Get_new_face():
    global choice
    print("正在从摄像头录入新人脸信息 \n")


    # 存在目录data就清空,不存在就创建,确保最后存在空的data目录
    filepath = "data"
    if not os.path.exists(filepath):
        os.mkdir(filepath)
    else:
        shutil.rmtree(filepath)
        os.mkdir(filepath)

    sample_num = 0  # 已经获得的样本数

    while True:  # 从摄像头读取图片
        choice = 2
        global success
        global img  # 因为要显示在可视化的控件内,所以要用全局的
        success, img = camera.read()

        # 转为灰度图片
        if success is True:
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        else:
            break

        # 检测人脸,将每一帧摄像头记录的数据带入OpenCv中,让Classifier判断人脸
        # 其中gray为要检测的灰度图像,1.3为每次图像尺寸减小的比例,5为minNeighbors
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)

        # 框选人脸,for循环保证一个能检测的实时动态视频流
        for (x, y, w, h) in faces:
            # xy为左上角的坐标,w为宽,h为高,用rectangle为人脸标记画框
            cv2.rectangle(img, (x, y), (x + w, y + w), (255, 0, 0))
            # 样本数加1
            sample_num += 1
            # 保存图像,把灰度图片看成二维数组来检测人脸区域,这里是保存在data缓冲文件夹内
            T = Total_face_num
            cv2.imwrite("./data/User." + str(T) + '.' + str(sample_num) + '.jpg', gray[y:y + h, x:x + w])

        pictur_num = 1000  # 表示摄像头拍摄取样的数量,越多效果越好,但获取以及训练的越慢

        cv2.waitKey(1)
        if sample_num > pictur_num:
            break
        else:  # 控制台内输出进度条
            l = int(sample_num / pictur_num * 50)
            r = int((pictur_num - sample_num) / pictur_num * 50)
            print("\r" + "%{:.1f}".format(sample_num / pictur_num * 100) + "=" * l + "->" + "_" * r, end="")
            var.set("%{:.1f}".format(sample_num / pictur_num * 100))  # 控件可视化进度信息
            # tk.Tk().update()
            window.update()  # 刷新控件以实时显示进度


def Train_new_face():


    print("\n正在训练")
    # cv2.destroyAllWindows()
    path = 'data'

    # 初始化识别的方法
    recog = recognizer

    # 调用函数并将数据喂给识别器训练
    faces, ids = get_images_and_labels(path)
    print('本次用于训练的识别码为:')  # 调试信息
    print(ids)  # 输出识别码

    # 训练模型  #将输入的所有图片转成四维数组
    recog.train(faces, np.array(ids))
    # 保存模型

    yml = str(Total_face_num) + ".yml"
    rec_f = open(yml, "w+")
    recog.save(yml)
    rec_f.close()
    # recog.save('aaa.yml')


# 创建一个函数,用于从数据集文件夹中获取训练图片,并获取id
# 注意图片的命名格式为User.id.sampleNum
def get_images_and_labels(path):
    image_paths = [os.path.join(path, f) for f in os.listdir(path)]
    # 新建连个list用于存放
    face_samples = []
    ids = []

    # 遍历图片路径,导入图片和id添加到list中
    for image_path in image_paths:

        # 通过图片路径将其转换为灰度图片
        img = Image.open(image_path).convert('L')

        # 将图片转化为数组
        img_np = np.array(img, 'uint8')

        if os.path.split(image_path)[-1].split(".")[-1] != 'jpg':
            continue

        # 为了获取id,将图片和路径分裂并获取
        id = int(os.path.split(image_path)[-1].split(".")[1])

        # 调用熟悉的人脸分类器
        detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

        faces = detector.detectMultiScale(img_np)

        # 将获取的图片和id添加到list中
        for (x, y, w, h) in faces:
            face_samples.append(img_np[y:y + h, x:x + w])
            ids.append(id)
    return face_samples, ids


def write_config():
    global user_name
    print("新人脸训练结束")
    f = open('config.txt', "a")
    T = Total_face_num
    f.write(str(T) + " "+ user_name + " \n")
    f.close()
    id_dict[T] = user_name

    # 这里修改文件的方式是先读入内存,然后修改内存中的数据,最后写回文件
    f = open('config.txt', 'r+')
    flist = f.readlines()
    flist[0] = str(int(flist[0]) + 1) + " \n"
    f.close()

    f = open('config.txt', 'w+')
    f.writelines(flist)
    f.close()


'''
============================================================================================
以上是录入新人脸信息功能的实现
============================================================================================
'''


def scan_face():
    # 使用之前训练好的模型
    for i in range(Total_face_num):  # 每个识别器都要用
        i += 1
        yml = str(i) + ".yml"
        print("\n本次:" + yml)  # 调试信息
        recognizer.read(yml)

        ave_poss = 0
        global choice
        for times in range(10):  # 每个识别器扫描十遍
            times += 1
            cur_poss = 0
            global success
            global img

            global system_state_lock
            while system_state_lock == 2:  # 如果正在录入新面孔就阻塞
                print("\r刷脸被录入面容阻塞", end="")
                pass
            choice = 1
            success, img = camera.read()
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            # 识别人脸
            faces = face_cascade.detectMultiScale(
                gray,
                scaleFactor=1.2,
                minNeighbors=5,
                minSize=(int(W_size), int(H_size))
            )
            # 进行校验
            for (x, y, w, h) in faces:

                # global system_state_lock
                while system_state_lock == 2:  # 如果正在录入新面孔就阻塞
                    print("\r刷脸被录入面容阻塞", end="")
                    pass
                # 这里调用Cv2中的rectangle函数 在人脸周围画一个矩形
                cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
                # 调用分类器的预测函数,接收返回值标签和置信度
                idnum, confidence = recognizer.predict(gray[y:y + h, x:x + w])
                conf = confidence


                # 加载一个字体用于输出识别对象的信息
                font = cv2.FONT_HERSHEY_SIMPLEX

                # 输出检验结果以及用户名

                # 展示结果
                # cv2.imshow('camera', img)

                print("conf=" + str(conf), end="\t")
                if 65 > conf > 0:
                    cur_poss = 1  # 表示可以识别
                else:
                    cur_poss = 0  # 表示不可以识别

            k = cv2.waitKey(1)
            if k == 27:
                # cam.release()  # 释放资源
                cv2.destroyAllWindows()
                break

            ave_poss += cur_poss

        if ave_poss >= 5:  # 有一半以上识别说明可行则返回
            return i

    return 0  # 全部过一遍还没识别出说明无法识别


'''
============================================================================================
以上是关于刷脸功能的设计
============================================================================================
'''


def f_scan_face_thread():
    global choice
    # 使用之前训练好的模型
    # recognizer.read('aaa.yml')
    var.set('刷脸')
    ans = scan_face()
    if ans == 0:
        print("最终结果:无法识别")
        var.set("最终结果:无法识别")

    else:
        ans_name = "最终结果:" + str(ans) + id_dict[ans]
        print(ans_name)
        var.set(ans_name)

    global system_state_lock
    print("锁被释放0")
    system_state_lock = 0  # 修改system_state_lock,释放资源
    choice = 0


def f_scan_face():
    print(choice)
    global system_state_lock
    print("\n当前锁的值为:" + str(system_state_lock))
    if system_state_lock == 1:
        print("阻塞,因为正在刷脸")
        return 0
    elif system_state_lock == 2:  # 如果正在录入新面孔就阻塞
        print("\n刷脸被录入面容阻塞\n"
              "")
        return 0
    system_state_lock = 1
    p = threading.Thread(target=f_scan_face_thread)
    p.setDaemon(True)  # 把线程P设置为守护线程 若主线程退出 P也跟着退出
    p.start()


def f_rec_face_thread():
    global choice
    var.set('录入')
    cv2.destroyAllWindows()
    global Total_face_num
    Total_face_num += 1
    Get_new_face()  # 采集新人脸
    print("采集完毕,开始训练")
    global system_state_lock  # 采集完就可以解开锁
    print("锁被释放0")
    system_state_lock = 0
    choice = 0
    Train_new_face()  # 训练采集到的新人脸
    write_config()  # 修改配置文件

#    recognizer.read('aaa.yml')  # 读取新识别器

# global system_state_lock
# print("锁被释放0")
# system_state_lock = 0  # 修改system_state_lock,释放资源


def f_rec_face():
    global user_name
    global choice
    global system_state_lock
    print("当前锁的值为:" + str(system_state_lock))
    user_name = var_user_name.get()
    if system_state_lock == 2:
        print("阻塞,因为正在录入面容")
        return 0
    else:
        system_state_lock = 2  # 修改system_state_lock
        print("改为2", end="")
        print("当前锁的值为:" + str(system_state_lock))

    p = threading.Thread(target=f_rec_face_thread)
    p.setDaemon(True)  # 把线程P设置为守护线程 若主线程退出 P也跟着退出
    p.start()
    # tk.Tk().update()


#  system_state_lock = 0  # 修改system_state_lock,释放资源


def f_exit():  # 退出按钮
    exit()


'''
============================================================================================
以上是关于多线程的设计
============================================================================================
'''

window = tk.Tk()
window.title('wjh lxq\' Face_rec 3.0')   # 窗口标题
window.geometry('1000x500')  # 这里的乘是小x

# 在图形界面上设定标签,类似于一个提示窗口的作用
var = tk.StringVar()
l = tk.Label(window, textvariable=var, bg='green', fg='white', font=('Arial', 12), width=50, height=4)
# 说明: bg为背景,fg为字体颜色,font为字体,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
l.pack()  # 放置l控件
var.set("wjh  lxq 人脸识别系统")

# 在窗口界面设置放置Button按键并绑定处理函数
button_a = tk.Button(window, text='开始刷脸', font=('Arial', 12), width=10, height=2, command=f_scan_face)
button_a.place(x=800, y=120)

button_b = tk.Button(window, text='录入人脸', font=('Arial', 12), width=10, height=2, command=f_rec_face)
button_b.place(x=800, y=220)

button_c = tk.Button(window, text='退出', font=('Arial', 12), width=10, height=2, command=f_exit)
button_c.place(x=800, y=320)

panel = tk.Label(window, width=500, height=350)  # 摄像头模块大小
panel.place(x=10, y=100)  # 摄像头模块的位置
window.config(cursor="arrow")

tk.Label(window, text='name: ').place(x=600, y=235)
var_user_name = tk.StringVar()
entry_user_name = tk.Entry(window, textvariable=var_user_name)
entry_user_name.place(x=650, y=235)


def video_loop():  # 用于在label内动态展示摄像头内容(摄像头嵌入控件)
    global success
    global img
    global choice
    if not choice:
        success, img = camera.read()
    if success:
        cv2.waitKey(1)
        cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)  # 转换颜色从BGR到RGBA
        current_image = Image.fromarray(cv2image)  # 将图像转换成Image对象
        imgtk = ImageTk.PhotoImage(image=current_image)
        panel.imgtk = imgtk
        panel.config(image=imgtk)
        window.after(1, video_loop)


video_loop()

#  窗口循环,用于显示
window.mainloop()

'''
============================================================================================
以上是关于界面的设计
============================================================================================
'''

自备config.txt和haarcascade_frontalface_default.xml文件

config.txt 第一行写一个0即可

录脸的时候输入name.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/100414.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

postman-使用Postman的模拟服务来模拟(mock)后端数据,完成前端模拟API调用

最近项目上比较忙,任务多时间紧,导致后端开发任务繁多,无法及时开发完毕,但是前端同学已经把对应功能开发完成,需要进行前后端联调来验证API及一些交互问题;这不能因为后端的进度来影响前端的工作完成情况&…

python爬虫-Selenium

一、Selenium简介 Selenium是一个用于Web应用程序测试的工具,Selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。模拟浏览器功能,自动执行网页中的js代码,实现动态加载。 二、环境配置 1、查看本机电脑谷歌浏览器的版…

【设备树笔记整理7】实践操作

1 使用设备树给DM9000网卡_触摸屏指定中断 1.1 修改方法 根据设备节点的compatible属性,在驱动程序中构造/注册 platform_driver,在 platform_driver 的 probe 函数中获得中断资源。 1.2 实验方法 以下是修改好的代码:第6课第1节_网卡_触摸…

PyTorch深度学习遥感影像地物分类与目标检测、分割及遥感影像问题深度学习优化实践技术应用

我国高分辨率对地观测系统重大专项已全面启动,高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成,将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB,遥感大数据时…

WEBGL(3):鼠标动态绘制点

1 实现思路 绘制单个点鼠标事件监听点击事件将点推送到数组中绘制数组中所有点 2 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge&…

应届生面试指南:如何在缺乏经验的情况下脱颖而出

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

运用Python解析HTML页面获取资料

目录 安装Beautiful Soup库&#xff1a; 解析HTML页面&#xff1a; 怎么获取图片、视频、音频资源 1. 图片资源&#xff1a; 2. 视频资源&#xff1a; 3. 音频资源&#xff1a; 可能遇到的问题 1. 编码问题&#xff1a; 2. 动态内容&#xff1a; 3. 反爬虫机制&#…

关于在香橙派安装mysql时遇到的坑

前言 基础环境&#xff1a;硬件&#xff1a;香橙派5操作系统&#xff1a;openkylincpu架构&#xff1a;arm 过程&#xff1a;最近有个任务&#xff0c;要在新的环境中验证一些服务是否可用。目的时向全国产化靠拢。 需要在香橙派上安装openkylin&#xff0c;一开始尝试的是香橙…

用于设计和分析具有恒定近心点半径的低推力螺旋轨迹研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Oracle报错 PLS-00103: 出现符号 ““在需要下列之一时

在IDEA中执行以下SQL时&#xff0c;报了这个异常 检查了语法&#xff0c;你会发现语法没有任何问题&#xff0c;标点也没有任何问题。 罪魁祸首在这&#xff1a; 换行符为CRLF&#xff0c;我们需要改成LF 即可执行成功

B080-RabbitMQ

目录 RabbitMQ认识概念使用场景优点AMQP协议JMS RabbitMQ安装安装elang安装RabbitMQ安装管理插件登录RabbitMQ消息队列的工作流程 RabbitMQ常用模型HelloWorld-基本消息模型生产者发送消息导包获取链接工具类消息的生产者 消费者消费消息模拟消费者手动签收消息 Work QueuesSen…

控制goroutine 的并发执行数量

goroutine的数量上限是1048575吗&#xff1f; 正常项目&#xff0c;协程数量超过十万就需要引起重视。如果有上百万goroutine&#xff0c;一般是有问题的。 但并不是说协程数量的上限是100多w 1048575的来自类似如下的demo代码: package mainimport ( "fmt" "ma…

机械臂+2d相机实现复合机器人定位抓取

硬件参数 机械臂&#xff1a;艾利特 相机&#xff1a;海康相机 2d识别库&#xff1a;lindmod&#xff0c;github可以搜到 光源&#xff1a;磐鑫光源 软件参数 系统&#xff1a;windows / Linux 开发平台&#xff1a;Qt 开发语言&#xff1a;C 开发视觉库&#xff1a;OpenCV …

【算法系列篇】位运算

文章目录 前言什么是位运算算法1.判断字符是否唯一1.1 题目要求1.2 做题思路1.3 Java代码实现 2. 丢失的数字2.1 题目要求2.2 做题思路2.3 Java代码实现 3. 两数之和3.1 题目要求3.2 做题思路3.3 Java代码实现 4. 只出现一次的数字4.1 题目要求4.2 做题思路4.3 Java代码实现 5.…

【若依框架RuoYi-Vue-Plus 图片回显不显示问题,OSS文件上传或者本地上传】

一、问题 1.设计表 product&#xff08;商品表&#xff09; 有 id &#xff08;id&#xff09; name&#xff08;商品名&#xff09;icon&#xff08;图标&#xff09; 2.使用若依代码生成功能&#xff0c;导入product表&#xff0c;代码生成。 3.将生成的代码导入到项目中得到…

3D点云处理:提取指定圆环内的点(附源码)

文章目录 0. 测试效果1. 基本内容2. 代码实现文章目录:3D视觉个人学习目录微信:dhlddxB站: Non-Stop_目标:提取指定范围的点云0. 测试效果 红色为根据指定条件提取的点 1. 基本内容 要提取指定圆环内和指定高度范围内的点云,可以按照以下步骤进行操作: 定义圆环和高度参数…

ArcGIS地块面积分割调整工具插件

地块分割调整工具可以实现将选定的图斑按照面积比例或者指定的面积&#xff0c;分割成多个图斑。 各个图斑的面积用逗号分隔&#xff0c;比例分割设置时&#xff0c;用整数表示。 面积分割时&#xff0c;最后一个图斑的面积可以不写&#xff0c;插件可以自动计算图斑的面积&a…

基于Springboot实现的Echarts图表

概述 ECharts是百度开源的一个前端组件。它是一个使用 JavaScript 实现的开源可视化库&#xff0c;可以流畅的运行在 PC 和移动设备上&#xff0c;兼容当前绝大部分浏览器&#xff08;IE8/9/10/11&#xff0c;Chrome&#xff0c;Firefox&#xff0c;Safari等&#xff09;&…

yolov8机器视觉-工业质检

使用训练好的模型进行预测 yolo predict taskdetect model训练好的模型路径 source测试图片文件夹路径 showTrue效果展示 切换模型进行训练&#xff08;yolov8s&#xff09; 修改main.py训练参数文件 使用云gpu进行训练&#xff0c;很方便&#xff1a;点击链接转至在线云gpu…

Javase | IO流

目录&#xff1a; 1.输入 (Intput/Read)2.输出 (Output/Write)3.IO4.IO流5.IO流的分类&#xff1a;5.1 分类总述5.2 按照 “流的方向” 进行分类5.3 按照 “读取数据的方式” 进行分类 6.IO包下要重点掌握的流&#xff1a;6.1 文件专属 (流)6.2 转换流 ( 将字节流转换为字符流 …
最新文章