SimpleBlobDetector 类移植
来源:互联网 发布:软件开发人员等级评定 编辑:程序博客网 时间:2024/06/06 03:18
opencv中集成了斑点检测的类:SimpleBlobDetector ,但是需要2.2版本以后才支持。
angstrom系统中自带的opencv版本是2.2.0的,恰好不支持斑点检测。之前编译了cvblob插件,没成功。
angstrom系统中自带的opencv版本是2.2.0的,恰好不支持斑点检测。之前编译了cvblob插件,没成功。
看了新版本里的SimpleBlobDetector 类后,发现其实现并不难,基于FeatureDetector类,而FeatureDetector是一个特征检测的基础类,其成员函数并没有什么实质的东西。而SimpleBlobDetector 类的实现函数用到的函数、变量类型等都是opencv2.2版本中有的,所以可以直接把SimpleBlobDetector 类拿出来,放到自己的应用程序中。并且可以在带opencv2.2的系统中编译通过。
/**头文件:定义类*/#ifndef BLOB_H#define BLOB_H#include <opencv2/core/core.hpp>#include <opencv2/core/types_c.h>#include <opencv2/flann/miniflann.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/imgproc/imgproc_c.h>#include <opencv2/core/internal.hpp>#include <iterator>#include <opencv2/highgui/highgui.hpp>#include <iostream>using namespace cv;using namespace std;class CV_EXPORTS BlobDetector //: public cv::FeatureDetector{public: struct CV_EXPORTS Params { Params(); float thresholdStep; float minThreshold; float maxThreshold; size_t minRepeatability; float minDistBetweenBlobs; bool filterByColor; uchar blobColor; bool filterByArea; float minArea, maxArea; bool filterByCircularity; float minCircularity, maxCircularity; bool filterByInertia; float minInertiaRatio, maxInertiaRatio; bool filterByConvexity; float minConvexity, maxConvexity; void read( const FileNode& fn ); void write( FileStorage& fs ) const; }; BlobDetector(const BlobDetector::Params ¶meters = BlobDetector::Params()); void read( const FileNode& fn ); void write( FileStorage& fs ) const;/**detect keypoints in an image.*image the image.*keypoints the detected keypoints*mask mask specifying where to look for keypoints(optional).must be a char* matrix with non-zero values in the region of intestest.*/ void detect(const Mat& image,vector<KeyPoint>& keypoints,const Mat& mask=Mat()) const;/**detect keypoints in an image set*images image collection*keypoints collection of keypoints detected in an input image.* keypoints[i] is a set of keypoints detected in an images[i]*masks masks for image set. masks[i] is a mask for images[i].*/ void detect(const vector<Mat>& images,vector< vector<KeyPoint> >& keypoints,const vector<Mat>& masks=vector<Mat>()) const; static Ptr<BlobDetector> create(const string& detectorName); void blobTest();protected: struct CV_EXPORTS Center { Point2d location; double radius; double confidence; }; void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const; void findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, std::vector<Center> ¢ers) const; Params params;};#endif // BLOB_H
/**源文件:类的实现*/#include "blob.h"/** BlobDetector*/BlobDetector::Params::Params(){ thresholdStep = 10; minThreshold = 50; maxThreshold = 220; minRepeatability = 2; minDistBetweenBlobs = 10; filterByColor = true; blobColor = 0; filterByArea = true; minArea = 25; maxArea = 5000; filterByCircularity = false; minCircularity = 0.8f; maxCircularity = std::numeric_limits<float>::max(); filterByInertia = true; //minInertiaRatio = 0.6; minInertiaRatio = 0.1f; maxInertiaRatio = std::numeric_limits<float>::max(); filterByConvexity = true; //minConvexity = 0.8; minConvexity = 0.95f; maxConvexity = std::numeric_limits<float>::max();}void BlobDetector::Params::read(const cv::FileNode& fn ){ thresholdStep = fn["thresholdStep"]; //getFileNodeByName,从文件中读取参数 minThreshold = fn["minThreshold"]; maxThreshold = fn["maxThreshold"]; minRepeatability = (size_t)(int)fn["minRepeatability"]; minDistBetweenBlobs = fn["minDistBetweenBlobs"]; filterByColor = (int)fn["filterByColor"] != 0 ? true : false; blobColor = (uchar)(int)fn["blobColor"]; filterByArea = (int)fn["filterByArea"] != 0 ? true : false; minArea = fn["minArea"]; maxArea = fn["maxArea"]; filterByCircularity = (int)fn["filterByCircularity"] != 0 ? true : false; minCircularity = fn["minCircularity"]; maxCircularity = fn["maxCircularity"]; filterByInertia = (int)fn["filterByInertia"] != 0 ? true : false; minInertiaRatio = fn["minInertiaRatio"]; maxInertiaRatio = fn["maxInertiaRatio"]; filterByConvexity = (int)fn["filterByConvexity"] != 0 ? true : false; minConvexity = fn["minConvexity"]; maxConvexity = fn["maxConvexity"];}void BlobDetector::Params::write(cv::FileStorage& fs) const //储存参数{ fs << "thresholdStep" << thresholdStep; fs << "minThreshold" << minThreshold; fs << "maxThreshold" << maxThreshold; fs << "minRepeatability" << (int)minRepeatability; fs << "minDistBetweenBlobs" << minDistBetweenBlobs; fs << "filterByColor" << (int)filterByColor; fs << "blobColor" << (int)blobColor; fs << "filterByArea" << (int)filterByArea; fs << "minArea" << minArea; fs << "maxArea" << maxArea; fs << "filterByCircularity" << (int)filterByCircularity; fs << "minCircularity" << minCircularity; fs << "maxCircularity" << maxCircularity; fs << "filterByInertia" << (int)filterByInertia; fs << "minInertiaRatio" << minInertiaRatio; fs << "maxInertiaRatio" << maxInertiaRatio; fs << "filterByConvexity" << (int)filterByConvexity; fs << "minConvexity" << minConvexity; fs << "maxConvexity" << maxConvexity;}/**/BlobDetector::BlobDetector(const BlobDetector::Params ¶meters) : params(parameters){}void BlobDetector::read( const cv::FileNode& fn ){ params.read(fn);}void BlobDetector::write( cv::FileStorage& fs ) const{ params.write(fs);}/**先找出轮廓,再通过轮廓的距求出其圆心和半径*/void BlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, vector<Center> ¢ers) const{ (void)image; centers.clear(); vector < vector<Point> > contours; Mat tmpBinaryImage = binaryImage.clone(); findContours(tmpBinaryImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找轮廓#ifdef DEBUG_BLOB_DETECTOR// Mat keypointsImage;// cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB );//// Mat contoursImage;// cvtColor( binaryImage, contoursImage, CV_GRAY2RGB );// drawContours( contoursImage, contours, -1, Scalar(0,255,0) );// imshow("contours", contoursImage );#endif for (size_t contourIdx = 0; contourIdx < contours.size(); contourIdx++) { Center center; center.confidence = 1; Moments moms = moments(Mat(contours[contourIdx])); //根据各种筛选模式筛选斑点 if (params.filterByArea) { double area = moms.m00; if (area < params.minArea || area >= params.maxArea) continue; } if (params.filterByCircularity) { double area = moms.m00; double perimeter = arcLength(Mat(contours[contourIdx]), true); double ratio = 4 * CV_PI * area / (perimeter * perimeter); if (ratio < params.minCircularity || ratio >= params.maxCircularity) continue; } if (params.filterByInertia) { double denominator = sqrt(pow(2 * moms.mu11, 2) + pow(moms.mu20 - moms.mu02, 2)); const double eps = 1e-2; double ratio; if (denominator > eps) { double cosmin = (moms.mu20 - moms.mu02) / denominator; double sinmin = 2 * moms.mu11 / denominator; double cosmax = -cosmin; double sinmax = -sinmin; double imin = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmin - moms.mu11 * sinmin; double imax = 0.5 * (moms.mu20 + moms.mu02) - 0.5 * (moms.mu20 - moms.mu02) * cosmax - moms.mu11 * sinmax; ratio = imin / imax; } else { ratio = 1; } if (ratio < params.minInertiaRatio || ratio >= params.maxInertiaRatio) continue; center.confidence = ratio * ratio; } if (params.filterByConvexity) { vector < Point > hull; convexHull(Mat(contours[contourIdx]), hull); double area = contourArea(Mat(contours[contourIdx])); double hullArea = contourArea(Mat(hull)); double ratio = area / hullArea; if (ratio < params.minConvexity || ratio >= params.maxConvexity) continue; } center.location = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00); //得出圆心坐标 if (params.filterByColor) { if (binaryImage.at<uchar> (cvRound(center.location.y), cvRound(center.location.x)) != params.blobColor) continue; } //compute blob radius 计算半径 { vector<double> dists; for (size_t pointIdx = 0; pointIdx < contours[contourIdx].size(); pointIdx++) { Point2d pt = contours[contourIdx][pointIdx]; dists.push_back(norm(center.location - pt)); } std::sort(dists.begin(), dists.end()); center.radius = (dists[(dists.size() - 1) / 2] + dists[dists.size() / 2]) / 2.; } centers.push_back(center);#ifdef DEBUG_BLOB_DETECTOR// circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 );#endif }#ifdef DEBUG_BLOB_DETECTOR// imshow("bk", keypointsImage );// waitKey();#endif}void BlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat&) const{ //TODO: support mask keypoints.clear(); Mat grayscaleImage; if (image.channels() == 3) cvtColor(image, grayscaleImage, CV_BGR2GRAY); else grayscaleImage = image; vector < vector<Center> > centers; for (double thresh = params.minThreshold; thresh < params.maxThreshold; thresh += params.thresholdStep) { Mat binarizedImage; threshold(grayscaleImage, binarizedImage, thresh, 255, THRESH_BINARY);#ifdef DEBUG_BLOB_DETECTOR// Mat keypointsImage;// cvtColor( binarizedImage, keypointsImage, CV_GRAY2RGB );#endif vector < Center > curCenters; findBlobs(grayscaleImage, binarizedImage, curCenters); vector < vector<Center> > newCenters; for (size_t i = 0; i < curCenters.size(); i++) {#ifdef DEBUG_BLOB_DETECTOR// circle(keypointsImage, curCenters[i].location, curCenters[i].radius, Scalar(0,0,255),-1);#endif bool isNew = true; for (size_t j = 0; j < centers.size(); j++) { double dist = norm(centers[j][ centers[j].size() / 2 ].location - curCenters[i].location); isNew = dist >= params.minDistBetweenBlobs && dist >= centers[j][ centers[j].size() / 2 ].radius && dist >= curCenters[i].radius; if (!isNew) { centers[j].push_back(curCenters[i]); size_t k = centers[j].size() - 1; while( k > 0 && centers[j][k].radius < centers[j][k-1].radius ) { centers[j][k] = centers[j][k-1]; k--; } centers[j][k] = curCenters[i]; break; } } if (isNew) { newCenters.push_back(vector<Center> (1, curCenters[i]));//centers.push_back(vector<Center> (1, curCenters[i])); } } std::copy(newCenters.begin(), newCenters.end(), std::back_inserter(centers));#ifdef DEBUG_BLOB_DETECTOR// imshow("binarized", keypointsImage );//waitKey();#endif } for (size_t i = 0; i < centers.size(); i++) { if (centers[i].size() < params.minRepeatability) continue; Point2d sumPoint(0, 0); double normalizer = 0; for (size_t j = 0; j < centers[i].size(); j++) { sumPoint += centers[i][j].confidence * centers[i][j].location; normalizer += centers[i][j].confidence; } sumPoint *= (1. / normalizer); KeyPoint kpt(sumPoint, (float)(centers[i][centers[i].size() / 2].radius)); keypoints.push_back(kpt); }#ifdef DEBUG_BLOB_DETECTOR namedWindow("keypoints", CV_WINDOW_NORMAL); Mat outImg = image.clone(); for(size_t i=0; i<keypoints.size(); i++) { circle(outImg, keypoints[i].pt, keypoints[i].size, Scalar(255, 0, 255), -1); }//drawKeypoints(image, keypoints, outImg); imshow("keypoints", outImg); waitKey();#endif}void BlobDetector::detect(const Mat &image, vector<KeyPoint> &keypoints, const Mat &mask) const{ keypoints.clear(); if( image.empty() ) return; CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); detectImpl(image,keypoints,mask);}void BlobDetector::detect(const vector<Mat> &images, vector<vector<KeyPoint> > &keypoints, const vector<Mat> &masks) const{ keypoints.resize(images.size()); for( size_t i = 0; i< images.size(); i++ ) detect(images[i], keypoints[i], masks.empty()? Mat():masks[i]);}Ptr<BlobDetector> BlobDetector::create(const string &detectorName){ BlobDetector* fd = 0; if( !detectorName.compare("Blob") ) fd = new BlobDetector(); return fd;}void BlobDetector::blobTest(){ cout << "----------blob debug-----------" << endl; cout << params.thresholdStep << endl << params.minThreshold << endl << params.maxThreshold << endl << params.minRepeatability << endl << params.minDistBetweenBlobs << endl << params.minArea << endl;// VideoCapture camera(0); // video source for webcam// camera.set(CV_CAP_PROP_FRAME_WIDTH,640);// camera.set(CV_CAP_PROP_FRAME_HEIGHT,480);}
/**测试:采集摄像头,进行斑点检测*///测试blob工具,斑点检测// Initialize blob detectorBlobDetector::Params params;params.minThreshold = 40;params.maxThreshold = 60;params.thresholdStep = 5;params.minArea = 1000;params.minConvexity = .4f;params.minInertiaRatio = .1f;params.maxArea = 8000;params.maxConvexity = 2;params.filterByColor = false;params.filterByCircularity = false;BlobDetector blobDetector( params );blobDetector.create("Blob");vector<KeyPoint> keyPoints;blobDetector.blobTest();Mat blurImage; // blur imageMat hsvImage; // HSV imageMat hue; // hue channelMat hue1; // Hue upper boundMat hue2; // Hue lower boundMat hue3; // hue color filteringMat final; // Final display imagevector<Mat> slices;// Theshold Settingsint HuethresL = 30, HuethresH =71, blurSize = 1; //Greenfor(;;){camera->read(camImage);// blur imageblur(camImage, blurImage, Size(2,2));//imshow("blurImage", blurImage);// convert raw image to hsvcvtColor (camImage, hsvImage, CV_RGB2HSV);//imshow("hsvImage", hsvImage);blur(hsvImage, hsvImage, Size(3,3));//imshow("hsvImage blurImage", hsvImage);// split image to H,S and V imagessplit(hsvImage,slices);slices[0].copyTo(hue); // get the hue channelimshow("hue", hue);threshold (hue,hue1,HuethresL,255, CV_THRESH_BINARY); // get lower boundimshow("hue1", hue1);threshold (hue,hue2,HuethresH,255, CV_THRESH_BINARY_INV); // get upper boundimshow("hue2", hue2);hue3 = hue1 & hue2; // multiply to get color range//Just to show we can access the keyPoints array directly//You can also investigate the properties of the features to determine their _size_camImage.copyTo(final);blobDetector.detect(hue3, keyPoints);for(int i=0; i<keyPoints.size(); i++){circle(final, keyPoints[i].pt, 20, cvScalar(255,0,0), 10);}//Alternatively, there exists a simple function://drawKeypoints(camImage, keyPoints, final, CV_RGB(0,255,0), 4);// show imagesimshow("Webcam Orignal", camImage);imshow("Hue color",hue3);imshow("Final",final);if( cvWaitKey(10) >= 0 )break;}
0 0
- SimpleBlobDetector 类移植
- SimpleBlobDetector 类
- opencv: SimpleBlobDetector 使用
- 斑点SimpleBlobDetector检测
- opencv simpleBlobDetector入坑
- Opencv2.4.9源码分析——SimpleBlobDetector
- 图像局部特征(十六)--SimpleBlobDetector
- Opencv2.4.9源码分析——SimpleBlobDetector
- 利用OpenCV的SimpleBlobDetector检测图像的奇异区域(斑点)
- Opencv中SimpleBlobDetector的使用(斑点检测)
- Autoconf类项目移植
- (File类文件移植)
- 移植
- 移植
- 移植
- 移植
- SqlServer2005 尝试移植NET的String类
- VS2008环境中移植对话框类
- 初步理解加密,解密,数字签名,数字证书
- dd命令
- 蓝桥杯-代码填空之二
- 【BF算法 字符】
- Linux驱动之设备模型(7)
- SimpleBlobDetector 类移植
- 如何实现ubuntu每天定时关机
- windows 8 安装visual studio 2008的方法
- 算法学习笔记之三:八皇后问题(递归、回溯)
- JAVA JDK安装
- CF #133(DIV.2) B
- windows窗口样式和编辑框样式
- 常量指针与指针常量的区别(转帖)
- c++简单的习题