我们将使用 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

如下:

{0: 1.0, 1: 1.9131672}
  • 创建类权重字典以在训练过程中平衡权重。
  • 这个过程完成是因为我们的类在这种情况下是不平衡的。
  • 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")

如下:

深度学习项目:火灾烟雾监测【附完整源码】_python_02

加载模型

# 加载训练的模型
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)

如下:

深度学习项目:火灾烟雾监测【附完整源码】_原力计划_03


(火灾图片违规了,不方便展示,放在就是能识别出)