2017-11-26 2 views
0

Ich versuche, OpenCV-Methode WarpPerspective() von Grund auf neu zu implementieren, habe ich den Code unten, kann es Verschiebungen in y und x, aber wenn ich Homographie-Matrix von FindHomography() an die Funktion übergeben Ich habe es immer leeres Bild im Vergleich zu WarpPerspective() ausgegeben.implementieren openCV-Methode warpPerspective()

ich diese Definition folgte die neuen Positionen der Pixel zu finden:

s*x' h1 h2 h3 x s*y' = h4 h5 h6 * y s h7 h8 1 1

meine Mapping wie auf einfache Verschiebung funktioniert {1, 0,5, -51,0,1,50,0,0 , 1} enter image description here

aber als Matrix ist wie: [1.0340946, 0.032195676, -6.419126; 0.00302419, 1.0487343, -96.520393; 3.7013847e-06, 0.00010837225, 1] der Ausgang ist wie folgt: enter image description here

Meine Implementierung: -Given H, und Bild A, -Finden Sie neue Positionen von Pixeln in A und speichern Sie sie in TransArry.Where der Index des Arrays ist der linearisierte Index von A. -Remap Pixel von A in TranImg .

Mat transform(Mat A, Mat H) 
{ 
// allocate array of all locations 
int Numrows = A.rows; 
int Numcols = A.cols; 
int channels = A.channels(); 
cout << "rows " << Numrows << "col " << Numcols << "channels " << channels <<endl; 
int size = Numrows*Numcols; 
int MaxX,MaxY = -1000; 
int MinX,MinY = 1000; 
int *TransArry = (int *)malloc(sizeof(int)*size); 
int Idx; 

int homeX=Idx % Numcols; 
int homeY=Idx/Numcols; 
cout << H << endl; 

waitKey();   
for (Idx=0; Idx < size; ++Idx){ 

     homeX=Idx % Numcols; 
     homeY=Idx/Numcols; 

     float x = (H.at<float>(0,0) * (homeX)) +(H.at<float>(0,1) * (homeY)) + (H.at<float>(0,2) * 1) ; 
     float y = (H.at<float>(1,0) * (homeX)) +(H.at<float>(1,1) * (homeY)) + (H.at<float>(1,2) * 1) ; 
     float s = (H.at<float>(2,0) * (homeX)) +(H.at<float>(2,1) * (homeY)) + (H.at<float>(2,2) * 1) ; 

     cout << " x = " << x << " y= " << y << " s= " << s; 
     x = (x/s); 

     y = y/s; 

     // for the first col in TransMatrix 
     if (homeX ==0){ 
      if (x > MaxX) MaxX = x; 
      if (x < MinX) MinX = x; 
     } 

     //for thee first row in TransMatrix 
     if (homeY ==0){ 
      if (y > MaxY) MaxY = y; 
      if (y < MinY) MinY = y; 
     } 
     if((y)>=A.rows || (y)<0 || (x)>=A.cols || (x)<0){ 
      TransArry[Idx] = -1; 
      cout << "x= " << x << "y= "<< y << endl; 
     }else{ 
      TransArry[Idx] = (y * Numcols + x); 
     }   

     //cout << Numcols << endl; 
     cout <<  "New index of " << Idx << "is " << TransArry[Idx] << endl; 
     } 

     Mat tranImg ; 

     A.copyTo(tranImg); 
     tranImg = tranImg - tranImg; 
     cout <<  "Rows" << tranImg.rows << "cols" << tranImg.cols << "cha" << A.channels() << endl; 


     waitKey(); 
     // Remap Image 
     for (Idx=0; Idx < size; Idx ++){ 

      homeX=Idx % Numcols; 
      homeY=Idx/Numcols;     
      //tranImg.at<uchar>(homeY, homeX) =0; 
      if(TransArry[Idx] != -1){ 
       //cout << "Index " << Idx << "Passed " << endl; 
       int newhomeX=TransArry[Idx] % Numcols; // Col ID 
       int newhomeY=TransArry[Idx]/Numcols; // Row ID 


       cout << "Index is " << Idx << endl; 
       cout << "HomeX is " << homeX << " and HomeY is " << homeY << endl; 
       cout << "New Index is " << TransArry[Idx] << endl; 
       cout << "New HomeX is " << newhomeX << " and New HomeY is " << newhomeY << endl; 
       cout << "*****************************************"<< endl; 
       // if (!(Idx%100)) sleep(20); 

       tranImg.at<uchar>(newhomeY, (newhomeX*channels)) = A.at<uchar>(homeY, homeX*channels); 
       if(channels>1) 
        tranImg.at<uchar>(newhomeY, newhomeX*channels+1) = A.at<uchar>(homeY, homeX*channels+1); 
       if(channels>2) 
        tranImg.at<uchar>(newhomeY, newhomeX*channels+2) = A.at<uchar>(homeY, homeX*channels+2); 
       // if (!(Idx%100)){ 
        // imshow("inside", tranImg); 
        // waitKey(1); 
        // } 
       } 
     } 
     //cout << tranImg << endl; 

return tranImg; 

} 

H wird berechnet und verifiziert.

Also, gibt es ein Problem in der Art, wie ich auf die Matrizen H und A zugreifen?

Antwort

2

Siehe meine Antwort here und es sollte beide Fragen beantworten. Diese Antwort verwendet immer noch warpPerspective(), aber es gibt den vollen Einblick, wie berechnet werden kann, wie weit außerhalb der Bildgrenzen Ihre Homographie das Bild verzerrt, so dass Sie auf jeder Seite des Bildes entsprechend padieren können.

Wenn Sie manuell warpPerspective() machen, müssen Sie lediglich alle Ihre Bildkoordinaten in ein linearisiertes homogenes Array eingeben und mit Ihrer Homographie multiplizieren und dann durch die letzte Koordinate dividieren, um zu den kartesischen Koordinaten zurückzukehren. Dann können Sie die Interpolation mit remap() durchführen. Die Syntax für remap() kann verwirrend sein, also können Sie meine Antwort here beziehen, um eine Vorstellung davon zu bekommen, wie man sie benutzt. Diese Antwort zeigt eine manuelle Transformation und Interpolation, es sollte Ihnen (zumindest nahezu) identische Ergebnisse zu warpPerspective() geben.

+0

danke für Ihre ausführliche Antwort, ich habe eine Lösung versucht, aber ich bekomme nicht das gedrehte Bild. Soll ich meinen Code auf eine andere Frage stellen? da ich Probleme mit Matrizenelementen habe und versuche, sie in c-Array umzuwandeln. –

+1

@KaramAboGhalieh Ich denke, es passt immer noch in den Rahmen dieser Frage, Sie sollten nur Ihren ursprünglichen Beitrag bearbeiten und den Code und aktuelle Probleme (aber ich würde vorschlagen, keine Ihrer aktuellen Post entfernen). Wenn Sie Ihren Beitrag bearbeiten, wird er auch in der Fragenwarteschlange angezeigt, sodass Sie möglicherweise auch mehr Antworten erhalten. Überprüfen Sie auch mein GitHub Repo für [gepolsterte Warps in C++] (https://github.com/alkasm/padded-transformations-cpp), die hilfreich sein könnten. –

+0

meine Implementierung funktioniert gut für x oder y Verschiebung, aber es kann nicht umgehen volle H-Matrix –

Verwandte Themen