opencv角点检测android,计算机视觉 OpenCV Android | 特征检测与匹配之角点检测——Harris角点检测与Shi-Tomasi角点检测...

本文要点总结(俩算法的联系与区别)

Harris角点检测与Shi-Tomasi角点检测都是经典的角点特征提取算法,

但两者在API的使用上有出入(详见文中代码或GitHub项目);

Harris角点检测的API,返回/输出的是一个与输入图像大小一致的Mat对象,

这个Mat对象的每一个坐标(i,j)都是对应输入图像对应坐标(i,j)的像素的响应值R,

要先将这个Mat对象归一化,

再循环每一个Mat数据元素,一 一 跟自己设置的阈值进行比较,

合格的再认为是角点并提取出来,

进行绘制和保存;

与Harris角点输出不同,shi-tomasi简单多了,

直接输出一个包含若干个(具体个数通过API形参设置)角点坐标的角点数组,(其数据类型是MatOfPoint)

省略了很多步骤;

遍历这个角点数组,

绘制出每个角点即可。

引子

前面两章笔记(图像操作、基本特征检测)

主要讲述了OpenCV中图像处理模块的主要知识与API使用;

本章的笔记记录OpenCV中另外一个重要模块——feature2d模块,

该模块的主要功能是检测图像的特征,

并根据特征进行对象匹配;

首先,关于图像的特征,

简单地说,特征就是边缘、角点、纹理等。

本章会笔记特征提取、检测与匹配相关的知识与API,

包括角点特征检测、特征点检测、特征描述子提取,

以及根据特征描述子去匹配、寻找特征对象。

本章知识会涉及较多的数学知识与公式,

我们可以阅读一些与特征提取相关的数学知识,

比如导数与微分、多项式与高斯公式曲线拟合,三角函数,矩阵的特征值与特征向量的简单计算等基础数学知识,

以更好地掌握本章知识以及各个API参数意义与用法。

0 角点的定义与作用

基本特征检测一章中,学习了关于边缘检测的知识,

在图像边缘中,有一些特殊的像素点值得我们特别关注,

那就是图像边缘的角点,

这些角点更能反映出图像中对象的整体特征,

基于角点周围的像素块生成特征描述子可以更好地表述图像特征数据。

本文首先笔记如何提取图像的角点特征。

1 Harris角点检测

关于角点特征提取最经典的算法之一就是Harris角点检测。

Harris角点检测的基本原理是对图像求导,对每个像素点生成二阶梯度图像,

只是在卷积核使用的时候需要使用高斯核,

得到图像X与Y方向的二阶矩,

基于它们就可以得到如下Hessian矩阵:

ea2ba8c007b7

求得最大两个特征值 λ1 与 λ2,可以得到如下 角点响应值R:

ea2ba8c007b7

其中,系数K常见的取值范围为0.02~0.04。

每个像素点有自己的一个响应值R,

也即有自己的一对特征值 λ1 与 λ2;

全局像素则有多个R值;

根据M计算可以得到特征值 λ1、λ2,它们的值与角点的关系如下图:

ea2ba8c007b7

Harris角点检测的API:

cornerHarris(Mat src, Mat dst, int blockSize, int ksize, double k)

src:单通道的8位或者浮点数图像,用灰度图像;

dst:输出的每个像素点的响应值,是CV_32F类型,大小与输入图像一致。

blockSize:根据特征值与特征向量计算矩阵M的大小,常见取值为2。

ksize Sobel:算子梯度计算,常见取值为3。

k:系数大小,取值范围为0.02~0.04。

使用Harris角点检测函数计算得到图像角点的演示代码如下:

private void harrisCornerDemo(Mat src, Mat dst) {

// 定义阈值T//初始化各种Mat对象

int threshold = 100;

Mat gray = new Mat();

Mat response = new Mat();

Mat response_norm = new Mat();

// 角点检测

Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);//转灰度!!!!!!

Imgproc.cornerHarris(gray, response, 2, 3, 0.04);

Core.normalize(response, response_norm, 0, 255, Core.NORM_MINMAX, CvType.CV_32F);//归一化

// 绘制角点

dst.create(src.size(), src.type());

src.copyTo(dst);

float[] data = new float[1];//!!!!!!!!!!

for(int j=0; j

{

for(int i=0; i

{

response_norm.get(j, i, data);

if((int)data[0] > 100)

{

Imgproc.circle(dst, new Point(i, j), 5, new Scalar(0, 0, 255),

2, 8, 0);

Log.i("Harris Corner", "find corner point……");

}

}

}

gray.release();

response.release();

}

response_norm归一化后的响应值Mat对象

data[0]是某个响应值;

>100认为其是一个较大的响应值,

响应值大于指定阈值T(这里是100),则对应的像素点被认为是角点;

float[] data = new float[1] //在这里,可能有人有疑问, 数组长度只有 1

get()方法,第三个参数要求是数组,

get多个像素时,传入一个多元素空数组,常规理解操作;

但当只要get一个像素,则需创建一个只有一个元素的数组!而非变量!

这种接口设计思想,

一个方法(如get())接口即可实现包含一到多个数据元素的形式参数的传入;

而没必要去准备/重载两个方法——

一个用来接收包含单个数据元素的变量型形参,

另一个用来接收包含多个数据元素的数组型形参;没必要这样了;

即无论是负责接收数据的形参是包含 单个数据元素 还是 多个数据元素 ,一律按 数组型形参 处理,把数据形参位定义成数组类型,接口统一设计,一套代码,一个接口即可,省时省力!

上述程序首先把彩色RGB图像转换为单通道灰度图像,

然后使用Harris角点检测函数完成各个像素点上角点响应值的计算,

最后使用阈值过滤绘制那些响应值R比较大的像素点(角点)。

注意,阈值T与绘制检测得到的角点数目相关,

T值越大,被过滤的响应像素点越多,留下来的就越可能是角点,反之亦然。

本章完整代码在文末GitHub里边的Feature2dMainActivity.java文件中,后续对此不再说明。

2 Shi-Tomasi角点检测

还有一种经常使用的角点检测方法称为Shi-Tomasi角点检测,

其与Harris角点检测类似,这种方法同样是基于梯度图像发展而来的,

它是1994年由两位作者Jianbo Shi与Carlo Tomasi一起提出来的,

他们当时所发表的论文名为<>,

这也是为什么在OpenCV中使用同名函数来表示Shi-Tomasi角点检测的原因。

Shi-Tomasi角点检测与Harris角点检测唯一(指的是方法逻辑,不包括API,API的输出还不同) 不同的地方在于计算角点响应R值时使用的是如下方法:

ea2ba8c007b7

如果R大于指定阈值T,则对应的像素点被认为是角点;

假设λ1、λ2为坐标,

则对角点的描述就是当λ1、λ2都大于阈值T=λmin的右上角时,

角点响应值满足要求的区域,

如下图:

ea2ba8c007b7

相关的API如下:

goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, boolean useHarrisDetector, double k)

image:表示输入图像、类型为单通道的8位或浮点数,用灰度图像;

corners:输出得到角点数组,注意数据类型;

maxCorners:表示获取前N个最强响应R值的角点。

qualityLevel:其取值范围为0~1,这里取它与最大R值相乘,得到的值作为阈值T,低于它的都要被丢弃,

假设Rmax=1500,qualityLevel=0.01,则阈值T=15,小于15的角点都会被丢弃。

每个像素点有自己的一个响应值R,去全局像素最大的R为Rmax;

minDistance:最终返回的角点之间的最小距离,小于这个距离则的角点被丢弃。

mask:默认全部为零。

blockSize:计算矩阵M时需要的,常取值为3。

useHarrisDetector:是否使用Harris角点检测,true表示使用,若为false则使用Shi-Tomasi角点检测。

k:当使用Harris角点检测的时候才使用。

实现shi-tomasi角点检测的demo:

private void shiTomasicornerDemo(Mat src, Mat dst) {

// 变量定义

double k = 0.04;

int blockSize = 3;

double qualityLevel= 0.01;

boolean useHarrisCorner = false;

// 角点检测

Mat gray = new Mat();

Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);

MatOfPoint corners = new MatOfPoint();

Imgproc.goodFeaturesToTrack(gray, corners, 100, qualityLevel, 10, new Mat(), blockSize, useHarrisCorner, k);

// 绘制角点

dst.create(src.size(), src.type());

src.copyTo(dst);

Point[] points = corners.toArray();

for(int i=0; i

Imgproc.circle(dst, points[i], 5, new Scalar(0, 0, 255), 2, 8, 0);

}

gray.release();

}

完整的代码可参考GitHub项目。

参考材料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shi-Tomasi角点检测算法是一种经典的角点检测算法,它可以在图像中找到具有最大角度的角点。在OpenCV中,可以使用cv.goodFeaturesToTrack()函数进行Shi-Tomasi角点检测。 函数原型: ``` cv.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners[, mask[, blockSize[, useHarrisDetector[, k]]]]]) ``` 参数说明: - image:输入图像,必须是单通道8位或32位浮点型图像。 - maxCorners:检测到的最大角点数。 - qualityLevel:角点的最小质量水平,范围为0到1,表示角点的最小可接受质量。 - minDistance:角点之间的最小欧几里得距离。 - corners:输出角点的坐标。 - mask:用于限制检测区域的掩码图像。 - blockSize:计算图像梯度的邻域大小。 - useHarrisDetector:如果为true,则使用Harris角点检测算法。 - k:Harris角点检测算法的自由参数。 示例代码: ```python import cv2 as cv import numpy as np img = cv.imread('test.jpg') gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) corners = cv.goodFeaturesToTrack(gray, 100, 0.01, 10) corners = np.int0(corners) for corner in corners: x, y = corner.ravel() cv.circle(img, (x, y), 3, (0, 0, 255), -1) cv.imshow('img', img) cv.waitKey(0) cv.destroyAllWindows() ``` 效果如下图所示: ![shi-tomasi角点检测示例](https://img-blog.csdn.net/20180313173704656?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ29vZGllX2Jsb2c=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/75)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值