utilities.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRCOMPUTERVISION_UTILITIES_H_
00016 #define _DLRCOMPUTERVISION_UTILITIES_H_
00017 
00018 #include <dlrComputerVision/colorspaceConverter.h>
00019 #include <dlrComputerVision/image.h>
00020 
00021 namespace dlr {
00022 
00023   namespace computerVision {
00024     
00071     template<ImageFormat FORMAT>
00072     bool
00073     associateColorComponents(
00074       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& inputArray,
00075       Image<FORMAT>& outputImage);
00076 
00077 
00098     template<ImageFormat FORMAT>
00099     Image<FORMAT>
00100     associateColorComponents(
00101       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& inputArray);
00102 
00103 
00125     template<ImageFormat OUTPUT_FORMAT, ImageFormat INPUT_FORMAT>
00126     Image<OUTPUT_FORMAT>
00127     convertColorspace(const Image<INPUT_FORMAT>& inputImage);
00128 
00129 
00176     template<ImageFormat FORMAT>
00177     bool
00178     dissociateColorComponents(
00179       Image<FORMAT>& inputImage,
00180       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& outputArray);
00181 
00182 
00205     template<ImageFormat FORMAT>
00206     Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>
00207     dissociateColorComponents(Image<FORMAT>& inputImage);
00208 
00209 
00239     template<ImageFormat Format>
00240     Image<Format>
00241     subsample(const Image<Format>& inputImage,
00242               size_t rowStep = 2,
00243               size_t columnStep = 2);
00244 
00245 
00268     template<ImageFormat InputFormat,
00269              ImageFormat OutputFormat,
00270              ImageFormat IntermediateFormat>
00271     Image<OutputFormat>
00272     supersample(const Image<InputFormat>& inputImage);
00273   
00274     
00289     template <class Type, ImageFormat FORMAT>
00290     Array2D<Type>
00291     toArray(const Image<FORMAT>& inputImage);
00292 
00293   } // namespace computerVision    
00294 
00295 } // namespace dlr
00296 
00297 
00298 /* ============ Definitions of inline & template functions ============ */
00299 
00300 
00301 namespace dlr {
00302 
00303   namespace computerVision {
00304 
00306     namespace privateCode {
00307 
00308       // This function simplifies template specialization of
00309       // associateColorComponents, which makes things easier on the
00310       // compiler.
00311       template<ImageFormat Format, class ComponentType>
00312       inline bool
00313       associateColorComponents(
00314         Array2D<ComponentType>& inputArray,
00315         Image<Format>& outputImage)
00316       {
00317         // Some typedefs for notational convenience.
00318         typedef typename ImageFormatTraits<Format>::PixelType PixelType;
00319         typedef typename Image<Format>::iterator ImageIterator;
00320         typedef typename Array2D<ComponentType>::iterator ArrayIterator;
00321       
00322         // Argument checking.
00323         if(inputArray.columns()
00324            % ImageFormatTraits<Format>::getNumberOfComponents()
00325            != 0) {
00326           DLR_THROW(ValueException, "associateColorComponents()",
00327                     "Input image must have a number of columns which is "
00328                     "evenly divisible by the number of color components.");
00329         }
00330 
00331         // Calculate output image width.
00332         size_t numberOfOutputColumns = inputArray.columns()
00333           / ImageFormatTraits<Format>::getNumberOfComponents();
00334 
00335         bool returnValue;
00336         if(PixelType::isContiguous()) {
00337           // Build the output image.
00338           outputImage = Image<Format>(
00339             inputArray.rows(), numberOfOutputColumns,
00340             reinterpret_cast<PixelType*>(inputArray.data()));
00341           returnValue = true;
00342         } else {
00343           if(outputImage.rows() != inputArray.rows()
00344              || outputImage.columns() != numberOfOutputColumns) {
00345             outputImage = Image<Format>(
00346               inputArray.rows(), numberOfOutputColumns);
00347           }
00348           ArrayIterator arrayIterator = inputArray.begin();
00349           for(ImageIterator imageIterator = outputImage.begin();
00350               imageIterator != outputImage.end(); ++imageIterator) {
00351             imageIterator->copyFromIterator(arrayIterator);
00352             ++imageIterator;
00353           }
00354           returnValue = false;
00355         }
00356         return returnValue;
00357       }
00358 
00359   
00360       // Explicit specializations of
00361       // privateCode::associateColorComponents() are needed for those
00362       // image formats which use builtin types as pixels.
00363       template<>
00364       inline bool
00365       associateColorComponents(
00366         Array2D<bool>& inputArray,
00367         Image<GRAY1>& outputImage)
00368       {
00369         outputImage = inputArray;
00370         return true;
00371       }
00372 
00373 
00374       template<>
00375       inline bool
00376       associateColorComponents(Array2D<UnsignedInt8>& inputArray,
00377                                Image<GRAY8>& outputImage)
00378       {
00379         outputImage = inputArray;
00380         return true;
00381       }
00382 
00383     
00384       template<>
00385       inline bool
00386       associateColorComponents(Array2D<UnsignedInt16>& inputArray,
00387                                Image<GRAY16>& outputImage)
00388       {
00389         outputImage = inputArray;
00390         return true;
00391       }
00392 
00393     
00394       template<>
00395       inline bool
00396       associateColorComponents(Array2D<UnsignedInt32>& inputArray,
00397                                Image<GRAY32>& outputImage)
00398       {
00399         outputImage = inputArray;
00400         return true;
00401       }
00402 
00403     
00404       template<>
00405       inline bool
00406       associateColorComponents(Array2D<Int16>& inputArray,
00407                                Image<GRAY_SIGNED16>& outputImage)
00408       {
00409         outputImage = inputArray;
00410         return true;
00411       }
00412 
00413     
00414       template<>
00415       inline bool
00416       associateColorComponents(Array2D<Int32>& inputArray,
00417                                Image<GRAY_SIGNED32>& outputImage)
00418       {
00419         outputImage = inputArray;
00420         return true;
00421       }
00422 
00423     
00424       template<>
00425       inline bool
00426       associateColorComponents(Array2D<Float32>& inputArray,
00427                                Image<GRAY_FLOAT32>& outputImage)
00428       {
00429         outputImage = inputArray;
00430         return true;
00431       }
00432 
00433     
00434       template<>
00435       inline bool
00436       associateColorComponents(Array2D<Float64>& inputArray,
00437                                Image<GRAY_FLOAT64>& outputImage)
00438       {
00439         outputImage = inputArray;
00440         return true;
00441       }
00442 
00443       // This function returns by reference an array which either shares
00444       // or copies the data from the input image.
00445       template<ImageFormat Format, class ComponentType>
00446       inline bool
00447       dissociateColorComponents(
00448         Image<Format>& inputImage,
00449         Array2D<ComponentType>& outputArray)
00450       {
00451         // Some typedefs for notational convenience.
00452         typedef typename ImageFormatTraits<Format>::PixelType PixelType;
00453         typedef typename Image<Format>::iterator ImageIterator;
00454         typedef typename Array2D<ComponentType>::iterator ArrayIterator;
00455 
00456         // Calculate output array width.
00457         size_t numberOfOutputColumns = inputImage.columns()
00458           * ImageFormatTraits<Format>::getNumberOfComponents();
00459     
00460         // Now build the output array.
00461         bool returnValue;
00462         if(PixelType::isContiguous()) {
00463           outputArray = Array2D<ComponentType>(
00464             inputImage.rows(), numberOfOutputColumns,
00465             reinterpret_cast<ComponentType*>(inputImage.data()));
00466           returnValue = true;
00467         } else {
00468           if(outputArray.rows() != inputImage.rows()
00469              || outputArray.columns() != numberOfOutputColumns) {
00470             outputArray = Array2D<ComponentType>(
00471               inputImage.rows(), numberOfOutputColumns);
00472           }
00473           ArrayIterator arrayIterator = outputArray.begin();
00474           for(ImageIterator imageIterator = inputImage.begin();
00475               imageIterator != inputImage.end(); ++imageIterator) {
00476             imageIterator->copyToIterator(arrayIterator);
00477             ++imageIterator;
00478           }
00479           returnValue = false;
00480         }
00481         return returnValue;
00482       }
00483   
00484   
00485       // Explicit specializations of dissociateColorComponents() are needed
00486       // for those image formats which use builtin types as pixels.
00487       template<>
00488       inline bool
00489       dissociateColorComponents(Image<GRAY1>& inputImage,
00490                                 Array2D<bool>& outputArray)
00491       {
00492         outputArray = inputImage;
00493         return true;
00494       }
00495 
00496     
00497       template<>
00498       inline bool
00499       dissociateColorComponents(Image<GRAY8>& inputImage,
00500                                 Array2D<UnsignedInt8>& outputArray)
00501       {
00502         outputArray = inputImage;
00503         return true;
00504       }
00505 
00506     
00507       template<>
00508       inline bool
00509       dissociateColorComponents(Image<GRAY16>& inputImage,
00510                                 Array2D<UnsignedInt16>& outputArray)
00511       {
00512         outputArray = inputImage;
00513         return true;
00514       }
00515 
00516     
00517       template<>
00518       inline bool
00519       dissociateColorComponents(Image<GRAY32>& inputImage,
00520                                 Array2D<UnsignedInt32>& outputArray)
00521       {
00522         outputArray = inputImage;
00523         return true;
00524       }
00525 
00526     
00527       template<>
00528       inline bool
00529       dissociateColorComponents(Image<GRAY_SIGNED16>& inputImage,
00530                                 Array2D<Int16>& outputArray)
00531       {
00532         outputArray = inputImage;
00533         return true;
00534       }
00535 
00536     
00537       template<>
00538       inline bool
00539       dissociateColorComponents(Image<GRAY_SIGNED32>& inputImage,
00540                                 Array2D<Int32>& outputArray)
00541       {
00542         outputArray = inputImage;
00543         return true;
00544       }
00545 
00546     
00547       template<>
00548       inline bool
00549       dissociateColorComponents(Image<GRAY_FLOAT32>& inputImage,
00550                                 Array2D<Float32>& outputArray)
00551       {
00552         outputArray = inputImage;
00553         return true;
00554       }
00555 
00556     
00557       template<>
00558       inline bool
00559       dissociateColorComponents(Image<GRAY_FLOAT64>& inputImage,
00560                                 Array2D<Float64>& outputArray)
00561       {
00562         outputArray = inputImage;
00563         return true;
00564       }
00565 
00566     } // namespace privateCode
00568 
00569 
00570     // This function returns by reference an image which either shares
00571     // or copies the data from the input array.
00572     template<ImageFormat FORMAT>
00573     bool
00574     associateColorComponents(
00575       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& inputArray,
00576       Image<FORMAT>& outputImage)
00577     {
00578       return privateCode::associateColorComponents(inputArray, outputImage);
00579     }
00580 
00581     
00582     // This deprecated function tries to return an Image which
00583     // references the same memory as the input array, but in which each
00584     // pixel is the aggregate of the appropriate number of elements from
00585     // the array.  If it is not possible to do so, then this function
00586     template<ImageFormat FORMAT>
00587     Image<FORMAT>
00588     associateColorComponents(
00589       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& inputArray)
00590     {
00591       typedef typename ImageFormatTraits<FORMAT>::PixelType PixelType;
00592       if(!PixelType::isContiguous()) {
00593         DLR_THROW(dlr::LogicException, "associateColorComponents()",
00594                   "The deprecated single-argument version of "
00595                   "associateColorComponents() can only be use with "
00596                   "contiguous pixel types.");
00597       }
00598 
00599       Image<FORMAT> outputImage;
00600       associateColorComponents(inputArray, outputImage);
00601       return outputImage;
00602     }
00603 
00604 
00605     // This function takes an image in one colorspace and generates a
00606     // corresponding image in a second colorspace.
00607     template<ImageFormat OUTPUT_FORMAT, ImageFormat INPUT_FORMAT>
00608     Image<OUTPUT_FORMAT>
00609     convertColorspace(const Image<INPUT_FORMAT>& inputImage)
00610     {
00611       Image<OUTPUT_FORMAT> outputImage(
00612         inputImage.rows(), inputImage.columns());
00613       ColorspaceConverter<INPUT_FORMAT, OUTPUT_FORMAT> converter;
00614       std::transform(inputImage.begin(), inputImage.end(),
00615                      outputImage.begin(), converter);
00616       return outputImage;
00617     }
00618 
00619 
00620     // This function returns by reference an array which either shares
00621     // or copies the data from the input image.
00622     template<ImageFormat FORMAT>
00623     bool
00624     dissociateColorComponents(
00625       Image<FORMAT>& inputImage,
00626       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>& outputArray)
00627     {
00628       return privateCode::dissociateColorComponents(inputImage, outputArray);
00629     }
00630   
00631 
00632     // This deprecated function tries to return an Array2D which
00633     // references the same memory as the input image, but in which each
00634     // pixel has been "flattened" so that the returned array has a
00635     // separate element for each color component of each pixel.  If it
00636     template<ImageFormat FORMAT>
00637     Array2D<typename ImageFormatTraits<FORMAT>::ComponentType>
00638     dissociateColorComponents(Image<FORMAT>& inputImage)
00639     {
00640       typedef typename ImageFormatTraits<FORMAT>::PixelType PixelType;
00641       if(!PixelType::isContiguous()) {
00642         DLR_THROW(dlr::LogicException, "dissociateColorComponents()",
00643                   "The deprecated single-argument version of "
00644                   "dissociateColorComponents() can only be use with "
00645                   "contiguous pixel types.");
00646       }
00647       Array2D<typename ImageFormatTraits<FORMAT>::ComponentType> outputArray;
00648       dissociateColorComponents(inputImage, outputArray);
00649       return outputArray;
00650     }
00651 
00652   
00653     // This function subsamples its input to create a new, smaller
00654     // image.
00655     template<ImageFormat Format>
00656     Image<Format>
00657     subsample(const Image<Format>& inputImage,
00658               size_t rowStep,
00659               size_t columnStep)
00660     {
00661       // Argument checking.
00662       if(inputImage.size() == 0) {
00663         return Image<Format>();
00664       }
00665       if(rowStep == 0) {
00666         rowStep = 1;
00667       }
00668       if(columnStep == 0) {
00669         columnStep = 1;
00670       }
00671 
00672       // Output image size is at least (1, 1).  All rows and columns
00673       // must map to valid positions in the input image.
00674       Image<Format> outputImage((inputImage.rows() - 1) / rowStep + 1,
00675                                 (inputImage.columns() - 1) / columnStep + 1);
00676       for(size_t outputRowIndex = 0; outputRowIndex < outputImage.rows();
00677           ++outputRowIndex) {
00678         Array1D<typename Image<Format>::PixelType> inputRow =
00679           inputImage.row(rowStep * outputRowIndex);
00680         Array1D<typename Image<Format>::PixelType> outputRow =
00681           outputImage.row(outputRowIndex);
00682         size_t inputColumnIndex = 0;
00683         for(size_t outputColumnIndex = 0;
00684             outputColumnIndex < outputImage.columns();
00685             ++outputColumnIndex) {
00686           outputRow[outputColumnIndex] = inputRow[inputColumnIndex];
00687           inputColumnIndex += columnStep;
00688         }
00689       }
00690       return outputImage;
00691     }
00692 
00693 
00694     // This function interpolates its input to create a new, larger
00695     // image.
00696     template<ImageFormat InputFormat,
00697              ImageFormat OutputFormat,
00698              ImageFormat IntermediateFormat>
00699     Image<OutputFormat>
00700     supersample(const Image<InputFormat>& inputImage)
00701     {
00702       Image<OutputFormat> outputImage(inputImage.rows() * 2 - 1,
00703                                       inputImage.columns() * 2 - 1);
00704       ColorspaceConverter<InputFormat, OutputFormat> converter0;
00705       ColorspaceConverter<InputFormat, IntermediateFormat> converter1;
00706       ColorspaceConverter<IntermediateFormat, OutputFormat> converter2;
00707 
00708       // Working variables.
00709       typename ImageFormatTraits<IntermediateFormat>::PixelType tempPixel;
00710       Array1D<typename Image<InputFormat>::PixelType> inputRow0;
00711       Array1D<typename Image<InputFormat>::PixelType> inputRow1;
00712       Array1D<typename Image<OutputFormat>::PixelType> outputRow0;
00713       Array1D<typename Image<OutputFormat>::PixelType> outputRow1;
00714 
00715       // The main supersampling loop.
00716       for(size_t inputRowIndex = 0; inputRowIndex < (inputImage.rows() - 1);
00717           ++inputRowIndex) {
00718         inputRow0 = inputImage.row(inputRowIndex);
00719         inputRow1 = inputImage.row(inputRowIndex + 1);
00720         outputRow0 = outputImage.row(2 * inputRowIndex);
00721         outputRow1 = outputImage.row(2 * inputRowIndex + 1);
00722         size_t outputColumnIndex = 0;
00723         for(size_t inputColumnIndex = 0;
00724             inputColumnIndex < (inputImage.columns() - 1);
00725             ++inputColumnIndex) {
00726           outputRow0[outputColumnIndex] =
00727             converter0(inputRow0[inputColumnIndex]);
00728 
00729           // Note(xxx): This can be made more efficient.
00730           tempPixel = converter1(inputRow0[inputColumnIndex]);
00731           tempPixel += converter1(inputRow0[inputColumnIndex + 1]);
00732           tempPixel /= 2;
00733           outputRow0[outputColumnIndex + 1] = converter2(tempPixel);
00734 
00735           tempPixel = converter1(inputRow0[inputColumnIndex]);
00736           tempPixel += converter1(inputRow1[inputColumnIndex]);
00737           tempPixel /= 2;
00738           outputRow1[outputColumnIndex] = converter2(tempPixel);
00739 
00740           tempPixel = converter1(inputRow0[inputColumnIndex]);
00741           tempPixel += converter1(inputRow0[inputColumnIndex + 1]);
00742           tempPixel += converter1(inputRow1[inputColumnIndex]);
00743           tempPixel += converter1(inputRow1[inputColumnIndex + 1]);
00744           tempPixel /= 4;
00745           outputRow1[outputColumnIndex + 1] = converter2(tempPixel);
00746 
00747           outputColumnIndex += 2;
00748         }
00749         // Handle pixels at end of rows.
00750         outputRow0[outputColumnIndex] =
00751           converter0(inputRow0[inputRow0.size() - 1]);
00752 
00753         tempPixel = converter1(inputRow0[inputRow0.size() - 1]);
00754         tempPixel += converter1(inputRow1[inputRow0.size() - 1]);
00755         tempPixel /= 2;
00756         outputRow1[outputColumnIndex] = converter2(tempPixel);
00757       }
00758 
00759       // Handle final row.
00760       inputRow0 = inputImage.row(inputImage.rows() - 1);
00761       outputRow0 = outputImage.row(outputImage.rows() - 1);
00762       size_t outputColumnIndex = 0;
00763       for(size_t inputColumnIndex = 0;
00764           inputColumnIndex < (inputImage.columns() - 1);
00765           ++inputColumnIndex) {
00766         outputRow0[outputColumnIndex] =
00767           converter0(inputRow0[inputColumnIndex]);
00768 
00769         tempPixel = converter1(inputRow0[inputColumnIndex]);
00770         tempPixel += converter1(inputRow0[inputColumnIndex + 1]);
00771         tempPixel /= 2;
00772         outputRow0[outputColumnIndex + 1] = converter2(tempPixel);
00773 
00774         outputColumnIndex += 2;
00775       }
00776       outputRow0[outputImage.columns() - 1] =
00777         inputRow0[inputImage.columns() - 1];
00778 
00779       return outputImage;
00780     }
00781   
00782 
00783     // This function creates a new array and copies into it the pixel
00784     // data from the input image.
00785     template <class Type, ImageFormat FORMAT>
00786     Array2D<Type>
00787     toArray(const Image<FORMAT>& inputImage)
00788     {
00789       // A typedef for notational convenience.
00790       typedef typename ImageFormatTraits<FORMAT>::ComponentType ComponentType;
00791 
00792       size_t numberOfOutputColumns = inputImage.columns()
00793         * ImageFormatTraits<FORMAT>::getNumberOfComponents();
00794 
00795       Array2D<ComponentType> tempArray;
00796       dissociateColorComponents(
00797         const_cast< Image<FORMAT>& >(inputImage), tempArray);
00798 
00799       Array2D<Type> returnValue(inputImage.rows(), numberOfOutputColumns);
00800       returnValue.copy(tempArray);
00801       return returnValue;
00802     }
00803   
00804   } // namespace computerVision    
00805   
00806 } // namespace dlr
00807 
00808 #endif /* #ifndef _DLRCOMPUTERVISION_UTILITIES_H_ */

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