从 python 中的旋转矩形生成新图像
Generate new image from rotated rectangle in python
我正在研究图像查看器的导出功能。我在总是形成一个矩形的图像上有 4 个点,但该矩形可能会旋转。我也有矩形的旋转。现在我想从输入图像和我上面解释的值生成一个新图像。我怎样才能做到这一点 python ?下图可能会让我更清楚地了解我真正想做的事情:
我将使用下面的图片为例:
创建想要的矩形
信息丰富,你说你得到了我刚刚在这里为示例创建的矩形本身,如下所示:
# creating source points - informative
xx = [50, 50, 200, 200]
yy = [30, 60, 30, 60]
alpha = np.pi/6 # 30 degrees
rotMat = np.array([[np.cos(alpha), -1*np.sin(alpha)],
[np.sin(alpha), np.cos(alpha)]])
src_pts = []
for [x, y] in zip(xx,yy):
src_pts.append(rotMat.dot(np.array([x, y])) + np.array([3, 7]))
src_pts = np.array(src_pts)
生成矩形坐标后:
[[ 31.30127019 57.98076211]
[ 16.30127019 83.96152423]
[161.20508076 132.98076211]
[146.20508076 158.96152423]]
我们通过检查向量的点积是否为 0(表示它们之间成 90 度)来得到边:
if np.isclose((src_pts[1] - src_pts[0]).dot(src_pts[2] - src_pts[0]), 0):
side1 = np.around(np.linalg.norm(src_pts[1] - src_pts[0]), 2)
side2 = np.around(np.linalg.norm(src_pts[2] - src_pts[0]), 2)
dst_points = np.array([[0, 0],[0, side1], [side2, 0]])
src_pts = src_pts[[0, 1, 2]]
作为完整性检查,我们可以打印侧面并查看:
print(side1, side2) # 30.0 150.0 ; match the original rectangle sides
并且我们可以看到图中的三个点以及经过旋转+移位(仿射变换)后的新位置
我们可以看到蓝色的原始点和橙色的旋转+移动点。
仿射变换
现在我们可以使用opencv找到affine transformation(旋转+平移)带我们到那里:
# finding affine transformation
affine = cv2.getAffineTransform(np.float32(src_pts), np.float32(dst_points))
print(affine)
#[[ 0.86602543 0.50000001 -56.09807697]
#[ -0.49999998 0.8660254 -34.56217897]]
为了检查我们是否得到了正确的仿射变换以及我们的坐标点是否被点亮,我们可以看到左边的 2X2
矩阵对应于一个旋转矩阵(在这种情况下,我们旋转了 30 度以创建矩形),右边的 2X1
向量是移位或平移向量。
应用转换
一切都已准备就绪,只为压轴大戏进行画面变换和剪裁。使用 opencv 可以很好地完成所有工作:
# Applying affine transform to the image
img_new = cv2.warpAffine(img, affine, dsize=(int(side2), int(side1)))
绘制我们得到的结果:
我正在研究图像查看器的导出功能。我在总是形成一个矩形的图像上有 4 个点,但该矩形可能会旋转。我也有矩形的旋转。现在我想从输入图像和我上面解释的值生成一个新图像。我怎样才能做到这一点 python ?下图可能会让我更清楚地了解我真正想做的事情:
我将使用下面的图片为例:
创建想要的矩形
信息丰富,你说你得到了我刚刚在这里为示例创建的矩形本身,如下所示:
# creating source points - informative
xx = [50, 50, 200, 200]
yy = [30, 60, 30, 60]
alpha = np.pi/6 # 30 degrees
rotMat = np.array([[np.cos(alpha), -1*np.sin(alpha)],
[np.sin(alpha), np.cos(alpha)]])
src_pts = []
for [x, y] in zip(xx,yy):
src_pts.append(rotMat.dot(np.array([x, y])) + np.array([3, 7]))
src_pts = np.array(src_pts)
生成矩形坐标后:
[[ 31.30127019 57.98076211]
[ 16.30127019 83.96152423]
[161.20508076 132.98076211]
[146.20508076 158.96152423]]
我们通过检查向量的点积是否为 0(表示它们之间成 90 度)来得到边:
if np.isclose((src_pts[1] - src_pts[0]).dot(src_pts[2] - src_pts[0]), 0):
side1 = np.around(np.linalg.norm(src_pts[1] - src_pts[0]), 2)
side2 = np.around(np.linalg.norm(src_pts[2] - src_pts[0]), 2)
dst_points = np.array([[0, 0],[0, side1], [side2, 0]])
src_pts = src_pts[[0, 1, 2]]
作为完整性检查,我们可以打印侧面并查看:
print(side1, side2) # 30.0 150.0 ; match the original rectangle sides
并且我们可以看到图中的三个点以及经过旋转+移位(仿射变换)后的新位置
我们可以看到蓝色的原始点和橙色的旋转+移动点。
仿射变换
现在我们可以使用opencv找到affine transformation(旋转+平移)带我们到那里:
# finding affine transformation
affine = cv2.getAffineTransform(np.float32(src_pts), np.float32(dst_points))
print(affine)
#[[ 0.86602543 0.50000001 -56.09807697]
#[ -0.49999998 0.8660254 -34.56217897]]
为了检查我们是否得到了正确的仿射变换以及我们的坐标点是否被点亮,我们可以看到左边的 2X2
矩阵对应于一个旋转矩阵(在这种情况下,我们旋转了 30 度以创建矩形),右边的 2X1
向量是移位或平移向量。
应用转换
一切都已准备就绪,只为压轴大戏进行画面变换和剪裁。使用 opencv 可以很好地完成所有工作:
# Applying affine transform to the image
img_new = cv2.warpAffine(img, affine, dsize=(int(side2), int(side1)))
绘制我们得到的结果: