美文网首页ocr
python调用c++ so库· pybind11(二)

python调用c++ so库· pybind11(二)

作者: 夕一啊 | 来源:发表于2019-12-19 20:19 被阅读0次

    简单介绍看(一)

    计算iou复杂例子

    pybind主要是用在把python的array传给c++,变成c++可以处理的类型
    这里计算交集并集用到了clipper库,
    iou.cpp

    #include "pybind11/pybind11.h"
    #include "pybind11/numpy.h"
    #include "pybind11/stl.h"
    #include "pybind11/stl_bind.h"
    
    #include "clipper/clipper.hpp"
    
    namespace py = pybind11;
    namespace cl = ClipperLib;
    
    
    namespace iou{
    
        using Polygon = cl::Path; //其实是两层的vector,
    
        float paths_area(const ClipperLib::Paths &ps) {
            float area = 0;
            for (auto &&p: ps)
                area += cl::Area(p);
            return area;
        }
    
        // clipper 库计算iou
        float poly_iou(const Polygon &a, const Polygon &b) {
            cl::Clipper clpr;
            clpr.AddPath(a, cl::ptSubject, true);
            clpr.AddPath(b, cl::ptClip, true);
    
            cl::Paths inter, uni;
            clpr.Execute(cl::ctIntersection, inter, cl::pftEvenOdd);
            clpr.Execute(cl::ctUnion, uni, cl::pftEvenOdd);
    
            auto inter_area = paths_area(inter);
            auto uni_area = paths_area(uni);
            float tmp = 0.01;
            return std::abs(inter_area) / std::max(std::abs(uni_area), tmp);
        }
    
        //其实是两层的vector,所以直接push,把多边形的点都加进去
        Polygon get_poly(const float *data, size_t n){
            using cInt = cl::cInt;
            Polygon a{ {cInt(data[0]), cInt(data[1])}};
            std::vector<std::vector<cInt>> ret;
            for (size_t i = 2; i < n;) {
                a.emplace_back(cInt(data[i]), cInt(data[i+1]));
                i += 2;
            }
            return a;
        }
      
        // 接收python数据类型,转换为c++数据类型,用指针来访问数组
        float iou(
        py::array_t<float, py::array::c_style> poly_one,
        py::array_t<float, py::array::c_style> poly_two)
        {
            auto poly_one_c = poly_one.request();
            auto poly_two_c = poly_two.request();
            auto line_count = poly_one_c.shape[0];
            auto cont_coutn = poly_two_c.shape[0];
    
            auto ptr_one = static_cast<float *>(poly_one_c.ptr);
            auto ptr_two = static_cast<float *>(poly_two_c.ptr);
            auto a = get_poly(ptr_one, poly_one_c.shape[0]);
            auto b = get_poly(ptr_two, poly_two_c.shape[0]);
    
            return poly_iou(a, b);
        }
    }
    
    
    PYBIND11_MODULE(iou, m){
        m.def("iou_cpp", &iou::iou, " re-implementation pse algorithm(cpp)", py::arg("poly_one"), py::arg("poly_two"));
    }
    

    编译so

    g++ -o iou.so -I include  -std=c++11 -O3 -I/opt/conda/include/python3.6m -I/opt/conda/include/python3.6m  -Wno-unused-result -Wsign-compare -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -O3 -ffunction-sections -pipe  -fdebug-prefix-map=/tmp/build/80754af9/python_1564510748219/work=/usr/local/src/conda/python-3.6.9 -fdebug-prefix-map=/opt/conda=/usr/local/src/conda-prefix -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -flto -DNDEBUG -fwrapv -O3 -Wall -L/opt/conda/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/opt/conda/lib -lpython3.6m -lpthread -ldl  -lutil -lrt -lm  -Xlinker -export-dynamic iou.cpp include/clipper/clipper.cpp --shared -f
    

    对比python和刚写的c++库

    import numpy as np
    from iou import iou_cpp
    from shapely.geometry import Polygon
    import time
    
    def cpp_iou():
        time0 = time.time()
        poly_one = np.array([10,10,30,10,30,30,20,30,10,30]).astype(np.float32)
        poly_two = np.array([20,20,40,20,40,40,20,40]).astype(np.float32)
        print("iou:", iou_cpp(poly_one, poly_two))
        print("cpp cost:%.5f ms"%((time.time() - time0) * 1000))
    
    def py_iou():
        time0 = time.time()
        poly_one = np.array([[10,10],[30,10],[30,30],[10,30]]).astype(np.float32)
        poly_two = np.array([[20,20],[40,20],[40,40],[20,40]]).astype(np.float32)
        poly_one = Polygon(poly_one)
        poly_two = Polygon(poly_two)
        print("iou:", poly_one.intersection(poly_two).area / poly_one.union(poly_two).area)
        print("py  cost:%.5f ms"%((time.time() - time0) * 1000))
    
    
    if __name__ == "__main__":
    
        print("\nfisrt time:")
        cpp_iou()
        py_iou()
        print("\nsecond time:")
        cpp_iou()
        py_iou()
    

    结果,c++写的比python shapely.geometry 快很多

    fisrt time:
    iou: 0.1428571492433548
    cpp cost:0.36979 ms
    iou: 0.14285714285714285
    py  cost:1.79982 ms
    
    second time:
    iou: 0.1428571492433548
    cpp cost:0.14234 ms
    iou: 0.14285714285714285
    py  cost:0.78845 ms
    
    

    相关文章

      网友评论

        本文标题:python调用c++ so库· pybind11(二)

        本文链接:https://www.haomeiwen.com/subject/hcevnctx.html