c++ - Proper way to determine thresholding parameters -
i trying find triangles (blue contours) , trapezoids (yellow contours) in real time. in general it's okay.
there problems. first it's false positives. triangles become trapezoids , vice versa. , don't know how how solve problem. second it's "noise". . tried check area of figure, noise can equal area. did not much. noise depends on thresholding parameters. cv::adaptivethreshold
does not @ all. it's adds more noise (and slow) erode
, dilate
cant fix in proper way
and here code.
cv::mat detect(cv::mat imagergb) { //rgb -> gray cv::mat imagegray; cv::cvtcolor(imagergb, imagegray, cv_bgr2gray); //bluring cv::mat image; cv::gaussianblur(imagegray, image, cv::size(5,5), 2); //thresholding cv::threshold(image, image, 100, 255, cv_thresh_binary_inv); //slow , noise //cv::adaptivethreshold(image, image, 255.0, cv_adaptive_thresh_gaussian_c, cv_thresh_binary, 21, 0); //calculating canny params. cv::scalar mu; cv::scalar sigma; cv::meanstddev(image, mu, sigma); cv::mat imagecanny; cv::canny(image, imagecanny, mu.val[0] + sigma.val[0], mu.val[0] - sigma.val[0]); //detecting conturs. std::vector<std::vector<cv::point> > contours; std::vector<cv::vec4i> hierarchy; cv::findcontours(imagecanny, contours, hierarchy,cv_retr_tree, cv_chain_approx_none); //hierarchy not needed here clear it. hierarchy.clear(); (std::size_t = 0; < contours.size(); i++) { //fitellipse need @ last 5 points. if (contours.at(i).size() < 5) { continue; } //skip small contours. if (std::fabs(cv::contourarea(contours.at(i))) < 800.0) { continue; } //calculating rotatedrect contours not hull //because fitellipse need @ last 5 points. cv::rotatedrect bellipse = cv::fitellipse(contours.at(i)); //finds convex hull of point set. std::vector<cv::point> hull; cv::convexhull(contours.at(i), hull, true); //approx it, we'll 3 point triangles //and 4 points trapez. cv::approxpolydp(hull, hull, 15, true); //is our contour convex. it's mast be. if (!cv::iscontourconvex(hull)) { continue; } //triangle if (hull.size() == 3) { cv::drawcontours(imagergb, contours, i, cv::scalar(255, 0, 0), 2); cv::circle(imagergb, bellipse.center, 3, cv::scalar(0, 255, 0), 2); } //trapez if (hull.size() == 4) { cv::drawcontours(imagergb, contours, i, cv::scalar(0, 255, 255), 2); cv::circle(imagergb, bellipse.center, 3, cv::scalar(0, 0, 255), 2); } } return imagergb; }
so... in general problems coused wrong thresholding parameters, how can calculete in proper way (automatically, of course)? , how can can (lol, sorry english) prevent false positives?
thesholding - think should try otsu binarization - here theory , nice picture , here documentation. kind of thresholding trying find 2 common values in image , use average value of them threshold value.
alternatively consider using hsv color space, might easier distinguish black , white regions other regions. idea use inrange function (in rgb or in hsv color space - should work in woth situations) - need find 2 ranges (one black regions , 1 white) , search regions (using inrange function) - at post.
another way accomplish task might using library blob extraction like one or blob extractor part of opencv.
distinguish triangle trapezoid - see 2 basic ways improve solution here:
- in line
cv::approxpolydp(hull, hull, 15, true);
make third parameter (15 in situation) not constant value, part of contour area or length. should adapt contour size, can't canstant value. it's hard how calculate without testing - try start 1-5% of contour area or length (i start length, guess) , see whether value fine/to big/to small check other values if needed. unfortunetely there no other way, finding equation manually shouldn't take long time. - when have 4 or 5 points calculate equations of lines join consecutive points (point 1 point 2, point 2 point 3, etc don't forget calculate line between first point , last point), check whether 2 of lines parallel (or @ least close being parallel - angle between them close 0 degress) - if find parallel lines contour trapezoid, otherwise it's triangle.
Comments
Post a Comment