gnebehay / CppMT

Other
313 stars 185 forks source link

Python + Matlab Wrapper #1

Open kornerc opened 9 years ago

kornerc commented 9 years ago

Hi Georg.

I'm planning to write a Python wrapper for this library. It would be nice if you could provide a nice c-api for your library. It's also straightforward for a Matlab wrapper.

The c-api may look similar to this

// cwrapper.h

#ifndef WRAPPER_H
#define WRAPPER_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#include <stdlib.h>

typedef void* cmt_Cmt;

cmt_Cmt cmt_new();
void cmt_del(cmt_Cmt cmt);
void cmt_initialize(cmt_Cmt cmt,
  unsigned char* im_gray, size_t rows, size_t cols,
  int rect_x, int rect_y, int rect_w, int rect_h);
// ...

#ifdef __cplusplus
}
#endif // __cplusplus

#endif /* WRAPPER_H */
// cwrapper.cpp
#include "cwrapper.h"

#include <opencv2/core/core.hpp>

#include "CMT.h"

using cmt::CMT;
using namespace cv;

cmt_Cmt cmt_new() {
    CMT* cmt = new CMT();
    return cmt;
}

void cmt_del(cmt_Cmt cmt) {
    CMT* cmt_cpp = static_cast<CMT*>(cmt);
    delete cmt_cpp;
}

void cmt_initialize(cmt_Cmt cmt,
  unsigned char* im_gray, size_t rows, size_t cols,
  int rect_x, int rect_y, int rect_w, int rect_h) {
    CMT* cmt_cpp = static_cast<CMT*>(cmt);

    Mat image = Mat(rows, cols, CV_8UC1, im_gray);
    Rect rect(rect_x, rect_y, rect_w, rect_h);

    cmt_cpp.initialize(image, rect);

    // ...
}

// ...

BR Clemens

kornerc commented 9 years ago

Here is a small example how I'm planning to program the bridge between Numpy (Python side) and OpenCV (C++ side)

# CMakeLists.txt
project(wrapper)

cmake_minimum_required(VERSION 2.6)

option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." ON)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

find_package(OpenCV REQUIRED)
link_directories(${OpenCV_LIB_DIR})

add_library(wrapper wrapper.cpp)
target_link_libraries(wrapper ${OpenCV_LIBS})
// wrapper.h
#ifndef WRAPPER_H
#define WRAPPER_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#include <stdlib.h>

void array_to_mat(unsigned char* data, size_t rows, size_t cols);

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // WRAPPER_H
// wrapper.cpp
#include "wrapper.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

void array_to_mat(unsigned char* data, size_t rows, size_t cols) {
    Mat image = Mat(rows, cols, CV_8UC1, data);
    namedWindow("Image", WINDOW_AUTOSIZE);
    imshow("Image", image);
    waitKey(0);
}
# pywrapper.py

import numpy as np
import ctypes as ct
import cv2

_libwrapper = np.ctypeslib.load_library('libwrapper', '.')

_libwrapper.array_to_mat.argtypes = [np.ctypeslib.ndpointer(dtype=np.uint8),
        ct.c_size_t,
        ct.c_size_t]
_libwrapper.array_to_mat.restype = None

def array_to_mat(image):
    image = image.astype(np.uint8)
    shape = image.shape
    _libwrapper.array_to_mat(image, shape[0], shape[1])

if __name__ == '__main__':
    image = cv2.imread('test.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
    array_to_mat(image)
gnebehay commented 9 years ago

Initial version is here: 7099a01829b7c9b6e0564c47c87fa08a42c09c7d

soulslicer commented 8 years ago

good day, may I know the progress of your Python wrapper?

kornerc commented 8 years ago

There is a branch called wrapper with the python code. Just compile the library as usual and put pycmt.py to the binaries, that's it. The basic functions are wrapped, but it's not possible to change any parameters yet. My recommendation is to use the original python program CMT for now.

soulslicer commented 8 years ago

Yes, but the original python code doesn't seem to be as performant as CppCMT. That is, the tracking is not as robust on by datasets, with alot of outlier keypoints that seem to skew the ROI computed. I think some algorithm changes were probably implemented on CppMT

Also, I will try the Wrapper branch. Are there any changes in CppMT? I notice this branch is 6 months old. Can I grab pycmt, compile master branch then place the wrapper in the new one?

soulslicer commented 8 years ago

Can I request for some direction on how I may modify your CMakeLists.txt to build a single shared library called libcmt?

soulslicer commented 8 years ago

I used the following line to generate the static library file (in osx it creates libcmt.dylib) add_library(cmt STATIC CMT.cpp common.cpp gui.cpp Consensus.cpp Fusion.cpp Matcher.cpp Tracker.cpp fastcluster/fastcluster.cpp)

But when I use the pycmt.py, I get this error: Traceback (most recent call last): File "pycmt.py", line 8, in _libccmt.newCMT.argtypes = None File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/init.py", line 378, in getattr func = self.getitem(name) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/init.py", line 383, in getitem func = self._FuncPtr((name_or_ordinal, self))

kornerc commented 8 years ago

I'm sorry, but it's not possible to use the python-wrapper with the static libcmt library. It has to be a shared one. The wrapper uses ctypes for wrapping: ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.