opencv学习之路(32)、角点检测
一、角点检测的相关概念



二、Harris角点检测——cornerHarris()

参考网址: http://www.cnblogs.com/ronny/p/4009425.html

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat img = imread("E://3.jpg");
imshow("src", img);
Mat result = img.clone();
Mat gray, dst , corner_img;//corner_img存放检测后的角点图像
cvtColor(img, gray, CV_BGR2GRAY); cornerHarris(gray, corner_img, , , 0.04);//cornerHarris角点检测
//imshow("corner", corner_img);
threshold(corner_img, dst, 0.015, , CV_THRESH_BINARY);
imshow("dst", dst); int rowNumber = gray.rows; //获取行数
int colNumber = gray.cols; //获取每一行的元素
cout << rowNumber << endl;
cout << colNumber << endl;
cout << dst.type() << endl; for (int i = ; i<rowNumber; i++)
{
for (int j = ; j<colNumber; j++)
{
if (dst.at<float>(i, j) == )//二值化后,灰度值为255为角点
{
circle(result, Point(j, i),, Scalar(, , ), , );
}
}
} imshow("result", result);
waitKey();
}

浅墨代码
http://blog.csdn.net/poem_qianmo/article/details/29356187
#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; #define WINDOW_NAME1 "【程序窗口1】"
#define WINDOW_NAME2 "【程序窗口2】"
Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = ; //当前阈值
int max_thresh = ; //最大阈值 void on_CornerHarris(int, void*)
{
Mat dstImage;//目标图
Mat normImage;//归一化后的图
Mat scaledImage;//线性变换后的八位无符号整型的图 //初始化:置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
g_srcImage1 = g_srcImage.clone(); //进行角点检测
cornerHarris(g_grayImage, dstImage, , , 0.04);
// 归一化与转换
normalize(dstImage, normImage, , , NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型 // 进行绘制:将检测到的,且符合阈值条件的角点绘制出来
for (int j = ; j < normImage.rows; j++)
{
for (int i = ; i < normImage.cols; i++)
{
if ((int)normImage.at<float>(j, i) > thresh + )
{
circle(g_srcImage1, Point(i, j), , Scalar(, , ), , , );
circle(scaledImage, Point(i, j), , Scalar(, , ), , , );
}
}
}
imshow(WINDOW_NAME1, g_srcImage1);
imshow(WINDOW_NAME2, scaledImage); } static void ShowHelpText()
{
printf("\n\n\n\t\t\t【欢迎来到Harris角点检测示例程序~】\n\n");
printf("\n\n\n\t请调整滚动条观察图像效果~\n\n");
printf("\n\n\t\t\t\t\t\t\t\t by浅墨");
} void main()
{
system("color 3F");
ShowHelpText(); //载入原始图并进行克隆保存
g_srcImage = imread("E://1.jpg", );
if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return ; }
imshow("原始图", g_srcImage);
g_srcImage1 = g_srcImage.clone();
cvtColor(g_srcImage1, g_grayImage, CV_BGR2GRAY); //创建窗口和滚动条
namedWindow(WINDOW_NAME1, CV_WINDOW_NORMAL);
createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
on_CornerHarris(, );//调用一次回调函数,进行初始化 waitKey();
}

三、Shi-Tomasi角点检测——goodFeaturesToTrack()


#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat src = imread("E://0.jpg");
imshow("src", src);
Mat result = src.clone();
Mat gray;
cvtColor(src, gray,CV_BGR2GRAY); vector<Point2f>corners;//Point2f类型的向量:存储每个角点的坐标
//输入图,向量,最大角点数量,角点的最小特征值,角点间最小距离,掩码(Mat()表示掩码为空),blocksize,是否使用Harris角点检测,权重系数
goodFeaturesToTrack(gray, corners, ,0.01,,Mat(),,false,0.04);
cout << "角点数量" << corners.size() << endl; //画圆标注角点
for (int i = ; i < corners.size(); i++)
circle(result, corners[i], , Scalar(, , ),,);
imshow("result", result);
waitKey();
}

浅墨大神代码(加了滑动条效果)
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std; #define WINDOW_NAME "【Shi-Tomasi角点检测】"
Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = ;
int g_maxTrackbarNumber = ;
RNG g_rng();//初始化随机数生成器 //-----------------------------【on_GoodFeaturesToTrack( )函数】----------------------------
// 描述:响应滑动条移动消息的回调函数
//----------------------------------------------------------------------------------------------
void on_GoodFeaturesToTrack(int, void*)
{
//【1】对变量小于等于1时的处理
if (g_maxCornerNumber <= ) { g_maxCornerNumber = ; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
vector<Point2f> corners;
double qualityLevel = 0.01;//角点检测可接受的最小特征值
double minDistance = ;//角点之间的最小距离
int blockSize = ;//计算导数自相关矩阵时指定的邻域范围
double k = 0.04;//权重系数
Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域 //【3】进行Shi-Tomasi角点检测
goodFeaturesToTrack(g_grayImage,//输入图像
corners,//检测到的角点的输出向量
g_maxCornerNumber,//角点的最大数量
qualityLevel,//角点检测可接受的最小特征值
minDistance,//角点之间的最小距离
Mat(),//感兴趣区域
blockSize,//计算导数自相关矩阵时指定的邻域范围
false,//不使用Harris角点检测
k);//权重系数 //【4】输出文字信息
cout << "\t>此次检测到的角点数量为:" << corners.size() << endl; //【5】绘制检测到的角点
int r = ;
for (int i = ; i < corners.size(); i++)
{
//以随机的颜色绘制出角点
circle(copy, corners[i], r, Scalar(g_rng.uniform(, ), g_rng.uniform(, ),
g_rng.uniform(, )), -, , );
} //【6】显示(更新)窗口
imshow(WINDOW_NAME, copy);
} static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV2版的第87个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
//输出一些帮助信息
printf("\n\n\n\t欢迎来到【Shi-Tomasi角点检测】示例程序\n");
printf("\n\t请调整滑动条观察图像效果\n\n"); } void main()
{
system("color 2F");
ShowHelpText(); //【1】载入源图像并将其转换为灰度图
g_srcImage = imread("3.jpg", );
cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY); //【2】创建窗口和滑动条,并进行显示和回调函数初始化
namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
imshow(WINDOW_NAME, g_srcImage);
on_GoodFeaturesToTrack(, ); waitKey();
}
由于VS2015和opencv2有些兼容问题,会出现断言错误(具体原因在上一篇博客有讲),这里就不贴效果图了。
四、亚像素角点检测——cornerSubPix()

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat img = imread("E://2.jpg");
imshow("src", img);
Mat result = img.clone();
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY); //Shi-Tomasi角点检测
vector<Point2f> corners;
goodFeaturesToTrack(gray, corners, , 0.01, , Mat(), , false, 0.04);
cout << "角点数量" << corners.size() << endl; for (int i = ; i<corners.size(); i++)
{
cout << "像素坐标:(" << corners[i].x << ", " << corners[i].y << ")" << endl;
circle(result, corners[i], , Scalar(, , ), , );
}
imshow("result", result); Size winSize = Size(, );
Size zeroZone = Size(-, -);
//精度或最大迭代数目,其中任意一个达到 迭代次数40,精度0.001
TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, , 0.001);
cornerSubPix(gray, corners, winSize, zeroZone, criteria); for (int j = ; j<corners.size(); j++)
{
cout << "亚像素坐标:(" << corners[j].x << ", " << corners[j].y << ")" << endl;
circle(img, corners[j], , Scalar(, , ), -, );
}
imshow("subPix", img); waitKey();
}

opencv学习之路(32)、角点检测的更多相关文章
- 【OpenCV文档】用于角点检测的Fast算法
原文地址:http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_fast/py_fast.html#fast-algorithm- ...
- OpenCV亚像素级的角点检测
亚像素级的角点检测 目标 在本教程中我们将涉及以下内容: 使用OpenCV函数 cornerSubPix 寻找更精确的角点位置 (不是整数类型的位置,而是更精确的浮点类型位置). 理论 代码 这个教程 ...
- opencv学习之路(37)、运动物体检测(二)
一.运动物体轮廓椭圆拟合及中心 #include "opencv2/opencv.hpp" #include<iostream> using namespace std ...
- opencv学习之路(36)、运动物体检测(一)
一.简介 二.背景减法 图片说明 #include "opencv2/opencv.hpp"using namespace cv; void main() { Mat img1 = ...
- opencv学习之路(35)、SURF特征点提取与匹配(三)
一.简介 二.opencv中的SURF算法接口 三.特征点匹配方法 四.代码 1.特征点提取 #include "opencv2/opencv.hpp" #include < ...
- OpenCV 学习笔记03 直线和圆检测
检测边缘和轮廓不仅重要,还经常用到,它们也是构成其他复杂操作的基础. 直线和形状检测与边缘和轮廓检测有密切的关系. 霍夫hough 变换是直线和形状检测背后的理论基础.霍夫变化是基于极坐标和向量开展的 ...
- Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练
在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...
- opencv学习之路(41)、人脸识别
一.人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespace cv; using namespac ...
- opencv学习之路(34)、SIFT特征匹配(二)
一.特征匹配简介 二.暴力匹配 1.nth_element筛选 #include "opencv2/opencv.hpp" #include <opencv2/nonfree ...
随机推荐
- 《SQL Server性能调优实战》知识点汇总
2.4数据库结构的设计 好的性能出自好的设计 尽可能添加数据完整约束(非空约束.默认值约束.CHECK约束.唯一约束.外键约束)等,这些约束的添加将有助于数据库关系引擎分析执行计划. 尽可能小的字段类 ...
- Xposed 在android 6.0上报couldn't load class,找不到xposed_init中配置的入口类
经测试再android 4.4时是可以直接在android studio中运行debug签名包,在xposed中运行的,但是6.0的机器不好使.解决办法是在运行时使用release版并签名 apply ...
- 学习Makefile
1> 编译一个文件2> 编译多个文件3> 编译多个目录下的文件4> inclue makefile5> 使用规则1>target:depend[tab]cmddep ...
- 继承 & 多态 & 封装
什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 class Par ...
- Android 跨进程数据共享
Android 开发过程中,基于功能隔离.进程安全.进程保活等等考虑,我们经常需要为应用划分进程,然后不得不面临跨进程通信和跨进程共享数据的挑战. 跨进程通信 相对来说,跨进程通信比较简单,常用的方式 ...
- .Net Core知识点
1:const,readonly,和get访问器,三者都可在自己的生命域里赋值,但是编译器也是可以在构造函数里进行初始化赋值的 2:Debugger.IsAttached 属性 http://msdn ...
- principal(括号匹配+多组查询)
题目传送门: 把所有括号相匹配的段直接预处理出来就行了 #include <bits/stdc++.h> using namespace std; #define ll long long ...
- Netflix是怎样运行的(极度简化版)— 每次点击播放按钮背后的复杂东西
Netflix是怎样运行的(极度简化版)- 每次点击播放按钮背后的复杂东西 本文摘译自 How Netflix works: the (hugely simplified) complex stuff ...
- 跨平台技术实践案例: 用 reactxp 重写墨刀的移动端
Authors: Gao Cong, Perry Poon Illustrators: Shena Bian April 20, 2019 重新编写,又一次,我们又一次重新编写了移动端应用和移动端 ...
- 接口自动化框架(java)--1.项目概述
项目github地址: https://github.com/tianchiTester/API_AutoFramework 这套框架的报告是自己封装的 1.测试基类TestBase: 接口请求的te ...