Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exposing the LBP descriptors from OpenCV in Python

Tags:

c++

python

opencv

I want to be able to calculate the LBP discriptor in python using OpenCV. According to this I need to compile openCV again.

I changed the elbp() functions in opencv-2.4.6.1/modules/contrib/src/facerec.cpp, so they won't be statisc anymore. Now I have to declare them in an HFile (let's say i created elbp.hpp, or should I add this to an existing file?):

// This is a header file created to expose the elbp (evaluate LBP) functions

#include "opencv2/core/core.hpp"

namespace cv {

Mat elbp(InputArray src, int radius, int neighbors);
Mat elbp(InputArray src, OutputArray dst, int radius, int neighbors);
Mat spatial_histogram(InputArray _src, int numPatterns, int grid_x, int grid_y, bool /*normed*/);
};

In order to compile OpenCV I followed instructions here, and created the cv2.so shared object.

My question is, how to create python "wrappers" (if I'm using the right word) to be able to call the elbp() functions from python? I feel I am missing a crucial step here.

For example, the cv2.HogDescriptor() function exists in python, I want to similarly expose the LBP descriptor.

like image 765
eran Avatar asked Dec 25 '22 21:12

eran


2 Answers

So, it worked.

To make the function accessible: .

  1. I made the following change to facerec.cpp, from:

    static void elbp(InputArray src, OutputArray dst, int radius, int neighbors)
    {
    ...
    }    
    
    static Mat elbp(InputArray src, int radius, int neighbors) {
        Mat dst;
        elbp(src, dst, radius, neighbors);
        return dst;
    }
    
    static Mat spatial_histogram(InputArray _src, int numPatterns,
                             int grid_x, int grid_y, bool /*normed*/)
    {
    ...
    }
    

    to:

    void elbp(InputArray src, OutputArray dst, int radius, int neighbors)
    {
    ...
    }    
    
    Mat elbp(InputArray src, int radius, int neighbors) {
        Mat dst;
        elbp(src, dst, radius, neighbors);
        return dst;
    }
    
    Mat spatial_histogram(InputArray _src, int numPatterns,
                             int grid_x, int grid_y, bool /*normed*/)
    {
    ...
    }
    
  2. I added the following into /modules/contrib/include/opencv2/include/contrib.hpp under the cv namespace:

    CV_EXPORTS_W void elbp(InputArray src, OutputArray dst, int radius, int neighbors);
    
  3. I then creted a release folder in the opencv root.
  4. From within that folder, I ran:

    cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PYTHON_SUPPORT=ON -D WITH_TBB=ON -D BUILD_EXAMPLES=ON ..
    
  5. Next, I ran make
  6. take the cv2.so shared object created under /lib and put it where python looks for the packages. For me, it was /usr/local/lib/python2.7/dist-packages/
  7. run python

    from cv2 import spatial_histogram
    

Voila!

like image 89
eran Avatar answered Dec 28 '22 20:12

eran


This is actually the same problem, if not the same question, as how to call a dll in python - But you can use either ctypes or swig however since there is already a python interface into OpenCV your best bet is to take a look to see how the existing one is done.

It may also be worth taking a look at pyopencv which provides a Boost based interface.

Update:

To see how the current system does things take a look at CMakeLists.txt in opencv/modules/python and you will find that a number of generated headers are created by opencv/modules/python/src2/gen2.py - you will need to spend some time looking at these two files.

like image 30
Steve Barnes Avatar answered Dec 28 '22 21:12

Steve Barnes