原力计划

封图 | CSDN 下载自东方 IC

出品 | CSDN 博客

昨天在 GitHub 上看到一个有趣的开源项目,它能检测我们是否有戴口罩,跑起程序测试后,发现识别率挺高的,也适应不同环境,于是分享给大家。

首先感谢 AIZOOTech 的开源项目 —— FaceMaskDetection,以下为该项目的 GitHub 地址:

https://github.com/AIZOOTech/FaceMaskDetection

测试环境

我们采用:

  • Windows 系统;

  • 软件:PyCharm;

  • 使用模型:TensorFlow。

  • 先看一下效果:

    检测出帅气的胡歌没有带口罩。红色框框是圈出人脸部分,上方的字体:NoMask ,准确率 1 (即有 100% 把握认为没带口罩)。

    如果在多人的情况下,能检测出来吗?如下图所示。

    不错不错,这个模型能同时检测多人的,并且准确高。

    有人带口罩,有人没带口罩,能检测出来吗?

    哇,这个模型很棒。检测出带口罩大叔,和两个没带口罩的小伙子。

    大家可以先在 页体验一下:

    https://aizoo.com/face-mask-detection.html

    接下来,我们具体分析一下这个项目:

  • 支持 5 大主流深度学习框架(PyTorch、TensorFlow、MXNet、Keras 和 Caffe),已经写好接口了;可以根据自身的环境选择合适的框架,比如:TensorFlow;所有模型都在 models 文件夹下。

  • 公开了近 8000 张的人脸口罩数据和模型,数据集来自于 WIDER Face 和 MAFA 数据集, 重新修改了标注并进行了校验(主要是 MAFA 和 WIDER Face 的人脸位置定义不一样,所以进行了修改标注)并将其开源出来。

  • 模型结构

    本模型输入大小为 260×260,主干 络只有 8 个卷积层,加上定位和分类层,一共只有 24 层(每层的通道数目基本都是 3264128),所以模型特别小,只有 101.5 万参数。模型对于普通人脸基本都能检测出来,但是对于小人脸,检测效果肯定不如大模型。

    页使用了 Tensorflow.js 库,所以模型是完全运行在浏览器里面的。运行速度的快慢,取决于电脑配置的高低。

    模型在五个卷积层上接出来了定位分类层,其大小和 anchor 设置信息如下表。

    工程包目录结构分析

    GitHub 工程包下载:

    https://github.com/AIZOOTech/FaceMaskDetection

    下载完 FaceMaskDetection 压缩包后,解压后如下图:

    如何运行程序?

    以 TensorFlow 模型为例子,代码中 TensorFlow 版本应该是 1.x;

    如果是 TensorFlow 版本是 2.x 的朋友,对应函数修改为 tf.compat.v1.xxxx,使函数与 1.x 版本兼容。

    如果想运行图片:

    python tenforflow_infer.py --img-path /path/to/your/img
    python tenforflow_infer.py --img-path img/demo2.jpg

    运行结果:

    如果想运行运行视频:

    python tenforflow_infer.py --img-mode 0 --video-path /path/to/video

    /path/to/video 为视频所在的路径+视频名。

    如果想实时使用摄像头检测:

    python tenforflow_infer.py --img-mode 0 --video-path 0

    这里的 0 ,代表在电脑中设备 ;0 默认为电脑自带的摄像头。

    如果想使用外接摄像头,可以改为 1 (比如外接上一个 USB 摄像头)。

    这里看一下 tenforflow_infer.py 代码:

    # -*- coding:utf-8 -*-
    import cv2
    import time
    import argparse

    import numpy as np
    from PIL import Image
    from keras.models import model_from_json
    from utils.anchor_generator import generate_anchors
    from utils.anchor_decode import decode_bbox
    from utils.nms import single_class_non_max_suppression
    from load_model.tensorflow_loader import load_tf_model, tf_inference


    #sess, graph = load_tf_model('FaceMaskDetection-mastermodelsface_mask_detection.pb')
    sess, graph = load_tf_model('modelsface_mask_detection.pb')
    # anchor configuration
    feature_map_sizes = [[33, 33], [17, 17], [9, 9], [5, 5], [3, 3]]
    anchor_sizes = [[0.04, 0.056], [0.08, 0.11], [0.16, 0.22], [0.32, 0.45], [0.64, 0.72]]
    anchor_ratios = [[1, 0.62, 0.42]] * 5

    # generate anchors
    anchors = generate_anchors(feature_map_sizes, anchor_sizes, anchor_ratios)

    #用于推断,批大小为1,模型输出形状为[1,N,4],因此将锚点的dim扩展为[1,anchor_num,4]
    anchors_exp = np.expand_dims(anchors, axis=0)
    id2class = {0: 'Mask', 1: 'NoMask'}


    def inference(image, conf_thresh=0.5, iou_thresh=0.4, target_shape=(160, 160), draw_result=True, show_result=True):
    ''' 检测推理的主要功能
    # :param image:3D numpy图片数组
    # :param conf_thresh:分类概率的最小阈值。
    # :param iou_thresh: 管的IOU门限
    # :param target_shape:模型输入大小。
    # :param draw_result:是否将边框拖入图像。
    # :param show_result:是否显示图像。
    '''
    # image = np.copy(image)
    output_info =
    height, width, _ = image.shape
    image_resized = cv2.resize(image, target_shape)
    image_np = image_resized / 255.0 # 归一化到0~1
    image_exp = np.expand_dims(image_np, axis=0)
    y_bboxes_output, y_cls_output = tf_inference(sess, graph, image_exp)

    # remove the batch dimension, for batch is always 1 for inference.
    y_bboxes = decode_bbox(anchors_exp, y_bboxes_output)[0]
    y_cls = y_cls_output[0]
    # 为了加快速度,请执行单类NMS,而不是多类NMS。
    bbox_max_scores = np.max(y_cls, axis=1)
    bbox_max_score_classes = np.argmax(y_cls, axis=1)

    # keep_idx是nms之后的活动边界框。
    keep_idxs = single_class_non_max_suppression(y_bboxes, bbox_max_scores, conf_thresh=conf_thresh,iou_thresh=iou_thresh)
    for idx in keep_idxs:
    conf = float(bbox_max_scores[idx])
    class_id = bbox_max_score_classes[idx]
    bbox = y_bboxes[idx]
    # 裁剪坐标,避免该值超出图像边界。
    xmin = max(0, int(bbox[0] * width))
    ymin = max(0, int(bbox[1] * height))
    xmax = min(int(bbox[2] * width), width)
    ymax = min(int(bbox[3] * height), height)

    if draw_result:
    if class_id == 0:
    color = (0, 255, 0)
    else:
    color = (255, 0, 0)
    cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color, 2)
    cv2.putText(image, "%s: %.2f" % (id2class[class_id], conf), (xmin + 2, ymin - 2),
    cv2.FONT_HERSHEY_SIMPLEX, 1, color)
    output_info.append([class_id, conf, xmin, ymin, xmax, ymax])

    if show_result:
    Image.fromarray(image).show
    return output_info


    def run_on_video(video_path, output_video_name, conf_thresh):
    cap = cv2.VideoCapture(video_path)
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    fps = cap.get(cv2.CAP_PROP_FPS)
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    #writer = cv2.VideoWriter(output_video_name, fourcc, int(fps), (int(width), int(height)))
    total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    if not cap.isOpened:
    raise ValueError("Video open failed.")
    return
    status = True
    idx = 0
    while status:
    start_stamp = time.time
    status, img_raw = cap.read
    img_raw = cv2.cvtColor(img_raw, cv2.COLOR_BGR2RGB)
    read_frame_stamp = time.time
    if (status):
    inference(img_raw,
    conf_thresh,
    iou_thresh=0.5,
    target_shape=(260, 260),
    draw_result=True,
    show_result=False)
    cv2.imshow('image', img_raw[:, :, ::-1])
    cv2.waitKey(1)
    inference_stamp = time.time
    # writer.write(img_raw)
    write_frame_stamp = time.time
    idx += 1
    print("%d of %d" % (idx, total_frames))
    print("read_frame:%f, infer time:%f, write time:%f" % (read_frame_stamp - start_stamp,
    inference_stamp - read_frame_stamp,
    write_frame_stamp - inference_stamp))
    # writer.release


    if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Face Mask Detection")
    parser.add_argument('--img-mode', type=int, default=0, help='set 1 to run on image, 0 to run on video.') #这里设置为1:检测图片;还是设置为0:视频文件(实时图像数据)检测
    parser.add_argument('--img-path', type=str, help='path to your image.')
    parser.add_argument('--video-path', type=str, default='0', help='path to your video, `0` means to use camera.')
    # parser.add_argument('--hdf5', type=str, help='keras hdf5 file')
    args = parser.parse_args
    if args.img_mode:
    imgPath = args.img_path
    #img = cv2.imread("imgPath")
    img = cv2.imread(imgPath)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    inference(img, show_result=True, target_shape=(260, 260))
    else:
    video_path = args.video_path
    if args.video_path == '0':
    video_path = 0
    run_on_video(video_path, '', conf_thresh=0.5)

    测试集 PR 曲线

    因为 WIDER face 是一个任务比较复杂的数据集,模型又设计的非常小,所以对于人脸的 PR 曲线并不是那么性感。这点可以通过设计大模型来提升对于小人脸的检测效果。

    再次感谢 AIZOOTech 的开源项目 —— FaceMaskDetection。

    原文地址:
    https://blog.csdn.net/qq_41204464/article/details/104596777

    ?小米回应”暴力裁员”; 告称安卓手机贬值速度是 iPhone 两倍;Ant Design 4.0.1 发布| 极客头条

    ?技术大佬:我去,你写的 switch 语句也太老土了吧!

    ?赔偿谷歌1.8亿美元!前Uber自动驾驶主管被告到破产

    ?乔布斯遗孀裸捐 250 亿美元财产:没兴趣累积财富

    ?时间复杂度的表示、分析、计算方法……一文带你看懂时间复杂度!

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2020年2月1日
    下一篇 2020年2月1日

    相关推荐