OpenCV目标跟踪(一)-寻找角点

来源:互联网 发布:软件项目阶段性报告 编辑:程序博客网 时间:2024/06/02 02:12

这两天在看OpenCV中的跟踪与运动这一块,跟踪和运动是一个很大的课题,里面的涉及的内容有很多,按着自己的学习进度上,简要的做个总结。
在我们处理一段视频而非某张静止的图片时,我们往往会去关注画面中的一个或者几个物体。对运动的物体的关注,我们处理的方式往往不是将整个物体都作为关注对象,而是选取几个独特的特征点去跟踪,这样我们就引出了角点的概念。
(1)角点
角点在运动与跟踪的研究中,就是说可以拿来作为跟踪的特征点都被称为角点。通俗直观的解释就是,一类含有足够信息且能从当前帧和下一帧中都能提取出来的点。
(2)角点的具体描述
a.一阶导数的局部最大所对应的像素点;
b.两条及两条以上边缘的交点;
c.图像中梯度值和梯度方向的变化速率都很高的点;
d.角点处的一阶导数最大,二阶导数为0,指示物体边缘变化不连续的方向。
(3)Harris角点检测算法简述
Harris角点检测算子是依据自相关函数给出的,得出了矩阵M,矩阵M中的特征值是自相关函数的一阶曲率,如果一阶曲率都很高的话,那么就可以认为这个是特征点。
下面给出图来直观的解释下:
这里写图片描述
图(a)是窗口在图像的平滑区域滑动,窗口在各个方向上没有变化,图(b)窗口在边缘方向上没有变化,图(c)窗口在各个方向上有变化,此时即为角点。

Harris角点的检测,相对于一幅图像来看,主要和自相关函数的曲率特性有关。自相关函数描述了局部图像灰度的变化程度,主要可以表示为:
这里写图片描述
上式中,E是窗口平移产生的图像灰度变化,也即是自相关函数,w是窗口,I是图像灰度。对上式进行展开即有:
这里写图片描述
其中
这里写图片描述
而对于小的偏移:
这里写图片描述
其中即有:
这里写图片描述
为了更好的降低噪声,采用高斯窗口进行图像降噪,高斯窗口函数即为:
这里写图片描述
这样E就可以通过矩阵的形式表现出来:
这里写图片描述
其中:
这里写图片描述
为了避免求解M特征值(M特征值和自相关函数的极值曲率有关),定义:
这里写图片描述
给出角点的响应函数为:
这里写图片描述
上式中R的值越大,越有可能是角点。

以上的思想是Harris提出的响应函数,后来Shi和Tomasi发现,若两个特征值的较小的一个大于最小阈值,则会得到强角点。
后来又有学者提出了亚像素角点的概念,通俗的来说就是以一个角点作为初始点进行不停的迭代,直到满足预先设置的迭代阈值条件,具体的大家感兴趣的话可以参阅相关文献。

在OpenCV中,给出了一个这样的函数cvGoodFeaturesToTrack(),采用的即是Shi和Tomasi给出的算法,即先计算出二阶导数,再计算特征值,小特征值大于最小阈值,找出角点。

void cvGoodFeaturesToTrack(    const CvArr*  image,//输入的图像,须为8位或32位单通道图像    CvArr* eigImage,    CvArr* tempImage,//这两个参数都是和输入图像相同的32位单通道图像    CvPoint2D32f* corners,//为函数的输出,得到的是个角点数组    int* corner_count,//表示可以返回的最大角点数目,程序结束后返回角点数目    double quality_level,//这个参数常用值为0.1或者0.01    double min_distance,//保证角点的距离不能小于此参数值    const CvArr* mask=NULL,//选择整幅图像    int block_size=3;//计算导数的自相关矩阵时指定点的邻域    int use_harris=0;//此参数值非0时,用Harris角点定义,为0时则用Shi-Tomasi定义    double k=0.4;//用于设置Hessian自相关矩阵即对Hessian行列式的相对权重的权重系数,这里可以回看上文的公式   );

下面给出这个程序的完整示例:

#include<iostream>#include<opencv2/opencv.hpp>using namespace std;#define MAX_CORNERS 100int main(){    int cornersCount = MAX_CORNERS;    CvPoint2D32f corners[MAX_CORNERS];    IplImage *srcImage = 0, *grayImage = 0, *corners1 = 0, *corners2 = 0;    int i;    CvScalar color = CV_RGB(255, 0, 0);    char *filename = "3.jpg";    cvNamedWindow("image", 1);    srcImage = cvLoadImage(filename, 1);    grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);    cvCvtColor(srcImage, grayImage, CV_BGR2GRAY);//转换为灰度图    corners1 = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_32F, 1);    corners2 = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_32F, 1);//先创立两个图像,在函数中药包含这两个参数    cvGoodFeaturesToTrack(grayImage, corners1, corners2, corners, &cornersCount, 0.05, 30, 0, 3, 0, 0.4);//调用OpenCV函数    cout << "num corners found: " << cornersCount << endl;    if (cornersCount > 0)    {        for (i = 0; i < cornersCount; ++i)        {            cvCircle(srcImage, cvPoint((int)(corners[i].x), (int)(corners[i].y)),2,color,2,CV_AA,0);        }    }//将认为是角点的画出来    cvShowImage("image", srcImage);    cvSaveImage("imagedst.png", srcImage);    cvReleaseImage(&srcImage);    cvReleaseImage(&grayImage);    cvReleaseImage(&corners1);    cvReleaseImage(&corners2);    cvWaitKey(0);    return 0;}

运行结果如图:
这里写图片描述

大家从上面可以看得出来,角点已经基本检测出来,但似乎依旧不是特别理想,大家可以尝试着修改下函数cvGoodFeaturesToTrack()中的参数值,运行后观察角点的检测效果。

0 0
原创粉丝点击