我试图编写一个3剪切旋转算法阿兰·佩思的Java实现。问题不是值的计算,而是将旋转点拟合到图像网格上。在本文中,旋转是通过下列计算给出的三个连续剪刀进行的:
α和β是根据给定的角度(θ;半径)计算的,公式如下:
利用这些公式,点围绕着坐标系的中心旋转。
为了纠正负值,我将相应轴的最小计算坐标添加到每个点,使最小值始终为0。
到目前为止,我的Java实现:
ShiftPoint[] val = new ShiftPoint[m*n];
double minX = 0,minY = 0, maxX = 0, maxY = 0;
double alpha = -1d* Math.tan(Math.toRadians(theta)/2d);
double beta = Math.sin(Math.toRadians(theta));
for(int a = 0; a < m; a++) {
for(int b = 0; b < n; b++) {
ShiftPoint temp = new ShiftPoint(a, b, values[a][b]);
double newX = b + alpha * a; //first shear
double newY = a + beta * newX; //second shear
newX += alpha * newY; //third shear
temp.setX(newX);
temp.setY(newY);
val[m * b + b] = temp;
}
}注意: ShiftPoint是一个简单的自写类,用于保存特定坐标和矩阵中的值(在图像处理中:像素的rgb值)。下面是计算的图形表示:

问题:虽然计算值似乎是正确的,并且图形表示显示旋转实际上是有效的,但我不知道如何在固定网格上拟合计算值--图像(或2d数组)--不失真它。此外,我也不完全理解Paeth文件中给出的实现(对于x轴剪切):

我得到,斜交是计算值的整数部分,斜交是分数部分,但是宽度、高度、烯烃和左边长是多少呢?另外:为什么他在第一次计算时将y值加到0.5,而不考虑x值?
注意:我知道Java提供了简单的旋转图像的方法,但是为了好玩,我尝试实现这个特定的算法。我还知道有3-5个网站可以通过网络搜索(如#1和#2)找到,并试图解释该算法,但首先它们不使用java,其次它们主要引用Paeth的示例实现,因此它们不是很有用。
发布于 2018-04-05 13:59:49
这种图像旋转方法背后的基本原则有两方面:
第一步通常比较容易,涉及x&y坐标的简单线性组合。剪切转换(这不是严格意义上的旋转,因为它们不保存每个像素的面积)只涉及x -> x+ alpha * y之类的东西。
Paeth论文中给出的算法(从1986年开始)似乎是对剪切变换进行第二步(插值)的一种精心优化的方法。我认为这可以归结为沿x轴的分段线性插值,但是以一种不需要对输出图像中的每个像素进行多个数组查找的形式编写。一种更清晰(且效率稍低)的方法可能会涉及到一些东西,比如斜and*像素(x-斜维-1,y) +(1-斜and)*像素(x-斜维,y)。
这种特殊的算法对于单轴偏斜显然是高度专门化的.对于一般的旋转,您可能需要更像一个双线性插值在每个2x2平方的像素周围的未旋转位置对应于旋转图像中每个像素的中心。(计算这个中心像素值可能是Paeth代码中y+0.5的起源。)
考虑到我们现在相对有1986年的计算能力,我怀疑如果你为这个双线性插值包含一个显式公式,即使它确实比Paeth的方法使用更多的数组查找,你的代码会更容易理解,除非你真的需要最大的性能。
https://stackoverflow.com/questions/47619685
复制相似问题