基于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通道造成字体颜色不匹配,如果有找到合适的颜色模式,希望可以分享在评论区。
-----------------一枚学习人脸识别的新手记录
标签:人脸识别,PIL,img,Python,cv2,face,乱码,OpenCV,图像 From: https://blog.csdn.net/t3036374036/article/details/141586586