Domanda

Ho un'immagine con due punti, allineata in questo modo:

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

Ho entrambe le coordinate X, Y per entrambi i punti e ho bisogno di ruotare l'immagine di X gradi in modo che appaia così:

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

Fondamentalmente in modo che si allineino l'uno accanto all'altro, qual è la matematica per questo? (Un esempio di codice in C # sarebbe ancora migliore ma non obbligatorio)

È stato utile?

Soluzione

Dipende da quale punto si desidera utilizzare come "centro" per la tua rotazione. Chiamiamo il punto verso l'alto e il punto sinistro A e quello a destra e sotto il punto B. Se vuoi ruotare attorno al punto A in modo che il punto B si allinei con esso, il calcolo dell'angolo di rotazione in radianti dovrebbe andare in questo modo:

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

Non capisco come stai gestendo la tua immagine, quindi quanto segue si applica solo se stai usando System.Drawing.Graphics:

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

Spero che sia d'aiuto.

Altri suggerimenti

Nessun codice, scusami, ma una stratagemma.

Devi essere in grado di creare l'immagine del risultato campionando l'immagine di origine. Conosci l'angolo di rotazione, quindi ora devi creare una funzione di mappatura che esegua il mapping dal risultato all'originale.

Il codice dovrebbe semplicemente scansionare ogni riga dell'immagine risultante e mappare il pixel sull'immagine originale. Puoi fare un semplice;

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

Quindi ora abbiamo solo bisogno del magico " getOriginalPixel " metodo, ed è qui che entra in gioco la matematica.

Se ruotiamo l'immagine di 0 gradi, quindi plotX, plotY è solo la X / Y dell'immagine originale. Ma non è divertente.

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

Penso che mapperà sul pixel di origine. Dovrai verificare se è fuori dai limiti e tornare semplicemente nero o qualcosa di simile :)

Il codice seguente funziona

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

Per prima cosa trova il punto centrale:

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

Quindi usa il trigonomentry per risolvere l'angolo. Suppongo che abbiamo ridisegnato l'origine al nostro punto centrale, quindi ora ho un nuovo x3 e y3 su uno dei punti.

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

Stiamo risolvendo l'angolo sconosciuto TH

Sin(TH) = opposite / hypotenuse

Quindi per risolvere per TH abbiamo bisogno:

TH = Asin(y3 / hypotenuse)

Ruota di TH .

Vedi Wikipedia per riferimento alle funzioni trigonometriche

L'esecuzione di una trasformazione 2D generale implica la risoluzione di una coppia di eq precauzioni con 6 incognite.

'x = xA + yB + C

'y = xD + yE + D

Dati 3 punti corrispondenti, avrai 6 noti e il sistema può essere risolto. In questo caso hai solo 4 punti, poiché non ti interessa il taglio, ma potresti immaginare di introdurre un terzo punto a 90 gradi rispetto alla linea formata dagli altri due punti. La creazione di un'immagine ruotata è quindi (pseudo-codedily) solo qualcosa del tipo:

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

Se le prestazioni sono importanti, le moltiplicazioni nel ciclo interno possono essere ottimizzate osservando che y * B cambia solo nell'aspetto esterno e che newx, newy cambia con le costanti A e D nel ciclo interno.

Devi cercare le matrici di rotazione geometriche: Visita questo sito per una spiegazione dettagliata

Tuttavia, per risultati ottimali, è necessario passare dalla destinazione alla sorgente e quindi utilizzare la trasformazione per ciascun pixel di destinazione:

m = rotation matrix

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

Esistono, nei metodi del framework .net, tutto ciò: System.Drawing.Graphics.RotateTransform e System.Drawing.Graphics.TranslateTransform . Sarà necessario impostare una traduzione per spostare il punto di rotazione dell'immagine sull'origine, quindi applicare la rotazione e quindi un'altra traduzione per riportarla nella posizione originale. Dovrai sperimentare queste funzioni per capire come si comportano: al momento sono al lavoro e non ho il tempo di mettere insieme un po 'di codice che funzioni. : - (

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top