基于OpenCV-Python实现人脸识别-----摄像头捕获人脸图像显示中文乱码问题

基于OpenCV-Python实现人脸识别时,为了使图像上显示识别到人员的中文名字,做了几次尝试,使用PIL.Image和OpenCV图像格式相互转换解决:

使用OpenCV将图片灰度化,对加载的灰度化图使用分类器中的detectMultiScale()函数查找目标人脸,并使用for循环实现矩形框和圆形框框住查找到的人脸。再使用OpenCV中识别器face.LBPHFaceRecognizer()方法得到预测结果ids和置信度confidence

--------此时图像是OpenCV格式

# 加载训练数据集文件--加载识别器LBRHFaceRegnizer_create()
recogizer=cv2.face.LBPHFaceRecognizer_create() # 需要安装pip install opencv_contrib-python

def face_detect_demo(img):
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 图片灰度化---cv2.cvtColor()
    # 加载分类器--进行检测
    face_detector=cv2.CascadeClassifier('F:/Program Files/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
    # face=face_detector.detectMultiScale(gray,1.1,5,cv2.CASCADE_SCALE_IMAGE,(100,100),(300,300))
    face=face_detector.detectMultiScale(gray) # 使用默认参数
    # face=face_datector.deteMultiScale(gray)  # 默认
    for x,y,w,h in face: # 将整张人脸框住(矩形框+圆形框)
        cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2) # 绘制矩形框住识别的人脸
        cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1) # 绘制圆框住识别的人脸
        # 人脸识别--预测和评分--recogizer.predict()输入参数是一个人脸图像,输出结果一个元组,包括预测结果ids和置信度confidence---取gray中矩形框住的部分
        ids,confidence=recogizer.predict(gray[y:y+h,x:x+w]) # 调用识别器cv2.face.LBPHFaceRecognizer中的predict()方法

--------使用PIL将OpenCV图像转成PIL.Image图像格式

# ------将OpenCV图像转成PIL图像:使用PIL解决人脸识别中文字体乱码-----------
global pilimg
pilimg=Image.fromarray(img)  # 将cv2图像转成pil
draw=ImageDraw.Draw(pilimg) # 使用ImageDraw.Draw()在pilimg图像上打印
font=ImageFont.truetype('F:/a.Machine Learn/font/SimSun.ttf',40,encoding='utf-8') # 宋体simsun-ttf size字体大小  encoding编码方式

先使用Image.fromarray()将OpenCV图像转成PIL型,再使用ImageDraw.Draw()在PIL图像上打印,font是下载的SimSun.ttf字体,需要导入源路径,40设置字体大小,编码方式‘utf-8’。

在需要使用文字的地方加上语句

draw.text((x + 10, y - 10), '李华', font=font, fill='yellow', stroke_width=2)

其中(x+10,y-10)文字开始显示的坐标,'李华'是输入的text文本,font=font表示字体类型,fill:字体颜色(有一点问题,颜色可以更改但是好像对应不上hhhh),stroke_width设置字体粗细。

--------在适当位置,将PIL.Image转成OpenCV图像类型

#-----将PIL.Image图像转成cv2图像格式------
    img=cv2.cvtColor(np.asarray(pilimg),cv2.COLOR_BGR2BGRA)
    # img=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
    cv2.imshow('result',img) # 显示人脸检测图像

使用OpenCV中的cvtColor()函数将PIL.image类型的pilimg图像转成OpenCV图像,其中cv2.COLOR_BGR2GRAY是给BGR(RGB)格式的图片添加透明通道BGRA(RGBA)。

该部分完整代码

import cv2
import numpy as np
import os
from PIL import Image,ImageDraw,ImageFont

# 加载训练数据集文件--加载识别器LBRHFaceRegnizer_create()
recogizer=cv2.face.LBPHFaceRecognizer_create() # 需要安装pip install opencv_contrib-python

# 加载数据--训练好人脸识别得到的数据
recogizer.read('./trainer/trainer1.yml')


names=[] # 创建空列表,储存识别的名字name--图片名称第一个点和第二个点间部分

# 准备识别的图片
def face_detect_demo(img):
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 图片灰度化---cv2.cvtColor()
    # 加载分类器--进行检测
    face_detector=cv2.CascadeClassifier('F:/Program Files/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
    # face=face_detector.detectMultiScale(gray,1.1,5,cv2.CASCADE_SCALE_IMAGE,(100,100),(300,300))
    face=face_detector.detectMultiScale(gray) # 使用默认参数
    # face=face_datector.deteMultiScale(gray)  # 默认
    for x,y,w,h in face: # 将整张人脸框住(矩形框+圆形框)
        global pilimg
        cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2) # 绘制矩形框住识别的人脸
        cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1) # 绘制圆框住识别的人脸
        # 人脸识别--预测和评分--recogizer.predict()输入参数是一个人脸图像,输出结果一个元组,包括预测结果ids和置信度confidence---取gray中矩形框住的部分
        ids,confidence=recogizer.predict(gray[y:y+h,x:x+w]) # 调用识别器cv2.face.LBPHFaceRecognizer中的predict()方法

        # ------将OpenCV图像转成PIL图像:使用PIL解决人脸识别中文字体乱码-----------
        pilimg=Image.fromarray(img)  # 将cv2图像转成pil
        draw=ImageDraw.Draw(pilimg) # 使用ImageDraw.Draw()在pilimg图像上打印
        font=ImageFont.truetype('F:/a.Machine Learn/font/SimSun.ttf',40,encoding='utf-8') # 宋体simsun-ttf size字体大小  encoding编码方式


        print('标签id:',ids,'置信评分:',confidence)
        if confidence>100: # confidence比较大时说明不可信
            draw.text((x + 10, y - 10), 'unknow', font=font, fill='yellow', stroke_width=2)
        else: # 当人是白名单人员时,将人名打印到人脸的方框上
            draw.text((x + 10, y - 10), str(names[ids-1]), font=font,fill='yellow', stroke_width=2)

    #-----将PIL.Image图像转成cv2图像格式------
    img=cv2.cvtColor(np.asarray(pilimg),cv2.COLOR_BGR2BGRA) # cv2.COLOR_BGR2BGRA
    # img=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
    cv2.imshow('result',img) # 显示人脸检测图像


# 名字标签
def name(): # 定义name()函数---获取训练保存图片的人员名字
    path='./data/jm1/'
    # names=[]
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)] # path路径 f是图片名.jpg
    for imagePath in imagePaths:
        name=str(os.path.split(imagePath)[1].split('.',2)[1])
        names.append(name)


# 加载视频、选定摄像头、加载图片
# cap=cv2.VideoCapture('1.mp4') # 参数为 0 调用本地摄像头,url连接调取网络摄像头,文件地址获取本地视频
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW) # 识别电脑摄像头并打开
name()

while True:
    flag,frame=cap.read() # 读取cap 中的self和iamge;当有视频内容时self值非空,image当前帧的图像
    frame=cv2.flip(frame,1)
    if not flag: # 没有视频内容时 跳出整个while循环
        break
    face_detect_demo(frame) # 如果有视频内容,调用face_detect_demo()方法识别图片
    if ord(' ')==cv2.waitKey(10): # 按空格键(表示等待10秒?),则跳出循环
        break

# 释放内存
cv2.destroyAllWindows()
cap.release()

在最后PIL.Image图像转成OpenCV类型图像时,采用了cv2.COLOR_BGR2BGRA,可能是这里增加alpha通道造成字体颜色不匹配,如果有找到合适的颜色模式,希望可以分享在评论区。

-----------------一枚学习人脸识别的新手记录

你可能感兴趣的:(opencv,python,人工智能)