简单介绍看(一)
计算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
网友评论