简体   繁体   English

如何像在 matlab 中一样在 python 中进行集中仿射变换

[英]how to make centralized affine transform in python like in matlab

Ho can I imply in python a transformation with a centralization like imtransform in matlab (see it's exact semantics, it is acutely relevant).我能在 python 中暗示一个像 matlab 中的 imtransform 一样的中心化转换(参见它的确切语义,它非常相关)。

For example in matlab: for this tform:例如在 matlab 中:对于这个 tform:

tform = maketform('affine',[1 0 0; -1 1 0; 0 0 1]);

I get:我得到: 在此处输入图像描述

and in python in a big variety of affine transformation methods (piilow, opencv, skimage and etc) I get it non-centralized and cut:并在 python 中使用多种仿射变换方法(piilow、opencv、skimage 等),我将其非集中并剪切:

在此处输入图像描述

How can I choose my 3*3 matrix of the tform for python libraries, such that it will centralize the image after such skewing?如何为 python 库选择 tform 的 3*3 矩阵,以便在这种倾斜后集中图像?

MATLAB default behavior is expanding and centralizing the output image, but this behavior is unique to MATLAB. MATLAB 默认行为是扩展和集中 output 映像,但此行为是 MATLAB 独有的。

There might be some Python equivalent that I am not aware of, but I would like to focus on OpenCV solution.可能有一些我不知道的 Python 等价物,但我想专注于 OpenCV 解决方案。
In OpenCV, you need to compute the coefficients of the transformation matrix, and compute the size of the output image in order to get the same result as in MATLAB.在 OpenCV 中,您需要计算变换矩阵的系数,并计算 output 图像的大小,以获得与 MATLAB 相同的结果。

Consider the following implementation details:考虑以下实现细节:

  • In OpenCV, the transformation matrix is transposed relative to MATLAB (different convention).在 OpenCV 中,变换矩阵相对于 MATLAB 进行了转置(不同的约定)。
  • In Python the first index is [0, 0] and in MATLAB [1, 1].在 Python 中,第一个索引是 [0, 0],在 MATLAB [1, 1] 中。
  • You need to compute the dimensions (width and height) of the output image from advance.您需要提前计算 output 图像的尺寸(宽度和高度)。
    You need the output dimensions to include the entire transformed image (all the corners of the transformed image should enter the output image).您需要 output 尺寸以包含整个变换图像(变换图像的所有角都应输入 output 图像)。
    My suggestion is transforming the four corners, and compute max_x - min_x and max_y - min_y of the transformed corners.我的建议是转换四个角,并计算转换角的max_x - min_xmax_y - min_y
  • For centralizing the output, you need to compute the translation coefficients (last column in OpenCV matrix).为了集中 output,您需要计算平移系数(OpenCV 矩阵中的最后一列)。
    Assume: Source center is transformed (shifted) to destination center.假设:源中心被转换(移动)到目标中心。
    For computing the translation, you may use inverse transformation, and compute the translation (shift in pixels) from the source center to destination center.为了计算平移,您可以使用逆变换,并计算从源中心到目标中心的平移(以像素为单位)。

Here is a Python code sample (using 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]]) # https://stackoverflow.com/questions/44378098/trouble-getting-cv-transform-to-work (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 code for comparing results: 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)])

We are lucky to get zero difference - result of imwarp in MATLAB gives minor differences (but imtransform result is same as OpenCV).我们很幸运能够获得零差异 - imwarp中的 imwarp 结果给出了微小的差异(但imtransform结果与 OpenCV 相同)。


Python output image (same as MATLAB output image): Python output 图像(与 MATLAB Z78E6221F6393D1356681DB3DZF1 图像相同)
在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM