旋转图像数学(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图像旋转方法: