TensorFlow:旋转图像和点时以任意角度偏移

时间:2018-11-28 16:46:47

标签: python tensorflow

我有一张图片和3分。我想一起旋转图像和点。为此,我将图像旋转某个角度 a ,然后将这些点旋转相同的角度。 将 a 固定为python标量(例如pi / 3)时,旋转效果很好(请参见下图,蓝色点在黑色正方形上)。

enter image description here

angle = tf.random_uniform([])随机选择角度时,旋转的图像和旋转的点之间会有偏移。

enter image description here

下面是重现此行为的完整代码。

我的问题是:如何解释这种行为并纠正它?

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# create toy image
square = np.zeros((1, 800, 800, 3))
square[:, 100:400, 100:400] = 1
square[:, 140:180, 140:180] = 0
square[:, 240:280, 240:280] = 0
square[:, 280:320, 280:320] = 0
kp = np.array([[160, 160], [260, 260], [300, 300]])
kp = np.expand_dims(kp, axis=0)

def _rotate(image, keypoints, angle, keypoints_num):
    image = tf.contrib.image.rotate(image, angle)
    cos, sin = tf.cos(angle), tf.sin(angle)
    x0, y0  = .5, .5
    rot_mat = tf.Variable([[cos, -sin], [sin, cos]], trainable=False)
    keypoints -= (x0, y0)
    keypoints = tf.reshape(keypoints, shape=[-1, 2])
    keypoints = tf.matmul(keypoints, rot_mat)
    keypoints = tf.reshape(keypoints, shape=[-1, keypoints_num, 2])
    keypoints += (x0, y0)
    return image, keypoints


image = tf.placeholder(tf.float32, [None, 800, 800, 3])
keypoints = tf.placeholder(tf.float32, [None, 3, 2])

angle = np.pi / 3 # fix angle, works fine
#angle = tf.random_uniform([]) # random angle, does not work
image_r, keypoints_r = _rotate(image, keypoints / 800, angle, 3)
keypoints_r *= 800

sess = tf.Session()
sess.run(tf.initialize_all_variables())

imr, kr = sess.run([image_r, keypoints_r], feed_dict={image: square, keypoints:kp})

# displaying output
plt.imshow(imr[0])
plt.scatter(*zip(*kr[0]))
plt.savefig('rotation.jpg')

1 个答案:

答案 0 :(得分:2)

问题在这里:

rot_mat = tf.Variable([[cos, -sin], [sin, cos]], trainable=False)

由于rot_mat是一个变量,因此仅在变量初始化时才设置其值,

sess.run(tf.initialize_all_variables())

因此,此时rot_mat得到了一些值(使用cossin,这又取决于angle,这是随机的),并且不再改变。然后,当您这样做时:

imr, kr = sess.run([image_r, keypoints_r], feed_dict={image: squares, keypoints:kps})

这是对run的另一个调用,因此tf.random_uniform会产生一个新值,但是rot_mat仍保持与初始化时相同的值。由于图像的旋转方向是:

image = tf.contrib.image.rotate(image, angle)

关键点旋转:

keypoints = tf.matmul(keypoints, rot_mat)

旋转不匹配。最简单的解决方法是不要为rot_mat使用变量:

rot_mat = [[cos, -sin], [sin, cos]]

这样,代码可以正常工作。如果确实需要rot_mat作为变量,则可以,但是还有很多工作要做,这里似乎不需要。如果您不喜欢rot_mat作为列表,而是想使用合适的张量,则可以使用tf.convert_to_tensor

rot_mat = tf.convert_to_tensor([[cos, -sin], [sin, cos]])