機(jī)器視覺中Blob是非常重要的特征,對(duì)于Blob的選擇可以依據(jù)其幾何特征,OpenCv中具有專門的
類來解決這個(gè)問題:
class CV_EXPORTS_W SimpleBlobDetector : public Feature2D { public: struct CV_EXPORTS_W_SIMPLE Params { CV_WRAP Params(); CV_PROP_RW float thresholdStep;//閾值步長(zhǎng) CV_PROP_RW float minThreshold;//最小閾值 CV_PROP_RW float maxThreshold;//最大閾值 CV_PROP_RW size_t minRepeatability; CV_PROP_RW float minDistBetweenBlobs;//兩個(gè)Blob的最小距離 CV_PROP_RW bool filterByColor//采用顏色分割; CV_PROP_RW uchar blobColor;//主要針對(duì)色彩的強(qiáng)度,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()); };
該類的使用方法是首先設(shè)置參數(shù)Params,然后提取滿足Param的Blob的重心。SimpleBlobDetector類雖然可以識(shí)別出滿足條件的Blob,并識(shí)別出Blob的重心,但是無法將其作為ROI區(qū)域分割開。
為了分割出Blob區(qū)域作為ROI區(qū)域,本例的主要步驟為:
1.SimpleBlobDetector 選出滿足條件的Blob的中心。
2.findContours 查找所有Blob的輪廓。
3.floodFill 漫水填充滿足條件的Blob區(qū)域。
4.在原圖中分割出滿足條件的Blob區(qū)域作為ROI區(qū)域
本例需要注意的有以下幾點(diǎn):
1.SimpleBlobDetector::Param具有默認(rèn)值,注意初始化。
2.由vector轉(zhuǎn)換為vector 的方法:points.push_back(keypoints[i].pt);
#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設(shè)置參數(shù) 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的關(guān)鍵點(diǎn)(中心) 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的重心為起始點(diǎn)進(jìn)行填充(該方案只適合B重心在Blob上的區(qū)域) 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));//注意輸入圖像為三通道,因此對(duì)三個(gè)通道都要填充 } 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區(qū)域 imshow("Blob", Blob); imshow("原圖", imagecolor); waitKey(); return 0; }
聯(lián)系客服