C# C语言中的矩阵/坐标变换#

C# C语言中的矩阵/坐标变换#,c#,image,matrix,coordinates,transformation,C#,Image,Matrix,Coordinates,Transformation,我有一个坐标数组,它反映了图像上的已知位置。让我们称之为模板图像。它具有唯一的条形码和方向标记(也位于坐标阵列中) 图像被打印、扫描并反馈到我的应用程序中进行检测。在打印和扫描过程中,图像可以通过三种方式进行变换;平移、旋转和缩放 假设我可以在扭曲的图像上找到方向标记,如何使用矩阵变换来获得剩余坐标的相对位置 我把这个问题贴在了SO上,但把它弄得太复杂了,弄不明白我想要什么 编辑 namespace MatrixTest { using System; using System.Drawing;

我有一个坐标数组,它反映了图像上的已知位置。让我们称之为模板图像。它具有唯一的条形码和方向标记(也位于坐标阵列中)

图像被打印、扫描并反馈到我的应用程序中进行检测。在打印和扫描过程中,图像可以通过三种方式进行变换;平移、旋转和缩放

假设我可以在扭曲的图像上找到方向标记,如何使用矩阵变换来获得剩余坐标的相对位置

我把这个问题贴在了SO上,但把它弄得太复杂了,弄不明白我想要什么

编辑

namespace MatrixTest
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections.Generic;

public static class Program
{
public static void Main ()
{
Template template = new Template(); // Original template image.
Document document = new Document(); // Printed and scanned distorted image.

template.CreateTemplateImage();

// The template image is printed and scanned. This method generates an example scan or this question.
document.CreateDistortedImageFromTemplateImage();
// Stuck here.
document.Transform();
// Draw transformed points on the image to verify that transformation is successful.
document.DrawPoints();

System.Diagnostics.Process.Start(new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).Directory.FullName);
}
}

public class Page
{
public Bitmap Image { get; set; }
public Point[] Markers = new Point[3]; // Orientation markers: 1=TopLeft, 2=TopRight, 3=BottomRight.
public Point[] Points = new Point[100]; // Coordinates to transform in the TemplateScanned derived class!
}

// This class represents the originalk template image.
public class Template: Page
{
public Template ()
{
this.Image = new Bitmap(300, 400);

// Known dimentions for marker rectangles.
this.Markers[0] = new Point(10, 10);
this.Markers[1] = new Point(this.Image.Width - 20 - 10, 10);
this.Markers[2] = new Point(this.Image.Width - 20 - 10, this.Image.Height - 20 - 10);

// Known points of interest. Consider them hardcoded.
int index = 0;
for (int y = 0; y < 10; y++)
for (int x = 0; x < 10; x++)
this.Points[index++] = new Point((this.Image.Width / 10) + (x * 20), (this.Image.Height / 10) + (y * 20));
}

public void CreateTemplateImage ()
{
using (Graphics graphics = Graphics.FromImage(this.Image))
{
graphics.Clear(Color.White);

for (int i = 0; i < this.Markers.Length; i++)
graphics.FillRectangle(Brushes.Black, this.Markers[i].X, this.Markers[i].Y, 20, 20);

for (int i = 0; i < this.Points.Length; i++)
graphics.DrawRectangle(Pens.Red, this.Points[i].X, this.Points[i].Y, 5, 5);
}

this.Image.Save("Document Original.png");
}
}

// This class represents the scanned image.
public class Document: Page
{
public struct StructTransformation
{
public float AngleOfRotation;
public SizeF ScaleRatio;
public SizeF TranslationOffset;
}

private Template Template = new Template();
private StructTransformation Transformation = new StructTransformation();

public Document ()
{
this.Template = new Template();
this.Transformation = new StructTransformation { AngleOfRotation = 5f, ScaleRatio = new SizeF(.8f, .7f), TranslationOffset = new SizeF(100f, 30f) };

this.Template.CreateTemplateImage();

// Copy points from template.
for (int i = 0; i < this.Template.Markers.Length; i++)
this.Markers[i] = this.Template.Markers[i];

for (int i = 0; i < this.Points.Length; i++)
this.Points[i] = this.Template.Points[i];
}

// Just distorts the original template image as if it had been read from a scanner.
public void CreateDistortedImageFromTemplateImage ()
{
// Distort coordinates.
Matrix matrix = new Matrix();
matrix.Rotate(this.Transformation.AngleOfRotation);
matrix.Scale(this.Transformation.ScaleRatio.Width, this.Transformation.ScaleRatio.Height);
matrix.Translate(this.Transformation.TranslationOffset.Width, this.Transformation.TranslationOffset.Height);
matrix.TransformPoints(this.Markers);
matrix.TransformPoints(this.Points);

// Distort and save image for visual reference.
this.Image = new Bitmap(this.Template.Image.Width, this.Template.Image.Height);
using (Graphics graphics = Graphics.FromImage(this.Image))
{
graphics.Clear(Color.White);
graphics.RotateTransform(this.Transformation.AngleOfRotation);
graphics.ScaleTransform(this.Transformation.ScaleRatio.Width, this.Transformation.ScaleRatio.Height);
graphics.TranslateTransform(this.Transformation.TranslationOffset.Width, this.Transformation.TranslationOffset.Height);
graphics.DrawImage(this.Template.Image, 0, 0);
}
this.Image.Save("Document Scanned.png");
}

public void Transform ()
{
// The rectangles of the ScannedDcoument are not known at this time. They would obviously be relative to the three orientation markers.
//    I can't figure out how to use the following code properly i.e. using Matrix to apply all three transformations.
Matrix matrix = new Matrix();
matrix.Rotate(-this.Transformation.AngleOfRotation);
matrix.Scale(1f/this.Transformation.ScaleRatio.Width, 1f/this.Transformation.ScaleRatio.Height);
matrix.Translate(-this.Transformation.TranslationOffset.Width, -this.Transformation.TranslationOffset.Height);
matrix.TransformPoints(this.Markers);
matrix.TransformPoints(this.Points);
}

public void DrawPoints ()
{
using (Graphics graphics = Graphics.FromImage(this.Image))
{
graphics.Clear(Color.White);

for (int i = 0; i < this.Markers.Length; i++)
graphics.FillRectangle(Brushes.Blue, this.Markers[i].X, this.Markers[i].Y, 20, 20);

for (int i = 0; i < this.Points.Length; i++)
graphics.DrawRectangle(Pens.Purple, this.Points[i].X, this.Points[i].Y, 5, 5);
}
this.Image.Save("Document Fixed.png");
}
}
}
namespace-MatrixTest
{
使用制度;
使用系统图;
使用System.Drawing.Drawing2D;
使用System.Collections.Generic;
公共静态类程序
{
公共静态void Main()
{
Template Template=新模板();//原始模板图像。
Document Document=new Document();//打印和扫描的扭曲图像。
CreateTemplateImage();
//打印并扫描模板图像。此方法生成示例扫描或此问题。
document.createTexturedImageFromTemplateImage();
//被困在这里。
document.Transform();
//在图像上绘制变换点以验证变换是否成功。
文件.支取点();
System.Diagnostics.Process.Start(新的System.IO.FileInfo(System.Reflection.Assembly.GetExecutionGassembly().Location)、Directory.FullName);
}
}
公共类页面
{
公共位图图像{get;set;}
公共点[]标记=新点[3];//方向标记:1=左上角,2=右上角,3=右下角。
公共点[]点=新点[100];//要在TemplateScanned派生类中转换的坐标!
}
//此类表示originalk模板图像。
公共类模板:第页
{
公共模板()
{
this.Image=新位图(300400);
//标记矩形的已知尺寸。
此.Markers[0]=新点(10,10);
this.Markers[1]=新点(this.Image.Width-20-10,10);
this.Markers[2]=新点(this.Image.Width-20-10,this.Image.Height-20-10);
//已知的兴趣点。考虑它们的硬编码。
int指数=0;
对于(int y=0;y<10;y++)
对于(int x=0;x<10;x++)
this.Points[index++]=新点((this.Image.Width/10)+(x*20),(this.Image.Height/10)+(y*20));
}
public void CreateTemplateImage()
{
使用(Graphics Graphics=Graphics.FromImage(this.Image))
{
图形。清晰(颜色。白色);
for(int i=0;i
我假设您要将图像转换为单位平方((0,0)-(1.0,1.0)) 您需要三个点,一个是原点,另一个将变换为x轴(1.0,0),另一个是t轴
(1   0   -Ox)
(0   1   -Oy)
(0   0    1) 
(RX1   RX2   0)
(RY1   RY2   0)
( 0    0     1)
(RY2/D   -RX2/D   0)
(-RY1/D   RX1/D   0)
(  0       0      1)