基于卷积神经网络(CNN)的火焰识别探讨(一)
环境描述
操作系统:windows10
开发语言:python3.7.6
深度学习后端:tensorflow2.1.0
深度学习前端:keras(ts内嵌的keras)
显卡:GTX1050TI(安装cuda)
一、准备数据
从百度或谷歌上搜火、火焰、火灾等图片,建立两个文件夹(因为是二分类问题,有火or无火)fire和nofire。效果如下:
截图的文件夹分为conv和不带conv的文件夹,其实是火和无火的图片是经过多次添加的,因为训练数据的过程中会发现某些图片识别效果不是很好,所以得在训练样本中增加特定的图片(比如初次训练的时候没有增加枯草的图片进行训练,然后验证的时候会发现训练结果会误把枯草识别成火,因为数据应该是多次修正和新增的),conv文件夹其实就是将不带conv文件夹内的图片进行统一尺寸和格式(因为网上下载的数据基本上不可能统一尺寸,为了使用深度学习工具进行训练和张量运算,因此要统一尺寸)。
如下图,火的数据:
无火的数据如下:
将图片统一尺寸代码如下(需要自行修改图片路径):
from PIL import Image
import os.path
import glob
def convertjpg(jpgfile,outdir,width=300,height=300):
img=Image.open(jpgfile)
try:
new_img=img.resize((width,height),Image.BILINEAR)
new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
except Exception as e:
print(e)
for jpgfile in glob.glob('E:/fireimages/sources/nofire-1/*.jpg'):
convertjpg(jpgfile,'E:/fireimages/sources/conv_nofire-1')
二、调整数据
新建train和val两个文件夹,将统一尺寸后的图片基本上按照5:1的比例分配到train和val两个文件夹内,train里面包含fire和nofire两个文件夹,val同理,如下图:
三、使用googlenet(inceptionV3模型进行训练)
上代码,自行修改路径:
from tensorflow import keras
from keras.applications.inception_v3 import InceptionV3
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras import models
from keras import layers
import os
from keras import optimizers
from keras.utils import to_categorical
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from keras.applications.inception_v3 import InceptionV3,preprocess_input
from keras.layers import GlobalAveragePooling2D,Dense
from keras.models import Model
from keras.utils.vis_utils import plot_model
from keras.optimizers import Adagrad
# 动物数据预处理
train_dir = 'E:/fireimages/conv1/train'
val_dir = 'E:/fireimages/conv1/val'
# 不使用数据增强
train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)
# 使用数据增强
# train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=30., width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
# val_datagen = ImageDataGenerator(rescale=1./255, rotation_range=30., width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
# 使用迭代器生成图片张量
train_generator = train_datagen.flow_from_directory(train_dir, target_size=(300, 300), batch_size=10, class_mode='binary')
val_generator = train_datagen.flow_from_directory(val_dir, target_size=(300, 300), batch_size=10, class_mode='binary')
# resnet_base = InceptionV3(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
# 构建基础模型
base_model = InceptionV3(weights='imagenet',include_top=False, input_shape=(300, 300, 3))
# 增加新的输出层
x = base_model.output
# GlobalAveragePooling2D 将 MxNxC 的张量转换成 1xC 张量,C是通道数
x = GlobalAveragePooling2D()(x)
x = Dense(512,activation='relu')(x)
predictions = Dense(1,activation='sigmoid')(x)
model = Model(inputs=base_model.input,outputs=predictions)
'''
这里的base_model和model里面的iv3都指向同一个地址
'''
def setup_to_transfer_learning(model,base_model):
for layer in base_model.layers:
layer.trainable = False
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
def setup_to_fine_tune(model,base_model):
GAP_LAYER = 17
for layer in base_model.layers[:GAP_LAYER+1]:
layer.trainable = False
for layer in base_model.layers[GAP_LAYER+1:]:
layer.trainable = True
model.compile(optimizer=Adagrad(lr=0.0001),loss='binary_crossentropy',metrics=['accuracy'])
setup_to_transfer_learning(model,base_model)
history_tl = model.fit_generator(generator=train_generator,
epochs=5,
validation_data=val_generator,
validation_steps=5,
class_weight='auto'
)
model.save('E:/fireimages/fire-inceptionV3-more21.h5')
setup_to_fine_tune(model,base_model)
history_ft = model.fit_generator(generator=train_generator,
epochs=5,
validation_data=val_generator,
validation_steps=5,
class_weight='auto')
model.save('E:/fireimages/fire-inceptionV3-more22.h5')
四、训练
在vscode内进行训练,结果如下:训练集合验证集效果都还不错。
可见最后一轮的验证精度居然达到了惊人的100%。
五、测试数据
上代码:
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras import models
from keras import layers
from keras import optimizers
import matplotlib.pyplot as plt
from keras.applications import VGG16
from tensorflow import keras
from keras import models
import numpy as np
from keras.preprocessing import image
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
import os
import tkinter as tk
from tkinter import filedialog
# model = models.load_model('E:/KaggleDatas/dogvscat/dc.h5')
model = models.load_model('E:/fireimages/fire-inceptionV3-more22.h5')
root = tk.Tk()
root.withdraw()
print('press enter to discern your image.')
print('press e to exit.')
for i in range(1000):
cmd = input('input command.')
if cmd == '':
# 选择文件
path = filedialog.askopenfilename()
img = image.load_img(path)
img = img.resize((300, 300))
# img = img.scale()
x = image.img_to_array(img)
x /= 255
x = np.expand_dims(x, axis=0)
# x = preprocess_input(x, mode='torch')
y = model.predict(x)
# print(y)
j = 0
for data in y[0]:
if data <= 0.3:
print('fire {:.2f}'.format(data))
else:
print('nofire {:.2f}'.format(data))
elif cmd == 'e':
break
此处设定了阈值,当概率小于0.3的时候默认为是有火,否则无火,百度随便下载几张和训练验证集不相同的图片进行验证,效果如下:
在VS控制台按下回车选择图片进行验证,效果如下:
经过测试,发现通过手机拍照的拿着打火机点火的图片未识别出火焰,可能与图片资源有关,因此后续需要继续增加火焰数据集增加手拿打火机点火的照片,然后放到训练集里进行训练,手机拍出来的照片与横竖也有些关系,与照片尺寸也有关系(手机拍出来的尺寸较大)缩放到300*300后会损失不少像素,因此需要继续增强数据集。
六、下一步需要增加视频采集的火焰检测
计划每秒采集两帧图片进行火焰识别,待续……
上一篇: 递推算法