旋转图像数学(C#)

我有一个有两个点的图像,对齐如下:

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

我有两个点的X,Y坐标,我需要将图像旋转X度,所以它看起来像这样:

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

基本上所以他们在彼此旁边对齐,这是什么数学? (C#中的代码示例会更好但不是必需的)

这取决于您希望将哪个点用作轮换的“中心”。 让我们将点指向向上和向左的点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); 

希望能帮助到你。

没有代码,对不起,但是一个战略。

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

代码将简单地扫描结果图像的每一行,并将像素映射回原始图像。 你可以做一个简单的事;

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

所以现在我们只需要神奇的“getOriginalPixel”方法,这就是数学的用武之地。

如果我们将图像旋转0度,则plotX,plotY只是原始图像的X / Y. 但那没什么好玩的。

 pickX = x * cos(angle) - y * sin(angle) pickY = y * cos(angle) + x * sin(angle) 

我认为将映射到源像素。 你需要检查它是否超出范围并且只返回黑色或者其他东西:)

以下代码有效

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

首先找到中心点:

 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旋转。

有关三角函数的参考,请参阅Wikipedia

执行一般的2D转换涉及解决一对具有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 * B仅发生变化以及内部循环中的newx,newy由常数A和D改变来优化内部循环中的乘法。

您需要查找几何旋转矩阵: 有关详细说明,请参阅此站点

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

 m = rotation matrix for each point p in destination p' = pm get pixel p' from source set pixle p in destination 

在.net框架方法中有以下所有这些: System.Drawing.Graphics.RotateTransformSystem.Drawing.Graphics.TranslateTransform 。 您需要设置平移以将图像的旋转点移动到原点,然后应用旋转,然后进行另一次平移以将其返回到原始位置。 您需要尝试使用这些函数来计算它们的行为 – 我现在正在工作,没有时间将一些代码放在一起工作。 🙁