如何像在 matlab 中一样在 python 中进行集中仿射变换
how to make centralized affine transform in python like in matlab
我可以在 python 中暗示像 matlab 中的 imtransform 这样的集中化转换吗(看它是精确的语义,它非常相关)。
例如在matlab中:
对于此格式:
tform = maketform('affine',[1 0 0; -1 1 0; 0 0 1]);
我得到:
并且在 python 中,在大量的仿射变换方法(piilow、opencv、skimage 和 e.t.c)中,我将其非集中化并剪切:
如何为 python 库选择我的 tform 的 3*3 矩阵,以便它在这种倾斜后集中图像?
MATLAB 默认行为是扩展和集中输出图像,但此行为是 MATLAB 独有的。
可能有一些我不知道的 Python 等价物,但我想专注于 OpenCV 解决方案。
在OpenCV中,需要计算变换矩阵的系数,计算输出图像的大小,才能得到与MATLAB相同的结果。
考虑以下实施细节:
- 在OpenCV中,变换矩阵是相对于MATLAB转置的(不同约定)。
- 在 Python 中第一个索引是 [0, 0] 而在 MATLAB 中是 [1, 1].
- 您需要预先计算输出图像的尺寸(宽度和高度)。
您需要输出尺寸包括整个转换后的图像(转换后图像的所有角都应进入输出图像)。
我的建议是变换四个角,然后计算变换后的角的 max_x - min_x
和 max_y - min_y
。
- 为了集中输出,您需要计算平移系数(OpenCV 矩阵的最后一列)。
假设:源中心被转换(移动)到目标中心。
为了计算平移,您可以使用逆变换,并计算从源中心到目标中心的平移(以像素为单位)。
这是一个 Python 代码示例(使用 OpenCV):
import numpy as np
import cv2
# Read input image
src_im = cv2.imread('peppers.png')
# Build a transformation matrix (the transformation matrix is transposed relative to MATLAB)
t = np.float32([[1, -1, 0],
[0, 1, 0],
[0, 0, 1]])
# Use only first two rows (affine transformation assumes last row is [0, 0, 1])
#trans = np.float32([[1, -1, 0],
# [0, 1, 0]])
trans = t[0:2, :]
inv_t = np.linalg.inv(t)
inv_trans = inv_t[0:2, :]
# get the sizes
h, w = src_im.shape[:2]
# Transfrom the 4 corners of the input image
src_pts = np.float32([[0, 0], [w-1, 0], [0, h-1], [w-1, h-1]]) # (see comment).
dst_pts = cv2.transform(np.array([src_pts]), trans)[0]
min_x, max_x = np.min(dst_pts[:, 0]), np.max(dst_pts[:, 0])
min_y, max_y = np.min(dst_pts[:, 1]), np.max(dst_pts[:, 1])
# Destination matrix width and height
dst_w = int(max_x - min_x + 1) # 895
dst_h = int(max_y - min_y + 1) # 384
# Inverse transform the center of destination image, for getting the coordinate on the source image.
dst_center = np.float32([[(dst_w-1.0)/2, (dst_h-1.0)/2]])
src_projected_center = cv2.transform(np.array([dst_center]), inv_trans)[0]
# Compute the translation of the center - assume source center goes to destination center
translation = src_projected_center - np.float32([[(w-1.0)/2, (h-1.0)/2]])
# Place the translation in the third column of trans
trans[:, 2] = translation
# Transform
dst_im = cv2.warpAffine(src_im, trans, (dst_w, dst_h))
# Show dst_im as output
cv2.imshow('dst_im', dst_im)
cv2.waitKey()
cv2.destroyAllWindows()
# Store output for testing
cv2.imwrite('dst_im.png', dst_im)
用于比较结果的MATLAB代码:
I = imread('peppers.png');
tform = maketform('affine',[1 0 0; -1 1 0; 0 0 1]);
J = imtransform(I, tform);
figure;imshow(J)
% MATLAB recommends using affine2d and imwarp instead of maketform and imtransform.
% tform = affine2d([1 0 0; -1 1 0; 0 0 1]);
% J = imwarp(I, tform);
% figure;imshow(J)
pyJ = imread('dst_im.png');
figure;imagesc(double(rgb2gray(J)) - double(rgb2gray(pyJ)));
title('MATLAB - Python Diff');impixelinfo
max_abs_diff = max(imabsdiff(J(:), pyJ(:)));
disp(['max_abs_diff = ', num2str(max_abs_diff)])
我们很幸运得到零差异 - imwarp
在 MATLAB 中的结果给出了微小的差异(但 imtransform
结果与 OpenCV 相同)。
Python输出图像(与MATLAB输出图像相同):
我可以在 python 中暗示像 matlab 中的 imtransform 这样的集中化转换吗(看它是精确的语义,它非常相关)。
例如在matlab中: 对于此格式:
tform = maketform('affine',[1 0 0; -1 1 0; 0 0 1]);
我得到:
并且在 python 中,在大量的仿射变换方法(piilow、opencv、skimage 和 e.t.c)中,我将其非集中化并剪切:
如何为 python 库选择我的 tform 的 3*3 矩阵,以便它在这种倾斜后集中图像?
MATLAB 默认行为是扩展和集中输出图像,但此行为是 MATLAB 独有的。
可能有一些我不知道的 Python 等价物,但我想专注于 OpenCV 解决方案。
在OpenCV中,需要计算变换矩阵的系数,计算输出图像的大小,才能得到与MATLAB相同的结果。
考虑以下实施细节:
- 在OpenCV中,变换矩阵是相对于MATLAB转置的(不同约定)。
- 在 Python 中第一个索引是 [0, 0] 而在 MATLAB 中是 [1, 1].
- 您需要预先计算输出图像的尺寸(宽度和高度)。
您需要输出尺寸包括整个转换后的图像(转换后图像的所有角都应进入输出图像)。
我的建议是变换四个角,然后计算变换后的角的max_x - min_x
和max_y - min_y
。 - 为了集中输出,您需要计算平移系数(OpenCV 矩阵的最后一列)。
假设:源中心被转换(移动)到目标中心。
为了计算平移,您可以使用逆变换,并计算从源中心到目标中心的平移(以像素为单位)。
这是一个 Python 代码示例(使用 OpenCV):
import numpy as np
import cv2
# Read input image
src_im = cv2.imread('peppers.png')
# Build a transformation matrix (the transformation matrix is transposed relative to MATLAB)
t = np.float32([[1, -1, 0],
[0, 1, 0],
[0, 0, 1]])
# Use only first two rows (affine transformation assumes last row is [0, 0, 1])
#trans = np.float32([[1, -1, 0],
# [0, 1, 0]])
trans = t[0:2, :]
inv_t = np.linalg.inv(t)
inv_trans = inv_t[0:2, :]
# get the sizes
h, w = src_im.shape[:2]
# Transfrom the 4 corners of the input image
src_pts = np.float32([[0, 0], [w-1, 0], [0, h-1], [w-1, h-1]]) # (see comment).
dst_pts = cv2.transform(np.array([src_pts]), trans)[0]
min_x, max_x = np.min(dst_pts[:, 0]), np.max(dst_pts[:, 0])
min_y, max_y = np.min(dst_pts[:, 1]), np.max(dst_pts[:, 1])
# Destination matrix width and height
dst_w = int(max_x - min_x + 1) # 895
dst_h = int(max_y - min_y + 1) # 384
# Inverse transform the center of destination image, for getting the coordinate on the source image.
dst_center = np.float32([[(dst_w-1.0)/2, (dst_h-1.0)/2]])
src_projected_center = cv2.transform(np.array([dst_center]), inv_trans)[0]
# Compute the translation of the center - assume source center goes to destination center
translation = src_projected_center - np.float32([[(w-1.0)/2, (h-1.0)/2]])
# Place the translation in the third column of trans
trans[:, 2] = translation
# Transform
dst_im = cv2.warpAffine(src_im, trans, (dst_w, dst_h))
# Show dst_im as output
cv2.imshow('dst_im', dst_im)
cv2.waitKey()
cv2.destroyAllWindows()
# Store output for testing
cv2.imwrite('dst_im.png', dst_im)
用于比较结果的MATLAB代码:
I = imread('peppers.png');
tform = maketform('affine',[1 0 0; -1 1 0; 0 0 1]);
J = imtransform(I, tform);
figure;imshow(J)
% MATLAB recommends using affine2d and imwarp instead of maketform and imtransform.
% tform = affine2d([1 0 0; -1 1 0; 0 0 1]);
% J = imwarp(I, tform);
% figure;imshow(J)
pyJ = imread('dst_im.png');
figure;imagesc(double(rgb2gray(J)) - double(rgb2gray(pyJ)));
title('MATLAB - Python Diff');impixelinfo
max_abs_diff = max(imabsdiff(J(:), pyJ(:)));
disp(['max_abs_diff = ', num2str(max_abs_diff)])
我们很幸运得到零差异 - imwarp
在 MATLAB 中的结果给出了微小的差异(但 imtransform
结果与 OpenCV 相同)。
Python输出图像(与MATLAB输出图像相同):