30 #include <opencv2/imgproc/imgproc.hpp>
42 : m_contour(contour), m_moms(cv::moments(m_contour)),
44 m_center(m_moms.m10 / m_moms.m00, m_moms.m01 / m_moms.m00),
45 m_rect(cv::boundingRect(m_contour)) {}
47 double area()
const {
return m_area; }
50 double diameter()
const {
return 2 * std::sqrt(area() / CV_PI); }
53 double perimeter()
const {
return cv::arcLength(m_contour,
true); }
58 return 4 * CV_PI * area() / (perim * perim);
60 cv::Point2d center()
const {
return m_center; }
61 cv::Rect boundingRectangle()
const {
return m_rect; }
63 ContourType &&moveOutContour() {
return std::move(m_contour); }
66 ContourType m_contour;
73 BlobData getBlobDataFromContour(ContourType
const &contour) {
74 ContourInterrogation contourDetails(contour);
76 BlobData{contourDetails.center(), contourDetails.area(),
77 contourDetails.circularity(), contourDetails.diameter(),
78 contourDetails.boundingRectangle()};
80 ret.contour = std::move(contourDetails.moveOutContour());
84 BlobBasics getContourBasicDetails(ContourType
const &contour) {
85 ContourInterrogation contourDetails(contour);
86 return BlobBasics{contourDetails.center(), contourDetails.area(),
87 contourDetails.boundingRectangle()};
90 double getConvexity(ContourType
const &contour,
const double area) {
92 cv::convexHull(contour, hull);
93 auto hullArea = cv::contourArea(hull);
94 return area / hullArea;
97 LedMeasurementVec BasicThresholdBlobDetector::
98 operator()(cv::Mat
const &gray,
99 cv::SimpleBlobDetector::Params
const ¶ms) {
100 grayImage_ = gray.clone();
102 static_cast<int>((params.minThreshold + params.maxThreshold) / 2);
103 LedMeasurementVec ret;
104 for (
auto &contour : binarizeAndGetSolidComponents(thresh)) {
105 auto data = getBlobDataFromContour(contour);
106 if (params.filterByArea) {
107 if (data.area < params.minArea || data.area > params.maxArea) {
111 if (params.filterByCircularity) {
112 if (data.circularity < params.minCircularity) {
116 ret.push_back(LedMeasurement(castPointToFloat(data.center),
117 static_cast<float>(data.diameter),
122 std::vector<ContourType>
123 BasicThresholdBlobDetector::binarizeAndGetSolidComponents(
int thresh) {
125 cv::threshold(grayImage_, binarized, thresh, 255, cv::THRESH_BINARY);
126 std::vector<ContourType> contours;
127 std::vector<cv::Vec4i> hierarchy;
128 cv::findContours(binarized, contours, hierarchy, CV_RETR_CCOMP,
129 CV_CHAIN_APPROX_NONE);
130 auto n = contours.size();
131 std::vector<ContourType> ret;
132 for (std::size_t i = 0; i < n; ++i) {
135 if (hierarchy[i][2] < 0) {
136 ret.emplace_back(std::move(contours[i]));
142 void BasicThresholdBlobDetector::makeFloodFillMask(cv::Mat
const &gray) {
143 floodFillMask_.create(gray.rows + 2, gray.cols + 2, CV_8UC1);
144 origBoundsInFloodFill_ =
145 cv::Rect(1, 1, floodFillMask_.cols - 2, floodFillMask_.rows - 2);
147 void BasicThresholdBlobDetector::augmentPoint(cv::Point peakCenter,
151 cv::Mat scratchNot = ~floodFillMask_;
152 cv::Mat grayClone = grayImage_.clone();
153 cv::Rect filledBounds;
154 auto m_area = cv::floodFill(
155 grayClone, floodFillMask_, peakCenter, 255, &filledBounds, loDiff,
156 upDiff, CV_FLOODFILL_MASK_ONLY | ( 4) |
161 cv::Mat thisPointResults = scratchNot & floodFillMask_;
double perimeter() const
Gets perimeter - requires contour.
double circularity() const
As used by OpenCV, return value in [0, 1] - requires contour.
double diameter() const
Approximation of a diameter based on assumption of circularity.