訂閱
糾錯
加入自媒體

計算機視覺的自動編碼器有無限可能

介紹

大家好,在過去的幾個月中,我致力于計算機視覺自動編碼器 的開發(fā),坦白地說,我對使用它們可以構(gòu)建的大量應用程序印象深刻。本文的目的是解釋自動編碼器,可以使用自動編碼器構(gòu)建的一些應用程序,未連接的編碼器-解碼器層的缺點以及諸如U-Net之類的體系結(jié)構(gòu)如何幫助提高自動編碼器的質(zhì)量。

1. 什么是自動編碼器?

簡單來說,自動編碼器是一種順序神經(jīng)網(wǎng)絡,由兩個組件組成,一個是編碼器,另一個是**解碼器。**供我們參考,假設我們正在處理圖像,**編碼器的工作是從圖像中提取特征,從而減小圖像的高度和寬度,但同時增加其深度,**即編碼器對圖像進行了潛在表示,F(xiàn)在,解碼器的工作是解碼潛在表示并形成滿足我們給定標準的圖像。從下面的圖像中可以很容易理解。

圖1:自動編碼器架構(gòu)自動編碼器的輸入和輸出都是圖像,在下面給出的示例中,自動編碼器將輸入轉(zhuǎn)換為Monet樣式的繪畫。

圖2:自動編碼器的輸入和輸出

2. 自動編碼器,用于語義分割和未連接的編碼器-解碼器層的缺點語義分割

是指為圖像的每個像素分配標簽,從而將屬于同一對象的像素分組在一起,以下圖像將幫助你更好地理解這一點。

圖3:圖像及其語義分割輸出

以下代碼定義了用于此應用程序的自動編碼器體系結(jié)構(gòu):

myTransformer = tf.keras.models.Sequential([

## defining encoder 

    tf.keras.layers.Input(shape= (256, 256, 3)),

    tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.MaxPool2D(pool_size = (2, 2)),

    tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), strides = (2,2), activation = 'relu',padding = 'valid'),

    tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), strides = (2,2), activation = 'relu',padding = 'same'),

    tf.keras.layers.MaxPool2D(pool_size = (2, 2)),

    tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 256, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 512, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    ## defining decoder path

    tf.keras.layers.UpSampling2D(size = (2,2)),

    tf.keras.layers.Conv2D(filters = 256, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.UpSampling2D(size = (2,2)),

    tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.UpSampling2D(size = (2,2)),

    tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.UpSampling2D(size = (2,2)),

    tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu', padding = 'same'),

    tf.keras.layers.Conv2D(filters = 3, kernel_size = (3,3), activation = 'relu', padding = 'same'),
])

請參考本文的參考部分以獲取完整的訓練渠道。以下是你使用此網(wǎng)絡可獲得的結(jié)果

圖4:用于語義分割的自動編碼器結(jié)果

很好,看來我們的自動編碼器可以很好地解決此問題,但是,你是否覺得所獲得的結(jié)果有點模糊,可能出了什么問題?

2.1 自動編碼器中未連接的編碼器-解碼器層的缺點

這種模糊性的原因在于**,**即使我們可以實現(xiàn)目標,但輸出質(zhì)量還不夠好。因此,當信息從編碼器傳遞到解碼器時,功能映射就會丟失。因此,最合乎邏輯的方法是將解碼器層與編碼器層中的對應層連接起來,從而補償重建圖像時丟失的特征,這就是像U-Net這樣的體系結(jié)構(gòu)。從下圖可以更好地理解這一點:

圖5:Unet體系結(jié)構(gòu)

看一下解碼器和編碼器層之間的互連,它們使像U-Net這樣的體系結(jié)構(gòu)優(yōu)于原始自動編碼器。如此說來,讓我們討論一些可以使用UNet構(gòu)建的實際應用程序。

3. 自動編碼器的一些實際應用

3.1 通過預測相關(guān)掩碼進行圖像分割

這是你遇到的另一個分割問題,與上述示例不同。給定一幅圖像,將要求你為圖像中的目標物體預測一個二進制掩碼,當你將此預測掩碼與給定圖像相乘時,你將獲得目標圖像。此類預測模型可用于查找腎臟中癌細胞或結(jié)石的位置。因為一張圖片的價值勝過千言萬語,這里有一張圖片可以說明我所說的:

圖6:實際的分割

這是定義所用模型架構(gòu)的代碼。

# defining Conv2d block for our u-net

# this block essentially performs 2 convolution

def Conv2dBlock(inputTensor, numFilters, kernelSize = 3, doBatchNorm = True):

    #first Conv

    x = tf.keras.layers.Conv2D(filters = numFilters, kernel_size = (kernelSize, kernelSize),

                                                    kernel_initializer = 'he_normal', padding = 'same') (inputTensor)

    if doBatchNorm:
               x = tf.keras.layers.BatchNormalization()(x)

    x =tf.keras.layers.Activation('relu')(x)

    #Second Conv

    x = tf.keras.layers.Conv2D(filters = numFilters, kernel_size = (kernelSize, kernelSize),
                                                          kernel_initializer = 'he_normal', padding = 'same') (x)

    if doBatchNorm:
               x = tf.keras.layers.BatchNormalization()(x)

    x = tf.keras.layers.Activation('relu')(x)

    return x


# Now defining Unet 

def GiveMeUnet(inputImage, numFilters = 16, droupouts = 0.1, doBatchNorm = True):

    # defining encoder Path
          c1 = Conv2dBlock(inputImage, numFilters * 1, kernelSize = 3, doBatchNorm = doBatchNorm)
          p1 = tf.keras.layers.MaxPooling2D((2,2))(c1)
          p1 = tf.keras.layers.Dropout(droupouts)(p1)
          c2 = Conv2dBlock(p1, numFilters * 2, kernelSize = 3, doBatchNorm = doBatchNorm)
          p2 = tf.keras.layers.MaxPooling2D((2,2))(c2)
          p2 = tf.keras.layers.Dropout(droupouts)(p2)
          c3 = Conv2dBlock(p2, numFilters * 4, kernelSize = 3, doBatchNorm = doBatchNorm)
          p3 = tf.keras.layers.MaxPooling2D((2,2))(c3)
          p3 = tf.keras.layers.Dropout(droupouts)(p3)
          c4 = Conv2dBlock(p3, numFilters * 8, kernelSize = 3, doBatchNorm = doBatchNorm)
          p4 = tf.keras.layers.MaxPooling2D((2,2))(c4)
          p4 = tf.keras.layers.Dropout(droupouts)(p4)
          c5 = Conv2dBlock(p4, numFilters * 16, kernelSize = 3, doBatchNorm = doBatchNorm)
          # defining decoder path
          u6 = tf.keras.layers.Conv2DTranspose(numFilters*8, (3, 3), strides = (2, 2), padding = 'same')(c5)
          u6 = tf.keras.layers.concatenate([u6, c4])
          u6 = tf.keras.layers.Dropout(droupouts)(u6)
          c6 = Conv2dBlock(u6, numFilters * 8, kernelSize = 3, doBatchNorm = doBatchNorm)
          u7 = tf.keras.layers.Conv2DTranspose(numFilters*4, (3, 3), strides = (2, 2), padding = 'same')(c6)
          u7 = tf.keras.layers.concatenate([u7, c3])
          u7 = tf.keras.layers.Dropout(droupouts)(u7)
          c7 = Conv2dBlock(u7, numFilters * 4, kernelSize = 3, doBatchNorm = doBatchNorm)
          u8 = tf.keras.layers.Conv2DTranspose(numFilters*2, (3, 3), strides = (2, 2), padding = 'same')(c7)
          u8 = tf.keras.layers.concatenate([u8, c2])
          u8 = tf.keras.layers.Dropout(droupouts)(u8)
          c8 = Conv2dBlock(u8, numFilters * 2, kernelSize = 3, doBatchNorm = doBatchNorm)
          u9 = tf.keras.layers.Conv2DTranspose(numFilters*1, (3, 3), strides = (2, 2), padding = 'same')(c8)
          u9 = tf.keras.layers.concatenate([u9, c1])
          u9 = tf.keras.layers.Dropout(droupouts)(u9)
          c9 = Conv2dBlock(u9, numFilters * 1, kernelSize = 3, doBatchNorm = doBatchNorm)
          output = tf.keras.layers.Conv2D(1, (1, 1), activation = 'sigmoid')(c9)
          model = tf.keras.Model(inputs = [inputImage], outputs = [output])
          return model

請參考本文的參考部分以了解整個訓練流程。

3.2 根據(jù)衛(wèi)星圖像預測路線圖

你可以將上述架構(gòu)應用于在衛(wèi)星圖像中查找道路,因為如果你想到這一點,那么這又是一個分割問題,使用適當?shù)臄?shù)據(jù)集就可以輕松實現(xiàn)此任務。與往常一樣,這是一個顯示此概念的圖像。

圖7:根據(jù)航拍圖像預測路線

與往常一樣,你可以在“參考”部分中找到代碼。

3.3 使用自動編碼器實現(xiàn)超分辨率

你是否曾在放大低分辨率圖像時注意到發(fā)生的像素失真?超分辨率本質(zhì)上是指提高低分辨率圖像的分辨率,F(xiàn)在,也可以僅通過對圖像進行上采樣并使用雙線性插值法來填充新的像素值來實現(xiàn)此目的,但是由于你無法增加圖像中的信息量,因此生成的圖像將變得模糊為了解決這個問題,我們教了一個神經(jīng)網(wǎng)絡來預測高分辨率圖像的像素值(**本質(zhì)上是增加信息)。**你可以使用自動編碼器來實現(xiàn)這一點(這就是本文標題為“無限可能的世界”的原因!)。你只需在模型的輸出層中將通道數(shù)更改為3(而不是1),就可以對上述體系結(jié)構(gòu)進行一些小的更改。這里有幾個結(jié)果:

結(jié)論

這些只是我設法使用自動編碼器構(gòu)建的一些應用程序,但可能性是無限的,因此,我建議讀者充分發(fā)揮自己的創(chuàng)造力,并找到更好的自動編碼器用途。謝謝。

參考

1.) Vanilla AutoEncoder

2.) UNet Code and  Binary Segmentation

3.) UNet for Road map generation from aerial Images.

4.) Super Resolution

聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權(quán)或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

    掃碼關(guān)注公眾號
    OFweek人工智能網(wǎng)
    獲取更多精彩內(nèi)容
    文章糾錯
    x
    *文字標題:
    *糾錯內(nèi)容:
    聯(lián)系郵箱:
    *驗 證 碼:

    粵公網(wǎng)安備 44030502002758號