void MarkerDetector::findContours(cv::Mat& thresholdImg, ContoursVector& contours, int minContourPointsAllowed) { ContoursVector allContours; cv::findContours(thresholdImg, allContours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); contours.clear(); for (size_t i=0; i<allContours.size(); i++) { int contourSize = allContours[i].size(); if (contourSize > minContourPointsAllowed) { contours.push_back(allContours[i]); } } #ifdef SHOW_DEBUG_IMAGES { cv::Mat contoursImage(thresholdImg.size(), CV_8UC1); contoursImage = cv::Scalar(0); cv::drawContours(contoursImage, contours, -1, cv::Scalar(255), 2, CV_AA); cv::imshow("Contours", contoursImage); cv::waitKey(); } #endif }
bool MultiContourObjectDetector::findBaseShape(cv::Mat& baseImage) { vector<vector<vector<Point>>> approxContours = findApproxContours(baseImage, true, true); if (approxContours.size() == 0) { cerr << "ERROR: No valid contours found in base image" << endl; return false; } _baseShape = approxContours[0]; _aspectedContours = _baseShape.size(); _minContourPoints = numeric_limits<int>::max(); for (int i = 0; i < _baseShape.size(); i++) { vector<Point> tempKeypoints; Utility::findCentroidsKeypoints(_baseShape[i], tempKeypoints, Utility::CentroidDetectionMode::THREE_LOOP); _baseKeypoints.push_back(tempKeypoints); if (_baseShape[i].size() < _minContourPoints) _minContourPoints = _baseShape[i].size(); } #ifdef DEBUG_MODE Mat contoursImage(baseImage.size(), CV_8UC1); contoursImage = cv::Scalar(0); drawContours(contoursImage, _baseShape, -1, cv::Scalar(255), 1, CV_AA); imshow("TO FIND CONTOUR", contoursImage); #endif return true; }
// The workflow of the marker detection routine is the following: // 1. convert the input image to grayscale; // 2. perform a binary threshold operation; // 3. detect contours; // 4. search for possible markers; // 5. detect and decode markers; // 6. estimate marker 3D pose. void MarkerDetector::processFrame(const cv::Mat& frame) { // ... std::vector<Marker> markers; //cv::Mat bgraMat( frame.rows, frame.cols, CV_8UC4 ); //cv::cvtColor( frame, bgraMat, CV_BGR2BGRA ); // Convert the image to grayscale. // See: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor // The conversion to grayscale is necessary because markers usually contain only black and white blocks. // So it is much easier to operate with them using grayscale images. //cv::cvtColor( bgraMat, grayscaleImage, CV_BGRA2GRAY ); cv::cvtColor(frame, grayscaleImage, CV_BGR2GRAY); // Make it binary. // See: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold // The binarization operation will transform each pixel of our image to black (0 intensity) or white (255 intensity). // This step is required to find contours. cv::threshold(grayscaleImage, thresholdImg, 127.0, 255.0, cv::THRESH_BINARY_INV); #ifdef _DEBUG cv::imshow("THR", thresholdImg); #endif // Detect contours. MarkerDetector::findContours(thresholdImg, contours, grayscaleImage.cols / 5); #ifdef _DEBUG cv::Mat contoursImage(thresholdImg.size(), CV_8UC1); contoursImage = cv::Scalar(0); // See: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#drawcontours cv::drawContours(contoursImage, contours, -1, cv::Scalar(255), 2, CV_AA); cv::imshow("CNT", contoursImage); #endif // Find closed contours that can be approximated with 4 points. findMarkerCandidates(contours, markers); // Find if there are markers. detectMarkers(grayscaleImage, markers); // Calcualte their poses. estimatePosition(markers); // Sort by id. // See: http://www.cplusplus.com/reference/algorithm/sort/ std::sort(markers.begin(), markers.end()); // ... transformations.clear(); ids.clear(); for (size_t i = 0; i < markers.size(); i++) { transformations.push_back(markers[i].transformation); ids.push_back(markers[i].id); } }
// Each marker usually looks like a square figure with black and white areas inside it. // So the best way to locate a marker is to find closed contours and approximate them with polygons of 4 vertices. // This function will detect contours on the input binary image. // The return value is a list of polygons where each polygon represents a single contour. // This function skips contours that have their perimeter in pixel value set to be less than a specific input threshold. // This because we are not interested in small contours. void MarkerDetector::findContours(const cv::Mat& thresholdImg, std::vector< std::vector<cv::Point> >& contours, int minContourPointsAllowed) { std::vector< std::vector<cv::Point> > allContours; // See: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours cv::findContours(thresholdImg, allContours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); contours.clear(); for (size_t i = 0; i < allContours.size(); i++) { int contourSize = allContours[i].size(); if (contourSize > minContourPointsAllowed) { contours.push_back(allContours[i]); } } #ifdef _DEBUG cv::Mat contoursImage(thresholdImg.size(), CV_8UC1); contoursImage = cv::Scalar(0); cv::drawContours(contoursImage, contours, -1, cv::Scalar(255), 2, CV_AA); cv::imshow("Contours Image", contoursImage); #endif }