2015-09-17 15 views

Odpowiedz

4

Dla mnie krzywizna jest:

t gdzie jest pozycja wewnątrz konturu i x(t) wzgl. y(t) zwróć odpowiednią odpowiedź x lub y wartość. Zobacz here.

Więc, według mojej definicji krzywizny, można wdrożyć go w ten sposób:

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

działa na niezamkniętych pointlists również. W przypadku zamkniętych konturów może zajść potrzeba zmiany zachowania granicy (dla pierwszych iteracji).

UPDATE:

wyjaśnienie pochodne:

Pochodna nieprzerwanie 1 funkcją wymiarów f(t) jest:

ale jesteśmy w dyskretnym miejscu i mieć dwie dyskretne funkcje f_x(t) i gdzie najmniejszy krok dla t to jeden.

Druga pochodna jest pochodną pierwszej pochodnej:

Stosując przybliżenie pierwszej pochodnej, to otrzymuje się:

Istnieją inne przybliżenia dla instrumentów pochodnych, jeżeli y ou google, znajdziesz dużo.

+0

Dzięki za komentarz. Ale nie rozumiem, dlaczego f1stDerivative.x i f2ndDerivative.x można obliczyć jako formule wyświetlane w kodzie? – kookoo121

+0

Istnieje kilka opcji. Dodaję wyjaśnienie do odpowiedzi. – Gombat

+0

Wielkie dzięki! – kookoo121

5

Podczas gdy teoria stojąca za odpowiedzią Gombata jest poprawna, występują pewne błędy w kodzie, jak również we wzorach (mianownik t+n-x powinien być t+n-t).Dokonaniu kilku zmian:

  • stosowanie pochodnych symetryczne, aby uzyskać bardziej precyzyjne rozmieszczenie krzywizny maksimów
  • pozwala na użycie wielkości kroku kalkulacji pochodnej (może być stosowany w celu ograniczenia hałasu z głośnym kontury)
  • prace przy zamkniętych konturów

rozwiązania: * powrotu nieskończoności, gdy krzywizna mianownikiem jest 0 (brak 0) * dodano kwadratowy obliczenia w mianowniku * prawidłowe kontrola 0 dzielnik

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; 
} 
Powiązane problemy