Cet article est une suite de l'article qui a été segmenté sémantiquement à l'aide de SegNet [^ 2] pour CaDIS: un ensemble de données Cataract [^ 1] qui a été effectué précédemment. est. Cette fois, nous comparerons les performances d'U-Net [^ 3] avec une structure skip intégrée au réseau de previous.
Veuillez vous référer à Dernière fois.
Cette fois, nous allons implémenter U-Net [^ 3] avec une structure de saut dans SegNet [^ 2] de précédent et comparer les performances. U-Net connecte la sortie avant le regroupement maximum de l'encodeur avec la sortie après l'échantillonnage ascendant du décodeur et l'entrent dans la couche de convolution du réseau comme indiqué dans la figure ci-dessous. Cela permet de récupérer des informations qui ont été perdues en compressant l'image avec Max Pooling.
Cette fois, nous n'introduirons que la structure de saut dans la structure de réseau de précédent. Tout d'abord, branchez le réseau comme suit.
x = Conv2D(32, (3, 3), padding='same', kernel_initializer='he_normal')(inputs)
x = BatchNormalization()(x)
x1 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x1)
Branchement de la sortie en laissant x1
non mis à jour. Ensuite, concaténez les sorties branchées comme suit.
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x1], axis=-1)
x = Conv2D(64, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
Vous pouvez concaténer des tenseurs d'entrée en utilisant concatenate ()
. Cette fois, nous combinons x1 = (hauteur, largeur, ch1)
et x = (hauteur, largeur, ch2)
pour obtenir le tenseur de sortie de(hauteur, largeur, ch1 + ch2)
. Le réseau auquel cela est appliqué dans chaque regroupement maximum et échantillonnage ascendant est indiqué ci-dessous.
<détails> De plus, je pense que la description de la partie réseau deviendra redondante en raison de l'approfondissement à l'avenir, je vais donc rendre le codeur La méthode d'apprentissage et les paramètres sont les mêmes que Dernière fois. Les résultats d'apprentissage sont les suivants.
L'évaluation est effectuée par l'IoU moyen pour chaque classe et l'IoU moyen qui est la moyenne d'entre eux, comme dans le précédent. Voici les résultats de l'évaluation. À partir du tableau, nous pouvons voir que le précédent était de 0% pour de nombreuses classes, qui sont légèrement inférables. De plus, Io U moyen était de 18,5%. Dernière fois SegNet [^ 2] était de 15,0%, nous avons donc pu améliorer la précision de 3,5%. Dans cet article, nous avons implémenté U-Net [^ 3] qui incorpore une structure de saut dans SegNet [^ 2] de précédent. Pour CaDIS: a Cataract Dataset [^ 1], nous avons comparé les performances à l'IoU moyenne et confirmé une amélioration de 3,5% de la précision. La précision la plus élevée du papier [^ 1] est de 34,16%, jusqu'à 52,66% de PSPNet. Sur la base de ce résultat, nous continuerons à intégrer les dernières méthodes telles que la structure du réseau et la méthode d'extension des données, et viserons des performances identiques ou meilleures.from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, MaxPool2D, UpSampling2D, concatenate
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation
# U-Net(8 couches d'encodeur, 8 couches de décodeur)Construire
def cnn(input_shape, classes):
#La taille de l'image d'entrée doit être un multiple de 32
assert input_shape[0]%32 == 0, 'Input size must be a multiple of 32.'
assert input_shape[1]%32 == 0, 'Input size must be a multiple of 32.'
#encodeur
##Couche d'entrée
inputs = Input(shape=(input_shape[0], input_shape[1], 3))
##1ère couche
x = Conv2D(32, (3, 3), padding='same', kernel_initializer='he_normal')(inputs)
x = BatchNormalization()(x)
x1 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x1)
##2ème couche
x = Conv2D(64, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x2 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x2)
##3e couche
x = Conv2D(128, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x3 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x3)
##4ème couche
x = Conv2D(256, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x4 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x4)
##5ème et 6ème couches
x = Conv2D(512, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(512, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x5 = Activation('relu')(x)
x = MaxPool2D(pool_size=(2, 2))(x5)
##7ème et 8ème couches
x = Conv2D(1024, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(1024, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
#Décodeur
##1ère couche
x = Conv2D(1024, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
##2ème et 3ème couches
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x5], axis=-1)
x = Conv2D(512, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(512, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
##4ème couche
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x4], axis=-1)
x = Conv2D(256, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
##5ème couche
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x3], axis=-1)
x = Conv2D(128, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
##6ème couche
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x2], axis=-1)
x = Conv2D(64, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
##7ème et 8ème couches
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x1], axis=-1)
x = Conv2D(64, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = Conv2D(classes, (1, 1), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
outputs = Activation('softmax')(x)
return Model(inputs=inputs, outputs=outputs)
#Construction de réseau
model = cnn(image_size, classes)
Conv + BN + Relu + MaxPool
et le décodeur Conv + BN + Relu + Upsampl
fonctionnels. Ce qui suit est une version légèrement rafraîchissante de la fonction.import dataclasses
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, MaxPool2D, UpSampling2D, concatenate
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation
# U-Net(8 couches d'encodeur, 8 couches de décodeur)Construire
@dataclasses.dataclass
class CNN:
input_shape: tuple #Taille de l'image d'entrée
classes: int #Nombre de classes de classification
def __post_init__(self):
#La taille de l'image d'entrée doit être un multiple de 32
assert self.input_shape[0]%32 == 0, 'Input size must be a multiple of 32.'
assert self.input_shape[1]%32 == 0, 'Input size must be a multiple of 32.'
#Bloc codeur
@staticmethod
def encoder(x, blocks, filters, pooling):
for i in range(blocks):
x = Conv2D(filters, (3, 3), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
if pooling:
return MaxPool2D(pool_size=(2, 2))(x), x
else:
return x
#Bloc décodeur
@staticmethod
def decoder(x1, x2, blocks, filters):
x = UpSampling2D(size=(2, 2))(x1)
x = concatenate([x, x2], axis=-1)
for i in range(blocks):
x = Conv2D(filters, (3, 3), padding='same', kernel_initializer='he_normal')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
return x
def create(self):
#encodeur
inputs = Input(shape=(self.input_shape[0], self.input_shape[1], 3)) #Couche d'entrée
x, x1 = self.encoder(inputs, blocks=1, filters=32, pooling=True) #1ère couche
x, x2 = self.encoder(x, blocks=1, filters=64, pooling=True) #2ème couche
x, x3 = self.encoder(x, blocks=1, filters=128, pooling=True) #3e couche
x, x4 = self.encoder(x, blocks=1, filters=256, pooling=True) #4ème couche
x, x5 = self.encoder(x, blocks=2, filters=512, pooling=True) #5ème et 6ème couches
x = self.encoder(x, blocks=2, filters=1024, pooling=False) #7ème et 8ème couches
#Décodeur
x = self.encoder(x, blocks=1, filters=1024, pooling=False) #1ère couche
x = self.decoder(x, x5, blocks=2, filters=512) #2ème et 3ème couches
x = self.decoder(x, x4, blocks=1, filters=256) #4ème couche
x = self.decoder(x, x3, blocks=1, filters=128) #5ème couche
x = self.decoder(x, x2, blocks=1, filters=64) #6ème couche
##7ème et 8ème couches
x = UpSampling2D(size=(2, 2))(x)
x = concatenate([x, x1], axis=-1)
x = Conv2D(64, (3, 3), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
x = Conv2D(self.classes, (1, 1), strides=(1, 1), padding='same', kernel_initializer='he_normal')(x)
outputs = Activation('softmax')(x)
return Model(inputs=inputs, outputs=outputs)
#Construction de réseau
model = CNN(input_shape=image_size, classes=classes).create()
5. Évaluation
Index
Class
average IoU(SegNet)[%]
average IoU(U-Net)[%]
0
Pupil
85.3
86.5
1
Surgical Tape
53.3
57.1
2
Hand
6.57
6.96
3
Eye Retractors
21.9
53.6
4
Iris
74.4
76.0
5
Eyelid
0
0
6
Skin
49.7
48.4
7
Cornea
88.0
88.5
8
Hydro. Cannula
0
31.8
9
Visco. Cannula
0
4.36
10
Cap. Cystotome
0
3.71
11
Rycroft Cannula
0
4.37
12
Bonn Forceps
3.58
7.94
13
Primary Knife
5.35
10.3
14
Phaco. Handpiece
0.0781
12.3
15
Lens Injector
16.4
15.8
16
A/I Handpiece
16.4
20.5
17
Secondary Knife
6.08
11.8
18
Micromanipulator
0
8.99
19
A/I Handpiece Handle
6.49
8.16
20
Cap. Forceps
0
0.337
21
Rycroft Cannula Handle
0
0.00863
22
Phaco. Handpiece Handle
0
4.26
23
Cap. Cystotome Handle
0
0.407
24
Secondary Knife Handle
2.49
3.82
25
Lens Injector Handle
0
0
26
Water Sprayer
─
─
27
Suture Needle
0
0
28
Needle Holder
─
─
29
Charleux Cannula
0
0
30
Vannas Scissors
─
─
31
Primary Knife Handle
0
0
32
Viter. Handpiece
0
0
33
Mendez Ring
─
─
34
Biomarker
─
─
35
Marker
─
─
7. Résumé