OpenCV, jak używać tablic punktów do konturów wygładzania i próbkowania?
Mam problem z opanowaniem konturów wygładzania i próbkowania w OpenCV (C ++ API). Powiedzmy, że mam sekwencję pobranych punktówcv::findContours
(na przykład zastosowane na tym obrazie:
W końcu chcę
Wygładzanie sekwencji punktów przy użyciu różnych jąder.Aby zmienić rozmiar sekwencji przy użyciu różnych typów interpolacji.Po wygładzeniu mam nadzieję, że wynik będzie taki jak:
Rozważałem też rysowanie mojego konturu wcv::Mat
, filtrowanie Maty (za pomocą rozmycia lub operacji morfologicznych) i ponowne znalezienie konturów, ale jest powolne i nieoptymalne. Idealnie więc mógłbym wykonać zadanie, używając wyłącznie sekwencji punktów.
Przeczytałem kilka postów na ten temat i naiwnie pomyślałem, że mogę po prostu przekonwertowaćstd::vector
(zcv::Point
) do acv::Mat
a następnie funkcje OpenCV, takie jak rozmycie / zmiana rozmiaru, wykonają pracę za mnie ... ale nie zrobiły tego.
Oto, co próbowałem:
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;
}
Czy ktoś mógłby wyjaśnić, jak to zrobić?
Ponadto, ponieważ prawdopodobnie pracuję ze znacznie mniejszymi konturami, zastanawiałem się, w jaki sposób to podejście poradziłoby sobie z efektem granicznym (np. Podczas wygładzania, ponieważ kontury są okrągłe, ostatnie elementy sekwencji muszą być użyte do obliczenia nowej wartości pierwsze elementy ...)
Dziękuję bardzo za porady,
Edytować:
Próbowałem teżcv::approxPolyDP()
ale, jak widzisz, ma tendencję do zachowania ekstremalnych punktów (które chcę usunąć):
Epsilon = 0
Epsilon = 6
Epsilon = 12
Epsilon = 24
Edytuj 2: Jak sugeruje Ben, wydaje się, żecv::GaussianBlur()
nie jest obsługiwany, alecv::blur()
jest. Wygląda znacznie bliżej moich oczekiwań. Oto moje wyniki, które go używają:
k = 13
k = 53
k = 103
Aby obejść efekt granicy, zrobiłem:
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]);
Nadal szukam rozwiązań interpolujących / próbkujących mój kontur.