Android学习九---OpenCV4android org.opencv.feature2d
不管是在识别,配准等应用中,提取图像的特征都是很关键的一环,提取特征是先找出图像的关键点(如角点,边缘点等),然后用描述子来描述这些点,最后整幅图像就可以表示成一个特征向量,特征向量就可以利用在后续识别中。
这个流程在matlab,opencv中都有相应的函数来实现,matlab封装性好,比较简单,只要输入图像和参数,调用函数就能够得到特征,而opencv就稍微复杂点,我们先通过opencv的c++程序来了解这个过程(资料比较好找点),接着通过阅读opencv4android文档来了解提供的API,最后实现在Android找关键点并画图。
一、OpenCV c++图像配准程序来了解
图像配准程序包括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下
首先了解OpenCV java 特征提取的API和相应的数据结构。有关特征提取的API是存在包Package org.opencv.features2d中,主要包含以下几个类
1.DescriptorExtractor
计算特征点的特征描述子的抽象类。
主要使用两个methods:
1.1 create
创建特征描述子
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);
1.2 compute
提取特征描述子
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);
2. FeatureDetector
用来提取二维图像特征点的类
主要是两个Methods
2.1 create
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);
2.2 detect
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.
3. KeyPoint
采用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
有用关键点的邻接区域的半径。
4. DescriptorMatcher
同前面的特征提取,需要create和match
4.1 create
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
4.2 Match
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)
对于每一个查询特征描述子, 在特定距离范围内寻找特征描述子.
5. DMatch
保存匹配特征的数据结构
float distance
两个特征向量之间的欧氏距离,越小表明匹配度越高。
int imgIdx
训练图像的索引(若有多个)
int queryIdx
此匹配对应的查询图像的特征描述子索引
int trainIdx
此匹配对应的训练(模板)图像的特征描述子索引
三、完整的C++匹配代码
来自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实现
待更新

Android学习九---OpenCV4android org.opencv.feature2d的更多相关文章
- Android学习九:屏幕自适应
android中不同手机分辨率适配问题 在项目开发的过程中,同一个布局对应不同的手机会显示出不同的效果.导致这个现象产生的原因是不同手机的分辨率不同.在android sdk提供的帮助文档中,我们可以 ...
- android学习九 对话框碎片
1.android的对话框是异步的,对话框创建后马上执行下面的代码.好处: a.通过实现对话框的回调方法反馈用户与对话框的交互. b.能够在代码中清楚对话框. 2.碎片对话框基 ...
- 九、Android学习第八天——广播机制与WIFI网络操作(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...
- Android学习——在Android中使用OpenCV的第一个程序
刚開始学习Android,因为之前比較熟悉OpenCV,于是就想先在Android上执行OpenCV试试 =============================================== ...
- Android学习七---Hello OpenCV samples
创建一个能够使用OpenCV JavaCameraView的应用程序来了解基于OpenCV java API 的应用程序的开发流程.有了Android的基础,在程序中需要修改的几个地方1.activi ...
- 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...
- 【转】 Pro Android学习笔记(九四):AsyncTask(3):ProgressDialog
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Progress Dialog小例子 我们 ...
- 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...
- 【转】 Pro Android学习笔记(九三):AsyncTask(2):小例子
目录(?)[-] 继承AsyncTask UI操作接口 使用AsyncTask 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn. ...
随机推荐
- 如何使用UltraISO将制作的ios文件挂载到虚拟机上面
选中要挂载的文件例如图中蓝色的部分移动到上面,然后点击文件中的保存按钮就可以了. 接下来设置虚拟机上的red hat6.3 记住一定要把红色部分选中,才能在虚拟机上看到 然后点击光盘就可以看到挂载的内 ...
- logback参考配置
logback配置 <?xml version="1.0" encoding="UTF-8"?> <configuration> < ...
- 设置EntityFramework中decimal类型数据精度
EF中默认的decimal数据精度为两位数,当我们数据库设置的精度大于2时,EF将只会保留到2为精度. e.g. 2.1999将会被保存为2.20 网上找到常见的方法为重写DbContext的OnMo ...
- MFC中CString转换成char数组的问题
由于结构体中用到联合体(联合体需要确定分配内存分配大小)或其它因素,需要用char数组来保存字符串,但是在MFC中一般都是用CString来存放字条串.关于它们之间的转换,在VS2008中有时会出现异 ...
- 【BZOJ】1687: [Usaco2005 Open]Navigating the City 城市交通(bfs)
http://www.lydsy.com/JudgeOnline/problem.php?id=1687 bfs后然后逆向找图即可.因为题目保证最短路唯一 #include <cstdio> ...
- java collection 类图
转载:http://visionsky.blog.51cto.com/733317/371809/
- DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016错误解决方法
这个错误是:表处于"装入暂挂"状态. 经多次尝试 总结方法: 1:reorg table <表>: 假如不好使 则下面方法 2,先前尝试装入(LOAD)此表失败.表的状 ...
- 关于spotlight for Windows和spotlight for oracle的使用
http://blog.csdn.net/luowangjun/article/details/4866084 http://konglx.iteye.com/blog/1873805
- 【转】Windows Dump文件获取
dump文件是进程的内存镜像.可以把程序的执行状态,即当时程序内存空间数据通过调试器保存到dump文件中. 1.利用WinDbg里的adplus来获取dump文件 Adplus.vbs 是一个Visu ...
- 笔记:C语言图形基本函数及实例五子棋游戏
初始化图形界面 int gdriver; int gmode; gdriver = DETECT; initgraph(&gdriver,&gmode,"" ); ...