dilate.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRCOMPUTERVISION_DILATE_H_
00016 #define _DLRCOMPUTERVISION_DILATE_H_
00017 
00018 #include <dlrComputerVision/image.h>
00019 
00020 namespace dlr {
00021 
00022   namespace computerVision {
00023     
00024     template<ImageFormat FORMAT>
00025     Image<FORMAT>
00026     dilate(const Image<FORMAT>& inputImage);
00027 
00028 
00029     template<ImageFormat FORMAT>
00030     Image<FORMAT>
00031     dilate(const Image<FORMAT>& inputImage, size_t radius);
00032 
00033   } // namespace computerVision
00034     
00035 } // namespace dlr
00036 
00037 
00038 /* ============ Definitions of inline & template functions ============ */
00039 
00040 
00041 #include <cmath>
00042 #include <dlrNumeric/stencil2D.h>
00043 
00044 namespace dlr {
00045 
00046   namespace computerVision {
00047 
00048     namespace privateCode {
00049 
00050 
00051       template<ImageFormat FORMAT>
00052       void
00053       dilateBottomBorder(const Image<FORMAT>& inputImage, size_t radius,
00054                          Image<FORMAT>& outputImage)
00055       {
00056         typedef typename Image<FORMAT>::value_type ValueType;
00057 
00058         // Some constants to help with loops below.
00059         const size_t columns = inputImage.columns();
00060         const size_t columnsMinusRadius = inputImage.columns() - radius;
00061         const size_t rows = inputImage.rows();
00062         const size_t rowsMinusRadius = inputImage.rows() - radius;
00063 
00064         // This variable will scan the entire border in raster order.
00065         size_t outputIndex = rowsMinusRadius * columns;
00066         
00067         // Bottom border is made up of last radius rows.
00068         for(size_t row = rowsMinusRadius; row < rows; ++row) {
00069 
00070           // First radius columns are a special case.
00071           for(size_t column = 0; column < radius; ++column) {
00072             outputImage[outputIndex] = ValueType(0);
00073             for(size_t row2 = row - radius; row2 < rows; ++row2) {
00074               for(size_t column2 = 0; column2 <= column + radius; ++column2) {
00075                 if(inputImage(row2, column2)) {
00076                   outputImage[outputIndex] = ValueType(1);
00077                   break;
00078                 }
00079               }
00080               if(outputImage[outputIndex]) {
00081                 break;
00082               }
00083             }
00084             ++outputIndex;
00085           }
00086 
00087           for(size_t column = radius; column < columnsMinusRadius; ++column) {
00088             outputImage[outputIndex] = ValueType(0);
00089             for(size_t row2 = row - radius; row2 < rows; ++row2) {
00090               for(size_t column2 = column - radius; column2 <= column + radius;
00091                   ++column2) {
00092                 if(inputImage(row2, column2)) {
00093                   outputImage[outputIndex] = ValueType(1);
00094                   break;
00095                 }
00096               }
00097               if(outputImage[outputIndex]) {
00098                 break;
00099               }
00100             }
00101             ++outputIndex;
00102           }
00103 
00104 
00105           // Last radius columns are a special case.
00106           for(size_t column = columnsMinusRadius; column < columns; ++column) {
00107             outputImage[outputIndex] = ValueType(0);
00108             for(size_t row2 = row - radius; row2 < rows; ++row2) {
00109               for(size_t column2 = column - radius; column2 < columns;
00110                   ++column2) {
00111                 if(inputImage(row2, column2)) {
00112                   outputImage[outputIndex] = ValueType(1);
00113                   break;
00114                 }
00115               }
00116               if(outputImage[outputIndex]) {
00117                 break;
00118               }
00119             }
00120             ++outputIndex;
00121           }
00122         }
00123       }
00124       
00125 
00126       template<ImageFormat FORMAT>
00127       void
00128       dilateTopBorder(const Image<FORMAT>& inputImage, size_t radius,
00129                       Image<FORMAT>& outputImage)
00130       {
00131         typedef typename Image<FORMAT>::value_type ValueType;
00132 
00133         // Some constants to help with loops below.
00134         const size_t columns = inputImage.columns();
00135         const size_t columnsMinusRadius = inputImage.columns() - radius;
00136       
00137         // This variable will scan the entire output image in raster order.
00138         size_t outputIndex = 0;
00139 
00140         // The top border consists of the first radius rows.
00141         for(size_t row = 0; row < radius; ++row) {
00142 
00143           // First radius columns are a special case.
00144           for(size_t column = 0; column < radius; ++column) {
00145             outputImage[outputIndex] = ValueType(0);
00146             for(size_t row2 = 0; row2 <= row + radius; ++row2) {
00147               for(size_t column2 = 0; column2 <= column + radius; ++column2) {
00148                 if(inputImage(row2, column2)) {
00149                   outputImage[outputIndex] = ValueType(1);
00150                   break;
00151                 }
00152               }
00153               if(outputImage[outputIndex]) {
00154                 break;
00155               }
00156             }
00157             ++outputIndex;
00158           }
00159 
00160           for(size_t column = radius; column < columnsMinusRadius; ++column) {
00161             outputImage[outputIndex] = ValueType(0);
00162             for(size_t row2 = 0; row2 <= row + radius; ++row2) {
00163               for(size_t column2 = column - radius; column2 <= column + radius;
00164                   ++column2) {
00165                 if(inputImage(row2, column2)) {
00166                   outputImage[outputIndex] = ValueType(1);
00167                   break;
00168                 }
00169               }
00170               if(outputImage[outputIndex]) {
00171                 break;
00172               }
00173             }
00174             ++outputIndex;
00175           }
00176         
00177           // Last radius columns are a special case.
00178           for(size_t column = columnsMinusRadius; column < columns; ++column) {
00179             outputImage[outputIndex] = ValueType(0);
00180             for(size_t row2 = 0; row2 <= row + radius; ++row2) {
00181               for(size_t column2 = column - radius; column2 < columns;
00182                   ++column2) {
00183                 if(inputImage(row2, column2)) {
00184                   outputImage[outputIndex] = ValueType(1);
00185                   break;
00186                 }
00187               }
00188               if(outputImage[outputIndex]) {
00189                 break;
00190               }
00191             }
00192             ++outputIndex;
00193           }
00194         }
00195       }
00196 
00197       
00198       template<ImageFormat FORMAT, size_t StencilSize>
00199       void
00200       sizedDilate(const Image<FORMAT>& inputImage, size_t radius,
00201                   Image<FORMAT>& outputImage)
00202       {
00203         typedef typename Image<FORMAT>::value_type ValueType;
00204 
00205         // Some constants to help with loops below.
00206         const size_t columns = inputImage.columns();
00207         const size_t columnsMinusRadius = inputImage.columns() - radius;
00208         // const size_t rows = inputImage.rows();
00209         const size_t rowsMinusRadius = inputImage.rows() - radius;
00210 
00211         // A stencil to avoid quadruple-looping over most of the image.
00212         typedef typename ImageFormatTraits<FORMAT>::PixelType PixType;
00213         dlr::numeric::Stencil2D<const PixType, StencilSize> inputStencil(
00214           2 * radius + 1, 2 * radius + 1);
00215         inputStencil.setTarget(inputImage);
00216         typedef dlr::numeric::StencilIterator<const PixType, StencilSize>
00217           InputIterator;
00218 
00219         // Now do the bulk of the image (up to the last radius rows).
00220         for(size_t row = radius; row < rowsMinusRadius; ++row) {
00221           size_t outputIndex = row * outputImage.columns();
00222           
00223           // First radius columns are a special case.
00224           for(size_t column = 0; column < radius; ++column) {
00225             outputImage[outputIndex] = ValueType(0);
00226             for(size_t row2 = row - radius; row2 <= row + radius; ++row2) {
00227               for(size_t column2 = 0; column2 <= column + radius; ++column2) {
00228                 if(inputImage(row2, column2)) {
00229                   outputImage[outputIndex] = ValueType(1);
00230                   break;
00231                 }
00232               }
00233               if(outputImage[outputIndex]) {
00234                 break;
00235               }
00236             }
00237             ++outputIndex;
00238           }
00239           
00240           inputStencil.goTo(row - radius, 0);
00241           for(size_t column = radius; column < columnsMinusRadius; ++column) {
00242             InputIterator inputIterator = inputStencil.begin(); 
00243             InputIterator endIterator = inputStencil.end(); 
00244             outputImage[outputIndex] = ValueType(0);
00245             while(inputIterator != endIterator) {
00246               if(*inputIterator) {
00247                 outputImage[outputIndex] = ValueType(1);
00248                 break;
00249               }
00250               ++inputIterator;
00251             }
00252             inputStencil.advance();
00253             ++outputIndex;
00254           }
00255 
00256 
00257           // Last radius columns are a special case.
00258           for(size_t column = columnsMinusRadius; column < columns; ++column) {
00259             outputImage[outputIndex] = ValueType(0);
00260             for(size_t row2 = row - radius; row2 <= row + radius; ++row2) {
00261               for(size_t column2 = column - radius; column2 < columns;
00262                   ++column2) {
00263                 if(inputImage(row2, column2)) {
00264                   outputImage[outputIndex] = ValueType(1);
00265                   break;
00266                 }
00267               }
00268               if(outputImage[outputIndex]) {
00269                 break;
00270               }
00271             }
00272             ++outputIndex;
00273           }
00274         }
00275       }
00276 
00277     } // namespace privateCode
00278     
00279   
00280     template<ImageFormat FORMAT>
00281     Image<FORMAT>
00282     dilate(const Image<FORMAT>& inputImage)
00283     {
00284       typedef typename Image<FORMAT>::value_type ValueType;
00285     
00286       Image<FORMAT> outputImage(inputImage.rows(), inputImage.columns());
00287 
00288       size_t index0 = 0;
00289       if(inputImage[0]
00290          || inputImage[1]
00291          || inputImage[inputImage.columns()]
00292          || inputImage[inputImage.columns() + 1]) {
00293         outputImage[index0] = ValueType(1);
00294       } else {
00295         outputImage[index0] = ValueType(0);
00296       }
00297       ++index0;
00298 
00299       for(size_t column = 1; column < inputImage.columns() - 1; ++column) {
00300         if(inputImage[index0]
00301            || inputImage[index0 - 1]
00302            || inputImage[index0 + 1]
00303            || inputImage[index0 + inputImage.columns() - 1]
00304            || inputImage[index0 + inputImage.columns()]
00305            || inputImage[index0 + inputImage.columns() + 1]) {
00306           outputImage[index0] = ValueType(1);
00307         } else {
00308           outputImage[index0] = ValueType(0);
00309         }
00310         ++index0;
00311       }
00312         
00313       if(inputImage[index0]
00314          || inputImage[index0 - 1]
00315          || inputImage[index0 + inputImage.columns() - 1]
00316          || inputImage[index0 + inputImage.columns()]) {
00317         outputImage[index0] = ValueType(1);
00318       } else {
00319         outputImage[index0] = ValueType(0);
00320       }
00321       ++index0;
00322 
00323       for(size_t row = 1; row < inputImage.rows() - 1; ++row) {
00324         if(inputImage[index0]
00325            || inputImage[index0 + 1]
00326            || inputImage[index0 - inputImage.columns()]
00327            || inputImage[index0 - inputImage.columns() + 1]
00328            || inputImage[index0 + inputImage.columns()]
00329            || inputImage[index0 + inputImage.columns() + 1]) {
00330           outputImage[index0] = ValueType(1);
00331         } else {
00332           outputImage[index0] = ValueType(0);
00333         }
00334         ++index0;
00335 
00336         for(size_t column = 1; column < inputImage.columns() - 1; ++column) {
00337           if(inputImage[index0]
00338              || inputImage[index0 - 1]
00339              || inputImage[index0 + 1]
00340              || inputImage[index0 - inputImage.columns() - 1]
00341              || inputImage[index0 - inputImage.columns()]
00342              || inputImage[index0 - inputImage.columns() + 1]
00343              || inputImage[index0 + inputImage.columns() - 1]
00344              || inputImage[index0 + inputImage.columns()]
00345              || inputImage[index0 + inputImage.columns() + 1]) {
00346             outputImage[index0] = ValueType(1);
00347           } else {
00348             outputImage[index0] = ValueType(0);
00349           }
00350           ++index0;
00351         }
00352 
00353         if(inputImage[index0]
00354            || inputImage[index0 - 1]
00355            || inputImage[index0 - inputImage.columns()]
00356            || inputImage[index0 - inputImage.columns() - 1]
00357            || inputImage[index0 + inputImage.columns()]
00358            || inputImage[index0 + inputImage.columns() - 1]) {
00359           outputImage[index0] = ValueType(1);
00360         } else {
00361           outputImage[index0] = ValueType(0);
00362         }
00363         ++index0;
00364       }
00365 
00366       if(inputImage[index0]
00367          || inputImage[index0 + 1]
00368          || inputImage[index0 - inputImage.columns()]
00369          || inputImage[index0 - inputImage.columns() + 1]) {
00370         outputImage[index0] = ValueType(1);
00371       } else {
00372         outputImage[index0] = ValueType(0);
00373       }
00374       ++index0;
00375 
00376       for(size_t column = 1; column < inputImage.columns() - 1; ++column) {
00377         if(inputImage[index0]
00378            || inputImage[index0 - 1]
00379            || inputImage[index0 + 1]
00380            || inputImage[index0 - inputImage.columns() - 1]
00381            || inputImage[index0 - inputImage.columns()]
00382            || inputImage[index0 - inputImage.columns() + 1]) {
00383           outputImage[index0] = ValueType(1);
00384         } else {
00385           outputImage[index0] = ValueType(0);
00386         }
00387         ++index0;
00388       }
00389         
00390       if(inputImage[index0]
00391          || inputImage[index0 - 1]
00392          || inputImage[index0 - inputImage.columns() - 1]
00393          || inputImage[index0 - inputImage.columns()]) {
00394         outputImage[index0] = ValueType(1);
00395       } else {
00396         outputImage[index0] = ValueType(0);
00397       }
00398       ++index0;
00399 
00400       return outputImage;
00401     }
00402 
00403 
00404     template<ImageFormat FORMAT>
00405     Image<FORMAT>
00406     dilate(const Image<FORMAT>& inputImage, size_t radius)
00407     {
00408       typedef typename Image<FORMAT>::value_type ValueType;
00409 
00410       if(radius >= inputImage.rows() || radius >= inputImage.columns()) {
00411         DLR_THROW(ValueException, "dilate()",
00412                   "Argument radius must be less than both the width and "
00413                   "height of the input image.");
00414       }
00415       
00416       Image<FORMAT> outputImage(inputImage.rows(), inputImage.columns());
00417 
00418       privateCode::dilateTopBorder(inputImage, radius, outputImage);
00419 
00420       // Now do the bulk of the image (up to the last radius rows).
00421       if(radius < 5) {
00422         privateCode::sizedDilate<FORMAT, 81>(inputImage, radius, outputImage);
00423       } else if(radius < 10) {
00424         privateCode::sizedDilate<FORMAT, 361>(inputImage, radius, outputImage);
00425       } else if(radius < 20) {
00426         privateCode::sizedDilate<FORMAT, 1521>(inputImage, radius, outputImage);
00427       } else {
00428         DLR_THROW(NotImplementedException, "dilate()",
00429                   "Dilations with radius >= 20 are not currently supported.");
00430       }
00431 
00432       privateCode::dilateBottomBorder(inputImage, radius, outputImage);
00433       
00434       return outputImage;
00435     }
00436     
00437   } // namespace computerVision
00438     
00439 } // namespace dlr
00440 
00441 #endif /* #ifndef _DLRCOMPUTERVISION_DILATE_H_ */

Generated on Wed Nov 25 12:15:04 2009 for dlrComputerVision Utility Library by  doxygen 1.5.8