旋转图像数学(C#)

旋转图像数学(C#),c#,math,image,rotation,C#,Math,Image,Rotation,我有一张有两个点的图像,像这样对齐: |----------------| | | | . | | | | . | | | |----------------| double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X); 我有两个点的X,Y坐标,我需要将图像旋转X度,因此它看

我有一张有两个点的图像,像这样对齐:

|----------------|
|                |
|    .           |
|                |
|          .     |
|                |
|----------------|
double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X);
我有两个点的X,Y坐标,我需要将图像旋转X度,因此它看起来像这样:

|----------------|
|                |
|                |
|    .     .     |
|                |
|                |
|----------------|

基本上,它们相邻排列,这有什么数学依据?(C#中的代码示例更好,但不是必需的)

您需要查找几何旋转矩阵:

但是,为了获得最佳效果,您需要从目标转换到源,然后对每个目标像素使用转换:

m = rotation matrix

for each point p in destination
  p' = p.m
  get pixel p' from source
  set pixle p in destination

在.net framework中,有一些方法可以完成这一切:
System.Drawing.Graphics.RotateTransform
System.Drawing.Graphics.TranslateTransform
。您需要设置一个平移以将图像的旋转点移动到原点,然后应用旋转,然后再进行另一个平移以将其返回到原始位置。您需要对这些函数进行实验,以了解它们的行为-我目前正在工作,没有时间来整理一些可以工作的代码:-(

对不起,没有密码,只是一个策略

您需要能够通过对源图像进行采样来创建结果图像。您知道旋转角度,因此现在需要创建一个映射器函数,将结果映射回原始图像

代码只需扫描结果图像的每一行,并将像素映射回原始图像

for (int plotY = 0; plotY < resultHeight; plotY++)
{
   for (int plotX = 0; plotX < resultWidth; plotX++)
   {
         resultImage.PlotPixel(getOriginalPixel(plotX, plotY, angleOfRotation));
   } 
}

我认为将映射到源像素。您需要检查它是否超出边界,然后返回黑色或其他颜色:)

首先找到中心点:

Point p = new Point((x1-x2)/2, (y1-y2)/2)
然后使用三角函数尝试求解角度。我假设我们已经将原点重定为中心点,所以我现在有一个新的x3和y3到其中一个点

hypotenuse = SqrRt(x3^2 + y3^2)
我们正在求解未知角度
TH

Sin(TH) = opposite / hypotenuse
因此,为了解决TH问题,我们需要:

TH = Asin(y3 / hypotenuse)
旋转
TH


请参见

这取决于要将哪个点用作旋转的“中心”。让我们把这个点称为上点和左点A,把这个点称为右点和下点B。如果要围绕点A旋转以使点B与其对齐,则以弧度为单位计算旋转角度如下所示:

|----------------|
|                |
|    .           |
|                |
|          .     |
|                |
|----------------|
double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X);
我不知道您是如何处理图像的,因此以下内容仅适用于使用System.Drawing.Graphics的情况:

myImage.TranslateTransform(-pointA.X, -pointA.Y);
myImage.RotateTransform((float) angle, MatrixOrder.Append);
myImage.TranslateTransform(pointA.X, pointA.Y, MatrixOrder.Append);

希望有帮助。

执行一般二维变换需要解一对包含6个未知项的方程

'x=xA+yB+C

‘y=xD+yE+D

给出3个对应点,你将有6个知识,系统可以解决。在这种情况下,您只有4个点,因为您不关心剪切,但是您可以想象在其他两点形成的直线上引入90度的第三个点。然后,创建旋转图像(伪代码)就像:

for ( y = 0; y < height; y++ )
 for ( x = 0; x < width; x++ )
  {
    newx = x*A + y*B + C;
    newy = x*D + y*D + E;
    newimage(x,y ) = oldimage( newx, newy );
  }
}
(y=0;y 对于(x=0;x 如果性能很重要,则可以通过注意y*B仅改变外观,以及newx、newy通过内循环中的常数A和D进行改变来优化内循环中的倍数。

以下代码有效

  Matrix mRotate = new Matrix();
    mRotate.Translate(Convert.ToInt32(Width.Value) / -2, Convert.ToInt32(Height.Value) / -2, MatrixOrder.Append);
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);

    using (GraphicsPath gp = new GraphicsPath())
    {  // transform image points by rotation matrix
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(Convert.ToInt32(Width.Value), 0), new Point(0, Convert.ToInt32(Height.Value)) });
        gp.Transform(mRotate);
        PointF[] pts = gp.PathPoints;

        // create destination bitmap sized to contain rotated source image
        Rectangle bbox = boundingBox(bmpSrc, mRotate);
        Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height);


        using (Graphics gDest = Graphics.FromImage(bmpDest))
        {  // draw source into dest


            Matrix mDest = new Matrix();
            mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
            gDest.Transform = mDest;
            gDest.DrawImage(bmpSrc, pts);
            gDest.DrawRectangle(Pens.Transparent, bbox);
            //drawAxes(gDest, Color.Red, 0, 0, 1, 100, "");
            return bmpDest;
        }
    }

您应该返回Color.Transparent,如果它超出了边界这是一个旧线程,但我要提到的是,我在这里发布了一个C#WinForms图像旋转方法: