【发布时间】:2014-01-21 05:28:06
【问题描述】:
我正在从事一个大型计算机视觉项目,我需要对来自多个摄像头的每一帧进行一些处理。它很重,我想提高速度。所以我想到了使用 boost python 在 c++ 中包装一个 python 函数。
这里是我想用 c++ 包装的函数:
def computeSumInboundingbox(self, cameraTable, integral):
for line in cameraTable:
minX, minY, maxX, maxY = line[2], line[3], line[4], line[5]
# sum of the pixel in the bounding box according to integral image
sumBox = integral[(minY,minX)] + integral[(maxY, maxX)] - integral[(maxY,minX)] - integral[(minY,maxX)]
# we scale the sumBox
if sumBox != 0:
self.bitmap[line[0],line[1]] = \
float(sumBox) / ((maxX - minX) * (maxY - minY))
此函数正在从 2D 列表 cameraTable(查找表)中读取一些坐标。该表已在我的课程初始化期间加载。 Integral 和 bitmap 是 2d numpy 数组。 我有很多坐标,所以每一帧都这样做有点慢。
然后我将函数包装在 c++ 中。
boost::python::numeric::array computeSumInboundingbox(boost::python::numeric::array integral, list cameraTable, boost::python::numeric::array bitmap)
{
list currCameraTable;
float sumBox;
for (int i = 0 ; i < len(cameraTable) ; i++)
{
int x = extract<float>(cameraTable[i][0]);
int y = extract<float>(cameraTable[i][1]);
float minX = extract<float>(cameraTable[i][2]);
float minY = extract<float>(cameraTable[i][3]);
float maxX = extract<float>(cameraTable[i][4]);
float maxY = extract<float>(cameraTable[i][5]);
// // sum of the pixel in the bounding box according of integral image
sumBox = extract<float>(integral[make_tuple(minY, minX)] + integral[make_tuple(maxY, maxX)] -
integral[make_tuple(maxY, minX)] - integral[make_tuple(minY, maxX)]);
// we scale the sumBox
if (sumBox != 0)
bitmap[make_tuple(y,x)] = sumBox / ((maxX - minX) * (maxY - minY));
}
return bitmap;
}
但是我的性能很差,一个 2000 帧的视频,运行时间多 45 秒!
然后我认为提取函数可能需要一段时间来处理,所以首先我将我的二维列表转换为 python 中的一维 std::vector(我并没有真正找到创建二维向量的方法)
boost::python::numeric::array computeSumInboundingbox(boost::python::numeric::array integral, std::vector<float> cameraTable, boost::python::numeric::array bitmap)
{
list currCameraTable;
float sumBox;
int x;
int y;
float minX, minY, maxX, maxY;
for (int i = 0 ; i < cameraTable.size() ; i+=6)
{
int x = cameraTable[i];
int y = cameraTable[i+1];
float minX = cameraTable[i+2];
float minY = cameraTable[i+3];
float maxX = cameraTable[i+4];
float maxY = cameraTable[i+5];
// // sum of the pixel in the bounding box according of integral image
sumBox = extract<float>(integral[make_tuple(minY, minX)] + integral[make_tuple(maxY, maxX)] -
integral[make_tuple(maxY, minX)] - integral[make_tuple(minY, maxX)]);
// we scale the sumBox
if (sumBox != 0)
bitmap[make_tuple(y,x)] = sumBox / ((maxX - minX) * (maxY - minY));
}
return bitmap;
}
仅供参考:
BOOST_PYTHON_MODULE(Mapper_ext)
{
using namespace boost::python;
using namespace std;
boost::python::numeric::array::set_module_and_type("numpy", "ndarray");
class_<vector<float> >("VectorFloat")
.def(vector_indexing_suite<vector<float> > ());
def("computeSumInboundingbox", computeSumInboundingbox);
}
这是2000帧这三个函数的处理时间
- python 函数 = 100s
- 第一个 c++ 函数 = 145s
- 第二个 c++ 函数 = 121s
即使第二个 c++ 函数也比第一个好,它仍然比只使用 python 慢。为什么?我认为使用 C++ 会更快,尤其是使用 for 循环。无论如何我可以让 c++ 比 python 执行得更快,还是我在这里浪费时间?
这是我的 numba 版本。一开始我的 createFloorBitmap 方法在我的类中,我将 numba 装饰器添加到类中,但我无法让它工作,所以我将该方法移出类。 setup() 和 execute() 继承自对象 Node。
class Mapper(Node):
def setup(self):
# initialise some parameters self.bitmap, self.coordTable
def execute(self,data):
# main function
integral = data['image']
self.bitmap[:] = 0
self.bitmap = createFloorBitmap(self.bitmap, self.coordTable, integral)
return self.bitmap
@jit(f8[:,::1](f8[:,::1], f8[:,::1], f8[:,::1]))
def createFloorBitmap(bitmap, lines, integral):
for row in range(lines.shape[0]):
minX, minY, maxX, maxY = lines[row, 2], lines[row, 3], lines[row, 4], lines[row, 5]
sumBox = integral[minY,minX] + integral[maxY, maxX] - integral[maxY,minX] - integral[minY,maxX]
if sumBox != 0:
bitmap[lines[row, 1],lines[row, 0]] = float(sumBox) / ((maxX - minX) * (maxY - minY))
return bitmap
感谢您的帮助
【问题讨论】:
标签: python c++ performance boost numpy