計算機視覺 OpenCV Android | 特徵檢測與匹配 之 Feature2D中的檢測器與描述子
引言及特徵點監測器
前面提到的SURF與SIFT特徵檢測器與描述子
,
其實都是OpenCV擴充套件模組xfeature2d
中的內容,
而在OpenCV本身包含的feature2d模組中
也包含了幾個非常有用的特徵檢測器與描述子
,
其所支援的特徵點檢測器(FeatureDetector)
如下:
- FAST=1
- STAR=2
- ORB=5
- MSER=6
- GFTT=7
- HARRIS=8
- SIMPLEBLOB=9
- DENSE=10
- BRISK=11
- AKAZE=12
其中,3、4
本來是SIFT
與SURF
的,但在OpenCV3.x
中,它們已經被移到擴充套件模組
中了。
如果使用OpenCV官方編譯好的OpenCV4Android 3.x版本的SDK
,
則當宣告與使用這兩個型別的時候,它會告訴你不支援
。
描述子型別
feature2d
支援的特徵點檢測器
還支援以下的描述子型別
:
- DescriptorExtractor.ORB=3
- DescriptorExtractor.BRIEF=4
- DescriptorExtractor.BRISK=5
- DescriptorExtractor.FREAK=6
- DescriptorExtractor.AKAZE=7
這裡其實還有1與2
分別是SIFT與SURF
,
但其已經被移到擴充套件模組
了,所以如果宣告使用會丟擲不支援
的錯誤提示。
簡單介紹幾種特徵提取方法
在feature2d模組
中同時具有特徵點檢測與描述子功能的方法
有ORB、BRISK、AKAZE
。
下面我們簡單介紹一下這三種特徵提取方法
。
1.ORB檢測器與描述子
-
ORB(Oriented FAST and Rotated BRIEF)
是OpenCV實驗室於2011年開發出來的一種新的特徵提取演算法
,相比較於SIFT與SURF
,ORB的一大好處是
沒有專利限制
,可以
免費自由使用
,同時
具有旋轉不變性與尺度不變性
。
OpenCV4Android中建立ORB檢測器與描述子的程式碼:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
2.BRISK檢測器與描述子
-
BRISK(Binary Robust Invariant Scalable Keypoint)特徵檢測與描述子
是在2011年由幾位作者聯合提出的一種新的特徵提取演算法
,
OpenCV4Android中建立ORB檢測器與描述子的程式碼如下:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.BRISK); DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.BRISK);
3.AKAZE檢測器與描述子
-
AKAZE演算法是
SIFT演算法之後
,具有
尺度不變性
與旋轉不變性演算法領域
的再一次突破
,它是
KAZE特徵提取演算法
的加速版本
; -
其
演算法原理有別於前面提到的幾種方法
,其是通過
正則化PM方程與AOS(加性運算元分裂)方法
來求解非線性擴散
,從而
得到 尺度空間 的 每一層
; -
取樣的方法與
SIFT
類似,對每一層實現
候選點的定位與過濾
以實現關鍵點的提取
; -
然後再使用與
SURF
求解方向角度類似的方法實現旋轉不變性
特徵,最終生成
AKAZE描述子
。
AKAZE演算法的原理本身比較複雜,筆者所讀的書中亦無詳細解說,
感興趣的小夥伴閱讀相關論文去深入瞭解。
在OpenCV4Android中建立AKAZE特徵檢測器與描述子的程式碼如下:
FeatureDetector detector = FeatureDetector.create(FeatureDetector.AKAZE); DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.AKAZE);
4. OpenCV4Android中feature2d檢測器與描述子的使用
基於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影象即可。
當然我們也可以更改一下程式碼,使用別的圖片進行測試或者把圖片放在專案中進行測試。
參考材料
- 《OpenCV Android 開發實戰》(賈志剛 著)
- 關於《OpenCV Android 開發實戰》作者的GitHub專案
- 筆者基於作者GitHub維護的APP