矩阵/坐标转换在C# [英] Matrix / coordinate transformation in C#

查看:225
本文介绍了矩阵/坐标转换在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有反映在图像上的已知位置坐标的阵列。让我们把这个模板图像。它具有独特的条形码和取向标记(这也是坐标阵列中)。



打印图像,扫描并反馈到我的应用程序来检测。期间打印和扫描,图像可以以三种方式来转化;平移,旋转和缩放。



假如我能找到的失真图像上的方向标,我怎么可以用矩阵变换来获得剩余的坐标的相对位置?



我贴在SO 这个问题之前, 但做它太复杂,理解我想要的东西。



修改

 命名空间MatrixTest 
{
使用系统;
使用System.Drawing中;
使用System.Drawing.Drawing2D;
使用System.Collections.Generic;

公共静态类节目
{
公共静态无效的主要()
{
模板模板=新的模板(); //原始模板图像。
文档的文档=新的文件(); //打印和扫描失真图像。

template.CreateTemplateImage();

//模板图像被打印和扫描。这种方法生成的例子扫描或这个问题。
document.CreateDistortedImageFromTemplateImage();
//困在这里。
document.Transform();
//绘制图像转换点来验证改造是成功的。
document.DrawPoints();

System.Diagnostics.Process.Start(新System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly()位置).Directory.FullName);
}
}

公共类页
{
公共位图图像{搞定;组; }
公共点[]标记=新点[3]; //取向标记:1 =左上,2 = TopRight,3 = BottomRight。
公共点[]分=新的点[100]; //坐标在TemplateScanned派生类改造!
}

//此类表示originalk模板图像。
公共类模板:页面
{
公共模板()
{
this.Image =新位图(300,400);

//为标志矩形已知dimentions。
this.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 ++)
的for(int x = 0; X小于10; X ++)
this.Points [指数++] =新的点( (this.Image.Width / 10)+(X * 20),(this.Image.Height / 10)+(γ* 20));
}

公共无效CreateTemplateImage()
{使用
(图形图像= Graphics.FromImage(this.Image))
{
graphics.Clear(Color.White);

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

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

this.Image.Save(文档Original.png);
}
}

//此类表示扫描的图像。
公共类文件:第
{
公共结构StructTransformation
{
公众持股量AngleOfRotation;
公众的SizeF ScaleRatio;
公众的SizeF TranslationOffset;
}

私人模板模板=新模板();
私人StructTransformation转型=新StructTransformation();

公开文件()
{
this.Template =新模板();
this.Transformation =新StructTransformation {AngleOfRotation = 1006米,ScaleRatio =新的SizeF(.8f,.7f),TranslationOffset =新的SizeF(100F,30F)};

this.Template.CreateTemplateImage();从模板

//复制点。
的for(int i = 0; I< this.Template.Markers.Length;我++)
this.Markers [I] = this.Template.Markers [I]

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

//只要扭曲原始模板图像,就好像它已被从扫描仪读取。
公共无效CreateDistortedImageFromTemplateImage()
{
//扭曲坐标。
矩阵的矩阵=新的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);

//扭曲并保存图像视觉参考。
this.Image =新位图(this.Template.Image.Width,this.Template.Image.Height);使用
(图形图像= 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(文档Scanned.png);
}

公共无效变换()
{
//将ScannedDcoument的矩形此时不称。它们显然是相对于这三个方向的标记。
//我无法弄清楚如何使用矩阵应用所有三个转变,即正确使用下面的代码。
矩阵的矩阵=新的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);
}

公共无效DrawPoints()
{使用
(图形图像= Graphics.FromImage(this.Image))
{
graphics.Clear(Color.White);

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

的for(int i = 0; I< this.Points.Length;我++)
graphics.DrawRectangle(Pens.Purple,this.Points [I] .X,this.Points [Ⅰ] .Y,5,5);
}
this.Image.Save(文档Fixed.png);
}
}
}


解决方案

我假设你想将图像转换为单位正方形((0,0) - (1.0,1.0))
你需要三点,一是为原点,其他将转变。向x轴(1.0,0),另一个在Y轴(0,1.0)



在原始坐标系统




  • 起源(牛,Oy公司)

  • X轴是(X1,Y2)

  • Y轴是(X2,Y2)

  • X轴相对于原点(X1-牛,Y1-Oy公司)将缩短至(RX1,RY1)

  • Y轴相对于原点(X2-牛,Y2-Oy公司)将缩短至(RX2,RY2)



首先,我们将产地转移到(0,0)的齐次坐标变换矩阵将

 (1 0 -Ox)
(0 1 -oy)
(001)



在新的空间,以旧是由以下矩阵表示变换:

 (RX1 RX2 0 )
(RY1 RY2 0)
(001)

由于您要逆变换,从旧空间的新的,我们需要反转这个矩阵:
让我们缩短(RX1 * RY2,RX2 * RY1)为D

 (RY2 / D -RX2 / D 0)
(-RY2 / D RX1 / D 0)
(001)

现在,你可以乘这两个矩阵首先你做翻译,然后用第二个矩阵变换的基础。


I have an array of coordinates that reflect known positions on an image. Let's call this the template image. It has a unique barcode and orientation markers (which are also in the coordinate array).

The image is printed, scanned and fed back into my application to be detected. During printing and scanning, the image could be transformed in three ways; translation, rotation and scale.

Assuming that I can find the orientation markers on the distorted image, how can I use matrix transformation to get the relative positions of the remaining coordinates?

I posted this question on SO before but made it too complicated to understand what I wanted.

EDIT

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");
}
}
}

解决方案

I'm assuming you want to transform the image to the unit square ( (0, 0) - (1.0, 1.0)) You need three points, one is the origin, the other will be transformed to the x-axis (1.0, 0) and the other to the y-axis (0, 1.0).

In the original coordinate system:

  • origin is (Ox, Oy)
  • X-Axis is (X1, Y2)
  • Y-Axis is (X2, Y2)
  • X-Axis relative to origin (X1-Ox, Y1-Oy) will be shortened to (RX1, RY1)
  • Y-Axis relative to origin (X2-ox, Y2-Oy) will be shortened to (RX2, RY2)

First we will shift the origin to (0,0) in homogeneous coordinates the transform matrix will be

(1   0   -Ox)
(0   1   -Oy)
(0   0    1) 

The transform from the new space to the old one is represented by the following matrix:

(RX1   RX2   0)
(RY1   RY2   0)
( 0    0     1)

Because you want the inverse transformation, from old space to the new one, we need the invert this matrix: Let's shorten (RX1*RY2-RX2*RY1) as D

(RY2/D   -RX2/D   0)
(-RY2/D   RX1/D   0)
(  0       0      1)

Now you can multiply both matrices first you do the translation and then use the second matrix to transform the basis.

这篇关于矩阵/坐标转换在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆