00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 #ifndef PCL_FILTERS_IMPL_PYRAMID_HPP
00041 #define PCL_FILTERS_IMPL_PYRAMID_HPP
00042 
00043 template <typename PointT> bool
00044 pcl::filters::Pyramid<PointT>::initCompute ()
00045 {
00046   if (!input_->isOrganized ())
00047   {
00048     PCL_ERROR ("[pcl::fileters::%s::initCompute] Number of levels should be at least 2!", getClassName ().c_str ());
00049     return (false);
00050   }
00051   
00052   if (levels_ < 2)
00053   {
00054     PCL_ERROR ("[pcl::fileters::%s::initCompute] Number of levels should be at least 2!", getClassName ().c_str ());
00055     return (false);
00056   }
00057 
00058   
00059   
00060   
00061   
00062   if (levels_ > 4)
00063   {
00064     PCL_ERROR ("[pcl::fileters::%s::initCompute] Number of levels should not exceed 4!", getClassName ().c_str ());
00065     return (false);
00066   }
00067   
00068   if (large_)
00069   {
00070     Eigen::VectorXf k (5);
00071     k << 1.f/16.f, 1.f/4.f, 3.f/8.f, 1.f/4.f, 1.f/16.f;
00072     kernel_ = k * k.transpose ();
00073     if (threshold_ != std::numeric_limits<float>::infinity ())
00074       threshold_ *= 2 * threshold_;
00075 
00076   }
00077   else
00078   {
00079     Eigen::VectorXf k (3);
00080     k << 1.f/4.f, 1.f/2.f, 1.f/4.f;
00081     kernel_ = k * k.transpose ();
00082     if (threshold_ != std::numeric_limits<float>::infinity ())
00083       threshold_ *= threshold_;
00084   }
00085   
00086   return (true);
00087 }
00088 
00089 template <typename PointT> void
00090 pcl::filters::Pyramid<PointT>::compute (std::vector<PointCloudPtr>& output)
00091 {
00092   std::cout << "compute" << std::endl;
00093   if (!initCompute ())
00094   {
00095     PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
00096     return;
00097   }
00098 
00099   int kernel_rows = static_cast<int> (kernel_.rows ());
00100   int kernel_cols = static_cast<int> (kernel_.cols ());
00101   int kernel_center_x = kernel_cols / 2;
00102   int kernel_center_y = kernel_rows / 2;
00103 
00104   output.resize (levels_ + 1);
00105   output[0].reset (new pcl::PointCloud<PointT>);
00106   *(output[0]) = *input_;
00107 
00108   if (input_->is_dense)
00109   {
00110     for (int l = 1; l <= levels_; ++l)
00111     {
00112       output[l].reset (new pcl::PointCloud<PointT> (output[l-1]->width/2, output[l-1]->height/2));
00113       const PointCloud<PointT> &previous = *output[l-1];
00114       PointCloud<PointT> &next = *output[l];
00115 #ifdef _OPENMP
00116 #pragma omp parallel for shared (next) num_threads(threads_)
00117 #endif
00118       for(int i=0; i < next.height; ++i)
00119       {
00120         for(int j=0; j < next.width; ++j)
00121         {
00122           for(int m=0; m < kernel_rows; ++m)
00123           {
00124             int mm = kernel_rows - 1 - m;      
00125             for(int n=0; n < kernel_cols; ++n) 
00126             {
00127               int nn = kernel_cols - 1 - n;
00128 
00129               int ii = 2*i + (m - kernel_center_y);
00130               int jj = 2*j + (n - kernel_center_x);
00131               
00132               if (ii < 0) ii = 0;
00133               if (ii >= previous.height) ii = previous.height - 1;
00134               if (jj < 0) jj = 0;
00135               if (jj >= previous.width) jj = previous.width - 1;
00136               next.at (j,i) += previous.at (jj,ii) * kernel_ (mm,nn);
00137             }
00138           }
00139         }
00140       }
00141     }
00142   }
00143   else
00144   {
00145     for (int l = 1; l <= levels_; ++l)
00146     {
00147       output[l].reset (new pcl::PointCloud<PointT> (output[l-1]->width/2, output[l-1]->height/2));
00148       const PointCloud<PointT> &previous = *output[l-1];
00149       PointCloud<PointT> &next = *output[l];
00150 #ifdef _OPENMP
00151 #pragma omp parallel for shared (next) num_threads(threads_)
00152 #endif
00153       for(int i=0; i < next.height; ++i)
00154       {
00155         for(int j=0; j < next.width; ++j)
00156         {
00157           float weight = 0;
00158           for(int m=0; m < kernel_rows; ++m)
00159           {
00160             int mm = kernel_rows - 1 - m;
00161             for(int n=0; n < kernel_cols; ++n)
00162             {
00163               int nn = kernel_cols - 1 - n;
00164               int ii = 2*i + (m - kernel_center_y);
00165               int jj = 2*j + (n - kernel_center_x);
00166               if (ii < 0) ii = 0;
00167               if (ii >= previous.height) ii = previous.height - 1;
00168               if (jj < 0) jj = 0;
00169               if (jj >= previous.width) jj = previous.width - 1;
00170               if (!isFinite (previous.at (jj,ii)))
00171                 continue;
00172               if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
00173               {
00174                 next.at (j,i) += previous.at (jj,ii).x * kernel_ (mm,nn);
00175                 weight+= kernel_ (mm,nn);
00176               }
00177             }
00178           }
00179           if (weight == 0)
00180             nullify (next.at (j,i));
00181           else
00182           {
00183             weight = 1.f/weight;
00184             next.at (j,i)*= weight;
00185           }
00186         }
00187       }
00188     }
00189   }    
00190 }
00191 
00192 namespace pcl
00193 {
00194   namespace filters
00195   {
00196     template <> void 
00197     Pyramid<pcl::PointXYZRGB>::compute (std::vector<Pyramid<pcl::PointXYZRGB>::PointCloudPtr> &output)
00198     {
00199       std::cout << "PointXYZRGB" << std::endl;
00200       if (!initCompute ())
00201       {
00202         PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
00203         return;
00204       }
00205       
00206       int kernel_rows = static_cast<int> (kernel_.rows ());
00207       int kernel_cols = static_cast<int> (kernel_.cols ());
00208       int kernel_center_x = kernel_cols / 2;
00209       int kernel_center_y = kernel_rows / 2;
00210 
00211       output.resize (levels_ + 1);
00212       output[0].reset (new pcl::PointCloud<pcl::PointXYZRGB>);
00213       *(output[0]) = *input_;
00214 
00215       if (input_->is_dense)
00216       {
00217         for (int l = 1; l <= levels_; ++l)
00218         {
00219           output[l].reset (new pcl::PointCloud<pcl::PointXYZRGB> (output[l-1]->width/2, output[l-1]->height/2));
00220           const PointCloud<pcl::PointXYZRGB> &previous = *output[l-1];
00221           PointCloud<pcl::PointXYZRGB> &next = *output[l];
00222 #ifdef _OPENMP
00223 #pragma omp parallel for shared (next) num_threads(threads_)
00224 #endif
00225           for(int i=0; i < next.height; ++i)              
00226           {
00227             for(int j=0; j < next.width; ++j)          
00228             {
00229               float r = 0, g = 0, b = 0;
00230               for(int m=0; m < kernel_rows; ++m)     
00231               {
00232                 int mm = kernel_rows - 1 - m;      
00233                 for(int n=0; n < kernel_cols; ++n) 
00234                 {
00235                   int nn = kernel_cols - 1 - n;  
00236                   
00237                   int ii = 2*i + (m - kernel_center_y);
00238                   int jj = 2*j + (n - kernel_center_x);
00239                   
00240                   
00241                   if (ii < 0) ii = 0;
00242                   if (ii >= previous.height) ii = previous.height - 1;
00243                   if (jj < 0) jj = 0;
00244                   if (jj >= previous.width) jj = previous.width - 1;
00245                   next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
00246                   next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
00247                   next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
00248                   b += previous.at (jj,ii).b * kernel_ (mm,nn);
00249                   g += previous.at (jj,ii).g * kernel_ (mm,nn);
00250                   r += previous.at (jj,ii).r * kernel_ (mm,nn);
00251                 }
00252               }
00253               next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00254               next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00255               next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00256             }
00257           }
00258         }
00259       }
00260       else
00261       {
00262         for (int l = 1; l <= levels_; ++l)
00263         {
00264           output[l].reset (new pcl::PointCloud<pcl::PointXYZRGB> (output[l-1]->width/2, output[l-1]->height/2));
00265           const PointCloud<pcl::PointXYZRGB> &previous = *output[l-1];
00266           PointCloud<pcl::PointXYZRGB> &next = *output[l];
00267 #ifdef _OPENMP
00268 #pragma omp parallel for shared (next) num_threads(threads_)
00269 #endif
00270           for(int i=0; i < next.height; ++i)
00271           {
00272             for(int j=0; j < next.width; ++j)
00273             {
00274               float weight = 0;
00275               float r = 0, g = 0, b = 0;
00276               for(int m=0; m < kernel_rows; ++m)
00277               {
00278                 int mm = kernel_rows - 1 - m;
00279                 for(int n=0; n < kernel_cols; ++n)
00280                 {
00281                   int nn = kernel_cols - 1 - n;
00282                   int ii = 2*i + (m - kernel_center_y);
00283                   int jj = 2*j + (n - kernel_center_x);
00284                   if (ii < 0) ii = 0;
00285                   if (ii >= previous.height) ii = previous.height - 1;
00286                   if (jj < 0) jj = 0;
00287                   if (jj >= previous.width) jj = previous.width - 1;
00288                   if (!isFinite (previous.at (jj,ii)))
00289                     continue;
00290                   if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
00291                   {
00292                     next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
00293                     next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
00294                     next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
00295                     b += previous.at (jj,ii).b * kernel_ (mm,nn);
00296                     g += previous.at (jj,ii).g * kernel_ (mm,nn);
00297                     r += previous.at (jj,ii).r * kernel_ (mm,nn);
00298                     weight+= kernel_ (mm,nn);
00299                   }
00300                 }
00301               }
00302               if (weight == 0)
00303                 nullify (next.at (j,i));
00304               else
00305               {
00306                 weight = 1.f/weight;
00307                 r*= weight; g*= weight; b*= weight;
00308                 next.at (j,i).x*= weight; next.at (j,i).y*= weight; next.at (j,i).z*= weight;
00309                 next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00310                 next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00311                 next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00312               }
00313             }
00314           }
00315         }
00316       }    
00317     }
00318     
00319     template <> void 
00320     Pyramid<pcl::PointXYZRGBA>::compute (std::vector<Pyramid<pcl::PointXYZRGBA>::PointCloudPtr> &output)
00321     {
00322       std::cout << "PointXYZRGBA" << std::endl;
00323       if (!initCompute ())
00324       {
00325         PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
00326         return;
00327       }
00328       
00329       int kernel_rows = static_cast<int> (kernel_.rows ());
00330       int kernel_cols = static_cast<int> (kernel_.cols ());
00331       int kernel_center_x = kernel_cols / 2;
00332       int kernel_center_y = kernel_rows / 2;
00333 
00334       output.resize (levels_ + 1);
00335       output[0].reset (new pcl::PointCloud<pcl::PointXYZRGBA>);
00336       *(output[0]) = *input_;
00337 
00338       if (input_->is_dense)
00339       {
00340         for (int l = 1; l <= levels_; ++l)
00341         {
00342           output[l].reset (new pcl::PointCloud<pcl::PointXYZRGBA> (output[l-1]->width/2, output[l-1]->height/2));
00343           const PointCloud<pcl::PointXYZRGBA> &previous = *output[l-1];
00344           PointCloud<pcl::PointXYZRGBA> &next = *output[l];
00345 #ifdef _OPENMP
00346 #pragma omp parallel for shared (next) num_threads(threads_)
00347 #endif
00348           for(int i=0; i < next.height; ++i)              
00349           {
00350             for(int j=0; j < next.width; ++j)          
00351             {
00352               float r = 0, g = 0, b = 0, a = 0;
00353               for(int m=0; m < kernel_rows; ++m)     
00354               {
00355                 int mm = kernel_rows - 1 - m;      
00356                 for(int n=0; n < kernel_cols; ++n) 
00357                 {
00358                   int nn = kernel_cols - 1 - n;  
00359                   
00360                   int ii = 2*i + (m - kernel_center_y);
00361                   int jj = 2*j + (n - kernel_center_x);
00362                   
00363                   
00364                   if (ii < 0) ii = 0;
00365                   if (ii >= previous.height) ii = previous.height - 1;
00366                   if (jj < 0) jj = 0;
00367                   if (jj >= previous.width) jj = previous.width - 1;
00368                   next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
00369                   next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
00370                   next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
00371                   b += previous.at (jj,ii).b * kernel_ (mm,nn);
00372                   g += previous.at (jj,ii).g * kernel_ (mm,nn);
00373                   r += previous.at (jj,ii).r * kernel_ (mm,nn);
00374                   a += previous.at (jj,ii).a * kernel_ (mm,nn);
00375                 }
00376               }
00377               next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00378               next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00379               next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00380               next.at (j,i).a = static_cast<pcl::uint8_t> (a);
00381             }
00382           }
00383         }
00384       }
00385       else
00386       {
00387         for (int l = 1; l <= levels_; ++l)
00388         {
00389           output[l].reset (new pcl::PointCloud<pcl::PointXYZRGBA> (output[l-1]->width/2, output[l-1]->height/2));
00390           const PointCloud<pcl::PointXYZRGBA> &previous = *output[l-1];
00391           PointCloud<pcl::PointXYZRGBA> &next = *output[l];
00392 #ifdef _OPENMP
00393 #pragma omp parallel for shared (next) num_threads(threads_)
00394 #endif
00395           for(int i=0; i < next.height; ++i)
00396           {
00397             for(int j=0; j < next.width; ++j)
00398             {
00399               float weight = 0;
00400               float r = 0, g = 0, b = 0, a = 0;
00401               for(int m=0; m < kernel_rows; ++m)
00402               {
00403                 int mm = kernel_rows - 1 - m;
00404                 for(int n=0; n < kernel_cols; ++n)
00405                 {
00406                   int nn = kernel_cols - 1 - n;
00407                   int ii = 2*i + (m - kernel_center_y);
00408                   int jj = 2*j + (n - kernel_center_x);
00409                   if (ii < 0) ii = 0;
00410                   if (ii >= previous.height) ii = previous.height - 1;
00411                   if (jj < 0) jj = 0;
00412                   if (jj >= previous.width) jj = previous.width - 1;
00413                   if (!isFinite (previous.at (jj,ii)))
00414                     continue;
00415                   if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
00416                   {
00417                     next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
00418                     next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
00419                     next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
00420                     b += previous.at (jj,ii).b * kernel_ (mm,nn);
00421                     g += previous.at (jj,ii).g * kernel_ (mm,nn);
00422                     r += previous.at (jj,ii).r * kernel_ (mm,nn);
00423                     a += previous.at (jj,ii).a * kernel_ (mm,nn);
00424                     weight+= kernel_ (mm,nn);
00425                   }
00426                 }
00427               }
00428               if (weight == 0)
00429                 nullify (next.at (j,i));
00430               else
00431               {
00432                 weight = 1.f/weight;
00433                 r*= weight; g*= weight; b*= weight; a*= weight;
00434                 next.at (j,i).x*= weight; next.at (j,i).y*= weight; next.at (j,i).z*= weight;
00435                 next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00436                 next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00437                 next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00438                 next.at (j,i).a = static_cast<pcl::uint8_t> (a);
00439               }
00440             }
00441           }
00442         }
00443       }    
00444     }
00445 
00446     template<> void
00447     Pyramid<pcl::RGB>::nullify (pcl::RGB& p)
00448     {
00449       p.r = 0; p.g = 0; p.b = 0;
00450     }    
00451 
00452     template <> void 
00453     Pyramid<pcl::RGB>::compute (std::vector<Pyramid<pcl::RGB>::PointCloudPtr> &output)
00454     {
00455       std::cout << "RGB" << std::endl;
00456       if (!initCompute ())
00457       {
00458         PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
00459         return;
00460       }
00461       
00462       int kernel_rows = static_cast<int> (kernel_.rows ());
00463       int kernel_cols = static_cast<int> (kernel_.cols ());
00464       int kernel_center_x = kernel_cols / 2;
00465       int kernel_center_y = kernel_rows / 2;
00466 
00467       output.resize (levels_ + 1);
00468       output[0].reset (new pcl::PointCloud<pcl::RGB>);
00469       *(output[0]) = *input_;
00470 
00471       if (input_->is_dense)
00472       {
00473         for (int l = 1; l <= levels_; ++l)
00474         {
00475           output[l].reset (new pcl::PointCloud<pcl::RGB> (output[l-1]->width/2, output[l-1]->height/2));
00476           const PointCloud<pcl::RGB> &previous = *output[l-1];
00477           PointCloud<pcl::RGB> &next = *output[l];
00478 #ifdef _OPENMP
00479 #pragma omp parallel for shared (next) num_threads(threads_)
00480 #endif
00481           for(int i=0; i < next.height; ++i)
00482           {
00483             for(int j=0; j < next.width; ++j)
00484             {
00485               float r = 0, g = 0, b = 0;
00486               for(int m=0; m < kernel_rows; ++m)
00487               {
00488                 int mm = kernel_rows - 1 - m;
00489                 for(int n=0; n < kernel_cols; ++n)
00490                 {
00491                   int nn = kernel_cols - 1 - n;
00492                   int ii = 2*i + (m - kernel_center_y);
00493                   int jj = 2*j + (n - kernel_center_x);
00494                   if (ii < 0) ii = 0;
00495                   if (ii >= previous.height) ii = previous.height - 1;
00496                   if (jj < 0) jj = 0;
00497                   if (jj >= previous.width) jj = previous.width - 1;
00498                   b += previous.at (jj,ii).b * kernel_ (mm,nn);
00499                   g += previous.at (jj,ii).g * kernel_ (mm,nn);
00500                   r += previous.at (jj,ii).r * kernel_ (mm,nn);
00501                 }
00502               }
00503               next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00504               next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00505               next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00506             }
00507           }
00508         }
00509       }
00510       else
00511       {
00512         for (int l = 1; l <= levels_; ++l)
00513         {
00514           output[l].reset (new pcl::PointCloud<pcl::RGB> (output[l-1]->width/2, output[l-1]->height/2));
00515           const PointCloud<pcl::RGB> &previous = *output[l-1];
00516           PointCloud<pcl::RGB> &next = *output[l];
00517 #ifdef _OPENMP
00518 #pragma omp parallel for shared (next) num_threads(threads_)
00519 #endif
00520           for(int i=0; i < next.height; ++i)
00521           {
00522             for(int j=0; j < next.width; ++j)
00523             {
00524               float weight = 0;
00525               float r = 0, g = 0, b = 0;
00526               for(int m=0; m < kernel_rows; ++m)
00527               {
00528                 int mm = kernel_rows - 1 - m;
00529                 for(int n=0; n < kernel_cols; ++n)
00530                 {
00531                   int nn = kernel_cols - 1 - n;
00532                   int ii = 2*i + (m - kernel_center_y);
00533                   int jj = 2*j + (n - kernel_center_x);
00534                   if (ii < 0) ii = 0;
00535                   if (ii >= previous.height) ii = previous.height - 1;
00536                   if (jj < 0) jj = 0;
00537                   if (jj >= previous.width) jj = previous.width - 1;
00538                   if (!isFinite (previous.at (jj,ii)))
00539                     continue;
00540                   if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
00541                   {
00542                     b += previous.at (jj,ii).b * kernel_ (mm,nn);
00543                     g += previous.at (jj,ii).g * kernel_ (mm,nn);
00544                     r += previous.at (jj,ii).r * kernel_ (mm,nn);
00545                     weight+= kernel_ (mm,nn);
00546                   }
00547                 }
00548               }
00549               if (weight == 0)
00550                 nullify (next.at (j,i));
00551               else
00552               {
00553                 weight = 1.f/weight;
00554                 r*= weight; g*= weight; b*= weight;
00555                 next.at (j,i).b = static_cast<pcl::uint8_t> (b);
00556                 next.at (j,i).g = static_cast<pcl::uint8_t> (g);
00557                 next.at (j,i).r = static_cast<pcl::uint8_t> (r);
00558               }
00559             }
00560           }
00561         }
00562       }    
00563     }
00564 
00565   }
00566 }
00567 
00568 #endif