GPU ORB Extractor API#

This tutorial shows how to use GPU ORB Extractor library API. GPU ORB Extractor library provide stereo and mono support API.

Sample code - stereo mode#

Create file sample.cpp with following code:

#include "orb_extractor.h"
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
#include <fstream>
#include <memory>

constexpr uint32_t max_num_keypts_ = 2000;
constexpr int num_levels_ = 8;
constexpr int ini_fast_thr_ = 20;
constexpr int min_fast_thr_ = 7;
constexpr float scale_factor_ = 1.2f;

int main()
{
   std::vector<cv::Mat> stereo_images;
   stereo_images.resize(2); //left and right image
   stereo_images[0] = cv::imread("../../images/market.jpg", cv::IMREAD_GRAYSCALE);
   stereo_images[1] = cv::imread("../../images/market.jpg", cv::IMREAD_GRAYSCALE);
   std::vector<std::vector<cv::KeyPoint>> keypts;
   keypts.resize(2); //for left and right image keypoint
   std::vector<cv::Mat> stereo_descriptors;
   stereo_descriptors.resize(2);

   const cv::_InputArray in_image_array(stereo_images);
   const cv::_InputArray in_image_mask_array;
   const cv::_OutputArray descriptor_array(stereo_descriptors);

   std::vector<std::vector<float>> mask_rect;

   auto extractor = std::make_shared<orb_extractor>(max_num_keypts_, scale_factor_, num_levels_, ini_fast_thr_, min_fast_thr_, mask_rect);
   extractor->set_gpu_kernel_path("../../build");

   double total_host_time = 0.0;

   for (int i = 0; i < iterations; i++)
   {
       std::cout << "iteration " << i <<"/" << iterations << "\r";
       std::cout.flush();
       double host_start = getTimeStamp();

       extractor->extract(in_image_array, in_image_mask_array, keypts, descriptor_array);

       double host_end = getTimeStamp();
       double host_time_diff = (host_end - host_start)/(float)iterations;
       total_host_time += host_time_diff;
   }

   std::vector<cv::KeyPoint> left_keypts =  keypts.at(0);
   std::vector<cv::KeyPoint> right_keypts = keypts.at(1);
   //left image
   cv::Mat left_out (left_cv_image.rows, left_cv_image.cols, CV_8U);;
   cv::drawKeypoints(left_cv_image, left_keypts, left_out, cv::Scalar(255,0,0));
   cv::imshow("left_result", left_out);

   //right image
   cv::Mat right_out (right_cv_image.rows, right_cv_image.cols, CV_8U);;
   cv::drawKeypoints(right_cv_image, right_keypts, right_out, cv::Scalar(255,0,0));
   cv::imshow("right_result", right_out);
   cv::waitKey(0);
}

Stereo code explanation#

Configuration for the ORB extractor:

constexpr uint32_t max_num_keypts_ = 2000;
constexpr int num_levels_ = 8;
constexpr int ini_fast_thr_ = 20;
constexpr int min_fast_thr_ = 7;
constexpr float scale_factor_ = 1.2f;

Initialize the input and output parameters:

std::vector<cv::Mat> stereo_images;
stereo_images.resize(2);
stereo_images[0] = cv::imread("../../images/market.jpg", cv::IMREAD_GRAYSCALE);
stereo_images[1] = cv::imread("../../images/market.jpg", cv::IMREAD_GRAYSCALE);
std::vector<std::vector<cv::KeyPoint>> keypts;
keypts.resize(2); //for left and right image keypoint
std::vector<cv::Mat> stereo_descriptors;
stereo_descriptors.resize(2);

const cv::_InputArray in_image_array(stereo_images);
const cv::_InputArray in_image_mask_array;
const cv::_OutputArray descriptor_array(stereo_descriptors);

Create orb_extract object:

auto extractor = std::make_shared<orb_extractor>(max_num_keypts_, scale_factor_, num_levels_, ini_fast_thr_, min_fast_thr_, mask_rect)

Set gpu kernel path: Specific the path to GPU binaries such as gaussian_genx.bin, resize_genx.bin.

extractor->set_gpu_kernel_path("../../GPU_ORB_Library_Path");

Call orb extractor for stereo mode:

extract(in_image_array, in_image_mask_array, keypts, descriptor_array);

In stereo mode, all input and output parameter will be same as mono, except image vector, keypoints vector and descriptor vector need to double size.

Draw the keypoint on the image:

cv::Mat out (cv_image.rows, cv_image.cols, CV_8U);;
cv::drawKeypoints(cv_image, keypts, out, cv::Scalar(255,0,0));
cv::imshow("result", out);
cv::waitKey(0);

Sample code - mono mode#

Create file sample.cpp with following code:

#include "orb_extractor.h"
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
#include <fstream>
#include <memory>

constexpr uint32_t max_num_keypts_ = 2000;
constexpr int num_levels_ = 8;
constexpr int ini_fast_thr_ = 20;
constexpr int min_fast_thr_ = 7;
constexpr float scale_factor_ = 1.2f;

int main()
{
    cv::Mat cv_image = cv::imread("../../images/market.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<std::vector<cv::KeyPoint>> all_keypts;
    all_keypts.resize(1);
    cv::Mat descriptor;

    const cv::_InputArray in_image_array(cv_image);
    const cv::_InputArray in_image_mask_array;
    const cv::_OutputArray descriptor_array(descriptor);

    std::vector<std::vector<float>> mask_rect;

    auto extractor = std::make_shared<orb_extractor>(max_num_keypts_, scale_factor_, num_levels_, ini_fast_thr_, min_fast_thr_, mask_rect);
    extractor->set_gpu_kernel_path("../../build");

    extractor->extract(in_image_array, in_image_mask_array, all_keypts, descriptor_array);
    auto& keypts = all_keypts.at(0);
    cv::Mat out (cv_image.rows, cv_image.cols, CV_8U);;
    cv::drawKeypoints(cv_image, keypts, out, cv::Scalar(255,0,0));
    cv::imshow("result", out);
    cv::waitKey(0);
}

Mono code explanation#

Call to same API with mono mode:

extract(in_image_array, in_image_mask_array, keypts, descriptor_array);

In mono mode, all input and output parameter will be same as stereo. Only Image Mat vector, keypoints vector and Mat descriptor vector need to resize 1.

Compile and run the program#

cd sample
mkdir build
cd build
cmake ../
make -j

After compile the code, run the sample as following.

$ ./extract_feature

After executing, the input image will display keypoints in blue color dots.