2009-01-23 7 views
10

Ich habe ein Bild mit zwei Punkten, ausgerichtet sind etwa wie folgt:Bild drehen math (C#)

|----------------| 
|    | 
| .   | 
|    | 
|   .  | 
|    | 
|----------------| 

I sowohl X, Y für beide Punkte Koordinaten und ich brauche die Bild X Grad zu drehen, so dass es sieht stattdessen so aus:

|----------------| 
|    | 
|    | 
| .  .  | 
|    | 
|    | 
|----------------| 

Grundsätzlich, so dass sie nebeneinander ausgerichtet sind, was ist die Mathematik dafür? (A Codebeispiel in C# wäre noch besser, aber nicht erforderlich)

+0

Dies ist ein alter Thread, aber ich werde nur erwähnen, dass ich ein C# WinForms Bildrotationsverfahren hier gepostet haben: http://stackoverflow.com/questions/2163829/how-do-i-rotate-a-Bild-in-c-sharp – RenniePet

Antwort

14

Es kommt darauf an, welche Stelle Sie als „center“ verwenden möchten für Ihre Rotation. Lassen Sie uns den Punkt auf den oberen und linken Punkt A und den einen Punkt nach rechts und unter Punkt B setzen. Wenn Sie möchten, um den Punkt A drehen, so dass Punkt B mit ihm ausgerichtet ist, in Radiant den Drehwinkel der Berechnung so gehen würde:

double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X); 

ich nicht, wie sind Sie Ihr Bild Handhabung, so dass die folgende Dies gilt nur, wenn Sie System.Drawing.Graphics verwenden:

myImage.TranslateTransform(-pointA.X, -pointA.Y); 
myImage.RotateTransform((float) angle, MatrixOrder.Append); 
myImage.TranslateTransform(pointA.X, pointA.Y, MatrixOrder.Append); 

Ich hoffe, es hilft.

2

Sie müssen geometrische Drehmatrizen nachzuschlagen: See this site for an detailed explanation

jedoch für die besten Ergebnisse, müssen Sie vom Ziel zur Quelle zu transformieren und dann verwenden Sie die Transformation für jedes Zielpixel:

m = rotation matrix 

for each point p in destination 
    p' = p.m 
    get pixel p' from source 
    set pixle p in destination 

Es ist in .NET Framework Methoden, um dies zu tun: System.Drawing.Graphics.RotateTransform und System.Drawing.Graphics.TranslateTransform. Sie müssen eine Translation einrichten, um den Rotationspunkt des Bildes an den Ursprung zu verschieben, und dann die Drehung und dann eine weitere Translation anwenden, um sie an die ursprüngliche Position zurückzubringen. Sie müssen mit diesen Funktionen experimentieren, um herauszufinden, wie sie sich verhalten - ich bin im Moment an der Arbeit und habe nicht die Zeit, etwas Code zusammen zu bekommen, der funktioniert. :-(

5

Kein Code, sorry, aber ein stratagy.

Sie müssen durch Abtasten der das Quellbild das Ergebnisbild erstellen können. Sie kennen den Drehwinkel, so dass Sie jetzt erstellen müssen eine Mapper-Funktion, die auf dem Original aus dem Ergebnis Karten zurück

der Code einfach jede Zeile des Ergebnisbildes abtasten würde, und das Pixel auf das Originalfoto Karte zurück Sie können eine einfache tun;..

for (int plotY = 0; plotY < resultHeight; plotY++) 
{ 
    for (int plotX = 0; plotX < resultWidth; plotX++) 
    { 
     resultImage.PlotPixel(getOriginalPixel(plotX, plotY, angleOfRotation)); 
    } 
} 

So, jetzt brauchen wir nur noch das magische "getOriginalPixel" -Methode d, und hier kommt die Mathematik ins Spiel.

Wenn wir das Bild um 0 Grad drehen, dann ist plotX, plotY nur das X/Y des Originalbildes. Aber das macht keinen Spaß.

pickX = x * cos(angle) - y * sin(angle) 
pickY = y * cos(angle) + x * sin(angle) 

Ich denke, wird auf das Quellpixel zuordnen. Sie müssen überprüfen, ob es außerhalb der Grenzen ist und kehren nur schwarz oder etwas :)

+0

Sie sollten Color.Transparent zurückgeben, wenn es außerhalb der Grenzen ist – MrFox

2

zuerst den Mittelpunkt finden:

Point p = new Point((x1-x2)/2, (y1-y2)/2) 

Dann trigonomentry verwenden für den Winkel zu lösen. Ich gehe davon aus, dass wir den Ursprung auf unseren zentralen Punkt zurückgesetzt haben, so dass ich jetzt einen neuen x3 und y3 zu einem der Punkte habe.

hypotenuse = SqrRt(x3^2 + y3^2) 

Wir sind für den unbekannten Winkel der Lösung TH

Sin(TH) = opposite/hypotenuse 

Also für TH lösen wir brauchen:

TH = Asin(y3/hypotenuse) 

Drehen von TH.

Siehe Wikipedia for trigonometric functions reference

2

Bei einer allgemeinen 2D-Transformation müssen zwei Gleichungen mit 6 Unbekannten gelöst werden.

'x = xA + yB + C

' y = xD + yE + D

3 angegebene entsprechende Punkte, werden Sie 6 knowns haben und das System gelöst werden kann. Sie haben nur 4 Punkte in diesem Fall, da Sie sich nicht für Scherung interessieren, aber Sie könnten sich vorstellen, einen dritten Punkt in 90 Grad zu der Linie einzuführen, die von den anderen zwei Punkten gebildet wird. Erstellen eines gedrehten Bildes wird dann (pseudo codedily) nur so etwas wie:

for (y = 0; y < height; y++) 
for (x = 0; x < width; x++) 
    { 
    newx = x*A + y*B + C; 
    newy = x*D + y*D + E; 
    newimage(x,y) = oldimage(newx, newy); 
    } 
} 

Wenn die Leistung ist, kann die Multiplikationen in der inneren Schleife wichtig, optimiert werden weg von der Feststellung, dass y * B nur Änderungen im äußeren Aussehen und dass newx, newy wird durch die Konstanten A und D in der inneren Schleife geändert.

4

Der Code unten arbeitet

Matrix mRotate = new Matrix(); 
    mRotate.Translate(Convert.ToInt32(Width.Value)/-2, Convert.ToInt32(Height.Value)/-2, MatrixOrder.Append); 
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append); 

    using (GraphicsPath gp = new GraphicsPath()) 
    { // transform image points by rotation matrix 
     gp.AddPolygon(new Point[] { new Point(0, 0), new Point(Convert.ToInt32(Width.Value), 0), new Point(0, Convert.ToInt32(Height.Value)) }); 
     gp.Transform(mRotate); 
     PointF[] pts = gp.PathPoints; 

     // create destination bitmap sized to contain rotated source image 
     Rectangle bbox = boundingBox(bmpSrc, mRotate); 
     Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height); 


     using (Graphics gDest = Graphics.FromImage(bmpDest)) 
     { // draw source into dest 


      Matrix mDest = new Matrix(); 
      mDest.Translate(bmpDest.Width/2, bmpDest.Height/2, MatrixOrder.Append); 
      gDest.Transform = mDest; 
      gDest.DrawImage(bmpSrc, pts); 
      gDest.DrawRectangle(Pens.Transparent, bbox); 
      //drawAxes(gDest, Color.Red, 0, 0, 1, 100, ""); 
      return bmpDest; 
     } 
    }