欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

32运动与跟踪-亚像素级角点检测

程序员文章站 2024-01-16 22:55:58
...

32运动与跟踪-亚像素级角点检测

如果我们进行图像处理的目的不是提取用于识别的特征点而是进行几何测量,则通常需要更高的精度,而函数 cvGoodFeaturesToTrack()只能提供简单的像素的坐标值,就是说,我们有时候会需要实数坐标值而不是整数坐标值。

图像测量常用的领域为三维重建、摄像机标定、推向拼接以及在卫星图像中查找特定的信号,如一栋建筑的精确位置。亚像素级角点的位置在摄像机标定、跟踪并重建摄像机的轨迹或者重建被跟踪目标的三维结构时是一个基本的测量值。


相关函数的接口:

C++: void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria);  
C: void cvFindCornerSubPix(const CvArr* image, CvPoint2D32f* corners, int count, CvSize win, CvSize zero_zone, CvTermCriteria criteria);  

函数参数

函数参数说明如下:

image:输入图像

corners:输入角点的初始坐标以及精准化后的坐标用于输出。

winSize:搜索窗口边长的一半,例如如果winSize=Size(5,5),则一个大小(5*2+1*(5*2+1)=11*11为的搜索窗口将被使用。

zeroZone:搜索区域中间的dead region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。
criteria:角点精准化迭代过程的终止条件。也就是当迭代次数超过criteria.maxCount,或者角点位置变化小于criteria.epsilon时,停止迭代过程。

实例代码:

#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  
#include <iostream>  
#include <stdio.h>  
#include <stdlib.h>  
using namespace cv;
using namespace std;

/// 全局变量  
Mat src, srcGray;
int maxCorners = 10;    //角点个数的最大值   
int maxCornersThresh = 20;  //角点个数最大值的上限(滑动条范围0-20)   
const char* detectWindow = "detection";
const char* refineWindow = "refinement";

/// 角点精准化函数声明  
void doCornerRefinement(int, void*);

int main(int argc, char** argv)
{
    /// 载入图像并灰度化   
    src = imread("building_original.tif", 1);
    cvtColor(src, srcGray, CV_BGR2GRAY);

    /// 创建显示窗口以及滑动条    
    namedWindow(detectWindow, 0);
    createTrackbar("max  num:", detectWindow, &maxCorners, maxCornersThresh, doCornerRefinement);
    imshow(detectWindow, src);

    doCornerRefinement(0, 0);


    waitKey(0);
    return(0);
}

/// 使用Shi-Tomasi方法检测角点,再对角点位置进行精准化  
void doCornerRefinement(int, void*)
{
    if (maxCorners < 1)
        maxCorners = 1;

    /// Shi-Tomasi的参数设置  
    vector<Point2f> corners;
    double qualityLevel = 0.01;
    double minDistance = 10;
    int blockSize = 3;
    bool useHarrisDetector = false;   //不使用Harris检测算法  
    double k = 0.04;

    /// 深度拷贝原图像用于绘制角点  
    Mat detectSrcCopy = src.clone();
    Mat refineSrcCopy = src.clone();

    /// 应用Shi-Tomasi角点检测算法   
    goodFeaturesToTrack(srcGray,
        corners,
        maxCorners,
        qualityLevel,
        minDistance,
        Mat(),   //未选择感兴趣区域   
        blockSize,
        useHarrisDetector,
        k);

    /// 当maxCorners的值较小时,以下两个值基本是一样的;    
    /// 当maxCorners的值较大时,实际检测到的角点数目有可能小于maxCorners,以下两个值不一样。    
    cout << "*  detected corners : " << corners.size() << endl;
    cout << "** max corners: " << maxCorners << endl;

    /// 1--显示角点检测结果  
    int r = 3;
    cout << "-- Before refinement: " << endl;
    for (int i = 0; i < corners.size(); i++)
    {
        // 标示出角点  
        circle(detectSrcCopy, corners[i], r, Scalar(255, 0, 0), 2, 8, 0);
        // 输出角点坐标  
        cout << "  [" << i << "]  (" << corners[i].x << "," << corners[i].y << ")" << endl;
    }
    namedWindow(detectWindow, 0);
    imshow(detectWindow, detectSrcCopy);

    /// 角点位置精准化参数  
    Size winSize = Size(5, 5);
    Size zeroZone = Size(-1, -1);
    TermCriteria criteria = TermCriteria(
        CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,
        40, //maxCount=40  
        0.001);  //epsilon=0.001  
                 /// 计算精准化后的角点位置  
    cornerSubPix(srcGray, corners, winSize, zeroZone, criteria);

    /// 2--显示精准化后的角点  
    cout << "-- After refinement: " << endl;
    for (int i = 0; i < corners.size(); i++)
    {
        // 标示出角点  
        circle(refineSrcCopy, corners[i], r, Scalar(255, 0, 0), 2, 8, 0);
        // 输出角点坐标  
        cout << " [" << i << "]  (" << corners[i].x << "," << corners[i].y << ")" << endl;
    }
    namedWindow(refineWindow, 0);
    imshow(refineWindow, refineSrcCopy);

    cout << endl;
}

最终的结果如下:
32运动与跟踪-亚像素级角点检测