环境描述
操作系统: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后会损失不少像素,因此需要继续增强数据集。
六、下一步需要增加视频采集的火焰检测
计划每秒采集两帧图片进行火焰识别,待续……
转载:https://blog.csdn.net/cumtwys/article/details/104822560
