试图使用旋转矩阵,并失败

时间:2013-11-19 18:40:08

标签: c++ arrays image math rotation

我一直在尝试使用旋转矩阵来旋转图像。以下是我一直在使用的代码。我一直试图这样做几天,而且每次看起来都有问题,但我无法看到我做错了什么。例如,我的图像变得倾斜,而不是旋转......

下面的代码分为两部分:实际旋转,向上移动图片使其出现在正确的位置(需要将其所有点都高于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;
    }
}

我宁愿自己解决这个问题,但是现在已经超过一个星期了。我不明白为什么函数没有旋转输入像素数组的位置信息。如果有人可以看一看,也许发现我的逻辑不起作用的原因,我将非常感激。谢谢。

2 个答案:

答案 0 :(得分:4)

似乎你刚刚在旋转矩阵中犯了错误:

p_pixelsToRotate[i].y = round( sin( rad ) * x + sin( rad ) * y );
                                                ^^^---------------change to cos

答案 1 :(得分:3)

首先,这是一个错误:

    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 );