本文介绍了学习opencv图像检测的知识
主要有FAST与HARRIS,图像的匹配与测距
代码部分只展示FAST,HARRIS,图像的匹配
文章开头,借学长照片一用
背景知识:
一、FAST
在FAST特质点的检测是根据角点来判断的,什么是角点?“如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点”,通俗的讲是在这一点的灰度值与其他地方有很大的区别,我们就是通过这样的点去判断。
一般情况下我们会检测周围16个点(半径为3的膨胀)是否与该点有很大的区别来判断该点是否是角点,如图:
但是为了效率,我们通常只比较4个点,同时循环也是从i=3开始的(下面代码会有介绍)
实验证明,比较9个点是最有效率的。
二、HARRIS
对于HARRIS特质点检测而言,检测的对象是“方块”,同样如果这个“方块”左右移动灰度值改变非常大,那么这就是你找的点。如图:
)
R=det(M)-k*(trace(M)^2)
详情代码:
一、FAST
//判断两点灰度值的差距大小
bool isdif(uchar a, uchar b)
{
if (abs(a - b)<30)
{
return false;
}
else
{
return true;
}
}
VideoCapture cap(0);
while (true)
{
Mat frame;
cap >> frame;
/*
fast
*/
Mat frame_rgb;
frame.copyTo(frame_rgb);
//FAST是对灰度图检测的
cvtColor(frame, frame, CV_64FC1);
//cout<<frame.at<uchar>(0,0);
//FAST 角点检测
int pos[4][2];
//初始化FAST检测的四个位置
pos[0][0] = 0;
pos[0][1] = -3;
pos[1][0] = 3;
pos[1][1] = 0;
pos[2][0] = 0;
pos[2][1] = 3;
pos[3][0] = -3;
pos[3][1] = 0;
//由于检测角点是用圆来判断,所以i从3开始循环
for (int i = 3; i<frame.rows - 3; i++)
{
for (int j = 3; j<frame.cols - 3; j++)
{
int num = 0;
uchar cen = frame.at<uchar>(i, j);
for (int k = 0; k<4; k++)
{
//
uchar temp = frame.at<uchar>(i + pos[k][0], j + pos[k][1]);
//如果cen与temp差距很大,就加入其中,num是代表4个位置检查比较相差比较大的位置数量
if (isdif(cen, temp))
{
num++;
}
}
//如果num是1 3 4,表示该点是角点,画出该点
if ((num == 1) || (num == 3) || (num == 4))
{
//画圆
circle(frame_rgb, cvPoint(j, i), 2, CV_RGB(255, 0, 0), 2);
}
}
}
二、HARRIS
for (int i = 1; i < frame.rows - 1; i++)
{
for (int j = 1; j < frame.cols - 1; j++)
{
double IX, IY;
//求导
IX = frame.at<uchar>(i, j - 1) - frame.at<uchar>(i, j + 1);
IY = frame.at<uchar>(i - 1, j) - frame.at<uchar>(i + 1, j);
double R = IX*IX*IY*IY - 0.1*(IX*IX + IY*IY);
//R=x*x*y*y-k*(x*x-y*y),原理是一个矩阵的值
//k越大抑制越大
cout << R << endl;
if (R>10000)
{
circle(frame_rgb, cvPoint(j, i), 1, CV_RGB(255, 0, 0));
//CV_RGB(255,0,0)代表最红的颜色,红色 绿色 蓝色
}
}
}
三、API调用HARRIS
Mat con;
Mat cornerStrength;
Mat frame_gray=frame.clone();
cornerHarris(frame_gray, cornerStrength, 2, 3, 0.1);
Mat harrisCorner;
//进行二值化
threshold(cornerStrength, harrisCorner, 0.000001, 255, THRESH_BINARY);
imshow("角点检测后的二值效果图", harrisCorner);
//二值化增强图片显示效果,将阈值设置成0或者255
imshow("【原灰度图】", frame);
imshow("【二值化HARRIS图】", frame_rgb);
waitKey(10);
总结:
自从入了opencv的坑,我发现自己的数学功底十分欠缺,之前学的线性代数,高数都是一些小儿科的东西,如果要想学好opencv,数学是非常关键的。虽千万人吾往矣!
ps:
图像的测距我没有贴出代码块。以上都是我自己的学习体会以及自己的理解,如果想要更加了解以上内容,请参考一下博客:
FAST特征点检测
http://blog.csdn.net/yang_xian521/article/details/7411438
HARRIS角点估计
http://blog.csdn.net/crzy_sparrow/article/details/7391511
HARRIS的API调用
http://blog.csdn.net/poem_qianmo/article/details/29356187
代码文件及ppt