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_CONVOLUTION_IMPL_HPP
00041 #define PCL_FILTERS_CONVOLUTION_IMPL_HPP
00042
00043 #include <pcl/pcl_config.h>
00044 #include <pcl/common/distances.h>
00045
00046 template <typename PointIn, typename PointOut>
00047 pcl::filters::Convolution<PointIn, PointOut>::Convolution ()
00048 : borders_policy_ (BORDERS_POLICY_IGNORE)
00049 , distance_threshold_ (std::numeric_limits<float>::infinity ())
00050 , input_ ()
00051 , kernel_ ()
00052 , half_width_ ()
00053 , kernel_width_ ()
00054 , threads_ (1)
00055 {}
00056
00057 template <typename PointIn, typename PointOut> void
00058 pcl::filters::Convolution<PointIn, PointOut>::initCompute (PointCloud<PointOut>& output)
00059 {
00060 if (borders_policy_ != BORDERS_POLICY_IGNORE &&
00061 borders_policy_ != BORDERS_POLICY_MIRROR &&
00062 borders_policy_ != BORDERS_POLICY_DUPLICATE)
00063 PCL_THROW_EXCEPTION (InitFailedException,
00064 "[pcl::filters::Convolution::initCompute] unknown borders policy.");
00065
00066 if(kernel_.size () % 2 == 0)
00067 PCL_THROW_EXCEPTION (InitFailedException,
00068 "[pcl::filters::Convolution::initCompute] convolving element width must be odd.");
00069
00070 if (distance_threshold_ != std::numeric_limits<float>::infinity ())
00071 distance_threshold_ *= static_cast<float> (kernel_.size () % 2) * distance_threshold_;
00072
00073 half_width_ = static_cast<int> (kernel_.size ()) / 2;
00074 kernel_width_ = static_cast<int> (kernel_.size () - 1);
00075
00076 if (&(*input_) != &output)
00077 {
00078 if (output.height != input_->height || output.width != input_->width)
00079 {
00080 output.resize (input_->width * input_->height);
00081 output.width = input_->width;
00082 output.height = input_->height;
00083 }
00084 }
00085 output.is_dense = input_->is_dense;
00086 }
00087
00088 template <typename PointIn, typename PointOut> inline void
00089 pcl::filters::Convolution<PointIn, PointOut>::convolveRows (PointCloudOut& output)
00090 {
00091 try
00092 {
00093 initCompute (output);
00094 switch (borders_policy_)
00095 {
00096 case BORDERS_POLICY_MIRROR : convolve_rows_mirror (output);
00097 case BORDERS_POLICY_DUPLICATE : convolve_rows_duplicate (output);
00098 case BORDERS_POLICY_IGNORE : convolve_rows (output);
00099 }
00100 }
00101 catch (InitFailedException& e)
00102 {
00103 PCL_THROW_EXCEPTION (InitFailedException,
00104 "[pcl::filters::Convolution::convolveRows] init failed " << e.what ());
00105 }
00106 }
00107
00108 template <typename PointIn, typename PointOut> inline void
00109 pcl::filters::Convolution<PointIn, PointOut>::convolveCols (PointCloudOut& output)
00110 {
00111 try
00112 {
00113 initCompute (output);
00114 switch (borders_policy_)
00115 {
00116 case BORDERS_POLICY_MIRROR : convolve_cols_mirror (output);
00117 case BORDERS_POLICY_DUPLICATE : convolve_cols_duplicate (output);
00118 case BORDERS_POLICY_IGNORE : convolve_cols (output);
00119 }
00120 }
00121 catch (InitFailedException& e)
00122 {
00123 PCL_THROW_EXCEPTION (InitFailedException,
00124 "[pcl::filters::Convolution::convolveCols] init failed " << e.what ());
00125 }
00126 }
00127
00128 template <typename PointIn, typename PointOut> inline void
00129 pcl::filters::Convolution<PointIn, PointOut>::convolve (const Eigen::ArrayXf& h_kernel,
00130 const Eigen::ArrayXf& v_kernel,
00131 PointCloud<PointOut>& output)
00132 {
00133 try
00134 {
00135 PointCloudInPtr tmp (new PointCloud<PointIn> ());
00136 setKernel (h_kernel);
00137 convolveRows (*tmp);
00138 setInputCloud (tmp);
00139 setKernel (v_kernel);
00140 convolveCols (output);
00141 }
00142 catch (InitFailedException& e)
00143 {
00144 PCL_THROW_EXCEPTION (InitFailedException,
00145 "[pcl::filters::Convolution::convolve] init failed " << e.what ());
00146 }
00147 }
00148
00149 template <typename PointIn, typename PointOut> inline void
00150 pcl::filters::Convolution<PointIn, PointOut>::convolve (PointCloud<PointOut>& output)
00151 {
00152 try
00153 {
00154 PointCloudInPtr tmp (new PointCloud<PointIn> ());
00155 convolveRows (*tmp);
00156 setInputCloud (tmp);
00157 convolveCols (output);
00158 }
00159 catch (InitFailedException& e)
00160 {
00161 PCL_THROW_EXCEPTION (InitFailedException,
00162 "[pcl::filters::Convolution::convolve] init failed " << e.what ());
00163 }
00164 }
00165
00166 template <typename PointIn, typename PointOut> inline PointOut
00167 pcl::filters::Convolution<PointIn, PointOut>::convolveOneRowDense (int i, int j)
00168 {
00169 using namespace pcl::common;
00170 PointOut result;
00171 for (int k = kernel_width_, l = i - half_width_; k > -1; --k, ++l)
00172 result+= (*input_) (l,j) * kernel_[k];
00173 return (result);
00174 }
00175
00176 template <typename PointIn, typename PointOut> inline PointOut
00177 pcl::filters::Convolution<PointIn, PointOut>::convolveOneColDense (int i, int j)
00178 {
00179 using namespace pcl::common;
00180 PointOut result;
00181 for (int k = kernel_width_, l = j - half_width_; k > -1; --k, ++l)
00182 result+= (*input_) (i,l) * kernel_[k];
00183 return (result);
00184 }
00185
00186 template <typename PointIn, typename PointOut> inline PointOut
00187 pcl::filters::Convolution<PointIn, PointOut>::convolveOneRowNonDense (int i, int j)
00188 {
00189 using namespace pcl::common;
00190 PointOut result;
00191 float weight = 0;
00192 for (int k = kernel_width_, l = i - half_width_; k > -1; --k, ++l)
00193 {
00194 if (!isFinite ((*input_) (l,j)))
00195 continue;
00196 if (pcl::squaredEuclideanDistance ((*input_) (i,j), (*input_) (l,j)) < distance_threshold_)
00197 {
00198 result+= (*input_) (l,j) * kernel_[k];
00199 weight += kernel_[k];
00200 }
00201 }
00202 if (weight == 0)
00203 result.x = result.y = result.z = std::numeric_limits<float>::quiet_NaN ();
00204 else
00205 {
00206 weight = 1.f/weight;
00207 result*= weight;
00208 }
00209 return (result);
00210 }
00211
00212 template <typename PointIn, typename PointOut> inline PointOut
00213 pcl::filters::Convolution<PointIn, PointOut>::convolveOneColNonDense (int i, int j)
00214 {
00215 using namespace pcl::common;
00216 PointOut result;
00217 float weight = 0;
00218 for (int k = kernel_width_, l = j - half_width_; k > -1; --k, ++l)
00219 {
00220 if (!isFinite ((*input_) (i,l)))
00221 continue;
00222 if (pcl::squaredEuclideanDistance ((*input_) (i,j), (*input_) (i,l)) < distance_threshold_)
00223 {
00224 result+= (*input_) (i,l) * kernel_[k];
00225 weight += kernel_[k];
00226 }
00227 }
00228 if (weight == 0)
00229 result.x = result.y = result.z = std::numeric_limits<float>::quiet_NaN ();
00230 else
00231 {
00232 weight = 1.f/weight;
00233 result*= weight;
00234 }
00235 return (result);
00236 }
00237
00238 namespace pcl
00239 {
00240 namespace filters
00241 {
00242 template<> pcl::PointXYZRGB
00243 Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::convolveOneRowDense (int i, int j)
00244 {
00245 pcl::PointXYZRGB result;
00246 float r = 0, g = 0, b = 0;
00247 for (int k = kernel_width_, l = i - half_width_; k > -1; --k, ++l)
00248 {
00249 result.x += (*input_) (l,j).x * kernel_[k];
00250 result.y += (*input_) (l,j).y * kernel_[k];
00251 result.z += (*input_) (l,j).z * kernel_[k];
00252 r += kernel_[k] * static_cast<float> ((*input_) (l,j).r);
00253 g += kernel_[k] * static_cast<float> ((*input_) (l,j).g);
00254 b += kernel_[k] * static_cast<float> ((*input_) (l,j).b);
00255 }
00256 result.r = static_cast<pcl::uint8_t> (r);
00257 result.g = static_cast<pcl::uint8_t> (g);
00258 result.b = static_cast<pcl::uint8_t> (b);
00259 return (result);
00260 }
00261
00262 template<> pcl::PointXYZRGB
00263 Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::convolveOneColDense (int i, int j)
00264 {
00265 pcl::PointXYZRGB result;
00266 float r = 0, g = 0, b = 0;
00267 for (int k = kernel_width_, l = j - half_width_; k > -1; --k, ++l)
00268 {
00269 result.x += (*input_) (i,l).x * kernel_[k];
00270 result.y += (*input_) (i,l).y * kernel_[k];
00271 result.z += (*input_) (i,l).z * kernel_[k];
00272 r += kernel_[k] * static_cast<float> ((*input_) (i,l).r);
00273 g += kernel_[k] * static_cast<float> ((*input_) (i,l).g);
00274 b += kernel_[k] * static_cast<float> ((*input_) (i,l).b);
00275 }
00276 result.r = static_cast<pcl::uint8_t> (r);
00277 result.g = static_cast<pcl::uint8_t> (g);
00278 result.b = static_cast<pcl::uint8_t> (b);
00279 return (result);
00280 }
00281
00282 template<> pcl::PointXYZRGB
00283 Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::convolveOneRowNonDense (int i, int j)
00284 {
00285 pcl::PointXYZRGB result;
00286 float weight = 0;
00287 float r = 0, g = 0, b = 0;
00288 for (int k = kernel_width_, l = i - half_width_; k > -1; --k, ++l)
00289 {
00290 if (!isFinite ((*input_) (l,j)))
00291 continue;
00292 if (pcl::squaredEuclideanDistance ((*input_) (i,j), (*input_) (l,j)) < distance_threshold_)
00293 {
00294 result.x += (*input_) (l,j).x * kernel_[k]; result.y += (*input_) (l,j).y * kernel_[k]; result.z += (*input_) (l,j).z * kernel_[k];
00295 r+= kernel_[k] * static_cast<float> ((*input_) (l,j).r);
00296 g+= kernel_[k] * static_cast<float> ((*input_) (l,j).g);
00297 b+= kernel_[k] * static_cast<float> ((*input_) (l,j).b);
00298 weight += kernel_[k];
00299 }
00300 }
00301
00302 if (weight == 0)
00303 result.x = result.y = result.z = std::numeric_limits<float>::quiet_NaN ();
00304 else
00305 {
00306 weight = 1.f/weight;
00307 r*= weight; g*= weight; b*= weight;
00308 result.x*= weight; result.y*= weight; result.z*= weight;
00309 result.r = static_cast<pcl::uint8_t> (r);
00310 result.g = static_cast<pcl::uint8_t> (g);
00311 result.b = static_cast<pcl::uint8_t> (b);
00312 }
00313 return (result);
00314 }
00315
00316 template<> pcl::PointXYZRGB
00317 Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::convolveOneColNonDense (int i, int j)
00318 {
00319 pcl::PointXYZRGB result;
00320 float weight = 0;
00321 float r = 0, g = 0, b = 0;
00322 for (int k = kernel_width_, l = j - half_width_; k > -1; --k, ++l)
00323 {
00324 if (!isFinite ((*input_) (i,l)))
00325 continue;
00326 if (pcl::squaredEuclideanDistance ((*input_) (i,j), (*input_) (i,l)) < distance_threshold_)
00327 {
00328 result.x += (*input_) (i,l).x * kernel_[k]; result.y += (*input_) (i,l).y * kernel_[k]; result.z += (*input_) (i,l).z * kernel_[k];
00329 r+= kernel_[k] * static_cast<float> ((*input_) (i,l).r);
00330 g+= kernel_[k] * static_cast<float> ((*input_) (i,l).g);
00331 b+= kernel_[k] * static_cast<float> ((*input_) (i,l).b);
00332 weight+= kernel_[k];
00333 }
00334 }
00335 if (weight == 0)
00336 result.x = result.y = result.z = std::numeric_limits<float>::quiet_NaN ();
00337 else
00338 {
00339 weight = 1.f/weight;
00340 r*= weight; g*= weight; b*= weight;
00341 result.x*= weight; result.y*= weight; result.z*= weight;
00342 result.r = static_cast<pcl::uint8_t> (r);
00343 result.g = static_cast<pcl::uint8_t> (g);
00344 result.b = static_cast<pcl::uint8_t> (b);
00345 }
00346 return (result);
00347 }
00348
00350 template<> pcl::RGB
00351 Convolution<pcl::RGB, pcl::RGB>::convolveOneRowDense (int i, int j)
00352 {
00353 pcl::RGB result;
00354 float r = 0, g = 0, b = 0;
00355 for (int k = kernel_width_, l = i - half_width_; k > -1; --k, ++l)
00356 {
00357 r += kernel_[k] * static_cast<float> ((*input_) (l,j).r);
00358 g += kernel_[k] * static_cast<float> ((*input_) (l,j).g);
00359 b += kernel_[k] * static_cast<float> ((*input_) (l,j).b);
00360 }
00361 result.r = static_cast<pcl::uint8_t> (r);
00362 result.g = static_cast<pcl::uint8_t> (g);
00363 result.b = static_cast<pcl::uint8_t> (b);
00364 return (result);
00365 }
00366
00367 template<> pcl::RGB
00368 Convolution<pcl::RGB, pcl::RGB>::convolveOneColDense (int i, int j)
00369 {
00370 pcl::RGB result;
00371 float r = 0, g = 0, b = 0;
00372 for (int k = kernel_width_, l = j - half_width_; k > -1; --k, ++l)
00373 {
00374 r += kernel_[k] * static_cast<float> ((*input_) (i,l).r);
00375 g += kernel_[k] * static_cast<float> ((*input_) (i,l).g);
00376 b += kernel_[k] * static_cast<float> ((*input_) (i,l).b);
00377 }
00378 result.r = static_cast<pcl::uint8_t> (r);
00379 result.g = static_cast<pcl::uint8_t> (g);
00380 result.b = static_cast<pcl::uint8_t> (b);
00381 return (result);
00382 }
00383
00384 template<> pcl::RGB
00385 Convolution<pcl::RGB, pcl::RGB>::convolveOneRowNonDense (int i, int j)
00386 {
00387 return (convolveOneRowDense (i,j));
00388 }
00389
00390 template<> pcl::RGB
00391 Convolution<pcl::RGB, pcl::RGB>::convolveOneColNonDense (int i, int j)
00392 {
00393 return (convolveOneColDense (i,j));
00394 }
00395
00396 template<> void
00397 Convolution<pcl::RGB, pcl::RGB>::makeInfinite (pcl::RGB& p)
00398 {
00399 p.r = 0; p.g = 0; p.b = 0;
00400 }
00401 }
00402 }
00403
00404 template <typename PointIn, typename PointOut> void
00405 pcl::filters::Convolution<PointIn, PointOut>::convolve_rows (PointCloudOut& output)
00406 {
00407 using namespace pcl::common;
00408
00409 int width = input_->width;
00410 int height = input_->height;
00411 int last = input_->width - half_width_;
00412 if (input_->is_dense)
00413 {
00414 #ifdef _OPENMP
00415 #pragma omp parallel for shared (output, last) num_threads (threads_)
00416 #endif
00417 for(int j = 0; j < height; ++j)
00418 {
00419 for (int i = 0; i < half_width_; ++i)
00420 makeInfinite (output (i,j));
00421
00422 for (int i = half_width_; i < last; ++i)
00423 output (i,j) = convolveOneRowDense (i,j);
00424
00425 for (int i = last; i < width; ++i)
00426 makeInfinite (output (i,j));
00427 }
00428 }
00429 else
00430 {
00431 #ifdef _OPENMP
00432 #pragma omp parallel for shared (output, last) num_threads (threads_)
00433 #endif
00434 for(int j = 0; j < height; ++j)
00435 {
00436 for (int i = 0; i < half_width_; ++i)
00437 makeInfinite (output (i,j));
00438
00439 for (int i = half_width_; i < last; ++i)
00440 output (i,j) = convolveOneRowNonDense (i,j);
00441
00442 for (int i = last; i < width; ++i)
00443 makeInfinite (output (i,j));
00444 }
00445 }
00446 }
00447
00448 template <typename PointIn, typename PointOut> void
00449 pcl::filters::Convolution<PointIn, PointOut>::convolve_rows_duplicate (PointCloudOut& output)
00450 {
00451 using namespace pcl::common;
00452
00453 int width = input_->width;
00454 int height = input_->height;
00455 int last = input_->width - half_width_;
00456 int w = last - 1;
00457 if (input_->is_dense)
00458 {
00459 #ifdef _OPENMP
00460 #pragma omp parallel for shared (output, last) num_threads (threads_)
00461 #endif
00462 for(int j = 0; j < height; ++j)
00463 {
00464 for (int i = half_width_; i < last; ++i)
00465 output (i,j) = convolveOneRowDense (i,j);
00466
00467 for (int i = last; i < width; ++i)
00468 output (i,j) = output (w, j);
00469
00470 for (int i = 0; i < half_width_; ++i)
00471 output (i,j) = output (half_width_, j);
00472 }
00473 }
00474 else
00475 {
00476 #ifdef _OPENMP
00477 #pragma omp parallel for shared (output, last) num_threads (threads_)
00478 #endif
00479 for(int j = 0; j < height; ++j)
00480 {
00481 for (int i = half_width_; i < last; ++i)
00482 output (i,j) = convolveOneRowNonDense (i,j);
00483
00484 for (int i = last; i < width; ++i)
00485 output (i,j) = output (w, j);
00486
00487 for (int i = 0; i < half_width_; ++i)
00488 output (i,j) = output (half_width_, j);
00489 }
00490 }
00491 }
00492
00493 template <typename PointIn, typename PointOut> void
00494 pcl::filters::Convolution<PointIn, PointOut>::convolve_rows_mirror (PointCloudOut& output)
00495 {
00496 using namespace pcl::common;
00497
00498 int width = input_->width;
00499 int height = input_->height;
00500 int last = input_->width - half_width_;
00501 int w = last - 1;
00502 if (input_->is_dense)
00503 {
00504 #ifdef _OPENMP
00505 #pragma omp parallel for shared (output, last) num_threads (threads_)
00506 #endif
00507 for(int j = 0; j < height; ++j)
00508 {
00509 for (int i = half_width_; i < last; ++i)
00510 output (i,j) = convolveOneRowDense (i,j);
00511
00512 for (int i = last, l = 0; i < width; ++i, ++l)
00513 output (i,j) = output (w-l, j);
00514
00515 for (int i = 0; i < half_width_; ++i)
00516 output (i,j) = output (half_width_+1-i, j);
00517 }
00518 }
00519 else
00520 {
00521 #ifdef _OPENMP
00522 #pragma omp parallel for shared (output, last) num_threads (threads_)
00523 #endif
00524 for(int j = 0; j < height; ++j)
00525 {
00526 for (int i = half_width_; i < last; ++i)
00527 output (i,j) = convolveOneRowNonDense (i,j);
00528
00529 for (int i = last, l = 0; i < width; ++i, ++l)
00530 output (i,j) = output (w-l, j);
00531
00532 for (int i = 0; i < half_width_; ++i)
00533 output (i,j) = output (half_width_+1-i, j);
00534 }
00535 }
00536 }
00537
00538 template <typename PointIn, typename PointOut> void
00539 pcl::filters::Convolution<PointIn, PointOut>::convolve_cols (PointCloudOut& output)
00540 {
00541 using namespace pcl::common;
00542
00543 int width = input_->width;
00544 int height = input_->height;
00545 int last = input_->height - half_width_;
00546 if (input_->is_dense)
00547 {
00548 #ifdef _OPENMP
00549 #pragma omp parallel for shared (output, last) num_threads (threads_)
00550 #endif
00551 for(int i = 0; i < width; ++i)
00552 {
00553 for (int j = 0; j < half_width_; ++j)
00554 makeInfinite (output (i,j));
00555
00556 for (int j = half_width_; j < last; ++j)
00557 output (i,j) = convolveOneColDense (i,j);
00558
00559 for (int j = last; j < height; ++j)
00560 makeInfinite (output (i,j));
00561 }
00562 }
00563 else
00564 {
00565 #ifdef _OPENMP
00566 #pragma omp parallel for shared (output, last) num_threads (threads_)
00567 #endif
00568 for(int i = 0; i < width; ++i)
00569 {
00570 for (int j = 0; j < half_width_; ++j)
00571 makeInfinite (output (i,j));
00572
00573 for (int j = half_width_; j < last; ++j)
00574 output (i,j) = convolveOneColNonDense (i,j);
00575
00576 for (int j = last; j < height; ++j)
00577 makeInfinite (output (i,j));
00578 }
00579 }
00580 }
00581
00582 template <typename PointIn, typename PointOut> void
00583 pcl::filters::Convolution<PointIn, PointOut>::convolve_cols_duplicate (PointCloudOut& output)
00584 {
00585 using namespace pcl::common;
00586
00587 int width = input_->width;
00588 int height = input_->height;
00589 int last = input_->height - half_width_;
00590 int h = last -1;
00591 if (input_->is_dense)
00592 {
00593 #ifdef _OPENMP
00594 #pragma omp parallel for shared (output, last) num_threads (threads_)
00595 #endif
00596 for(int i = 0; i < width; ++i)
00597 {
00598 for (int j = half_width_; j < last; ++j)
00599 output (i,j) = convolveOneColDense (i,j);
00600
00601 for (int j = last; j < height; ++j)
00602 output (i,j) = output (i,h);
00603
00604 for (int j = 0; j < half_width_; ++j)
00605 output (i,j) = output (i, half_width_);
00606 }
00607 }
00608 else
00609 {
00610 #ifdef _OPENMP
00611 #pragma omp parallel for shared (output, last) num_threads (threads_)
00612 #endif
00613 for(int i = 0; i < width; ++i)
00614 {
00615 for (int j = half_width_; j < last; ++j)
00616 output (i,j) = convolveOneColNonDense (i,j);
00617
00618 for (int j = last; j < height; ++j)
00619 output (i,j) = output (i,h);
00620
00621 for (int j = 0; j < half_width_; ++j)
00622 output (i,j) = output (i,half_width_);
00623 }
00624 }
00625 }
00626
00627 template <typename PointIn, typename PointOut> void
00628 pcl::filters::Convolution<PointIn, PointOut>::convolve_cols_mirror (PointCloudOut& output)
00629 {
00630 using namespace pcl::common;
00631
00632 int width = input_->width;
00633 int height = input_->height;
00634 int last = input_->height - half_width_;
00635 int h = last -1;
00636 if (input_->is_dense)
00637 {
00638 #ifdef _OPENMP
00639 #pragma omp parallel for shared (output, last) num_threads (threads_)
00640 #endif
00641 for(int i = 0; i < width; ++i)
00642 {
00643 for (int j = half_width_; j < last; ++j)
00644 output (i,j) = convolveOneColDense (i,j);
00645
00646 for (int j = last, l = 0; j < height; ++j, ++l)
00647 output (i,j) = output (i,h-l);
00648
00649 for (int j = 0; j < half_width_; ++j)
00650 output (i,j) = output (i, half_width_+1-j);
00651 }
00652 }
00653 else
00654 {
00655 #ifdef _OPENMP
00656 #pragma omp parallel for shared (output, last) num_threads (threads_)
00657 #endif
00658 for(int i = 0; i < width; ++i)
00659 {
00660 for (int j = half_width_; j < last; ++j)
00661 output (i,j) = convolveOneColNonDense (i,j);
00662
00663 for (int j = last, l = 0; j < height; ++j, ++l)
00664 output (i,j) = output (i,h-l);
00665
00666 for (int j = 0; j < half_width_; ++j)
00667 output (i,j) = output (i,half_width_+1-j);
00668 }
00669 }
00670 }
00671
00672 #endif //PCL_FILTERS_CONVOLUTION_IMPL_HPP