使用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)