小言_互联网的博客

基于卷积神经网络(CNN)的火焰识别探讨(一)

490人阅读  评论(0)

    环境描述

    操作系统:windows10

    开发语言:python3.7.6

    深度学习后端:tensorflow2.1.0

    深度学习前端:keras(ts内嵌的keras)

    显卡:GTX1050TI(安装cuda)

 

    一、准备数据

    从百度或谷歌上搜火、火焰、火灾等图片,建立两个文件夹(因为是二分类问题,有火or无火)fire和nofire。效果如下:

    截图的文件夹分为conv和不带conv的文件夹,其实是火和无火的图片是经过多次添加的,因为训练数据的过程中会发现某些图片识别效果不是很好,所以得在训练样本中增加特定的图片(比如初次训练的时候没有增加枯草的图片进行训练,然后验证的时候会发现训练结果会误把枯草识别成火,因为数据应该是多次修正和新增的),conv文件夹其实就是将不带conv文件夹内的图片进行统一尺寸和格式(因为网上下载的数据基本上不可能统一尺寸,为了使用深度学习工具进行训练和张量运算,因此要统一尺寸)。

    如下图,火的数据:

    无火的数据如下:

将图片统一尺寸代码如下(需要自行修改图片路径):


  
  1. from PIL import Image
  2. import os.path
  3. import glob
  4. def convertjpg(jpgfile,outdir,width=300,height=300):
  5. img=Image.open(jpgfile)
  6. try:
  7. new_img=img.resize((width,height),Image.BILINEAR)
  8. new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
  9. except Exception as e:
  10. print(e)
  11. for jpgfile in glob.glob( 'E:/fireimages/sources/nofire-1/*.jpg'):
  12. convertjpg(jpgfile, 'E:/fireimages/sources/conv_nofire-1')

二、调整数据

    新建train和val两个文件夹,将统一尺寸后的图片基本上按照5:1的比例分配到train和val两个文件夹内,train里面包含fire和nofire两个文件夹,val同理,如下图:

三、使用googlenet(inceptionV3模型进行训练)

上代码,自行修改路径:


  
  1. from tensorflow import keras
  2. from keras.applications.inception_v3 import InceptionV3
  3. import numpy as np
  4. from keras.preprocessing.image import ImageDataGenerator
  5. from keras import models
  6. from keras import layers
  7. import os
  8. from keras import optimizers
  9. from keras.utils import to_categorical
  10. import matplotlib.pyplot as plt
  11. from keras.preprocessing.image import ImageDataGenerator
  12. from keras.applications.inception_v3 import InceptionV3,preprocess_input
  13. from keras.layers import GlobalAveragePooling2D,Dense
  14. from keras.models import Model
  15. from keras.utils.vis_utils import plot_model
  16. from keras.optimizers import Adagrad
  17. # 动物数据预处理
  18. train_dir = 'E:/fireimages/conv1/train'
  19. val_dir = 'E:/fireimages/conv1/val'
  20. # 不使用数据增强
  21. train_datagen = ImageDataGenerator(rescale= 1./ 255)
  22. val_datagen = ImageDataGenerator(rescale= 1./ 255)
  23. # 使用数据增强
  24. # 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)
  25. # 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)
  26. # 使用迭代器生成图片张量
  27. train_generator = train_datagen.flow_from_directory(train_dir, target_size=( 300, 300), batch_size= 10, class_mode= 'binary')
  28. val_generator = train_datagen.flow_from_directory(val_dir, target_size=( 300, 300), batch_size= 10, class_mode= 'binary')
  29. # resnet_base = InceptionV3(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  30. # 构建基础模型
  31. base_model = InceptionV3(weights= 'imagenet',include_top= False, input_shape=( 300, 300, 3))
  32. # 增加新的输出层
  33. x = base_model.output
  34. # GlobalAveragePooling2D 将 MxNxC 的张量转换成 1xC 张量,C是通道数
  35. x = GlobalAveragePooling2D()(x)
  36. x = Dense( 512,activation= 'relu')(x)
  37. predictions = Dense( 1,activation= 'sigmoid')(x)
  38. model = Model(inputs=base_model.input,outputs=predictions)
  39. '''
  40. 这里的base_model和model里面的iv3都指向同一个地址
  41. '''
  42. def setup_to_transfer_learning(model,base_model):
  43. for layer in base_model.layers:
  44. layer.trainable = False
  45. model.compile(optimizer= 'adam',loss= 'binary_crossentropy',metrics=[ 'accuracy'])
  46. def setup_to_fine_tune(model,base_model):
  47. GAP_LAYER = 17
  48. for layer in base_model.layers[:GAP_LAYER+ 1]:
  49. layer.trainable = False
  50. for layer in base_model.layers[GAP_LAYER+ 1:]:
  51. layer.trainable = True
  52. model.compile(optimizer=Adagrad(lr= 0.0001),loss= 'binary_crossentropy',metrics=[ 'accuracy'])
  53. setup_to_transfer_learning(model,base_model)
  54. history_tl = model.fit_generator(generator=train_generator,
  55. epochs= 5,
  56. validation_data=val_generator,
  57. validation_steps= 5,
  58. class_weight= 'auto'
  59. )
  60. model.save( 'E:/fireimages/fire-inceptionV3-more21.h5')
  61. setup_to_fine_tune(model,base_model)
  62. history_ft = model.fit_generator(generator=train_generator,
  63. epochs= 5,
  64. validation_data=val_generator,
  65. validation_steps= 5,
  66. class_weight= 'auto')
  67. model.save( 'E:/fireimages/fire-inceptionV3-more22.h5')

四、训练

    在vscode内进行训练,结果如下:训练集合验证集效果都还不错。

可见最后一轮的验证精度居然达到了惊人的100%。

五、测试数据

上代码:


  
  1. import os
  2. import numpy as np
  3. from keras.preprocessing.image import ImageDataGenerator
  4. from keras import models
  5. from keras import layers
  6. from keras import optimizers
  7. import matplotlib.pyplot as plt
  8. from keras.applications import VGG16
  9. from tensorflow import keras
  10. from keras import models
  11. import numpy as np
  12. from keras.preprocessing import image
  13. from keras.applications.imagenet_utils import preprocess_input, decode_predictions
  14. import os
  15. import tkinter as tk
  16. from tkinter import filedialog
  17. # model = models.load_model('E:/KaggleDatas/dogvscat/dc.h5')
  18. model = models.load_model( 'E:/fireimages/fire-inceptionV3-more22.h5')
  19. root = tk.Tk()
  20. root.withdraw()
  21. print( 'press enter to discern your image.')
  22. print( 'press e to exit.')
  23. for i in range( 1000):
  24. cmd = input( 'input command.')
  25. if cmd == '':
  26. # 选择文件
  27. path = filedialog.askopenfilename()
  28. img = image.load_img(path)
  29. img = img.resize(( 300, 300))
  30. # img = img.scale()
  31. x = image.img_to_array(img)
  32. x /= 255
  33. x = np.expand_dims(x, axis= 0)
  34. # x = preprocess_input(x, mode='torch')
  35. y = model.predict(x)
  36. # print(y)
  37. j = 0
  38. for data in y[ 0]:
  39. if data <= 0.3:
  40. print( 'fire {:.2f}'.format(data))
  41. else:
  42. print( 'nofire {:.2f}'.format(data))
  43. elif cmd == 'e':
  44. break

此处设定了阈值,当概率小于0.3的时候默认为是有火,否则无火,百度随便下载几张和训练验证集不相同的图片进行验证,效果如下:

在VS控制台按下回车选择图片进行验证,效果如下:

经过测试,发现通过手机拍照的拿着打火机点火的图片未识别出火焰,可能与图片资源有关,因此后续需要继续增加火焰数据集增加手拿打火机点火的照片,然后放到训练集里进行训练,手机拍出来的照片与横竖也有些关系,与照片尺寸也有关系(手机拍出来的尺寸较大)缩放到300*300后会损失不少像素,因此需要继续增强数据集。

六、下一步需要增加视频采集的火焰检测

    计划每秒采集两帧图片进行火焰识别,待续……


转载:https://blog.csdn.net/cumtwys/article/details/104822560
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场