當前位置:
首頁 > 知識 > OpenCV3中ORB特徵提取演算法的實現與分析

OpenCV3中ORB特徵提取演算法的實現與分析

ORB特徵提取演算法是一種通過檢測提取待測圖片與模板圖片中的灰度特徵,實現模板圖片與待測圖片匹配的一種特徵提取演算法。相比於模板匹配matchTemple,ORB更集中於圖像的灰度細節,速度也更快。

ORB的全稱是ORiented Brief,也被稱為rBrief。該演算法在ICCV2011上由《ORB: an efficient alternative to SIFT or SURF》一文提出,並很快被收錄於OpenCV2版本中。在OpenCV3.0中曾被放到OpenCV-contrib第三方擴展包中(當時可能因為版權),後來又被集成回OpenCV3本體中。ORB在OpenCV中分為CPU、GPU(CUDA)兩種實現途徑,ORB本身是為無法用GPU加速的CPU運算處理器設計的,網上能查到的CPU版ORB演算法程序也佔大多數,此文也暫時先介紹CPU版的ORB程序。

相比於先前的surf、sift特徵提取演算法,ORB的運行效率都更快(超過10倍),且具有surf和sift都不具備的旋轉不變性。ORB本身不具備尺度不變性,但OpenCV里通過圖像金字塔使ORB演算法仍能檢測出發生了一定程度尺度變換的目標,並通過透視變換等方法校正目標。(詳情可參考毛星雲的《OpenCV3編程入門》)

博主此文中的ORB代碼在OpenCV3.1與3.3上都進行了實現,運行環境為Ubuntu14.04與16.04,代碼複製後修改待測圖像、模板圖像的文件名,在編譯中加入OpenCV的動態庫,可直接使用。

博主用的模板是

OpenCV3中ORB特徵提取演算法的實現與分析

解析度為170*209,命名為model.jpg;

用的目標檢測圖片是

OpenCV3中ORB特徵提取演算法的實現與分析

解析度為1200*668,命名為ORB_test.jpg;

在IDE中創建C++項目,用C++11的規則運行如下程序:

[cpp] view plain copy

  1. #include <iostream>
  2. #include <signal.h>
  3. #include <vector>
  4. #include <opencv2/opencv.hpp>
  5. using

    namespace

    cv;
  6. using

    namespace

    std;
  7. int

    main()
  8. {
  9. Mat img_1 = imread("model.jpg");
  10. Mat img_2 = imread("ORB_test.jpg");
  11. if

    (!img_1.data || !img_2.data)
  12. {
  13. cout << "error reading images " << endl;
  14. return

    -1;
  15. }
  16. vector<Point2f> recognized;
  17. vector<Point2f> scene;
  18. recognized.resize(500);
  19. scene.resize(500);
  20. Mat d_srcL, d_srcR;
  21. Mat img_matches, des_L, des_R;
  22. //ORB演算法的目標必須是灰度圖像
  23. cvtColor(img_1, d_srcL, COLOR_BGR2GRAY);//CPU版的ORB演算法源碼中自帶對輸入圖像灰度化,此步可省略
  24. cvtColor(img_2, d_srcR, COLOR_BGR2GRAY);
  25. Ptr<ORB> d_orb = ORB::create();
  26. Mat d_descriptorsL, d_descriptorsR, d_descriptorsL_32F, d_descriptorsR_32F;
  27. vector<KeyPoint> keyPoints_1, keyPoints_2;
  28. //設置關鍵點間的匹配方式為NORM_L2,更建議使用 FLANNBASED = 1, BRUTEFORCE = 2, BRUTEFORCE_L1 = 3, BRUTEFORCE_HAMMING = 4, BRUTEFORCE_HAMMINGLUT = 5, BRUTEFORCE_SL2 = 6
  29. Ptr<DescriptorMatcher> d_matcher = DescriptorMatcher::create(NORM_L2);
  30. std::vector<DMatch> matches;//普通匹配
  31. std::vector<DMatch> good_matches;//通過keyPoint之間距離篩選匹配度高的匹配結果
  32. d_orb -> detectAndCompute(d_srcL, Mat(), keyPoints_1, d_descriptorsL);
  33. d_orb -> detectAndCompute(d_srcR, Mat(), keyPoints_2, d_descriptorsR);
  34. d_matcher -> match(d_descriptorsL, d_descriptorsR, matches);
  35. int

    sz = matches.size();
  36. double

    max_dist = 0;

    double

    min_dist = 100;
  37. for

    (

    int

    i = 0; i < sz; i++)
  38. {
  39. double

    dist = matches[i].distance;

  40. if

    (dist < min_dist) min_dist = dist;
  41. if

    (dist > max_dist) max_dist = dist;
  42. }
  43. cout << "
    -- Max dist : " << max_dist << endl;
  44. cout << "
    -- Min dist : " << min_dist << endl;
  45. for

    (

    int

    i = 0; i < sz; i++)
  46. {
  47. if

    (matches[i].distance < 0.6*max_dist)
  48. {
  49. good_matches.push_back(matches[i]);
  50. }
  51. }
  52. //提取良好匹配結果中在待測圖片上的點集,確定匹配的大概位置
  53. for

    (

    size_t

    i = 0; i < good_matches.size(); ++i)
  54. {
  55. scene.push_back(keyPoints_2[ good_matches[i].trainIdx ].pt);
  56. }
  57. for

    (unsigned

    int

    j = 0; j < scene.size(); j++)
  58. cv::circle(img_2, scene[j], 2, cv::Scalar(0, 255, 0), 2);
  59. //畫出普通匹配結果
  60. Mat ShowMatches;
  61. drawMatches(img_1,keyPoints_1,img_2,keyPoints_2,matches,ShowMatches);
  62. imshow("matches", ShowMatches);
  63. imwrite("matches.png", ShowMatches);
  64. //畫出良好匹配結果
  65. Mat ShowGoodMatches;
  66. drawMatches(img_1,keyPoints_1,img_2,keyPoints_2,good_matches,ShowGoodMatches);
  67. imshow("good_matches", ShowGoodMatches);
  68. imwrite("good_matches.png", ShowGoodMatches);
  69. //畫出良好匹配結果中在待測圖片上的點集
  70. imshow("MatchPoints_in_img_2", img_2);
  71. imwrite("MatchPoints_in_img_2.png", img_2);
  72. waitKey(0);
  73. return

    0;

  74. }

程序運行結果如下:

1、顯示模板、待測圖間keyPoint之間的最大、最小距離,用於篩選良好的匹配結果:

OpenCV3中ORB特徵提取演算法的實現與分析

2、顯示良好的匹配結果,程序中設置模板與待測圖間keyPoint的距離在最大keyPoint距離的0.6倍以內。從顯示的圖像上可見,drawMatches將模板與待測圖連接並放在一張圖上,keyPoint一般是選擇圖形的邊緣、灰度變化較大的地方,這也意味著圖像中若圖形邊緣較多,灰度變化的地方較多,則關鍵點也較多,匹配的效果也更好:

OpenCV3中ORB特徵提取演算法的實現與分析

博主也試過將待測圖片換成攝像頭輸入(將OpenCV讀入的攝像頭圖像>>img_2,核心程序用for循環即可),在drawMatches的顯示中效果極佳,模板與攝像頭圖像中的目標匹配良好,說明ORB演算法完全可用於攝像頭的目標檢測。但根據博主的測試經驗,將ORB用於攝像頭目標檢測需注意兩點:

(1)模板的灰度變換一定要較多且明顯(否則在複雜環境下匹配集中度不高),建議使用相同攝像頭在相同解析度下獲取模板(OpenCV獲取模板的程序博主下幾篇文章中將給出);

(2)一旦攝像頭全黑,程序無法匹配到任何圖像時ORB程序將崩潰,可能需要用try或守護進程等解決方法(一定時間間隔檢查程序是否在運行,不在運行則啟動程序)。

3、顯示普通匹配結果,以示良好匹配與普通匹配間的差別。該匹配結果和match選擇方法也有很大關係,在合適的match方法作用下,良好匹配結果的匹配線應儘可能相互平行,或呈扇形(和旋轉目標進行匹配):

OpenCV3中ORB特徵提取演算法的實現與分析

4、顯示良好匹配結果中在待測圖片上的點集,可見大多數在灰度變化較大、較密集的地方,匹配程度較高,但附近也存在誤差點。既然已將這些點集提取出,之後就可用概率統計分布的方式排除誤差,框出目標的大概位置。

OpenCV3中ORB特徵提取演算法的實現與分析

得到目標的大概位置後,一般要用OpenCV中的透視變換perspectiveTransform或warpPerspective來確定、框出物體的實際位置,確認其中心坐標。博主也在研究這一方面的內容,可能需要和matchTemple模板匹配結合,歡迎討論!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

為什麼 GitHub 上的開發者比 iOS 上的要更值錢?
windows離線狀態下源碼安裝Robotframework 環境及依賴包

TAG:程序員小新人學習 |