2016-01-20 18 views
5

Do là một hình ảnh màu xám tôi như 2D tensor (Dimension W, H) và một tensor tọa độ C (Dim. Không, 2). Tôi muốn giải thích các hàng của C dưới dạng tọa độ trong I, mẫu I tại các tọa độ đó bằng cách sử dụng một số loại nội suy (song tuyến có thể là tốt cho trường hợp sử dụng của tôi) và lưu trữ các giá trị kết quả trong một Tensor mới P (của thứ nguyên Không, tức là 1 chiều với nhiều mục nhập như C có các hàng).suy lấy mẫu của các điểm trong một hình ảnh với TensorFlow

Điều này có thể (hiệu quả) với TensorFlow không? Tất cả những gì tôi có thể tìm thấy là các chức năng để thay đổi kích thước (cách lấy mẫu lại nếu bạn thích) của hình ảnh. Nhưng tôi không thể tìm thấy bất cứ thứ gì ngoài hộp để lấy mẫu tại một danh sách tọa độ.

I.e. Tôi đã có thể mong đợi để tìm một cái gì đó giống như một tf.interpolate() chức năng:

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

Lý tưởng nhất là tôi sẽ tìm kiếm một giải pháp mà sẽ cho phép tôi suy trong một tensor N chiều tôi cùng kích thước M sử dụng một C với hình dạng (Không có, M) và tạo ra đầu ra N-M + 1 chiều, như được chỉ ra bởi tham số "trục" trong mã ở trên.

("Hình ảnh" trong ứng dụng của tôi không phải là hình ảnh btw., Dữ liệu được lấy mẫu từ mô hình vật lý (khi được sử dụng làm trình giữ chỗ) hoặc mô hình học được thay thế (khi được sử dụng làm biến). có 2 bậc tự do, do đó, nội suy trong một "hình ảnh" là đủ cho bây giờ, nhưng tôi có thể nhìn vào các mô hình chiều cao hơn trong tương lai.)

Trong trường hợp một điều như vậy là không thể với các tính năng TensorFlow hiện có: Nơi nên Tôi bắt đầu khi tôi muốn thực hiện một cái gì đó như thế này tf.interpolate() nhà điều hành? (tài liệu và/hoặc mã ví dụ đơn giản)

+1

Có cách hiệu quả để làm khu vực gần xóm suy sử dụng tf.gather ... không chắc chắn về suy tuyến tính –

+0

Có 'tf.image.resize_bilinear'. Đó không phải là những gì bạn muốn? – Albert

+0

@Albert No. Điều này sẽ chỉ làm những gì tôi muốn nếu tôi muốn lấy mẫu hình ảnh nguồn trên tất cả các điểm trên lưới. Nhưng các hàng của C có thể là bất kỳ tọa độ nào trong ảnh nguồn. – CliffordVienna

Trả lời

7

Không có tích hợp sẵn để thực hiện loại nội suy này, nhưng bạn có thể thực hiện bằng cách sử dụng thành phần của các chỉ số TensorFlow hiện có. Tôi muốn đề nghị chiến lược sau đây đối với trường hợp Bilinear:

  1. Từ tensor của bạn C của chỉ số, tensors số nguyên tính toán tương ứng với bốn điểm góc. Ví dụ (với tên giả định rằng nguồn gốc là ở phía trên cùng bên trái):

    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. Từ mỗi tensor đại diện cho một điểm góc đặc biệt, trích xuất một vector của các giá trị từ I tại các điểm.Ví dụ, đối với các chức năng sau đây thực hiện điều này đối với trường hợp 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. Tính nội suy theo hướng ngang đầu tiên:

    # 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. Bây giờ tính toán nội suy theo hướng thẳng đứng:

    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

Điều này có thể áp dụng cho hình ảnh rgb theo đợt không? Tôi đã thử thay đổi 'get_values_at_coordinates()' để định hình lại hình ảnh thành 'input_as_vector = tf.reshape (input, [-1, 3])' (C = 3) nhưng nó không hoạt động! –

+0

Mã trong câu trả lời dành riêng cho một hình ảnh thang độ xám đơn (như trong câu hỏi), nhưng bạn có thể áp dụng nó cho một loạt các hình ảnh bằng cách sử dụng 'tf.map_fn()' để áp dụng nó trên một lô. – mrry

+0

Có gì thay đổi đối với ảnh RGB không, trước khi áp dụng 'tf.map_fn()'? Vẫn không thể làm cho nó hoạt động. –

2

này hóa ra là khó khăn cho hàng xóm gần nhất cho rằng TF chưa có Numpy slicing generality (github issue #206) và thực tế là gather chỉ hoạt động trên thứ nguyên đầu tiên. Nhưng đây là một cách để làm việc xung quanh nó bằng cách sử dụng gather-> transpose-> gather-> trích chéo

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

Vì vậy, bắt đầu với một ma trận như thế này:

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

Mã này chiết xuất một đường chéo trên chính

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

có một số kỳ diệu xảy ra với [] các nhà khai thác bị biến thành SqueezeSlice

enter image description here

Các vấn đề liên quan