00001
00002
00003
00004
00005
00006
00007 #include "moving_object_filter.h"
00008 #include "umath.h"
00009 #include "optical_flow.h"
00010
00011
00012
00013 #define VIEW_RESULT
00014
00015
00016 using namespace Eigen;
00017
00018 MovingObjectFilter::MovingObjectFilter( int argc, char**argv ):rgb_frame_id(""),depth_frame_id(""){
00019
00020 ros::NodeHandle nh ;
00021 rgbPub_ = nh.advertise<sensor_msgs::Image>( "/filter/rgb" , 10 ) ;
00022 depthPub_ = nh.advertise<sensor_msgs::Image>( "/filter/depth", 10 ) ;
00023 cloudPub_ = nh.advertise<sensor_msgs::PointCloud2>("/filter/pointcloud2",10) ;
00024 num1 = 0 ;
00025
00026
00027 }
00028 void MovingObjectFilter::setFrameId(std::string rgb_frame, std::string depth_frame){
00029 rgb_frame_id = rgb_frame ;
00030 depth_frame_id = depth_frame ;
00031 }
00032
00033 void MovingObjectFilter::processData( const cv::Mat & image, const cv::Mat &depth ,
00034 float cx,float cy,
00035 float fx,float fy){
00036
00037 cv::Mat imageMono ;
00038
00039
00040 if(image.channels() > 1){
00041 cv::cvtColor(image, imageMono, cv::COLOR_BGR2GRAY) ;
00042 }else{
00043 imageMono = image ;
00044 }
00045
00046 timeval start , end ;
00047 long long time ;
00048
00049 gettimeofday( &start, NULL ) ;
00050
00051
00052 this->computeHomography(imageMono);
00053
00054 gettimeofday( &end, NULL ) ;
00055 time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) ;
00056
00057 #ifdef TIME
00058 cout << "findhomography Time = " << time << endl;
00059 #endif TIME
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00071 gettimeofday( &start, NULL ) ;
00072
00073 cloud = this->cloudFromDepthRGB( image, depth, cx, cy, fx, fy, 1.0 ) ;
00074 gettimeofday( &end, NULL ) ;
00075 time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) ;
00076
00077 #ifdef TIME
00078 cout << "calculateCloud Time = " << time << endl;
00079 #endif TIME
00080
00081
00082
00083
00084
00085
00086
00087 gettimeofday( &start, NULL ) ;
00088
00089
00090 this->image_diff( imageMono, cloud ) ;
00091
00092 gettimeofday( &end, NULL ) ;
00093 time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) ;
00094
00095 #ifdef TIME
00096 cout << "Diffetrence Time = " << time << endl;
00097 #endif TIME
00098
00099 pcl::PointCloud<pcl::PointXYZRGB>::Ptr restCloud;
00100 cv::Mat restDepth ;
00101
00102 gettimeofday( &start, NULL ) ;
00103
00104
00105 restDepth = this->pcl_segmentation(cloud, image, depth, cx, cy, fx, fy) ;
00106
00107 gettimeofday( &end, NULL ) ;
00108 time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) ;
00109
00110 #ifdef TIME
00111 cout << "CloudCluster Time = " << time << endl;
00112 #endif TIME
00113
00114
00115
00116 cv_bridge::CvImage cv_image ;
00117 cv_image.image = restDepth ;
00118 cv_image.encoding = "16UC1" ;
00119 sensor_msgs::Image depth_image ;
00120 cv_image.toImageMsg( depth_image ) ;
00121 depth_image.header.stamp = ros::Time::now() ;
00122 depth_image.header.frame_id = depth_frame_id ;
00123 depthPub_.publish(depth_image) ;
00124
00125
00126 cv_bridge::CvImage cv_rgbImage ;
00127 cv_rgbImage.image = image ;
00128 cv_rgbImage.encoding = "bgr8" ;
00129 sensor_msgs::Image rgbImage ;
00130 cv_rgbImage.toImageMsg( rgbImage ) ;
00131 rgbImage.header.stamp = ros::Time::now() ;
00132 rgbImage.header.frame_id = rgb_frame_id ;
00133 rgbPub_.publish( rgbImage ) ;
00134
00135
00136
00137
00138 restCloud = this->cloudFromDepthRGB(image, restDepth, cx, cy, fx, fy, 1.0) ;
00139
00140 #ifdef DEBUG_WRITE
00141 pcl::PCDWriter writer ;
00142
00143 std::stringstream ss1;
00144 ss1 << "restcloud_" << num1 << ".pcd" ;
00145 writer.write<pcl::PointXYZRGB>(ss1.str(), *restCloud,false) ;
00146
00147 #endif DEBUG_WRITE
00148
00149 #ifdef View
00150
00151
00152
00153
00154
00155
00156
00157
00158 #endif
00159
00160 sensor_msgs::PointCloud2::Ptr cloudMsg(new sensor_msgs::PointCloud2) ;
00161 pcl::toROSMsg(*restCloud, *cloudMsg) ;
00162 cloudMsg->header.stamp = ros::Time::now() ;
00163 cloudMsg->header.frame_id = "camera_link" ;
00164 cloudPub_.publish(cloudMsg) ;
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 void MovingObjectFilter::computeHomography(cv::Mat &grayImage){
00183
00184
00185 cv::ORB orb ;
00186 std::vector<cv::KeyPoint> lastKeypoints ;
00187 std::vector<cv::KeyPoint> keypoints ;
00188
00189 #ifdef DEBUG_WRITE
00190
00191
00192 std::stringstream ss;
00193 ss << "currentImage" << num1 << ".jpg";
00194 cv::imwrite( ss.str(), grayImage ) ;
00195
00196 #endif DEBUG_WRITE
00197
00198
00199
00200
00201
00202
00203 cv::Mat lastDescriptors ;
00204 cv::Mat descriptors ;
00205
00206 if(!lastImage.empty()){
00207 orb( lastImage, cv::Mat(), lastKeypoints, lastDescriptors) ;
00208 orb( grayImage, cv::Mat(), keypoints, descriptors );
00209 }
00210
00211 cv::BFMatcher matcher(cv::NORM_L2) ;
00212
00213 std::vector<cv::DMatch> matches ;
00214
00215 std::vector<cv::DMatch> goodMatches ;
00216 double minDist = 1000.0 , maxDist = 0.0 ;
00217 cv::Mat img_matches ;
00218 std::vector<cv::Point2f> lastPoint ;
00219 std::vector<cv::Point2f> currentPoint ;
00220 cv::Mat shft ;
00221 if(!lastDescriptors.empty()){
00222
00223 matcher.match( lastDescriptors, descriptors, matches );
00224 for(int i=0; i<lastDescriptors.rows; i++){
00225 double dist = matches[i].distance ;
00226 if(dist < minDist)
00227 minDist = dist ;
00228 if(dist > maxDist)
00229 maxDist = dist ;
00230 }
00231
00232 for(int i=0; i<lastDescriptors.rows; i++){
00233 if( matches[i].distance < 0.6*maxDist ){
00234 goodMatches.push_back(matches[i]);
00235 }
00236 }
00237
00238
00239
00240
00241
00242 cv::drawMatches( lastImage, lastKeypoints, grayImage, keypoints, goodMatches,img_matches, cv::Scalar::all(-1), cv::Scalar::all(-1),std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
00243
00244
00245 #ifdef DEBUG_WRITE
00246
00247 std::stringstream ss1;
00248 ss1 << "matchesImage" << num1 << ".jpg";
00249 cv::imwrite( ss1.str(), img_matches ) ;
00250 #endif DEBUG_WRITE
00251
00252 #ifdef DEBUG_WRITE
00253 std::stringstream ss2;
00254 ss2 << "lastImage" << num1 << ".jpg";
00255 cv::imwrite( ss2.str(), lastImage ) ;
00256 #endif DEBUG_WRITE
00257
00258
00259
00260 if(cv::waitKey(1) > 0){
00261 exit(0);
00262 }
00263 cout << "match size = " << goodMatches.size() << endl ;
00264 if(goodMatches.size() > 4){
00265 for( int i=0; i<goodMatches.size();i++ ){
00266 lastPoint.push_back( lastKeypoints[goodMatches[i].queryIdx].pt );
00267 currentPoint.push_back( keypoints[goodMatches[i].trainIdx].pt );
00268 }
00269 double m[3][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
00270 Homography = cv::Mat(3, 3, CV_64F, m );
00271 Homography = cv::findHomography( lastPoint, currentPoint, CV_RANSAC ) ;
00272 shft = ( cv::Mat_<double>(3,3)<< 1.0, 0, lastImage.cols, 0, 1.0, 0, 0, 0, 1.0) ;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 #ifdef DEBUG_WRITE
00289 std::stringstream ss3;
00290 ss3 << "warpImage" << num1 << ".jpg";
00291 cv::imwrite( ss3.str(), dst ) ;
00292
00293 #endif DEBUG_WRITE
00294 }
00295
00296 lastImage = grayImage ;
00297
00298 }
00299
00300
00301
00302 void MovingObjectFilter::image_diff(const cv::Mat ¤tImage, cloud_type::ConstPtr cloud){
00303 cv::Mat BlurImage1, BlurImage2 ;
00304 if(lastBlurImage.empty()){
00305 cv::GaussianBlur( currentImage, BlurImage1, cv::Size( 11, 11 ), 0, 0 );
00306 lastBlurImage = BlurImage1 ;
00307
00308 lastCloud = *cloud ;
00309 }else{
00310 cv::GaussianBlur( currentImage, BlurImage2, cv::Size( 11, 11 ), 0, 0 );
00311
00312
00313
00314
00315 cv::Mat last_frame( 480,640, CV_8UC1, cv::Scalar(0) );
00316 cv::Mat current_frame( 480,640, CV_8UC1, cv::Scalar(0) );
00317 cv::Mat diffFrame( 480,640, CV_8UC1, cv::Scalar(0) );
00318
00319
00320 lastFrame = last_frame ;
00321 currentFrame = current_frame ;
00322 threshod = 40 ;
00323
00324
00325
00326
00327 #ifdef VIEW
00328 cv::namedWindow("currentImage");
00329 cv::imshow("currentImage", currentImage) ;
00330 cv::waitKey(1) ;
00331 #endif VIEW
00332
00333 ros::Time timebegin = ros::Time::now();
00334 cv::Mat dst ;
00335 cv::absdiff(lastImage, BlurImage2, dst) ;
00336 ros::Time timeend = ros::Time::now() ;
00337 ros::Duration time1 = timeend - timebegin;
00338 double timecost = time1.toSec();
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 cv::Point warpPt ;
00349
00350
00351 double hom[4][4] ;
00352
00353 for( int rows=0; rows < Homography.rows; rows++ ){
00354 const double* homPtr = Homography.ptr<double>(rows) ;
00355 for(int cols=0; cols< Homography.cols; cols++){
00356
00357 hom[rows][cols] = homPtr[cols] ;
00358 }
00359 }
00360
00361
00362 double srcMatrix[4][2];
00363 double resMatrix[4][2];
00364
00365 for( int rows=0; rows < lastImage.rows; rows++ ){
00366 for(int cols=0; cols< lastImage.cols; cols++){
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 srcMatrix[0][0] = cols ;
00377 srcMatrix[1][0] = rows ;
00378 srcMatrix[2][0] = 1.0 ;
00379 resMatrix[0][0] = hom[0][0]*srcMatrix[0][0] + hom[0][1]*srcMatrix[1][0] + hom[0][2]*srcMatrix[2][0] ;
00380 resMatrix[1][0] = hom[1][0]*srcMatrix[0][0] + hom[1][1]*srcMatrix[1][0] + hom[1][2]*srcMatrix[2][0] ;
00381 resMatrix[2][0] = hom[2][0]*srcMatrix[0][0] + hom[2][1]*srcMatrix[1][0] + hom[2][2]*srcMatrix[2][0] ;
00382
00383 warpPt.x = cvRound( resMatrix[0][0] / resMatrix[2][0] ) ;
00384 warpPt.y = cvRound( resMatrix[1][0] / resMatrix[2][0] ) ;
00385
00386
00387
00388
00389 const uchar* lastBlurImagePtr ;
00390 const uchar* currentBlurImagePtr ;
00391
00392 if( warpPt.x>0 && warpPt.x<640 && warpPt.y>0 && warpPt.y< 480){
00393 lastBlurImagePtr = lastBlurImage.ptr<uchar>( rows );
00394 currentBlurImagePtr = BlurImage2.ptr<uchar>( warpPt.y );
00395 const uchar& lastCol = lastBlurImagePtr[cols] ;
00396 const uchar& currentCol = currentBlurImagePtr[warpPt.x] ;
00397 double imageDiff = abs(lastCol - currentCol) ;
00398
00399
00400
00401 double lastDepthValue = 0.0 ;
00402 double depthValue = 0.0 ;
00403
00404
00405
00406
00407
00408 uchar* lastFramePtr = lastFrame.ptr<uchar>(rows) ;
00409 uchar* lastFrameCol = &lastFramePtr[cols] ;
00410
00411 uchar* currentFramePtr = currentFrame.ptr<uchar>(warpPt.y) ;
00412 uchar* currentFrameCol = ¤tFramePtr[warpPt.x] ;
00413
00414
00415
00416 if( imageDiff > threshod ){
00417 diffFrame.at<unsigned char>(warpPt.y ,warpPt.x) = 255 ;
00418
00419
00420
00421 lastDepthValue = isnan( lastCloud.at(rows*lastCloud.width + cols).z) ? 20 : lastCloud.at(rows*lastCloud.width + cols).z ;
00422 depthValue = isnan( cloud->at(warpPt.y*cloud->width + warpPt.x).z) ? 20 : cloud->at(warpPt.y*cloud->width + warpPt.x).z ;
00423
00424 if( lastDepthValue - depthValue > 0.2 && lastDepthValue<20 ){
00425 *currentFrameCol = 255 ;
00426
00427
00428
00429
00430
00431 }else if( depthValue -lastDepthValue > 0.2 && depthValue <20 ){
00432 *lastFrameCol = 255 ;
00433
00434
00435
00436
00437
00438 }else{
00439 continue ;
00440 }
00441
00442 }else{
00443 continue ;
00444 }
00445 }else{
00446 continue ;
00447 }
00448 }
00449 }
00450 ros::Time timeend1 = ros::Time::now();
00451 ros::Duration time2 = timeend1 - timeend;
00452 double timecost1 = time2.toSec();
00453
00454
00455
00456
00457
00458
00459 #ifdef DEBUG_WRITE
00460 std::stringstream ss1;
00461 ss1 << "differenceImage" << num1 << ".jpg";
00462 cv::imwrite( ss1.str(), diffFrame ) ;
00463 #endif DEBUG_WRITE
00464
00465 #ifdef DEBUG_WRITE
00466 std::stringstream ss2;
00467 ss2 << "lastFrame" << num1 << ".jpg";
00468 cv::imwrite( ss2.str(), lastFrame ) ;
00469 #endif DEBUG_WRITE
00470
00471 #ifdef DEBUG_WRITE
00472 std::stringstream ss3;
00473 ss3 << "currentFrame" << num1 << ".jpg";
00474 cv::imwrite( ss3.str(),currentFrame ) ;
00475 #endif DEBUG_WRITE
00476
00477 #ifdef DEBUG_WRITE
00478 pcl::PCDWriter writer ;
00479 std::stringstream ss4;
00480 ss4 << "cloud_filtered_" << num1 << ".pcd" ;
00481 writer.write<pcl::PointXYZRGB>( ss4.str(), *cloud, false ) ;
00482 #endif DEBUG_WRITE
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 #ifdef VIEW
00495 cv::imshow("currentFrame",currentFrame) ;
00496 cv::waitKey(5);
00497 #endif VIEW
00498
00499
00500
00501
00502
00503
00504
00505 lastBlurImage = BlurImage2 ;
00506 lastCloud = *cloud ;
00507
00508
00509 }
00510 }
00511
00512 pcl::PointXYZ MovingObjectFilter::projectDepthTo3D(
00513 const cv::Mat & depthImage,
00514 float x, float y,
00515 float cx, float cy,
00516 float fx, float fy,
00517 bool smoothing,
00518 float maxZError)
00519 {
00520
00521
00522 pcl::PointXYZ pt;
00523 float bad_point = std::numeric_limits<float>::quiet_NaN ();
00524
00525 int u = int(x+0.5f);
00526 int v = int(y+0.5f);
00527
00528 if(!(u >=0 && u<depthImage.cols && v >=0 && v<depthImage.rows))
00529 {
00530
00531
00532 pt.x = pt.y = pt.z = bad_point;
00533 return pt;
00534 }
00535
00536 bool isInMM = depthImage.type() == CV_16UC1;
00537
00538
00539
00540
00541
00542
00543
00544
00545 int u_start = std::max(u-1, 0);
00546 int v_start = std::max(v-1, 0);
00547 int u_end = std::min(u+1, depthImage.cols-1);
00548 int v_end = std::min(v+1, depthImage.rows-1);
00549 const uint16_t *depthPtr = depthImage.ptr<uint16_t>( v ) ;
00550 const uint16_t &dv = depthPtr[u] ;
00551
00552
00553 float depth = isInMM?(float) dv*0.001f : dv ;
00554 if(depth!=0.0f && uIsFinite(depth))
00555 {
00556 if(smoothing)
00557 {
00558 float sumWeights = 0.0f;
00559 float sumDepths = 0.0f;
00560 for(int uu = u_start; uu <= u_end; ++uu)
00561 {
00562 for(int vv = v_start; vv <= v_end; ++vv)
00563 {
00564 if(!(uu == u && vv == v))
00565 {
00566
00567 float d = isInMM ? (float)dv*0.001f : dv ;
00568
00569 if(d != 0.0f && uIsFinite(d) && fabs(d - depth) < maxZError)
00570 {
00571 if(uu == u || vv == v)
00572 {
00573 sumWeights+=2.0f;
00574 d*=2.0f;
00575 }
00576 else
00577 {
00578 sumWeights+=1.0f;
00579 }
00580 sumDepths += d;
00581 }
00582 }
00583 }
00584 }
00585
00586 depth *= 4.0f;
00587 sumWeights += 4.0f;
00588
00589
00590 depth = (depth+sumDepths)/sumWeights;
00591 }
00592
00593
00594 cx = cx > 0.0f ? cx : float(depthImage.cols/2) - 0.5f;
00595 cy = cy > 0.0f ? cy : float(depthImage.rows/2) - 0.5f;
00596
00597
00598 pt.x = (x - cx) * depth / fx ;
00599 pt.y = (y - cy) * depth / fy ;
00600 pt.z = depth;
00601 }
00602 else
00603 {
00604 pt.x = pt.y = pt.z = bad_point;
00605 }
00606 return pt;
00607 }
00608
00609 pcl::PointCloud<pcl::PointXYZRGB>::Ptr MovingObjectFilter::cloudFromDepthRGB(
00610 const cv::Mat & imageRgb,
00611 const cv::Mat & imageDepth,
00612 float cx, float cy,
00613 float fx, float fy,
00614 int decimation)
00615 {
00616
00617
00618 assert(imageDepth.type() == CV_16UC1);
00619 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
00620 if( decimation < 1 ){
00621 return cloud;
00622 }
00623
00624 bool mono;
00625 if(imageRgb.channels() == 3){
00626 mono = false;
00627 }else if(imageRgb.channels() == 1){
00628 mono = true;
00629 }else{
00630 return cloud;
00631 }
00632
00633
00634 cloud->height = imageDepth.rows/decimation;
00635 cloud->width = imageDepth.cols/decimation;
00636 cloud->is_dense = false;
00637 cloud->resize(cloud->height * cloud->width);
00638 pcl::PointCloud<pcl::PointXYZRGB>::iterator pc_iter = cloud->begin() ;
00639
00640
00641
00642 for(int h = 0; h < imageDepth.rows && h/decimation < (int)cloud->height; h+=decimation){
00643 const cv::Vec3b *rgbPtr = imageRgb.ptr<cv::Vec3b>( h ) ;
00644 for(int w = 0; w < imageDepth.cols && w/decimation < (int)cloud->width; w+=decimation){
00645 pcl::PointXYZRGB &pt = *pc_iter++ ;
00646 const cv::Vec3b& col = rgbPtr[w];
00647
00648 if(!mono){
00649 pt.b = col[0] ;
00650 pt.g = col[1] ;
00651 pt.r = col[2] ;
00652 }else{
00653
00654 pt.b = col[0] ;
00655 pt.g = col[1] ;
00656 pt.r = col[2] ;
00657 }
00658
00659 pcl::PointXYZ ptXYZ = this->projectDepthTo3D(imageDepth, w, h, cx, cy, fx, fy, false);
00660 pt.x = ptXYZ.x;
00661 pt.y = ptXYZ.y;
00662 pt.z = ptXYZ.z;
00663 }
00664 }
00665
00666
00667
00668
00669
00670
00671
00672 return cloud;
00673 }
00674 cv::Mat MovingObjectFilter::pcl_segmentation( cloud_type::ConstPtr cloud , const cv::Mat &image , const cv::Mat &depthImage, float cx, float cy, float fx, float fy ){
00675
00676 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZRGB>);
00677 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_f (new pcl::PointCloud<pcl::PointXYZRGB>);
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 timeval start , end, start1, end1, start2, end2 ;
00712 long long time , time1, time2;
00713
00714 gettimeofday( &start, NULL ) ;
00715
00716
00717 pcl::PCDWriter writer ;
00718 pcl::VoxelGrid<pcl::PointXYZRGB> downSampler;
00719 downSampler.setInputCloud (cloud->makeShared());
00720 downSampler.setLeafSize (0.02f, 0.02f, 0.02f);
00721 downSampler.filter (*cloud_filtered);
00722
00723
00724
00725
00726
00727 gettimeofday( &end, NULL ) ;
00728 time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) ;
00729 #ifdef TIME
00730 cout << "Downsampler Time = " << time << endl;
00731 #endif TIME
00732
00733 #ifdef DEBUG
00734 static int num1=0 ;
00735 std::stringstream ss1;
00736 ss1 << "cloud_" << num1 << ".pcd" ;
00737 writer.write<pcl::PointXYZRGB>(ss1.str(), *cloud_filtered,false) ;
00738
00739 #endif DEBUG
00740
00741 gettimeofday( &start1, NULL ) ;
00742
00743
00744 pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
00745 pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
00746 pcl::SACSegmentation<pcl::PointXYZRGB> seg;
00747
00748
00749 seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
00750 seg.setMethodType (pcl::SAC_RANSAC);
00751 seg.setDistanceThreshold (0.1);
00752 seg.setMaxIterations(300);
00753 seg.setAxis(Eigen::Vector3f(0.0, 1.0, 0.0));
00754 seg.setEpsAngle (pcl::deg2rad (8.0));
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZRGB> ()) ;
00768 pcl::PointCloud<pcl::PointXYZRGB> plane ;
00769 pcl::ExtractIndices<pcl::PointXYZRGB> extract;
00770 int nr_points = (int) cloud_filtered->points.size ();
00771 while(cloud_filtered->points.size () > 0.4 * nr_points){
00772 seg.setInputCloud (cloud_filtered->makeShared());
00773 seg.segment (*inliers, *coefficients);
00774 if (inliers->indices.size () == 0){
00775 std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
00776 break;
00777 }
00778 cout << "a = " << coefficients->values.at(0) << " ;b = " << coefficients->values.at(1) << " ;c = " << coefficients->values.at(2)<< " ;d = " << coefficients->values.at(3) << endl ;
00779
00780 extract.setInputCloud (cloud_filtered->makeShared());
00781
00782 extract.setIndices (inliers) ;
00783 extract.setNegative (false) ;
00784 extract.filter (*cloud_plane) ;
00785 plane += *cloud_plane ;
00786
00787
00788 extract.setNegative (true) ;
00789 extract.filter ( *cloud_f ) ;
00790 *cloud_filtered = *cloud_f ;
00791 break ;
00792 }
00793
00794
00795
00796
00797
00798 #ifdef DEBUG
00799 std::stringstream ss2;
00800 ss2 << "cloud_filtered_" << num1 << ".pcd" ;
00801 writer.write<pcl::PointXYZRGB>(ss2.str(), *cloud_filtered,false) ;
00802 #endif DEBUG
00803
00804
00805
00806
00807
00808
00809
00810
00811 gettimeofday( &end1, NULL ) ;
00812 time1 = 1000000*(end1.tv_sec - start1.tv_sec) + (end1.tv_usec - start1.tv_usec) ;
00813
00814 #ifdef TIME
00815 cout << "Removing Planar Time = " << time1 << endl;
00816 #endif TIME
00817
00818 gettimeofday( &start2, NULL ) ;
00819
00820 pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>);
00821 tree->setInputCloud (cloud_filtered->makeShared());
00822
00823 std::vector<pcl::PointIndices> cluster_indices ;
00824 pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> ec ;
00825 ec.setClusterTolerance (0.06) ;
00826 ec.setMinClusterSize (100) ;
00827 ec.setMaxClusterSize (50000) ;
00828 ec.setSearchMethod (tree) ;
00829 ec.setInputCloud (cloud_filtered->makeShared()) ;
00830 ec.extract (cluster_indices) ;
00831
00832
00833
00834
00835
00836
00837 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZRGB>);
00838 pcl::PointCloud<pcl::PointXYZRGB>::Ptr dynamic_object (new pcl::PointCloud<pcl::PointXYZRGB>);
00839
00840
00841
00842 static int num = 0 ;
00843 int j = 0 ;
00844 pcl::PointCloud<pcl::PointXYZRGB>::Ptr static_object(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00845 pcl::PointCloud<pcl::PointXYZRGB>::Ptr object(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00846 *static_object = plane ;
00847
00848
00849 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00850
00851 int num_dy_object = 0;
00852 cv::Mat imageMono ;
00853
00854
00855 if(image.channels() > 1){
00856 cv::cvtColor(image, imageMono, cv::COLOR_BGR2GRAY) ;
00857 }else{
00858 imageMono = image ;
00859 }
00860 dynamicImage = imageMono ;
00861
00862 for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it){
00863 for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
00864 cloud_cluster->push_back( cloud_filtered->points[*pit]) ;
00865
00866 cloud_cluster->width = cloud_cluster->points.size () ;
00867 cloud_cluster->height = 1 ;
00868 cloud_cluster->is_dense = true ;
00869 cloud_cluster->sensor_origin_ = cloud_filtered->sensor_origin_ ;
00870 cloud_cluster->sensor_orientation_ = cloud_filtered->sensor_orientation_ ;
00871 *cluster += *cloud_cluster ;
00872
00873 #ifdef DEBUG
00874 std::stringstream ss;
00875 ss << "cluster_cloud_" << num << "_" << j << ".pcd" ;
00876 writer.write<pcl::PointXYZRGB>(ss.str(), *cloud_cluster,false) ;
00877 #endif DEBUG
00878
00879
00880 if(image_extract_cluster( cloud_cluster->makeShared(), cloud->makeShared(), image, cx, cy, fx, fy, num , j)) {
00881 *object = objectFromOriginalCloud( cloud_cluster,cloud ) ;
00882
00883 *dynamic_object += *object;
00884
00885 #ifdef DEBUG
00886 std::stringstream ss;
00887 ss << "cluster_dynamic_" << num << "_" << j << ".pcd" ;
00888 writer.write<pcl::PointXYZRGB>(ss.str(), *cloud_cluster,false) ;
00889 #endif DEBUG
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 num_dy_object ++;
00900 }else{
00901
00902
00903 }
00904 j++ ;
00905 num++ ;
00906 #ifdef DEBUG
00907 cout << "j = " << j << endl ;
00908 #endif DEBUG
00909
00910 cloud_cluster->clear();
00911
00912 }
00913
00914 cout << "dynamic objects: " << num_dy_object << endl;
00915
00916
00917
00918
00919
00920 #ifdef VIEW_RESULT
00921 cv::namedWindow("dynamicObjectDetection") ;
00922 cv::imshow("dynamicObjectDetection", dynamicImage) ;
00923 cv::waitKey(5) ;
00924 #endif VIEW_RESULT
00925
00926 gettimeofday( &end2, NULL ) ;
00927 time2 = 1000000*(end2.tv_sec - start2.tv_sec) + (end2.tv_usec - start2.tv_usec) ;
00928
00929 #ifdef TIME
00930 cout << "cluster Time = " << time2 << endl;
00931 #endif TIME
00932
00933
00934 dynamic_object->width = dynamic_object->points.size () ;
00935 dynamic_object->height = 1 ;
00936 dynamic_object->is_dense = true ;
00937 dynamic_object->resize(dynamic_object->height * dynamic_object->width);
00938
00939
00940
00941
00942
00943
00944 cv::Mat rest ;
00945 rest = getDepth( dynamic_object, depthImage, cx, cy, fx, fy );
00946 this->getImage( dynamic_object, image, cx, cy, fx, fy );
00947
00948
00949
00950 #ifdef DEBUG
00951 num++ ;
00952 #endif DEBUG
00953
00954 return rest ;
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 }
00967 bool MovingObjectFilter::image_extract_cluster( cloud_type::ConstPtr cluster_cloud, cloud_type::ConstPtr cloud, const cv::Mat &image , float cx, float cy, float fx, float fy , int num , int j){
00968
00969 cv::Mat imageMono ;
00970
00971
00972 if(image.channels() > 1){
00973 cv::cvtColor(image, imageMono, cv::COLOR_BGR2GRAY) ;
00974 }else{
00975 imageMono = image ;
00976 }
00977 double minX(1000.0), minY(1000.0), minZ(1000.0), maxX(0.0), maxY(0.0) , maxZ(0.0) ;
00978 double averageZ = 0.0 ;
00979 cv::Mat cluster( 480,640, CV_8UC1, cv::Scalar(0) );
00980 float x0 = 0.0 , y0 = 0.0 , z = 0.0 ;
00981 int x = 0 , y = 0 ;
00982 int count = 0 ;
00983 cv::Mat result = imageMono ;
00984 for( int i = 0 ; i < cluster_cloud->points.size(); i++){
00985 z = cluster_cloud->points[i].z ;
00986 x0 = (cluster_cloud->points[i].x * fx)/z + cx ;
00987 y0 = (cluster_cloud->points[i].y * fy)/z + cy ;
00988 x = cvRound(x0) ;
00989 y = cvRound(y0) ;
00990 cluster.at<unsigned char>(y, x) = 255 ;
00991
00992
00993 if( x < minX ) minX = x ;
00994 if( y < minY ) minY = y ;
00995 if( z < minZ ) minZ = z ;
00996
00997 if( x > maxX ) maxX = x ;
00998 if( y > maxY ) maxY = y ;
00999 if( z > maxZ ) maxZ = z ;
01000
01001 averageZ += z ;
01002 }
01003
01004 averageZ = averageZ / cluster_cloud->points.size() ;
01005
01006
01007
01008
01009
01010
01011 const uchar * currentImagePtr ;
01012 for(int row = 0 ; row < currentFrame.rows; row++){
01013 currentImagePtr = currentFrame.ptr<uchar>(row) ;
01014 for(int col= 0; col < currentFrame.cols; col++){
01015 const uchar ¤tCol = currentImagePtr[col] ;
01016 if( currentCol == 255){
01017
01018 if(row > minY && row<maxY && col>minX && col<maxX){
01019 if(cloud->at(row*cloud->width + col).z > minZ && cloud->at(row*cloud->width + col).z<maxZ ){
01020
01021 dynamicImage.at<unsigned char>(row,col) = 255;
01022 count ++ ;
01023 }
01024 }
01025 }
01026 }
01027 }
01028
01029
01030
01031
01032
01033
01034
01035 cout << "count= " << count << endl ;
01036
01037
01038
01039
01040 if(count > 3000){
01041 cv::line( dynamicImage, cvPoint(maxX, maxY),cvPoint(minX, maxY),CV_RGB(255,0,0),2,CV_AA,0) ;
01042 cv::line( dynamicImage, cvPoint(minX, maxY),cvPoint(minX, minY),CV_RGB(255,0,0),2,CV_AA,0) ;
01043 cv::line( dynamicImage, cvPoint(minX, minY),cvPoint(maxX, minY),CV_RGB(255,0,0),2,CV_AA,0) ;
01044 cv::line( dynamicImage, cvPoint(maxX, minY),cvPoint(maxX, maxY),CV_RGB(255,0,0),2,CV_AA,0) ;
01045 double density = count/((maxY-minY)*(maxX-minX)) ;
01046 cout << "density = " << density << endl ;
01047
01048
01049
01050
01051
01052 cout << "The count of dynamic objects = " << count << endl ;
01053
01054 return true ;
01055
01056
01057
01058
01059 }else{
01060 return false ;
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 }
01077 pcl::PointCloud<pcl::PointXYZRGB> MovingObjectFilter::objectFromOriginalCloud(cloud_type::ConstPtr clusterCloud, cloud_type::ConstPtr cloud){
01078 double average_z = 0.0 ;
01079 for(int i = 0; i < clusterCloud->size(); i++){
01080 average_z += clusterCloud->points[i].z ;
01081 }
01082 average_z = average_z / clusterCloud->size() ;
01083 cloud_type::Ptr cluster (new cloud_type) ;
01084 cluster->points.resize(clusterCloud->size());
01085
01086 for(int i = 0; i < clusterCloud->size();i++ ){
01087 cluster->points[i].x = clusterCloud->points[i].x ;
01088 cluster->points[i].y = clusterCloud->points[i].y ;
01089 cluster->points[i].z = average_z ;
01090 cluster->points[i].b = clusterCloud->points[i].b ;
01091 cluster->points[i].g = clusterCloud->points[i].g ;
01092 cluster->points[i].r = clusterCloud->points[i].r ;
01093 }
01094 cluster->width = cluster->points.size ();
01095 cluster->height = 1;
01096 cluster->is_dense = true;
01097 pcl::PointCloud<pcl::PointXYZRGB>::Ptr hull_points (new pcl::PointCloud<pcl::PointXYZRGB> ());
01098 pcl::PointIndices::Ptr cloud_indices (new pcl::PointIndices);
01099 pcl::ConcaveHull<pcl::PointXYZRGB> hull ;
01100 hull.setInputCloud (cluster);
01101 hull.setAlpha(0.2);
01102 hull.reconstruct (*hull_points);
01103 double z_min = -0.2, z_max = 0.2;
01104 pcl::ExtractIndices<pcl::PointXYZRGB> extract;
01105 pcl::PointCloud<pcl::PointXYZRGB>::Ptr objects(new pcl::PointCloud<pcl::PointXYZRGB>);
01106
01107 if (hull.getDimension () == 2){
01108 pcl::ExtractPolygonalPrismData<pcl::PointXYZRGB> prism;
01109 prism.setInputCloud (cloud);
01110 prism.setInputPlanarHull (hull_points);
01111 prism.setHeightLimits (z_min, z_max);
01112 prism.segment (*cloud_indices);
01113 if(cloud_indices->indices.size() == 0){
01114 cout << "Cloud not find objects" << endl ;
01115
01116 }else{
01117 cout << "indices.size() = " << cloud_indices->indices.size() << endl ;
01118 }
01119 extract.setInputCloud(cloud);
01120 extract.setIndices(cloud_indices);
01121 extract.filter(*objects);
01122
01123 objects->width = objects->points.size() ;
01124 objects->height = 1 ;
01125 objects->is_dense = true ;
01126 objects->resize(objects->height * objects->width);
01127
01128
01129
01130
01131
01132 }else{
01133 PCL_ERROR ("The input cloud does not represent a planar surface.\n");
01134 }
01135 return *objects ;
01136
01137 }
01138
01139 cv::Mat MovingObjectFilter::getDepth(cloud_type::ConstPtr cloud , const cv::Mat &depthImage, float cx, float cy, float fx, float fy){
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 cout << "Enter calculating depthImage" << endl ;
01150 cv::Mat restDepth = depthImage ;
01151 float x0 = 0.0 , y0 = 0.0 , z = 0.0 ;
01152 int x = 0 , y = 0 ;
01153
01154 for( int i = 0 ; i < cloud->points.size(); i++){
01155 z = cloud->points[i].z ;
01156 x0 = (cloud->points[i].x * fx)/z + cx ;
01157 y0 = (cloud->points[i].y * fy)/z + cy ;
01158 x = cvRound(x0) ;
01159 y = cvRound(y0) ;
01160
01161
01162
01163 restDepth.at<uint16_t>(y, x) = 0 ;
01164
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 return restDepth ;
01177
01178 }
01179 void MovingObjectFilter::getImage(cloud_type::ConstPtr cloud , const cv::Mat &image, float cx, float cy, float fx, float fy){
01180
01181
01182 cv::Mat imageMono ;
01183 if(image.channels() > 1){
01184 cv::cvtColor(image, imageMono, cv::COLOR_BGR2GRAY) ;
01185 }else{
01186 imageMono = image ;
01187 }
01188
01189 cv::Mat restImage = imageMono ;
01190
01191
01192 #ifdef DEBUG_LOOP
01193 std::stringstream ss;
01194 ss << "currentImage" << num1 << ".jpg";
01195 cv::imwrite( ss.str(),restImage ) ;
01196 #endif DEBUG_LOOP
01197
01198 float x0 = 0.0 , y0 = 0.0 , z = 0.0 ;
01199 int x = 0 , y = 0 ;
01200
01201 for( int i = 0 ; i < cloud->points.size(); i++){
01202 z = cloud->points[i].z ;
01203 x0 = (cloud->points[i].x * fx)/z + cx ;
01204 y0 = (cloud->points[i].y * fy)/z + cy ;
01205 x = cvRound(x0) ;
01206 y = cvRound(y0) ;
01207 restImage.at<unsigned char>(y, x) = 255 ;
01208
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218 #ifdef DEBUG_LOOP
01219 std::stringstream ss1;
01220 ss1 << "restImage" << num1 << ".jpg";
01221 cv::imwrite( ss1.str(),restImage ) ;
01222 #endif DEBUG_LOOP
01223
01224 #ifdef VIEW_RESULT
01225 cv::namedWindow("restImage") ;
01226 cv::imshow("restImage", restImage) ;
01227 cv::waitKey(5) ;
01228 #endif VIEW_RESULT
01229
01230 #ifdef DEBUG
01231 static int num = 0 ;
01232 std::stringstream ss4;
01233 ss4 << "rest" << num << ".jpg";
01234 cv::imwrite( ss4.str(), restImage ) ;
01235 num++ ;
01236 #endif
01237 num1++ ;
01238
01239
01240
01241
01242 }
01243
01244
01245 cv::Mat MovingObjectFilter::bgrFromCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, bool bgrOrder)
01246 {
01247 cv::Mat frameBGR = cv::Mat(cloud.height,cloud.width,CV_8UC3);
01248
01249 for(unsigned int h = 0; h < cloud.height; h++)
01250 {
01251 for(unsigned int w = 0; w < cloud.width; w++)
01252 {
01253 if(bgrOrder)
01254 {
01255 frameBGR.at<cv::Vec3b>(h,w)[0] = cloud.at(h*cloud.width + w).b;
01256 frameBGR.at<cv::Vec3b>(h,w)[1] = cloud.at(h*cloud.width + w).g;
01257 frameBGR.at<cv::Vec3b>(h,w)[2] = cloud.at(h*cloud.width + w).r;
01258 }
01259 else
01260 {
01261 frameBGR.at<cv::Vec3b>(h,w)[0] = cloud.at(h*cloud.width + w).r;
01262 frameBGR.at<cv::Vec3b>(h,w)[1] = cloud.at(h*cloud.width + w).g;
01263 frameBGR.at<cv::Vec3b>(h,w)[2] = cloud.at(h*cloud.width + w).b;
01264 }
01265 }
01266 }
01267 return frameBGR;
01268 }
01269
01270
01271
01272
01273 cv::Mat MovingObjectFilter::depthFromCloud(
01274 const pcl::PointCloud<pcl::PointXYZRGB> & cloud,
01275 float & fx,
01276 float & fy,
01277 bool depth16U)
01278 {
01279 cv::Mat frameDepth = cv::Mat(cloud.height,cloud.width,depth16U?CV_16UC1:CV_32FC1);
01280 fx = 0.0f;
01281 fy = 0.0f;
01282 for(unsigned int h = 0; h < cloud.height; h++)
01283 {
01284 for(unsigned int w = 0; w < cloud.width; w++)
01285 {
01286 float depth = cloud.at(h*cloud.width + w).z;
01287 if(depth16U)
01288 {
01289 depth *= 1000.0f;
01290 unsigned short depthMM = 0;
01291 if(depth <= (float)USHRT_MAX)
01292 {
01293 depthMM = (unsigned short)depth;
01294 }
01295 frameDepth.at<unsigned short>(h,w) = depthMM;
01296 }
01297 else
01298 {
01299 frameDepth.at<float>(h,w) = depth;
01300 }
01301
01302
01303 if(fx == 0.0f &&
01304 uIsFinite(cloud.at(h*cloud.width + w).x) &&
01305 uIsFinite(depth) &&
01306 w != cloud.width/2 &&
01307 depth > 0)
01308 {
01309 fx = cloud.at(h*cloud.width + w).x / ((float(w) - float(cloud.width)/2.0f) * depth);
01310 if(depth16U)
01311 {
01312 fx*=1000.0f;
01313 }
01314 }
01315 if(fy == 0.0f &&
01316 uIsFinite(cloud.at(h*cloud.width + w).y) &&
01317 uIsFinite(depth) &&
01318 h != cloud.height/2 &&
01319 depth > 0)
01320 {
01321 fy = cloud.at(h*cloud.width + w).y / ((float(h) - float(cloud.height)/2.0f) * depth);
01322 if(depth16U)
01323 {
01324 fy*=1000.0f;
01325 }
01326 }
01327 }
01328 }
01329 return frameDepth;
01330 }
01331