1

I have written some optimized C++ code for FLANN Matching with SIFT features (OpenCV) that returns the number of good matches (int) found on two images. My code works well when I pass the two image paths (query and train images) as char* via ctypes. I am writing a wrapper class in Python to handle these functions. However, I want to pass the two arguments as image instances and not as char* or std::string, namely the objects that are results of cv2.imread(apath) in Python OpenCV bindings.

My .cpp source code:

//detectors.cpp
#include <stdio.h>
#include <iostream>
#include "string.h"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

///* (extern c) Get good matches using SIFT and FLANN Matcher * ///
extern "C" int get_matches_sift_flann(char* img1, char* img2)
{
  Mat img_1 = imread(img1, CV_LOAD_IMAGE_GRAYSCALE );
  Mat img_2 = imread(img2, CV_LOAD_IMAGE_GRAYSCALE );

  //-- Step 1: Detect the keypoints using SIFT Detector
  int minHessian = 400;
  SiftFeatureDetector detector( minHessian );
  std::vector<KeyPoint> keypoints_1, keypoints_2;
  detector.detect( img_1, keypoints_1 );
  detector.detect( img_2, keypoints_2 );
  //-- Step 2: Calculate descriptors (feature vectors)
  SiftDescriptorExtractor extractor;
  Mat descriptors_1, descriptors_2;
  extractor.compute( img_1, keypoints_1, descriptors_1 );
  extractor.compute( img_2, keypoints_2, descriptors_2 );
  //-- Step 3: Matching descriptor vectors using FLANN matcher
  FlannBasedMatcher matcher;
  std::vector< DMatch > matches;
  matcher.match( descriptors_1, descriptors_2, matches );
  double max_dist = 0; double min_dist = 100;
  //-- Quick calculation of max and min distances between keypoints
  for( int i = 0; i < descriptors_1.rows; i++ )
  { double dist = matches[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
  }
  //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
  //-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
  //-- small)
  //-- PS.- radiusMatch can also be used here.
  vector< DMatch > good_matches;
  for( int i = 0; i < descriptors_1.rows; i++ )
  { if( matches[i].distance <= max(2*min_dist, 0.02) )
    { good_matches.push_back( matches[i]); }
  }
  int n =  (int) good_matches.size();
  return n;
}

And my python wrapper.py module

#wrapper module for libdetectors.so

import os
import ctypes as c

libDETECTORS = c.cdll.LoadLibrary('./libdetectors.so')

class CExternalMatchesFunction:

    def __init__(self, c_func):
        self.c_func = c_func
        self.c_func.argtypes = [c.c_char_p, c.c_char_p]
        self.c_func.restype = c.c_int

    def __call__(self, train_img_filename, query_img_filename):
        r = self.c_func(c.c_char_p(train_img_filename), c.c_char_p(query_img_filename))
        return r

#initialize wrapped functions               
get_matches_sift_flann = CExternalMatchesFunction(libDETECTORS.get_matches_sift_flann)

All in all, I want to change CExternalMatchesFunction().c_func.argtypes to a list of image objects like these:

import cv2 
img1 = cv2.imread('foo.jpg')
img2 = cv2.imread('boo.jpg')

Thanks in advance

1
  • Is it acceptable to pass a pointer to an image, as opposed to passing the image data? That should be easier and faster I imagine. Commented Sep 4, 2014 at 12:23

1 Answer 1

1

SOLUTION: Return void* and cast it again to cpp object when passed

Sign up to request clarification or add additional context in comments.

1 Comment

Can you share exactly where you did this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.