Tensorflow T-Net de entrada máscara de segmentación

Akash Parikh:

Soy nuevo en tensorflow y segmentación semántica.

Estoy diseñando un T-Net para segmentaion semántica. Cada imagen tiene un objeto que quiero clasificar. Pero en total tengo imágenes de 10 objetos diferentes. Estoy confundido, ¿cómo puedo preparar mi entrada de la máscara? Se consideró como la segmentación multi-etiqueta o sólo para una clase?

¿Debo convertir mi entrada a una codificada caliente? ¿Debo usar to_categorical? Encuentro exaples para la segmentación multi-clase, pero no sé, Si ese es el caso aquí. Debido a que en una imagen que sólo tengo un objeto a detectar / clasificar.

He intentado utilizar esto como mi código de entrada. Pero no estoy seguro, lo que estoy haciendo es correcto o no.

#Generation of batches of image and mask
class DataGen(keras.utils.Sequence):
    def __init__(self, image_names, path, batch_size, image_size=128):
        self.image_names = image_names
        self.path = path
        self.batch_size = batch_size
        self.image_size = image_size

    def __load__(self, image_name):
        # Path
        image_path = os.path.join(self.path, "images/aug_test", image_name) + ".png"
        mask_path = os.path.join(self.path, "masks/aug_test",image_name) +  ".png"

        # Reading Image
        image = cv2.imread(image_path, 1)
        image = cv2.resize(image, (self.image_size, self.image_size))


        # Reading Mask
        mask = cv2.imread(mask_path, -1)
        mask = cv2.resize(mask, (self.image_size, self.image_size))

        ## Normalizaing 
        image = image/255.0
        mask = mask/255.0

        return image, mask

    def __getitem__(self, index):
        if(index+1)*self.batch_size > len(self.image_names):
            self.batch_size = len(self.image_names) - index*self.batch_size

        image_batch = self.image_names[index*self.batch_size : (index+1)*self.batch_size]

        image = []
        mask  = []

        for image_name in image_batch:
            _img, _mask = self.__load__(image_name)
            image.append(_img)
            mask.append(_mask)

        #This is where I am defining my input
        image = np.array(image)
        mask  = np.array(mask)
        mask = tf.keras.utils.to_categorical(mask, num_classes=10, dtype='float32') #Is this true?


        return image, mask

    def __len__(self):
        return int(np.ceil(len(self.image_names)/float(self.batch_size)))

¿Es esto cierto? Si lo es, entonces, para obtener la etiqueta / clase como salida lo que debería cambiar en mi entrada? ¿Debo cambiar el valor de píxel de la máscara de acuerdo a mi clase?

Aquí está mi arquitectura T-Net.

# Convolution and deconvolution Blocks

def down_scaling_block(x, filters, kernel_size=(3, 3), padding="same", strides=1):
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(x)
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(conv)
    pool = keras.layers.MaxPool2D((2, 2), (2, 2))(conv)
    return conv, pool

def up_scaling_block(x, skip, filters, kernel_size=(3, 3), padding="same", strides=1):
    conv_t = keras.layers.UpSampling2D((2, 2))(x)
    concat = keras.layers.Concatenate()([conv_t, skip])
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(concat)
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(conv)
    return conv

def bottleneck(x, filters, kernel_size=(3, 3), padding="same", strides=1):
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(x)
    conv = keras.layers.Conv2D(filters, kernel_size, padding=padding, strides=strides, activation="relu")(conv)
    return conv

def UNet():
    filters = [16, 32, 64, 128, 256]
    inputs = keras.layers.Input((image_size, image_size, 3))

    '''inputs2 = keras.layers.Input((image_size, image_size, 1))
       conv1_2, pool1_2 = down_scaling_block(inputs2, filters[0])'''

    Input = inputs
    conv1, pool1 = down_scaling_block(Input, filters[0])
    conv2, pool2 = down_scaling_block(pool1, filters[1])
    conv3, pool3 = down_scaling_block(pool2, filters[2])
    '''conv3 = keras.layers.Conv2D(filters[2], kernel_size=(3,3), padding="same", strides=1, activation="relu")(pool2)
    conv3 = keras.layers.Conv2D(filters[2], kernel_size=(3,3), padding="same", strides=1, activation="relu")(conv3)
    drop3 = keras.layers.Dropout(0.5)(conv3)
    pool3 = keras.layers.MaxPooling2D((2,2), (2,2))(drop3)'''
    conv4, pool4 = down_scaling_block(pool3, filters[3])

    bn = bottleneck(pool4, filters[4])

    deConv1 = up_scaling_block(bn, conv4, filters[3]) #8 -> 16
    deConv2 = up_scaling_block(deConv1, conv3, filters[2]) #16 -> 32
    deConv3 = up_scaling_block(deConv2, conv2, filters[1]) #32 -> 64
    deConv4 = up_scaling_block(deConv3, conv1, filters[0]) #64 -> 128

    outputs = keras.layers.Conv2D(10, (1, 1), padding="same", activation="softmax")(deConv4)
    model = keras.models.Model(inputs, outputs)
    return model

model = UNet()
model.compile(optimizer='adam', loss="categorical_crossentropy", metrics=["acc"])

train_gen = DataGen(train_img, train_path, image_size=image_size, batch_size=batch_size)
valid_gen = DataGen(valid_img, train_path, image_size=image_size, batch_size=batch_size)
test_gen = DataGen(test_img, test_path, image_size=image_size, batch_size=batch_size)

train_steps = len(train_img)//batch_size
valid_steps = len(valid_img)//batch_size

model.fit_generator(train_gen, validation_data=valid_gen, steps_per_epoch=train_steps, validation_steps=valid_steps, 
                    epochs=epochs)

Espero que he explicado mi pregunta correctamente. Cualquier ayuda appriciated!

ACTUALIZACIÓN: He cambiado el valor de cada píxel de máscara según la clase de objeto. (Si la imagen contiene objeto que quiero clasificar como objeto no. 2, a continuación, he cambiado el valor de pixel máscara a 2. todo el conjunto de máscara contendrá 0 (bg) y 2 (objeto). De acuerdo con ello para cada objeto, la máscara contendrá 0 y 3, 0 y 10 etc.)

Aquí primero cambiado la máscara a binario y luego, si el valor de pixel es mayor que 1, lo cambié a 1 o 2 o 3. (de acuerdo con objeto / clase no.)

Entonces les convirtió al one_hot con to_categorical como se muestra en mi código. carreras de entrenamiento, pero la red duerma aprender nada. La precisión y mantener las pérdidas de balanceo entre dos valores. ¿Cuál es mi error aquí? ¿Estoy cometiendo un error al generar la máscara (cambiando el valor de píxeles?) O en el to_categorical función?

PROBLEMA ENCONTRADO: yo estaba haciendo un error al crear la máscara .. yo estaba leyendo imagen con cv2, que lee la imagen como heightxwidth .. yo estaba creando máscara con valores de píxel según la clase, después de considerar mi Dimensión imagen como widthxheight .. que estaba causando problemas y la toma de red no aprendan nada .. se está trabajando ahora ..

javierjsa :

Cada imagen tiene un objeto que quiero clasificar. Pero en total tengo imágenes de 10 objetos diferentes. Estoy confundido, ¿cómo puedo preparar mi entrada de la máscara? Se consideró como la segmentación multi-etiqueta o sólo para una clase?

Si el conjunto de datos tiene N etiquetas diferentes (es decir: 0 - fondo, 1 - perros, 2 -Los gatos ...), usted tiene un problema de múltiples clases, incluso si las imágenes contienen único tipo de objeto.

¿Debo convertir mi entrada a una codificada caliente? ¿Debo usar to_categorical?

Sí, debe codificar uno en caliente de las etiquetas. Usando to_categorical se reduce al formato de la fuente de sus etiquetas. Digamos que tiene N clases y sus etiquetas son (altura, ancho, 1), donde cada píxel tiene un valor en el rango [0, N). En ese caso keras.utils.to_categorical (etiqueta, N) proporcionará una etiqueta de flotación (altura, anchura, N), donde cada píxel es 0 ó 1. Y usted no tiene que dividir por 255.

si su formato de origen es diferente, puede que tenga que utilizar una función personalizada para obtener el mismo formato de salida.

Echa un vistazo a esta cesión temporal (no es mi trabajo): Keras-UNET . Los cuadernos carpeta contienen dos ejemplos para entrenar a un T-red en pequeños conjuntos de datos. Ellos no son multiclase, pero es fácil que ir paso a paso para utilizar su propio conjunto de datos. Star de la carga de las etiquetas como:

im = Image.open(mask).resize((512,512))
im = to_categorical(im,NCLASSES)

reformar y normalizar así:

x = np.asarray(imgs_np, dtype=np.float32)/255
y = np.asarray(masks_np, dtype=np.float32)
y = y.reshape(y.shape[0], y.shape[1], y.shape[2], NCLASSES)
x = x.reshape(x.shape[0], x.shape[1], x.shape[2], 3)

adaptar su modelo a NCLASSES

model = custom_unet(
input_shape,
use_batch_norm=False,
num_classes=NCLASSES,
filters=64,
dropout=0.2,
output_activation='softmax')

seleccione la pérdida correcta:

from keras.losses import categorical_crossentropy
model.compile(    
   optimizer=SGD(lr=0.01, momentum=0.99),
   loss='categorical_crossentropy',    
   metrics=[iou, iou_thresholded])

Espero eso ayude

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=285219&siteId=1
Recomendado
Clasificación