Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
integral_image2D.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: integral_image2D.hpp 4702 2012-02-23 09:39:33Z gedikli $
00037  */
00038 
00039 #ifndef PCL_INTEGRAL_IMAGE2D_IMPL_H_
00040 #define PCL_INTEGRAL_IMAGE2D_IMPL_H_
00041 
00042 #include <cstddef>
00043 
00045 template <typename DataType, unsigned Dimension> void
00046 pcl::IntegralImage2D<DataType, Dimension>::setSecondOrderComputation (bool compute_second_order_integral_images)
00047 {
00048   compute_second_order_integral_images_ = compute_second_order_integral_images;
00049 }
00050 
00052 template <typename DataType, unsigned Dimension> void
00053 pcl::IntegralImage2D<DataType, Dimension>::setInput (const DataType * data, unsigned width,unsigned height, unsigned element_stride, unsigned row_stride)
00054 {
00055   if ((width + 1) * (height + 1) > first_order_integral_image_.size () )
00056   {
00057     width_  = width;
00058     height_ = height;
00059     first_order_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00060     finite_values_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00061     if (compute_second_order_integral_images_)
00062       second_order_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00063   }
00064   computeIntegralImages (data, row_stride, element_stride);
00065 }
00066 
00068 template <typename DataType, unsigned Dimension> typename pcl::IntegralImage2D<DataType, Dimension>::ElementType
00069 pcl::IntegralImage2D<DataType, Dimension>::getFirstOrderSum (
00070     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00071 {
00072   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00073   const unsigned upper_right_idx     = upper_left_idx + width;
00074   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00075   const unsigned lower_right_idx     = lower_left_idx + width;
00076 
00077   return (first_order_integral_image_[lower_right_idx] + first_order_integral_image_[upper_left_idx]  -
00078           first_order_integral_image_[upper_right_idx] - first_order_integral_image_[lower_left_idx]  );
00079 }
00080 
00082 template <typename DataType, unsigned Dimension> typename pcl::IntegralImage2D<DataType, Dimension>::SecondOrderType
00083 pcl::IntegralImage2D<DataType, Dimension>::getSecondOrderSum (
00084     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00085 {
00086   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00087   const unsigned upper_right_idx     = upper_left_idx + width;
00088   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00089   const unsigned lower_right_idx     = lower_left_idx + width;
00090 
00091   return (second_order_integral_image_[lower_right_idx] + second_order_integral_image_[upper_left_idx]  -
00092           second_order_integral_image_[upper_right_idx] - second_order_integral_image_[lower_left_idx]  );
00093 }
00094 
00096 template <typename DataType, unsigned Dimension> unsigned
00097 pcl::IntegralImage2D<DataType, Dimension>::getFiniteElementsCount (
00098     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00099 {
00100   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00101   const unsigned upper_right_idx     = upper_left_idx + width;
00102   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00103   const unsigned lower_right_idx     = lower_left_idx + width;
00104 
00105   return (finite_values_integral_image_[lower_right_idx] + finite_values_integral_image_[upper_left_idx]  -
00106           finite_values_integral_image_[upper_right_idx] - finite_values_integral_image_[lower_left_idx]  );
00107 }
00108 
00110 template <typename DataType, unsigned Dimension> void
00111 pcl::IntegralImage2D<DataType, Dimension>::computeIntegralImages (
00112     const DataType *data, unsigned row_stride, unsigned element_stride)
00113 {
00114   ElementType* previous_row = &first_order_integral_image_[0];
00115   ElementType* current_row  = previous_row + (width_ + 1);
00116   memset (previous_row, 0, sizeof (ElementType) * (width_ + 1));
00117 
00118   unsigned* count_previous_row = &finite_values_integral_image_[0];
00119   unsigned* count_current_row  = count_previous_row + (width_ + 1);
00120   memset (count_previous_row, 0, sizeof (unsigned) * (width_ + 1));
00121 
00122   if (!compute_second_order_integral_images_)
00123   {
00124     for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
00125                                                 previous_row = current_row, current_row += (width_ + 1),
00126                                                 count_previous_row = count_current_row, count_current_row += (width_ + 1))
00127     {
00128       current_row [0].setZero ();
00129       count_current_row [0] = 0;
00130       for (unsigned colIdx = 0, valIdx = 0; colIdx < width_; ++colIdx, valIdx += element_stride)
00131       {
00132         current_row [colIdx + 1] = previous_row [colIdx + 1] + current_row [colIdx] - previous_row [colIdx];
00133         count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
00134         const InputType* element = reinterpret_cast <const InputType*> (&data [valIdx]);
00135         if (pcl_isfinite (element->sum ()))
00136         {
00137           current_row [colIdx + 1] += element->template cast<typename IntegralImageTypeTraits<DataType>::IntegralType>();
00138           ++(count_current_row [colIdx + 1]);
00139         }
00140       }
00141     }
00142   }
00143   else
00144   {
00145     SecondOrderType* so_previous_row = &second_order_integral_image_[0];
00146     SecondOrderType* so_current_row  = so_previous_row + (width_ + 1);
00147     memset (so_previous_row, 0, sizeof (SecondOrderType) * (width_ + 1));
00148 
00149     SecondOrderType so_element;
00150     for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
00151                                                 previous_row = current_row, current_row += (width_ + 1),
00152                                                 count_previous_row = count_current_row, count_current_row += (width_ + 1),
00153                                                 so_previous_row = so_current_row, so_current_row += (width_ + 1))
00154     {
00155       current_row [0].setZero ();
00156       so_current_row [0].setZero ();
00157       count_current_row [0] = 0;
00158       for (unsigned colIdx = 0, valIdx = 0; colIdx < width_; ++colIdx, valIdx += element_stride)
00159       {
00160         current_row [colIdx + 1] = previous_row [colIdx + 1] + current_row [colIdx] - previous_row [colIdx];
00161         so_current_row [colIdx + 1] = so_previous_row [colIdx + 1] + so_current_row [colIdx] - so_previous_row [colIdx];
00162         count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
00163 
00164         const InputType* element = reinterpret_cast <const InputType*> (&data [valIdx]);
00165         if (pcl_isfinite (element->sum ()))
00166         {
00167           current_row [colIdx + 1] += element->template cast<typename IntegralImageTypeTraits<DataType>::IntegralType>();
00168           ++(count_current_row [colIdx + 1]);
00169           for (unsigned myIdx = 0, elIdx = 0; myIdx < Dimension; ++myIdx)
00170             for (unsigned mxIdx = myIdx; mxIdx < Dimension; ++mxIdx, ++elIdx)
00171               so_current_row [colIdx + 1][elIdx] += (*element)[myIdx] * (*element)[mxIdx];
00172         }
00173       }
00174     }
00175   }
00176 }
00177 
00179 
00180 template <typename DataType> void
00181 pcl::IntegralImage2D<DataType, 1>::setInput (const DataType * data, unsigned width,unsigned height, unsigned element_stride, unsigned row_stride)
00182 {
00183   if ((width + 1) * (height + 1) > first_order_integral_image_.size () )
00184   {
00185     width_  = width;
00186     height_ = height;
00187     first_order_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00188     finite_values_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00189     if (compute_second_order_integral_images_)
00190       second_order_integral_image_.resize ( (width_ + 1) * (height_ + 1) );
00191   }
00192   computeIntegralImages (data, row_stride, element_stride);
00193 }
00194 
00196 template <typename DataType> typename pcl::IntegralImage2D<DataType, 1>::ElementType
00197 pcl::IntegralImage2D<DataType, 1>::getFirstOrderSum (
00198     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00199 {
00200   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00201   const unsigned upper_right_idx     = upper_left_idx + width;
00202   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00203   const unsigned lower_right_idx     = lower_left_idx + width;
00204 
00205   return (first_order_integral_image_[lower_right_idx] + first_order_integral_image_[upper_left_idx]  -
00206           first_order_integral_image_[upper_right_idx] - first_order_integral_image_[lower_left_idx]  );
00207 }
00208 
00210 template <typename DataType> typename pcl::IntegralImage2D<DataType, 1>::SecondOrderType
00211 pcl::IntegralImage2D<DataType, 1>::getSecondOrderSum (
00212     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00213 {
00214   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00215   const unsigned upper_right_idx     = upper_left_idx + width;
00216   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00217   const unsigned lower_right_idx     = lower_left_idx + width;
00218 
00219   return (second_order_integral_image_[lower_right_idx] + second_order_integral_image_[upper_left_idx]  -
00220           second_order_integral_image_[upper_right_idx] - second_order_integral_image_[lower_left_idx]  );
00221 }
00222 
00224 template <typename DataType> unsigned
00225 pcl::IntegralImage2D<DataType, 1>::getFiniteElementsCount (
00226     unsigned start_x, unsigned start_y, unsigned width, unsigned height) const
00227 {
00228   const unsigned upper_left_idx      = start_y * (width_ + 1) + start_x;
00229   const unsigned upper_right_idx     = upper_left_idx + width;
00230   const unsigned lower_left_idx      = (start_y + height) * (width_ + 1) + start_x;
00231   const unsigned lower_right_idx     = lower_left_idx + width;
00232 
00233   return (finite_values_integral_image_[lower_right_idx] + finite_values_integral_image_[upper_left_idx]  -
00234           finite_values_integral_image_[upper_right_idx] - finite_values_integral_image_[lower_left_idx]  );
00235 }
00236 
00238 template <typename DataType> void
00239 pcl::IntegralImage2D<DataType, 1>::computeIntegralImages (
00240     const DataType *data, unsigned row_stride, unsigned element_stride)
00241 {
00242   ElementType* previous_row = &first_order_integral_image_[0];
00243   ElementType* current_row  = previous_row + (width_ + 1);
00244   memset (previous_row, 0, sizeof (ElementType) * (width_ + 1));
00245 
00246   unsigned* count_previous_row = &finite_values_integral_image_[0];
00247   unsigned* count_current_row  = count_previous_row + (width_ + 1);
00248   memset (count_previous_row, 0, sizeof (unsigned) * (width_ + 1));
00249 
00250   if (!compute_second_order_integral_images_)
00251   {
00252     for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
00253                                                 previous_row = current_row, current_row += (width_ + 1),
00254                                                 count_previous_row = count_current_row, count_current_row += (width_ + 1))
00255     {
00256       current_row [0] = 0.0;
00257       count_current_row [0] = 0;
00258       for (unsigned colIdx = 0, valIdx = 0; colIdx < width_; ++colIdx, valIdx += element_stride)
00259       {
00260         current_row [colIdx + 1] = previous_row [colIdx + 1] + current_row [colIdx] - previous_row [colIdx];
00261         count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
00262         if (pcl_isfinite (data [valIdx]))
00263         {
00264           current_row [colIdx + 1] += data [valIdx];
00265           ++(count_current_row [colIdx + 1]);
00266         }
00267       }
00268     }
00269   }
00270   else
00271   {
00272     SecondOrderType* so_previous_row = &second_order_integral_image_[0];
00273     SecondOrderType* so_current_row  = so_previous_row + (width_ + 1);
00274     memset (so_previous_row, 0, sizeof (SecondOrderType) * (width_ + 1));
00275 
00276     for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
00277                                                 previous_row = current_row, current_row += (width_ + 1),
00278                                                 count_previous_row = count_current_row, count_current_row += (width_ + 1),
00279                                                 so_previous_row = so_current_row, so_current_row += (width_ + 1))
00280     {
00281       current_row [0] = 0.0;
00282       so_current_row [0] = 0.0;
00283       count_current_row [0] = 0;
00284       for (unsigned colIdx = 0, valIdx = 0; colIdx < width_; ++colIdx, valIdx += element_stride)
00285       {
00286         current_row [colIdx + 1] = previous_row [colIdx + 1] + current_row [colIdx] - previous_row [colIdx];
00287         so_current_row [colIdx + 1] = so_previous_row [colIdx + 1] + so_current_row [colIdx] - so_previous_row [colIdx];
00288         count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
00289         if (pcl_isfinite (data[valIdx]))
00290         {
00291           current_row [colIdx + 1] += data[valIdx];
00292           so_current_row [colIdx + 1] += data[valIdx] * data[valIdx];
00293           ++(count_current_row [colIdx + 1]);
00294         }
00295       }
00296     }
00297   }
00298 }
00299 #endif    // PCL_INTEGRAL_IMAGE2D_IMPL_H_
00300