2016-01-20 94 views
5

圖像鑑於點的插值採樣是灰度圖像爲2D張量(尺寸W,H)和座標的張量Ç(DIM。無,2)。我想解釋的的列C如使用某種插值(雙線性很可能是罰款,我使用的情況下)在,樣品在這些座標座標,並將得到的值存儲在一個新的張量P(的尺寸沒有限制,即1維與儘可能多的條目ç具有行)。與TensorFlow

這是可能的(有效)與TensorFlow?我所能找到的都是調整圖像大小(如果你喜歡的等距重採樣)的功能。但是我找不到任何可以在座標列表中進行抽樣的東西。

I.e.我本來希望能夠找到像一個tf.interpolate()函數:

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

理想我要尋找一個解決辦法,讓我在N維張量插值一起使用M個維度ç具有形狀(無,M),併產生N-M + 1維輸出,通過在上面的代碼中的「軸」參數所指示的。 (我的應用程序中的「圖像」不是圖片btw。它是從物理模型(用作佔位符)或替代學習模型(當用作變量時)的採樣數據。現在,這個物理模型有2個自由度,因此插入一個「圖像」對於現在來說已經足夠了,但我可能會在未來考慮更高維的模型。)

在現有的TensorFlow功能不可能的情況下:我開始時,我想實現像這樣的tf.interpolate()運算符? (文檔和/或簡單的示例代碼)

+1

有效率的方式使用tf.gather做近鄰插值...不知道關於線性插值 –

+0

有'tf.image.resize_bilinear'。這不是你想要的嗎? – Albert

+0

@Albert號這隻會做我想要的,如果我想在網格上的所有點上採樣源圖像。但是C的行可以是源圖像中的任何座標。 – CliffordVienna

回答

7

沒有內置執行這種插值運算的,但你應該能夠使用現有的TensorFlow OPS的組成做到這一點。我建議雙線性情況如下策略:

  1. 從你的張量指數C,對應於四個角點計算整數張量。例如(其名稱假設原點在左上角):

    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. 從代表特定角點各張量,在這些點從I提取的值的矢量。例如,對於下面的函數執行此爲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. 計算在水平方向上的內插第一:

    # 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. 現在計算在垂直方向上的內插:

    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

這可以適用於批處理RGB圖像?我試着改變'get_values_at_coordinates()'把圖像重塑爲'input_as_vector = tf.reshape(input,[-1,3])'(C = 3),但它不工作! –

+0

答案中的代碼專門針對單個灰度圖像(如問題中所示),但您可以使用'tf.map_fn()'將其應用於一批圖像,從而將其應用於一批圖像。 – mrry

+0

在應用'tf.map_fn()'之前,RGB圖像會有什麼變化嗎?仍然沒有成功。 –

2

事實證明,這是棘手近鄰因爲TF沒有Numpy切片普遍性(github issue #206),並且gather僅適用於第一維。但這裏有一個方法,通過使用gather-> transpose-> gather->提取對角線來解決它

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}) 

所以用這樣的矩陣開始:

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

此代碼提取一個對角線上方主要

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

有一些魔術[]運營商發生越來越變成SqueezeSlice

enter image description here