前言

  红胖子,来也!
  做识别,有时候遇到需求,比如识别一个三角形,并求得三角形三个顶点的角度,这种属于教育场景类似的,还有其他场景,那么检测角点就显得很重要了,检测出角点并且求出其角度。

 

Demo

  
  
  
  
  
  

 

图像特征三大类型

  • 边缘:图像强度发生突变的区域,其实就是高强度梯度区域;
  • 角点:两个边缘相交的地方,看起来像一个角;
  • 斑点:按特征划分的区域,强度特别高、强度特别低或具备特定纹理的区域;
 

Harris角点

概述

  Harris角点检测是一种基于灰度图像的角点提取算法,稳定性高,在opencv中harris角点检测的性能相对较低,因为其使用了高斯滤波。
  基于灰度图像的角点检测又分为基于梯度、基于模板和基于模板梯度组合三类型的方法,而Harris算法就是基于灰度图像中的基于模板类型的算法。

原理

  人眼对角点的识别通常是通过一个局部的小窗口内完成的:如果在各个方向上移动这个小窗口,窗口内的灰度发生了较大的变化,那么说明窗口内存在角点,具体分为以下三种情况:

  • 如果在各个方向移动,灰度几乎不变,说明是平坦区域;
  • 如果只沿着某一个方向移动,灰度几乎不变,说明是直线;
  • 如果沿各个方向移动,灰度均发生变化,说明是角点。
      基本的原理,如下图:
      
      具体的计算公式如下:

      
      泰勒展开:
      
      代入得到:
      
      其中:
      
      二次项函数本质上就是一个椭圆函数,椭圆的扁平率和尺寸是由矩阵M的两个特征值决定的。
        
      
      矩阵M的两个特征值与图像中的角点,边缘,平坦区域的关系。
      Harris定义角点响应函数即:
      
      即R=Det(M)-k*trace(M)*trace(M),k为经验常数0.04~0.06 。
      定义当R>threshold时且为局部极大值的点时,定义为角点。

Harris函数原型

void cornerHarris(InputArray src,
OutputArray dst,
int blockSize,
int ksize,
double k,
intborderType=BORDER DEFAULT );
  • 参数一:InputArray类型的src,输入图像,即源图像,填Mat类的对象 即可,且须为单通道8位或者浮点型图像;
  • 参数二:OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸,特别注意输出类型是CV_32F;
  • 参数三:int类型的blockSize,表示邻域的大小;
  • 参数四:int类型的ksize,表示Sobel()算子的孔径大小;
  • 参数五:double类型的k,Harris角点响应函数,一般为0.04~0.06;
  • 参数六:int类型的borderType,图像像素的边界模式:
      

归一化概述

  归一化是指对矩阵cv::Mat进行归一化操作。
  归一化是一种无量纲处理手段,使物理系统数值的绝对值变成某种相对值关系。简化计算,缩小量值的有效办法。例如,滤波器中各个频率值以截止频率作归一化后,频率都是截止频率的相对值,没有了量纲。阻抗以电源内阻作归一化后,各个阻抗都成了一种相对阻抗值,“欧姆”这个量纲也没有了。等各种运算都结束后,反归一化一切都复原了。信号处理工具箱中经常使用的是nyquist频率,它被定义为采样频率的二分之一,在滤波器的阶数选择和设计中的截止频率均使用nyquist频率进行归一化处理。例如对于一个采样频率为500hz的系统,400hz的归一化频率就为400/500=0.8,归一化频率范围在[0,1]之间。
  

归一化函数原型

void normalize( InputArray src,
InputOutputArray dst,
double alpha = 1,
double beta = 0,
int norm_type = NORM_L2,
int dtype = -1,
InputArray mask = noArray());
  • 参数一:InputArray类型的src,一般为mat;
  • 参数二:InputOutputArray类型的dst,一般为mat,大小与src一样;
  • 参数三:double类型的alpha,归一化的最小值,默认值1;
  • 参数四:double类型的beta,归一化的最大值,默认值0;
  • 参数五:int类型的norm_type,归一化类型,具体查看cv::NormTypes,默认为;
  • 参数六:int类型的dtype,默认值-1,负数时,其输出矩阵与src类型相同,否则它和src有同样的通道数,且此时图像深度为CV_MAT_DEPTH。
  • 参数七:InputArray类型的mask,可选的操作掩膜,默认值为noArray();

增强图像函数原型

void convertScaleAbs(InputArray src,
OutputArray dst,
double alpha = 1,
double beta = 0);
  • 参数一:InputArray类型的src,一般为mat;
  • 参数二:OutputArray类型的dst,一般为mat,大小与src一样;
  • 参数三:double类型的alpha,归一化的最大值,默认值1;
  • 参数四:double类型的beta,归一化的最大值,默认值0;
 

Demo源码

void OpenCVManager::testHarris()
{
QString fileName1 =
"E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/16.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;
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 + 100, "threshold2");
cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 120, 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); // harris角点检测
cv::cornerHarris(grayMat, grayMat2, 2, 3, 0.01);
// 归一化与转换
cv::normalize(grayMat2, grayMat2, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
cv::convertScaleAbs(grayMat2 , grayMat2); //将归一化后的图线性变换成 8U位元符号整
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::cvtColor(grayMat2, grayMat2, cv::COLOR_GRAY2BGR); cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat); // harris角点检测
cv::cornerHarris(tempMat, tempMat, 2, 3, 0.01);
// 归一化与转换
cv::normalize(tempMat, tempMat, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
cv::convertScaleAbs(tempMat , tempMat); //将归一化后的图线性变换成 8U位元符号整
// copy
mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::cvtColor(tempMat, tempMat, cv::COLOR_GRAY2BGR);
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.54.0

  对应版本号v1.54.0

 
 

OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)的更多相关文章

  1. OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  2. OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  3. OpenCV开发笔记(六十九):红胖子8分钟带你使用传统方法识别已知物体(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  4. OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  5. OpenCV开发笔记(五十五):红胖子8分钟带你深入了解Haar、LBP特征以及级联分类器识别过程(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  6. OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练

    前言   红胖子,来也!  做图像处理,经常头痛的是明明分离出来了(非颜色的),分为几块区域,那怎么知道这几块区域到底哪一块是我们需要的,那么这部分就涉及到需要识别了.  识别可以自己写模板匹配.特征 ...

  7. OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体

    前言   级联分类器的效果并不是很好,准确度相对深度学习较低,本章使用opencv通过tensorflow深度学习,检测已有模型的分类.   Demo       可以猜测,1其实是人,18序号类是狗 ...

  8. OpenCV开发笔记(七十三):红胖子8分钟带你使用opencv+dnn+yolov3识别物体

      前言   级联分类器的效果并不是很好,准确度相对深度学习较低,上一章节使用了dnn中的tensorflow,本章使用yolov3模型,识别出具体的分类.   Demo   320x320,置信度0 ...

  9. OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台

    前言   移植opencv到海思平台,opencv支持对视频进行解码,需要对应的ffmpeg支持.   Ffmpeg的移植   Ffmpeg的移植请参考之前的文章:<FFmpeg开发笔记(十): ...

  10. Django开发笔记六

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...

随机推荐

  1. [转帖]怎么查看Linux服务器硬件信息,这些命令告诉你

    https://zhuanlan.zhihu.com/p/144368206 Linux服务器配置文档找不到,你还在为查询Linux服务器硬件信息发愁吗?学会这些命令,让你轻松查看Linux服务器的C ...

  2. [转帖]关于winrm远程ps登录执行出现中文乱码和?乱码问题及其解决办法

    https://segmentfault.com/a/1190000040566946?utm_source=sf-similar-article python的winrm库提供了命令行远程连接的功能 ...

  3. [转帖]python字符串如何删除后几位

    https://www.python51.com/jc/15070.html 1.首先在jupyter notebook中新建一个空白的python文件: 2.然后定义一个字符串,用字符串截取的方式打 ...

  4. 如何安装typescript-如何运行typescript

    如何安装 typescript npm install typescript -g 安装 ts 之前需要安装 node 哈 查看 ts 的版本 tsc -V 我的是 3.6.3 的版本 typescr ...

  5. plcTIA Portal V16找不到许可证

    首先快捷键win+s唤出搜索,搜:服务 其次搜索这个服务Automation License Manager Service 右击-启动服务,然后重新启动plc即可选择CPU型号了

  6. 未能加载文件或程序集“System.ValueTuple, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。

    一些老的项目在使用SAEA.Socket相关库后,程序本地测试正常,结果上传到服务器上后提示:未能加载文件或程序集"System.ValueTuple, Version=0.0.0.0, C ...

  7. C++ CryptoPP使用AES加解密

    Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库.它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密.非对称加密.哈希函数.消息认证码 (MAC).数字签名等.C ...

  8. 转换流(InputStreamReader OutputStreamWriter)

    1.字节输出转换流(OutputStreamWriter) 1 package iochange; 2 3 import java.io.*; 4 5 /* 6 java.io.OutputStrea ...

  9. 物联网浏览器(IoTBrowser)-Modbus协议集成和测试

    Modbus协议在应用中一般用来与PLC或者其他硬件设备通讯,Modbus集成到IoTBrowser使用串口插件模式开发,不同的是采用命令函数,具体可以参考前面几篇文章.目前示例实现了Modbus-R ...

  10. AIX6.1系统NTP同步配置

    前言   当AIX系统的本地时间与时间服务器授出的标准时间误差大于±1000秒时.xntpd服务将无法同步时间并变得无法正常工作,请进行ntp配置前,先修改AIX系统的本地时间,尽量和时间服务器的标准 ...