2012-08-27 36 views
2

考慮下面的兩幅圖像(分別爲原始圖像和變換圖像)。三個藍色正方形(標記)用於定位。使用矩陣標準化C#中的變換圖像

OriginalTransformed

原始圖像:

  • 我們知道,寬度,高度
  • 我們知道(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

@ChrisWalton:謝謝。我收集到我需要某種線性函數來計算一個向量相對於另一個向量,而不是以這種方式應用轉換。我正在看[線性變換圖](http://en.wikipedia.org/wiki/Linear_map),看看它是否是我需要的。 –

+0

剛剛嘗試過您的代碼,即使不旋轉,也會產生不同的結果,只需更改縮放順序並進行翻譯即可。 – Xantix

回答

2

從我從herehere,並here明白了,Graphics.Drawing轉換是通過在應用變換的順序相乘的矩陣合在一起進行。

用整數,A * B * C = B * A * C

然而,隨着matricies,ABC幾乎總是不等於BAC。

因此,看起來轉換順序很重要,因爲矩陣乘法不是可交換的。

換句話說,它看來,如果我做你的圖片如下:

的情況下1:

  • 翻譯(100,50)
  • 規模(0.5,0。(100,50) 和右下角處:(200190)

    情況2:7)

圖像結束於了左上角

  • 規模(0.5 0.7)
  • 翻譯(100,50)

圖像與在左上角結束:(50,35) 和底部-R ight corner at:(150,174)

這意味着,通過先縮放然後翻譯縮放也可以縮放翻譯量,這就是爲什麼在情況二中圖片最終以(50,35)對於左上角翻譯的X和翻譯Y的一半的一半。