diff --git a/data/detect_blob.png b/data/detect_blob.png new file mode 100644 index 000000000..fe8537ab0 Binary files /dev/null and b/data/detect_blob.png differ diff --git a/samples/cpp/detect_blob.cpp b/samples/cpp/detect_blob.cpp new file mode 100644 index 000000000..badbaaa41 --- /dev/null +++ b/samples/cpp/detect_blob.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +using namespace std; +using namespace cv; + + +static void help() +{ + cout << "\n This program demonstrates how to use BLOB to detect and filter region \n" + "Usage: \n" + " ./detect_blob \n" + "Press a key when image window is active to change descriptor"; +} + + +static String Legende(SimpleBlobDetector::Params &pAct) +{ + String s = ""; + if (pAct.filterByArea) + { + String inf = static_cast(&(ostringstream() << pAct.minArea))->str(); + String sup = static_cast(&(ostringstream() << pAct.maxArea))->str(); + s = " Area range [" + inf + " to " + sup + "]"; + } + if (pAct.filterByCircularity) + { + String inf = static_cast(&(ostringstream() << pAct.minCircularity))->str(); + String sup = static_cast(&(ostringstream() << pAct.maxCircularity))->str(); + if (s.length() == 0) + s = " Circularity range [" + inf + " to " + sup + "]"; + else + s += " AND Circularity range [" + inf + " to " + sup + "]"; + } + if (pAct.filterByColor) + { + String inf = static_cast(&(ostringstream() << (int)pAct.blobColor))->str(); + if (s.length() == 0) + s = " Blob color " + inf; + else + s += " AND Blob color " + inf; + } + if (pAct.filterByConvexity) + { + String inf = static_cast(&(ostringstream() << pAct.minConvexity))->str(); + String sup = static_cast(&(ostringstream() << pAct.maxConvexity))->str(); + if (s.length() == 0) + s = " Convexity range[" + inf + " to " + sup + "]"; + else + s += " AND Convexity range[" + inf + " to " + sup + "]"; + } + if (pAct.filterByInertia) + { + String inf = static_cast(&(ostringstream() << pAct.minInertiaRatio))->str(); + String sup = static_cast(&(ostringstream() << pAct.maxInertiaRatio))->str(); + if (s.length() == 0) + s = " Inertia ratio range [" + inf + " to " + sup + "]"; + else + s += " AND Inertia ratio range [" + inf + " to " + sup + "]"; + } + return s; +} + + + +int main(int argc, char *argv[]) +{ + vector fileName; + Mat img(600, 800, CV_8UC1); + if (argc == 1) + { + fileName.push_back("../data/detect_blob.png"); + } + else if (argc == 2) + { + fileName.push_back(argv[1]); + } + else + { + help(); + return(0); + } + img = imread(fileName[0], IMREAD_COLOR); + if (img.rows*img.cols <= 0) + { + cout << "Image " << fileName[0] << " is empty or cannot be found\n"; + return(0); + } + + SimpleBlobDetector::Params pDefaultBLOB; + // This is default parameters for SimpleBlobDetector + pDefaultBLOB.thresholdStep = 10; + pDefaultBLOB.minThreshold = 10; + pDefaultBLOB.maxThreshold = 220; + pDefaultBLOB.minRepeatability = 2; + pDefaultBLOB.minDistBetweenBlobs = 10; + pDefaultBLOB.filterByColor = false; + pDefaultBLOB.blobColor = 0; + pDefaultBLOB.filterByArea = false; + pDefaultBLOB.minArea = 25; + pDefaultBLOB.maxArea = 5000; + pDefaultBLOB.filterByCircularity = false; + pDefaultBLOB.minCircularity = 0.9f; + pDefaultBLOB.maxCircularity = (float)1e37; + pDefaultBLOB.filterByInertia = false; + pDefaultBLOB.minInertiaRatio = 0.1f; + pDefaultBLOB.maxInertiaRatio = (float)1e37; + pDefaultBLOB.filterByConvexity = false; + pDefaultBLOB.minConvexity = 0.95f; + pDefaultBLOB.maxConvexity = (float)1e37; + // Descriptor array for BLOB + vector typeDesc; + // Param array for BLOB + vector pBLOB; + vector::iterator itBLOB; + // Color palette + vector< Vec3b > palette; + for (int i = 0; i<65536; i++) + { + palette.push_back(Vec3b((uchar)rand(), (uchar)rand(), (uchar)rand())); + } + help(); + + + // This descriptor are going to be detect and compute BLOBS with 6 differents params + // Param for first BLOB detector we want all + typeDesc.push_back("BLOB"); // see http://docs.opencv.org/trunk/d0/d7a/classcv_1_1SimpleBlobDetector.html + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByArea = true; + pBLOB.back().minArea = 1; + pBLOB.back().maxArea = float(img.rows*img.cols); + // Param for second BLOB detector we want area between 500 and 2900 pixels + typeDesc.push_back("BLOB"); + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByArea = true; + pBLOB.back().minArea = 500; + pBLOB.back().maxArea = 2900; + // Param for third BLOB detector we want only circular object + typeDesc.push_back("BLOB"); + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByCircularity = true; + // Param for Fourth BLOB detector we want ratio inertia + typeDesc.push_back("BLOB"); + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByInertia = true; + pBLOB.back().minInertiaRatio = 0; + pBLOB.back().maxInertiaRatio = (float)0.2; + // Param for fifth BLOB detector we want ratio inertia + typeDesc.push_back("BLOB"); + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByConvexity = true; + pBLOB.back().minConvexity = 0.; + pBLOB.back().maxConvexity = (float)0.9; + // Param for six BLOB detector we want blob with gravity center color equal to 0 bug #4321 must be fixed + typeDesc.push_back("BLOB"); + pBLOB.push_back(pDefaultBLOB); + pBLOB.back().filterByColor = true; + pBLOB.back().blobColor = 0; + + itBLOB = pBLOB.begin(); + vector desMethCmp; + Ptr b; + String label; + // Descriptor loop + vector::iterator itDesc; + for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++) + { + vector keyImg1; + if (*itDesc == "BLOB") + { + b = SimpleBlobDetector::create(*itBLOB); + label = Legende(*itBLOB); + itBLOB++; + } + try + { + // We can detect keypoint with detect method + vector keyImg; + vector zone; + vector > region; + Mat desc, result(img.rows, img.cols, CV_8UC3); + if (b.dynamicCast() != NULL) + { + Ptr sbd = b.dynamicCast(); + sbd->detect(img, keyImg, Mat()); + drawKeypoints(img, keyImg, result); + int i = 0; + for (vector::iterator k = keyImg.begin(); k != keyImg.end(); k++, i++) + circle(result, k->pt, (int)k->size, palette[i % 65536]); + } + namedWindow(*itDesc + label, WINDOW_AUTOSIZE); + imshow(*itDesc + label, result); + imshow("Original", img); + waitKey(); + } + catch (Exception& e) + { + cout << "Feature : " << *itDesc << "\n"; + cout << e.msg << endl; + } + } + return 0; +}