setcursorposition - Transformación de matriz/coordenadas en C#
programa en c++ para convertir de coordenadas polares a rectangulares (1)
Tengo una serie de coordenadas que reflejan posiciones conocidas en una imagen. Vamos a llamar a esto la imagen de la plantilla. Tiene un código de barras único y marcadores de orientación (que también están en la matriz de coordenadas).
La imagen se imprime, escanea y retroalimenta en mi aplicación para ser detectada. Durante la impresión y el escaneo, la imagen se puede transformar de tres maneras; traducción, rotación y escala.
Suponiendo que puedo encontrar los marcadores de orientación en la imagen distorsionada, ¿cómo puedo usar la transformación de matriz para obtener las posiciones relativas de las coordenadas restantes?
Publiqué esta pregunta en SO antes, pero lo hice demasiado complicado para entender lo que quería.
EDITAR
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");
}
}
}
Supongo que quieres transformar la imagen en el cuadrado de la unidad ((0, 0) - (1.0, 1.0)) Necesitas tres puntos, uno es el origen, el otro se transformará en el eje x (1.0, 0) y el otro al eje y (0, 1.0).
En el sistema de coordenadas original:
- el origen es (Ox, Oy)
- X-Axis es (X1, Y2)
- Eje Y es (X2, Y2)
- El eje X relativo al origen (X1-Ox, Y1-Oy) se acortará a (RX1, RY1)
- El eje Y relativo al origen (X2-ox, Y2-Oy) se acortará a (RX2, RY2)
Primero cambiaremos el origen a (0,0) en coordenadas homogéneas, la matriz de transformación será
(1 0 -Ox)
(0 1 -Oy)
(0 0 1)
La transformación del nuevo espacio al anterior está representada por la siguiente matriz:
(RX1 RX2 0)
(RY1 RY2 0)
( 0 0 1)
Como desea la transformación inversa, del espacio antiguo al nuevo, necesitamos invertir esta matriz: acortemos (RX1 * RY2-RX2 * RY1) como D
(RY2/D -RX2/D 0)
(-RY2/D RX1/D 0)
( 0 0 1)
Ahora puedes multiplicar ambas matrices primero haces la traducción y luego utilizas la segunda matriz para transformar la base.