使用矩阵在C#中标准化转换后的图像

时间:2012-08-27 06:22:09

标签: c# .net image matrix transformation

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

Original Transformed

原始图片:

  • 我们知道宽度,高度
  • 我们知道所有三个标记的(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)坐标处应用旋转,因为我应该做一些不同的事情。不确定是什么。

1 个答案:

答案 0 :(得分:3)

根据我对hereherehere的理解,通过将矩阵乘以应用转换的顺序来执行Graphics.Drawing转换。

使用整数,a * b * c = b * a * c

然而,对于matricies,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)左上角,一半翻译的Y的翻译的X和.7。