我正在开发一个大型计算机视觉项目,我需要对来自多个摄像头的每个帧进行一些处理。它很重,我想提高速度。所以我想用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 和 位图 是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中的1D std :: vector中转换了我的2D列表(我真的没有找到创建2D矢量的方法)
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帧的三个函数的处理时间
即使第二个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
感谢您的帮助
答案 0 :(得分:3)
您可以使用数组作为索引来提高速度,下面是代码:
w = 600
integral = np.random.randint(0, 255, (w, w))
bitmap = np.zeros_like(integral)
lines = np.random.randint(0, w, (10000, 6))
def computeSumInboundingbox(bitmap, cameraTable, integral):
for line in cameraTable:
minX, minY, maxX, maxY = line[2], line[3], line[4], line[5]
sumBox = integral[(minY,minX)] + integral[(maxY, maxX)] - integral[(maxY,minX)] - integral[(minY,maxX)]
if sumBox != 0:
bitmap[line[0],line[1]] = float(sumBox) / ((maxX - minX) * (maxY - minY))
def computeSumInboundingbox2(bitmap, line, integral):
tx, ty, minx, miny, maxx, maxy = line.T
sumBox = integral[miny, minx] + integral[maxy, maxx] - integral[maxy, minx] - integral[miny, maxx]
mask = sumBox != 0
bitmap[tx[mask], ty[mask]] = (sumBox.astype(float)[mask] / ((maxx - minx) * (maxy - miny))[mask])
bitmap1 = np.zeros_like(integral)
bitmap2 = np.zeros_like(integral)
computeSumInboundingbox(bitmap1, lines, integral)
computeSumInboundingbox2(bitmap2, lines, integral)
print np.allclose(bitmap1, bitmap2)
现在是时间:
computeSumInboundingbox: 10 loops, best of 3: 42.4 ms per loop
computeSumInboundingbox2: 100 loops, best of 3: 2.36 ms per loop
为什么c ++很慢,因为你使用python对象级方法来进行数组索引。您可以使用cython,它知道如何访问c级数据。
修改强>
这是一个numba版本:
import numba
@numba.jit("void(i4[:,::1], i4[:,::1], i4[:,::1])")
def computeSumInboundingbox3(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, 0],lines[row, 1]] = float(sumBox) / ((maxX - minX) * (maxY - minY))
和速度:
10000 loops, best of 3: 119 µs per loop