2015-09-17 13 views

Antwort

4

Für mich Krümmung ist:

wo t die Position innerhalb der Kontur ist und x(t) resp. y(t) geben Sie die zugehörigen x resp. y Wert. Siehe here.

Also, nach meiner Definition der Krümmung, kann man es auf diese Weise implementieren:

std::vector<float> vecCurvature(vecContourPoints.size()); 

cv::Point2f posOld, posOlder; 
cv::Point2f f1stDerivative, f2ndDerivative; 
for (size_t i = 0; i < vecContourPoints.size(); i++) 
{ 
    const cv::Point2f& pos = vecContourPoints[i]; 

    if (i == 0){ posOld = posOlder = pos; } 

    f1stDerivative.x = pos.x -  posOld.x; 
    f1stDerivative.y = pos.y -  posOld.y; 
    f2ndDerivative.x = - pos.x + 2.0f * posOld.x - posOlder.x; 
    f2ndDerivative.y = - pos.y + 2.0f * posOld.y - posOlder.y; 

    float curvature2D = 0.0f; 
    if (std::abs(f2ndDerivative.x) > 10e-4 && std::abs(f2ndDerivative.y) > 10e-4) 
    { 
     curvature2D = sqrt(std::abs( 
      pow(f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y, 2.0f)/
      pow(f2ndDerivative.x + f2ndDerivative.y, 3.0))); 
    } 

    vecCurvature[i] = curvature2D; 

    posOlder = posOld; 
    posOld = pos; 
} 

Es funktioniert auf nicht geschlossene pointlists auch. Bei geschlossenen Konturen möchten Sie möglicherweise das Grenzverhalten ändern (für die ersten Iterationen).

UPDATE:

Erläuterung für die Derivate:

Ein Derivat nach einer kontinuierlichen 1 dimensionalen Funktion f(t) ist:

aber wir sind in einem diskreten Raum und haben zwei diskrete Funktionen f_x(t) und f_y(t) wo die kleinste Stufe für t ist eins.

Die zweite Ableitung ist die Ableitung der ersten Ableitung:

die Annäherung der ersten Ableitung verwenden, ist es ergibt zu:

Es gibt andere Näherungen für die Derivate, wenn y google es, Sie werden eine Menge finden.

+0

Danke für Ihren Kommentar. Aber ich verstehe nicht, warum f1stDerivative.x und f2ndDerivative.x als Formel berechnen können, die Sie im Code zeigen? – kookoo121

+0

Dafür gibt es mehrere Möglichkeiten. Ich füge der Antwort eine Erklärung hinzu. – Gombat

+0

Vielen Dank !!! – kookoo121

5

Während die Theorie hinter Gombats Antwort korrekt ist, gibt es sowohl im Code als auch in den Formeln einige Fehler (der Nenner t+n-x sollte t+n-t sein).Ich habe einige Änderungen vorgenommen:

  • symmetrische Derivate Verwendung präzise Positionen der Krümmungsmaxima zu bekommen
  • erlauben eine Schrittgröße für derivative Berechnung zu verwenden (kann verwendet werden, um Rauschen von lauten Konturen zu reduzieren)
  • Werke mit geschlossenen Konturen

Fixes: * Rückkehr Unendlichkeit als Krümmung wenn Nenner 0 ist (nicht 0) * hinzugefügt Quadratberechnungs in Nenner * korrekte Überprüfung auf 0 Divisor

std::vector<double> getCurvature(std::vector<cv::Point> const& vecContourPoints, int step) 
{ 
    std::vector<double> vecCurvature(vecContourPoints.size()); 

    if (vecContourPoints.size() < step) 
    return vecCurvature; 

    auto frontToBack = vecContourPoints.front() - vecContourPoints.back(); 
    std::cout << CONTENT_OF(frontToBack) << std::endl; 
    bool isClosed = ((int)std::max(std::abs(frontToBack.x), std::abs(frontToBack.y))) <= 1; 

    cv::Point2f pplus, pminus; 
    cv::Point2f f1stDerivative, f2ndDerivative; 
    for (int i = 0; i < vecContourPoints.size(); i++) 
    { 
     const cv::Point2f& pos = vecContourPoints[i]; 

     int maxStep = step; 
     if (!isClosed) 
     { 
      maxStep = std::min(std::min(step, i), (int)vecContourPoints.size()-1-i); 
      if (maxStep == 0) 
      { 
       vecCurvature[i] = std::numeric_limits<double>::infinity(); 
       continue; 
      } 
     } 


     int iminus = i-maxStep; 
     int iplus = i+maxStep; 
     pminus = vecContourPoints[iminus < 0 ? iminus + vecContourPoints.size() : iminus]; 
     pplus = vecContourPoints[iplus > vecContourPoints.size() ? iplus - vecContourPoints.size() : iplus]; 


     f1stDerivative.x = (pplus.x -  pminus.x)/(iplus-iminus); 
     f1stDerivative.y = (pplus.y -  pminus.y)/(iplus-iminus); 
     f2ndDerivative.x = (pplus.x - 2*pos.x + pminus.x)/((iplus-iminus)/2*(iplus-iminus)/2); 
     f2ndDerivative.y = (pplus.y - 2*pos.y + pminus.y)/((iplus-iminus)/2*(iplus-iminus)/2); 

     double curvature2D; 
     double divisor = f1stDerivative.x*f1stDerivative.x + f1stDerivative.y*f1stDerivative.y; 
     if (std::abs(divisor) > 10e-8) 
     { 
      curvature2D = std::abs(f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y)/
       pow(divisor, 3.0/2.0) ; 
     } 
     else 
     { 
      curvature2D = std::numeric_limits<double>::infinity(); 
     } 

     vecCurvature[i] = curvature2D; 


    } 
    return vecCurvature; 
} 
Verwandte Themen