zoukankan      html  css  js  c++  java
  • 人脸检测,openCV 上放置中文

    #################################################

    未曾验证:(据说只适合python 2)

    https://www.cnblogs.com/datou-swag/articles/10671842.html

    http://www.voidcn.com/article/p-hmuycojw-bms.html

    http://www.voidcn.com/article/p-uewkhlef-bbc.html

    #################################################

    OpenCV 的 cv2.putText 方法中无法放置中文。

    但是PIL 的 Image.Draw 的方法中有 draw.text 的方法是可以设置中文字体的。simsum.ttc 宋体。

    OpenCV 读出的图像是np.ndarray 的图像格式。

    PIL 读出的图像格式与上述有所不同。所以当图像从cv2 转到 PIL 操作时,两者的图像格式需要做一些变化。

    #!/usr/bin/env python
    # !_*_ coding:utf-8 _*_
    
    import face_recognition
    import cv2
    import numpy as np
    from PIL import Image, ImageDraw, ImageFont
    
    
    def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
        if (isinstance(img, np.ndarray)):
            pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            draw = ImageDraw.Draw(pil_img)
            # 字体默认在 C:WindowsFonts 下面,要鼠标右键查看属性
            # fontStyle = ImageFont.truetype('simsun.ttc', textSize, encoding='utf-8')
            fontStyle = ImageFont.truetype('msyh.ttc', textSize, encoding='utf-8')
            draw.text((left, top), text, textColor, font=fontStyle)
            return cv2.cvtColor(np.asarray(pil_img), cv2.COLOR_RGB2BGR)
    
    
    face_image = face_recognition.load_image_file('imgs/qsz001.jpg')
    # face_recognition.load_image_file 读出的文件是RGB,而后面需要在cv2 上画框,cv2是BGR 的np.ndarray的数组文件
    face_image = cv2.cvtColor(face_image, cv2.COLOR_RGB2BGR)
    face_locations = face_recognition.face_locations(face_image)
    for face_location in face_locations:
        print(face_location)
        top, right, bottom, left = face_location
        cv2.rectangle(face_image, (left, top), (right, bottom), (0, 255, 0), 2)
        face_image = cv2ImgAddText(face_image, "邱淑贞", left, bottom + 5, (255, 0, 0), 20)
    
        cv2.imshow("image", face_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

    注意 字体的路径: 

    字体默认在 C:WindowsFonts 下面,要鼠标右键查看属性



    下面代码是经过测试的,能够正常运行。
    #!/usr/bin/env python
    # !_*_ coding:utf-8 _*_
    
    import numpy as np
    import freetype
    import copy
    import pdb
    """
    ##################################################
    # tools                                          #
    #------------------------------------------------#
    # draw chinese text using freetype on python3.7  #                  
    # 2020-04-12                                     #
    ##################################################
    https://www.pythonheidong.com/blog/article/327766/a72be84affd143fcc7f1/
    
    """
    
    class put_chinese_text(object):
        def __init__(self, ttf):
            self._face = freetype.Face(ttf)
    
        def draw_text(self, image, pos, text, text_size, text_color):
            '''
            draw chinese(or not) text with ttf
            :param image:     image(numpy.ndarray) to draw text
            :param pos:       where to draw text
            :param text:      the context, for chinese should be unicode type
            :param text_size: text size
            :param text_color:text color
            :return:          image
            '''
            self._face.set_char_size(text_size * 64)
            metrics = self._face.size
            ascender = metrics.ascender / 64.0
    
            # descender = metrics.descender/64.0
            # height = metrics.height/64.0
            # linegap = height - ascender + descender
            ypos = int(ascender)
    
            # if not isinstance(text, unicode):
            #    text = text.decode('utf-8')
            img = self.draw_string(image, pos[0], pos[1] + ypos, text, text_color)
            return img
    
        def draw_string(self, img, x_pos, y_pos, text, color):
            '''
            draw string
            :param x_pos: text x-postion on img
            :param y_pos: text y-postion on img
            :param text:  text (unicode)
            :param color: text color
            :return:      image
            '''
            prev_char = 0
            pen = freetype.Vector()
            pen.x = x_pos << 6  # div 64
            pen.y = y_pos << 6
    
            hscale = 1.0
            matrix = freetype.Matrix(int(hscale) * 0x10000, int(0.2 * 0x10000), 
                                     int(0.0 * 0x10000), int(1.1 * 0x10000))
            cur_pen = freetype.Vector()
            pen_translate = freetype.Vector()
    
            image = copy.deepcopy(img)
            for cur_char in text:
                self._face.set_transform(matrix, pen_translate)
    
                self._face.load_char(cur_char)
                kerning = self._face.get_kerning(prev_char, cur_char)
                pen.x += kerning.x
                slot = self._face.glyph
                bitmap = slot.bitmap
    
                cur_pen.x = pen.x
                cur_pen.y = pen.y - slot.bitmap_top * 64
                self.draw_ft_bitmap(image, bitmap, cur_pen, color)
    
                pen.x += slot.advance.x
                prev_char = cur_char
    
            return image
    
        def draw_ft_bitmap(self, img, bitmap, pen, color):
            '''
            draw each char
            :param bitmap: bitmap
            :param pen:    pen
            :param color:  pen color e.g.(0,0,255) - red
            :return:       image
            '''
            x_pos = pen.x >> 6
            y_pos = pen.y >> 6
            cols = bitmap.width
            rows = bitmap.rows
    
            glyph_pixels = bitmap.buffer
    
            for row in range(rows):
                for col in range(cols):
                    if glyph_pixels[row * cols + col] != 0:
                        img[y_pos + row][x_pos + col][0] = color[0]
                        img[y_pos + row][x_pos + col][1] = color[1]
                        img[y_pos + row][x_pos + col][2] = color[2]
    
    
    if __name__ == '__main__':
        # just for test
        import cv2
    
        line = '美美的'
        # img = np.zeros([300,300,3])
        img = cv2.imread('imgs/qsz001.jpg', cv2.IMREAD_COLOR)
    
        color_ = (0, 0, 255)  # Green
        pos = (30, 30)
        text_size = 50
    
        # ft = put_chinese_text('wqy-zenhei.ttc')
        ft = put_chinese_text('C:/Windows/Fonts/simkai.ttf')
        image = ft.draw_text(img, pos, line, text_size, color_)
    
        cv2.imshow('freetype', image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    
    
     

     My Code

    #!/usr/bin/env python
    # !_*_ coding:utf-8 _*_
    
    import cv2
    import face_recognition
    import numpy as np
    from PIL import Image, ImageFont, ImageDraw
    import os
    
    
    def load_image(path):
        """
        读取已知的文件库,把所有人的 encodings 作为一个文件库,后续视频中的头像来与他做比较。
        os.walk() 与 os.listdir() 都可以得到文件的filenames。
    
        :param path:
        :return:
        """
        for root, dirnames, filenames in os.walk(path):
            # print(root, dirnames, filenames)
            print("正在加载已知人员的图片信息......")
            facelib_encodings = []
            for filename in filenames:
                file_path = os.path.join(root, filename)
                # print(file_path)
                face_image = face_recognition.load_image_file(file_path)
                # 因为文件库中的头像均是单人照,所以取索引【0】
                facelib_encoding = face_recognition.face_encodings(face_image)[0]
                facelib_encodings.append(facelib_encoding)
    
        return facelib_encodings, filenames
    
    
    def cv2ImgAddText(img, text, left, top, textcolor, textsize=20):
        if (isinstance(img, np.ndarray)):
            pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            draw = ImageDraw.Draw(pil_img)
            # 字体默认在 C:WindowsFonts 下面,要鼠标右键查看属性
            # fontStyle = ImageFont.truetype('simsun.ttc', textSize, encoding='utf-8')
            fontStyle = ImageFont.truetype('simsun.ttc', textsize, encoding='utf-8')
            draw.text((left, top), text, textcolor, font=fontStyle)
            # 因为后面还需要调用cv2.imshow的函数,所以要把pil_img 转化的cv2的领域 RGB---->BGR
            cv2_image = cv2.cvtColor(np.asarray(pil_img), cv2.COLOR_RGB2BGR)
            return cv2_image
    
    
    # def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
    #     if (isinstance(img, np.ndarray)):
    #         pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    #         draw = ImageDraw.Draw(pil_img)
    #         # 字体默认在 C:WindowsFonts 下面,要鼠标右键查看属性
    #         # fontStyle = ImageFont.truetype('simsun.ttc', textSize, encoding='utf-8')
    #         fontStyle = ImageFont.truetype('msyh.ttc', textSize, encoding='utf-8')
    #         draw.text((left, top), text, textColor, font=fontStyle)
    #         return cv2.cvtColor(np.asarray(pil_img), cv2.COLOR_RGB2BGR)
    
    
    face_lib, filenames = load_image('facelib')
    
    # 下面摄像头开始抓取图片
    capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    while True:
        ret, frame = capture.read()
        # flip函数是使图像做镜像,由后面的参数决定 0:垂直翻转; 1:水平翻转; -1:水平,垂直均翻转
        # frame = cv2.flip(frame, 1)
    
        # 把图像缩小至1/4,以便于后续分析,但是后续得到的坐标需要 *4 才是frame上真实的坐标
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        face_locations = face_recognition.face_locations(small_frame)
        face_encodings = face_recognition.face_encodings(small_frame, face_locations)
    
        names = []
        # 上述得到的face_encodings,可能是单个人像,也有可能是多人的图像(摄像头中可能由多个人)
        for face_encoding in face_encodings:
            name = "未知人像"
            matches = face_recognition.compare_faces(face_lib, face_encoding, tolerance=0.5)
            # 如果有人匹配,要找出匹配的索引,以便于找到相应的 filename,然后取其姓名。
            for item in matches:
                if item == True:
                    index_num = matches.index(True)
                    name = filenames[index_num].split(".")[0]
            names.append(name)
            print(names)
    
        for face_location, name in zip(face_locations, names):
            top, right, bottom, left = face_location
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4
            # 利用cv2画矩形框
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
            # print(name)
    
            # 利用PIL 写汉字
            frame = cv2ImgAddText(frame, name, left, bottom + 5, (255, 255, 255), 25)
    
        cv2.imshow("video", frame)
        key = cv2.waitKey(50)
        if key & 0xFF == ord('q'):
            break
    
    cv2.destroyAllWindows()
    capture.release()



  • 相关阅读:
    SecureCRT:保存输出日志的方法
    中文数字转阿拉伯数字
    XP 安装Oralce 10g 数据库
    SQL语句处理一些修改、新增、删除、修改属性操作(MySql)
    SpringBoot整合Shiro完成认证
    SpringBoot 集成Shiro之使用Redis缓存授权认证信息
    解决Establishing SSL connection without server‘s identity verification is not recommended.
    操作系统的内存笔记
    Shiro的认证与授权
    详解 TCP的三次握手四次挥手
  • 原文地址:https://www.cnblogs.com/xuwenwei/p/14549181.html
Copyright © 2011-2022 走看看