void GeodesicObjectProposal::getSegments(const cv::Mat src, std::vector<cv::Mat> &segments, const int nSuperPixels, const int top_segments){ /* Create the proposlas */ Proposal prop( this->prop_settings ); // swap BGR2RGB cv::Mat rgb; cv::cvtColor(src, rgb, CV_BGR2RGB); Image8u im(rgb.cols, rgb.rows, rgb.channels()); // we should copy the image data memcpy(im.data(), rgb.data, sizeof(unsigned char) *3 * rgb.rows * rgb.cols); pthread_mutex_lock(&this->mutex); static int nIters = 10; // Create an over-segmentation std::shared_ptr<ImageOverSegmentation> s = geodesicKMeans( im, detector, nSuperPixels, nIters); RMatrixXb p = prop.propose( *s ); segments.reserve(top_segments); for (int idx = 0; idx < std::min(top_segments, (int)p.rows()); ++idx){ cv::Mat segment(src.rows, src.cols, CV_8UC1); #pragma omp parallel for for( int j=0; j<s->s().rows(); ++j ){ unsigned char *ptr = segment.ptr<unsigned char>(j); for( int i=0; i<s->s().cols(); ++i ) ptr[i] = p( idx, s->s()(j,i) ); } segments.push_back(segment); } segments.resize(segments.size()); pthread_mutex_unlock(&this->mutex); }
void GeodesicObjectProposal::apply(const cv::Mat src, std::vector<cv::Mat> &segments, std::vector<cv::Rect> &bboxes, const int nSuperPixels, const int top_segments){ /* Create the proposlas */ Proposal prop( this->prop_settings ); // swap BGR2RGB cv::Mat rgb; cv::cvtColor(src, rgb, CV_BGR2RGB); Image8u im(rgb.cols, rgb.rows, rgb.channels()); // we should copy the image data memcpy(im.data(), rgb.data, sizeof(unsigned char) *3 * rgb.rows * rgb.cols); /****** LOCK MUTEX ******/ pthread_mutex_lock(&this->mutex); static int nIters = 10; // Create an over-segmentation std::shared_ptr<ImageOverSegmentation> s = geodesicKMeans( im, detector, nSuperPixels, nIters); RMatrixXb p = prop.propose( *s ); int nSegments; if (top_segments < 0) nSegments = (int)p.rows(); else nSegments = top_segments; segments.reserve(nSegments); bboxes.reserve(nSegments); // boxes -> [x0, y0, x1, y1] RMatrixXi boxes = s->maskToBox( p ); for (int idx = 0; idx < nSegments; ++idx){ // extract segments cv::Mat segment(src.rows, src.cols, CV_8UC1); #pragma omp parallel for for( int j=0; j<s->s().rows(); ++j ){ unsigned char *ptr = segment.ptr<unsigned char>(j); for( int i=0; i<s->s().cols(); ++i ) ptr[i] = p( idx, s->s()(j,i) ); } segments.push_back(segment); // extract bbox cv::Rect box(boxes(idx, 0), boxes(idx, 1), boxes(idx, 2) - boxes(idx, 0)+1, boxes(idx, 3) - boxes(idx, 1)+1); bboxes.push_back(box); } segments.resize(segments.size()); bboxes.resize(bboxes.size()); /****** UNLOCK MUTEX ******/ pthread_mutex_unlock(&this->mutex); }
std::tuple<RMatrixXb,RMatrixXb> matchAny( const RMatrixXb & a, const RMatrixXb & b, double max_r ) { const int W = a.cols(), H = a.rows(); eassert( W == b.cols() && H == b.rows() ); RMatrixXb ma = RMatrixXb::Zero( H, W ), mb = RMatrixXb::Zero( H, W ); float r2 = max_r*max_r*(W*W+H*H); const int rd = (int) ceil(sqrt(r2)); for( int j=0; j<H; j++ ) for( int i=0; i<W; i++ ) if( a(j,i) ) for( int jj=std::max(j-rd,0); jj<=std::min(j+rd,H-1); jj++ ) for( int ii=std::max(i-rd,0); ii<=std::min(i+rd,W-1); ii++ ) if( (i-ii)*(i-ii)+(j-jj)*(j-jj) <= r2 ) if( b(jj,ii) ) ma(j,i) = mb(jj,ii) = 1; return std::make_tuple( ma, mb ); }
//void matchBp( bool * pr, const bool * pa, const bool * pb, int W, int H, double max_r ) { // using namespace EvalPrivate; // matchAny( pr, pa, pb, W, H, max_r ); // float r2 = max_r*max_r*(W*W+H*H); // const int rd = (int) ceil(sqrt(r2)); // // Compute the bipartite graph size // std::vector<int> ia(W*H,-1), ib(W*H,-1); // int ca=0,cb=0; // for( int j=0; j<H; j++ ) // for( int i=0; i<W; i++ ) { // if( pr[j*W+i+0] ) // ia[j*W+i] = ca++; // if( pr[j*W+i+W*H] ) // ib[j*W+i] = cb++; // } // // std::vector< BipartiteMatch::Edge > edges; // for( int j=0; j<H; j++ ) // for( int i=0; i<W; i++ ) // if( ia[j*W+i]>=0 ) // for( int jj=std::max(j-rd,0); jj<=std::min(j+rd,H-1); jj++ ) // for( int ii=std::max(i-rd,0); ii<=std::min(i+rd,W-1); ii++ ) // if( (i-ii)*(i-ii)+(j-jj)*(j-jj) <= r2 ) // if( ib[jj*W+ii]>=0 ) // edges.push_back( BipartiteMatch::Edge(ia[j*W+i],ib[jj*W+ii]) ); // // BipartiteMatch match( ca, cb, edges ); // for( int j=0; j<H; j++ ) // for( int i=0; i<W; i++ ) { // if( ia[j*W+i]>=0 ) // pr[j*W+i+0] = (match.match_a[ ia[j*W+i] ]>=0); // if( ib[j*W+i]>=0 ) // pr[j*W+i+W*H] = (match.match_b[ ib[j*W+i] ]>=0); // } //} //np::ndarray matchBp(const np::ndarray & a, const np::ndarray & b, double max_r ) { // checkArray( a, bool, 2, 2, true ); // checkArray( b, bool, 2, 2, true ); // int H = a.shape(0), W = a.shape(1); // if( H != b.shape(0) || W != b.shape(1) ) // throw std::invalid_argument( "a and b need to have the same shape!\n" ); // np::ndarray r = np::zeros( make_tuple(2,H,W), a.get_dtype() ); // matchBp( (bool*)r.get_data(), (const bool*)a.get_data(), (const bool*)b.get_data(), W, H, max_r ); // return r; //} Vector4i evalBoundaryBinary( const RMatrixXb & d, const std::vector<RMatrixXb> & bnd, double max_r, const RMatrixXb & mask ) { const int W = d.cols(), H = d.rows(), D = bnd.size(); eassert( mask.cols() == W && mask.rows() == H ); int sum_r=0, cnt_r=0; RMatrixXb ma, mb, acc = RMatrixXb::Zero(H,W); for( int k=0; k<D; k++ ) { eassert( W == bnd[k].cols() && H == bnd[k].rows() ); std::tie(ma,mb) = matchBp( d, bnd[k], max_r ); acc = acc.array() || (ma.array() && mask.array()); sum_r += (bnd[k].array() && mask.array()).cast<int>().sum(); cnt_r += (mb.array() && mask.array()).cast<int>().sum(); } int sum_p = (d.array() && mask.array()).cast<int>().sum(); int cnt_p = (acc.array() && mask.array()).cast<int>().sum(); return Vector4i(cnt_r,sum_r,cnt_p,sum_p); }
static void Proposal_propose( MEX_ARGS ) { if( nrhs != 2 ) { mexErrMsgTxt("Expected to get proposal and ImageOverSegmentation"); return; } if( nlhs != 1 ) { mexErrMsgTxt("Expected a single output argument"); return; } std::shared_ptr<Proposal> p = mat2Ptr<Proposal>( prhs[0] ); std::shared_ptr<ImageOverSegmentation> os = mat2Ptr<ImageOverSegmentation>( prhs[1] ); RMatrixXb r = p->propose( *os ); // Create and write the resulting segmentation mwSize dims[2] = {(mwSize)r.rows(), (mwSize)r.cols()}; plhs[0] = mxCreateNumericArray( 2, dims, mxLOGICAL_CLASS, mxREAL ); MatrixXb::Map( (mxLogical*)mxGetData(plhs[0]), r.rows(), r.cols() ) = r; }
std::tuple<RMatrixXb,RMatrixXb> matchBp( const RMatrixXb & a, const RMatrixXb & b, double max_r ) { using namespace EvalPrivate; const int W = a.cols(), H = a.rows(); eassert( W == b.cols() && H == b.rows() ); RMatrixXb ma, mb; std::tie(ma,mb) = matchAny( a, b, max_r ); float r2 = max_r*max_r*(W*W+H*H); const int rd = (int) ceil(sqrt(r2)); // Compute the bipartite graph size std::vector<int> ia(W*H,-1), ib(W*H,-1); int ca=0,cb=0; for( int j=0; j<H; j++ ) for( int i=0; i<W; i++ ) { if( ma(j,i) ) ia[j*W+i] = ca++; if( mb(j,i) ) ib[j*W+i] = cb++; } std::vector< BipartiteMatch::Edge > edges; for( int j=0; j<H; j++ ) for( int i=0; i<W; i++ ) if( ia[j*W+i]>=0 ) for( int jj=std::max(j-rd,0); jj<=std::min(j+rd,H-1); jj++ ) for( int ii=std::max(i-rd,0); ii<=std::min(i+rd,W-1); ii++ ) if( (i-ii)*(i-ii)+(j-jj)*(j-jj) <= r2 ) if( ib[jj*W+ii]>=0 ) edges.push_back( BipartiteMatch::Edge(ia[j*W+i],ib[jj*W+ii]) ); BipartiteMatch match( ca, cb, edges ); for( int j=0; j<H; j++ ) for( int i=0; i<W; i++ ) { if( ia[j*W+i]>=0 ) ma(j,i) = (match.match_a[ ia[j*W+i] ]>=0); if( ib[j*W+i]>=0 ) mb(j,i) = (match.match_b[ ib[j*W+i] ]>=0); } return std::make_tuple(ma, mb); }
TEST(Vision, load_default_color_config) { RMatrixXb config = load_single_color_config(default_yellow_config, Vision::COLOR_MASK_TYPE::YELLOW); ASSERT_TRUE((config.array() > 0).any()); config *=4; write_png_file("/tmp/conf.png",config.cast<uint8_t>()); }
Vector4i evalBoundaryBinary( const RMatrixXb & d, const std::vector<RMatrixXb> & bnd, double max_r ) { return evalBoundaryBinary( d, bnd, max_r, RMatrixXb::Ones(d.rows(),d.cols()) ); }