尝试使用旋转矩阵,但失败了
Trying to use a rotation matrix, and failing
我一直在尝试使用旋转矩阵来旋转图像。下面是我一直在使用的代码。我已经试了好几天了,每次似乎都有什么不对劲,但我看不出我做错了什么。例如,我的图像变得倾斜,而不是旋转。。。
下面的代码分为两部分:实际旋转,以及向上移动图片以使其出现在正确的位置(需要将其所有点都保持在0以上才能正确保存)。它将一个像素阵列(包含位置信息(x,y)和颜色信息(r,g,b))、一个图像(仅用于获取其像素数,也就是阵列大小和宽度)以及一个以弧度为单位的旋转值作为输入。
负责旋转本身的部分是线上方的部分,而线下方的部分负责计算图像中的最低点,并将所有像素向上或向右移动,以实现完全匹配(当图像旋转45度或类似时,我仍然需要实现一个函数来更改图像大小)。
void Rotate( Pixel *p_pixelsToRotate, prg::Image* img, float rad )
{
int imgLength = img->getPixelCount();
int width = img->getWidth();
int x { 0 }, y { 0 };
for( int i = 0; i < imgLength; i++ )
{
x = p_pixelsToRotate[i].x;
y = p_pixelsToRotate[i].y;
p_pixelsToRotate[i].x = round( cos( rad ) * x - sin( rad ) * y );
p_pixelsToRotate[i].y = round( sin( rad ) * x + sin( rad ) * y );
}
===========================================================================
Pixel* P1 = &p_pixelsToRotate[ width - 1 ]; // Definitions of these are in the supporting docs
Pixel* P3 = &p_pixelsToRotate[ imgLength - 1 ];
int xDiff = 0;
int yDiff = 0;
if( P1->x < 0 || P3->x < 0 )
{
(( P1->x < P3->x )) ? ( xDiff = abs( P1->x )) : ( xDiff = abs( P3->x ));
}
if( P1->y < 0 || P3->y < 0 )
{
(( P1->y < P3->y )) ? ( yDiff = abs( P1->y )) : ( yDiff = abs( P3->y ));
}
for( int i = 0; i < imgLength; i++ )
{
p_pixelsToRotate[i].x += xDiff;
p_pixelsToRotate[i].y += yDiff;
}
}
我更愿意自己解决这个问题,但已经一个多星期没能解决了。我不明白为什么函数不旋转输入像素阵列的位置信息。如果有人能看一看,也许能发现为什么我的逻辑不起作用,我会非常感激。非常感谢。
似乎你只是在旋转矩阵本身犯了一个错误:
p_pixelsToRotate[i].y = round( sin( rad ) * x + sin( rad ) * y );
^^^---------------change to cos
首先,这是一个错误:
p_pixelsToRotate[i].x = round( cos( rad ) * x - sin( rad ) * y );
p_pixelsToRotate[i].y = round( sin( rad ) * x + >>>sin<<<( rad ) * y );
>>>sin<<<
应该是cos
。这可以解释得到剪切而不是旋转。
其他评论:在位图数据中存储像素坐标是解决位图旋转问题的一种极其昂贵的方法。更好的方法是逆变换采样。对于源图像X,并希望用变换R旋转它以获得Y,您当前正在考虑
Y = R X
其中X和Y具有明确存储的像素坐标。要使用逆采样,请考虑用R的逆在两侧相乘的相同方程。
R^(-1) Y = X
其中坐标是隐含的。也就是说,为了产生Y[j][i],用逆R^(-1)
变换(j,i)以获得x图像中的坐标(x,Y)。使用此项对X中最近的像素X[round(X)][round(y)]进行采样,并将其指定为y[j][i]。
(实际上,更复杂的算法不是简单的舍入,而是对(X,y)周围的X个像素进行加权平均,以获得更平滑的结果。如何选择权重是一个很大的附加主题。)
完成这项工作后,你可以更进一步。一些代数将表明,只需几次加法,就可以更新先前的采样坐标,以获得相邻的采样坐标(紧挨着右边或左边,向上或向下),而不是对每个像素进行全矩阵矢量乘法。这大大加快了速度。
旋转的倒数计算起来微不足道!只需将旋转角度取反即可。
最后一点需要注意的是,使用三元运算符o ? o : o
来选择赋值真的很糟糕。取而代之的是:
(( P1->x < P3->x )) ? ( xDiff = abs( P1->x )) : ( xDiff = abs( P3->x ));
比如
xDiff = ( P1->x < P3->x ) ? abs( P1->x ) : abs( P3->x );
- 如果没有malloc,链表实现将失败
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 与互斥锁相比,旋转锁可以保证上下文切换
- 视图中的参数推导失败:take_while
- 链接到自行创建的dll失败
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- GetShortPathName在网络驱动器上使用中文文件夹时失败
- gcc和c++17的过载解析失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在WSL:configure_file上对config_file的每次调用都失败:配置文件时出现问题
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 从父数组测试用例构造二叉树失败
- 绘制旋转的三角形
- LibGit2 SSH身份验证失败
- 如何让LLDB在成功时退出,在失败时等待
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- 尝试使用旋转矩阵,但失败了