标签:
不管是在识别,配准等应用中,提取图像的特征都是很关键的一环,提取特征是先找出图像的关键点(如角点,边缘点等),然后用描述子来描述这些点,最后整幅图像就可以表示成一个特征向量,特征向量就可以利用在后续识别中。
这个流程在matlab,opencv中都有相应的函数来实现,matlab封装性好,比较简单,只要输入图像和参数,调用函数就能够得到特征,而opencv就稍微复杂点,我们先通过opencv的c++程序来了解这个过程(资料比较好找点),接着通过阅读opencv4android文档来了解提供的API,最后实现在Android找关键点并画图。
图像配准程序包括1.定义存储关键点和关键点描绘子的数据结构。2.定义要提取的特征,分别对两幅图像进行关键点检测。3.计算关键点的特征描述子。4.计算匹配点数并显示。
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/nonfree/features2d.hpp> #include <opencv2/legacy/legacy.hpp> using namespace cv; int main() { Mat image1=imread("../b1.png"); Mat image2=imread("../b2.png"); // 检测surf特征点 vector<KeyPoint> keypoints1,keypoints2; SurfFeatureDetector detector(400); detector.detect(image1, keypoints1); detector.detect(image2, keypoints2); // 描述surf特征点 SurfDescriptorExtractor surfDesc; Mat descriptros1,descriptros2; surfDesc.compute(image1,keypoints1,descriptros1); surfDesc.compute(image2,keypoints2,descriptros2); // 计算匹配点数 BruteForceMatcher<L2<float>>matcher; vector<DMatch> matches; matcher.match(descriptros1,descriptros2,matches); std::nth_element(matches.begin(),matches.begin()+24,matches.end()); matches.erase(matches.begin()+25,matches.end()); // 画出匹配图 Mat imageMatches; drawMatches(image1,keypoints1,image2,keypoints2,matches, imageMatches,Scalar(255,0,0)); namedWindow("image2"); imshow("image2",image2); waitKey(); return 0; }
首先了解OpenCV java 特征提取的API和相应的数据结构。有关特征提取的API是存在包Package org.opencv.features2d中,主要包含以下几个类
计算特征点的特征描述子的抽象类。
主要使用两个methods:
创建特征描述子
Usage :public static DescriptorExtractor create(int extractorType)
ExtractorType:
· "SIFT" -- "SIFT"
· "SURF" -- "SURF"
· "BRIEF" -- "BriefDescriptorExtractor"
· "BRISK" -- "BRISK"
· "ORB" -- "ORB"
· "FREAK" -- "FREAK"
Example:
DescriptorExtractor descriptor=DescriptorExtractor.create(DescriptorExtractor.SIFT);
提取特征描述子
Usage:public void compute(java.util.List<Mat> images,
java.util.List<MatOfKeyPoint> keypoints,
java.util.List<Mat> descriptors)
public void compute(Mat image,
MatOfKeyPoint keypoints,
Mat descriptors)
image – 输入的图像.
keypoints – 输入的关键点,由FeatureDetector得到。
descriptors – 计算出来的特征描述子
Example:descriptor.compute(mRgba, keypoint, mask);
用来提取二维图像特征点的类
主要是两个Methods
Usage :public static FeatureDetector create(int detectorType)
DetectorType:
"FAST" -- "FastFeatureDetector"
"STAR" -- "StarFeatureDetector"
"SIFT" -- "SIFT" (nonfree module)
"SURF" -- "SURF" (nonfree module)
"ORB" -- "ORB"
"BRISK" -- "BRISK"
"MSER" -- "MSER"
"GFTT" -- "GoodFeaturesToTrackDetector"
"HARRIS" -- "GoodFeaturesToTrackDetector" with Harris detector enabled
"Dense" -- "DenseFeatureDetector"
"SimpleBlob" -- "SimpleBlobDetector"
Example:FeatureDetector detector = FeatureDetector.create(FeatureDetector.MSER);
Usage:
public void detect(java.util.List<Mat> images,
java.util.List<MatOfKeyPoint> keypoints,
java.util.List<Mat> masks)
public void detect(Mat image,
MatOfKeyPoint keypoints,
Mat mask)
public void detect(Mat image,
MatOfKeyPoint keypoints,)
image –输入图像.
keypoints – 检测得到的关键点
mask – 模板,指定要取关键点度的位置. It must be a 8-bit integer matrix with non-zero values in the region of interest.
采用detect检测得到关键点的数据结构
包括:一些构造函数和相应的域,构造函数不介绍,介绍对应的有哪些域。
angle
public float angle
计算特征点的方向.
class_id
public int class_id
物体的标签,可以用来分类关键点属于哪个类。
octave
public int octave
关键点使在金字塔的哪一层被提取的.
pt
public Point pt
关键点的坐标
response
public float response
响应,对应于哪个关键点的位置。.
size
public float size
有用关键点的邻接区域的半径。
同前面的特征提取,需要create和match
public static DescriptorMatcher create(int matcherType)
采用默认参数创建一个特征描述子匹配
matcherType:模式匹配的方式,算法
static int BRUTEFORCE
static int BRUTEFORCE_HAMMING
static int BRUTEFORCE_HAMMINGLUT
static int BRUTEFORCE_L1
static int BRUTEFORCE_SL2
static int FLANNBASED
match
public void match(Mat queryDescriptors,
Mat trainDescriptors,
MatOfDMatch matches)
Finds the best match for each descriptor from a query set.
给定查询集合中的每个特征描述子,寻找 最佳匹配
Parameters:
queryDescriptors -特征描述子查询集.
trainDescriptors - 待训练(模板)的特征描述子集. 这个集没被加载到类的对象中.
matches –匹配点数. 匹配点数的大小小于待查询的特征描述子的个数。
knnMatch
public void knnMatch(Mat queryDescriptors,
Mat trainDescriptors,
java.util.List<MatOfDMatch> matches,
int k,
Mat mask,
boolean compactResult)
给定查询集合中的每个特征描述子,寻找 k个最佳匹配.
radiusMatch
public void radiusMatch(Mat queryDescriptors,
java.util.List<MatOfDMatch> matches,
float maxDistance)
对于每一个查询特征描述子, 在特定距离范围内寻找特征描述子.
保存匹配特征的数据结构
float distance
两个特征向量之间的欧氏距离,越小表明匹配度越高。
int imgIdx
训练图像的索引(若有多个)
int queryIdx
此匹配对应的查询图像的特征描述子索引
int trainIdx
此匹配对应的训练(模板)图像的特征描述子索引
来自http://blog.csdn.net/masibuaa/article/details/8998601
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/nonfree/features2d.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace cv; using namespace std; int main() { initModule_nonfree();//初始化模块,使用SIFT或SURF时用到 Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );//创建SIFT特征检测器 Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SIFT" );//创建特征向量生成器 Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器 if( detector.empty() || descriptor_extractor.empty() ) cout<<"fail to create detector!"; //读入图像 Mat img1 = imread("desk.jpg"); Mat img2 = imread("desk_glue.jpg"); //特征点检测 double t = getTickCount();//当前滴答数 vector<KeyPoint> keypoints1,keypoints2; detector->detect( img1, keypoints1 );//检测img1中的SIFT特征点,存储到keypoints1中 detector->detect( img2, keypoints2 ); cout<<"图像1特征点个数:"<<keypoints1.size()<<endl; cout<<"图像2特征点个数:"<<keypoints2.size()<<endl; //根据特征点计算特征描述子矩阵,即特征向量矩阵 Mat descriptors1,descriptors2; descriptor_extractor->compute( img1, keypoints1, descriptors1 ); descriptor_extractor->compute( img2, keypoints2, descriptors2 ); t = ((double)getTickCount() - t)/getTickFrequency(); cout<<"SIFT算法用时:"<<t<<"秒"<<endl; cout<<"图像1特征描述矩阵大小:"<<descriptors1.size() <<",特征向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl; cout<<"图像2特征描述矩阵大小:"<<descriptors2.size() <<",特征向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl; //画出特征点 Mat img_keypoints1,img_keypoints2; drawKeypoints(img1,keypoints1,img_keypoints1,Scalar::all(-1),0); drawKeypoints(img2,keypoints2,img_keypoints2,Scalar::all(-1),0); //imshow("Src1",img_keypoints1); //imshow("Src2",img_keypoints2); //特征匹配 vector<DMatch> matches;//匹配结果 descriptor_matcher->match( descriptors1, descriptors2, matches );//匹配两个图像的特征矩阵 cout<<"Match个数:"<<matches.size()<<endl; //计算匹配结果中距离的最大和最小值 //距离是指两个特征向量间的欧式距离,表明两个特征的差异,值越小表明两个特征点越接近 double max_dist = 0; double min_dist = 100; for(int i=0; i<matches.size(); i++) { double dist = matches[i].distance; if(dist < min_dist) min_dist = dist; if(dist > max_dist) max_dist = dist; } cout<<"最大距离:"<<max_dist<<endl; cout<<"最小距离:"<<min_dist<<endl; //筛选出较好的匹配点 vector<DMatch> goodMatches; for(int i=0; i<matches.size(); i++) { if(matches[i].distance < 0.31 * max_dist) { goodMatches.push_back(matches[i]); } } cout<<"goodMatch个数:"<<goodMatches.size()<<endl; //画出匹配结果 Mat img_matches; //红色连接的是匹配的特征点对,绿色是未匹配的特征点 drawMatches(img1,keypoints1,img2,keypoints2,goodMatches,img_matches, Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2); imshow("MatchSIFT",img_matches); waitKey(0); return 0; }
待更新
Android学习九---OpenCV4android org.opencv.feature2d
标签:
原文地址:http://www.cnblogs.com/dawnminghuang/p/4219871.html