2017-05-18 23 views
5

Mam autodenoder, który pobiera obraz jako dane wejściowe i tworzy nowy obraz jako wynik.Rekonstrukcja obrazu po użyciu funkcji extract_image_patches

Obraz wejściowy (1x1024x1024x3) jest dzielony na łatki (1024x32x32x3) przed dostarczeniem do sieci.

Po uzyskaniu danych wyjściowych, również partii łat wielkości 1024x32x32x3, chcę odtworzyć obraz o wymiarach 1024x1024x3. Pomyślałem, że mam to sussed przez proste przekształcenie, ale oto co się stało.

Po pierwsze, obraz jako przeczytane przez Tensorflow: Input image

I połatany obraz z następującego kodu

patch_size = [1, 32, 32, 1] 
patches = tf.extract_image_patches([image], 
    patch_size, patch_size, [1, 1, 1, 1], 'VALID') 
patches = tf.reshape(patches, [1024, 32, 32, 3]) 

Oto kilka plastrów z tego obrazka:

Patched input #168Patched input #169

Ale to jest, gdy przekształcam dane tej poprawki z powrotem w n obraz, że rzeczy mają kształt gruszki.

reconstructed = tf.reshape(patches, [1, 1024, 1024, 3]) 
converted = tf.image.convert_image_dtype(reconstructed, tf.uint8) 
encoded = tf.image.encode_png(converted) 

Reconstructed output

W tym przykładzie, operacja nie została wykonana między łatanie i odbudowę. Zrobiłem version of the code, którego możesz użyć do przetestowania tego zachowania. Aby go użyć, należy wykonać:

echo "/path/to/test-image.png" > inputs.txt 
mkdir images 
python3 image_test.py inputs.txt images 

Kod uczyni jeden obraz wejściowy, jeden plaster obrazu i jednego obrazu dla każdego z 1024 plastrów każdego obrazu wejściowego, więc wypowiedzieć się linie, które tworzą wejście i obrazy wyjściowe, jeśli chodzi tylko o zapisanie wszystkich poprawek.

Ktoś proszę wyjaśnić, co się stało :(

+0

CJxD, rzucić okiem na moją odpowiedź. Możesz wydrukować łatki i zrekonstruować je w pierwszej części, aby zobaczyć błąd, który wystąpił w twoim kodzie. Mam nadzieję, że moja odpowiedź ci pomoże. – hars

+0

"że rzeczy mają kształt gruszki". Pożyczę to wyrażenie! –

Odpowiedz

3

Zastosowanie Aktualizacja # 2 - Jeden mały przykład dla zadania: (TF 1.0)

Zważywszy obraz wielkości (4,4,1) w przeliczeniu na płaty wielkości (4,2,2,1) i zrekonstruowano je z powrotem do obrazu

import tensorflow as tf 
image = tf.constant([[[1], [2], [3], [4]], 
       [[5], [6], [7], [8]], 
       [[9], [10], [11], [12]], 
       [[13], [14], [15], [16]]]) 

patch_size = [1,2,2,1] 
patches = tf.extract_image_patches([image], 
    patch_size, patch_size, [1, 1, 1, 1], 'VALID') 
patches = tf.reshape(patches, [4, 2, 2, 1]) 
reconstructed = tf.reshape(patches, [1, 4, 4, 1]) 
rec_new = tf.space_to_depth(reconstructed,2) 
rec_new = tf.reshape(rec_new,[4,4,1]) 

sess = tf.Session() 
I,P,R_n = sess.run([image,patches,rec_new]) 
print(I) 
print(I.shape) 
print(P.shape) 
print(R_n) 
print(R_n.shape) 

wyjściowa:.

[[[ 1][ 2][ 3][ 4]] 
    [[ 5][ 6][ 7][ 8]] 
    [[ 9][10][11][12]] 
    [[13][14][15][16]]] 
(4, 4, 1) 
(4, 2, 2, 1) 
[[[ 1][ 2][ 3][ 4]] 
    [[ 5][ 6][ 7][ 8]] 
    [[ 9][10][11][12]] 
    [[13][14][15][16]]] 
(4,4,1) 

Aktualizacja - 3 kanały (debugowania ..)

pracy wyłącznie p = sqrt (h)

import tensorflow as tf 
import numpy as np 
c = 3 
h = 1024 
p = 32 

image = tf.random_normal([h,h,c]) 
patch_size = [1,p,p,1] 
patches = tf.extract_image_patches([image], 
    patch_size, patch_size, [1, 1, 1, 1], 'VALID') 
patches = tf.reshape(patches, [h, p, p, c]) 
reconstructed = tf.reshape(patches, [1, h, h, c]) 
rec_new = tf.space_to_depth(reconstructed,p) 
rec_new = tf.reshape(rec_new,[h,h,c]) 

sess = tf.Session() 
I,P,R_n = sess.run([image,patches,rec_new]) 
print(I.shape) 
print(P.shape) 
print(R_n.shape) 
err = np.sum((R_n-I)**2) 
print(err) 

wyjściowa:

(1024, 1024, 3) 
(1024, 32, 32, 3) 
(1024, 1024, 3) 
0.0 

Aktualizacja 2

odtworzenie z wyjście output_image_patches wydaje się trudne. Używał innych funkcji do wyodrębniania łat i odwracał proces, aby zrekonstruować, co wydaje się łatwiejsze.

import tensorflow as tf 
import numpy as np 
c = 3 
h = 1024 
p = 128 


image = tf.random_normal([1,h,h,c]) 

# Image to Patches Conversion 
pad = [[0,0],[0,0]] 
patches = tf.space_to_batch_nd(image,[p,p],pad) 
patches = tf.split(patches,p*p,0) 
patches = tf.stack(patches,3) 
patches = tf.reshape(patches,[(h/p)**2,p,p,c]) 

# Do processing on patches 
# Using patches here to reconstruct 
patches_proc = tf.reshape(patches,[1,h/p,h/p,p*p,c]) 
patches_proc = tf.split(patches_proc,p*p,3) 
patches_proc = tf.stack(patches_proc,axis=0) 
patches_proc = tf.reshape(patches_proc,[p*p,h/p,h/p,c]) 

reconstructed = tf.batch_to_space_nd(patches_proc,[p, p],pad) 

sess = tf.Session() 
I,P,R_n = sess.run([image,patches,reconstructed]) 
print(I.shape) 
print(P.shape) 
print(R_n.shape) 
err = np.sum((R_n-I)**2) 
print(err) 

wyjściowa:

(1, 1024, 1024, 3) 
(64, 128, 128, 3) 
(1, 1024, 1024, 3) 
0.0 

Można zobaczyć inne funkcje transformacji tensor chłodny tutaj: https://www.tensorflow.org/api_guides/python/array_ops

+0

Twój drugi przykład ulega awarii, jeśli ustawię inny rozmiar poprawki. p = 64 na przykład – Temak

+0

Musisz dostosować "h" podczas przekształcania poprawek. Zaktualizuje to teraz. – hars

+0

To zawiesza się, nawet jeśli ustawisz 'tf.reshape (łatki, [(h/p) ** 2, p, p, c])' – Temak

2

tf.extract_image_patches jest cichy trudne w użyciu, jak to robi wiele rzeczy w tle.

Jeśli potrzebujesz tylko nie nakładania się, to o wiele łatwiej jest napisać to samodzielnie. Możesz zrekonstruować pełny obraz, odwracając wszystkie operacje w image_to_patches.

przykładowy kod (Działki oryginalnego obrazu i poprawek):

import tensorflow as tf 
from skimage import io 
import matplotlib.pyplot as plt 


def image_to_patches(image, patch_height, patch_width): 
    # resize image so that it's dimensions are dividable by patch_height and patch_width 
    image_height = tf.cast(tf.shape(image)[0], dtype=tf.float32) 
    image_width = tf.cast(tf.shape(image)[1], dtype=tf.float32) 
    height = tf.cast(tf.ceil(image_height/patch_height) * patch_height, dtype=tf.int32) 
    width = tf.cast(tf.ceil(image_width/patch_width) * patch_width, dtype=tf.int32) 

    num_rows = height // patch_height 
    num_cols = width // patch_width 
    # make zero-padding 
    image = tf.squeeze(tf.image.resize_image_with_crop_or_pad(image, height, width)) 

    # get slices along the 0-th axis 
    image = tf.reshape(image, [num_rows, patch_height, width, -1]) 
    # h/patch_h, w, patch_h, c 
    image = tf.transpose(image, [0, 2, 1, 3]) 
    # get slices along the 1-st axis 
    # h/patch_h, w/patch_w, patch_w,patch_h, c 
    image = tf.reshape(image, [num_rows, num_cols, patch_width, patch_height, -1]) 
    # num_patches, patch_w, patch_h, c 
    image = tf.reshape(image, [num_rows * num_cols, patch_width, patch_height, -1]) 
    # num_patches, patch_h, patch_w, c 
    return tf.transpose(image, [0, 2, 1, 3]) 


image = io.imread('http://www.petful.com/wp-content/uploads/2011/09/slow-blinking-cat.jpg') 
print('Original image shape:', image.shape) 
tile_size = 200 
image = tf.constant(image) 
tiles = image_to_patches(image, tile_size, tile_size) 

sess = tf.Session() 
I, tiles = sess.run([image, tiles]) 
print(I.shape) 
print(tiles.shape) 


plt.figure(figsize=(1 * (4 + 1), 5)) 
plt.subplot(5, 1, 1) 
plt.imshow(I) 
plt.title('original') 
plt.axis('off') 
for i, tile in enumerate(tiles): 
    plt.subplot(5, 5, 5 + 1 + i) 
    plt.imshow(tile) 
    plt.title(str(i)) 
    plt.axis('off') 
plt.show()