OpenCV, как использовать массивы точек для сглаживания и выборки контуров?

У меня проблема с тем, чтобы научиться сглаживать и выбирать контуры в OpenCV (C ++ API). Допустим, у меня есть последовательность точек, полученных изcv::findContours (например, применяется к этому изображению:

enter image description here

В конечном итоге я хочу

To smooth a sequence of points using different kernels. To resize the sequence using different types of interpolations.

После сглаживания я надеюсь получить такой результат:

enter image description here

Я также решил нарисовать мой контур вcv::Matфильтрация мата (с использованием размытия или морфологических операций) и повторное нахождение контуров, но медленная и неоптимальная. Таким образом, в идеале я мог бы выполнять работу, используя исключительно последовательность точек.

Я прочитал несколько постов и наивно подумал, что могу простоstd::vector(изcv::Point) кcv::Mat и тогда функции OpenCV, такие как размытие / изменение размера, сделали бы работу за меня ... но они этого не сделали.

Вот что я попробовал:

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

Кто-нибудь может объяснить, как это сделать?

Кроме того, поскольку я, вероятно, буду работать с намного меньшими контурами, мне было интересно, как этот подход будет справляться с эффектом границы (например, при сглаживании, поскольку контуры круглые, последние элементы последовательности должны использоваться для вычисления нового значения первые элементы ...)

Большое спасибо за ваши советы,

Edit:

Я тоже пробовалcv::approxPolyDP() но, как вы можете видеть, он имеет тенденцию сохранять экстремальные точки (которые я хочу удалить):

Эпсилон = 0

enter image description here

Эпсилон = 6

enter image description here

Эпсилон = 12

enter image description here

Эпсилон = 24

enter image description here

Edit 2: По предположению Бена, кажется, чтоcv::GaussianBlur() не поддерживается, ноcv::blur() является. Это выглядит намного ближе к моим ожиданиям. Вот мои результаты, используя его:

к = 13

enter image description here

к = 53

enter image description here

к = 103

enter image description here

Чтобы обойти эффект границы, я сделал:

    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]);

Я все еще ищу решения для интерполяции / выборки моего контура.

Ответы на вопрос(7)

Ваш ответ на вопрос