深度学习项目:火灾烟雾监测【附完整源码】
原创
©著作权归作者所有:来自51CTO博客作者wx62a0461bcb0eb的原创作品,请联系作者获取转载授权,否则将追究法律责任
我们将使用 CNN 来实施这个项目。我已经使用数据增强来增加我的图像数据集的容量,并且在这样的数据集上我获得了大约 90% 的非常令人满意的准确度。
文章目录
- 导入火灾和烟雾检测所需的库
- 定义一些常量。
- 读取图像并存储它们
- 标签的一种热编码
- 创建类权重字典
- 训练测试拆分数据
- 初始化数据增强对象
- 创建模型
- 训练和保存模型
- 可视化训练过程
- 加载模型
- 预测
导入火灾和烟雾检测所需的库
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import np_utils
from tensorflow.keras.optimizers import SGD
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential,load_model
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import BatchNormalization,Dense,SeparableConv2D,MaxPooling2D,Activation,Flatten,Dropout
定义一些常量。
# 定义初始化 learning rate, batch size, and number of epochs
INIT_LR = 0.1
BATCH_SIZE = 64
NUM_EPOCHS = 10
lr_find = True
classes = ['Non_Fire','Fire']
读取图像并存储它们
images = []
labels = []
for c in classes:
try:
for img in os.listdir('data/'+c):
img = cv2.imread('data/'+c+'/'+img)
img = cv2.resize(img,(128,128))
images.append(img)
labels.append([0,1][c=='Fire'])
except:
pass
images = np.array(images,dtype='float32')/255.
- 在这里,我们刚刚使用cv2.imread()读取所有图像并将它们存储在一个数组中。
- 此外,我们正在存储标签。1 代表Fire,0 代表 Non_Fire。
- 在最后一行中,我们只是简单地对图像进行归一化。以前我们的图像是从 0-255,但现在它们是从 0-1。
标签的一种热编码
labels = np.array(labels)
labels = np_utils.to_categorical(labels,num_classes=2)
classTotals = labels.sum(axis=0)
classWeight = classTotals.max() / classTotals
使用np_utils.to_categorical对标签进行一次热编码。
创建类权重字典
d = {}
d[0] = classWeight[0]
d[1] = classWeight[1]
d
如下:
- 创建类权重字典以在训练过程中平衡权重。
- 这个过程完成是因为我们的类在这种情况下是不平衡的。
- Non_Fire 图像是 Fire 图像的两倍。
训练测试拆分数据
X_train, X_test, y_train, y_test = train_test_split(images, labels, test_size=0.25, shuffle=True, random_state=42)
y_test
初始化数据增强对象
aug = ImageDataGenerator(
rotation_range=30,
zoom_range=0.15,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.15,
horizontal_flip=True,
fill_mode="nearest")
使用ImageDataGenerator()在进一步的步骤中增加数据。
创建模型
model = Sequential()
# CONV => RELU => POOL
model.add(SeparableConv2D(16,(7,7),padding='same',input_shape=(128,128,3)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2,2)))
# CONV => RELU => POOL
model.add(SeparableConv2D(32,(3,3),padding='same'))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2,2)))
# CONV => RELU => CONV => RELU => POOL
model.add(SeparableConv2D(64,(3,3),padding='same'))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(SeparableConv2D(64,(3,3),padding='same'))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2,2)))
# first set of FC => RELU layers
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# second set of FC => RELU layers
model.add(Dense(128))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# softmax classifier
model.add(Dense(len(classes)))
model.add(Activation("softmax"))
opt = SGD(learning_rate=INIT_LR, momentum=0.9,decay=INIT_LR / NUM_EPOCHS)
model.compile(loss='binary_crossentropy',
optimizer=opt,
metrics=['accuracy'])
print(model.summary())
如下:
训练和保存模型
print("[INFO] training network...")
H = model.fit(
aug.flow(X_train, y_train, batch_size=BATCH_SIZE),
validation_data=(X_test, y_test),
steps_per_epoch=X_train.shape[0] // BATCH_SIZE,
epochs=NUM_EPOCHS,
class_weight=d,
verbose=1)
print("[INFO] serializing network to '{}'...".format('output/model'))
model.save('output/fire_detection.h5')
- 简单地训练和保存我们的模型。
- model.fit 中的第一行是aug.flow(X_train, y_train, batch_size=BATCH_SIZE),它将创建增强数据。
- 此外,我们将class_weight参数作为我们在前面步骤中声明的d传递。
可视化训练过程
N = np.arange(0, NUM_EPOCHS)
plt.figure(figsize=(12,8))
plt.subplot(121)
plt.title("Losses")
plt.plot(N, H.history["loss"], label="train_loss")
plt.plot(N, H.history["val_loss"], label="val_loss")
plt.subplot(122)
plt.title("Accuracies")
plt.plot(N, H.history["accuracy"], label="train_acc")
plt.plot(N, H.history["val_accuracy"], label="val_acc")
plt.legend()
plt.savefig("output/training_plot.png")
如下:
加载模型
# 加载训练的模型
print("[INFO] loading model...")
model = load_model('output/fire_detection.h5')
预测
for i in range(50):
random_index = np.random.randint(0,len(X_test))
org_img = X_test[random_index]*255
img = org_img.copy()
img = cv2.resize(img,(128,128))
img = img.astype('float32')/256
pred = model.predict(np.expand_dims(img,axis=0))[0]
result = classes[np.argmax(pred)]
org_img = cv2.resize(org_img,(500,500))
cv2.putText(org_img, result, (35, 50), cv2.FONT_HERSHEY_SIMPLEX,1.25, (0, 255, 0), 3)
cv2.imwrite('output/testing/{}.png'.format(i),org_img)
如下:
(火灾图片违规了,不方便展示,放在就是能识别出)