精华内容
下载资源
问答
  • 安全帽识别安全帽检测yolo可以检测图片,视频流,有界面python识别率99%可商用源码具体效果:https://www.bilibili.com/video/BV1jJ41137N5?from=search&seid=12923138875718976927
  • 基于yolov3的安全帽检测及其训练数据集 数据集地址:链接: https://pan.baidu.com/s/14Bf0mk0Y-R4tsoQXhmI7Qg 提取码: eajs
  • 该资源中包含一段视频以及接近200张从视频里截取的图片,主要是用于检测安全帽的测试视频,包括若干行人戴着安全帽、不带安全帽、戴帽子的过程等并走过一固定的摄像头前面拍摄的画面。安全帽的颜色有白色黄色以及...
  • 本文聚焦于复杂场景下对工作人员是否佩戴安全帽的实时检测.YOLO (You Only Look Once)是当前最为先进的实时目标检测算法,在检测精度和速度上都取得了良好的效果,将YOLO应用于安全帽检测.针对未佩戴安全帽单类...
  • 基于图像分析的施工场景安全帽检测,王帅,项学智,本文主要针对工地场景下的施工工人是否正确佩戴安全帽的问题,利用图像分析的方式对施工场景下的安全帽进行检测。传统的人工检测
  • 通过使用bbox批注检测5k图像上的人员和安全帽,提高工作场所的安全性。该数据集包含以下3类的5000幅图像,这些图像带有PASCAL VOC格式的边界框注释:头盔;人; 头。
  • 安全帽检测

    2021-07-31 22:29:03
    安全帽检测 算法介绍:安全帽检测算法主要用工厂,建筑工地的入口,工作区域,可以进入作业区域的人员进行自动检测。若检测到人员未佩戴安全帽,可立即告警,该算法极大地提升了作业区域的管控效率,保障了作业人...

    安全帽检测

    算法介绍:安全帽检测算法主要用工厂,建筑工地的入口,工作区域,可以进入作业区域的人员进行自动检测。若检测到人员未佩戴安全帽,可立即告警,该算法极大地提升了作业区域的管控效率,保障了作业人安全!

    目标检测算法基于yolov5,数据集10000+张 均为txt格式。

    图文效果:

    在这里插入图片描述

    欢迎点赞 评论 留言 收藏

    展开全文
  • 此demo的python源代码 模型person-detection-retail-0013 示例视频文件 相关文章介绍 https://mp.csdn.net/postedit/93968520
  • 反射衣服检测和数据集yolov5 施工人员穿戴检测yolov5 作者是雷雷 yolov5 detect qq群(已满):980489677 yolov5检测qq2群:710514100 数据集下载链接详见说明-请参阅有关数据集下载链接的说明! 演示 数据标签...
  • 一种高精度的卷积神经网络安全帽检测方法.pdf
  • 安全帽检测detect.7z

    2020-05-25 15:06:33
    安全帽检测的检测,使用python实现,仅供参考。
  • 图像识别 安全帽检测 安全帽识别 用于安全帽的检测任务
  • 可以在arm嵌入式上运行的检测代码,无需编译直接运行,已在树莓派上测试过
  • “作为目标检测的鸿篇巨制YOLOV3,用来做安全帽检测非常合适”01—Yolov3简介Yolo_v3使用了darknet-53的前面的52层(没有全连接层),yolo_v3这个网络是一个...

     作为目标检测的鸿篇巨制YOLOV3,用来做安全帽检测非常合适

    01

    Yolov3简介

    Yolo_v3使用了darknet-53的前面的52层(没有全连接层),yolo_v3这个网络是一个全卷积网络,大量使用残差的跳层连接,并且为了降低池化带来的梯度负面效果,作者直接摒弃了POOLing,用conv的stride来实现降采样。在这个网络结构中,使用的是步长为2的卷积来进行降采样。为了加强算法对小目标检测的精确度,YOLO v3中采用类似FPN的upsample和融合做法(最后融合了3个scale,其他两个scale的大小分别是26×26和52×52),在多个scale的feature map上做检测。作者在3条预测支路采用的也是全卷积的结构,其中最后一个卷积层的卷积核个数是255,是针对COCO数据集的80类:3*(80+4+1)=255,3表示一个grid cell包含3个bounding box,4表示框的4个坐标信息,1表示objectness score。

    具体的网络结构介绍可以参见:

    https://blog.csdn.net/litt1e/article/details/88907542
    

    model.summary()可以看到整个参数大小

    02

    数据集介绍

    关于安全帽的数据集,可以通过网络爬取,也可以通过其他途径获取,剩下的就是数据打标了,这是一个体力活,具体的打标教程网上也可以找到很多,基本都是LabelImg,具体可以参见:

    https://www.jianshu.com/p/ff99d430150f
    

    我这边使用的数据集是已经打标好了的

    03

    训练集和测试集的制作

    Yolov3使用的数据集格式是遵循VOC数据集的格式,所以需要根据如下目录做好训练集和测试集

    关于两个数据集的目录,可以手工创建,也可以通过脚本来进行创建

    import os
    from shutil import copyfile
    #根据tarin.txt和test.txt将数据集分为标准数据集
    train_text_path = '/home/test/Lewis_Workspace/VOC2028/ImageSets/Main/train.txt'
    test_text_path = '/home/test/Lewis_Workspace/VOC2028/ImageSets/Main/test.txt'
    #图片存放地址
    image_path = '/home/test/Lewis_Workspace/VOC2028/JPEGImages'
    #xml文件存放地址
    xml_path = '/home/test/Lewis_Workspace/VOC2028/Annotations'
    
    
    #输出的目录
    outdir = '/home/test/Lewis_Workspace/VOC2028'
    #创建各级文件夹
    test_xml_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/Annotations')
    os.makedirs(test_xml_out)
    os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/ImageSets/Layout'))
    os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/ImageSets/Main'))
    os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/ImageSets/Segmentation'))
    test_img_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/JPEGImages')
    os.makedirs(test_img_out)
    os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/SegmentationClass'))
    os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2028/SegmentationObject'))
    train_xml_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/Annotations')
    os.makedirs(train_xml_out)
    os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/ImageSets/Layout'))
    os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/ImageSets/Main'))
    os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/ImageSets/Segmentation'))
    train_img_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/JPEGImages')
    os.makedirs(train_img_out)
    os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/SegmentationClass'))
    os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2028/SegmentationObject'))
    
    
    
    
    
    
    with open(train_text_path) as f:
        lines = f.readlines()
        for i in lines:
            img_save_path = os.path.join(train_img_out,i.rstrip('\n')+'.jpg')
            xml_save_path = os.path.join(train_xml_out, i.rstrip('\n') + '.xml')
            copyfile(os.path.join(image_path,i.rstrip('\n')+'.jpg'),img_save_path)
            copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
            print(i)
    with open(test_text_path) as f:
        lines = f.readlines()
        for i in lines:
            img_save_path = os.path.join(test_img_out, i.rstrip('\n') + '.jpg')
            xml_save_path = os.path.join(test_xml_out, i.rstrip('\n') + '.xml')
            copyfile(os.path.join(image_path, i.rstrip('\n') + '.jpg'), img_save_path)
            copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
            print(i)
    
    
    

    然后需要对原始数据集进行分割,可用如下脚本文件split.py

    import os
    import random
    import sys
    if len(sys.argv) < 2:
        print("no directory specified, please input target directory")
        exit()
    root_path = sys.argv[1]
    xmlfilepath = root_path + '/Annotations'
    txtsavepath = root_path + '/ImageSets/Main'
    
    
    if not os.path.exists(root_path):
        print("cannot find such directory: " + root_path)
        exit()
    
    
    if not os.path.exists(txtsavepath):
        os.makedirs(txtsavepath)
    
    
    trainval_percent = 0.9
    train_percent = 0.8
    total_xml = os.listdir(xmlfilepath)
    num = len(total_xml)
    list = range(num)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)
    trainval = random.sample(list, tv)
    train = random.sample(trainval, tr)
    
    
    print("train and val size:", tv)
    print("train size:", tr)
    
    
    ftrainval = open(txtsavepath + '/trainval.txt', 'w')
    ftest = open(txtsavepath + '/test.txt', 'w')
    ftrain = open(txtsavepath + '/train.txt', 'w')
    fval = open(txtsavepath + '/val.txt', 'w')
    
    
    for i in list:
        name = total_xml[i][:-4] + '\n'
        if i in trainval:
            ftrainval.write(name)
            if i in train:
                ftrain.write(name)
            else:
                fval.write(name)
        else:
            ftest.write(name)
    
    
    ftrainval.close()
    ftrain.close()
    fval.close()
    ftest.close()
    
    python split.py /home/test/Lewis_Workspace/VOC2028/VOC/train/VOCdevkit/VOC2028/
    
    python split.py /home/train/Lewis_Workspace/VOC2028/VOC/train/VOCdevkit/VOC2028/
    

    04

    训练

    直接运行train.py

    # -*- coding: utf-8 -*-
    #! /usr/bin/env python
    # coding=utf-8
    import os
    import time
    import shutil
    import numpy as np
    import tensorflow as tf
    import core.utils as utils
    from tqdm import tqdm
    from core.dataset import Dataset
    from core.yolov3 import YOLOv3, decode, compute_loss
    from core.config import cfg
    import logging
    
    
    logging.basicConfig(level=logging.DEBUG,  
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                        datefmt='%a, %d %b %Y %H:%M:%S',  
                        filename='train.log',  
                        filemode='w') 
    
    
    trainset = Dataset('train')
    logdir = "./data/log"
    steps_per_epoch = len(trainset)
    global_steps = tf.Variable(1, trainable=False, dtype=tf.int64)
    warmup_steps = cfg.TRAIN.WARMUP_EPOCHS * steps_per_epoch
    total_steps = cfg.TRAIN.EPOCHS * steps_per_epoch
    
    
    input_tensor = tf.keras.layers.Input([416, 416, 3])
    conv_tensors = YOLOv3(input_tensor)
    
    
    output_tensors = []
    for i, conv_tensor in enumerate(conv_tensors):
        pred_tensor = decode(conv_tensor, i)
        output_tensors.append(conv_tensor)
        output_tensors.append(pred_tensor)
    
    
    model = tf.keras.Model(input_tensor, output_tensors)
    optimizer = tf.keras.optimizers.Adam()
    if os.path.exists(logdir): shutil.rmtree(logdir)
    writer = tf.summary.create_file_writer(logdir)
    
    
    def train_step(image_data, target):
        with tf.GradientTape() as tape:
            pred_result = model(image_data, training=True)
            giou_loss=conf_loss=prob_loss=0
    
    
            # optimizing process
            for i in range(3):
                conv, pred = pred_result[i*2], pred_result[i*2+1]
                loss_items = compute_loss(pred, conv, *target[i], i)
                giou_loss += loss_items[0]
                conf_loss += loss_items[1]
                prob_loss += loss_items[2]
    
    
            total_loss = giou_loss + conf_loss + prob_loss
    
    
            gradients = tape.gradient(total_loss, model.trainable_variables)
            optimizer.apply_gradients(zip(gradients, model.trainable_variables))
            tf.print("=> STEP %4d   lr: %.6f   giou_loss: %4.2f   conf_loss: %4.2f   "
                     "prob_loss: %4.2f   total_loss: %4.2f" %(global_steps, optimizer.lr.numpy(),
                                                              giou_loss, conf_loss,
                                                              prob_loss, total_loss))
                                                              
            logging.info("=> STEP %4d   lr: %.6f   giou_loss: %4.2f   conf_loss: %4.2f   "
                     "prob_loss: %4.2f   total_loss: %4.2f" %(global_steps, optimizer.lr.numpy(),
                                                              giou_loss, conf_loss,
                                                              prob_loss, total_loss))
            # update learning rate
            global_steps.assign_add(1)
            if global_steps < warmup_steps:
                lr = global_steps / warmup_steps *cfg.TRAIN.LR_INIT
            else:
                lr = cfg.TRAIN.LR_END + 0.5 * (cfg.TRAIN.LR_INIT - cfg.TRAIN.LR_END) * (
                    (1 + tf.cos((global_steps - warmup_steps) / (total_steps - warmup_steps) * np.pi))
                )
            optimizer.lr.assign(lr.numpy())
    
    
            # writing summary data
            with writer.as_default():
                tf.summary.scalar("lr", optimizer.lr, step=global_steps)
                tf.summary.scalar("loss/total_loss", total_loss, step=global_steps)
                tf.summary.scalar("loss/giou_loss", giou_loss, step=global_steps)
                tf.summary.scalar("loss/conf_loss", conf_loss, step=global_steps)
                tf.summary.scalar("loss/prob_loss", prob_loss, step=global_steps)
            writer.flush()
    
    
    
    
    
    
    
    
    if __name__ == '__main__':
        for epoch in range(cfg.TRAIN.EPOCHS):
            for image_data, target in trainset:
                train_step(image_data, target)
            model.save_weights("./yolov3")
    
    
    

    下面这个截图是训练到2玩多步的时候的一个loss值

    另外通过tensorboard --logdir ./log查看学习率和各种loss的变化

    05

    测试

    #! /usr/bin/env python
    # coding=utf-8
    import cv2
    import numpy as np
    import core.utils as utils
    import tensorflow as tf
    from core.yolov3 import YOLOv3, decode
    from PIL import Image
    
    
    input_size   = 416
    image_path   = "./docs/000000.jpg"
    
    
    input_layer  = tf.keras.layers.Input([input_size, input_size, 3])
    feature_maps = YOLOv3(input_layer)
    
    
    original_image      = cv2.imread(image_path)
    original_image      = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
    original_image_size = original_image.shape[:2]
    
    
    image_data = utils.image_preporcess(np.copy(original_image), [input_size, input_size])
    image_data = image_data[np.newaxis, ...].astype(np.float32)
    
    
    bbox_tensors = []
    for i, fm in enumerate(feature_maps):
        bbox_tensor = decode(fm, i)
        bbox_tensors.append(bbox_tensor)
    
    
    model = tf.keras.Model(input_layer, bbox_tensors)
    #utils.load_weights(model, "./yolov3.weights")
    model.load_weights("./yolov3")
    model.summary()
    
    
    pred_bbox = model.predict(image_data)
    pred_bbox = [tf.reshape(x, (-1, tf.shape(x)[-1])) for x in pred_bbox]
    pred_bbox = tf.concat(pred_bbox, axis=0)
    bboxes = utils.postprocess_boxes(pred_bbox, original_image_size, input_size, 0.3)
    bboxes = utils.nms(bboxes, 0.45, method='nms')
    
    
    image = utils.draw_bbox(original_image, bboxes)
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
    cv2.imwrite("image_demo_result.jpg",image)
    

    05

    需要注意的问题

    1、如果是在windows上运行,保存weights的时候需要保存为.h5格式,不然无法保存。

    model.save("myolov3.h5")
    

    导入模型

    model.load_weights("myolov3.h5")
    

    2、如果在windows上出现测试的时候无法保存检测框的时候,可以尝试在linux下运行代码,至少现在在linux下还没碰到类似的问题

    3、如果在训练过程中loss值出现nan,可以试着调整学习率的上升速度和下降速度。

    if global_steps < warmup_steps:
        lr = global_steps / warmup_steps *cfg.TRAIN.LR_INIT
    else:
        lr = cfg.TRAIN.LR_END + 0.5 * (cfg.TRAIN.LR_INIT - cfg.TRAIN.LR_END) * (
            (1 + tf.cos((global_steps - warmup_steps) / (total_steps - warmup_steps) * np.pi))
        )
    

    具体可以通过改变warm_up的值,以及学习率的初始值。让学习率的上升速率和下降速度更缓和一点。

    4、关于为什么要使用warm_up

    由于刚开始训练时,模型的权重(weights)是随机初始化的,此时若选择一个较大的学习率,可能带来模型的不稳定(振荡),选择Warmup预热学习率的方式,可以使得开始训练的几个epoches或者一些steps内学习率较小,在预热的小学习率下,模型可以慢慢趋于稳定,等模型相对稳定后再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。

    在Residul NetWork训练中https://arxiv.org/abs/1512.03385,有提到这样一段话

    然后在transformer的一篇论文https://arxiv.org/abs/1706.03762中也有提到:

    根据上面的公式进行图像展示,可以发现学习率是先上升后下降的

    如果各位想具体了解学习率warm-up的作用,可以详见这篇论文

    https://arxiv.org/abs/1908.03265

    听说关注公众号的都是大牛

    展开全文
  • YoloV5训练安全帽检测并部署在安卓上 一.Requirements 本教程使用的环境:u版yolov5,源码下载地址: PyTorch:1.8.0 Cuda:10.2 Python:3.8 官方要求:Python>=3.6.0 is required with all requirements.txt ...

    YoloV5训练安全帽检测并部署在安卓上

    一.Requirements

    本教程使用的环境:u版yolov5,源码下载地址:

    yolov5

    PyTorch:1.8.0

    Cuda:10.2

    Python:3.8

    官方要求:Python>=3.6.0 is required with all requirements.txt installed including PyTorch>=1.7

    git clone https://github.com/ultralytics/yolov5
    cd yolov5
    pip install -r requirements.txt
    

    二.准备好自己的数据集(VOC格式)

    1.在yolov5目录下创建helmet_data文件夹(改名字根据具体项目自定义),目录结构如下,将使用labelImg标注好的xml文件和图片放到对应目录下

    helmet_data

    在这里插入图片描述

    Annotations #存放图片对应的xml文件

    images #存放图片

    ImageSets/Main #之后会在Main文件夹中生成test.txt、train.txt、trainval.txt和val.txt四个文件,分别存放测试集、训练集、验证集图片的名字

    示例如下:

    Annotations文件夹下面为xml文件(标注工具采用labelImg),内容如下:
    在这里插入图片描述
    images为jgp图片:

    在这里插入图片描述

    ImageSets文件夹下面有个Main子文件夹,其下面存放训练集、验证集、测试集的划分,通过脚本生成,在helmet_data下创建split_train_val.py文件,代码如下:

    # coding:utf-8
    
    import os
    import random
    import argparse
    
    parser = argparse.ArgumentParser()
    #xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
    parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
    #数据集的划分,地址选择自己数据下的ImageSets/Main
    parser.add_argument('--txt_path', default='ImageSets/Main', type=str, help='output txt label path')
    opt = parser.parse_args()
    
    trainval_percent = 1.0
    train_percent = 0.9
    xmlfilepath = opt.xml_path
    txtsavepath = opt.txt_path
    total_xml = os.listdir(xmlfilepath)
    if not os.path.exists(txtsavepath):
        os.makedirs(txtsavepath)
    
    num = len(total_xml)
    list_index = range(num)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)
    trainval = random.sample(list_index, tv)
    train = random.sample(trainval, tr)
    
    file_trainval = open(txtsavepath + '/trainval.txt', 'w')
    file_test = open(txtsavepath + '/test.txt', 'w')
    file_train = open(txtsavepath + '/train.txt', 'w')
    file_val = open(txtsavepath + '/val.txt', 'w')
    
    for i in list_index:
        name = total_xml[i][:-4] + '\n'
        if i in trainval:
            file_trainval.write(name)
            if i in train:
                file_train.write(name)
            else:
                file_val.write(name)
        else:
            file_test.write(name)
    
    file_trainval.close()
    file_train.close()
    file_val.close()
    file_test.close()
    
    
    

    运行之后在ImageSets\Mian下会生成下面四个txt文档:

    在这里插入图片描述

    2.接下来准备labels,吧数据集格式转换成yolo_txt格式,即将每个xml标注提取BoundingBox信息为txt格式,每个图像对应一个txt文件,文件内容为,class、x_center、y_center、width、height。格式如下:

    在这里插入图片描述

    在yolov5文件夹下创建voc_label.py文件,将训练集、验证集、测试集生成label标签,同时将数据集路径导入txt文件中,代码内容如下:

    # -*- coding: utf-8 -*-
    import xml.etree.ElementTree as ET
    import os
    from os import getcwd
    
    sets = ['train', 'val', 'test']
    classes = ["helmet"]   # 改成自己的类别
    abs_path = os.getcwd()
    print(abs_path)
    
    def convert(size, box):
        dw = 1. / (size[0])
        dh = 1. / (size[1])
        x = (box[0] + box[1]) / 2.0 - 1
        y = (box[2] + box[3]) / 2.0 - 1
        w = box[1] - box[0]
        h = box[3] - box[2]
        x = x * dw
        w = w * dw
        y = y * dh
        h = h * dh
        return x, y, w, h
    
    def convert_annotation(image_id):
        #Annotations文件夹路径
        in_file = open('E:\\yolov5-master\\yolov5-master\\helmet_data\\Annotations\\%s.xml' % (image_id), encoding='UTF-8')
        #labels文件夹路径
        out_file = open('E:\\yolov5-master\\yolov5-master\\helmet_data\\labels\\%s.txt' % (image_id), 'w')
        tree = ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)
        for obj in root.iter('object'):
            # difficult = obj.find('difficult').text
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in classes or int(difficult) == 1:
                continue
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            b1, b2, b3, b4 = b
            # 标注越界修正
            if b2 > w:
                b2 = w
            if b4 > h:
                b4 = h
            b = (b1, b2, b3, b4)
            bb = convert((w, h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    
    wd = getcwd()
    for image_set in sets:
        if not os.path.exists('E:\\yolov5-master\\yolov5-master\\helmet_data\\labels\\'):
            os.makedirs('E:\\yolov5-master\\yolov5-master\\helmet_data\\labels\\')
        #Main路径
        image_ids = open('E:\\yolov5-master\\yolov5-master\\helmet_data\\ImageSets\\Main\\%s.txt' % (image_set)).read().strip().split()
        list_file = open('helmet_data\\%s.txt' % (image_set), 'w')
        for image_id in image_ids:
            list_file.write(abs_path + '\\helmet_data\\images\\%s.jpg\n' % (image_id))
            convert_annotation(image_id)
        list_file.close()
    
    
    

    运行后会在labels中生成如下文件:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0zdlUKnL-1636952968895)(/Users/zhou/Desktop/yolov5/YoloV5训练安全帽检测并部署在安卓上.assets/9358FA382185E3DF5E2DD2294694F027-6893893.png)]

    该文件即为yolo_txt格式的label文件。并且在helmet_data中生成train、test、val的路径文件。如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K7gyDgtP-1636952968895)(/Users/zhou/Desktop/yolov5/YoloV5训练安全帽检测并部署在安卓上.assets/AC3F67AA4F8226AC8E0F7C3CB5CAD903-6894056.png)]

    这三个文件保存的是图片的绝对路径:

    在这里插入图片描述

    3.配置文件

    在yolov5目录下的data文件夹下新建helmet.yaml文件(根据项目自定义名字),用来存放训练集和验证集的划分文件(train.txt和val.txt),这两个文件是通过voc_label.py 生成的,然后设定目标的类别数目和具体类别列表,helmet_data内容如下:

    在这里插入图片描述

    ⚠️:***train:***与路径之间有个空格

    ⚠️:***val:***与路径之间有个空格

    4.选取模型

    在yolov5目录下的model文件夹下是模型的配置文件,官方提供s、m、l、x版本,逐渐增大,此处因为要部署在安卓端,因此采用最小的模型yolov5s.yaml,这里只需修改nc这一个参数,把nc修改成类别数,我们此处只有一个类别因此nc为1。在这里插入图片描述

    三.模型训练

    1、yolov5源码中提供了4中预下载模型,在weights文件夹下。weights的下载可能由于网络原因而难以进行,可以去找百度网盘中的预训练模型。

    2、训练

    在train.py中作一下修改:
    在这里插入图片描述

    参数解释:

    epochs:指的是训练过程中整个数据集将会迭代多少次,显卡性能差的调小一点

    batch-size:进行权重更新的图片数,显卡性能差的适当调小

    cfg:存储模型结构的配置文件

    data:存储训练、测试数据的文件

    img-size:输入的图片的宽高,显卡性能差的适当调小

    rect:进行矩形训练

    resume:使用最近保存的模型开始训练,默认为false,即重新训练

    nosave:仅保存最终的checkpoint

    notest:仅测试最后的epoch

    cache:存图片以加快训练

    weights:权重文件路径

    name:保存的文件名

    device:cuda device,i.e. 0 or 0,1,2,3 or cpu

    adam:使用adam优化

    multi-scale:多尺度训练,image-size +/-50%

    single-cls:单类别的训练集

    运行训练命令:

    python train.py --img 640 --batch 16 --epoch 300 --data data/helmet.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt --device 0
    

    3.训练过程可视化

    利用tensorboard可视化训练过程训练开始会在yolov5目录下生成一个runs文件夹保存着训练日志,查看命令如下:

    tensorboard --logdir=runs
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    至此,已经完成了模型的训练。

    四.模型测试

    评估模型的好坏就是在有标注的测试集或验证集上进行模型效果的评估,在目标检测中最常用的评估指标为mAP。在val.py文件中指定数据集配置文件。

    在这里插入图片描述

    通过下面的命令进行模型测试:

    python val.py --data data/helmet.yaml --weights runs/train/exp16/weights/best.pt --	augment
    

    模型测试结果如下:

    在这里插入图片描述

    五.模型推理

    将模型在没有标注的数据集上进行推理,在detect.py中指定测试图片和测试模型的路径,其中weights使用最满意的训练模型即可,source则提供一个包含所有测试图片的文件夹路径即可。

    python detect.py --weights runs/train/exp16/weights/best.pt --source data/images/ --device 0
    

    测试完毕后,会输出标有boundingbox的图片

    在这里插入图片描述

    六.模型导出

    我们需要将安全帽检测部署到安卓端,安卓端采用ncnn进行推理,这里需要先将模型转化成onnx然后在转换成ncnn所需的模型。

    在这里插入图片描述

    python export.py --weights runs/trains/exp16/weight/best.pt --include onnx --img 640 --batch 1
    

    这里命令中一定要使用train模式,否则在模型转换后会出现MemoryData。

    模型转换后使用onnxsim进行简化

    python -m onnxsim best.onnx best-sim.onnx
    

    在这里插入图片描述

    提示这个说明简化成功。

    七.模型转化

    使用onnx2ncnn进行模型转化

    ./onnx2ncnn best-sim.onnx best-sim.param best-sim.bin
    

    在这里插入图片描述

    转换为 ncnn 模型,会输出很多 Unsupported slice step,这是focus模块转换的报错

    打开param文件,使用自定义的YoloV5Focus层替代

    在这里插入图片描述

    修改后

    在这里插入图片描述

    替换后使用ncnnoptimize 过一遍模型,缩小模型体积

    ./ncnnoptimize best-sim.param best-sim.bin best-opt.param best-opt.bin
    

    至此已经完成模型的转化,可以部署至安卓端。

    八.安卓端部署

    新建一个Android Native Library
    在这里插入图片描述

    根据ncnn部署的方式将ncnn部署好

    以下代码为对应的java接口代码

    
    import android.content.res.AssetManager;
    import android.graphics.Bitmap;
    
    public class YoloV5Ncnn
    {
        private static YoloV5Ncnn instance;
        private YoloV5Ncnn(){
            System.out.println("YoloV5Ncnn has loaded");
        }
        public static YoloV5Ncnn getInstance(){
            if(instance==null){
                synchronized (YoloV5Ncnn.class){
                    if(instance==null){
                        instance=new YoloV5Ncnn();
                    }
                }
            }
            return instance;
        }
    
        public native boolean Init(AssetManager mgr);
    
        public class Obj
        {
            public float x;
            public float y;
            public float w;
            public float h;
            public String label;
            public float prob;
        }
    
        public native Obj[] Detect(Bitmap bitmap, boolean use_gpu);
    
        static {
            System.loadLibrary("native-lib");
        }
    }
    
    
    

    对应的cpp代码为

    //
    // Created by 45467 on 2021/10/12.
    //
    
    #include <android/asset_manager_jni.h>
    #include <android/bitmap.h>
    #include <android/log.h>
    
    #include <jni.h>
    
    #include <string>
    #include <vector>
    
    // ncnn
    #include "layer.h"
    #include "net.h"
    #include "benchmark.h"
    #include <jni.h>
    
    static ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
    static ncnn::PoolAllocator g_workspace_pool_allocator;
    
    static ncnn::Net yolov5;
    
    class YoloV5Focus : public ncnn::Layer
    {
    public:
        YoloV5Focus()
        {
            one_blob_only = true;
        }
    
        virtual int forward(const ncnn::Mat& bottom_blob, ncnn::Mat& top_blob, const ncnn::Option& opt) const
        {
            int w = bottom_blob.w;
            int h = bottom_blob.h;
            int channels = bottom_blob.c;
    
            int outw = w / 2;
            int outh = h / 2;
            int outc = channels * 4;
    
            top_blob.create(outw, outh, outc, 4u, 1, opt.blob_allocator);
            if (top_blob.empty())
                return -100;
    
    #pragma omp parallel for num_threads(opt.num_threads)
            for (int p = 0; p < outc; p++)
            {
                const float* ptr = bottom_blob.channel(p % channels).row((p / channels) % 2) + ((p / channels) / 2);
                float* outptr = top_blob.channel(p);
    
                for (int i = 0; i < outh; i++)
                {
                    for (int j = 0; j < outw; j++)
                    {
                        *outptr = *ptr;
    
                        outptr += 1;
                        ptr += 2;
                    }
    
                    ptr += w;
                }
            }
    
            return 0;
        }
    };
    
    DEFINE_LAYER_CREATOR(YoloV5Focus)
    
    struct Object
    {
        float x;
        float y;
        float w;
        float h;
        int label;
        float prob;
    };
    
    static inline float intersection_area(const Object& a, const Object& b)
    {
        if (a.x > b.x + b.w || a.x + a.w < b.x || a.y > b.y + b.h || a.y + a.h < b.y)
        {
            // no intersection
            return 0.f;
        }
    
        float inter_width = std::min(a.x + a.w, b.x + b.w) - std::max(a.x, b.x);
        float inter_height = std::min(a.y + a.h, b.y + b.h) - std::max(a.y, b.y);
    
        return inter_width * inter_height;
    }
    
    static void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)
    {
        int i = left;
        int j = right;
        float p = faceobjects[(left + right) / 2].prob;
    
        while (i <= j)
        {
            while (faceobjects[i].prob > p)
                i++;
    
            while (faceobjects[j].prob < p)
                j--;
    
            if (i <= j)
            {
                // swap
                std::swap(faceobjects[i], faceobjects[j]);
    
                i++;
                j--;
            }
        }
    
    #pragma omp parallel sections
        {
    #pragma omp section
            {
                if (left < j) qsort_descent_inplace(faceobjects, left, j);
            }
    #pragma omp section
            {
                if (i < right) qsort_descent_inplace(faceobjects, i, right);
            }
        }
    }
    
    static void qsort_descent_inplace(std::vector<Object>& faceobjects)
    {
        if (faceobjects.empty())
            return;
    
        qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1);
    }
    
    static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold)
    {
        picked.clear();
    
        const int n = faceobjects.size();
    
        std::vector<float> areas(n);
        for (int i = 0; i < n; i++)
        {
            areas[i] = faceobjects[i].w * faceobjects[i].h;
        }
    
        for (int i = 0; i < n; i++)
        {
            const Object& a = faceobjects[i];
    
            int keep = 1;
            for (int j = 0; j < (int)picked.size(); j++)
            {
                const Object& b = faceobjects[picked[j]];
    
                // intersection over union
                float inter_area = intersection_area(a, b);
                float union_area = areas[i] + areas[picked[j]] - inter_area;
                // float IoU = inter_area / union_area
                if (inter_area / union_area > nms_threshold)
                    keep = 0;
            }
    
            if (keep)
                picked.push_back(i);
        }
    }
    
    static inline float sigmoid(float x)
    {
        return static_cast<float>(1.f / (1.f + exp(-x)));
    }
    
    static void generate_proposals(const ncnn::Mat& anchors, int stride, const ncnn::Mat& in_pad, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
    {
        const int num_grid = feat_blob.h;
    
        int num_grid_x;
        int num_grid_y;
        if (in_pad.w > in_pad.h)
        {
            num_grid_x = in_pad.w / stride;
            num_grid_y = num_grid / num_grid_x;
        }
        else
        {
            num_grid_y = in_pad.h / stride;
            num_grid_x = num_grid / num_grid_y;
        }
    
        const int num_class = feat_blob.w - 5;
    
        const int num_anchors = anchors.w / 2;
    
        for (int q = 0; q < num_anchors; q++)
        {
            const float anchor_w = anchors[q * 2];
            const float anchor_h = anchors[q * 2 + 1];
    
            const ncnn::Mat feat = feat_blob.channel(q);
    
            for (int i = 0; i < num_grid_y; i++)
            {
                for (int j = 0; j < num_grid_x; j++)
                {
                    const float* featptr = feat.row(i * num_grid_x + j);
    
                    // find class index with max class score
                    int class_index = 0;
                    float class_score = -FLT_MAX;
                    for (int k = 0; k < num_class; k++)
                    {
                        float score = featptr[5 + k];
                        if (score > class_score)
                        {
                            class_index = k;
                            class_score = score;
                        }
                    }
    
                    float box_score = featptr[4];
    
                    float confidence = sigmoid(box_score) * sigmoid(class_score);
    
                    if (confidence >= prob_threshold)
                    {
                        // yolov5/models/yolo.py Detect forward
                        // y = x[i].sigmoid()
                        // y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i].to(x[i].device)) * self.stride[i]  # xy
                        // y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]  # wh
    
                        float dx = sigmoid(featptr[0]);
                        float dy = sigmoid(featptr[1]);
                        float dw = sigmoid(featptr[2]);
                        float dh = sigmoid(featptr[3]);
    
                        float pb_cx = (dx * 2.f - 0.5f + j) * stride;
                        float pb_cy = (dy * 2.f - 0.5f + i) * stride;
    
                        float pb_w = pow(dw * 2.f, 2) * anchor_w;
                        float pb_h = pow(dh * 2.f, 2) * anchor_h;
    
                        float x0 = pb_cx - pb_w * 0.5f;
                        float y0 = pb_cy - pb_h * 0.5f;
                        float x1 = pb_cx + pb_w * 0.5f;
                        float y1 = pb_cy + pb_h * 0.5f;
    
                        Object obj;
                        obj.x = x0;
                        obj.y = y0;
                        obj.w = x1 - x0;
                        obj.h = y1 - y0;
                        obj.label = class_index;
                        obj.prob = confidence;
    
                        objects.push_back(obj);
                    }
                }
            }
        }
    }
    
    extern "C" {
    
    // FIXME DeleteGlobalRef is missing for objCls
    static jclass objCls = NULL;
    static jmethodID constructortorId;
    static jfieldID xId;
    static jfieldID yId;
    static jfieldID wId;
    static jfieldID hId;
    static jfieldID labelId;
    static jfieldID probId;
    
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
    {
    __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "JNI_OnLoad");
    
    ncnn::create_gpu_instance();
    
    return JNI_VERSION_1_4;
    }
    
    JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "JNI_OnUnload");
    
        ncnn::destroy_gpu_instance();
    }
    
    // public native boolean Init(AssetManager mgr);
    
    JNIEXPORT jboolean JNICALL
    Java_com_luo_face_YoloV5Ncnn_Init(JNIEnv *env, jobject thiz, jobject assetManager) {
        ncnn::Option opt;
        opt.lightmode = true;
        opt.num_threads = 4;
        opt.blob_allocator = &g_blob_pool_allocator;
        opt.workspace_allocator = &g_workspace_pool_allocator;
        opt.use_packing_layout = true;
    
        // use vulkan compute
        if (ncnn::get_gpu_count() != 0)
            opt.use_vulkan_compute = true;
    
        AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
    
        yolov5.opt = opt;
    
        yolov5.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);
    
        // init param
        {
            int ret = yolov5.load_param(mgr, "helmet-opt.param");
            if (ret != 0)
            {
                __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "load_param failed");
                return JNI_FALSE;
            }
        }
    
        // init bin
        {
            int ret = yolov5.load_model(mgr, "helmet-opt.bin");
            if (ret != 0)
            {
                __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "load_model failed");
                return JNI_FALSE;
            }
        }
    
        // init jni glue
        jclass localObjCls = env->FindClass("com/luo/face/YoloV5Ncnn$Obj");
        objCls = reinterpret_cast<jclass>(env->NewGlobalRef(localObjCls));
    
        constructortorId = env->GetMethodID(objCls, "<init>", "(Lcom/luo/face/YoloV5Ncnn;)V");
    
        xId = env->GetFieldID(objCls, "x", "F");
        yId = env->GetFieldID(objCls, "y", "F");
        wId = env->GetFieldID(objCls, "w", "F");
        hId = env->GetFieldID(objCls, "h", "F");
        labelId = env->GetFieldID(objCls, "label", "Ljava/lang/String;");
        probId = env->GetFieldID(objCls, "prob", "F");
    
        return JNI_TRUE;
    }
    
    JNIEXPORT jobjectArray JNICALL
    Java_com_luo_face_YoloV5Ncnn_Detect(JNIEnv *env, jobject thiz, jobject bitmap, jboolean use_gpu) {
        // TODO: implement Detect()
        if (use_gpu == JNI_TRUE && ncnn::get_gpu_count() == 0)
        {
            return NULL;
            //return env->NewStringUTF("no vulkan capable gpu");
        }
    
        double start_time = ncnn::get_current_time();
    
        AndroidBitmapInfo info;
        AndroidBitmap_getInfo(env, bitmap, &info);
        const int width = info.width;
        const int height = info.height;
        if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
            return NULL;
    
        // ncnn from bitmap
        const int target_size = 640;
    
        // letterbox pad to multiple of 32
        int w = width;
        int h = height;
        float scale = 1.f;
        if (w > h)
        {
            scale = (float)target_size / w;
            w = target_size;
            h = h * scale;
        }
        else
        {
            scale = (float)target_size / h;
            h = target_size;
            w = w * scale;
        }
    
        ncnn::Mat in = ncnn::Mat::from_android_bitmap_resize(env, bitmap, ncnn::Mat::PIXEL_RGB, w, h);
    
        // pad to target_size rectangle
        // yolov5/utils/datasets.py letterbox
        int wpad = (w + 31) / 32 * 32 - w;
        int hpad = (h + 31) / 32 * 32 - h;
        ncnn::Mat in_pad;
        ncnn::copy_make_border(in, in_pad, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, ncnn::BORDER_CONSTANT, 114.f);
    
        // yolov5
        std::vector<Object> objects;
        {
            const float prob_threshold = 0.25f;
            const float nms_threshold = 0.45f;
    
            const float norm_vals[3] = {1 / 255.f, 1 / 255.f, 1 / 255.f};
            in_pad.substract_mean_normalize(0, norm_vals);
    
            ncnn::Extractor ex = yolov5.create_extractor();
    
            ex.set_vulkan_compute(use_gpu);
    
            ex.input("images", in_pad);
    
            std::vector<Object> proposals;
    
            // anchor setting from yolov5/models/yolov5s.yaml
    
            // stride 8
            {
                ncnn::Mat out;
                ex.extract("output", out);
    
                ncnn::Mat anchors(6);
                anchors[0] = 10.f;
                anchors[1] = 13.f;
                anchors[2] = 16.f;
                anchors[3] = 30.f;
                anchors[4] = 33.f;
                anchors[5] = 23.f;
    
                std::vector<Object> objects8;
                generate_proposals(anchors, 8, in_pad, out, prob_threshold, objects8);
    
                proposals.insert(proposals.end(), objects8.begin(), objects8.end());
            }
    
            // stride 16
            {
                ncnn::Mat out;
                ex.extract("427", out);
    
                ncnn::Mat anchors(6);
                anchors[0] = 30.f;
                anchors[1] = 61.f;
                anchors[2] = 62.f;
                anchors[3] = 45.f;
                anchors[4] = 59.f;
                anchors[5] = 119.f;
    
                std::vector<Object> objects16;
                generate_proposals(anchors, 16, in_pad, out, prob_threshold, objects16);
    
                proposals.insert(proposals.end(), objects16.begin(), objects16.end());
            }
    
            // stride 32
            {
                ncnn::Mat out;
                ex.extract("452", out);
    
                ncnn::Mat anchors(6);
                anchors[0] = 116.f;
                anchors[1] = 90.f;
                anchors[2] = 156.f;
                anchors[3] = 198.f;
                anchors[4] = 373.f;
                anchors[5] = 326.f;
    
                std::vector<Object> objects32;
                generate_proposals(anchors, 32, in_pad, out, prob_threshold, objects32);
    
                proposals.insert(proposals.end(), objects32.begin(), objects32.end());
            }
    
            // sort all proposals by score from highest to lowest
            qsort_descent_inplace(proposals);
    
            // apply nms with nms_threshold
            std::vector<int> picked;
            nms_sorted_bboxes(proposals, picked, nms_threshold);
    
            int count = picked.size();
    
            objects.resize(count);
            for (int i = 0; i < count; i++)
            {
                objects[i] = proposals[picked[i]];
    
                // adjust offset to original unpadded
                float x0 = (objects[i].x - (wpad / 2)) / scale;
                float y0 = (objects[i].y - (hpad / 2)) / scale;
                float x1 = (objects[i].x + objects[i].w - (wpad / 2)) / scale;
                float y1 = (objects[i].y + objects[i].h - (hpad / 2)) / scale;
    
                // clip
                x0 = std::max(std::min(x0, (float)(width - 1)), 0.f);
                y0 = std::max(std::min(y0, (float)(height - 1)), 0.f);
                x1 = std::max(std::min(x1, (float)(width - 1)), 0.f);
                y1 = std::max(std::min(y1, (float)(height - 1)), 0.f);
    
                objects[i].x = x0;
                objects[i].y = y0;
                objects[i].w = x1 - x0;
                objects[i].h = y1 - y0;
            }
        }
    
        // objects to Obj[]
        static const char* class_names[] = {"helmet"
    
        };
    
        jobjectArray jObjArray = env->NewObjectArray(objects.size(), objCls, NULL);
    
        for (size_t i=0; i<objects.size(); i++)
        {
            jobject jObj = env->NewObject(objCls, constructortorId, thiz);
    
            env->SetFloatField(jObj, xId, objects[i].x);
            env->SetFloatField(jObj, yId, objects[i].y);
            env->SetFloatField(jObj, wId, objects[i].w);
            env->SetFloatField(jObj, hId, objects[i].h);
            env->SetObjectField(jObj, labelId, env->NewStringUTF(class_names[objects[i].label]));
            env->SetFloatField(jObj, probId, objects[i].prob);
    
            env->SetObjectArrayElement(jObjArray, i, jObj);
        }
    
        double elasped = ncnn::get_current_time() - start_time;
        __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "%.2fms   detect", elasped);
    
        return jObjArray;
    }
    
    }
    

    此时我们需要修改下param文件中的输出

    在这里插入图片描述

    修改为:

    在这里插入图片描述

    对应的代码部分也需要作相应的修改

    在这里插入图片描述

    对应于:

    在这里插入图片描述

    在这里插入图片描述

    对应于:

    在这里插入图片描述

    在这里插入图片描述

    对应于:

    在这里插入图片描述

    还需修改对应的类名(按照需求更改为自己的类名)

    在这里插入图片描述

    此处只有helmet一个类。

    最后获取安全帽的置信度

    在这里插入图片描述

    至此,安全帽检测的已经完成了在安卓端的部署。

    感谢章某煜以及潘某怡同学帮忙制作的数据集。
    工地安全帽数据集已有一万多张,需要的请留言。

    展开全文
  • 数据集包含了工人的安全帽场景,适用于安全帽检测,数据已标注txt格式。 数据包含三个标注类别,head、person和Hard Hat。
  • 施冮场景图像描述的硏究较为匮乏,针对该问题,提出采用YωLOv3( You Only Look Once)的检测算法,以及基于语义规则和语勺模板相结合的方法递进式地生成安全帽佩戴的描述语句。首先,采集数据,制作安全帽佩戴检测...
  • 安全帽检测方法 我们中多少人曾经说过以下话: “我希望这行得通!” ? 毫无疑问,我们大多数人可能会不止一次。 这不是一个鼓舞人心的短语,因为它揭示了人们对我们的能力或所测试的功能的怀疑。 不幸的是,这句...

    安全帽检测方法

    我们中多少人曾经说过以下话: “我希望这行得通!”

    毫无疑问,我们大多数人可能会不止一次。 这不是一个鼓舞人心的短语,因为它揭示了人们对我们的能力或所测试的功能的怀疑。 不幸的是,这句话很好地定义了我们的传统安全模型。 我们基于这样的假设并希望我们采取的控制措施(从Web应用程序的漏洞扫描到端点上的防病毒),防止恶意行为者和软件进入我们的系统并破坏或窃取我们的信息。

    渗透测试通过主动尝试闯入网络,将恶意代码注入Web应用程序或通过发送网络钓鱼电子邮件来传播“恶意软件”,从而迈出了消除依赖假设的一步。 笔测试由在我们不同的安全层中查找和戳出Kong组成,因此无法考虑主动打开Kong的情况。 在安全性实验中,我们故意以受控的模拟事件行为的形式制造混乱,以客观地衡量我们检测和阻止此类活动的能力。

    “安全性实验为分布式系统的安全性实验提供了一种方法,以建立对抵御恶意条件的能力的信心。”

    当涉及到安全性和复杂的分布式系统时,混乱的工程界普遍认为“希望不是一种有效的策略”。 我们多久会主动检测我们设计或构建的内容,以确定控件是否失败? 大多数组织都不会发现他们的安全控制失败,直到该失败导致安全事件。 我们认为,“安全事件不是侦探措施”和“希望不是有效策略”应该是IT专业人员采取有效安全措施的口头禅。

    在现代分布式系统中,所有这些不断变化的无状态变量使人们几乎无法充分了解其系统的行为,因为这可能会随时变化。 解决此问题的一种方法是通过强大的系统仪表和监视。 为了进行安全性检测,您可以将域划分为两个主要的存储段: 测试和我们称为实验 。 测试是对先前已知结果的确认或评估。 简而言之,我们在寻找之前就知道了要寻找的东西。 另一方面,实验试图获得以前未知的新见解和信息。 尽管测试是成熟的安全团队的重要做法,但以下示例应有助于进一步阐明两者之间的差异,并对测试的附加值进行更具体的描述。

    示例场景:精酿啤酒交付

    考虑一个简单的Web服务或Web应用程序,该服务接受精酿啤酒交付的订单。

    对于这家精酿啤酒配送公司而言,这是一项至关重要的服务,该公司的订单来自客户的移动设备,网络以及通过其API来提供精酿啤酒的餐厅。 此关键服务在公司的AWS EC2环境中运行,并被公司认为是安全的。 该公司去年成功通过了PCI认证,并每年进行第三方渗透测试,因此假定其系统是安全的。

    该公司还为自己的DevOps和持续交付实践而感到自豪,有时会在一天之内部署两次。

    在了解了混乱的工程和安全性实验之后,该公司的开发团队希望连续确定其安全性系统对现实事件的恢复力和有效性,并确保它们不会将新问题引入到安全性中。安全控件无法检测到的系统。

    该团队希望从评估端口安全性和防火墙配置的能力入手,以检测,阻止和警告EC2安全组中端口配置的错误配置更改。

    • 该团队首先对他们对正常状态的假设进行总结。
    • 为他们的EC2实例中的端口安全性提出假设
    • 为未经授权的端口更改实验选择并配置YAML文件。
    • 此配置将指定要从中随机选择的目标,以及端口范围和应更改的端口数。
    • 该团队还配置了运行实验的时间,并缩小了爆炸半径的范围,以确保对业务的影响最小。
    • 对于第一个测试,团队选择在其阶段环境中运行实验,然后运行一次测试。
    • 在真正的比赛日风格中,团队选择了灾难大师,在预定的两个小时内运行实验。 在该时间段内,灾难管理员将在EC2实例安全组之一上执行实验。
    • 比赛日结束后,团队将开始进行彻底,无罪的验尸练习,重点是针对稳态和原始假设的实验结果。 问题将类似于以下内容:

    验尸问题

    • 防火墙是否检测到未经授权的端口更改?
    • 如果检测到更改,是否阻止了该更改?
    • 防火墙是否向日志聚合工具报告了有用的信息?
    • SIEM是否对未授权的更改发出警报?
    • 如果防火墙没有检测到更改,配置管理工具是否发现了更改?
    • 配置管理工具是否向日志聚合工具报告了良好的信息?
    • SIEM最终是否与警报关联?
    • 如果SIEM发出警报,安全运营中心是否收到警报?
    • 收到警报的SOC分析员是否能够对警报采取措施,还是缺少必要的信息?
    • 如果SOC警报确定警报是可信的,安全事件响应是否能够轻松地从数据中进行分类活动?

    对系统故障的认识和预期已经开始打破我们对系统工作方式的假设。 我们的使命是利用我们所学到的知识,并将其广泛应用,以开始积极主动地解决安全漏洞,超越目前在传统安全模型中占主导地位的被动流程。

    随着我们继续探索这个新领域,我们一定会发布我们的发现。 对于那些有兴趣了解更多有关研究或参与的人,请随时与Aaron RinehartGrayson Brewer联系

    特别感谢Samuel Roden在本文中提供的见解和想法。


    [请参阅我们的相关故事, 术语DevSecOps是否必要? ]

    翻译自: https://opensource.com/article/18/4/new-approach-security-instrumentation

    安全帽检测方法

    展开全文
  • 2018年为了参加中软杯比赛做的小项目,使用深度学习SSD算法框出安全帽和工人的位置,检测工地工人是否佩戴安全帽。环境为Tensorflow+PyQt,还用了SqlServer存储结果(因为麻烦没传,不影响正常运行)。
  • 19年做的毕业设计,用VS+opencv平台编写,基于机器学习的方法实现,融合动态检测、行人检测等算法进行实现,采用HOG+SVM,Haar+adaboost分类器级联实现安全帽的佩戴检测。 交流学习请添加QQ:1049122119 ...
  • 安全帽识别,安全帽检测yolo可以检测图片,视频流,有界面python识别率99% 效果图: 效果视频: 项目代码下载: 链接:https://pan.baidu.com/s/1CpcDb1LHpF84svV66blJSw 提取码:86sq 复制这段内容后...
  • 用darknet(yolo)进行安全帽检测流程

    千次阅读 热门讨论 2020-05-08 12:15:44
    应首先确保电脑中安装了CUDA,并且Makefile文件中前五行应该是 GPU=1 CUDNN=1 OPENCV=0 OPENMP=0 DEBUG=0 然后在darknet目录下进行编译 make 下载数据集 安全帽数据集 提取码:5td8 解压文件(在当前文件夹下): ...
  • 安全帽检测SDK 安全帽检测。 支持类别: safe unsafe SDK功能 安全帽检测,给出检测框和置信度 三个模型: 小模型(mobilenet0.25) 中模型(mobilenet1.0) 大模型(darknet53) 运行小模型例子 - ...
  • 基于深度学习的安全帽...安全帽检测 安全帽分类 yolo安全帽识别 yolo安全帽 tiny yolo安全帽识别 安卓安全帽识别 c++安全帽识别 源码交流加 w x deeplearning_gogogo 效果很棒,不服来战 换不多说,奉上效果图 ...
  • 基于MATLAB的安全帽检测系统 二、课题介绍 众所周知,在一些施工工地,必须明确佩戴安全帽。可以对生命安全起到保障作用。该课题为常见的安全帽的识别,主要分为红色,蓝色,黄色三类安全帽。而安全帽的主要是红色,...
  • 今天给大家分享的是百度大脑智能监控安全帽检测系统。该系统可对进入施工区域内的工人是否佩戴安全帽进行快速检测,具有高于96%识别准确率,极大降低人力监督成本,并可实时自动报警,下面我们一起来看具体详情! ...
  • Ubuntu+YOLOV3+安全帽检测 今天是2020年上半年最后一天,这是我的第一篇博客, 以前都是把一些思考、问题记录在微信上,觉得还是不太方便,从今后开始就记录在这里吧。 背景介绍 1.为了检测安全帽,数据集大考试...
  • 参考资料1:开源一个安全帽佩戴检测数据集及预训练模型 - supersayajin - 博客园 (cnblogs.com) 参考资料2:njvisionpower/Safety-Helmet-Wearing-Dataset: Safety helmet wearing detect dataset, with pretrained...
  • 基于深度学习的安全帽检测方法研究.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,677
精华内容 3,870
关键字:

安全帽检测

友情链接: mimo_ofdm.rar