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 }
00034
00035 }
00036
00037
00038
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
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
00065 size_t outputIndex = rowsMinusRadius * columns;
00066
00067
00068 for(size_t row = rowsMinusRadius; row < rows; ++row) {
00069
00070
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
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
00134 const size_t columns = inputImage.columns();
00135 const size_t columnsMinusRadius = inputImage.columns() - radius;
00136
00137
00138 size_t outputIndex = 0;
00139
00140
00141 for(size_t row = 0; row < radius; ++row) {
00142
00143
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
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
00206 const size_t columns = inputImage.columns();
00207 const size_t columnsMinusRadius = inputImage.columns() - radius;
00208
00209 const size_t rowsMinusRadius = inputImage.rows() - radius;
00210
00211
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
00220 for(size_t row = radius; row < rowsMinusRadius; ++row) {
00221 size_t outputIndex = row * outputImage.columns();
00222
00223
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
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 }
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
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 }
00438
00439 }
00440
00441 #endif