2.使用insightface读取视频进行人脸识别

6 篇文章 0 订阅
1 篇文章 0 订阅

1.人脸特征持久化

输入数据集的人脸并得到特征向量之后,首先要持久化下来。

import numpy as np
'''
前面的忽略,就是加载模型,获取数据集,跑模型得到向量f
'''
'''关键代码'''
f = model.get_feature(img)
f.tofile('/myfeature/rep.bin')

# 读取
f_ = np.fromfile('/myfeature/rep.bin', dtype=np.float32)
print(f_)

2.人脸识别

思路:

  1. 使用opencv读取视频流。
  2. 获取每一帧并进行人脸检测,进一步特征提取。
  3. 与特征库的特征进行比对。
  4. 设置阈值,求当前特征与特征库特征的距离,提取出最小的距离与阈值比对,如果小于阈值则返回特征所对应的姓名。
  5. 输出姓名到视频流中并用矩形框出识别出的人脸。
import face_model_v2 as face_model
import argparse
import cv2
import sys
import numpy as np
import pandas as pd
import os
parser = argparse.ArgumentParser(description='face model test')
# general
parser.add_argument('--image-size', default='112,112', help='')
parser.add_argument('--model', default='/models/model-r100-ii/model,0', help='path to load model.')
parser.add_argument('--ga-model', default='/models/gamodel-r50/model,0', help='path to load model.')
parser.add_argument('--gpu', default=0, type=int, help='gpu id')
parser.add_argument('--det', default=0, type=int, help='mtcnn option, 1 means using R+O, 0 means detect from begining')
parser.add_argument('--flip', default=0, type=int, help='whether do lr flip aug')
parser.add_argument('--threshold', default=1.24, type=float, help='ver dist threshold')
parser.add_argument('--videoPath', default=0)
parser.add_argument('--binPath', default=0)
args = parser.parse_args()
model = face_model.FaceModel(args)
# 获得持久化的特征库与对应的label
threshold = float(args.threshold)
#print(threshold)
videoPath = args.videoPath
binPath = args.binPath
feature = []
label = []
# 遍历目录获得目录中文件名字作为label,文件内容加入feature
for bin_ in os.listdir(binPath):
    # 注意要指定dtype
    feature.append(np.fromfile(binPath+'/' + bin_, dtype=np.float32))
    label.append(bin_.split('.')[0])


# 查找当前特征最接近的特征
def findNear(feature, f, threshold, label):
    dist_list = []
    # 遍历特征库
    for feature_unit in feature:
        # 距离的定义是(特征1-特征2)开根号并求和
        dist = np.sum(np.square(feature_unit - f))
        # dist_list作用是将所有距离都保存下来,以便获得最小距离
        dist_list.append(dist)
        # 寻找到最小距离
    minDist = np.min(dist_list)
        # 如果最小距离小于等于阈值
    if minDist <= threshold:
        # 求出最小距离对应的索引
        minIdx = np.argmin(dist_list)
        # 找到姓名
        return label[minIdx]
    else:
        # 如果没有满足条件的,就返回'none'
        return 'none'
print('*'*8, 'into video')
# read video
try:
    # 按路径读取视频
    cap = cv2.VideoCapture(videoPath)
    # 将视频缩小,目的是加快程序运行速度。
    cap.set(3, 240)
    cap.set(4, 180)
    print('get video')
    # 获得当前图像长宽
    width = int(cap.get(3))
    height = int(cap.get(4))
    # 不光读取图像,还要讲识别结果写入视频并返回,所以这一步是指定视频编码
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    # 指定视频输出对象,视频输出路径、编码、帧数、视频大小
    out = cv2.VideoWriter('./video/output.avi', fourcc, 25, (width,height))
    # 开始读取视频并做识别
    while True:
        # 读取视频,ret-是否读取成功, frame-图像
        ret, frame = cap.read()
        if ret:
            try:
                # 这里修改了一下face_model,使其返回的多个人脸和对应坐标
                imgs,bbox = model.get_input(frame)
                # 遍历人脸和坐标
                for img_unit,bbox_unit in zip(imgs, bbox):
                    # 因为有可能没有人脸,所以如果img_unit有shape值,那就是有人脸
                    if img_unit.shape:
                        # 获得特征
                        f = model.get_feature(img_unit)
                        # 找到匹配信息
                        res = findNear(feature, f, threshold, label)
                        # 如果匹配到了姓名
                        if res != 'none':
                            # 用方框标注,bbox_unit中的值为(左,上,右,下)
                            # 按照cv2.rectangle的参数写入
                            cv2.rectangle(frame, (int(bbox_unit[0]), int(bbox_unit[1])),(int(bbox_unit[2]), int(bbox_unit[3])), (0,0,255))
                            # 标记文字到图像中,参数:图像,文字,位置,字体,大小,颜色,宽度
                            frame = cv2.putText(frame, res, (int(bbox_unit[2]), int(bbox_unit[3])+2), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1)
                # 写出视频
                out.write(frame)
            except Exception as e:
                # 如果图像没有shape代表着没有人脸,img.shape就会报NoneType错误,捕获错误,并直接写出视频
                out.write(frame)
            # 每帧遍历
            if cv2.waitKey(1) & 0xff == ord('q'):
                break
        # 视频读取完毕,ret返回false那么退出循环
        else:
            break
    # 释放资源
    cap.release()
    out.release()
    cv2.destroyAllWindows()
# 程序就算报错也要正常释放资源,所以要捕获这个视频识别流程
except Exception as e:
    print(e)
# 最终释放资源
finally:
    cap.release()
    out.release()
    cv2.destroyAllWindows()
print('final')

3.源码改动

因为,源码指定了只检测一个人脸,所以需要更改源码以获得多个人脸进行识别。

进入insightface/deploy路径找到face_model.py,复制一份更名face_model_v2.py并编辑。

# 主要修改get_input方法
def get_input(self, face_img):
    #print('into face_model_v2')
    ret = self.detector.detect_face(face_img, det_type = self.args.det)
    if ret is None:
        return None
    bbox, points = ret
    # 存放所有检测的人脸图像
    aligned_list = []
    # 存放所有人脸坐标
    bbox_list = []    
    if bbox.shape[0]==0:
        return None
    for i in range(bbox.shape[0]):
        # 获取每一个坐标
        bbox_ = bbox[i,0:4]
        # 存放坐标
        bbox_list.append(bbox_)
        # 获取每一个特征点
        points_ = points[i,:].reshape((2,5)).T
        nimg = face_preprocess.preprocess(face_img, bbox_, points_, image_size='112,112')
        nimg = cv2.cvtColor(nimg, cv2.COLOR_BGR2RGB)
        aligned = np.transpose(nimg, (2,0,1))
        # 存放坐标
        aligned_list.append(aligned)
return aligned_list, bbox_list

4.接下来跑程序就行了,注意一下路径

  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值