作者 | Dhruvil Shah
来源 | Medium
编辑 | 代码医生团队
嵌入式处理技术的最新发展已使基于视觉的系统可以在监视过程中使用卷积神经网络检测火灾。在本文中,已经实现了两个定制的CNN模型,以实现用于监视视频的具有成本效益的火灾探测CNN体系结构。第一个模型是受AlexNet架构启发的定制的基本CNN架构。将实现并查看其输出和限制,并创建一个定制的InceptionV3模型。为了平衡效率和准确性,考虑目标问题和火灾数据的性质对模型进行了微调。将使用三个不同的数据集来训练模型。数据集的链接在本文结尾处可用。进入编码部分。
1.创建定制的CNN架构
将使用TensorFlow API Keras构建模型。首先创建用于标记数据的ImageDataGenerator。[1]和[2]数据集在这里用于训练。最后将提供980张训练图像和239张验证图像。还将使用数据增强。
import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator
TRAINING_DIR = "Train"
training_datagen = ImageDataGenerator(rescale = 1./255,
horizontal_flip=True,
rotation_range=30,
height_shift_range=0.2,
fill_mode='nearest')
VALIDATION_DIR = "Validation"
validation_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = training_datagen.flow_from_directory(TRAINING_DIR,
target_size=(224,224),
class_mode='categorical',
batch_size = 64)
validation_generator = validation_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(224,224),
class_mode='categorical',
batch_size= 16)
在上面的代码中,应用了3种数据增强技术-水平翻转,旋转和高度移位。
现在将创建CNN模型。该模型包含三对Conv2D-MaxPooling2D层对,然后是3层密集层。为了克服过度拟合的问题,还将添加辍学层。最后一层是softmax层,它将提供两个类别(火灾和非火灾)的概率分布。通过将类数更改为1,还可以在最后一层使用“ Sigmoid”激活功能。
from tensorflow.keras.optimizers import Adam
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(96, (11,11), strides=(4,4), activation='relu', input_shape=(224, 224, 3)), tf.keras.layers.MaxPooling2D(pool_size = (3,3), strides=(2,2)),
tf.keras.layers.Conv2D(256, (5,5), activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size = (3,3), strides=(2,2)),
tf.keras.layers.Conv2D(384, (5,5), activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size = (3,3), strides=(2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(2048, activation='relu'),
tf.keras.layers.Dropout(0.25),
tf.keras.layers.Dense(1024, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(2, activation='softmax')])
model.compile(loss='categorical_crossentropy',
optimizer=Adam(lr=0.0001),
metrics=['acc'])
history = model.fit(
train_generator,
steps_per_epoch = 15,
epochs = 50,
validation_data = validation_generator,
validation_steps = 15
)
将使用Adam作为学习率为0.0001的优化器。训练了50个纪元后,获得了96.83的训练准确度和94.98的验证准确度。训练损失和验证损失分别为0.09和0.13。
模型的训练过程
测试模型中的任何图像,看看它是否可以正确猜出。为了进行测试,选择了3张图像,其中包括火图像,非火图像以及包含火样颜色和阴影的照片。
在这里,可以看到上面创建的模型在对图像进行分类时犯了一个错误。该模型确保52%的图像中有火焰。这是因为已对其进行训练的数据集。数据集中几乎没有图像可以教授室内火灾的模型。因此该模型仅知道室外着火情况,因此在获得室内类似火灾的阴影图像时会出错。另一个原因是模型不是可以学习火的复杂特征的复杂模型。
接下来将使用标准的InceptionV3模型并对其进行自定义。复杂模型能够从图像中学习复杂特征。
2.创建定制的InceptionV3模型
这次将使用不同的数据集[3],其中包含室外和室内火灾图像。已经在该数据集中训练了以前的CNN模型,结果是它过拟合,因为它无法处理这个相对较大的数据集,无法从图像中学习复杂的特征。
开始为自定义的InceptionV3创建ImageDataGenerator。数据集包含3个类,但对于本文,将仅使用2个类。它包含用于训练的1800张图像和用于验证的200张图像。另外添加了8张客厅图像,以在数据集中添加一些噪点。
import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator
TRAINING_DIR = "Train"
training_datagen = ImageDataGenerator(rescale=1./255,
zoom_range=0.15,
horizontal_flip=True,
fill_mode='nearest')
VALIDATION_DIR = "/content/FIRE-SMOKE-DATASET/Test"
validation_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = training_datagen.flow_from_directory(
TRAINING_DIR,
target_size=(224,224),
shuffle = True,
class_mode='categorical',
batch_size = 128)
validation_generator = validation_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(224,224),
class_mode='categorical',
shuffle = True,
batch_size= 14)
为了使训练更加准确,可以使用数据增强技术。在上面的代码中,应用了2种数据增强技术水平翻转和缩放。
从Keras API导入InceptionV3模型。将在InceptionV3模型的顶部添加图层,如下所示。将添加一个全局空间平均池化层,然后是2个密集层和2个辍学层,以确保模型不会过拟合。最后将为2个类别添加一个softmax激活的密集层。
接下来将首先仅训练添加的层并进行随机初始化。将在这里使用RMSprop作为优化器。
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Input, Dropout
input_tensor = Input(shape=(224, 224, 3))
base_model = InceptionV3(input_tensor=input_tensor, weights='imagenet', include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(2048, activation='relu')(x)
x = Dropout(0.25)(x)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.2)(x)
predictions = Dense(2, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers:
layer.trainable = False
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['acc'])
history = model.fit(
train_generator,
steps_per_epoch = 14,
epochs = 20,
validation_data = validation_generator,
validation_steps = 14)
在训练了顶层20个纪元后,将冻结模型的前249层,并训练其余的层(即顶层2个初始块)。在这里将使用SGD作为优化器,学习率为0.0001。
#To train the top 2 inception blocks, freeze the first 249 layers and unfreeze the rest.
for layer in model.layers[:249]:
layer.trainable = False
for layer in model.layers[249:]:
layer.trainable = True
#Recompile the model for these modifications to take effect
from tensorflow.keras.optimizers import SGD
model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['acc'])
history = model.fit(
train_generator,
steps_per_epoch = 14,
epochs = 10,
validation_data = validation_generator,
validation_steps = 14)
经过10个时期的训练,获得了98.04的训练准确度和96.43的验证准确度。训练损失和验证损失分别为0.063和0.118。
以上10个时期的训练过程
测试模型是否具有相同的图像,看看它是否可以正确猜出。
这次模型可以使所有三个预测正确。96%可以确定图像没有任何火。用于测试的其他两个图像是:
来自下面引用的数据集中的非火灾图像
实时测试:
现在模型已准备好在实际场景中进行测试。以下是使用OpenCV访问网络摄像头并预测每个帧是否包含火的示例代码。如果框架中包含火焰,希望将该框架的颜色更改为B&W。
import cv2
import numpy as np
from PIL import Image
import tensorflow as tf
from keras.preprocessing import image
#Load the saved model
model = tf.keras.models.load_model('InceptionV3.h5')
video = cv2.VideoCapture(0)
while True:
_, frame = video.read()
#Convert the captured frame into RGB
im = Image.fromarray(frame, 'RGB')
#Resizing into 224x224 because we trained the model with this image size.
im = im.resize((224,224))
img_array = image.img_to_array(im)
img_array = np.expand_dims(img_array, axis=0) / 255
probabilities = model.predict(img_array)[0]
#Calling the predict method on model to predict 'fire' on the image
prediction = np.argmax(probabilities)
#if prediction is 0, which means there is fire in the frame.
if prediction == 0:
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
print(probabilities[prediction])
cv2.imshow("Capturing", frame)
key=cv2.waitKey(1)
if key == ord('q'):
break
video.release()
cv2.destroyAllWindows()
下面是上面代码的实时输出。
这个项目的Github链接在这里。可以从那里找到数据集和上面的所有代码。
https://github.com/jackfrost1411/fire-detection
Anandaram G在Unsplash上拍摄的照片
结论
使用智能相机,可以识别各种可疑事件,例如碰撞,医疗紧急情况和火灾。其中,火灾是最危险的异常事件,因为早期无法控制火灾可能会导致巨大的灾难,并造成人员,生态和经济损失。受CNN巨大潜力的启发,可以在早期阶段从图像或视频中检测到火灾。本文显示了两种用于火灾探测的自定义模型。考虑到CNN模型的合理火灾探测准确性,它可以帮助灾难管理团队按时管理火灾,从而避免巨额损失。
本文使用的数据集
1.火灾探测数据集
https://www.kaggle.com/atulyakumar98/test-dataset
2. FIRE数据集
https://www.kaggle.com/phylake1337/fire-dataset
3. DeepQuestAI /火烟数据集
https://github.com/DeepQuestAI/Fire-Smoke-Dataset