OpenCV开发笔记(六十一):红胖子8分钟带你深入了解Shi-Tomasi角点检测(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106436768
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
上一篇:《OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)》
下一篇:持续补充中…
前言
红胖子,来也!
做识别,有时候遇到需求,比如识别一个三角形,并求得三角形三个顶点的角度,这种属于教育集合场景,还有其他类似场景,那么检测角点就显得很重要了。
Demo





图像特征三大类型
- 边缘:图像强度发生突变的区域,其实就是高强度梯度区域;
- 角点:两个边缘相交的地方,看起来像一个角;
- 斑点:按特征划分的区域,强度特别高、强度特别低或具备特定纹理的区域;
Shi-Tomasi角点
概述
Shi-Tomasi角点检测是改进了Harris算法,次算法最原始的定义是将矩阵M的行列式与M的迹想见,再将差值进行同预先给定的预制进行比较,后来再次改进,若两个特征值中较小的一个大于最小阈值,则会得到强角点。
原理
由于Harris算法的稳定性和k值有关,Shi-Tomasi发现,角点的稳定性和矩阵M的较小特征值有关,改进的Harris算法即直接计算出矩阵M的特征值,用较小的特征值与阈值比较,大于阈值的即为强特征点。
Harris角点概述
Harris角点检测是一种基于灰度图像的角点提取算法,稳定性高,在opencv中harris角点检测的性能相对较低,因为其使用了高斯滤波。
基于灰度图像的角点检测又分为基于梯度、基于模板和基于模板梯度组合三类型的方法,而Harris算法就是基于灰度图像中的基于模板类型的算法。
Harris角点原理
人眼对角点的识别通常是通过一个局部的小窗口内完成的:如果在各个方向上移动这个小窗口,窗口内的灰度发生了较大的变化,那么说明窗口内存在角点,具体分为以下三种情况:
- 如果在各个方向移动,灰度几乎不变,说明是平坦区域;
- 如果只沿着某一个方向移动,灰度几乎不变,说明是直线;
- 如果沿各个方向移动,灰度均发生变化,说明是角点。
基本的原理,如下图:

具体的计算公式如下:

泰勒展开:

代入得到:

其中:

二次项函数本质上就是一个椭圆函数,椭圆的扁平率和尺寸是由矩阵M的两个特征值决定的。


矩阵M的两个特征值与图像中的角点,边缘,平坦区域的关系。
Harris定义角点响应函数即:

即R=Det(M)-k*trace(M)*trace(M),k为经验常数0.04~0.06 。
定义当R>threshold时且为局部极大值的点时,定义为角点。
Shi-Tomasi检测角点函数原型
// 重载函数:九个参数
void goodFeaturesToTrack( InputArray image,
OutputArray corners,
int maxCorners,
double qualityLevel,
double minDistance,
InputArray mask = noArray(),
int blockSize = 3,
bool useHarrisDetector = false,
double k = 0.04);
// 重载函数:十个参数
void goodFeaturesToTrack( InputArray image,
OutputArray corners,
int maxCorners,
double qualityLevel,
double minDistance,
InputArray mask,
int blockSize,
int gradientSize,
bool useHarrisDetector = false,
double k = 0.04 );
- 参数一:InputArray类型的image,输入图像,即源图像,填Mat类的对象 即可,且须为单通道8位或者浮点型32位单通道图像;
- 参数二:OutputArray类型的corners,检测到的角点的输出向量;
- 参数三:int类型的maxCorners,角点的最大数据量;
- 参数四:double类型的qualityLevel,角点检测可接受的最小特征值。其实实际用于过滤角点的最小特征是qualityLevel与图像中最大特征值的乘积。所以qualityLevel通常不会超过1(常用的值为0.10或者0.01)。检测完后所有的交点后,还要进一步提出掉一些距离较近的角点;
- 参数五:double类型的minDistance,角点之间的最细小距离,次参数用于保证返回的角点之间的距离不小于minDistance;
- 参数六:InputArray类型的mask,可选参数,表示感情兴的区域,默认为noArray(),若此参数非空则必须需为CV_8UC1类型,且和第一个参数image有相同的尺寸;
- 参数七:int类型的blockSize,有默认值3,是计算导数自相关矩阵时指定的领域范围;
- 参数八:bool类型的useHarrisDetector,只是是否使用Harris角点检测,默认为false,不使用;
- 参数九:double类型的k,为用于设置Hessian自相关矩阵韩烈士的相对权重的权重系数,默认值为0.04;
Demo源码
void OpenCVManager::testShiTomasi()
{
QString fileName1 =
"E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
int width = 400;
int height = 300;
cv::Mat srcMat = cv::imread(fileName1.toStdString());
cv::resize(srcMat, srcMat, cv::Size(width, height));
cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName);
cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3),
srcMat.type());
int threshold1 = 200;
int threshold2 = 100;
int qualityLevel = 1;
int minDistance = 10;
while(true)
{
windowMat = cv::Scalar(0, 0, 0);
cv::Mat mat;
cv::Mat tempMat;
// 原图先copy到左边
mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat);
{
// 灰度图
cv::Mat grayMat;
cv::cvtColor(srcMat, grayMat, cv::COLOR_BGR2GRAY);
// copy
mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::Mat grayMat2;
cv::cvtColor(grayMat, grayMat2, cv::COLOR_GRAY2BGR);
cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);
// 均值滤波
cv::blur(grayMat, tempMat, cv::Size(3, 3));
cvui::printf(windowMat, width * 1 + 20, height * 0 + 20, "threshold1");
cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 40, 200, &threshold1, 0, 255);
cvui::printf(windowMat, width * 1 + 20, height * 0 + 80, "threshold2");
cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 100, 200, &threshold2, 0, 255);
// canny边缘检测
cv::Canny(tempMat, tempMat, threshold1, threshold2);
// copy
mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::cvtColor(tempMat, grayMat2, cv::COLOR_GRAY2BGR);
cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);
cvui::printf(windowMat, width * 1 + 20, height * 0 + 140, "qualityLevel / 100.0f");
cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 160, 200, &qualityLevel, 1, 100);
cvui::printf(windowMat, width * 1 + 20, height * 0 + 200, "minDistance");
cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 220, 200, &minDistance, 1, 100);
// Shi-Tomasi角点检测
std::vector<cv::Point2f> corners;
cv::goodFeaturesToTrack(grayMat, // 输入图像
corners, // 输出角点
100, // 最大输出角点数量
qualityLevel / 100.0f, // 最小特征值
minDistance, // 最小间隔距离
cv::noArray(), // 感兴趣的区域
3, // 计算矩阵时的领域范围
false, // 不适用harris角点检测
0.04); // 权重系数
// 绘制检测到的角点
cv::Mat tempMat2 = srcMat.clone();
for(int index = 0; index < corners.size(); index++)
{
cv::circle(tempMat2, corners.at(index), 2, cv::Scalar(0, 0, 255), 2);
}
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(mat, 0.0f, tempMat2, 1.0f, 0.0f, mat);
// Shi-Tomasi角点检测
cv::goodFeaturesToTrack(tempMat, // 输入图像
corners, // 输出角点
100, // 最大输出角点数量
qualityLevel / 100.0f, // 最小特征值
minDistance, // 最小间隔距离
cv::noArray(), // 感兴趣的区域
3, // 计算矩阵时的领域范围
false, // 不适用harris角点检测
0.04); // 权重系数
// 绘制检测到的角点
tempMat = srcMat.clone();
for(int index = 0; index < corners.size(); index++)
{
cv::circle(tempMat, corners.at(index), 2, cv::Scalar(0, 0, 255), 2);
}
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::addWeighted(mat, 0.0f, tempMat, 1.0f, 0.0f, mat);
}
// 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
工程模板:对应版本号v1.55.0
对应版本号v1.55.0
上一篇:《OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)》
下一篇:持续补充中…
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106436768
OpenCV开发笔记(六十一):红胖子8分钟带你深入了解Shi-Tomasi角点检测(图文并茂+浅显易懂+程序源码)的更多相关文章
- OpenCV开发笔记(六十九):红胖子8分钟带你使用传统方法识别已知物体(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV开发笔记(五十五):红胖子8分钟带你深入了解Haar、LBP特征以及级联分类器识别过程(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练
前言 红胖子,来也! 做图像处理,经常头痛的是明明分离出来了(非颜色的),分为几块区域,那怎么知道这几块区域到底哪一块是我们需要的,那么这部分就涉及到需要识别了. 识别可以自己写模板匹配.特征 ...
- OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体
前言 级联分类器的效果并不是很好,准确度相对深度学习较低,本章使用opencv通过tensorflow深度学习,检测已有模型的分类. Demo 可以猜测,1其实是人,18序号类是狗 ...
- OpenCV开发笔记(七十三):红胖子8分钟带你使用opencv+dnn+yolov3识别物体
前言 级联分类器的效果并不是很好,准确度相对深度学习较低,上一章节使用了dnn中的tensorflow,本章使用yolov3模型,识别出具体的分类. Demo 320x320,置信度0 ...
- OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台
前言 移植opencv到海思平台,opencv支持对视频进行解码,需要对应的ffmpeg支持. Ffmpeg的移植 Ffmpeg的移植请参考之前的文章:<FFmpeg开发笔记(十): ...
- Django开发笔记六
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...
随机推荐
- 【转帖】ESXI上安装和使用MegaCli
https://www.diewufeiyang.com/post/964.html 一.第一步获取安装文件,官网目前搜索也找不到了,这里附件提供之前保存的安装文件 点击下载 二.使用VMware v ...
- CPU实际频率查看
cat /sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq
- [转帖]用实力诠释细节!“Java性能调优六大工具”之JDK命令行工具
https://www.zhihu.com/people/javajia-gou-ji-zhu-44/posts JDK命令行工具 在JDK的开发包中,除了大家熟知的java.exe和javac. ...
- 分享一个项目:`learning_go_plan9_assembly`, 学习 golang plan9 汇编
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 近期在学习 golang plan9 汇编,总算基本做到了 ...
- 临上线项目使用ILRuntime热更
前言 我们有一个用Unity引擎开发了二十个月的mmo arpg手游项目,在安卓已经测试三轮了,出于IOS的热的考虑且结合我们的情况:全部代码都是纯C#开发非Lua,所以计划使用ILRuntime热更 ...
- 深入浅出Java多线程(二):Java多线程类和接口
引言 大家好,我是你们的老伙计秀才!今天带来的是[深入浅出Java多线程]系列的第二篇内容:Java多线程类和接口.大家觉得有用请点赞,喜欢请关注!秀才在此谢过大家了!!! 在现代计算机系统中,多线程 ...
- .NET MAUI 简介
欢迎使用.NET 多平台应用程序 UI.此版本标志着我们在统一 .NET 平台的多年旅程中的新里程碑.现在,您和超过 500 万其他 .NET 开发人员拥有面向 Android.iOS.macOS 和 ...
- linux(centos) 下搭建svn服务器
1. 使用yum安装svn yum -y install subversion 安装完成之后,验证安装结果 此命令会全自动安装svn服务器相关服务和依赖,安装完成会自动停止命令运行 若需查看svn安 ...
- Python下的三维建模和可视化
本文介绍基于AnyCAD Rapid Py三维图形平台开发Python的三维应用 1 准备工作 1.1 安装 vc_resit 2022 在Windows下,AnyCAD Rapid SDK依赖Vis ...
- Advanced Installer傻瓜式打包教程
工具 Advanced Installer 11.0 前言 这个包不复杂,没有服务和注册表等操作,但需要.NET Framework 4.5和MySQL,同时需要初始化一下数据库,下面一起来实操一下. ...