moving_object_filter.cpp
Go to the documentation of this file.
00001 /*************************************************************************
00002         > File Name: moving_object_filter.cpp
00003         > Author: yincanben
00004         > Mail: yincanben@163.com
00005         > Created Time: 2015年01月09日 星期五 08时05分54秒
00006  ************************************************************************/
00007  #include "moving_object_filter.h"
00008  #include "umath.h"
00009  #include "optical_flow.h"
00010  //#define  DEBUG
00011  //#define  TIME
00012 // #define  VIEW
00013  #define  VIEW_RESULT
00014 // #define  DEBUG_LOOP
00015  //#define  DEBUG_WRITE
00016 using namespace Eigen;
00017  
00018  MovingObjectFilter::MovingObjectFilter( int argc, char**argv ):rgb_frame_id(""),depth_frame_id(""){//,result_viewer("Result"){//cloud_viewer("Moving Object Viewer"),viewer("Viewer")
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      //convert to grayscale
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      //compute the Homography
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      //OpticalFlow of ;
00062 
00063      //of.process( imageMono );
00064 
00065      //cv::imshow("current View", imageMono) ;
00066 
00067 
00068      //ROS_INFO( "Process data" ) ;
00069 
00070      pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00071      gettimeofday( &start, NULL ) ;
00072      //compute PointCloud
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      //if(!result_viewer.wasStopped()){
00082      //   result_viewer.showCloud(cloud) ;
00083      //}
00084 
00085 
00086 
00087      gettimeofday( &start, NULL ) ;
00088 
00089      // make image difference
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      //Publish depth image
00115      //std::cout << "rgb_frame_id" << rgb_frame_id << std::endl ;
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      //Publish RGB image
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      //previous_coordinate.clear() ;
00136      //current_coordinate.clear() ;
00137 
00138      restCloud = this->cloudFromDepthRGB(image, restDepth, cx, cy, fx, fy, 1.0) ;
00139 
00140      #ifdef DEBUG_WRITE
00141      pcl::PCDWriter writer ;
00142      //static int num1=0 ;
00143      std::stringstream ss1;
00144      ss1 << "restcloud_" << num1  << ".pcd" ;
00145      writer.write<pcl::PointXYZRGB>(ss1.str(), *restCloud,false) ;
00146      //num1++ ;
00147      #endif DEBUG_WRITE
00148 
00149      #ifdef View
00150      //cv::namedWindow("Image") ;
00151      //cv::imshow("Image", image) ;
00152      //cv::waitKey(1);
00153 
00154      //if(!result_viewer.wasStopped()){
00155      //   result_viewer.showCloud(restCloud->makeShared()) ;
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      //cv::namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
00171      //cv::imshow( "Display window", image );                   // Show our image inside it.
00172      //cv::waitKey(0);
00173      //rgbPub_.publish(binary_image) ;
00174      */
00175      //pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00176      //cloud = this->cloudFromDepthRGB( image, depth, cx, cy, fx, fy, 1 ) ;
00177      //this->image_separate(cloud);
00178 
00179 
00180 }
00181 
00182  void MovingObjectFilter::computeHomography(cv::Mat &grayImage){
00183 
00184      //Step 1: Detect the keypoints using ORB Detector
00185      cv::ORB orb ;
00186      std::vector<cv::KeyPoint> lastKeypoints ;
00187      std::vector<cv::KeyPoint> keypoints ;
00188 
00189      #ifdef DEBUG_WRITE
00190      //static int num1 = 0 ;
00191      //cout << "num = " << num1 << endl ;
00192      std::stringstream ss;
00193      ss << "currentImage" << num1 << ".jpg";
00194      cv::imwrite( ss.str(), grayImage ) ;
00195      //num1++ ;
00196      #endif DEBUG_WRITE
00197      
00198      //featureDetector_ ->detect( grayImage, keypoints ) ;
00199      //ROS_INFO( "The size of keypoints: %d", keypoints.size() ) ;
00200      //if( keypoints.size() == 0 )
00201      //    return ;
00202      //Step 2: Calculate descriptors (features vectors)
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      //cv::BruteForceMatcher<cv::HammingLUT> matcher ;
00213      std::vector<cv::DMatch> matches ;
00214      //matcher.match( lastDescriptors, descriptors, matches );
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          //cout << "************" << endl ;
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          //draw matches
00239 
00240 
00241          //cv::namedWindow("matches") ;
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          //imshow("matches", img_matches) ;
00244 
00245         #ifdef DEBUG_WRITE
00246         //static int num = 1 ;
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          //warp the image
00276 
00277 
00278          /*cv::Mat dst ;
00279          //cv::warpPerspective( lastImage, dst, Homography, cv::Size(lastImage.cols + grayImage.cols + lastImage.cols, lastImage.rows));
00280          cv::warpPerspective( lastImage, dst, shft*Homography, cv::Size(lastImage.cols + grayImage.cols + lastImage.cols, lastImage.rows));
00281 
00282          cv::Mat rightImage = grayImage ;
00283          rightImage.copyTo(cv::Mat( dst, cv::Rect( lastImage.cols, 0, grayImage.cols, grayImage.rows  ) )) ;
00284          //cv::namedWindow("warpImage") ;
00285          //cv::imshow("warpImage", dst) ;
00286          */
00287 
00288         #ifdef DEBUG_WRITE
00289         std::stringstream ss3;
00290         ss3 << "warpImage" << num1 << ".jpg";
00291         cv::imwrite( ss3.str(), dst ) ;
00292         //num++ ;
00293         #endif DEBUG_WRITE
00294      }
00295 
00296      lastImage = grayImage ;
00297 
00298  }
00299 
00300 
00301 
00302 void MovingObjectFilter::image_diff(const cv::Mat &currentImage, 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         //lastDepth = depth ;
00308         lastCloud = *cloud ;
00309     }else{
00310         cv::GaussianBlur( currentImage, BlurImage2, cv::Size( 11, 11 ), 0, 0 );
00311 
00312         //cv::absdiff( BlurImage2, lastImage, diff_image ) ;
00313 
00314         //Calculate the difference of image
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         //cv::Mat last = lastBlurImage ;
00319         //cv::Mat current = BlurImage2 ;
00320         lastFrame = last_frame ;
00321         currentFrame = current_frame ;
00322         threshod = 40 ;
00323         //cv::namedWindow("lastFrame") ;
00324         //cv::namedWindow("currentFrame") ;
00325         //cv::namedWindow("diffFrame") ;
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         //cout << "difference  Time1 : " << 1000*timecost << endl;
00340 
00341         //cv::namedWindow("dst") ;
00342         //cv::imshow("dst", dst) ;
00343         //cv::waitKey(1) ;
00344 
00345 
00346         //cv::Mat srcMat = cv::Mat::zeros(3,1,CV_64FC1);
00347         //cv::Mat warpMat ;
00348         cv::Point warpPt ;
00349 
00350         //MatrixXf hom(3,3) ;
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                 //cout << "homVal = " << homPtr[cols]  << endl ;
00357                 hom[rows][cols] = homPtr[cols] ;
00358             }
00359         }
00360         //MatrixXf srcMatrix(3,1) ;
00361         //MatrixXf resMatrix(3,1) ;
00362         double srcMatrix[4][2];
00363         double resMatrix[4][2];
00364         //float warpx  = 0.0 , warpy = 0.0 , warpz = 0.0 ;
00365         for( int rows=0; rows < lastImage.rows; rows++ ){
00366             for(int cols=0; cols< lastImage.cols; cols++){
00367 
00368                 //srcMat.at<double>(0,0) = cols ;
00369                 //srcMat.at<double>(1,0) = rows;
00370                 //srcMat.at<double>(2,0) = 1.0 ;
00371                 //warpMat = Homography * srcMat ;
00372                 //warpPt.x = cvRound( warpMat.at<double>(0,0) / warpMat.at<double>(2,0) ) ;
00373                 //warpPt.y = cvRound( warpMat.at<double>(1,0) / warpMat.at<double>(2,0) ) ;
00374                 //cout << "before, " << "warpPt.x= " << warpPt.x << endl;
00375                 //cout << "before, " << "warpPt.y= " << warpPt.y << endl ;
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                 //cout << "after, " << "warpPt.x= " << warpPt.x << endl;
00386                 //cout << "after, " << "warpPt.y= " << warpPt.y << endl ;
00387                 //float lastDepthValue = (float)lastDepth.at<uint16_t>( rows, cols )*0.001f ;
00388                 //cout << "The rows of depth:" << rows << " ,The cols of depth: " << cols << endl ;
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                     //double imageDiff = abs( lastBlurImage.at<unsigned char>(rows, cols) - BlurImage2.at<unsigned char>(warpPt.y ,warpPt.x));
00400 
00401                     double lastDepthValue = 0.0 ;
00402                     double depthValue = 0.0 ;
00403                     //Eigen::Vector3f v1 ;
00404                     //Eigen::Vector3f v2 ;
00405 
00406                     //cout << "After  abs" << endl;
00407                     //ROS_INFO("depth rows:%d ; cols:%d", depth.rows, depth.cols
00408                     uchar* lastFramePtr = lastFrame.ptr<uchar>(rows) ;
00409                     uchar* lastFrameCol = &lastFramePtr[cols] ;
00410 
00411                     uchar* currentFramePtr = currentFrame.ptr<uchar>(warpPt.y) ;
00412                     uchar* currentFrameCol = &currentFramePtr[warpPt.x] ;
00413 
00414                     //const uint16_t* lastDepthPtr = lastCloud.ptr<uint16_t>(cols);
00415                     //const uint16_t* currentDepthPtr = cloud
00416                     if( imageDiff > threshod ){
00417                         diffFrame.at<unsigned char>(warpPt.y ,warpPt.x) = 255 ;
00418 
00419                         //lastDepthValue = isnan( lastCloud.at( cols,rows).z) ? 20 : lastCloud.at(cols,rows).z ;
00420                         //depthValue = isnan( cloud->at(warpPt.x, warpPt.y).z) ? 20 : cloud->at(warpPt.x, warpPt.y).z ;
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                             //currentFrame.at<unsigned char>(warpPt.y ,warpPt.x) = 255 ;
00427                             //current.at<unsigned char>(warpPt.y ,warpPt.x) = 255 ;
00428                             //v1 << cloud->at(warpPt.x, warpPt.y).x , cloud->at(warpPt.x, warpPt.y).y ,cloud->at(warpPt.x, warpPt.y).z ;
00429                             //current_coordinate.push_back(v1) ;
00430 
00431                         }else if( depthValue -lastDepthValue > 0.2 && depthValue <20 ){
00432                             *lastFrameCol = 255 ;
00433                             //lastFrame.at<unsigned char>(rows, cols) = 255 ;
00434                             //last.at<unsigned char>(rows, cols) = 255 ;
00435                             //v2 << lastCloud.at( cols,rows).x , lastCloud.at( cols,rows).y , lastCloud.at( cols,rows).z ;
00436                             //previous_coordinate.push_back(v2) ;
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        // static int num = 1 ;
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         //num++ ;
00488 
00489         //cout << "difference  Time2 : " << 1000000*timecost1 << endl;
00490 
00491 
00492         //cv::imshow("lastFrame",lastFrame);
00493         //cv::waitKey(5);
00494         #ifdef VIEW
00495         cv::imshow("currentFrame",currentFrame) ;
00496         cv::waitKey(5);
00497         #endif VIEW
00498         //cv::imshow("diffFrame", diffFrame) ;
00499         //cv::waitKey(5);
00500 
00501         //if(cv::waitKey(1) > 0){
00502         //    exit(0);
00503         //}
00504 
00505         lastBlurImage = BlurImage2 ;
00506         lastCloud = *cloud ;
00507         //lastDepth = depth ;
00508         //cv::threshold( diff_image, binary_image, threshod_binary, 255, cv::THRESH_BINARY );
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     //UASSERT(depthImage.type() == CV_16UC1 || depthImage.type() == CV_32FC1);
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         //UERROR("!(x >=0 && x<depthImage.cols && y >=0 && y<depthImage.rows) cond failed! returning bad point. (x=%f (u=%d), y=%f (v=%d), cols=%d, rows=%d)",
00531         //              x,u,y,v,depthImage.cols, depthImage.rows);
00532         pt.x = pt.y = pt.z = bad_point;
00533         return pt;
00534     }
00535 
00536     bool isInMM = depthImage.type() == CV_16UC1; // is in mm?
00537 
00538 
00539     // Inspired from RGBDFrame::getGaussianMixtureDistribution() method from
00540     // https://github.com/ccny-ros-pkg/rgbdtools/blob/master/src/rgbd_frame.cpp
00541     // Window weights:
00542     //  | 1 | 2 | 1 |
00543     //  | 2 | 4 | 2 |
00544     //  | 1 | 2 | 1 |
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     //float depth = isInMM?(float)depthImage.at<uint16_t>(v,u)*0.001f:depthImage.at<float>(v,u);
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                         //float d = isInMM?(float)depthImage.at<uint16_t>(vv,uu)*0.001f:depthImage.at<float>(vv,uu);
00567                         float d = isInMM ? (float)dv*0.001f : dv ;
00568                         // ignore if not valid or depth difference is too high
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             // set window weight to center point
00586             depth *= 4.0f;
00587             sumWeights += 4.0f;
00588 
00589             // mean
00590             depth = (depth+sumDepths)/sumWeights;
00591         }
00592 
00593         // Use correct principal point from calibration
00594         cx = cx > 0.0f ? cx : float(depthImage.cols/2) - 0.5f; //cameraInfo.K.at(2)
00595         cy = cy > 0.0f ? cy : float(depthImage.rows/2) - 0.5f; //cameraInfo.K.at(5)
00596 
00597         // Fill in XYZ
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     //UASSERT(imageRgb.rows == imageDepth.rows && imageRgb.cols == imageDepth.cols);
00617     //UASSERT(!imageDepth.empty() && (imageDepth.type() == CV_16UC1 || imageDepth.type() == CV_32FC1));
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){// BGR
00626         mono = false;
00627     }else if(imageRgb.channels() == 1){ // Mono
00628         mono = true;
00629     }else{
00630         return cloud;
00631     }
00632 
00633     //cloud.header = cameraInfo.header;
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     //timeval start , end ;
00640     //gettimeofday( &start, NULL ) ;
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             //pcl::PointXYZRGB & pt = cloud->at((h/decimation)*cloud->width + (w/decimation));
00648             if(!mono){
00649                 pt.b = col[0] ;//imageRgb.at<cv::Vec3b>(h,w)[0];
00650                 pt.g = col[1] ;//imageRgb.at<cv::Vec3b>(h,w)[1];
00651                 pt.r = col[2] ;//imageRgb.at<cv::Vec3b>(h,w)[2];
00652             }else{
00653                 //unsigned char v = imageRgb.at<unsigned char>(h,w);
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 //    gettimeofday( &end, NULL ) ;
00666 //    long long time ;
00667 //    time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)  ;
00668 //    cout << "The time of calculating PointCloud = " << time << endl;
00669     //if(!result_viewer.wasStopped()){
00670     //result_viewer.showCloud(cloud) ;
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     // Step 1: Filter out NaNs from data
00680     //ros::Time last = ros::Time::now() ;
00681     /*
00682     pcl::PassThrough<pcl::PointXYZRGB> pass ;
00683     pass.setInputCloud (cloud);
00684     pass.setFilterFieldName ("z");
00685     pass.setFilterLimits (0.5, 6.0);
00686     pass.filter (*cloud_filtered);
00687     */
00688 
00689     //
00690     //pass.setInputCloud (cloud_filtered);
00691     //pass.setFilterFieldName ("x");
00692     //pass.setFilterLimits (-4.0, 4.0);
00693     //pass.setFilterLimitsNegative (true);
00694     //pass.filter (*cloud_filtered);
00695 
00696     //pass.setInputCloud (cloud_filtered);
00697     //pass.setFilterFieldName ("y");
00698     //pass.setFilterLimits (-4.0, 4.0);
00699     //pass.filter (*cloud_filtered);
00700     //
00701 
00702     // Step 2: Filter out statistical outliers*****************influence the speed
00703 
00704     //pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor ;
00705     //sor.setInputCloud(cloud_filtered) ;
00706     //sor.setMeanK(50) ;
00707     //sor.setStddevMulThresh(1.0) ;
00708     //sor.filter(*cloud_filtered) ;
00709 
00710     //Step 3: Downsample the point cloud (to save time in the next step)
00711     timeval start , end, start1, end1, start2, end2 ;
00712     long long time , time1, time2;
00713 
00714     gettimeofday( &start, NULL ) ;
00715 
00716     //spend time:50ms
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     //if(!result_viewer.wasStopped()){
00724     //    result_viewer.showCloud(cloud_filtered->makeShared()) ;
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     // Step 4: Remove the ground plane using RANSAC
00743     // Spend time : 10ms(max)
00744     pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
00745     pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
00746     pcl::SACSegmentation<pcl::PointXYZRGB> seg;
00747     //seg.setOptimizeCoefficients (true); // Optional
00748 
00749     seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);//SACMODEL_PERPENDICULAR_PLANE
00750     seg.setMethodType (pcl::SAC_RANSAC);
00751     seg.setDistanceThreshold (0.1); //10cm
00752     seg.setMaxIterations(300);//300
00753     seg.setAxis(Eigen::Vector3f(0.0, 1.0, 0.0));
00754     seg.setEpsAngle (pcl::deg2rad (8.0));//8 deg
00755 
00756     //seg.setModelType (pcl::SACMODEL_PLANE);
00757     //seg.setMethodType (pcl::SAC_RANSAC);
00758     //seg.setMaxIterations(1000);
00759     //seg.setDistanceThreshold (0.08);
00760     /*
00761     seg.setMethodType (pcl::SACMODEL_NORMAL_PARALLEL_PLANE) ;
00762     seg.setAxis(Eigen::Vector3f(0,0,1));
00763     seg.setMethodType (pcl::SAC_RANSAC);
00764     seg.setEpsAngle (0);
00765     seg.setDistanceThreshold (0.01); //1cm
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         // Step 4.1: Extract the points that lie in the ground plane
00782         extract.setIndices (inliers) ;
00783         extract.setNegative (false) ;
00784         extract.filter (*cloud_plane) ;
00785         plane += *cloud_plane ;
00786 
00787         // Step 4.2: Extract the points that are objects(i.e. are not in the ground plane)
00788         extract.setNegative (true) ;
00789         extract.filter ( *cloud_f ) ;
00790         *cloud_filtered = *cloud_f ;
00791         break ;
00792     }
00793     //if(!result_viewer.wasStopped()){
00794     //    result_viewer.showCloud(cloud_filtered->makeShared()) ;
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     //#ifdef DEBUG
00805     //std::stringstream ss3;
00806     //ss3 << "plane_" << num1  << ".pcd" ;
00807     //writer.write<pcl::PointXYZRGB>(ss3.str(), plane,false) ;
00808     //num1++ ;
00809     //#endif DEBUG
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     // Step 5: EuclideanCluster Extract the moving objects
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) ; // 4cm
00826     ec.setMinClusterSize (100) ;
00827     ec.setMaxClusterSize (50000) ;
00828     ec.setSearchMethod (tree) ;
00829     ec.setInputCloud (cloud_filtered->makeShared()) ;
00830     ec.extract (cluster_indices) ;
00831     //ros::Time now = ros::Time::now() ;
00832     //ros::Duration time = now - last ;
00833     //cout << "Time : " << time.nsec << endl;
00834 
00835     //cout << "The size of cluster_indices : " << cluster_indices.size() << endl;
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     //double minX(0.0), minY(0.0), minZ(0.0), maxX(0.0), maxY(0.0), maxZ(0.0) ;
00840     //point_type cluster_point ;
00841     //pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZRGB>);
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     //for view clusters
00849     pcl::PointCloud<pcl::PointXYZRGB>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZRGB>) ;
00850 
00851     int num_dy_object = 0;
00852     cv::Mat imageMono ;
00853     //convert to grayscale
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         //Extract the objects
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             //cout << "The size of object: " << object->size() << endl ;
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             //object->clear();
00892             //
00893             /*
00894             if(!cloud_viewer.wasStopped()){
00895                 cloud_viewer.showCloud(cloud_cluster);
00896                 num++ ;
00897                 cout << "num = "  << num << endl;
00898             }*/
00899             num_dy_object ++;
00900         }else{
00901             //*static_object += *cloud_cluster ;
00902             //continue ;
00903         }
00904         j++ ;
00905         num++ ;
00906         #ifdef DEBUG
00907         cout << "j = " << j << endl ;
00908         #endif DEBUG
00909 
00910         cloud_cluster->clear();
00911         //std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
00912     }
00913 
00914     cout << "dynamic objects:  " << num_dy_object << endl;
00915 
00916     //if(!result_viewer.wasStopped()){
00917     //    result_viewer.showCloud(cluster->makeShared()) ;
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     //cout << "The size of object =  " << object->size() << endl ;
00941 //    if(!result_viewer.wasStopped()){
00942 //      result_viewer.showCloud(dynamic_object) ;
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     //cv::Mat resultImage;
00957     //resultImage = this->bgrFromCloud( *static_object,false) ;
00958     //cv::namedWindow("resultImage");
00959     //cv::imshow("resultImage", resultImage);
00960     //cv::waitKey(1);
00961 
00962     //ros::Duration next = ros::Time::now() - now ;
00963     //cout << "next = " << next.nsec << endl ;
00964     //viewer.showCloud(cloud_cluster);
00965     //cloud_viewer->showCloud(cloud_plane) ;
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     //pcl::PointCloud<pcl::PointXYZ>  pt ;
00969     cv::Mat imageMono ;
00970     //convert to grayscale
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         //result.at<unsigned char>(y,x) = 255;
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     //cv::namedWindow("cluster") ;
01007     //cv::imshow("cluster", cluster) ;
01008     //cv::waitKey(1) ;
01009     //averageZ = averageZ / cloud->points.size()
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 &currentCol = currentImagePtr[col] ;
01016             if( currentCol == 255){
01017             //if( currentFrame.at<unsigned char>(row,col) == 255){
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                         //result.at<unsigned char>(row,col) = 255;
01021                         dynamicImage.at<unsigned char>(row,col) = 255;
01022                         count ++ ;
01023                     }
01024                 }
01025             }
01026         }
01027     }
01028 
01029 
01030     //std::stringstream ss;
01031     //ss << "clusterImage_" << num << "_" << j << ".jpg";
01032     //cv::imwrite( ss.str(), result ) ;
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         //#ifdef VIEW
01048         //cv::namedWindow("result") ;
01049         //cv::imshow("result", result) ;
01050         //cv::waitKey(5) ;
01051         //#endif VIEW
01052         cout << "The count of dynamic objects =  " << count << endl ;
01053         //if( density > 0.07){
01054         return true ;
01055         //}else{
01056         //  return false ;
01057         //}
01058 
01059     }else{
01060         return false ;
01061     }
01062 
01063     /*
01064     count ++ ;
01065     cout << "count= " << count << endl ;
01066     std::stringstream ss;
01067     ss << "Resultimage" << count << ".jpg";
01068     cv::namedWindow("cluster") ;
01069     cv::imshow("cluster", cluster) ;
01070     imwrite( ss.str(),cluster );
01071     cv::Mat new_cluster( 480,640, CV_8UC1, cv::Scalar(0) );
01072     cluster = new_cluster ;
01073     cv::waitKey(1) ;
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; // we want the points above the plane, no farther than 5 cm from the surface
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         //  if(!result_viewer.wasStopped()){
01129         //      result_viewer.showCloud(objects) ;
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     //convert to grayscale
01141     /*
01142     cv::Mat imageMono ;
01143     if(image.channels() > 1){
01144        cv::cvtColor(image, imageMono, cv::COLOR_BGR2GRAY) ;
01145     }else{
01146        imageMono = image ;
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     //cv::Mat rest( 480,640, CV_8UC1, cv::Scalar(0) );
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         //uint16_t *restPtr = restImage.ptr<uint16_t>(y) ;
01161         //uint16_t & restCol = restPtr[x] ;
01162         //restCol = 0 ;
01163         restDepth.at<uint16_t>(y, x) = 0 ;
01164         //result.at<unsigned char>(y,x) = 255;
01165     }
01166     /*
01167     for(int row = 0 ; row < rest.rows; row++){
01168         for(int col= 0; col < rest.cols; col++){
01169             if(rest.at<unsigned char>(y, x) == 255 )
01170                 restImage.at<unsigned char>(row,col) = 255;
01171         }
01172     }*/
01173     //cv::namedWindow("restCloud") ;
01174     //cv::imshow("resCloud", restDepth) ;
01175     //cv::waitKey(1) ;
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     //convert to grayscale
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     //static int num = 0 ;
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     //cv::Mat rest( 480,640, CV_8UC1, cv::Scalar(0) );
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         //result.at<unsigned char>(y,x) = 255;
01209     }
01210     /*
01211     for(int row = 0 ; row < rest.rows; row++){
01212         for(int col= 0; col < rest.cols; col++){
01213             if(rest.at<unsigned char>(y, x) == 255 )
01214                 restImage.at<unsigned char>(row,col) = 255;
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     //return restImage ;
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 // return float image in meter
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; // needed to reconstruct the cloud
01281     fy = 0.0f; // needed to reconstruct the cloud
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             // update constants
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 


micros_dynamic_objects_filter
Author(s):
autogenerated on Thu Jun 6 2019 17:55:18