2

考虑下面的两个图像(分别是原始图像和转换后的图像)。三个蓝色方块(标记)用于定位。

原来的 变身

原图:

  • 我们知道宽度,高度
  • 我们知道所有三个标记的 (x,y) 坐标。

转换后的图像:

  • 我们可以检测所有三个标记的 (x,y) 坐标。
  • 结果,我们可以计算旋转角度、(x,y) 平移量和 (x,y) 比例因子。

我现在想使用 System.Drawing.Graphics 对象来执行 RotateTransform、TranslateTransform 和 ScaleTransform。问题是,生成的图像永远不会像原始图像。

我在堆栈溢出时被告知应用转换的顺序无关紧要,但我的观察结果不同。下面是一些生成原始图像并在引入一些转换后尝试将其绘制在新画布上的代码。您可以更改转换的顺序以查看不同的结果。

public static void GenerateImages ()
{
    int width = 200;
    int height = 200;
    string filename = "";
    System.Drawing.Bitmap original = null; // Original image.
    System.Drawing.Bitmap transformed = null; // Transformed image.
    System.Drawing.Graphics graphics = null; // Drawing context.

    // Generate original image.
    original = new System.Drawing.Bitmap(width, height);
    graphics = System.Drawing.Graphics.FromImage(original);
    graphics.Clear(System.Drawing.Color.MintCream);
    graphics.DrawRectangle(System.Drawing.Pens.Red, 0, 0, original.Width - 1, original.Height - 1);
    graphics.FillRectangle(System.Drawing.Brushes.Blue, 10, 10, 20, 20);
    graphics.FillRectangle(System.Drawing.Brushes.Blue, original.Width - 31, 10, 20, 20);
    graphics.FillRectangle(System.Drawing.Brushes.Blue, original.Width - 31, original.Height - 31, 20, 20);
    filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Original.png");
    original.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
    graphics.Dispose();

    // Generate transformed images.
    transformed = new System.Drawing.Bitmap(width, height);
    graphics = System.Drawing.Graphics.FromImage(transformed);
    graphics.Clear(System.Drawing.Color.LightBlue);
    graphics.ScaleTransform(0.5F, 0.7F); // Add arbitrary transformation.
    graphics.RotateTransform(8); // Add arbitrary transformation.
    graphics.TranslateTransform(100, 50); // Add arbitrary transformation.
    graphics.DrawImage(original, 0, 0);
    filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Transformed.png");
    transformed.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
    graphics.Dispose();
    transformed.Dispose();

    original.Dispose();

    System.Diagnostics.Process.Start(filename);
}

我可以在这里看到两个潜在的问题:

  • 由于转换是一个接一个地应用,它们使最初计算的值变得无用。
  • 图形对象在 (0, 0) 坐标处应用旋转,因为我应该做一些不同的事情。不确定是什么。
4

1 回答 1

3

根据我从这里这里这里的理解,Graphics.Drawing 转换是通过按照应用转换的顺序将矩阵相乘来执行的。

对于整数,a*b*c = b*a*c

但是,对于矩阵,ABC 几乎从不等于 BAC。

因此,看起来转换的顺序确实很重要,因为矩阵乘法不是可交换的。

换句话说,如果我对你的图片执行以下操作:

情况1:

  • 翻译 (100,50)
  • 规模 (0.5,0.7)

图片以左上角结束:(100,50)和右下角:(200,190)

案例2:

  • 规模 (0.5,0.7)
  • 翻译 (100,50)

图片以左上角结束:(50,35)和右下角:(150,174)

这意味着通过先缩放,然后平移,缩放也将缩放平移量,这就是为什么如果两个图片在左上角的 (50,35) 处结束,则平移 X 的一半和翻译 Y 的 0.7。

于 2012-08-27T07:04:18.690 回答