python - TensorFlow:以随机角度旋转图像和点时的偏移量
问题描述
我有一个图像和 3 个点。我想一起旋转图像和点。为此,我将图像旋转了某个角度a并将点旋转了相同的角度。当a固定为 python 标量(例如 pi/3)时,旋转工作正常(参见下图,蓝点位于深色方块上)。
当使用 随机选择角度时angle = tf.random_uniform([])
,旋转图像和旋转点之间存在偏移。
以下是重现此行为的完整代码。
我的问题是:如何解释这种行为并纠正它?
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')
解决方案
问题在这里:
rot_mat = tf.Variable([[cos, -sin], [sin, cos]], trainable=False)
由于rot_mat
是一个变量,它的值只有在变量初始化时才被设置,这里:
sess.run(tf.initialize_all_variables())
所以在那一点上rot_mat
获得了一些价值(使用cos
and sin
,这又取决于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]])
推荐阅读
- node.js - Web3.js 1.0.0 contract.getPastEvents 返回 BigNuber 错误
- kubernetes - 如何手动从 Kubernetes 卸载/删除分蘖?
- .net - AWS SQS 重新处理正在进行的消息
- spring - Spring 5 不提供静态内容
- android - Google Play 商店显示更新按钮而不是打开按钮
- javascript - 在提交表单之前读取 JavaScript 代码中的 Rails 表单数据
- php - 来自字符串 PHP 的 Geenrate 方法调用
- elasticsearch - Grafana - 将弹性字符串值转换为
- python - 减去 pandas 中的日期时间总是等于 0
- c++ - Qt 通过退出显示回溯