OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

J'ai un problème pour obtenir ma tête autour de lissage et d'échantillonnage des contours dans OpenCV (API C++).
Disons que j'ai eu de la séquence de points récupérés à partir de cv::findContours (par exemple appliqué sur cette image:

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

En fin de compte, je veux

  1. Pour lisser une séquence de points à l'aide de différents noyaux.
  2. Pour redimensionner la séquence à l'aide de différents types d'interpolations.

Après le lissage, j'espère avoir un résultat comme :

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

J'ai également considéré le dessin de mon contour dans un cv::Matle filtrage, le Tapis (à l'aide de flou ou les opérations morphologiques) et de re-trouver les contours, mais il est lent et sous-optimale. Donc, idéalement, je pouvais faire le travail en utilisant exclusivement le point de la séquence.

J'ai lu quelques posts sur elle et pensais naïvement que je pourrais simplement de convertir un std::vector(de cv::Point) à un cv::Mat et puis OpenCV fonctions comme le flou ou le redimensionnement de faire le travail pour moi... mais ils n'ont pas.

Voici ce que j'ai essayé:

int main( int argc, char** argv ){

    cv::Mat conv,ori;
    ori=cv::imread(argv[1]);
    ori.copyTo(conv);
    cv::cvtColor(ori,ori,CV_BGR2GRAY);

    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Vec4i > hierarchy;

    cv::findContours(ori, contours,hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);

    for(int k=0;k<100;k += 2){
        cv::Mat smoothCont;

        smoothCont = cv::Mat(contours[0]);
        std::cout<<smoothCont.rows<<"\t"<<smoothCont.cols<<std::endl;
        /* Try smoothing: no modification of the array*/
//       cv::GaussianBlur(smoothCont, smoothCont, cv::Size(k+1,1),k);
        /* Try sampling: "Assertion failed (func != 0) in resize"*/
//       cv::resize(smoothCont,smoothCont,cv::Size(0,0),1,1);
        std::vector<std::vector<cv::Point> > v(1);
        smoothCont.copyTo(v[0]);
        cv::drawContours(conv,v,0,cv::Scalar(255,0,0),2,CV_AA);
        std::cout<<k<<std::endl;
        cv::imshow("conv", conv);
        cv::waitKey();
    }
    return 1;
}

Quelqu'un pourrait-il expliquer comment faire cela ?

En outre, depuis que j'ai la chance de travailler avec beaucoup de plus petits contours, je me demandais comment cette approche permettrait de traiter avec l'effet de bordure (par exemple, lorsque le lissage, car les contours sont circulaires, les derniers éléments d'une séquence doit être utilisée pour calculer la nouvelle valeur de la première éléments...)

Merci beaucoup pour vos conseils,

Edit:

J'ai aussi essayé cv::approxPolyDP() mais, comme vous pouvez le voir, elle tend à préserver extrémal points (qui je veux supprimer):

Epsilon=0

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

Epsilon=6

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

Epsilon=12

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

Epsilon=24

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

Edit 2:
Comme suggéré par Ben, il semble que cv::GaussianBlur() n'est pas pris en charge, mais cv::blur() est. Il a l'air beaucoup plus proche de mes attentes. Voici mes résultats en l'utilisant:

k=13

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

k=53

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

k=103

OpenCV, comment utiliser des tableaux de points pour lisser et échantillonner les contours?

Pour obtenir autour de la frontière effet, j'ai fait:

    cv::copyMakeBorder(smoothCont,smoothCont, (k-1)/2,(k-1)/2 ,0, 0, cv::BORDER_WRAP);
    cv::blur(smoothCont, result, cv::Size(1,k),cv::Point(-1,-1));
    result.rowRange(cv::Range((k-1)/2,1+result.rows-(k-1)/2)).copyTo(v[0]);

Je suis toujours à la recherche de solutions pour interpoler/exemple de mon contour.

source d'informationauteur Quentin Geissmann