深層学習認識モデルに基づく欠陥検出

1.はじめに

欠陥検出は、布の欠陥検出、ワークピースの表面品質の検出、航空宇宙分野などで広く使用されています。従来のアルゴリズムは、ルールに欠陥があり、シーンが比較的単純な状況ではうまく機能しますが、特徴が明確でなく、形状が多様で、シーンが混沌としている状況にはもはや適していません。近年、深層学習に基づく認識アルゴリズムはますます成熟しており、多くの企業が深層学習アルゴリズムを産業の機会に適用しようとし始めています。

2.欠陥データ

下の図に示すように、ここでは布のデータを例として使用しています。一般的な欠陥には、摩耗、白い斑点、複数の線の3つがあります。

ここに画像の説明を挿入ここに画像の説明を挿入
ここに画像の説明を挿入
トレーニングデータの作成方法は?これが元の画像のインターセプトで、小さな画像がインターセプトされます。たとえば、上の画像は512x512ですが、ここでは64x64の小さな画像にトリミングします。最初のタイプの欠陥を例にとると、データの作成方法は次のとおりです。

ここに画像の説明を挿入
ここに画像の説明を挿入

注:欠陥データを作成する場合、欠陥領域は傍受された画像の少なくとも2/3を占める必要があります。そうでない場合、欠陥領域は破棄され、欠陥画像として使用されません。

一般的に言って、欠陥データはバックグラウンドデータよりもはるかに少ないので、方法はありません。ここにある他のブログ投稿を参照してください。画像データの拡張https://blog.csdn.net/qq_29462849/article/details/83241797最終
的に合格拡張データ、欠陥:バックグラウンド= 1:1、各クラスは約1000~~~

3.ネットワーク構造

使用される特定のネットワーク構造は次のとおりです。入力サイズは64x64x3で、傍受された小さな画像のサイズが使用されます。各Conv畳み込み層の後にBN層が続き、特定の層パラメーターは次のとおりです。
Conv1:64x3x3
Conv2:
128x3x3 ResNetBlockとDenseNetBlockをそれぞれ2つずつ。詳細については、ResidualNetworkとDenseNetを参照してください。
追加:残差モジュールによって出力された結果とDenseNetBlockによって出力された結果を対応する特徴マップに追加します。追加方法は残差モジュールの場合と同じです。実際、これはより良い特徴抽出のためであり、メソッドは必ずしも残差モジュール+ DenseNetBlockである必要はなく、開始などである可能性があることに注意してください。
Conv3:128x3x3
Maxpool:stride = 2、size = 2x2
FC1:4096
Dropout1:0.5
FC2:1024
Dropout1:0.5
Softmax:分割するカテゴリに対応します。ここでは2番目のカテゴリです。

ここに画像の説明を挿入

最終損失関数については、HeKaimingの傑作であるFocalLossを選択することをお勧めします。ソースコードは次のとおりです。

def focal_loss(y_true, y_pred):
    pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
    return -K.sum(K.pow(1. - pt_1, 2) * K.log(pt_1))

データの準備ができました。トレーニングを開始できます~~~

4.シーン画像全体の欠陥検出

上記のトレーニングネットワークでは、入力は64x64x3ですが、シーン画像全体は512x512です。この入力は、モデルの入力と一致しません。どうすればよいですか?実際、トレーニングされたモデルパラメータを抽出し、それらを別の新しいモデルに割り当ててから、新しいモデルの入力を512x512に変更できますが、conv3 + maxpoolレイヤーで抽出された特徴マップは比較的大きく、これは特徴マップの場合です。は元の画像にマッピングされます。たとえば、元のモデルの最後のmaxpoolレイヤーの後、出力特徴マップのサイズは8x8x128で、そのうち128はチャネル数です。入力を512x512に変更すると、出力フィーチャマップは64x64x128になり、ここでの各8x8は元の画像の64x64に対応するため、8x8スライディングウィンドウを使用して64x64x128フィーチャマップのフィーチャをスライドおよびトリミングできます。次に、トリミングされたフィーチャを太くして、完全に接続されたレイヤーに送信します。詳細を下図に示します。

完全に接続された層もモデルを再構築する必要があり、入力はフラット化後の入力であり、出力はsoftmax層の出力です。これはシンプルな小さなモデルです。

ここに画像の説明を挿入

トレーニングされたモデルパラメータを別のモデルに読み込むコードは次のとおりです

#提取特征的大模型
def read_big_model(inputs):
    # 第一个卷积和最大池化层
    X = Conv2D(16, (3, 3), name="conv2d_1")(inputs)
    X = BatchNormalization(name="batch_normalization_1")(X)
    X = Activation('relu', name="activation_1")(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name="max_pooling2d_1")(X)
    # google_inception模块
    conv_1 = Conv2D(32, (1, 1), padding='same', name='conv2d_2')(X)
    conv_1 = BatchNormalization(name='batch_normalization_2')(conv_1)
    conv_1 = Activation('relu', name='activation_2')(conv_1)
    conv_2 = Conv2D(32, (3, 3), padding='same', name='conv2d_3')(X)
    conv_2 = BatchNormalization(name='batch_normalization_3')(conv_2)
    conv_2 = Activation('relu', name='activation_3')(conv_2)
    conv_3 = Conv2D(32, (5, 5), padding='same', name='conv2d_4')(X)
    conv_3 = BatchNormalization(name='batch_normalization_4')(conv_3)
    conv_3 = Activation('relu', name='activation_4')(conv_3)
    pooling_1 = MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same', name='max_pooling2d_2')(X)
    X = merge([conv_1, conv_2, conv_3, pooling_1], mode='concat', name='merge_1')
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='max_pooling2d_3')(X)  # 这里的尺寸变成16x16x112
    X = Conv2D(64, (3, 3), kernel_regularizer=regularizers.l2(0.01), padding='same', name='conv2d_5')(X)
    X = BatchNormalization(name='batch_normalization_5')(X)
    X = Activation('relu', name='activation_5')(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='max_pooling2d_4')(X)  # 这里尺寸变成8x8x64
    X = Conv2D(128, (3, 3), padding='same', name='conv2d_6')(X)
    X = BatchNormalization(name='batch_normalization_6')(X)
    X = Activation('relu', name='activation_6')(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same', name='max_pooling2d_5')(X)  # 这里尺寸变成4x4x128

    return X

def read_big_model_classify(inputs_sec):
    X_ = Flatten(name='flatten_1')(inputs_sec)
    X_ = Dense(256, activation='relu', name="dense_1")(X_)
    X_ = Dropout(0.5, name="dropout_1")(X_)
    predictions = Dense(2, activation='softmax', name="dense_2")(X_)
    return predictions
#建立的小模型
inputs=Input(shape=(512,512,3))
X=read_big_model(inputs)#读取训练好模型的网络参数
#建立第一个model
model=Model(inputs=inputs, outputs=X)
model.load_weights('model_halcon.h5', by_name=True)

5.測位結果を特定します

上記のスライディングウィンドウ方式は、元の画像に配置できます。元の画像に配置された8x8スライディングウィンドウは64x64です。同様に、元の画像では、さまざまなスライディングウィンドウ方式(ここでは、左右および上下)に従います。ステップは16ピクセルです)。複数の欠陥位置が特定されており、これには位置決め精度が含まれます。ここでの投票方法は、実際には元の画像上のマークされた各ピクセル位置をカウントすることです。指定されたしきい値よりも大きい場合は、不良ピクセルと判断されます。

認識結果を次の図に示します。
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

6.いくつかのトリック

上記の場合、実際には、64x64ポジショニングボックスは十分に正確ではありません。32x32サイズのモデルのトレーニングを検討してから、64x64モデルと同じ方法を適用し、最後に32x32ポジショニング位置と64x64ポジショニングに基づいて投票することができます。位置ですが、これには問題があります。つまり、時間が大幅に長くなるため、注意して使用する必要があります。

背景と前景にほとんど差がない場合は、ネットワークが深すぎないようにする必要があります。深すぎるネットワークは基本的に後で同じことを学習し、優れた識別能力がないため、私はしません。ここでオブジェクト検出を使用します。理由は、これらの検出モデルネットワークの深さが50以上であることが多く、バックボーンとしてモジュールが残っているにもかかわらず、効果が良くないためです。

ただし、背景と前景が大きく異なる場合は、より深いネットワークを選択することができます。この場合、物体検出方法が便利です。

7.ソースコードについて

ここのコードはもはやオープンソースではありません。デザインは技術的に機密であるため、興味があれば、自分で実装できます。難しくはありません〜

おすすめ

転載: blog.csdn.net/qq_29462849/article/details/84763421