Java 从变换矩阵求角度
我有一个像这样的值的变换矩阵 变换:分别为xx、xy、yx、yy、tx和tyJava 从变换矩阵求角度,java,math,Java,Math,我有一个像这样的值的变换矩阵 变换:分别为xx、xy、yx、yy、tx和ty 如何从上述给定值集合中找到角度。参考维基百科关于变换矩阵的页面: tx和ty是翻译。其余元素组成旋转矩阵: xx xy yx yy 请注意,这相当于 cos(θ) sin(θ) -sin(θ) cos(θ) 其中,θ为顺时针旋转角度。从中可以得到xx=yy=cos(θ)和xy=-yx=sin(θ)。角度的计算公式为数学atan2(xy,xx)。这将给您一个介于-π和π之间的结果Math.acos(xx),Math
如何从上述给定值集合中找到角度。参考维基百科关于变换矩阵的页面:
tx
和ty
是翻译。其余元素组成旋转矩阵:
xx xy
yx yy
请注意,这相当于
cos(θ) sin(θ)
-sin(θ) cos(θ)
其中,
θ
为顺时针旋转角度。从中可以得到xx=yy=cos(θ)
和xy=-yx=sin(θ)
。角度的计算公式为数学atan2(xy,xx)
。这将给您一个介于-π
和π
之间的结果Math.acos(xx)
,Math.acos(yy)
,Math.asin(xy)
,Math.asin(-yx)
和-Math.asin(yx)
这6个数字描述了一种仿射变换,通常包括(非均匀)缩放、旋转和平移。翻译用(tx,ty)
表示。剩下的4个数字必须分解为缩放和旋转。最简单的方法是:将矩阵分解为M=UDV
,其中M
是原始矩阵
xx xy
yx yy
U和V是正交旋转矩阵,D是对角矩阵。这将仿射变换表示为三个步骤:旋转
V
,然后缩放D
,以及旋转U
。D
的两个条目是x和y的两个比例系数。从U
和V
可以获得旋转角度,如Mad物理学家所述。总旋转是两者的总和。如果只是关于旋转,可以使用给定矩阵变换向量(1,0),并计算结果向量和x轴之间的角度,如对原始问题的评论中所述
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.Random;
public class ExtractRotation
{
public static void main(String[] args)
{
for (int i=0; i<=180; i++)
{
double angleRad = Math.toRadians(i);
AffineTransform at = createRandomTransform(angleRad);
double extractedAngleRad = extractAngle(at);
System.out.println(
"In: "+Math.toDegrees(angleRad)+ " " +
"Out "+Math.toDegrees(extractedAngleRad));
}
}
private static double extractAngle(double m[])
{
return extractAngle(new AffineTransform(m));
}
private static double extractAngle(AffineTransform at)
{
Point2D p0 = new Point();
Point2D p1 = new Point(1,0);
Point2D pp0 = at.transform(p0, null);
Point2D pp1 = at.transform(p1, null);
double dx = pp1.getX() - pp0.getX();
double dy = pp1.getY() - pp0.getY();
double angle = Math.atan2(dy, dx);
return angle;
}
private static Random random = new Random(0);
private static AffineTransform createRandomTransform(double angleRad)
{
AffineTransform at = new AffineTransform();
double scale = 1.0;
at.translate(randomDouble(), randomDouble());
scale = Math.abs(randomDouble());
at.scale(scale, scale);
at.rotate(angleRad);
at.translate(randomDouble(), randomDouble());
scale = Math.abs(randomDouble());
at.scale(scale, scale);
return at;
}
private static double randomDouble()
{
return -5.0 + random.nextDouble() * 10;
}
}
导入java.awt.Point;
导入java.awt.geom.AffineTransform;
导入java.awt.geom.Point2D;
导入java.util.Random;
公营班级轮换
{
公共静态void main(字符串[]args)
{
对于(int i=0;i如果选择使用具有4个自由度(缩放、旋转和平移)的仿射变换,则不必分解旋转矩阵。
对于提取平移和旋转,有一种直接的解决方案
下面是一个使用opencv的python实现
# Note: This function calculate only 4 degrees of freedom !!! scaling, rotation and translation
h, mask = cv.estimateAffinePartial2D(pointsRef, pointsCur, method=cv.RANSAC, ransacReprojThreshold=3, confidence=0.9)
# Estimate the rotation angle from the matrix [s]
# Extract traslation
dx = h[0, 2]
dy = h[1, 2]
# Extract rotation angle
da = np.arctan2(h[1, 0], h[0, 0])
print(np.rad2deg(da))
# Store transformation
transforms = [dx, dy, da]
可能是重复的。我个人会从这个答案中推荐这种方法:谢谢你,Marco,你有类似的java代码吗?在中添加了一些代码,如果你只有这六个参数,这意味着它们被适当地缩放了,否则你会丢失矩阵最后一行的信息。谢谢@Marco13,这正是我要找的。你知道是否也可以从给定的值中找到比例和转换信息。转换是通过用给定的矩阵转换点(0,0)的结果给出的。可以根据上述代码中pp0
和pp1
之间的距离来计算比例(如果缩放不均匀,则其x坐标和y坐标的差异)