前面提到的SURF与SIFT特征检测器与描述子,
其实都是OpenCV扩展模块xfeature2d
中的内容,
而在OpenCV本身包含的feature2d模块中也包含了几个非常有用的特征检测器与描述子,
其所支持的特征点检测器(FeatureDetector)
如下:
其中,3、4本来是SIFT与SURF的,但在OpenCV3.x中,它们已经被移到扩展模块中了。
如果使用OpenCV官方编译好的OpenCV4Android 3.x版本的SDK,
则当声明与使用这两个类型的时候,它会告诉你不支持
。
feature2d
支持的特征点检测器
还支持以下的描述子类型:
这里其实还有1与2分别是SIFT与SURF, 但其已经被移到扩展模块了,所以如果声明使用会抛出不支持的错误提示。
在feature2d模块中同时具有特征点检测与描述子功能的方法有ORB、BRISK、AKAZE。
下面我们简单介绍一下这三种特征提取方法。
OpenCV4Android中创建ORB检测器与描述子的代码:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
OpenCV4Android中创建ORB检测器与描述子的代码如下:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.BRISK);
DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.BRISK);
AKAZE算法的原理本身比较复杂,笔者所读的书中亦无详细解说, 感兴趣的小伙伴阅读相关论文去深入了解。
在OpenCV4Android中创建AKAZE特征检测器与描述子的代码如下:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.AKAZE);
DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.AKAZE);
基于feature2d中的检测器对象实现对象关键点检测的演示代码:
FeatureDetector detector = null;
if(type == 1) {
detector = FeatureDetector.create(FeatureDetector.ORB);
} else if(type == 2) {
detector = FeatureDetector.create(FeatureDetector.BRISK);
} else if(type == 3) {
detector = FeatureDetector.create(FeatureDetector.FAST);
} else if(type == 4){
detector = FeatureDetector.create(FeatureDetector.AKAZE);
} else {detector = FeatureDetector.create(FeatureDetector.HARRIS);
}
MatOfKeyPoint keyPoints = new MatOfKeyPoint();
detector.detect(src, keyPoints);
Features2d.drawKeypoints(src, keyPoints, dst);
以AKAZE为例,在feature2d中实现图像特征检测、描述子计算、特征匹配的演示代码如下:
private void descriptorDemo(Mat src, Mat dst) {
String boxFile = fileUri.getPath().replaceAll("box_in_scene", "box");
Mat boxImage = Imgcodecs.imread(boxFile);
FeatureDetector detector = FeatureDetector.create(FeatureDetector.AKAZE);
DescriptorExtractor descriptorExtractor = DescriptorExtractor.create
(DescriptorExtractor.AKAZE);
// 关键点检测
MatOfKeyPoint keyPoints_box = new MatOfKeyPoint();
MatOfKeyPoint keyPoints_scene = new MatOfKeyPoint();
detector.detect(boxImage, keyPoints_box);
detector.detect(src, keyPoints_scene);
// 描述子生成
Mat descriptor_box = new Mat();
Mat descriptor_scene = new Mat();
descriptorExtractor.compute(boxImage, keyPoints_box, descriptor_box);
descriptorExtractor.compute(src, keyPoints_scene, descriptor_scene);
// 特征匹配
MatOfDMatch matches = new MatOfDMatch();
DescriptorMatcher descriptorMatcher = DescriptorMatcher.create
(DescriptorMatcher.BRUTEFORCE_HAMMING);
descriptorMatcher.match(descriptor_box, descriptor_scene, matches);
Features2d.drawMatches(boxImage, keyPoints_box, src, keyPoints_scene, matches, dst);
// 释放内存
keyPoints_box.release();
keyPoints_scene.release();
descriptor_box.release();
descriptor_scene.release();
matches.release();
}
如果是作者本人的GitHub项目的话, 运行时,首先需要把drawable中的box.png与box_in_scene图像放到SD卡上的指定目录下, 在演示程序运行之后选择box_in_scene图像即可。 当然我们也可以更改一下代码,使用别的图片进行测试或者把图片放在项目中进行测试。