飞道的博客

绝缘子红外图像检测项目(TF2)

471人阅读  评论(0)

目录

1. 项目背景

2. 图像数据集介绍

labelimg的安装流程:

1. 打开Anaconda Prompt(Anaconda3)

2. 创建一个新环境来安装labelimg

3. 激活新创建的环境labelimg

4.输入

5.输入labelimg 即可运行

 3. 模型介绍

 4. 模型性能测试


1. 项目背景

       瓷绝缘子在长期机电负荷与恶劣气候条件影响下,易发生劣化并出现零值现象,导致绝缘子串的有效爬电距离缩短,在过电压下易发生闪络击穿,严重威胁输配电线路的安全运行。红外热像法因其非接触式、安全高效的优点,成为现有技术中相对可行的零值绝缘子带电检测方法。

2. 图像数据集介绍

          收集到440幅绝缘子红外测温图像,并利用labelimg对其中的绝缘子进行标注。

绝缘子VOC标签的格式如下:


  
  1. <annotation>
  2. <folder></folder>
  3. <filename> 1.jpg</filename>
  4. <path> 1.jpg</path>
  5. <source>
  6. <database>roboflow.ai</database>
  7. </source>
  8. <size>
  9. <width> 416</width>
  10. <height> 416</height>
  11. <depth> 3</depth>
  12. </size>
  13. <segmented> 0</segmented>
  14. < object>
  15. <name>insulator</name>
  16. <pose>Unspecified</pose>
  17. <truncated> 0</truncated>
  18. <difficult> 0</difficult>
  19. <occluded> 0</occluded>
  20. <bndbox>
  21. <xmin> 231</xmin>
  22. <xmax> 405</xmax>
  23. <ymin> 1</ymin>
  24. <ymax> 212</ymax>
  25. </bndbox>
  26. </ object>
  27. < object>
  28. <name>insulator</name>
  29. <pose>Unspecified</pose>
  30. <truncated> 0</truncated>
  31. <difficult> 0</difficult>
  32. <occluded> 0</occluded>
  33. <bndbox>
  34. <xmin> 193</xmin>
  35. <xmax> 254</xmax>
  36. <ymin> 262</ymin>
  37. <ymax> 367</ymax>
  38. </bndbox>
  39. </ object>
  40. </annotation>

labelimg的安装流程:

1. 打开Anaconda Prompt(Anaconda3)

2. 创建一个新环境来安装labelimg

conda create -n labelimg python=3.7

3. 激活新创建的环境labelimg

conda activate labelimg

4.输入

conda activate labelimg

5.输入labelimg 即可运行

 3. 模型介绍

    模型训练过程中采用余弦退火衰减算法、并采用adam优化完成对模型权值参数的更新,其中训练集:测试集=9:1,冻结原始预训练YOLOv5模型前234层,迭代训练800个epoch,batchsize1=8,再解冻迭代训练200个epoch,batchsize2=4,3060ti显卡。

主干特征提取网络:


  
  1. from functools import wraps
  2. import tensorflow as tf
  3. from tensorflow.keras import backend as K
  4. from tensorflow.keras.initializers import RandomNormal
  5. from tensorflow.keras.layers import (Add, BatchNormalization, Concatenate,
  6. Conv2D, Layer, MaxPooling2D,
  7. ZeroPadding2D)
  8. from tensorflow.keras.regularizers import l2
  9. from utils.utils import compose
  10. class SiLU( Layer):
  11. def __init__( self, **kwargs):
  12. super(SiLU, self).__init__(**kwargs)
  13. self.supports_masking = True
  14. def call( self, inputs):
  15. return inputs * K.sigmoid(inputs)
  16. def get_config( self):
  17. config = super(SiLU, self).get_config()
  18. return config
  19. def compute_output_shape( self, input_shape):
  20. return input_shape
  21. class Focus( Layer):
  22. def __init__( self):
  23. super(Focus, self).__init__()
  24. def compute_output_shape( self, input_shape):
  25. return (input_shape[ 0], input_shape[ 1] // 2 if input_shape[ 1] != None else input_shape[ 1], input_shape[ 2] // 2 if input_shape[ 2] != None else input_shape[ 2], input_shape[ 3] * 4)
  26. def call( self, x):
  27. return tf.concat(
  28. [x[..., :: 2, :: 2, :],
  29. x[..., 1:: 2, :: 2, :],
  30. x[..., :: 2, 1:: 2, :],
  31. x[..., 1:: 2, 1:: 2, :]],
  32. axis=- 1
  33. )
  34. @wraps(Conv2D)
  35. def DarknetConv2D( *args, **kwargs):
  36. darknet_conv_kwargs = { 'kernel_initializer' : RandomNormal(stddev= 0.02), 'kernel_regularizer' : l2(kwargs.get( 'weight_decay', 5e-4))}
  37. darknet_conv_kwargs[ 'padding'] = 'valid' if kwargs.get( 'strides')==( 2, 2) else 'same'
  38. try:
  39. del kwargs[ 'weight_decay']
  40. except:
  41. pass
  42. darknet_conv_kwargs.update(kwargs)
  43. return Conv2D(*args, **darknet_conv_kwargs)
  44. #---------------------------------------------------#
  45. # 卷积块 -> 卷积 + 标准化 + 激活函数
  46. # DarknetConv2D + BatchNormalization + SiLU
  47. #---------------------------------------------------#
  48. def DarknetConv2D_BN_SiLU( *args, **kwargs):
  49. no_bias_kwargs = { 'use_bias': False}
  50. no_bias_kwargs.update(kwargs)
  51. if "name" in kwargs.keys():
  52. no_bias_kwargs[ 'name'] = kwargs[ 'name'] + '.conv'
  53. return compose(
  54. DarknetConv2D(*args, **no_bias_kwargs),
  55. BatchNormalization(momentum = 0.97, epsilon = 0.001, name = kwargs[ 'name'] + '.bn'),
  56. SiLU())
  57. def Bottleneck( x, out_channels, shortcut=True, weight_decay=5e-4, name = ""):
  58. y = compose(
  59. DarknetConv2D_BN_SiLU(out_channels, ( 1, 1), weight_decay=weight_decay, name = name + '.cv1'),
  60. DarknetConv2D_BN_SiLU(out_channels, ( 3, 3), weight_decay=weight_decay, name = name + '.cv2'))(x)
  61. if shortcut:
  62. y = Add()([x, y])
  63. return y
  64. def C3( x, num_filters, num_blocks, shortcut=True, expansion=0.5, weight_decay=5e-4, name=""):
  65. hidden_channels = int(num_filters * expansion)
  66. x_1 = DarknetConv2D_BN_SiLU(hidden_channels, ( 1, 1), weight_decay=weight_decay, name = name + '.cv1')(x)
  67. x_2 = DarknetConv2D_BN_SiLU(hidden_channels, ( 1, 1), weight_decay=weight_decay, name = name + '.cv2')(x)
  68. for i in range(num_blocks):
  69. x_1 = Bottleneck(x_1, hidden_channels, shortcut=shortcut, weight_decay=weight_decay, name = name + '.m.' + str(i))
  70. #----------------------------------------------------------------#
  71. route = Concatenate()([x_1, x_2])
  72. return DarknetConv2D_BN_SiLU(num_filters, ( 1, 1), weight_decay=weight_decay, name = name + '.cv3')(route)
  73. def SPPBottleneck( x, out_channels, weight_decay=5e-4, name = ""):
  74. x = DarknetConv2D_BN_SiLU(out_channels // 2, ( 1, 1), weight_decay=weight_decay, name = name + '.cv1')(x)
  75. maxpool1 = MaxPooling2D(pool_size=( 5, 5), strides=( 1, 1), padding= 'same')(x)
  76. maxpool2 = MaxPooling2D(pool_size=( 9, 9), strides=( 1, 1), padding= 'same')(x)
  77. maxpool3 = MaxPooling2D(pool_size=( 13, 13), strides=( 1, 1), padding= 'same')(x)
  78. x = Concatenate()([x, maxpool1, maxpool2, maxpool3])
  79. x = DarknetConv2D_BN_SiLU(out_channels, ( 1, 1), weight_decay=weight_decay, name = name + '.cv2')(x)
  80. return x
  81. def resblock_body( x, num_filters, num_blocks, expansion=0.5, shortcut=True, last=False, weight_decay=5e-4, name = ""):
  82. # 320, 320, 64 => 160, 160, 128
  83. x = ZeroPadding2D((( 1, 0),( 1, 0)))(x)
  84. x = DarknetConv2D_BN_SiLU(num_filters, ( 3, 3), strides = ( 2, 2), weight_decay=weight_decay, name = name + '.0')(x)
  85. if last:
  86. x = SPPBottleneck(x, num_filters, weight_decay=weight_decay, name = name + '.1')
  87. return C3(x, num_filters, num_blocks, shortcut=shortcut, expansion=expansion, weight_decay=weight_decay, name = name + '.1' if not last else name + '.2')
  88. def darknet_body( x, base_channels, base_depth, weight_decay=5e-4):
  89. # 640, 640, 3 => 320, 320, 12
  90. x = Focus()(x)
  91. # 320, 320, 12 => 320, 320, 64
  92. x = DarknetConv2D_BN_SiLU(base_channels, ( 3, 3), weight_decay=weight_decay, name = 'backbone.stem.conv')(x)
  93. # 320, 320, 64 => 160, 160, 128
  94. x = resblock_body(x, base_channels * 2, base_depth, weight_decay=weight_decay, name = 'backbone.dark2')
  95. # 160, 160, 128 => 80, 80, 256
  96. x = resblock_body(x, base_channels * 4, base_depth * 3, weight_decay=weight_decay, name = 'backbone.dark3')
  97. feat1 = x
  98. # 80, 80, 256 => 40, 40, 512
  99. x = resblock_body(x, base_channels * 8, base_depth * 3, weight_decay=weight_decay, name = 'backbone.dark4')
  100. feat2 = x
  101. # 40, 40, 512 => 20, 20, 1024
  102. x = resblock_body(x, base_channels * 16, base_depth, shortcut= False, last= True, weight_decay=weight_decay, name = 'backbone.dark5')
  103. feat3 = x
  104. return feat1,feat2,feat3

yolov5模型:


  
  1. from tensorflow.keras.layers import (Concatenate, Input, Lambda, UpSampling2D,
  2. ZeroPadding2D)
  3. from tensorflow.keras.models import Model
  4. from nets.CSPdarknet import (C3, DarknetConv2D, DarknetConv2D_BN_SiLU,
  5. darknet_body)
  6. from nets.yolo_training import yolo_loss
  7. #---------------------------------------------------#
  8. def yolo_body( input_shape, anchors_mask, num_classes, phi, weight_decay=5e-4):
  9. depth_dict = { 's' : 0.33, 'm' : 0.67, 'l' : 1.00, 'x' : 1.33,}
  10. width_dict = { 's' : 0.50, 'm' : 0.75, 'l' : 1.00, 'x' : 1.25,}
  11. dep_mul, wid_mul = depth_dict[phi], width_dict[phi]
  12. base_channels = int(wid_mul * 64) # 64
  13. base_depth = max( round(dep_mul * 3), 1) # 3
  14. inputs = Input(input_shape)
  15. feat1, feat2, feat3 = darknet_body(inputs, base_channels, base_depth, weight_decay)
  16. P5 = DarknetConv2D_BN_SiLU( int(base_channels * 8), ( 1, 1), weight_decay=weight_decay, name = 'conv_for_feat3')(feat3)
  17. P5_upsample = UpSampling2D()(P5)
  18. P5_upsample = Concatenate(axis = - 1)([P5_upsample, feat2])
  19. P5_upsample = C3(P5_upsample, int(base_channels * 8), base_depth, shortcut = False, weight_decay=weight_decay, name = 'conv3_for_upsample1')
  20. P4 = DarknetConv2D_BN_SiLU( int(base_channels * 4), ( 1, 1), weight_decay=weight_decay, name = 'conv_for_feat2')(P5_upsample)
  21. P4_upsample = UpSampling2D()(P4)
  22. P4_upsample = Concatenate(axis = - 1)([P4_upsample, feat1])
  23. P3_out = C3(P4_upsample, int(base_channels * 4), base_depth, shortcut = False, weight_decay=weight_decay, name = 'conv3_for_upsample2')
  24. P3_downsample = ZeroPadding2D((( 1, 0),( 1, 0)))(P3_out)
  25. P3_downsample = DarknetConv2D_BN_SiLU( int(base_channels * 4), ( 3, 3), strides = ( 2, 2), weight_decay=weight_decay, name = 'down_sample1')(P3_downsample)
  26. P3_downsample = Concatenate(axis = - 1)([P3_downsample, P4])
  27. P4_out = C3(P3_downsample, int(base_channels * 8), base_depth, shortcut = False, weight_decay=weight_decay, name = 'conv3_for_downsample1')
  28. P4_downsample = ZeroPadding2D((( 1, 0),( 1, 0)))(P4_out)
  29. P4_downsample = DarknetConv2D_BN_SiLU( int(base_channels * 8), ( 3, 3), strides = ( 2, 2), weight_decay=weight_decay, name = 'down_sample2')(P4_downsample)
  30. P4_downsample = Concatenate(axis = - 1)([P4_downsample, P5])
  31. P5_out = C3(P4_downsample, int(base_channels * 16), base_depth, shortcut = False, weight_decay=weight_decay, name = 'conv3_for_downsample2')
  32. out2 = DarknetConv2D( len(anchors_mask[ 2]) * ( 5 + num_classes), ( 1, 1), strides = ( 1, 1), weight_decay=weight_decay, name = 'yolo_head_P3')(P3_out)
  33. out1 = DarknetConv2D( len(anchors_mask[ 1]) * ( 5 + num_classes), ( 1, 1), strides = ( 1, 1), weight_decay=weight_decay, name = 'yolo_head_P4')(P4_out)
  34. out0 = DarknetConv2D( len(anchors_mask[ 0]) * ( 5 + num_classes), ( 1, 1), strides = ( 1, 1), weight_decay=weight_decay, name = 'yolo_head_P5')(P5_out)
  35. return Model(inputs, [out0, out1, out2])
  36. def get_train_model( model_body, input_shape, num_classes, anchors, anchors_mask, label_smoothing):
  37. y_true = [Input(shape = (input_shape[ 0] // { 0: 32, 1: 16, 2: 8}[l], input_shape[ 1] // { 0: 32, 1: 16, 2: 8}[l], \
  38. len(anchors_mask[l]), num_classes + 5)) for l in range( len(anchors_mask))]
  39. model_loss = Lambda(
  40. yolo_loss,
  41. output_shape = ( 1, ),
  42. name = 'yolo_loss',
  43. arguments = {
  44. 'input_shape' : input_shape,
  45. 'anchors' : anchors,
  46. 'anchors_mask' : anchors_mask,
  47. 'num_classes' : num_classes,
  48. 'label_smoothing' : label_smoothing,
  49. 'balance' : [ 0.4, 1.0, 4],
  50. 'box_ratio' : 0.05,
  51. 'obj_ratio' : 1 * (input_shape[ 0] * input_shape[ 1]) / ( 640 ** 2),
  52. 'cls_ratio' : 0.5 * (num_classes / 80)
  53. }
  54. )([*model_body.output, *y_true])
  55. model = Model([model_body. input, *y_true], model_loss)
  56. return model

 4. 模型性能测试

模型测试的mAP值:

获取mAP的程序:


  
  1. import os
  2. import xml.etree.ElementTree as ET
  3. import tensorflow as tf
  4. from PIL import Image
  5. from tqdm import tqdm
  6. from utils.utils import get_classes
  7. from utils.utils_map import get_coco_map, get_map
  8. from yolo import YOLO
  9. gpus = tf.config.experimental.list_physical_devices(device_type= 'GPU')
  10. for gpu in gpus:
  11. tf.config.experimental.set_memory_growth(gpu, True)
  12. if __name__ == "__main__":
  13. classes_path = 'data/defeat_name.txt'
  14. MINOVERLAP = 0.5
  15. VOCdevkit_path = 'VOCdevkit'
  16. image_ids = open(os.path.join(VOCdevkit_path, "VOC2007/ImageSets/Main/test.txt")).read().strip().split()
  17. if not os.path.exists(map_out_path):
  18. os.makedirs(map_out_path)
  19. if not os.path.exists(os.path.join(map_out_path, 'ground-truth')):
  20. os.makedirs(os.path.join(map_out_path, 'ground-truth'))
  21. if not os.path.exists(os.path.join(map_out_path, 'detection-results')):
  22. os.makedirs(os.path.join(map_out_path, 'detection-results'))
  23. if not os.path.exists(os.path.join(map_out_path, 'images-optional')):
  24. os.makedirs(os.path.join(map_out_path, 'images-optional'))
  25. class_names, _ = get_classes(classes_path)
  26. if map_mode == 0 :
  27. print( "Load model.")
  28. yolo = YOLO(confidence = 0.001, nms_iou = 0.5)
  29. print( "Load model done.")
  30. print( "Get predict result.")
  31. for image_id in tqdm(image_ids):
  32. image_path = os.path.join(VOCdevkit_path, "VOC2007/JPEGImages/"+image_id+ ".jpg")
  33. image = Image. open(image_path)
  34. if map_vis:
  35. image.save(os.path.join(map_out_path, "images-optional/" + image_id + ".jpg"))
  36. yolo.get_map_txt(image_id, image, class_names, map_out_path)
  37. print( "Get predict result done.")

实例预测:


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