Opencv3笔记33——亚像素级角点检测

1.概述

我们处理图像的目的不是提取用于识别的特征点而是进行几何测量,需要更高的精度。函数goodFeaturesToTrack()只能提供简单的像素坐标,但是有的时候实数坐标值。
亚像素级角点检测的位置在摄像机标定,跟踪并重建摄像机的轨迹,或者重建跟踪目标的三维结构时,是一个基本的测量值。
这里写图片描述

一个向量和与其正交的向量的点积为0.
其中(a)点p附近的图像时均匀的,其梯度为0。(b)边缘的梯度与沿边缘方向的q-p向量正交。在图中的两种情况下,p点梯度与q-p向量的点积均为0
我们假设起始角点q在实际亚像素角点的附近。检测所有的q-p向量。若点p位于一个均匀的区域,则点p处的梯度为0。若q-p向量的所有方向与边缘的方向一致,则此边缘上p点处的梯度与q-p向量正交,在这两种情况下,p点处的梯度与q-p向量的点积为0.我们可以在p点周围找到很多组梯度以及相关的向量q-p,其点集为0,然后通过求解方程组,求出亚像素级精度的位置。

Opencv为我们提供了cornerSubPix()函数,用于发现亚像素精度的角点位置

2.寻找亚像素角点:cornerSubPix()函数

cornerSubpix()函数用于寻找亚像素角点位置。

void cornerSubPiix(InputArray image, InputOutputArray corners,Size winSize, Size zeroZone, TermCriteria criteria)
  • 第二个参数:InputOutputArray类型的corners,提供输入角点的初始坐标和明确的输出坐标
  • 第三个参数:Size类型的winSize,搜索窗口的一半尺寸。若winSize = Size(5,5),表示使用(5*2+1) × × (5*2+1)即 11×11 11 × 11 大小的搜索窗口
  • 第四个参数:Size类型的zeroZone,表示死区的一半尺寸。死区为部队搜索区域内的中央位置做求和运算的区域,用来避免自相关矩阵出现的某些可能的奇异性。
  • 第五个参数:TermCriteria类型的criteria,求角点的迭代的终止条件。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//描述:定义一些辅助宏

#define WINDOW_NAME "【亚像素角点检测】"

//全局变量声明
Mat g_srcImage;
Mat g_grayImage;
int g_maxCornerNumber = 33;
int g_maxTrackbarNumber = 500;
RNG g_rng(12345);

//回调函数
void on_GoodFeaturesToTrack(int, void *)
{
    if (g_maxCornerNumber <= 1)
    {
        g_maxCornerNumber = 1;
    }
    //shi-tomasi算法
    vector<Point2f> corner;
    double qualityLevel = 0.01;     //角点检测可接收的最小特征
    double minDistance = 10;        //角点之间的最小的距离
    int blockSize = 3;              //计算导数自相关矩阵时指定的邻域范围
    double k = 0.04;                //权重系数
    Mat copy = g_srcImage.clone();
    //进行角点检测
    goodFeaturesToTrack(g_grayImage, corner, g_maxCornerNumber, qualityLevel, minDistance, Mat(), blockSize, false, k);
    //输出文字信息
    cout << ">此次检测到的角点数量为:" << corner.size() << endl;
    //绘制检测到的角点
    Size winSize = Size(5, 5);
    Size zeroZone = Size(-1, -1);
    TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);
    cornerSubPix(g_grayImage, corner, winSize, zeroZone, criteria);
    for (int i = 0; i < corner.size(); i++)
    {
        cout << "\t>>精度角点坐标[" << i << "](" << corner[i].x << "," << corner[i].y << ")" << endl;
    }
    int r = 4;
    for (unsigned int i = 0; i < corner.size(); i++)
    {
        circle(copy, corner[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0);
    }
    //显示更新窗口
    imshow(WINDOW_NAME, copy);
}
int main()
{
    //载入原始图像
    g_srcImage = imread("1.jpg", 1);
    cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);

    //创建窗口和滑动条
    namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
    createTrackbar("最大角点数:", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
    imshow(WINDOW_NAME, g_srcImage);
    on_GoodFeaturesToTrack(0,0);
    waitKey(0);
    return 0;
}

这里写图片描述
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值