sobel.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRCOMPUTERVISION_SOBEL_H_
00016 #define _DLRCOMPUTERVISION_SOBEL_H_
00017 
00018 #include <dlrComputerVision/image.h>
00019 
00020 namespace dlr {
00021 
00022   namespace computerVision {
00023     
00024 
00048     template <ImageFormat FORMAT>
00049     Image<FORMAT>
00050     applySobelX(const Image<FORMAT>& inputImage, bool normalizeResult=false);
00051 
00052 
00076     template <ImageFormat FORMAT>
00077     Image<FORMAT>
00078     applySobelY(const Image<FORMAT>& inputImage, bool normalizeResult=false);
00079 
00080   } // namespace computerVision
00081 
00082 } // namespace dlr
00083 
00084 
00085 /* =============== Implementation follows =============== */
00086 
00087 
00088 namespace dlr {
00089 
00090   namespace computerVision {
00091 
00092     // This function applies the sobel edge operator in the X
00093     // direction.
00094     template <ImageFormat FORMAT>
00095     Image<FORMAT>
00096     applySobelX(const Image<FORMAT>& inputImage, bool normalizeResult)
00097     {
00098       // Argument checking.
00099       if(normalizeResult == true) {
00100         DLR_THROW(NotImplementedException, "applySobelX()",
00101                   "Argument normalizeResult must be false for now.");
00102       }
00103       if(inputImage.rows() < 2 || inputImage.columns() < 2) {
00104         DLR_THROW(ValueException, "applySobelX()",
00105                   "Argument inputImage must be 2x2 or larger.");
00106       }
00107 
00108       // Prepare a space for the result.
00109       Image<FORMAT> gradientImage(inputImage.rows(), inputImage.columns());
00110 
00111       // We'll keep a running index to avoid double-indexing the images.
00112       size_t index0 = 0;
00113       const size_t rows = inputImage.rows();
00114       const size_t cols = inputImage.columns();
00115       const size_t colsMinusOne = cols - 1;
00116 
00117       // NOTE: In all of the code below, We assume that the image
00118       // continues with constant first derivative into the (fictional)
00119       // out-of-bounds rows and columns.  This has the somewhat
00120       // surprising effect of making the first row of convolution
00121       // results independent of the second image row.
00122       
00123       // Use a very reduced kernel for the upper-left corner.
00124       gradientImage[index0] = (
00125         8 * (inputImage[index0 + 1] - inputImage[index0]));
00126       ++index0;
00127       
00128       // Use a reduced kernel for the first row.
00129       for(size_t column = 1; column < colsMinusOne; ++column) {
00130         gradientImage[index0] = (
00131           4 * (inputImage[index0 + 1] - inputImage[index0 - 1]));
00132         ++index0;
00133       }
00134 
00135       // Use a very reduced kernel for the upper-right corner.
00136       gradientImage[index0] = (
00137         8 * (inputImage[index0] - inputImage[index0 - 1]));
00138       ++index0;
00139       
00140       // Convolve the bulk of the image.
00141       for(size_t row = 1; row < rows - 1; ++row) {
00142 
00143         // Use a reduced kernel for first pixel in the row.
00144         gradientImage[index0] = (
00145           2 * (inputImage[index0 - cols + 1] - inputImage[index0 - cols])
00146           + 4 * (inputImage[index0 + 1] - inputImage[index0])
00147           + 2 * (inputImage[index0 + cols + 1] - inputImage[index0 + cols]));
00148         ++index0;
00149         
00150         // Convolve the bulk of the row.
00151         for(size_t column = 1; column < colsMinusOne; ++column) {
00152           gradientImage[index0] = (
00153             (inputImage[index0 - cols + 1] - inputImage[index0 - cols - 1])
00154             + 2 * (inputImage[index0 + 1] - inputImage[index0 - 1])
00155             + (inputImage[index0 + cols + 1] - inputImage[index0 + cols - 1]));
00156           ++index0;
00157         }
00158 
00159         // Use a reduced kernel for last pixel in the row.
00160         gradientImage[index0] = (
00161           2 * (inputImage[index0 - cols] - inputImage[index0 - cols - 1])
00162           + 4 * (inputImage[index0] - inputImage[index0 - 1])
00163           + 2 * (inputImage[index0 + cols] - inputImage[index0 + cols - 1]));
00164         ++index0;
00165       }
00166 
00167       // Use a very reduced kernel for the lower-left corner.
00168       gradientImage[index0] = (
00169         8 * (inputImage[index0 + 1] - inputImage[index0]));
00170       ++index0;
00171       
00172       // Use a reduced kernel for the last row.
00173       for(size_t column = 1; column < colsMinusOne; ++column) {
00174         gradientImage[index0] = (
00175           4 * (inputImage[index0 + 1] - inputImage[index0 - 1]));
00176         ++index0;
00177       }
00178 
00179       // Use a very reduced kernel for the lower-right corner.
00180       gradientImage[index0] = (
00181         8 * (inputImage[index0] - inputImage[index0 - 1]));
00182       ++index0;
00183 
00184       return gradientImage;
00185     }
00186 
00187 
00188     // This function applies the sobel edge operator in the Y
00189     // direction.
00190     template <ImageFormat FORMAT>
00191     Image<FORMAT>
00192     applySobelY(const Image<FORMAT>& inputImage, bool normalizeResult)
00193     {
00194       // Argument checking.
00195       if(normalizeResult == true) {
00196         DLR_THROW(NotImplementedException, "applySobelY()",
00197                   "Argument normalizeResult must be false for now.");
00198       }
00199       if(inputImage.rows() < 2 || inputImage.columns() < 2) {
00200         DLR_THROW(ValueException, "applySobelY()",
00201                   "Argument inputImage must be 2x2 or larger.");
00202       }
00203 
00204       // Prepare a space for the result.
00205       Image<FORMAT> gradientImage(inputImage.rows(), inputImage.columns());
00206 
00207       // We'll keep a running index to avoid double-indexing the images.
00208       size_t index0 = 0;
00209       const size_t rows = inputImage.rows();
00210       const size_t cols = inputImage.columns();
00211       const size_t colsMinusOne = cols - 1;
00212 
00213       // NOTE: In all of the code below, We assume that the image
00214       // continues with constant first derivative into the (fictional)
00215       // out-of-bounds rows and columns.  This has the somewhat
00216       // surprising effect of making the first row of convolution
00217       // results independent of the second image row.
00218       
00219       // Use a very reduced kernel for the upper-left corner.
00220       gradientImage[index0] = (
00221         8 * (inputImage[index0 + cols] - inputImage[index0]));
00222       ++index0;
00223       
00224       // Use a reduced kernel for the first row.
00225       for(size_t column = 1; column < colsMinusOne; ++column) {
00226         gradientImage[index0] = (
00227           2 * (inputImage[index0 + cols - 1] - inputImage[index0 - 1])
00228           + 4 * (inputImage[index0 + cols] - inputImage[index0])
00229           + 2 * (inputImage[index0 + cols + 1] - inputImage[index0 + 1]));
00230         ++index0;
00231       }
00232 
00233       // Use a very reduced kernel for the upper-right corner.
00234       gradientImage[index0] = (
00235         8 * (inputImage[index0 + cols] - inputImage[index0]));
00236       ++index0;
00237       
00238       // Convolve the bulk of the image.
00239       for(size_t row = 1; row < rows - 1; ++row) {
00240 
00241         // Use a reduced kernel for first pixel in the row.
00242         gradientImage[index0] = (
00243           4 * (inputImage[index0 + cols] - inputImage[index0 - cols]));
00244         ++index0;
00245         
00246         // Convolve the bulk of the row.
00247         for(size_t column = 1; column < colsMinusOne; ++column) {
00248           gradientImage[index0] = (
00249             (inputImage[index0 + cols - 1] - inputImage[index0 - cols - 1])
00250             + 2 * (inputImage[index0 + cols] - inputImage[index0 - cols])
00251             + (inputImage[index0 + cols + 1] - inputImage[index0 - cols + 1]));
00252           ++index0;
00253         }
00254 
00255         // Use a reduced kernel for last pixel in the row.
00256         gradientImage[index0] = (
00257           4 * (inputImage[index0 + cols] - inputImage[index0 - cols]));
00258         ++index0;
00259       }
00260 
00261       // Use a very reduced kernel for the lower-left corner.
00262       gradientImage[index0] = (
00263         8 * (inputImage[index0] - inputImage[index0 - cols]));
00264       ++index0;
00265       
00266       // Use a reduced kernel for the last row.
00267       for(size_t column = 1; column < colsMinusOne; ++column) {
00268         gradientImage[index0] = (
00269           2 * (inputImage[index0 - 1] - inputImage[index0 - cols - 1])
00270           + 4 * (inputImage[index0] - inputImage[index0 - cols])
00271           + 2 * (inputImage[index0 + 1] - inputImage[index0 - cols + 1]));
00272         ++index0;
00273       }
00274 
00275       // Use a very reduced kernel for the lower-right corner.
00276       gradientImage[index0] = (
00277         8 * (inputImage[index0] - inputImage[index0 - cols]));
00278       ++index0;
00279 
00280       return gradientImage;
00281     }
00282 
00283 
00284   } // namespace computerVision
00285   
00286 } // namespace dlr
00287 
00288 #endif /* #ifndef _DLRCOMPUTERVISION_KERNEL_H_ */

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