图像形状上下文特征ShapeContexts
本文参考1.https://blog.csdn.net/app_12062011/article/details/53606191
2.https://blog.csdn.net/wl2002200/article/details/51076598
3.https://blog.csdn.net/chai*/article/details/76975086
1.原理(参考链接1、2)
形状上下文特征多用于形状匹配,目标识别。它采用一种基于形状轮廓的特征描述方法,其在对数极坐标系下利用直方图描述形状特征能够很好地反映轮廓上采样点的分布情况。
形状上下文指的是像素点邻域内的其它像素点的分布情况。
step1:对给定的一个图像,获得图像的轮廓,对轮廓边缘采集到一组离散的点集(共n个点)。
step2:计算形状上下文。以上边获得点集中任意一点作为参考点,将该点作为圆心、R为半径的区域内按对数距离间隔建立N个同心圆。将此区域沿圆周方向M等分,形成如图1所示的靶状模板。该点到其它各点的向量相对位置简化为模板上各扇区内的点分布数。这些点的统计分布直方图,成为该点的形状上下文。
采用对数距离分割可以使形状上下文描述子对邻近的采样点比远离点更敏感,能强化局部特征。轮廓不同点处的形状上下文是不同的,但相似轮廓的对应点处趋于有相似的形状上下文,如图2。
用上述方法,对n个点,每个点作为参考点,最终可以获得n个形状直方图。它描述了整个轮廓形状的特征。采样点越多, 形状表达越精细,计算量也会加大。
step3:计算代价矩阵C,并基于该矩阵进行点的匹配操作。最后结果越大表示越不相似,结果越小表示越相似。
2.优缺点(参考链接1)
优点:充分利用上下文信息,在非刚性物体匹配中,具有很好的鲁棒性。
缺点:对于有背景、噪声点过多的情况,匹配效果很不好。
3.使用opencv3.0计算形状上下文代码
在opencv3.0中封装了ShapeContextDistanceExtractor类(参考链接3、4),使用该类中的函数计算形状上下文只需要两步
1)计算两图像的轮廓点;
2)使用ShapeContextDistanceExtractor中的computeDistance就可以得到两轮廓上下文特征的距离。
#include "opencv2/shape.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <opencv2/core/utility.hpp>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
using namespace cv;
static vector<Point> simpleContour(const Mat& currentQuery)
{
vector<vector<Point> > _contoursQuery;
vector <Point> contoursQuery;
threshold(currentQuery, currentQuery, 0, 255, CV_THRESH_OTSU);
findContours(currentQuery, _contoursQuery, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (size_t border = 0; border<_contoursQuery.size(); border++)
{
for (size_t p = 0; p<_contoursQuery[border].size(); p++)
{
contoursQuery.push_back(_contoursQuery[border][p]);
}
}
return contoursQuery;
}
int main()
{
cv::Ptr <cv::ShapeContextDistanceExtractor> mysc = cv::createShapeContextDistanceExtractor();
Mat query = imread("1.png", 0);
vector<Point> contQuery = simpleContour(query);
Mat iiIm = imread("2.png", 0);
resize(iiIm, iiIm, Size(query.cols,query.rows));
vector<Point> contii = simpleContour(iiIm);
float dis = mysc->computeDistance(contQuery, contii);
cout<<"1-2-dis:" << dis << endl;
Mat iiIm1 = imread("3.png", 0);
resize(iiIm1, iiIm1, Size(query.cols, query.rows));
vector<Point> contii1 = simpleContour(iiIm1);
float dis1 = mysc->computeDistance(contQuery, contii1);
cout << "1-3-dis:" << dis1 << endl;
return 0;
}
由结果可知,相似的图像距离更近。
若文中有不妥或错误之处,还望指出!
上一篇: 已知椭圆长短轴半径a,b,matlab画椭圆(附椭圆公式)
下一篇: 【转】画stacked bar