python检测吸烟的算法_EfficientDet训练⾃⼰的数据集实现抽
烟检测
哈哈,我⼜来了 再次⽴下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
del_selection import train_test_split
# 1.标签路径
labelme_path = "annotations/"
#原始labelme标注数据路径
saved_path = "VOC2007/"
# 保存路径
isUseTest=True#是否创建test集
# 2.创建要求⽂件夹
if not ists(saved_path + "Annotations"):
os.makedirs(saved_path + "Annotations")
if not ists(saved_path + "JPEGImages/"):
os.makedirs(saved_path + "JPEGImages/")
if not ists(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('\n')
xml.write('\t' + 'WH_data' + '\n')
xml.write('\t' + json_file_ + ".jpg" + '\n')
xml.write('\t\n')
xml.write('\t\tWH Data\n')
xml.write('\t\tWH\n')
xml.write('\t\tflickr\n')
xml.write('\t\tNULL\n')
xml.write('\t\n')
xml.write('\t\n')
xml.write('\t\tNULL\n')
xml.write('\t\tWH\n')
xml.write('\t\n')
xml.write('\t\n')
xml.write('\t\t' + str(width) + '\n')
xml.write('\t\t' + str(height) + '\n')
python处理xml文件
xml.write('\t\t' + str(channels) + '\n')
xml.write('\t\n')
xml.write('\t\t0\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\n')
xml.write('\t\t' + labelName+ '\n')
xml.write('\t\tUnspecified\n')
xml.write('\t\t1\n')
xml.write('\t\t0\n')
xml.write('\t\t\n')
xml.write('\t\t\t' + str(int(xmin)) + '\n')
xml.write('\t\t\t' + str(int(ymin)) + '\n')
xml.write('\t\t\t' + str(int(xmax)) + '\n')
xml.write('\t\t\t' + str(int(ymax)) + '\n')
xml.write('\t\t\n')
xml.write('\t\n')
print(json_filename, xmin, ymin, xmax, ymax, label)
# 5.复制图⽚到 VOC2007/JPEGImages/下
image_files = glob("jpeg/" + "*.jpg")
print("copy image files to VOC007/JPEGImages/")
for image in image_files:
# 6.split files for txt
txtsavepath = saved_path + "ImageSets/Main/"
ftrainval = open(txtsavepath + '/', 'w')
ftest = open(txtsavepath + '/', 'w')
ftrain = open(txtsavepath + '/', 'w')
fval = open(txtsavepath + '/', '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()
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 * pand_ratio
if pand_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