EfficientDet训练自己的数据集实现抽烟检测

本文详细介绍使用EfficientDet对抽烟行为进行检测的过程,包括环境配置、数据集处理、网络结构解析及训练测试步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈哈,我又来了!!! 再次立下flag,开学之后还是要保持更新频率!!!

本次用efficientdet来对抽烟检测,检测出是否抽烟。那么,老规矩,先上结果图!!!

那么,接下来,还是原先一套流程。走起!!!

一、环境配置

  • python==3.7.4
  • tensorflow-gpu==1.14.0
  • keras==2.2.4
  • numpy==1.17.4

本次,在租的gpu的机器上的。没办法,efficientnet这个网络占据显存太大了。本次机器带不动呀。

二、抽烟数据集

本次数据集是用labelme标注的,提供的json格式的数据集,但本次我们的voc格式的xml数据集,所以需要对json格式的数据进行转换。

图片:

标注的json格式数据:

转换后的xml格式

本次json转xml的源码如下:

# -*- coding: utf-8 -*-
"""
Created on Sun May 31 10:19:23 2020
@author: ywx
"""
import os
from typing import List, Any
import numpy as np
import codecs
import json
from glob import glob
import cv2
import shutil
from sklearn.model_selection import train_test_split
 
# 1.标签路径
labelme_path = "annotations/"
#原始labelme标注数据路径
saved_path = "VOC2007/"
# 保存路径
isUseTest=True#是否创建test集
# 2.创建要求文件夹
if not os.path.exists(saved_path + "Annotations"):
    os.makedirs(saved_path + "Annotations")
if not os.path.exists(saved_path + "JPEGImages/"):
    os.makedirs(saved_path + "JPEGImages/")
if not os.path.exists(saved_path + "ImageSets/Main/"):
    os.makedirs(saved_path + "ImageSets/Main/")
# 3.获取待处理文件
files = glob(labelme_path + "*.json")
files = [i.replace("\\","/").split("/")[-1].split(".json")[0] for i in files]
print(files)
# 4.读取标注信息并写入 xml
for json_file_ in files:
    json_filename = labelme_path + json_file_ + ".json"
    json_file = json.load(open(json_filename, "r", encoding="utf-8"))
    height, width, channels = cv2.imread('jpeg/' + json_file_ + ".jpg").shape
    with codecs.open(saved_path + "Annotations/" + json_file_ + ".xml", "w", "utf-8") as xml:
 
        xml.write('<annotation>\n')
        xml.write('\t<folder>' + 'WH_data' + '</folder>\n')
        xml.write('\t<filename>' + json_file_ + ".jpg" + '</filename>\n')
        xml.write('\t<source>\n')
        xml.write('\t\t<database>WH Data</database>\n')
        xml.write('\t\t<annotation>WH</annotation>\n')
        xml.write('\t\t<image>flickr</image>\n')
        xml.write('\t\t<flickrid>NULL</flickrid>\n')
        xml.write('\t</source>\n')
        xml.write('\t<owner>\n')
        xml.write('\t\t<flickrid>NULL</flickrid>\n')
        xml.write('\t\t<name>WH</name>\n')
        xml.write('\t</owner>\n')
        xml.write('\t<size>\n')
        xml.write('\t\t<width>' + str(width) + '</width>\n')
        xml.write('\t\t<height>' + str(height) + '</height>\n')
        xml.write('\t\t<depth>' + str(channels) + '</depth>\n')
        xml.write('\t</size>\n')
        xml.write('\t\t<segmented>0</segmented>\n')
        for multi in json_file["shapes"]:
            points = np.array(multi["points"])
            labelName=multi["label"]
            xmin = min(points[:, 0])
            xmax = max(points[:, 0])
            ymin = min(points[:, 1])
            ymax = max(points[:, 1])
            label = multi["label"]
            if xmax <= xmin:
                pass
            elif ymax <= ymin:
                pass
            else:
                xml.write('\t<object>\n')
                xml.write('\t\t<name>' + labelName+ '</name>\n')
                xml.write('\t\t<pose>Unspecified</pose>\n')
                xml.write('\t\t<truncated>1</truncated>\n')
                xml.write('\t\t<difficult>0</difficult>\n')
                xml.write('\t\t<bndbox>\n')
                xml.write('\t\t\t<xmin>' + str(int(xmin)) + '</xmin>\n')
                xml.write('\t\t\t<ymin>' + str(int(ymin)) + '</ymin>\n')
                xml.write('\t\t\t<xmax>' + str(int(xmax)) + '</xmax>\n')
                xml.write('\t\t\t<ymax>' + str(int(ymax)) + '</ymax>\n')
                xml.write('\t\t</bndbox>\n')
                xml.write('\t</object>\n')
                print(json_filename, xmin, ymin, xmax, ymax, label)
        xml.write('</annotation>')
# 5.复制图片到 VOC2007/JPEGImages/下
image_files = glob("jpeg/" + "*.jpg")
print("copy image files to VOC007/JPEGImages/")
for image in image_files:
    shutil.copy(image, saved_path + "JPEGImages/")
# 6.split files for txt
txtsavepath = saved_path + "ImageSets/Main/"
ftrainval = open(txtsavepath + '/trainval.txt', 'w')
ftest = open(txtsavepath + '/test.txt', 'w')
ftrain = open(txtsavepath + '/train.txt', 'w')
fval = open(txtsavepath + '/val.txt', 'w')
total_files = glob("./VOC2007/Annotations/*.xml")
total_files = [i.replace("\\","/").split("/")[-1].split(".xml")[0] for i in total_files]
trainval_files=[]
test_files=[] 
if isUseTest:
    trainval_files, test_files = train_test_split(total_files, test_size=0.15, random_state=55) 
else: 
    trainval_files=total_files 
for file in trainval_files: 
    ftrainval.write(file + "\n") 
# split 
train_files, val_files = train_test_split(trainval_files, test_size=0.15, random_state=55) 
# train
for file in train_files: 
    ftrain.write(file + "\n") 
# val 
for file in val_files: 
    fval.write(file + "\n")
for file in test_files:
    print(file)
    ftest.write(file + "\n")
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

三、EfficientDet理论介绍

EfficientDet是基于Efficientnet的目标检测网络,所以需要先读懂Efficientnet,这里可以先去看我之前写的卷积神经网络发展史中有关于Efficientnet的介绍。

简短来说,EfficientNet是将图片的分辨率,网络的宽度,网络的深度这三者结合起来,通过α实现缩放模型,不同的α有不同的模型精度。

总的来说,efficientdet目标检测网络,是以efficientnet为主干网络,之后经过bifpn特征特征网络,之后再输出检测结果。

1.EfficientNet

EfficientNet主要由Efficient Blocks构成,在其中小残差边以及大残差边构成,并在其中添加了注意力模块。

def mb_conv_block(inputs, block_args, activation, drop_rate=None, prefix='', ):
    """Mobile Inverted Residual Bottleneck."""

    has_se = (block_args.se_ratio is not None) and (0 < block_args.se_ratio <= 1)
    bn_axis = 3 if backend.image_data_format() == 'channels_last' else 1

    # workaround over non working dropout with None in noise_shape in tf.keras
    Dropout = get_dropout(
        backend=backend,
        layers=layers,
        models=models,
        utils=keras_utils
    )

    # Expansion phase
    filters = block_args.input_filters * block_args.expand_ratio
    if block_args.expand_ratio != 1:
        x = layers.Conv2D(filters, 1,
                          padding='same',
                          use_bias=False,
                          kernel_initializer=CONV_KERNEL_INITIALIZER,
                          name=prefix + 'expand_conv')(inputs)
        x = layers.BatchNormalization(axis=bn_axis, name=prefix + 'expand_bn')(x)
        x = layers.Activation(activation, name=prefix + 'expand_activation')(x)
    else:
        x = inputs

    # Depthwise Convolution
    x = layers.DepthwiseConv2D(block_args.kernel_size,
                               strides=block_args.strides,
                               padding='same',
                               use_bias=False,
                               depthwise_initializer=CONV_KERNEL_INITIALIZER,
                               name=prefix + 'dwconv')(x)
    x = layers.BatchNormalization(axis=bn_axis, name=prefix + 'bn')(x)
    x = layers.Activation(activation, name=prefix + 'activation')(x)

    # Squeeze and Excitation phase
    if has_se:
        num_reduced_filters = max(1, int(
            block_args.input_filters * block_args.se_ratio
        ))
        se_tensor = layers.GlobalAveragePooling2D(name=prefix + 'se_squeeze')(x)

        target_shape = (1, 1, filters) if backend.image_data_format() == 'channels_last' else (filters, 1, 1)
        se_tensor = layers.Reshape(target_shape, name=prefix + 'se_reshape')(se_tensor)
        se_tensor = layers.Conv2D(num_reduced_filters, 1,
                                  activation=activation,
                                  padding='same',
                                  use_bias=True,
                                  kernel_initializer=CONV_KERNEL_INITIALIZER,
                                  name=prefix + 'se_reduce')(se_tensor)
        se_tensor = layers.Conv2D(filters, 1,
                                  activation='sigmoid',
                                  padding='same',
                                  use_bias=True,
                                  kernel_initializer=CONV_KERNEL_INITIALIZER,
                                  name=prefix + 'se_expand')(se_tensor)
        if backend.backend() == 'theano':
            # For the Theano backend, we have to explicitly make
            # the excitation weights broadcastable.
            pattern = ([True, True, True, False] if backend.image_data_format() == 'channels_last'
                       else [True, False, True, True])
            se_tensor = layers.Lambda(
                lambda x: backend.pattern_broadcast(x, pattern),
                name=prefix + 'se_broadcast')(se_tensor)
        x = layers.multiply([x, se_tensor], name=prefix + 'se_excite')

    # Output phase
    x = layers.Conv2D(block_args.output_filters, 1,
                      padding='same',
                      use_bias=False,
                      kernel_initializer=CONV_KERNEL_INITIALIZER,
                      name=prefix + 'project_conv')(x)
    x = layers.BatchNormalization(axis=bn_axis, name=prefix + 'project_bn')(x)
    if block_args.id_skip and all(
            s == 1 for s in block_args.strides
    ) and block_args.input_filters == block_args.output_filters:
        if drop_rate and (drop_rate > 0):
            x = Dropout(drop_rate,
                        noise_shape=(None, 1, 1, 1),
                        name=prefix + 'drop')(x)
        x = layers.add([x, inputs], name=prefix + 'add')

    return x

2.BiFPN

改进了FPN中的多尺度特征融合方式,提出了加权双向特征金字塔网络BiFPN。BiFPN 引入了一种自顶向下的路径,融合P3~P7的多尺度特征

BiFPN模块类似于FPN网络(特征金字塔网络),不过比FPN更复杂些。其主要是为了增强特征,提取更有代表性的特征。

下图展示一下FPN网络:

而这是BiFPN的网络图:

其中的一个BiFPN模块为:

四、训练过程

1.准备数据集

准备抽烟数据,使用VOC格式的数据进行训练

  • 训练前将标签文件放在VOCdevkit文件夹下的VOC2007文件夹下的Annotation中。
  • 训练前将图片文件放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages中。
  • 在训练前利用voc2efficientdet.py文件生成对应的txt。
VOCdevkit
   -VOC2007
   	├─ImageSets    # 存放数据集列表文件,由voc2yolo3.py文件生成
   	├─Annotations  # 存放数据集中图片文件
   	├─JPEGImages   # 存放图片标签,xml 格式
   	└─voc2yolo4.py # 用来生成数据集列表文件

2.运行生成EfficientDet所需的数据

再运行根目录voc_annotation.py,运行前需要将voc_annotation文件中classes改成你自己的classes。
每一行对应其图片位置及其真实框的位置

3.修改voc_classes.txt

在训练前需要修改model_data里面的voc_classes.txt文件,需要将classes改成你自己的classes。

4.修改yolo_anchors.txt

运行kmeans_for_anchors.py生成yolo_anchors.txt

5.运行

运行train.py

  • 在main函数下:phi来控制efficient的版本
  • 在main函数下:model_path参数用于控制预训练权重

6.测试图片

需修改efficientdet.py文件中模型的位置,替换成你训练好的模型并修改phi为efficientdet的版本。然后在根目录下,运行python predict.py进行测试。

好了,本次就到此结束了!!!

哦,突然想起,我还保存了logs,在展示一波的训练过程吧!!!

好了,下次看情况,更新点别的东西,更新点有关bert文本的吧!!!

### 回答1: 要训练自己的数据集,您需要执行以下步骤: 1. 准备数据集:您需要准备自己的数据集,并将其转换为COCO格式。您可以使用开源工具,如labelImg,来标记您的图像。 2. 下载EfficientDet代码:您需要下载EfficientDet的代码,并安装所需的依赖项。 3. 配置训练参数:您需要配置训练参数,例如学习率、批量大小、训练轮数等。 4. 开始训练:运行训练脚本,开始训练您的模型。 5. 评估模型:在训练完成后,您需要评估您的模型,并根据需要进行微调。 6. 导出模型:最后,您需要导出您的模型,以便在生产环境中使用。 以上是训练自己数据集的基本步骤,您可以根据实际情况进行调整和优化。 ### 回答2: EfficientDet 是一种高效的目标检测算法,它在准确性和计算效率方面都有出色的表现。如果想要训练自己的数据,可以按照以下步骤操作: 1.数据准备 首先,需要准备好自己的数据集,包括图像和对应的标注文件,标注文件可以使用常见的格式如VOC、COCO等。 2.安装依赖 EfficientDet 是基于 TensorFlow 实现的,所以需要安装 TensorFlow 环境。在安装完成后,需要安装其他的依赖库,例如 TensorFlow Object Detection API、opencv-python等。 3.转换数据格式 EfficientDet 使用 TFRecord 形式的数据作为输入。因此,需要将自己的数据集转换成 TFRecord 格式。可以使用 TensorFlow Object Detection API 中的脚本来实现。 4.修改配置文件 EfficientDet 使用配置文件来定义模型的超参数和训练参数。可以根据自己的需求来修改配置文件。例如,可以设置训练的 batch size、学习率等参数。 5.训练模型 在准备好数据集和配置文件后,可以开始训练模型了。可以使用 TensorFlow Object Detection API 中的 train.py 脚本来启动训练过程。 6.检验训练结果 训练完成后,可以使用 TensorFlow Object Detection API 中提供的 evaluation.py 脚本来评估模型的性能。可以在自己的数据集上测试模型的准确度、召回率等指标。 以上是训练 EfficientDet 模型的基本流程。在实际操作过程中,还需要注意数据增强、模型调优等方面。需要综合考虑模型准确率和计算效率之间的平衡,以获得更好的检测效果。 ### 回答3: EfficientDet是为了解决对象检测问题而提出的一种强大的神经网络算法。由于EfficientDet网络参数少,计算量小,并且可以实现高质量的对象检测,因此在实际应用中被广泛采用。EfficientDet网络采用了一种先进的特征提取技术和多层次的任务特定网络来进行训练和推理。本文将介绍如何训练自己的数据以构建自己的目标检测模型。 1. 数据集制作 EfficientDet训练的第一步是准备适当的训练数据集。这涉及到的重要方面包括图像的增强、标注和准备。 对于数据增强,可以使用多种技术来增加样本数量。例如,可以随机旋转、缩放、裁剪和翻转图像,或者对图像应用随机颜色变换和噪声。 对于数据标注,可以使用多种工具来标注图像中物体的位置和类别。例如,可以使用labelImg来标注图像中的对象和标签。标注完成后,可以将数据保存为Pascal VOC格式或卡巴斯格式,这些格式是EfficientDet支持的标准数据格式。 2. 模型训练 有了训练数据集之后,就可以开始训练EfficientDet模型了。在本部分中,我们将介绍如何使用TensorFlow进行EfficientDet模型的训练。 首先,需要安装TF2版本及以上的TensorFlow,然后下载EfficientDet源码。然后,将自己的数据集导入EfficientDet源码。 接着,在EfficientDet的配置文件中,需要设置模型的参数,例如输入图像大小、批次大小、学习速率等。另外,还需要指定网络模型的类型以及要训练的层数和神经元数量。 训练模型时,需要对模型进行前向传递过程和反向传播过程。这涉及到多种技术,例如优化器和损失函数。对于EfficientDet,可以使用优化器和损失函数进行模型训练。 在训练的过程中,需要监视模型的性能和精度。可以采用多种技术来评估模型的性能,例如计算损失函数、精度等。最终,可以根据模型的性能和精度来调整模型的超参数和参数,以优化模型的性能和精度。 3. 模型评估 在模型训练完成后,需要对模型进行评估以确定其实际精度和性能。可以采用多种技术来评估模型的性能,例如计算准确率、召回率、F1得分等。 评估模型时,需要使用测试数据集对模型进行测试,并计算其准确率、召回率、F1得分等。如果模型的性能和精度较高,则可以将其部署到生产环境中,以用于实时目标检测
评论 125
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mind_programmonkey

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值