最近做一些特征检测方面的东西,用的opencv自带的一些算法surf++knn+ransac等,进行指定区域的识别和扣取。然而,对这个检测算子的理解一致不太深入。于是的于是呢,参考了《计算机视觉:算法与应用》后,决定对这个方向了解一下。第一个自然是前人最经典的杰作:moravec corner;
moravec corner 首先提取了8个以45°为步长的局部差方之和,然后在8个中选取最小的一个作为当前的特征值,具有一定程度上的旋转不变性。然会对这个特征值进行阈值判断,提取出角点。8个模板可以采用3*3 5*5 或者7*7;这里采用5*5的方法进行测试。
代码稍后奉上(只实现了大概流程,代码没有经过优化)
#pragma once
#include"opencv2/opencv.hpp"
#include
class CMoravecCorner
{
private:
int winsize;
int threshold;
std::vector corners;
public:
CMoravecCorner(void);
~CMoravecCorner(void);
void set_thresold(int threshold)
{
this->threshold =threshold;
}
std::vector corner_detect(const cv::Mat img, int winsize=5)
{
//转换为灰度图
cv::Mat src;
cv::cvtColor(img,src,cv::COLOR_RGB2GRAY );
int censize=winsize/2;
for(int x=censize+1;x<(src.rows-censize-1);x++)
{
for(int y=censize+1;y<(src.cols-censize-1);y++)
{
//检测8个方向的特征(1,0),(1,1),(0,1)(-1,1),(-1,0),(-1,-1),(0,-1),(1,-1);
float ssd[8]={0,0,0,0};
//(1,0)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[0]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x+1+win_leng,y+win_heig)),2);
}
}
//(1,1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[1]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x+1+win_leng,y+1+win_heig)),2);
}
}
//(0,1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[2]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x+win_leng,y+1+win_heig)),2);
}
}
//(-1,1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[3]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x-1+win_leng,y+1+win_heig)),2);
}
}
//(-1,0)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[4]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x-1+win_leng,y+win_heig)),2);
}
}
//(-1,-1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[5]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x-1+win_leng,y+win_heig-1)),2);
}
}
//(0,-1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[6]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x+win_leng,y+win_heig-1)),2);
}
}
//(1,-1)方向特征
for(int win_leng=-censize;win_leng<=censize;win_leng++)
{
for (int win_heig=-censize;win_heig<=censize;win_heig++)
{
ssd[7]+=pow((src.at(x+win_leng,y+win_heig)-src.at(x+1+win_leng,y+win_heig-1)),2);
}
}
//提取最小特征
float minvalue=ssd[0];
for(int i=0;i<8;i++)
{
minvalue=minvaluethreshold)
{
corners.push_back(cv::Point(y,x));
}
/*else continue;*/
}
}
std::cout<::const_iterator it=corners.begin ();
for(;it!=corners.end();it++)
{
cv::circle(src,*it,3,cv::Scalar(255,0,0),2);
}
//cv::imshow("temp",src); //显示结果
}
};