使用pybind11 来实现python 调用c++

参考 https://blog.csdn.net/luolinll1212/article/details/106061943

1 c++ 实现
2 编写pybind11的代码
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"
#include "pybind11/stl.h"
#include "lsd.h"

namespace py = pybind11;
using namespace std;

struct lsd_result
{
    int x1;
    int y1;
    int x2;
    int y2;
    float line_len;
    float line_angle;

};


std::vector<std::vector<float>> line_detect(py::array_t<double> img_data, int img_w, int img_h, double scale = 0.8)
{
    std::vector<std::vector<float>> res = {};
    int n = 0;

    py::buffer_info buf1 = img_data.request();
    double *data = (double*)buf1.ptr;
    double *out = lsd_scale(&n, data, img_w, img_h, scale);
    if (n > 0) {
        //printf("%d line segments found:\n", n);
        for (int i = 0; i < n; i++)
        {
            /*for (int j = 0; j < 7; j++)
                    printf("%f ", out[7 * i + j]);
                printf("\n");*/

                // x1,y1,x2,y2,line_width,p,-log10(NFA)
            float p1_x = out[7 * i + 0];
            float p1_y = out[7 * i + 1];
            float p2_x = out[7 * i + 2];
            float p2_y = out[7 * i + 3];
            float line_len = out[7 * i + 4];
            float angle_p = out[7 * i + 5];
            float nfa = out[7 * i + 6];
            //float angle = atan((p2_y - p1_y) *1.0 / (p2_x - p1_x)) * 180. / 3.1415926;

            std::vector<float> _line = { p1_x,p1_y, p2_x,p2_y,line_len,angle_p };
            res.push_back(_line);
        }
    }
    /* free memory */
    free((void *)out);
    return res;
}

PYBIND11_MODULE(pybind11_lsd, m)  //
{
    m.doc() = "lsd(gray img, dtype=double, size=(WxH))";
    m.def("line_detect", &line_detect,
        py::arg("img"),
        py::arg("img_w"),
        py::arg("img_h"),
        py::arg("scale"),
        "line_detect(double* img_data, int img_w, int img_h, double scale=0.8)"); 

// 返回结构体
py::class_<lsd_result>(m, "lsd_result")
.def(py::init<>())
.def_readwrite("x1", &lsd_result::x1)
.def_readwrite("y1", &lsd_result::y1)
.def_readwrite("x2", &lsd_result::x2)
.def_readwrite("y2", &lsd_result::y2)
.def_readwrite("line_len", &lsd_result::line_len)
.def_readwrite("line_angle", &lsd_result::line_angle);
}

3 编写makefile
### 没有任何依赖库的makefile
CXX=/usr/bin/c++
STRIP=/usr/bin/strip
CXXFLAGS =-std=gnu++11 -O3 -shared -fPIC -Wall
#LDFLAGS=$(shell python3.7-config --cflags --ldflags --libs)
#LDFLAGS+=`pkg-config --cflags --libs opencv`

PYTHON_INCLUDE=-I/usr/include/python3.7m
PYTHON_LIB=-L/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu -L/usr/lib
PYTHON_LDFLAGS=-lcrypt -lpthread -ldl -lutil -lm -lpython3.7m

PYBIND11_INCLUDE=-I/home/xx/build/pybind11-2.10.0/include
CCFLAGS=$(PYTHON_INCLUDE) $(PYBIND11_INCLUDE)
LDFLAGS+=$(PYTHON_LIB) $(PYTHON_LDFLAGS)

CXX_SOURCES = $(wildcard ./src/*.cpp)
LIB_SO = pybind11_lsd_tmp.so
LIB_SO_STRIP = pybind11_lsd.so

$(LIB_SO): $(CXX_SOURCES)
@$(CXX) $(CXXFLAGS) $(CCFLAGS) -o $@ $(CXX_SOURCES) $(LDFLAGS)
$(STRIP) $(LIB_SO) -s -o $(LIB_SO_STRIP)
rm -rf $(LIB_SO)


.PHONY : clean
clean:
rm -rf $(LIB_SO) $(LIB_SO_STRIP)


### 依赖 opencv 的makefile
CXX=/usr/bin/c++
STRIP=/usr/bin/strip
CXXFLAGS =-std=gnu++11 -O3 -shared -fPIC -Wall
#LDFLAGS=$(shell python3.7-config --cflags --ldflags --libs)
#LDFLAGS+=`pkg-config --cflags --libs opencv`

PYTHON_INCLUDE=-I/usr/include/python3.7m
PYTHON_LIB=-L/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu -L/usr/lib
#PYTHON_INCLUDE=-I/home/sunny-dxs/anaconda3/envs/py37/include/python3.7m
#PYTHON_LIB=-L/home/sunny-dxs/anaconda3/envs/py37/lib -L/usr/lib
PYTHON_LDFLAGS=-lcrypt -lpthread -ldl -lutil -lm -lpython3.7m

OPENCV_INCLUDE=-I/usr/local/include -I/usr/local/include/opencv
OPENCV_LIB =-L/usr/local/lib
OPENCV_LDFLAGS=-lopencv_imgcodecs -lopencv_imgproc -lopencv_core

PYBIND11_INCLUDE=-I/home/xxx/build/pybind11-2.10.0/include

CCFLAGS = $(PYTHON_INCLUDE) $(PYBIND11_INCLUDE) $(OPENCV_INCLUDE)
LDFLAGS = $(OPENCV_LIB) $(PYTHON_LIB)
LDFLAGS += $(OPENCV_LDFLAGS)
LDFLAGS += $(PYTHON_LDFLAGS)

CXX_SOURCES = $(wildcard ./src/*.hh ./src/*.cpp ./src/pybind11_main.cpp)
LIB_SO = pybind11_lsd_tmp.so
LIB_SO_STRIP = pybind11_lsd.so

$(LIB_SO): $(CXX_SOURCES)
@$(CXX) $(CXXFLAGS) $(CCFLAGS) -o $@ $(CXX_SOURCES) $(LDFLAGS)
$(STRIP) $(LIB_SO) -s -o $(LIB_SO_STRIP)
rm -rf $(LIB_SO)


.PHONY : clean
clean:
rm -rf $(LIB_SO) $(LIB_SO_STRIP)

4 make 生成*.so

5 python调用

import pybind11_lsd

res = pybind11_lsd.line_detect(img=gray_double, img_w=w, img_h=h, scale=0.8)
res = np.asarray(res).reshape(-1, 6)
print(res)
for x1, y1, x2, y2, _size, _angle in res:
    if _size < 4: continue
    x1, y1, x2, y2 = list(map(int, [x1, y1, x2, y2]))
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) 

 

 

posted @ 2022-10-18 15:24  dangxusheng  阅读(336)  评论(0编辑  收藏  举报