我有一个range-image并想将其转换为libpointmatcher point cloud。云是一个Eigen::Matrix
,每行4行(x,y,z,1)和几列。 范围图像是包含范围值(z)的unsigned short*
阵列和包含有关像素可见性信息的unsigned char*
阵列。使用tbb从阵列中保留并行顺序选择
在串行,我的代码看起来是这样的:
//container to hold the data
std::vector<Eigen::Vector4d> vec;
vec.reserve(this->Height*this->Width);
//contains information about pixel visibility
unsigned char* mask_data = (unsigned char*)range_image.mask.ToPointer();
//contains the actual pixel data
unsigned short* pixel_data = (unsigned short*)range_image.pixel.ToPointer();
for (int y =0;y < range_image.Height; y++)
{
for (int x = 0; x < range_image.Width; x++)
{
int index =x+y*range_image.Width;
if(*(mask_data+index) != 0)
{
vec.push_back(Eigen::Vector4d(x,y,(double)*(data+index),1));
}
}
}
// libpointmatcher point cloud with size of visible pixel
PM::Matrix features(4,vec.size());
PM::DataPoints::Labels featureLabels;
featureLabels.resize(4);
featureLabels[0] = PM::DataPoints::Label::Label("x");
featureLabels[1] = PM::DataPoints::Label::Label("y");
featureLabels[2] = PM::DataPoints::Label::Label("z");
featureLabels[3] = PM::DataPoints::Label::Label("pad");
//fill with data
for(int i = 0; i<vec.size(); i++)
{
features.col(i) = vec[i];
}
因为这个循环需要500ms的为84万点,那太慢的大图像。现在我的想法是将上面的代码集成到一个parallized函数中。问题是Eigen::Matrix
不提供push_back
功能,我不知道可见点的数量提前,我需要在正确的顺序点处理点云。
所以我需要一个并行算法从我的范围图像中提取可见的3D点并将它们按照正确的顺序插入到Eigen :: Matrix中。我正在与Microsoft Visual Studio 2012,我可以使用OpenMP 2.0或TBB。我感谢所有帮助:)
UPDATE
由于拱D.罗宾逊suggeested我试过tbb::parallel_scan
。我传递了掩码数组和一个双数组来保存三维坐标。输出数组的大小是输入数组的四倍,以存储均匀的3D数据(x,y,z,1)。然后,我将otput数组映射到Eigen :: Matrix。行的数量是固定的,并且cols来自parallel_scan的结果。
size_t vec_size = width*height;
double* out = new double[vec_size * 4];
size_t m1 = Compress(mask, pixel, out, height, width,
[](unsigned char x) {return x != 0; });
Map<MatrixXd> features(out, 4, m1);
。下面是从operator()
代码:
void operator()(const tbb::blocked_range2d<size_t, size_t>& r, Tag) {
// Use local variables instead of member fields inside the loop,
// to improve odds that values will be kept in registers.
size_t j = sum;
const unsigned char* m = in;
const unsigned short* p = in2;
T* values = out;
size_t yend = r.rows().end();
for (size_t y = r.rows().begin(); y != yend; ++y)
{
size_t xend = r.cols().end();
for (size_t x = r.cols().begin(); x != xend; ++x)
{
size_t index = x + y*width;
if (pred(m[index]))
{
if (Tag::is_final_scan())
{
size_t idx = j*4;
values[idx] = (double)x;
values[idx + 1] = (double)y;
values[idx + 2] = p[index];
values[idx + 3] = 1.0;
}
++j;
}
}
}
sum = j;
}
我现在快4倍,然后串行版本。你对这种方法有什么看法?我错过了任何想法,并有改进?谢谢
如果你需要的是的std :: copy_if的逻辑等价物,可以考虑使用TBB :: parallel_scan(https://software.intel.com /sites/default/files/bc/2b/parallel_scan.pdf)。 “最终扫描”阶段可以计算最终的目的地指数(作为“成功案例”指数的总和,并进行有条件的分配。) –
@ArchD。Robison可以给我一个关于parallel_scan要求的代码示例(Body,reverse_join_assign)?我不知道该怎么做:/什么是最好的结构来持有指数,我如何将它们合并到最终的扫描中?请帮助我:) – PSchn