Rotationsmatrix verschiebt Matrix

  • C++/CLI

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von xd-franky-5.

    Rotationsmatrix verschiebt Matrix

    Hallo Leute,
    wollte erst keinen Thread extra aufmachen, weil es doch sehr banal ist, aber bekomme es einfach nicht gelöst. Ich habe eine Matrix beliebiger Größe, sagen wir mal 2x2, diese möchte ich drehen mittels einer Rotationsmatrix (da es später auch für größere Matrizen funktionieren soll und mit belieben Winkeln, keine 90°-270° Rotationsmatrizen sondern mit Sinus- und Cosinus-Funktion). Habe also diese hier:


    und daraus ergibt sich ja:


    Und damit man die Matrix um einen Punkt (Mitte) drehen kann habe ich folgendes als Code:

    C-Quellcode

    1. std::vector<T> mat(mat_.size());
    2. for(int Y = 0; Y < m_; Y++) {
    3. int row = Y * n_;
    4. for (int X = 0; X < n_; X++)
    5. {
    6. float xt = X - center[0];
    7. float yt = Y - center[1];
    8. int x = (cos * X) + (-sin * Y) + (center[0] - cos * center[0] - (-sin * center[1]));
    9. int y = (sin * X) + (cos * Y) + (center[1] - sin * center[0] - cos * center[1]);
    10. //int x = (int)(center[0] + xt * cos - yt * sin);
    11. //float y = (int)(center[1] + xt * sin + yt * cos);
    12. if(x >= 0 && x < n_ && y >= 0 && y < m_) mat[row + X] = get(y, x);
    13. }
    14. }

    Bei den zwei Zeile für x und y habe ich zwei Varianten versucht, eine 3D-Roll, eine 2D-Rotate und beide geben ein "kaputtes" Ergebnis, denn aus:
    12
    34

    wird nicht bei 90°:
    31
    42

    sondern:
    03
    04


    Also offensichtlich nach rechts verschoben. Habe das gelöst mit -1 in der Formel aber bei anderen Winkeln bringt das nichts, bei 180° ist die Verschiebung zB in Y-Richtung um 1. Bei geraden Matrizen also 2x2 4x4 ist es immer um 1.0 verschoben, bei ungeraden, wie 3x3 um 0.5
    Bei 1000x1000 Matrizen für Bilder ist das irrelevant aber bei so kleinen Matrizen nicht ganz.

    Hoffentlich kann mir da wer weiter helfen :x
    LG Frank

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „xd-franky-5“ ()

    @xd-franky-5 Was machst Du da überhaupt?
    Im theoretischen Teil machst Du Rotation: 1D-Vektor = 2D-Matrix * 1D-Vektor.
    Im Ergebnisteil listest Du 2D-Matrizen auf.
    Dort sollten eigentlich 1D-Vektoren stehen.
    Also:
    Räume Deinen Mathematik-Code auf.
    Eine Prozedur für Rotation, eine für Translation.
    Feddich.
    Spoiler anzeigen

    C#-Quellcode

    1. private void button1_Click(object sender, EventArgs e)
    2. {
    3. double[] vector = new double[] { 1, 0 };
    4. double angle = (double)this.numericUpDown1.Value * Math.PI / 180.0;
    5. double si = Math.Sin(angle);
    6. double co = Math.Cos(angle);
    7. double[,] matrix = new double[2, 2];
    8. matrix[0, 0] = co;
    9. matrix[0, 1] = -si;
    10. matrix[1, 0] = si;
    11. matrix[1, 1] = co;
    12. double[] vector2 = this.Rotation(matrix, vector);
    13. this.listBox1.Items.Add(string.Format("{0}° => {{{1:0.0}, {2:0.0}}}", this.numericUpDown1.Value , vector2[0], vector2[1]));
    14. }
    15. private double[] Rotation(double[,] matrix, double[] vector)
    16. {
    17. double[] vector2 = new double[2];
    18. vector2[0] = matrix[0, 0] * vector[0] + matrix[0, 1] * vector[1];
    19. vector2[1] = matrix[1, 0] * vector[0] + matrix[1, 1] * vector[1];
    20. return vector2;
    21. }
    22. private double[] Translation(double[] vector1, double[] vector2)
    23. {
    24. double[] vector = new double[2];
    25. vector[0] = vector1[0] + vector2[0];
    26. vector[1] = vector1[1] + vector2[1];
    27. return vector;
    28. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das obere Mathebeispiel bezieht sich auf einen Punkt XY einer Matrix. Aber eigentlich sollte das schon so gehen, dass man eine Matrix hat und sie mittels einer Rotationsmatrix dreht, siehe OpenCV:

    Wenn ich das in meinem Code, welcher jeden Punkt der neuen Matrix durchgeht und ihn berechnet aus der alten Matrix und der Rotationsmatrix, sieht das so aus:
    (Die oben genannte Matrix von OpenCV wird mit (x, y, 1) mulitpliziert)

    C-Quellcode

    1. void rotate(float theta, Vector<float> center) {
    2. float rads = (PI * theta) / 180.0;
    3. float scale = 1.0;
    4. float b = std::sin(rads) * scale;
    5. float a = std::cos(rads) * scale;
    6. std::vector<T> mat(mat_.size());
    7. for(int Y = 0; Y < m_; Y++) {
    8. int row = Y * n_;
    9. for (int X = 0; X < n_; X++)
    10. {
    11. int x = X * a + Y * b + ((1 - a) * center[0] - b * center[1]);
    12. int y = X * -b + Y * a + (b * center[0] + (1 - a) * center[1]);
    13. if(x >= 0 && x < n_ && y >= 0 && y < m_) mat[row + X] = get(y, x);
    14. }
    15. }
    16. mat_ = mat;
    17. }


    123
    456
    789

    90° gedreht sollte mit center 1.5 das herauskommen. (1.5 weil die hälfte von 3, mit center 1 ist es nicht verschoben aber dann stimmen die Werte nicht mehr)
    Und laut OpenCV M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1) stimmt 1.5 eigentlich auch, also wo liegt der Wurm?
    741
    852
    963

    es kommt aber das heraus mal wieder um 1 nach rechts verschoben:
    074
    085
    096


    LG Frank

    EDIT: Habe den Fehler, es lag an einem Rundungsfehler bei std::cos(rads), da kam 4...*10^-11 raus anstatt 0, mit round geht das nun oder mit double statt float.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „xd-franky-5“ ()

    xd-franky-5 schrieb:

    es lag an einem Rundungsfehler
    An welcher Stelle?
    Und
    Für eine Matrix-mal-Matrix-Multiplikation wäre eine weitere Prozedur zu implementieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    "bei std::cos(rads)" also Zeile 5 bei meinem Code. Habe nie von einer Matrizen-Multiplikation gesprochen. Jeder Punkt der Matrix wird als Vektor angesehen und rotiert mit der Rotationsmatrix.