VectorXi IOUSet::computeTree(const VectorXb & s) const { VectorXi r = VectorXi::Zero(parent_.size()); std::copy( s.data(), s.data()+s.size(), r.data() ); for( int i=0; i<r.size(); i++ ) if( parent_[i] >= 0 ) r[ parent_[i] ] += r[i]; return r; }
typename pcl::PointCloud<T>::Ptr maskFilterDisorganized(typename pcl::PointCloud<T>::ConstPtr in, const VectorXb& mask) { int n = mask.sum(); typename pcl::PointCloud<T>::Ptr out(new typename pcl::PointCloud<T>()); out->points.reserve(n); for (int i=0; i < mask.size(); ++i) { if (mask[i]) out->points.push_back(in->points[i]); } setWidthToSize(out); return out; }
std::vector<T> filter( const std::vector<T> & v, const VectorXb & x ) { std::vector<T> r( x.cast<int>().array().sum() ); for( int i=0, j=0; i<x.size(); i++ ) if( x[i] ) r[j++] = v[i]; return r; }
static VectorXi find( const VectorXb & mask ) { VectorXi r( mask.cast<int>().sum() ); for( int i=0, k=0; i<mask.size(); i++ ) if( mask[i] ) r[k++] = i; return r; }
Proposals nms( const Proposals & proposals, const std::vector<int> & order, float max_iou ) { IOUSet iou_set( proposals.s ); std::vector< VectorXb > r; for( int i: order ) { VectorXb p = proposals.p.row( i ); // Run NMS if( p.any() && iou_set.addIfNotIntersects(p,max_iou) ) r.push_back( p ); } Proposals res; res.s = proposals.s; res.p = RMatrixXb( r.size(), proposals.p.cols() ); for( int j=0; j<r.size(); j++ ) res.p.row(j) = r[j]; return res; }
typename pcl::PointCloud<T>::Ptr maskFilterOrganized(typename pcl::PointCloud<T>::ConstPtr in, const VectorXb& mask) { typename pcl::PointCloud<T>::Ptr out(new typename pcl::PointCloud<T>(*in)); for (int i=0; i < mask.size(); ++i) { if (!mask[i]) { T& pt = out->points[i]; pt.x = NAN; pt.y = NAN; pt.z = NAN; } } return out; }
void build_dedge(const MatrixXu &F, const MatrixXf &V, VectorXu &V2E, VectorXu &E2E, VectorXb &boundary, VectorXb &nonManifold, const ProgressCallback &progress, bool quiet) { if (!quiet) { cout << "Building a directed edge data structure .. "; cout.flush(); } Timer<> timer; if (progress && !quiet) progress("Building directed edge data structure", 0.0f); V2E.resize(V.cols()); V2E.setConstant(INVALID); uint32_t deg = F.rows(); std::vector<std::pair<uint32_t, uint32_t>> tmp(F.size()); tbb::parallel_for( tbb::blocked_range<uint32_t>(0u, (uint32_t) F.cols(), GRAIN_SIZE), [&](const tbb::blocked_range<uint32_t> &range) { for (uint32_t f = range.begin(); f != range.end(); ++f) { for (uint32_t i = 0; i < deg; ++i) { uint32_t idx_cur = F(i, f), idx_next = F((i+1)%deg, f), edge_id = deg * f + i; if (idx_cur >= V.cols() || idx_next >= V.cols()) throw std::runtime_error("Mesh data contains an out-of-bounds vertex reference!"); if (idx_cur == idx_next) continue; tmp[edge_id] = std::make_pair(idx_next, INVALID); if (!atomicCompareAndExchange(&V2E[idx_cur], edge_id, INVALID)) { uint32_t idx = V2E[idx_cur]; while (!atomicCompareAndExchange(&tmp[idx].second, edge_id, INVALID)) idx = tmp[idx].second; } } } if (!quiet) SHOW_PROGRESS_RANGE(range, F.cols(), "Building directed edge data structure (1/3)"); } ); nonManifold.resize(V.cols()); nonManifold.setConstant(false); E2E.resize(F.cols() * deg); E2E.setConstant(INVALID); tbb::parallel_for( tbb::blocked_range<uint32_t>(0u, (uint32_t) F.cols(), GRAIN_SIZE), [&](const tbb::blocked_range<uint32_t> &range) { for (uint32_t f = range.begin(); f != range.end(); ++f) { for (uint32_t i = 0; i < deg; ++i) { uint32_t idx_cur = F(i, f), idx_next = F((i+1)%deg, f), edge_id_cur = deg * f + i; if (idx_cur == idx_next) continue; uint32_t it = V2E[idx_next], edge_id_opp = INVALID; while (it != INVALID) { if (tmp[it].first == idx_cur) { if (edge_id_opp == INVALID) { edge_id_opp = it; } else { nonManifold[idx_cur] = true; nonManifold[idx_next] = true; edge_id_opp = INVALID; break; } } it = tmp[it].second; } if (edge_id_opp != INVALID && edge_id_cur < edge_id_opp) { E2E[edge_id_cur] = edge_id_opp; E2E[edge_id_opp] = edge_id_cur; } } } if (!quiet) SHOW_PROGRESS_RANGE(range, F.cols(), "Building directed edge data structure (2/3)"); } ); std::atomic<uint32_t> nonManifoldCounter(0), boundaryCounter(0), isolatedCounter(0); boundary.resize(V.cols()); boundary.setConstant(false); /* Detect boundary regions of the mesh and adjust vertex->edge pointers*/ tbb::parallel_for( tbb::blocked_range<uint32_t>(0u, (uint32_t) V.cols(), GRAIN_SIZE), [&](const tbb::blocked_range<uint32_t> &range) { for (uint32_t i = range.begin(); i != range.end(); ++i) { uint32_t edge = V2E[i]; if (edge == INVALID) { isolatedCounter++; continue; } if (nonManifold[i]) { nonManifoldCounter++; V2E[i] = INVALID; continue; } /* Walk backwards to the first boundary edge (if any) */ uint32_t start = edge, v2e = INVALID; do { v2e = std::min(v2e, edge); uint32_t prevEdge = E2E[dedge_prev(edge, deg)]; if (prevEdge == INVALID) { /* Reached boundary -- update the vertex->edge link */ v2e = edge; boundary[i] = true; boundaryCounter++; break; } edge = prevEdge; } while (edge != start); V2E[i] = v2e; } if (!quiet) SHOW_PROGRESS_RANGE(range, V.cols(), "Building directed edge data structure (3/3)"); } ); if (!quiet) { cout << "done. ("; if (nonManifoldCounter) cout << nonManifoldCounter << " non-manifold vertices, "; if (boundaryCounter) cout << boundaryCounter << " boundary vertices, "; if (isolatedCounter) cout << isolatedCounter << " isolated vertices, "; cout << "took " << timeString(timer.value()) << ")" << endl; } }
std::vector<Proposals> nms( const std::vector<Proposals> & proposals, const std::vector<int> & order, float max_iou ) { int N = 0; for( const Proposals & p: proposals ) N += p.p.rows(); std::vector<int> s_id( N ), p_id( N ); for( int i=0, k=0; i<proposals.size(); i++ ) for( int j=0; j<proposals[i].p.rows(); j++, k++ ) { s_id[k] = i; p_id[k] = j; } std::vector<RMatrixXs> s; std::vector<int> Ns; for( int i=0; i<proposals.size(); i++ ) { s.push_back( proposals[i].s ); Ns.push_back( proposals[i].s.maxCoeff()+1 ); } const RMatrixXi ms = mergeOverSegmentations(s); const int Nms = ms.maxCoeff()+1; VectorXu ms_area = VectorXu::Zero( Nms ); for( int j=0; j<ms.rows(); j++ ) for( int i=0; i<ms.cols(); i++ ) ms_area[ ms(j,i) ]++; std::vector<IOUSet> iou_set; std::vector<VectorXs> ids; for( int i=0; i<s.size(); i++ ) { iou_set.push_back( s[i] ); ids.push_back( map_id( ms, s[i] ) ); } std::vector<int> pb; pb.reserve( Nms ); std::vector< std::vector< VectorXb > > r( proposals.size() ); for( int i: order ) { VectorXb p = proposals[ s_id[i] ].p.row( p_id[i] ); // Run NMS if( !p.any() || iou_set[ s_id[i] ].intersects(p,max_iou) ) continue; Vector4s bbox = iou_set[ s_id[i] ].computeBBox( p ); // Project each segmentation onto the common OS pb.clear(); for( int j=0; j<Nms; j++ ) if( p[ ids[ s_id[i] ][j] ] ) pb.push_back( j ); bool intersects = false; for( int k=0; !intersects && k<iou_set.size(); k++ ) if( s_id[i] != k ){ // Reproject the common OS to the current os VectorXu p_area = VectorXu::Zero( Ns[k] ); for( int j: pb ) p_area[ ids[ k ][j] ] += ms_area[ j ]; // Run more NMS intersects = iou_set[k].intersects(p_area, bbox, max_iou); } if( !intersects ) { // Add the segment iou_set[ s_id[i] ].add( p ); r[ s_id[i] ].push_back( p ); } } std::vector<Proposals> res( proposals.size() ); for( int i=0; i<proposals.size(); i++ ) { res[i].s = proposals[i].s; res[i].p = RMatrixXb( r[i].size(), proposals[i].p.cols() ); for( int j=0; j<r[i].size(); j++ ) res[i].p.row(j) = r[i][j]; } return res; }