Python 人脸识别 And cv2 putText不支持中文解决方案

描述

  • 其实之前我就看过一点python的人脸识别, 只是没弄成功, 最近空闲下来又想起来研究研究, 这次如期望一样的运行成功了, 其实并不需要我们自己去做太多事情, 只是需要正确安装, 然后正常运行起来就行, 然后去GitHub复制一个demo下来就行啦!
  • 以下标注GitHub地址的, 都是比较官方的介绍, 强烈推荐阅读

文档

Face Recognition 人脸识别, GitHub地址: English, 简体中文

 

译者注:

 

本项目face_recognition是一个强大、简单、易上手的人脸识别开源项目,并且配备了完整的开发文档和应用案例,特别是兼容树莓派系统。

 

为了便于中国开发者研究学习人脸识别、贡献代码,我将本项目README文件翻译成中文。

 

向本项目的所有贡献者致敬。

 

英译汉:同济大学开源软件协会 子豪兄Tommy

 

Translator's note:

 

face_recognition is a powerful, simple and easy-to-use face recognition open source project with complete development documents and application cases, especially it is compatible with Raspberry Pi.

 

In order to facilitate Chinese software developers to learn, make progress in face recognition development and source code contributions, I translated README file into simplified Chinese.

 

Salute to all contributors to this project.

 

Translator: Tommy in Tongji Univerisity Opensource Association 子豪兄Tommy

 

本项目是世界上最简洁的人脸识别库,你可以使用Python和命令行工具提取、识别、操作人脸。

 

本项目的人脸识别是基于业内领先的C++开源库 dlib中的深度学习模型,用Labeled Faces in the Wild人脸数据集进行测试,有高达99.38%的准确率。但对小孩和亚洲人脸的识别准确率尚待提升。

 

Labeled Faces in the Wild是美国麻省大学安姆斯特分校(University of Massachusetts Amherst)制作的人脸数据集,该数据集包含了从网络收集的13,000多张面部图像。

 

本项目提供了简易的face_recognition命令行工具,你可以用它处理整个文件夹里的图片。

 

安装

  • 安装这里很多时候不是那么顺利, 可能会有问题, 我自己是mac os 那就以mac os为例了!
  • 也可以看GitHub上面安装, 作者对安装这一块也做了很多介绍 GitHub 安装介绍
1
2
pip3 install face_recognition
pip3 install opencv-python  # cv2库

如何在macOS和Ubuntu上从github安装dlib v19.9或更高版本(带有python绑定)

GitHub地址: 安装介绍

 

先决条件:

 

  • 安装了Python 3。在macOS上,可以从自制软件安装,甚至可以通过https://www.python.org/download通过标准的Python 3.6下载安装程序进行安装。在Linux上,只需使用软件包管理器即可。
  • 在macOS上:
  • 从Mac App Store安装XCode(或安装XCode命令行实用程序)。
  • 有自制安装
  • 在Linux上:
  • 有关所需的apt软件包的完整列表,请查看示例Dockerfile并复制那里安装的内容。
  • 这些说明假定您使用的是Ubuntu 16.04或更高版本。如果您使用的是14.04,则可以尝试使用这些安装说明来解决旧的CMake版本。
  • 这些说明假定您没有nVidia GPU,没有安装Cuda和cuDNN,并且不希望GPU加速(因为当前所有Mac型号都不支持此功能)。

从github克隆代码:

 

1
git clone https://github.com/davisking/dlib.git

构建主要的dlib库(如果只想使用Python,则是可选的):

 

1
2
cd dlib
mkdir build; cd build; cmake ..; cmake --build .

 

 

构建并安装Python扩展:

 

1
2
cd ..
python3 setup.py install

此时,您应该能够运行python3并import dlib成功键入。
如果缺少cmake,则只需安装即可。在OSX上:

 

1
brew install cmake

cv2 putText不支持中文解决方案, 下面示例中有实际使用

  • cv2 put text 不支持中文呢, 官方解释是为了保持库的简单和轻量, 并且表明以后也不会支持中文
  • 字体下载路径: https://github.com/sonatype/maven-guide-zh/raw/master/content-zh/src/main/resources/fonts/simsun.ttc
1
2
3
4
5
6
fontpath = "./font/simsun.ttc"  # 宋体字体文件
font_1 = ImageFont.truetype(fontpath, 30)  # 加载字体, 字体大小
img_pil = Image.fromarray(frame)
draw = ImageDraw.Draw(img_pil)
draw.text((left + 10, bottom - 32), name, font=font_1, fill=(255, 255, 255))  # xy坐标, 内容, 字体, 颜色
frame = np.array(img_pil)

示例

  • 我这里是从GitHub复制下来的demo, 在加以修改, 主要是支持web浏览器网页端显示
  • 看注释, 理解逻辑, 没有的库直接安装就好

python

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# coding: utf-8
from tornado import web, httpserver, ioloop, websocket
import os
import cv2
import numpy as np
from PIL import Image, ImageFont, ImageDraw
import base64
import face_recognition

# 定义一些基本设置
port = 10101
address = "localhost"
JPEG_HEADER = "data:image/jpeg;base64,"  # 这个是对图片转码用的

# 开启一个摄像头
cap = cv2.VideoCapture(0)

# 加载示例图片并学习如何识别它。
obama_image = face_recognition.load_image_file("./img/jason.JPG")
obama_face_encoding = face_recognition.face_encodings(obama_image)[0]

# 加载第二个示例图片并学习如何识别它。
biden_image = face_recognition.load_image_file("./img/davis.jpg")
biden_face_encoding = face_recognition.face_encodings(biden_image)[0]

# 创建已知面编码及其名称的数组
known_face_encodings = [
    obama_face_encoding,
    biden_face_encoding
]
known_face_names = [
    "张**",  # 对应jason人脸
    "赵**"  # 对应davis人脸
]

# 初始化一些变量
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True


def get_image_dataurl():
    global face_locations
    global face_encodings
    global face_names
    global process_this_frame
    global known_face_encodings
    global known_face_names

    # 从摄像头读取数据, 读取成功 ret为True,否则为False,frame里面就是一个三维数组保存图像
    ret, frame = cap.read()

    # 将视频帧的大小调整为1/4以加快人脸识别处理
    small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

    # 将图像从BGR颜色(OpenCV使用)转换为RGB颜色(人脸识别使用)
    rgb_small_frame = small_frame[:, :, ::-1]

    # 仅每隔一帧处理一次视频以节省时间
    if process_this_frame:
        # 查找当前视频帧中的所有面和面编码
        face_locations = face_recognition.face_locations(rgb_small_frame)
        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

        face_names = []
        for face_encoding in face_encodings:
            # 查看该面是否与已知面匹配
            matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
            name = "未知"

            # 如果在已知的人脸编码中找到匹配项,请使用第一个。
            # 如果匹配为True:
            # first_match_index=matches.index(true)
            # name=known_face_names[first_match_index]

            # 或者,使用与新面的距离最小的已知面
            face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
            best_match_index = np.argmin(face_distances)
            if matches[best_match_index]:
                name = known_face_names[best_match_index]

            face_names.append(name)

    process_this_frame = not process_this_frame

    # 显示结果
    for (top, right, bottom, left), name in zip(face_locations, face_names):
        # 由于我们在中检测到的帧被缩放到1/4大小,因此缩放备份面位置
        top *= 4
        right *= 4
        bottom *= 4
        left *= 4

        # 在脸上画一个方框
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

        # 在面下画一个有名字的标签
        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
        # font = cv2.FONT_HERSHEY_DUPLEX
        # cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)

        # cv2.putText 不支持中文所以这里换一种方法
        fontpath = "./font/simsun.ttc"  # 宋体字体文件
        font_1 = ImageFont.truetype(fontpath, 30)  # 加载字体, 字体大小
        img_pil = Image.fromarray(frame)
        draw = ImageDraw.Draw(img_pil)
        draw.text((left + 10, bottom - 32), name, font=font_1, fill=(255, 255, 255))  # xy坐标, 内容, 字体, 颜色
        frame = np.array(img_pil)

    # 先将数组类型编码成 jepg 类型的数据,然后转字节数组,最后将其用base64编码
    r, buf = cv2.imencode(".jpeg", frame)
    dat = Image.fromarray(np.uint8(buf)).tobytes()
    img_date_url = JPEG_HEADER + str(base64.b64encode(dat))[2:-1]
    return img_date_url


class IndexHandler(web.RequestHandler):
    def get(self, *args, **kwargs):
        self.render("index.html")


class VideoHandler(websocket.WebSocketHandler):
    # 处理接收数据
    def on_message(self, message):
        self.write_message({"img": get_image_dataurl()})


if __name__ == '__main__':
    app = web.Application(handlers=[(r"/", IndexHandler),
                                    (r"/index", IndexHandler),
                                    (r'/video', VideoHandler)],
                          template_path=os.path.join(os.path.dirname(__file__), "ui"))
    http_server = httpserver.HTTPServer(app)
    http_server.listen(port=port, address=address)
    print("URL: http://{}:{}/index".format(address, port))
    ioloop.IOLoop.instance().start()

 

 

html

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
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Face Recognition</title>
</head>
<body>

<div style="width: 100%;height: auto;text-align: center;">
    <img src="" id="img" style="width: 50%;">
</div>

</body>

<script>
    var address = "localhost";
    var port = 10101;
    var ws = new WebSocket("ws://" + address + ":" + port + "/video");
    var img = document.getElementById("img");

    // 设置一个定时10ms,等待WebSocket 连接完成
    var timer = setInterval(function () {
        if (ws.readyState == 1) {
            //想服务器发送数据,请求图片,这里发送的内容随便都可以
            ws.send("msg");
            clearInterval(timer);
        }
    }, 10);

    //信息的回调处理函数
    ws.onmessage = function (res) {
        // 首先获取到一帧帧的图片
        var img_src = JSON.parse(res.data)["img"];
        img.src = img_src;
        ws.send("msg");
    }

</script>
</html>

转:https://www.codenong.com/js7ca7ea550b4e/

posted @ 2023-03-01 10:04  rmticocean  阅读(444)  评论(0编辑  收藏  举报