保存已知命名图片 通过摄像头识别第一次发现与保存图片相似的人时,将其姓名记录到csv文件中 实现摄像头签到功能

#主要思路   读取文件夹中已知图片中人物的人脸特征,保存在人脸特征列表中,然后使用摄像头识别到的
#人 获取其人脸特征与保存的相比较 相识度误差不超过0.42 误差程序中可自行调整
#最好安装GPU版本dlib 识别画面会流畅很多 CPU版本画面比较缓慢

import os

# import dlib
import cv2
import numpy as np
import face_recognition
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
import codecs
import re

import win32gui

#参数是默认参数 可自行修改
#这里实现窗口显示中文汉字  不是乱码
def zh_ch_Titile(oldTitle,newTitle='中文',oneRun=False):
    if oneRun == False:
        handle = win32gui.FindWindow(0, oldTitle)
        win32gui.SetWindowText(handle, newTitle)
        oneRun= True
    return oneRun
#该函数实现读取中文路径的图片
def imread2(imagePathName):  # 读取中文路径图片
    retImg = cv2.imdecode(np.fromfile(imagePathName, dtype=np.uint8), -1)
    return retImg
#该函数实现显示中文不会成乱码
def putText2(img,text,pos,size=36,color=(255,0,0)):

    img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    font = ImageFont.truetype(font=r'simsun.ttc', size=size)
    draw = ImageDraw.Draw(img_pil)
    draw.text(pos, text, font=font, fill=color)  # PIL中RGB=(255,0,0)表示红色
    img_cv = np.array(img_pil)                         # PIL图片转换为numpy
    img = cv2.cvtColor(img_cv, cv2.COLOR_RGB2BGR)      # PIL格式转换为OpenCV的BGR格式
    return img

#此处为了实现同一个人使用多张图片仍然正常识别
#比如为了识别张三 我们使用多张不同环境的图片或者不同光照条件的图片 为了提高正确的识别率
#命名为   张三.jpg  张三01.jpg  014张三.jpg 该程序都使用正则表达式忽略文件名中前后的数字
#保证程序识别率高  第一次到达的时间保存在csv文件中
path="images"
pattern = re.compile(r'(\d)*(\D+)(\d)*.*')   # 查找文件名 排除数字

# fileExist=os.path.isfile('a.csv')
# if not fileExist:
with codecs.open("最早到来时间.csv", 'w',encoding='utf-8') as f:
        f.write("姓名,时间")
#内存保存图片对象
images=[]
#保存图片名字,不包含扩展名,进行分类
classNames=[]

templateImageList=os.listdir(path)
print(templateImageList)

for currentImage in templateImageList:

    if os.path.splitext(currentImage)[1].lower() in [".jpg",".png",".jpeg"]:
        img=imread2(f"{path}/{currentImage}")
        images.append(img)
        print("加载图片", os.path.splitext(currentImage)[0])
        classNames.append(os.path.splitext(currentImage)[0])
print("所有图片",classNames)

#传入内存图片对象 读取特征保存到列表中
def findEncodings(imagesInMemory):

    n=len(imagesInMemory)
    encodeList=[]
    i=0
    for img in imagesInMemory:

        i=i+1
        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
        face_locations = face_recognition.face_locations(img)
        if len(face_locations) != 1:
            print("不是有效的图片")
            continue

        encode=face_recognition.face_encodings(img)[0]

        encodeList.append(encode)
        jdu=round(i/n,2)*100
        print(f"读取特征完成  {jdu}%")
    return encodeList
def markAttence(name):
    with codecs.open('最早到来时间.csv','r+',encoding='utf-8') as f:
        myDataList=f.readlines()
        nameList=[]
        for line in myDataList:
            entry=line.split(',')
            excludeNumberName = pattern.match(entry[0])
            if excludeNumberName:
               nameList.append(excludeNumberName.group(2))
        excludeNumberName = pattern.match(name)
        if excludeNumberName.group(2) not in nameList:
            now=datetime.now()
            dtString=now.strftime("%Y-%m-%d %H:%M:%S")
            if excludeNumberName:
                    name1 =excludeNumberName.group(2).strip()
                    f.writelines(f"{os.linesep}{name1},{dtString}")
                    print("第一次发现" + name1 + "已到达")
        # print(myDataList)

# markAttence('a')
encodingsSaved=findEncodings(images)
print("图片特征加载完毕")
cv2.namedWindow("img",cv2.WINDOW_NORMAL)
ima=cv2.imread("jz.png")
cv2.imshow("img",ima)
changeName=False
cap=cv2.VideoCapture(0)

while True:
    success,img=cap.read()
    imgResize=cv2.resize(img,(0,0),None,0.25,0.25)
    imgResize=cv2.cvtColor(imgResize,cv2.COLOR_BGR2RGB)

    faceCurrentFrame=face_recognition.face_locations(imgResize)
    encodeCrentFrame=face_recognition.face_encodings(imgResize,faceCurrentFrame)

    for encodeFace,faceLoc in zip(encodeCrentFrame,faceCurrentFrame):
        matches=face_recognition.compare_faces(encodingsSaved,encodeFace)
        faceDis=face_recognition.face_distance(encodingsSaved,encodeFace)
        # print(faceDis)
        matchesIndex=np.argmin(faceDis)

        #找到最匹配的特征 并且误差不超过0.42
        if matches[matchesIndex] and faceDis[matchesIndex]<0.42:
            name=classNames[matchesIndex].upper()
            # print(faceDis[matchesIndex],name)
            y1,x2,y2,x1=faceLoc
            y1, x2, y2, x1 = y1*4, x2*4, y2*4, x1*4
            cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),3)
            faceDis[matchesIndex]=round(faceDis[matchesIndex],2)
            # cv2.putText(img,name+" "+str(faceDis[matchesIndex]),(x1,y1-10),cv2.FONT_HERSHEY_TRIPLEX,1,(0,255,0),1)
            excludeNumberName = pattern.match(name)
            if excludeNumberName:
               img=putText2(img,excludeNumberName.group(2)+" "+str(faceDis[matchesIndex]),(x1,y1-25),25,(0,255,0))
            markAttence(name)


    cv2.imshow("img",img)
    k=cv2.waitKey(1)
    if k & 0xFF==ord('q'):
        break
    if changeName == False:
        changeName = zh_ch_Titile('img', "记录最早到来时间", changeName)


#新增修改上面部分代码,达到对无效图片进行验证 保证无效图片不会被读入

保存已知命名图片 通过摄像头识别第一次发现与保存图片相似的人时,将其姓名记录到csv文件中 实现摄像头签到功能_第1张图片

你可能感兴趣的:(opencv,计算机视觉,人工智能,python)