2016-01-20 9 views
5

Biorąc pod uwagę to, że w skali szarości obrazu jako 2D Tensor (wymiar W, H) i tensora współrzędnych C (wymiar. Brak, 2). Chcę interpretować wiersze C jako współrzędne w tych współrzędnych, używając pewnego rodzaju interpolacji (dwuliniowy prawdopodobnie będzie dobrze dla mojego przypadku użycia) i przechowywać wynikowe wartości w nowej tensor P (Wymiar Brak, tzn. 1-wymiarowy z tak wieloma wpisami, jak C ma wiersze).Interpolowana próbkowania punktów obrazu z TensorFlow

Czy to możliwe (sprawnie) z TensorFlow? Wszystko, co mogę znaleźć, to funkcje do zmiany rozmiaru (równomierne ponowne próbkowanie, jeśli chcesz) obrazów. Ale nie mogę znaleźć niczego gotowego do wypróbowania na liście współrzędnych.

tj. Liczyłam znaleźć coś jak tf.interpolate() Funkcja:

I = tf.placeholder("float", shape=[128, 128]) 
C = tf.placeholder("float", shape=[None, 2]) 
P = tf.interpolate(I, C, axis=[0, 1], method="linear") 

Idealnie będę szuka rozwiązania, które pozwoliłoby mnie do interpolacji w N wymiarowej tensora I wzdłuż wymiarach M używając C z kształtem (brak, M) i wytworzyć wyjście N-M + 1, jak wskazuje parametr "oś" w powyższym kodzie.

("Obraz" w mojej aplikacji nie jest obrazkiem btw., Jest próbkowanymi danymi z modelu fizycznego (gdy jest używany jako symbol zastępczy) lub alternatywnego modelu uczenia się (gdy jest używany jako zmienna) .Teraz ten model fizyczny ma 2 stopnie swobody, więc interpolacja w "obrazie" jest na razie wystarczająca, ale mogę w przyszłości przyjrzeć się modelom o wyższych wymiarach.)

Jeśli coś takiego nie jest możliwe przy istniejących funkcjach TensorFlow: Gdzie powinien Zaczynam, gdy chcę zaimplementować coś takiego, jak ten operator tf.interpolate()? (dokumentacja i/lub prosty przykładowy kod)

+1

Jest skuteczny sposób na najbliższy sąsiad za pomocą interpolacji tf.gather ... nie jestem pewien o interpolacji liniowej –

+0

Jest 'tf.image.resize_bilinear'. Czy tego nie chcesz? – Albert

+0

@Albert No. To zrobiłoby tylko to, co chcę, gdybym chciał wypróbować obrazy źródłowe we wszystkich punktach siatki. Ale wiersze C mogą być dowolnymi współrzędnymi w obrazie źródłowym. – CliffordVienna

Odpowiedz

7

Nie ma wbudowanego op, który wykonuje tego rodzaju interpolację, ale powinieneś być w stanie to zrobić używając kompozycji istniejących TensorFlow ops. Sugeruję następującą strategię przypadku dwuliniowa:

  1. ze swojego tensora C wskaźników, obliczyć tensory całkowite odpowiadające czterech punktów narożnych. Na przykład (z nazwy zakładając, że pochodzenie jest w lewym górnym rogu):

    top_left = tf.cast(tf.floor(C), tf.int32) 
    
    top_right = tf.cast(
        tf.concat(1, [tf.floor(C[:, 0:1]), tf.ceil(C[:, 1:2])]), tf.int32) 
    
    bottom_left = tf.cast(
        tf.concat(1, [tf.ceil(C[:, 0:1]), tf.floor(C[:, 1:2])]), tf.int32) 
    
    bottom_right = tf.cast(tf.ceil(C), tf.int32) 
    
  2. od siebie tensora reprezentujących konkretny punkt narożny, wyodrębnić wektor wartości od I w tych punktach.Na przykład, dla następującego wzoru czyni to w przypadku 2-D:

    def get_values_at_coordinates(input, coordinates): 
        input_as_vector = tf.reshape(input, [-1]) 
        coordinates_as_indices = (coordinates[:, 0] * tf.shape(input)[1]) + coordinates[:, 1] 
        return tf.gather(input_as_vector, coordinates_as_indices) 
    
    values_at_top_left = get_values_at_coordinates(I, top_left) 
    values_at_top_right = get_values_at_coordinates(I, top_right) 
    values_at_bottom_left = get_values_at_coordinates(I, bottom_left) 
    values_at_bottom_right = get_values_at_coordinates(I, bottom_right) 
    
  3. Oblicz interpolacji w kierunku poziomym pierwsze:

    # Varies between 0.0 and 1.0. 
    horizontal_offset = C[:, 0] - tf.cast(top_left[:, 0], tf.float32) 
    
    horizontal_interpolated_top = (
        ((1.0 - horizontal_offset) * values_at_top_left) 
        + (horizontal_offset * values_at_top_right)) 
    
    horizontal_interpolated_bottom = (
        ((1.0 - horizontal_offset) * values_at_bottom_left) 
        + (horizontal_offset * values_at_bottom_right)) 
    
  4. teraz obliczyć interpolacji w kierunku pionowym

    vertical_offset = C[:, 1] - tf.cast(top_left[:, 1], tf.float32) 
    
    interpolated_result = (
        ((1.0 - vertical_offset) * horizontal_interpolated_top) 
        + (vertical_offset * horizontal_interpolated_bottom)) 
    
+0

Czy to może mieć zastosowanie do zdjęć rgb w partiach? Próbowałem po prostu zmienić 'get_values_at_coordinates()', aby zmienić kształt obrazu na 'input_as_vector = tf.reshape (input, [-1, 3])' (C = 3), ale to nie działa! –

+0

Kod w odpowiedzi jest wyspecjalizowany dla pojedynczego obrazu w skali szarości (jak w pytaniu), ale możesz go zastosować do partii obrazów, używając 'tf.map_fn()', aby zastosować ją w całej partii. – mrry

+0

Czy wszystko zmieniłoby się dla obrazów RGB, to jest przed zastosowaniem 'tf.map_fn()'? Nadal nie udało się go uruchomić. –

2

okazało się to być trudne do najbliższego sąsiada zważywszy, że TF nie ma jeszcze Numpy krojącego ogólność (github issue #206), a fakt, że gather działa tylko w pierwszym wymiarze. Ale oto sposób obejść stosując gather-> transpose-> gather-> wyodrębnić przekątnej

def identity_matrix(n): 
    """Returns nxn identity matrix.""" 
    # note, if n is a constant node, this assert node won't be executed, 
    # this error will be caught during shape analysis 
    assert_op = tf.Assert(tf.greater(n, 0), ["Matrix size must be positive"]) 
    with tf.control_dependencies([assert_op]): 
    ones = tf.fill(n, 1) 
    diag = tf.diag(ones) 
    return diag 

def extract_diagonal(tensor): 
    """Extract diagonal of a square matrix.""" 

    shape = tf.shape(tensor) 
    n = shape[0] 
    assert_op = tf.Assert(tf.equal(shape[0], shape[1]), ["Can't get diagonal of " 
                 "a non-square matrix"]) 

    with tf.control_dependencies([assert_op]): 
    return tf.reduce_sum(tf.mul(tensor, identity_matrix(n)), [0]) 


# create sample matrix 
size=4 
I0=np.zeros((size,size), dtype=np.int32) 
for i in range(size): 
    for j in range(size): 
    I0[i, j] = 10*i+j 

I = tf.placeholder(dtype=np.int32, shape=(size,size)) 
C = tf.placeholder(np.int32, shape=[None, 2]) 
C0 = np.array([[0, 1], [1, 2], [2, 3]]) 
row_indices = C[:, 0] 
col_indices = C[:, 1] 

# since gather only supports dim0, have to transpose 
I1 = tf.gather(I, row_indices) 
I2 = tf.gather(tf.transpose(I1), col_indices) 
I3 = extract_diagonal(tf.transpose(I2)) 

sess = create_session() 
print sess.run([I3], feed_dict={I:I0, C:C0}) 

Więc zaczynając od matrycy jak ten:

array([[ 0, 1, 2, 3], 
     [10, 11, 12, 13], 
     [20, 21, 22, 23], 
     [30, 31, 32, 33]], dtype=int32) 

Kod ten wydobywa przekątnej jeden nad głównym

[array([ 1, 12, 23], dtype=int32)] 

jest jakaś magia dzieje się z [] operatorzy coraz przekształcony Squeeze i Slice

enter image description here