OpenCV_检测兴趣点
来源:互联网 发布:北航矩阵论答案 编辑:程序博客网 时间:2024/05/18 03:20
在计算机视觉领域,兴趣点(也称关键点或特征点)的概念已经得到了广泛的应用,包括目标识别、图像配准、视觉跟踪、三维重建等。这个概念的原理是,从图像中选取某些特征点并对图像进行局部分析,而非观察整幅图像。
*检测图像中的角点
角点是很容易在图像中定位的局部特征,并且大量存在于人造物体中。角点的价值在于它是两条边缘线的接合点,是一种二维特征,可以被精确地定位(即使是子像素级精度)
Harris特征检测是检测角点地经典方法。
OpenCV中检测Harris角点地基本函数是cv::cornerHarris.调用该函数时输入一个图像,返回地结果是一个浮点型图像,其中每个像素点表示角点强度。
原图:
效果:
代码:
HarrisDetector类:
class HarrisDetecter{private:cv::Mat cornerStrength;//32位浮点数型的角点强度图像cv::Mat cornerTh;//32位浮点数型的阈值化角点图像cv::Mat localMax;//局部最大值图像int neighbourhood;//平滑导数的邻域尺寸int aperture;//梯度计算的口径double k;//Harris参数double maxStrength;//阈值计算的最大强度double threshold;//计算得到的阈值int nonMaxSize;//非最大抑制的邻域尺寸cv::Mat kernel;//非最大抑制内核public:HarrisDetecter() :neighbourhood(3), aperture(3), k(0.01), maxStrength(0.0), threshold(0.01), nonMaxSize(3){setLocalMaxWindowSize(nonMaxSize);}void setLocalMaxWindowSize(int size){nonMaxSize = size;kernel.create(nonMaxSize, nonMaxSize, CV_8U);}void detect(const cv::Mat& image){cv::cornerHarris(image, cornerStrength, neighbourhood, aperture, k);//计算内部阈值double minStrength;cv::minMaxLoc(cornerStrength, &minStrength, &maxStrength);//检测局部最大值cv::Mat dilated;cv::dilate(cornerStrength, dilated, cv::Mat());cv::compare(cornerStrength, dilated, localMax, cv::CMP_EQ);}//用Harris值得到角点分布图cv::Mat getCornerMap(double qualityLevel){cv::Mat cornerMap;threshold = qualityLevel*maxStrength;cv::threshold(cornerStrength, cornerTh, threshold, 255, cv::THRESH_BINARY);cornerTh.convertTo(cornerMap, CV_8U);//非最大值抑制cv::bitwise_and(cornerMap, localMax, cornerMap);return cornerMap;}//用Harris值得到角点分布图void getCorners(std::vector<cv::Point>& points, double qualityLevel){cv::Mat cornerMap = getCornerMap(qualityLevel);getCorners(points, cornerMap);}void getCorners(std::vector<cv::Point>& points, const cv::Mat& cornerMap){for (int y = 0; y < cornerMap.rows; y++){const uchar* rowPtr = cornerMap.ptr<uchar>(y);for (int x = 0; x < cornerMap.cols; x++){if (rowPtr[x]){points.push_back(cv::Point(x, y));}}}}void drawOnImage(cv::Mat& image, const std::vector<cv::Point>& points,cv::Scalar color = cv::Scalar(255, 255, 255), int radius = 3, int thickness = 1){std::vector<cv::Point>::const_iterator it = points.begin();while (it != points.end()){cv::circle(image, *it, radius, color, thickness);it++;}}};
main函数:
int main(){cv::Mat image = cv::imread("church.jpg");cv::cvtColor(image, image, CV_BGR2GRAY);cv::imshow("original image", image);HarrisDetecter harris;harris.detect(image);std::vector<cv::Point>pts;harris.getCorners(pts, 0.02);harris.drawOnImage(image, pts);cv::imshow("harris detected", image);cvWaitKey();}错误记录:
在使用cv::cornerHarris()函数时报错,查阅官方文档:
其src为8位图像或浮点点图,故加载彩色图时image为CV_8U3
执行
cv::cvtColor(image, image, CV_BGR2GRAY);
语句后再次执行cv::cornerHarris()函数正确。
实现原理:
(因教材中公式有少量错误,故重新整理)
*适合跟踪的特征
有两个函数可以用来显式地计算Harris协方差矩阵地特征值(以及特征向量),即cv::cornerEignValAndVecs和cv::cornerMinEigenVal
还有一种对Harris地改进是针对特征点聚集地问题(兴趣点在图像中分布不均匀,聚集在高度纹理化地位置),改进的算法从Harris值最强的点开始,只允许一定距离之外的点成为兴趣点。,在OpenCV中调用函数
cv::goodFeaturesToTrack
实现这个算法,之所以采用这个函数名称,因为它检测到的特征非常适合作为视觉跟踪程序的起始集合。
cv::goodFeaturesToTrack与cv::coenerHarris效果的对比:
代码:
std::vector<cv::Point> corners;cv::goodFeaturesToTrack(image, corners,500,//返回角点的最大数量0.01,//质量等级10);//角点间允许的最大距离
*快速检测特征
Harris算子对角点做出了规范的数学定义,该定义基于在两个相互垂直的方向上强度值的变化率。虽然这是一种很完美的定义,但是它需要计算图像的导数,而计算导数非常耗时。
FAST(加速分割测试获得特征,Features from Accelerated Segment Test)专门用来快速检测兴趣点,只要对比几个像素,就可以判断是否为关键点。
在OpenCV中,检测特征点有通用接口,因此调用任何特征点检测器都非常容易。
结果:
代码:
int main(){cv::Mat image = cv::imread("church.jpg");std::vector<cv::KeyPoint> keypoints;cv::Ptr<cv::FastFeatureDetector> fast = cv::FastFeatureDetector::create(40);fast->detect(image, keypoints);cv::drawKeypoints(image, keypoints, image, cv::Scalar(255, 255, 255), cv::DrawMatchesFlags::DRAW_OVER_OUTIMG);cv::imshow("detected", image);cvWaitKey();}
在OpenCV3.3中,FastFeatureDetector为抽象类,不能实例化。
FAST检测器的使用方法为:
std::vector<cv::KeyPoint> keypoints;cv::Ptr<cv::FastFeatureDetector> fast = cv::FastFeatureDetector::create(40);
fast->detect(image, keypoints);OpenCV提供了在图像上画关键点的通用函数:
cv::drawKeypoints()
实现原理:
①测试圆周上相隔90°的四个点,若至少三个点都比圆心更亮或者更暗,进入②;
②检测圆上的像素点,如果存在这样一个圆弧,它的连续长度超过周长的3/4,并且它上面所有的像素强度值都与圆心的强度值明显不同,就确认为一个关键点。
*适配的特征检测
如果要更好地控制被检测特征点地数量,可使用cv::FeatureDetector的一个专门的子类,即cv::DynamicAdaptedFeatureDetector.它可以指定被检测兴趣点的数量范围。
这时使用FAST特征检测器的方法如下:
cv::DynamicAdaptedFeatureDetector fastD(
new cv::FastAdjuster(40),//特征检测器
150,//特征的最小数量
200,//特征的最大数量
50);//最大迭代次数
fastD.detect(image,keypoints);//检测特征点
(在OpneCV3.3.1官方文档中没有找到这个类)
*网格适配特征检测
实际上在检测图像中的关键点时,经常出现这种情况,即很多兴趣点聚集在特定的纹理区域,cv::GridAdaptedFeatureDetector可以在图像上定义一个网格,网格中的每个单元格可以设置一个最大元素数量。这里的理念是把被检测的关键点以更好的方式扩展到整幅图像上。
(OpenCV3.3.1的官方文档中同样没有找到这个类)
*尺度不变特征检测
计算机视觉界尺度不变特征的理念是:不仅在任何尺度下拍摄的物体都能检测到一致的关键点,而且每个被检测的特征点都对应一个尺度因子。
理想情况下,对于两幅图像中不同尺度的同一个物体点,计算得到的两个尺度因子之间的比率应该等于图像尺度的比率。
SURF全称“加速稳健特征”(Speeded Up Robust Feature),它们不仅是尺度不变特征,而且是具有较高计算效率的特征。
实现:
cv::Ptr<cv::FeatureDetector>detector = new cv::SURF(2000.0);//阈值detector->detect(image,keypoints);cv::drawKeypoints(image,keypoints,image,cv::Scalar(255,255,255),cv::DrawMatchedFlags::DRAW_RICH_KEYPOINTS);使用DRAW_RICH_KEYPOINTS可得到关键点的圆,并且圆的尺寸与每个特征计算得到的尺度成正比。为了使特征具有旋转不变性,SURF还让每个特征关联了一个方向,方向由院内的一条辐射线表示。
实现原理:
①对每个像素计算Hessian矩阵:
②根据矩阵的行列式的值,得到曲率的强度。该方法把角点定义为局部高曲率(即在多个方向上的变化幅度都很高)
Hessian矩阵的行列式值达到了局部最大值,那么就认为这是一个尺度不变性特征。
*SIFT特征检测算法
SUFR算法是SIFT算法的加速版,SIFT(尺度不变特征转换,Scale-Invariant Feature Transform)也采用图像空间和尺度空间的局部最大值,但它使用拉普拉斯滤波器响应而不是Hessian行列式值。SIFT算法检测的特征在空间和尺度上的定位更加精确,但是计算效率低。
调用方法:
cv::Ptr<cv::FeatureDetector>detector = new cv::SIFT();//阈值detector->detect(image,keypoints);cv::drawKeypoints(image,keypoints,image,cv::Scalar(255,255,255),cv::DrawMatchedFlags::DRAW_RICH_KEYPOINTS);*多尺度FAST特征的检测
1、BRISK(Binary Robust Invariant Scalable Keypoints,二元稳健恒定可扩展关键点)检测法,基于FAST特征检测法
代码:
int main(){cv::Mat image = cv::imread("church.jpg");std::vector<cv::KeyPoint> keypoints;cv::Ptr<cv::Feature2D> detector = cv::BRISK::create();detector->detect(image, keypoints);cv::drawKeypoints(image, keypoints, image, cv::Scalar(255, 255, 255),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);cv::imshow("BRISK", image);cvWaitKey();}*ORB特征检测算法
ORB代表定向FAST和旋转BRIEF(Oriented FAST and Rotated BRIEF)
这个缩写的第一层一丝表示关键点检测,第二层意思表示ORB算法提供的描述子。
效果:
代码:
int main(){cv::Mat image = cv::imread("church.jpg");std::vector<cv::KeyPoint> keypoints;cv::Ptr<cv::Feature2D> detector = cv::ORB::create(200,1.2,8);detector->detect(image, keypoints);cv::drawKeypoints(image, keypoints, image, cv::Scalar(255, 255, 255),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);cv::imshow("BRISK", image);cvWaitKey();}
- OpenCV_检测兴趣点
- OpenCV_描述和匹配兴趣点
- 检测兴趣点--00 简介
- OpenCV_人脸检测
- OpenCV_条形码检测
- 兴趣点
- 兴趣点检测方法及其最新改进思路
- 【OpenCV学习笔记 011】检测并匹配兴趣点
- OpenCV_(Corner Detect with Morphology) 基于形态学滤波的角点检测
- OpenCv_光流法运动目标检测
- POISearch兴趣点搜索
- POISearch兴趣点搜索
- 兴趣点取舍
- OpenCV_基于HOG特征的行人检测
- OpenCV_基于HOG特征的行人检测
- OpenCV_火焰检测——完整代码
- OpenCV_基于HOG特征的行人检测
- opencv_关于特征点匹配的数据结构
- 【Spring+SpringMVC+MyBatis深入学习及搭建】18.MyBatis+PageHelper实现分页
- TCP/IP网络编程 学习笔记_15 --多播与广播
- linux资料链接
- 树莓派
- dubbo-admin在jdk 1.8上部署出错问题
- OpenCV_检测兴趣点
- 【码云】git提交返回502错误,无法PUSH
- C# 给PDF文档添加超链接
- 京东商城选项卡效果改写
- 八种排序方法(五)——希尔排序
- 阿里云短信服务API服务调用SendSMSUtil
- 知道了很多道理,仍然过不好这一生
- 阿里云前端周刊
- 机器人技术基础pdf