机器视觉中Blob是非常重要的特征,对于Blob的选择可以依据其几何特征,OpenCv中具有专门的 class CV_EXPORTS_W SimpleBlobDetector : public Feature2D { public: struct CV_EXPORTS_W_SIMPLE Params { CV_WRAP Params(); CV_PROP_RW float thresholdStep;//阈值步长 CV_PROP_RW float minThreshold;//最小阈值 CV_PROP_RW float maxThreshold;//最大阈值 CV_PROP_RW size_t minRepeatability; CV_PROP_RW float minDistBetweenBlobs;//两个Blob的最小距离 CV_PROP_RW bool filterByColor//采用颜色分割; CV_PROP_RW uchar blobColor;//主要针对色彩的强度,0选择暗的Blob,255选择亮的Blob CV_PROP_RW bool filterByArea;//采用最大最小面积分割 CV_PROP_RW float minArea, maxArea; CV_PROP_RW bool filterByCircularity;//采用圆度分割0~1 CV_PROP_RW float minCircularity, maxCircularity; CV_PROP_RW bool filterByInertia;//采用惯性率分割0~1 CV_PROP_RW float minInertiaRatio, maxInertiaRatio; CV_PROP_RW bool filterByConvexity;//采用凹凸度分割0~1 CV_PROP_RW float minConvexity, maxConvexity; void read( const FileNode& fn ); void write( FileStorage& fs ) const; }; CV_WRAP static Ptr<SimpleBlobDetector> create(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params()); }; 该类的使用方法是首先设置参数Params,然后提取满足Param的Blob的重心。SimpleBlobDetector类虽然可以识别出满足条件的Blob,并识别出Blob的重心,但是无法将其作为ROI区域分割开。 本例需要注意的有以下几点: #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include "opencv2/features2d.hpp"using namespace cv;using namespace std;int main(int argc, char** argv) { cv::Mat imagecolor, Blob, Mask; imagecolor = imread("../data/Blob.png"); //为SimpleBlobDetector设置参数 SimpleBlobDetector::Params params; params.filterByCircularity = true; params.filterByConvexity = false; params.filterByInertia = true; params.filterByArea = true; params.filterByColor = false; params.minThreshold = 0; params.maxThreshold = 255; params.blobColor = 255; params.minArea = 200; params.maxArea = 10000; params.minInertiaRatio = 0; params.maxInertiaRatio = 0.5; params.minCircularity = 0.5; params.maxCircularity = 1; //提取满足条件的Blob的关键点(中心) Ptr<SimpleBlobDetector> detetor = SimpleBlobDetector::create(params); vector<KeyPoint> keypoints; detetor->detect(imagecolor, keypoints); drawKeypoints(imagecolor, keypoints, Mask, Scalar(255, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); //查找所有Blob轮廓 Mat imagegray; cvtColor(imagecolor, imagegray, CV_RGB2GRAY); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(imagegray, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); Mat drawing = Mat::zeros(imagecolor.size(), CV_8UC3); for (int i = 0; i < contours.size(); i++) { drawContours(drawing, contours, i, Scalar(255,255,255), 1, 8, hierarchy, 0, Point()); } //以满足条件的Blob的重心为起始点进行填充(该方案只适合B重心在Blob上的区域) vector<Point2f> points; Mat flood; for (int i = 0; i < keypoints.size(); i++) { points.push_back(keypoints[i].pt); floodFill(drawing, points[i], Scalar(255,255,255));//注意输入图像为三通道,因此对三个通道都要填充 } cv::Mat element5(2, 2, CV_8U, cv::Scalar(255, 255, 255)); cv::Mat open; cv::morphologyEx(drawing, open, cv::MORPH_OPEN, element5);//开操作去除未被选中的blob的contour imagecolor.copyTo(Blob, open);//分割出满足条件的Blob区域 imshow("Blob", Blob); imshow("原图", imagecolor); waitKey(); return 0; }
|
|