/** \file camellia.h * \brief Camellia Image Processing Library header file * \author Bruno STEUX (Mines Paris / ParisTech) * * Camellia Image Processing Library * The Camellia Image Processing Library is an open source low-level image processing library. As it uses the IplImage structure to describe images, it is a good replacement to the IPL (Intel) library and a good complement to the OpenCV library. It includes a lot of functions for image processing (filtering, morphological mathematics, labeling, warping, loading/saving images, etc.), some of them being highly optimized; It is also cross-platform and robust. It is doxygen-documented and examples of use are provided. This software library is an outcome of the Camellia european project (IST-2001-34410). It was developped by the Ecole des Mines de Paris (ENSMP), in coordination with the other partners of the project. ========================================================================== Copyright (c) 2002-2007, Ecole des Mines de Paris - Centre de Robotique All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Ecole des Mines de Paris nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ========================================================================== */ #ifndef _CAMELLIA_H_ #define _CAMELLIA_H_ #define CAM_VERSION "2.7.0 : Bastille ($Rev: 270 $)" #include /******************************************* * Compilation options : * */ // Pixel definition #define CAM_PIXEL unsigned char #define CAM_SIGNED_PIXEL signed char // Max image size #define CAM_MAX_SCANLINE 1280 #define CAM_MAX_FRAME_HEIGHT 1024 // 64-bit processor or memory bandwidth? #define CAM_64BITS // Pentium4 optimizations? #define CAM_OPT_P4 // Big endian architecture? //#define CAM_BIG_ENDIAN // Generate 8 AND 16 bits pixel size code #define CAM_GENERATE_FULL_CODE /* * *******************************************/ #ifdef _WIN32 #define CAM_INT64 __int64 #define CAM_UINT64 unsigned __int64 #else #define CAM_INT64 long long #define CAM_UINT64 unsigned long long #endif #ifdef __INTEL_COMPILER #define CAM_ALIGN16 __declspec(align(16)) #else #define CAM_ALIGN16 #endif #define CAM_FIXED_POINT signed long #define CAM_FLOAT2FIXED(x,dot_pos) ((CAM_FIXED_POINT)((x)*(1<(b))?(a):(b)) #define CAM_MIN(a,b) (((a)<(b))?(a):(b)) /*! \def CAM_RGBA * \brief 32 bits integer color representation, including an alpha channel. */ #define CAM_RGBA(r,g,b,a) ((r)|((g)<<8)|((b)<<16)|((a)<<24)) /*! \def CAM_RGB * \brief 24 bits integer color representation. Stricly equivalent to the Windows RGB macro. * Please use this one in place of RGB for better portability of the code. */ #define CAM_RGB(r,g,b) ((r)|((g)<<8)|((b)<<16)) #endif // SWIG /* General purpose structures */ /* Monadic and Dyadic Arithmetic Operators kernel */ #define CAM_ARITHM_ABS 0 #define CAM_ARITHM_INVERSE 1 #define CAM_ARITHM_SELECT 2 #define CAM_ARITHM_THRESHOLD 3 #define CAM_ARITHM_DOUBLE_THRESHOLD 4 #define CAM_ARITHM_ADD 0 #define CAM_ARITHM_SUM 0 #define CAM_ARITHM_SUB 1 #define CAM_ARITHM_MUL 2 #define CAM_ARITHM_ABSDIFF 3 #define CAM_ARITHM_WEIGHTED_SUM 4 #define CAM_ARITHM_INF 5 #define CAM_ARITHM_SUP 6 #define CAM_ARITHM_COMP_INF 7 #define CAM_ARITHM_COMP_EQUAL 8 #define CAM_ARITHM_COMP_SUP 9 #define CAM_ARITHM_AND 10 #define CAM_ARITHM_OR 11 // Shorter constants #define CAM_ABS 0 #define CAM_INVERSE 1 #define CAM_SELECT 2 #define CAM_THRESHOLD 3 #define CAM_DOUBLE_THRESHOLD 4 #define CAM_ADD 0 #define CAM_SUM 0 #define CAM_SUB 1 #define CAM_ABSDIFF 2 #define CAM_WEIGHTED_SUM 3 #define CAM_INF 4 #define CAM_SUP 5 #define CAM_COMP_INF 6 #define CAM_COMP_EQUAL 7 #define CAM_COMP_SUP 8 #define CAM_AND 9 #define CAM_OR 10 #ifndef SWIG /// This is the parameter structure for the arithmetic computation kernel /** Basically, it includes the code of the operation to execute, and * the different parameters for this operation. */ typedef struct { int operation; ///< Operation to apply to the sources int c1; ///< Additional parameter (see camMonadicArithm() and camDyadicArithm() for details) int c2; ///< Additional parameter (see camMonadicArithm() and camDyadicArithm() for details) int c3; ///< Additional parameter (see camMonadicArithm() and camDyadicArithm() for details) int c4; ///< Additional parameter (see camMonadicArithm() and camDyadicArithm() for details) } CamArithmParams; #endif // SWIG #ifdef __cplusplus extern "C" { #endif #ifndef SWIG /// This is the function that implements all the monadic arithmetic operators (i.e. operators with only one operand) /** This function can be used to compute the absolute value of an image (CAM_ARITHM_ABS), * to invert an image (CAM_ARITHM_INVERSE), to select all pixels with a given value in an image (CAM_ARITHM_SELECT), * to threshold an image either with one threshold value (CAM_ARITHM_THRESHOLD), or two threshold values (CAM_ARITHM_DOUBLE_THRESHOLD) * * \param source The source ::CamImage to process. The source must be a grey-level image, * except when the operation is an image inversion (CAM_ARITHM_INVERSE). * \param dest The destination ::CamImage. The destination image can be either a grey-level * image or a binary image. In the latter case, CAM_ARITHM_ABS is not a valid * operation * \param params A pointer to a ::CamArithmParams structure, defining all the parameters * of the function to apply to the source image. * * Here are the details on the operations and parameters to set in the ::CamArithmParams structure : * - CAM_ARITHM_ABS : Absolute value computation. pdest=abs(psource). * - CAM_ARITHM_INVERSE : Inverse. pdest=not(psource). * - CAM_ARITHM_SELECT : Selection of a part of an image. if (psource=c1) then pdest=c2 else pdest=c3. * - CAM_ARITHM_THRESHOLD : Comparison with a scalar (also called thresholding). if (psource. * - CAM_ARITHM_DOUBLE_THRESHOLD : Double thresholding. if (psource>c1 and psource. * * \return 0 (false) if an error occurs. An accumulator of all results pixel values otherwise. * * Note that this kernel supports in-place processing (i.e. dest can be the same as source param). * */ int camMonadicArithm(CamImage *source, CamImage *dest, CamArithmParams *params); /// This is the function that implements all the dyadic arithmetic operators (i.e. operators with two operands) /** This function can be used to compute the sum of two images (CAM_ARITHM_ADD), * to substract two images (CAM_ARITHM_SUB), to compute the absolute difference * between two images (CAM_ARITHM_ABSDIFF), to compute the weighted sum of two images (CAM_ARITHM_WEIGHTED_SUM), * etc. (see below) * * \param source1 The first source ::CamImage to process. Any source image can be either grey-level or * binary, depending on the operation to apply. * * \param source2 The second source ::CamImage to process. Any source image can be either grey-level or * binary, depending on the operation to apply. * * \param dest The destination ::CamImage. The destination image can be either a grey-level * image or a binary image, but source1, source2 and dest must be of the same kind. * * \param params A pointer to a ::CamArithmParams structure, defining all the parameters * of the function to apply to the source images. * * Here are the details on the operations and parameters to set in the ::CamArithmParams structure : * - CAM_ARITHM_ADD : Addition of images, with saturation. pdest=psource1+psource2; if (pdest<0) then pdest=0; if (pdest>valmax) then pdest=valmax. * - CAM_ARITHM_SUB : Substraction of images, with saturation. pdest=psource1-psource2; if (pdestvalmax) then pdest=valmax. * - CAM_ARITHM_MUL : Multiplication of images, with saturation. pdest=(psource1*psource2)>>c1; if (pdestvalmax) then pdest=valmax. * - CAM_ARITHM_ABSDIFF : Absolute difference, with saturation. pdest=abs(psource1-psource2). * - CAM_ARITHM_WEIGHTED_SUM : Weighted sum. pdest=(c1*psource1+c2*psource2)>>c3. * - CAM_ARITHM_INF : Inf. pdest=inf(psource1,psource2). * - CAM_ARITHM_SUP : Sup. pdest=sup(psource1,psource2). * - CAM_ARITHM_COMP_INF : Comparison. if (psource1. * - CAM_ARITHM_COMP_EQUAL : Equality test. if (psource1=psource2) pdest=c1 else pdest=c2. * - CAM_ARITHM_COMP_SUP : Comparison. if (psource1>psource2) pdest=c1 else pdest=c2. * - CAM_ARITHM_AND : pdest=psource1 & psource2 (arithmetic boolean "and" operator) * - CAM_ARITHM_OR : pdest=psource1 | psource2 (arithmetic boolean "or" operator) * * \return 0 (false) if an error occurs. An accumulator of all results pixel values otherwise. * * Note that this kernel supports in-place processing (i.e. dest can be the same as one of the sources). * * Note also that this kernel supports signed images, and thus can produce signed results * (see the member depth in ::CamImage structure). * */ int camDyadicArithm(CamImage *source1, CamImage *source2, CamImage *dest, CamArithmParams *params); /// Image addition /** Simple wrapper for camDyadicArithm() */ int camAdd(CamImage *source1, CamImage *source2, CamImage *dest); /// Image multiplication /** Simple wrapper for camDyadicArithm() */ int camMul(CamImage *source1, CamImage *source2, CamImage *dest); /// Image subtraction /** Simple wrapper for camDyadicArithm() */ int camSub(CamImage *source1, CamImage *source2, CamImage *dest); /// Simple threshold function (wrapper for camMonadicArithm() function) /** Turn all pixels below (<) the threshold value to 0, and all pixels above (>=) to 255 */ int camThreshold(CamImage *source, CamImage *dest, int threshold); /// Simple threshold function (wrapper for camMonadicArithm() function) /** Turn all pixels below (<) the threshold value to 255, and all pixels above (>=) to 0 */ int camThresholdInv(CamImage *source, CamImage *dest, int threshold); /// Compute absolute value of image (for signed images) (wrapper for camMonadicArithm() function) int camAbs(CamImage *source, CamImage *dest); /* Apply-a-LUT-on-image Kernel */ // 12 bits maximum LUT management #define CAM_TABLE_SIZE 4096 #define CamLUT CamTable #define CamHisto CamTable #ifdef __cplusplus /// Pixel table (LUT (Look-Up Table) and histogram) structure struct CamTable { #else /// LUT (Look-Up Table) structure typedef struct { #endif int t[CAM_TABLE_SIZE]; ///< Table containing the resulting pixel value for each input int size; ///< Number of valid entries #ifdef __cplusplus CamTable(int s=0) {size=s;} int &operator[](int n); bool set(const int* const array, int sz) { if (sz=0)&&(x=0)&&(y=0)&&(x=0)&&(y=0)&&(x=0)&&(y=0)&&(x=0)&&(ytop, left, width, height, cx, cy, * and surface. average, min and max * are computed only if a pointer on the original image is provided (slower). * * \param blobImage The result of a previous labeling operation. * \param original The original ::CamImage that was labelled previously. Can bet set to NULL. * \param info The ::CamLabelingResults structure provided by the former call to camLabeling().(in data) * \param results The ::CamBlobs structure that is filled with the collected blob information. * * \return 0 (false) if an error occurs, especially if the number of blobs is too high.(more than the CAM_LABEL_MAX_BLOBS constant) * * In-place processing (blobImage will be affected). */ int camBlobAnalysis1stScan(CamImage *blobImage, CamImage *original, CamLabelingResults *info, CamBlobs *results); ///< Blob analysis function. /// Second pass, to get some more information if needed. /** Computes the average, min and max blob information, if it was * not computed before. * * \param blobImage The result of a previous labeling operation. * \param original The original ::CamImage.that was labelled previously. * \param results The ::CamBlobs structure that is filled with the collected blob information. * * \return 0 (false) if an error occurs. */ int camBlobAnalysisRefinement(CamImage *blobImage, CamImage *original, CamBlobs *results); /* RLE Labeling kernel * New : v1.4 of LLAs * Updated v1.6 and v1.9, v2.0 of LLAs */ /** @name RLE images processing functions and data structures */ //@{ #ifdef __cplusplus /// The CamRLEImage structure : the RLE (Run Length Encoded) image structure. struct CamRLEImage { #else /// The CamRLEImage structure : the RLE (Run Length Encoded) image structure. typedef struct { #endif int nSize; ///< Size of CamImage struct int id; ///< Frame id (user dependent) int height; ///< Image height int width; ///< Image width int nbRuns; ///< The number of runs int allocated; ///< Number of runs allocated CamRun *runs; ///< A pointer to the array of runs #ifdef __cplusplus CamRLEImage() {nSize=sizeof(CamRLEImage); allocated=0; runs=NULL; nbRuns=0;} ///< Default constructor CamRLEImage(int nbruns); ///< Constructor with max number of runs parameter CamRLEImage(const CamRLEImage &image); ///< Copy constructor ~CamRLEImage(); ///< Default destructor CamRLEImage& operator=(const CamRLEImage &image); ///< Operator= redefinition CamRLEImage* clone() const; ///< Clone RLE image (using camRLEClone() function) bool alloc(int nbruns); ///< Allocator (C++ wrapping of camRLEAllocate() function) bool realloc(int nbruns); ///< Reallocator (C++ wrapping of camRLEReallocate() function) bool encode(const CamImage &image); ///< C++ wrapping for camRLEEncode() function bool encode_lut(const CamImage &image, const CamTable &LUT); ///< C++ wrapping for camRLEEncodeLUT() function bool encode_threshold(const CamImage &image, int threshold); ///< C++ wrapping for camRLEEncodeThreshold() function bool encode_threshold_inv(const CamImage &image, int threshold);///< C++ wrapping for camRLEEncodeThresholdInv() function bool encode_color(const CamImage &image, const CamTable &clusters); ///< C++ wrapping for camRLEEncodeColor() function CamBlobs* labeling(); ///< C++ wrapping for camRLELabeling() function bool labeling(CamBlobs &results); ///< C++ wrapping for camRLELabeling() function bool blob_analysis(CamBlobs &results) const; ///< C++ wrapping for camRLEBlobAnalysis() function bool apply_lut(const CamTable &LUT); ///< C++ wrapping for camRLEApplyLUT() function bool apply_lut(CamRLEImage &dest, const CamTable &LUT) const; ///< C++ wrapping for camRLEApplyLUT() function bool decode(CamImage &dest) const; ///< C++ wrapping for camRLEDecode() function bool decode(CamImage &dest, const CamTable &LUT) const; ///< C++ wrapping for camRLEDecode() function bool decode_blobs(CamImage &dest) const; ///< C++ wrapping for camRLEDecodeBlobs() function bool decode_blobs(CamImage &dest, const CamTable &LUT) const; ///< C++ wrapping for camRLEDecodeBlos() function bool inverse(); ///< C++ wrapping for camRLEInverse() function bool erode_cross(CamRLEImage &dest) const; ///< C++ wrapping for camRLEErodeCross() function CamRLEImage *erode_cross() const; ///< C++ wrapping for camRLEErodeCross() function bool erode_3x3(CamRLEImage &dest) const; ///< C++ wrapping for camRLEErode3x3() function CamRLEImage *erode_3x3() const; ///< C++ wrapping for camRLEErode3x3() function bool erode_3x2(CamRLEImage &dest) const; ///< C++ wrapping for camRLEErode3x2() function CamRLEImage *erode_3x2() const; ///< C++ wrapping for camRLEErode3x2() function }; #else } CamRLEImage; #endif /// RLE Image allocation. /** Allocates a RLE image. * * \param rle The ::CamRLEImage to allocate. The number of runs should be chosen * so that it is enough to encode the image to process. A typical value * used for this parameter is source.width*source.height/16, assuming * a typical run will of length 16. Note that this is very realistic when * the original image was thresholded and filtered. * \param max_runs The number of runs to allocate. * \return 0 (false) if an error occurs. * * Note that this function uses the standard C malloc() function. * * Note also that the amount of memory allocated is 8*max_runs bytes. Thus, using * the typical max_runs value exposed above, a grey-level image will be compressed * by a factor of 2, and a binary image expanded by a factor of 4 using RLE encoding. * * The RLE image should be deallocated using the camRLEDeallocate() function, * or by calling the standard C function free() on the * runs member of the ::CamRLEImage structure. * */ int camRLEAllocate(CamRLEImage *rle, int max_runs); /// RLE image deallocation. /** Release a RLE image memory. Should be matched with a call to camRLEAllocate() * * \param rle The ::CamRLEImage to deallocate. * \return 0 (false) if an error occurs. * * Note that this function uses the standard C free() function. * */ int camRLEDeallocate(CamRLEImage *rle); /// Alias for camRLEDeallocate() function int camRLEFree(CamRLEImage *rle); /// RLE image reallocation /** Reallocates a RLE image. * * \param rle The ::CamRLEImage to reallocate. * \param new_max_runs The new number of allocated runs * \return 0 (false) if an error occurs. * * Note that this function uses the standard C realloc() function. * */ int camRLEReallocate(CamRLEImage *rle, int new_max_runs); /// RLE image cloning /** Clone a RLE image. * * \param source The ::CamRLEImage to clone. * \param dest The ::CamRLEImage to allocate (shouldn't be allocated) * \return 0 (false) if an error occurs. * * Note that this function uses the standard C malloc() function. */ int camRLEClone(CamRLEImage *source, CamRLEImage *dest); /// Run-Length encoding /** * \param src The source ::CamImage to encode. This should be either a thresholded * image or a binary image. Note that this source image should be filtered * (using camErode3x3() for instance) before encoding, * in order to avoid a too high number of runs. * \param dest The ::CamRLEImage resulting of the encoding. * \return 0 (false) if an error occurs. * * Note that binary images encoding was optimized. */ int camRLEEncode(CamImage *src, CamRLEImage *dest); /// Run-Length encoding, with integrated LUT operations. /** Introduced v1.9. * * \param src The source ::CamImage to encode. This must be a grey-level image. * Note that this source image should be filtered * (using camErode3x3() for instance) before encoding, * in order to avoid a too high number of runs. * \param dest The ::CamRLEImage resulting of the encoding. * \param LUT An array of integer used to classify the source image pixels. * \return 0 (false) if an error occurs. */ int camRLEEncodeLUT(CamImage *src, CamRLEImage *dest, CamTable *LUT); /// Run-Length encoding, with integrated thresholding. /** \param src The source ::CamImage to encode. This must be a grey-level image. * Note that this source image should be filtered * (using camErodeSquare3() for instance) before encoding, * in order to avoid a too high number of runs. * \param dest The ::CamRLEImage resulting of the encoding. * \param threshold The threshold used. All pixels with value higher (>=) than threshold will be labelled.. * \return 0 (false) if an error occurs. */ int camRLEEncodeThreshold(CamImage *src, CamRLEImage *dest, int threshold); /// Run-Length encoding, with integrated thresholding. /** \param src The source ::CamImage to encode. This must be a grey-level image. * Note that this source image should be filtered * (using camErodeSquare3() for instance) before encoding, * in order to avoid a too high number of runs. * \param dest The ::CamRLEImage resulting of the encoding. * \param threshold The threshold used. All pixels with value lower (>=) than threshold will be labelled.. * \return 0 (false) if an error occurs. */ int camRLEEncodeThresholdInv(CamImage *src, CamRLEImage *dest, int threshold); int camRLEEncodeColor(CamImage *source, CamRLEImage *dest, CamTable *clusters); /// RLE image labeling + blob analysis. 4-connectedness labeling. /** Very fast labeling algorithm originally introduced by the Carneggie Mellon University (see below). * This function also performs a basic blob analysis * * \param src The source ::CamRLEImage to label. Note that the content of src is altered, * for RLE labeling is performed in-place. This is what makes it especially fast, * since it doesn't require neither an additional label image nor an equivalence * table, everything being stored in the ::CamRLEImage structure. * \param results The ::CamBlobs containing the results of the blob analysis. * \return 0 (false) if an error occurs. Generally when the number * of blobs exceeds the CAM_LABEL_MAX_BLOBS constant. * * This code is based on the ideas developped in the CMVision library by CMU. * * \verbatim ------------------------------------------------------------------------- Copyright 1999, 2000 #### ### ### ## ## ## #### ## ### ## ## James R. Bruce ## ####### ## ## ## ## ## ## ## ###### School of Computer Science ## ## # ## ## ## ## ### ## ## ## ## ### Carnegie Mellon University #### ## ## ### ## #### ## ### ## ## ------------------------------------------------------------------------- * \endverbatim */ int camRLELabeling(CamRLEImage *src, CamBlobs *results); /// The RLE Blob Analysis function /** Automatically called by camRLELabeling(). * * \param src The source ::CamRLEImage, already labelled. * \param results The ::CamBlobs containing the results of the blob analysis. * \return 0 (false) if an error occurs. Generally when the number * of blobs exceeds the CAM_LABEL_MAX_BLOBS constant. */ int camRLEBlobAnalysis(CamRLEImage *src, CamBlobs *results); /// The RLE "Apply a LUT" function /** Very useful to post-process a RLE image. This function join runs when needed. * * Applying a LUT (i.e. for instance thresholding) can be useful * for many purposes (like "several thresholds at once" processing). For experts only. * * \param src The source ::CamRLEImage. * \param dest The destination ::CamRLEImage. * \param LUT Look-up-table applied to the value member of each run. * \return 0 (false) if an error occurs. */ int camRLEApplyLUT(CamRLEImage *src, CamRLEImage *dest, CamTable *LUT); /// The RLE decoding function /** Reconstructs an ::CamImage from runs. * * \param src The source ::CamRLEImage. * \param dest The destination ::CamImage. Must be grey-level image * (binary image RLE decoding not yet implemented). * \param LUT Look-up-table applied to the value member of each run, to produce * the pixel value in the dest image. * \return 0 (false) if an error occurs. * * \todo Implement binary image RLE decoding */ int camRLEDecode(CamRLEImage *src, CamImage *dest, CamTable *LUT); /// Another RLE decoding function, used to retrieve some specific blobs. /** Reconstructs an ::CamImage from a labelled RLE image. Very useful to see the result of labeling. * * \param src The source ::CamRLEImage. * \param dest The destination ::CamImage. Must be grey-level image * (binary image RLE decoding not yet implemented). * \param LUT Look-up-table applied to the blob member of each run, to produce * the pixel value in the dest image. * \return 0 (false) if an error occurs. * * \todo Implement binary image RLE decoding */ int camRLEDecodeBlobs(CamRLEImage *src, CamImage *dest, CamTable *LUT); /// RLE image inversion /** Very useful function, for finding holes in blobs. * \param image The source and destination ::CamRLEImage. In-place processing only. * \return 0 (false) if an error occurs. */ int camRLEInverse(CamRLEImage *image); /// RLE blob sides reconstruction int camRLEBlobSides(CamBlobInfo *blob, int *left, int *top, int *right, int *bottom); /// RLE blob intersection with a ROI int camRLEBlobROIIntersect(CamBlobInfo *blob, CamROI *roi); /// Retrieves the average, min and max values int camRLEBlobMeasures(CamBlobInfo *blob, CamImage *original); /// RLE image erosion (cross structural element) /** * \param image The source ::CamRLEImage. * \param result The destination ::CamRLEImage * \return 0 (false) if an error occurs. */ int camRLEErodeCross(CamRLEImage *image, CamRLEImage *result); /// RLE image erosion (3x3 square structural element) /** * \param image The source ::CamRLEImage. * \param result The destination ::CamRLEImage * \return 0 (false) if an error occurs. */ int camRLEErode3x3(CamRLEImage *image, CamRLEImage *result); /// RLE image erosion (3x2 square structural element) /** * \param image The source ::CamRLEImage. * \param result The destination ::CamRLEImage * \return 0 (false) if an error occurs. */ int camRLEErode3x2(CamRLEImage *image, CamRLEImage *result); //@} /** @name Histogram computation */ //@{ /// The classical image histogramming /** Counts the number of occurence of each pixel value, on one channel only * (grey-level image), for images up to 12-bits deep. It supports signed images * by centering the histogram around the 0 value. * * \param image The ::CamImage to analyze. One channel only. * \param histo A pointer to a CamTable (array of integers) that will contain the results of histogramming. * \return 0 (false) if an error occurs. Accumulated values of scanned pixels otherwise. * * camHistogram supports masking and ROIs. */ int camHistogram(CamImage *image, CamTable *histo); #define CAM_EQUAL_PERFECT 0 #define CAM_EQUAL_FAST 1 /// Histogram Equalization /** Performs a histogram equalization, with no holes. * * \param src The ::CamImage to equalize. One channel only. * \param dest The resulting equalized image. * \param src_histo The histogram of the source image, obtained by a previous call to camHistogram(). * \param option CAM_EQUAL_FAST or CAM_EQUAL_PERFECT (default) * \param work A ::CamImage used for internal computation. If set to NULL, allocation and deallocation will be done internally. * \return 0 (false) if an error occurs. * * camHistogramEqualization supports in-place operation, masking and ROIs. */ int camHistogramEqualization(CamImage *src, CamImage *dest, CamTable *src_histo, int option, CamImage *work); /// Two channels histogram computation /** The result of this operation is 2D, and thus is stored in an image. * * \param image The ::CamImage for which to compute the histogram * \param ch1 The first channel number * \param ch2 The second channel number * \param result The ::CamImage containing the results of histogramming. * \param size Subsampling factor. size=1 results in a 256x256 picture, size=2 results in a 128x128 picture, etc. * \return 0 (false) if an error occurs. */ int camHistogram2Channels(CamImage *image, int ch1, int ch2, CamImage *result, int size); /// Compute the threshold for a given percentage of pixels int camFindThreshold(CamTable *histo, int percent); //@} /* Horizontal and vertical summing */ /// Horizontal and vertical summing function /** Very useful to detect features in images, generally after applying * a filter like sobel or morphological gradient. * * \param image The ::CamImage to process (or its ROI) * \param hsum The ::CamTable array of integers containing the horizontal sum. * \param vsum The ::CamTable array of integers containing the vertical sum. * \return 0 (false) if an error occurs. */ int camSumHV(CamImage *image, CamTable *hsum, CamTable *vsum); /// Vertical summing function /** Very useful to detect features in images, generally after applying * a filter like sobel or morphological gradient. * * \param image The ::CamImage to process (or its ROI) * \param results The ::CamTable array of integers filled with results. * \return 0 (false) if an error occurs. */ int camSumV(CamImage *image, CamTable *results); /// Horizontal summing function /** Very useful to detect features in images, generally after applying * a filter like sobel or morphological gradient. * * \param image The ::CamImage to process (or its ROI) * \param results The ::CamTable array of integers filled with results. * \return 0 (false) if an error occurs. */ int camSumH(CamImage *image, CamTable *results); #endif // SWIG /* Measures in an image : min, max, average computation */ #ifdef __cplusplus /// The structure containing the result of measuring struct CamMeasuresResults { #else /// The structure containing the result of measuring typedef struct { #endif int min, xmin, ymin; ///< Minimum pixel value int max, xmax, ymax; ///< Maximum pixel value int average; ///< Average pixel value int sum; ///< Sum of all the pixels #ifdef __cplusplus CamMeasuresResults() {min=0;xmin=0;ymin=0;max=0;xmax=0;ymax=0;average=0;sum=0;} }; #else } CamMeasuresResults; #endif #ifndef SWIG /// Sum of pixels in an image int camSumOfPixels(CamImage *image); /// Measures in an image : min, max, average and sum /** Average deviation is not measured. See camMeasureAverageDeviation(). * * \param image The ::CamImage to process (or its ROI) * \param results The ::CamMeasuresResults structure to be filled. * \return 0 (false) if an error occurs. */ int camMeasures(CamImage *image, CamMeasuresResults *results); /// Average deviation computation /** This makes the second scan required for average deviation estimation. * Uses the average field in ::CamMeasuresResults structure, so camMeasures() * must have been called prior to this function (to do the 1st scan). * * \param image The ::CamImage to process (or its ROI) * \param average A former measure of average. If 0 or a negative number is provided, the average will be computed * \return 0 (false) if an error occurs. */ float camMeasureAverageDeviation(CamImage *image, int average); /** @name Warping functions */ //@{ /// Warping using Volberg's algorithm /** This is a forward separable mapping algorithm, i.e. the user * must provide two functions that compute the destination points * of any source point. * * This function is the core function, making a single scanline mapping. * It must be called twice to have a full mapping. Use camVolbergFwd() * to do this. */ #ifdef CAM_VOLBERG_ORIGINAL void volbergfvd(double f[], int in[] , int out[] , int inlen, int outlen); #else void camVolbergFwdScanline(CAM_PIXEL *in, int inlen, CAM_PIXEL *out, int outlen, double f[]); #endif /// The structure to provide to the Volberg's algorithm : two functions typedef struct { void (*hfwd)(int x, int y, double *xp); ///< First scan, horizontal resampling void (*vfwd)(int x, int y, double *yp); ///< Second scan, vertical resampling } CamVolbergFwdParams; /// Helper function for using Volberg's warping algorithm /** * \param source The ::CamImage to warp * \param dest The warped image * \param params The ::camVolbergFwdParams structure providing the mapping functions */ void camVolbergFwd(CamImage *source, CamImage *dest, CamVolbergFwdParams *params); /* Backward warping */ #endif // SWIG #define CAM_NN_INTERPOLATION 0 #define CAM_BILINEAR_INTERPOLATION 1 #ifndef SWIG /// The parameters structure used by camWarping() typedef struct { int interpolation; ///< Interpolation method (either CAM_NN_INTERPOLATION or CAM_BILINEAR_INTERPOLATION. int perspective; ///< 2D (0) or 3D (parallel to the ground) /// The points in the source image. /** Beware : These are 16-bits fixed-points (1 is (1<<16)). * * Indexes : * - 0 : top-left source point * - 1 : top-right source point * - 2 : bottom-right source point * - 3 : bottom-left source point */ CamPoint p[4]; } CamWarpingParams; /// Backward warping function /** This function operates a backward mapping from the source image to a destination image. * All the params refer to locations in the source image, whereas the ROI scanned * by this warping function is set by the roi member of the dest image * * \param source The ::CamImage to warp * \param dest The warped image * \param params The ::CamWarpingParams structure providing the ROI in the source image (not rectangular) * */ int camWarping(CamImage *source, CamImage *dest, CamWarpingParams *params); /// Scaling function /** This function operates a scaling from the source image to the destination image. * It can upscale or downscale pictures, and uses bilinear interpolation technique. * * \param source The ::CamImage to warp * \param dest The warped image */ int camScale(CamImage *source, CamImage *dest); int camWarpingSuperSampling(CamImage *source, CamImage *dest, CamWarpingParams *params); /// Simple helper function, used by camWarping() /** * \param p An array defining the segments to intersect (AB and CD). These points * must be provided in 16-bits fixed-point arithmetic form (1 is (1<<16)). * \param res The intersection point. * \return 0 if the segments are parallel. 1 otherwise */ int camIntersectionSegments(CamPoint p[4], CamPoint *res); //@} /** @name Linear filtering kernel */ //@{ // For compatibility with older versions #define CamSobel3x3 camSobel #define CamSobelAbs3x3 camSobelAbs #define CAM_LINEAR_FILTER_KERNEL_MAX_SIZE 7 #endif //SWIG #ifdef __cplusplus /// The parameters structure for linear filtering struct CamLinearFilterKernel { #else /// The parameters structure for linear filtering typedef struct { #endif #ifndef SWIG int kernel[CAM_LINEAR_FILTER_KERNEL_MAX_SIZE][CAM_LINEAR_FILTER_KERNEL_MAX_SIZE]; ///< The NxN coefficients matrix (aka the kernel) #endif int coeff1; ///< Multiplicative coefficient int coeff2; ///< Final value is (result*coeff1)>>coeff2. This is to simulate division. #ifdef __cplusplus /// Default constructor CamLinearFilterKernel() { for (int i=0;i=0)&&(x=0)&&(y=0)&&(x=0)&&(y>coeff2. This is to simulate division. #ifdef __cplusplus /// Default constructor CamSepFilterKernel() { for (int i=0;i=0)&&(y=0)&&(x=0)&&(y=0)&&(xCAM_SOBEL_H performs a horizontal edges detection (3x3 sobel) * - CAM_SOBEL_V performs a vertical edges detection (3x3 sobel) * - CAM_GAUSSIAN_3x3 performs a gaussian filtering * - CAM_GAUSSIAN_5x5 performs a gaussian filtering * - CAM_GAUSSIAN_7x7 performs a gaussian filtering * - CAM_SCHARR_H performs a horizontal edges detection (3x3 scharr filter. Better preserves gradient direction) * - CAM_SCHARR_V performs a vertical edges detection (3x3 scharr filter. Better preserves gradient direction) * * \return 1 if the function succeeds. 0 otherwise. * * Note that this function supports in-place processing (i.e. dest can be the same as source param) * * Note also that signed saturation is to (-127;+127) instead of the traditional signed char (-128;+127), * so that results of filtering are unbiased. */ int camFixedFilter(CamImage *source, CamImage *dest, int filter); int camScharrH(CamImage *source, CamImage *dest); int camScharrV(CamImage *source, CamImage *dest); int camScharrHAbs(CamImage *source, CamImage *dest); int camScharrVAbs(CamImage *source, CamImage *dest); //@} /** @name Median filtering kernel */ //@{ #define camMedianFiltering3x3 camMedianFilter3x3 #define camMedianFiltering5x5 camMedianFilter5x5 /// 3x3 Median Filtering function /** For each 3x3 set of pixels, keep the median value. Considered as being a * good filter, less sensitive to noise.than linear filtering. * * \param source The source ::CamImage to process. Grey scale only. * \param dest The destination ::CamImage * \return 0 (false) if an error occurs * * Note that this function supports in-place processing (i.e. dest can be the same as source param) */ int camMedianFilter3x3(CamImage *source, CamImage *dest); /// 5x5 Median Filtering function /** For each 5x5 set of pixels, keep the median value. Considered as being a * good filter, less sensitive to noise.than linear filtering. * * \param source The source ::CamImage to process. Grey scale only. * \param dest The destination ::CamImage * \return 0 (false) if an error occurs * * Note that this function supports in-place processing (i.e. dest can be the same as source param) */ int camMedianFilter5x5(CamImage *source, CamImage *dest); //@} /** @name Watersheding kernel */ //@{ /// 1D watershed computation /** Retrieves all the watershed points, along with their depth (i.e. the minimum depth of * the 2 catchment bassins contributing to the watershed point). * * 1D watersheding operation is a very smart way to analyze the results of an histogram * (generally before thresholding), yielding better results than a simple n% threshold. * * \param input The 1D integer data for which to compute the watershed * \param size The size of the 1D integer array (t). Generally 256 when t is the * results of an histogramming operation. * \param results The 1D integer array contaning the results of the watershed computation. * A value different from 0 indicates a watershed point, the value indicating the depth * (and thus the importance) associated to this watershed point. * The memory for this array is not allocated by this function, and thus an array * of appropriate size must be allocated before calling this function. * * \return 0 (false) if an error occurs */ int camWatershed1D(int *input, int size, int *results); #else %immutable; #endif // SWIG /// The structure defining a basin typedef struct { int dynamics; ///< Its dynamics (importance) int minimum; ///< Minimum of the basin int flooded; ///< The catchment basin which has flooded it int surface; ///< Surface of the region int accsurface; ///< Accumulated surface of all children unsigned short x,y; ///< Position of the minimum } CamBasin; #define CAM_NOT_COMPUTED 65536 #ifndef SWIG #ifdef __cplusplus /// The table of basins structure. Simply a dynamic size array of CamBasin. struct CamTableOfBasins { int sizeMax; int nbBasins; CamBasin *tab; CamBasin& operator[](int index) {return tab[index];} void get_rid_of(CamBasin &basin) {basin.surface=0;} CamTableOfBasins() {tab=NULL;sizeMax=0;nbBasins=0;} ~CamTableOfBasins(); }; #else typedef struct { int sizeMax; int nbBasins; CamBasin *tab; } CamTableOfBasins; #endif /// Free a table of basins after use. void camFreeTableOfBasins(CamTableOfBasins *t); /// 2D Hierarchical watershed computation /** Retrieves all the basins (regional segmentation) * * Watersheding computes a hierarchichal segmentation of an image. * Watersheding operation is a very smart way to analyze the results of a gradient image. * * \param source The ::CamImage for which to compute the watershed * \param dest A 16-bits deep ::CamImage where the results of the watersheding operation are stored. * The index of the basin is given by the pixel value minus 1 (so starting at 1). * Border pixels are set to -32768. * dest must be allocated by the caller, and must have the same size as * the source image. It must also be a signed 16 bits deep image (CAM_DEPTH_16S). * \param tob The table of basins, containing their dynamics, their surface and their minimum value. * This table is allocated by the function. * * \return 0 (false) if an error occurs */ int camHierarchicalWatershed(CamImage *source, CamImage *dest, CamTableOfBasins *tob); /// 2D Hierarchical watershed computation (with watershed/contours markers) /** Retrieves all the watershed points, along with all the basins (regional segmentation) * * Watersheding computes a hierarchichal segmentation of an image. * Watersheding operation is a very smart way to analyze the results of a gradient image. * * \param source The ::CamImage for which to compute the watershed * \param dest A 16-bits deep ::CamImage where the results of the watersheding operation are stored. * A negative pixel value indicates a watershed point. * A positive indicates that this pixel belongs to a basin. * The index of the basin is given by the pixel value minus 1. Border pixels are set to -32768. * dest must be allocated by the caller, and must have the same size as * the source image. It must also be a signed 16 bits deep image (CAM_DEPTH_16S). * \param tob The table of basins, containing their dynamics, their surface and their minimum value. * This table is allocated by the function. * * \return 0 (false) if an error occurs */ int camHierarchicalWatershedContours(CamImage *source, CamImage *dest, CamTableOfBasins *tob); /// Retrieves regions from a watershed image /** Retrieves all the regions of basins with surface different from 0. The user can set the surface of a basin in * the table of basins to deselect it. Thus, the user can remove from the watershed image all the basins with * low dynamics, and the pixels of this basin will be affected to a flooding basin. * * \return 0 (false) if an error occurs */ int camHierarchicalWatershedRegions(CamImage *watershed, CamTableOfBasins *tob); //@} /** @name Hough functions */ //@{ /// Circle Hough. Find a circle in a picture. /** Find a circle in the input picture. Returns the circle with the bigger hough accumulation. * * \param image The ::CamImage to process * \param percent The percentage of pixels to consider (from the gradient image). Directly proportionnal to the speed of exection. Typically 10. * \param rmin The minimum radius to look for * \param rmax The maximum radius to look for. This determines the size of the (x,y,r) Hough cube * \param xc A pointer to the circle center (return value) * \param yc A pointer to the circle center (return value) * \param rc A pointer to the circle radius (return value) * * \return The confidence in the circle found (hough accumulator) */ int camHoughCircle(CamImage *image, int percent, int rmin, int rmax, int *xc, int *yc, int *rc); struct _CamKeypoints; #endif // SWIG /** @name Keypoints and Local descriptors */ //@{ #ifdef __cplusplus #ifdef SWIG %mutable; #endif /// The Keypoint structure struct CamKeypoint { #else typedef struct { #endif // __cplusplus int descriptor[128]; ///< The descriptor table itself int x; ///< x coordinate of keypoints in image int y; ///< y coordinate of keypoints in image int scale; ///< Scale in pixels int angle; ///< Angle in degrees int value; ///< Hessian value #ifdef SWIG %immutable; #endif int size; ///< Size of descriptor void *internal; ///< Internal use only #ifdef __cplusplus CamKeypoints *set; bool draw(CamImage &image, int color = 255) const; ///< C++ wrapping for camDrawKeypoint function bool set_descriptor(const int* const array, int sz); ///< Set the descriptor CamKeypoint() { x = 0; y = 0; scale = 0; angle = 0; value = 0; size = 0; internal = NULL; set = NULL; } }; #else struct _CamKeypoints *set; } CamKeypoint; #endif typedef struct { CamKeypoint *p1; CamKeypoint *p2; int mark; int error; } CamKeypointsMatch; #define CAM_MAX_NB_MATCHES 2048 #ifdef __cplusplus /// Affine Transform parameters struct CamAffineTransform { double m[6]; }; /// A match between 2 CamKeypoints struct CamKeypointsMatches { #else typedef struct { double m[6]; } CamAffineTransform; typedef struct { #endif //__cplusplus int nbMatches; int nbOutliers; int allocated; CamKeypointsMatch *pairs; #ifdef __cplusplus CamKeypointsMatches(int size = CAM_MAX_NB_MATCHES); ///< Default constructor ~CamKeypointsMatches(); ///< Default destructor CamAffineTransform find_affine_transform(int *error) const; ///< C++ wrapping for camFindAffindTransform function CamAffineTransform find_affine_transform2(int *error) const; ///< C++ wrapping for camFindAffindTransform function }; #else } CamKeypointsMatches; #endif #ifdef __cplusplus struct CamKeypointsKdTree; #ifdef SWIG %mutable; #endif /// The CamKeypoints structure struct CamKeypoints { #else /// The CamKeypoints structure typedef struct _CamKeypoints { #endif int width, height; ///< Original size of object (or picture of object) int cx, cy; ///< Reference coordinate of object (center) int id; ///< Id of reference object #ifdef SWIG %immutable; #endif int allocated; int nbPoints; ///< Number of valid points CamKeypoint **keypoint; ///< Array of keypoints CamKeypoint *bag; ///< Bag of keypoints #ifdef __cplusplus CamKeypoints() {allocated = 0; nbPoints = 0; keypoint = NULL; bag = NULL; cx = 0; cy = 0;} ///< Default constructor CamKeypoints(int nbPoints); ///< Constructor with max number of points #ifndef SWIG CamKeypoint& operator[](int index); #endif ~CamKeypoints(); ///< Default destructor bool add(CamKeypoint &p); CamKeypoints& operator<<(CamKeypoint &p) { add(p); return *this; } bool draw(CamImage &image, int color = 255) const; ///< C++ wrapping for camDrawKeypoints function int matching(const CamKeypoints **models, int nbModels, CamKeypointsMatches &matches) const; ///< C++ wrapping for camKeypointsMatching() function int matching2(const CamKeypoints &points, CamKeypointsMatches &matches) const; ///< C++ wrapping for camKeypointsMatching2() function int matchingKdTree(const CamKeypointsKdTree &kdTree, CamKeypointsMatches &matches, int explore = 100) const; ///< C++ wrapping for camKeypointsMatchingKdTree() function bool alloc(int nbPoints); ///< Allocator (C++ wrapping of camKeypointsAllocate() function) bool realloc(int nbPoints); ///< Reallocator (C++ wrapping of camKeypointsReallocate() function) }; #else } CamKeypoints; #endif #define CAM_UPRIGHT 1 int camKeypointsSetParameters(int patchSize, int sigma, int threshGradient); #ifndef SWIG /// Keypoints allocation int camAllocateKeypoints(CamKeypoints *fpoints, int nbPoints); /// Keypoints reallocation int camReallocateKeypoints(CamKeypoints *fpoints, int nbPoints); /// Keypoints release int camFreeKeypoints(CamKeypoints *fpoints); /// Draw kepoints on screen int camDrawKeypoints(CamKeypoints *points, CamImage *dest, int color); /// Draw one keypoint on screen int camDrawKeypoint(CamKeypoint *point, CamImage *dest, int color); /// Harris corner detector. /** \param k Harris' corner detection parameter (default value is 41, matching k=0.04 in Harris' article) */ int camHarris(CamImage *source, CamKeypoints *points, int k); /// Local maxima finder (Circle7 neighborhood) int camFindLocalMaximaCircle7(CamImage *source, CamKeypoints *points, int threshold); /// Local maxima finder (Circle5 neighborhood) int camFindLocalMaximaCircle5(CamImage *source, CamKeypoints *points, int threshold); /// Local maxima finder (Square3 neighborhood) int camFindLocalMaximaCircle3(CamImage *source, CamKeypoints *points, int threshold); /// Integral image computation int camIntegralImage(CamImage *src, CamImage *dest); /// Fast Hessian Detection (for one scale only) int camFastHessianDetectorFixedScale(CamImage *integral, CamImage *dest, int scale); /// Fast Hessian Detection (for all scales) int camFastHessianDetector(CamImage *source, CamKeypoints *points, int threshold, int options); /// Find a keypoint in a set of keypoints CamKeypoint* camFindKeypoint(CamKeypoint *point, CamKeypoints *points, int *dist1, int *dist2); /// Allocate keypoints matches int camAllocateKeypointsMatches(CamKeypointsMatches *matches, int nbpairs); /// Free keypoints matches void camFreeKeypointsMatches(CamKeypointsMatches *matches); /// Find an object in a database (brute force matching) int camKeypointsMatching(CamKeypoints *target, CamKeypoints **models, int nbModels, CamKeypointsMatches *matches); int camKeypointsMatching2(CamKeypoints *points1, CamKeypoints *points2, CamKeypointsMatches *matches); /// Find the affine transform from one object to the next int camFindAffineTransform(CamKeypointsMatches *matches, CamAffineTransform *t, int *error); int camFindAffineTransform2(CamKeypointsMatches *matches, CamAffineTransform *t, int *error); /// Apply an affine transform on a point (xy) to find the target point (uv) void camApplyAffineTransform(CamPoint *xy, CamPoint *uv, CamAffineTransform *t); typedef struct _CamFPKdTreeNode { int i; int m; struct _CamFPKdTreeNode *right; } CamFPKdTreeNode; int camKeypointsMatchingKdTree(CamKeypoints *target, CamFPKdTreeNode *kdTreeRoot, CamKeypointsMatches *matches, int explore); CamFPKdTreeNode *camKeypointsCompileKdTree(CamKeypoints **models, int nbModels); CamKeypoint *camFindKeypointKdTree(CamKeypoint *point, CamFPKdTreeNode *kdTreeRoot, int explore, int *dist1, int *dist2); #endif // SWIG #ifdef __cplusplus /// The CamKeypointsKdTree class struct CamKeypointsKdTree { CamFPKdTreeNode *root; void compile(const CamKeypoints **models, int nbModels) {root = camKeypointsCompileKdTree((CamKeypoints**)models, nbModels);} CamKeypoint *find(const CamKeypoint *point, int explore = 100, int *dist1 = NULL, int *dist2 = NULL) const; // C++ Wrapper for camFindKeypointKdTree function CamKeypointsKdTree(const CamKeypoints **models = NULL, int nbModels = 0) { if (nbModels != 0) compile(models, nbModels); else root = NULL;}; ~CamKeypointsKdTree() {if (root) free(root);} ///< Default destructor }; #endif // __cplusplus //@} /** @name Utility functions */ //@{ /* Image allocation utility routines */ #ifndef SWIG /// Grey scale image allocation int camAllocateImage(CamImage *image, int width, int height, int depth); /// Any kind of image allocation int camAllocateImageEx(CamImage *image, int width, int height, int depth, int color_seq); /// Fill image header (no memory initialization) int camFillImageHeader(CamImage *image, int width, int height, int depth, int channelseq); /// YUV image allocation int camAllocateYUVImage(CamImage *image, int width, int height); /// HLS image allocation int camAllocateHLSImage(CamImage *image, int width, int height); /// RGB image allocation int camAllocateRGBImage(CamImage *image, int width, int height); /// RGB image allocation with alpha channel int camAllocateRGBAImage(CamImage *image, int width, int height); /// BGR image allocation int camAllocateBGRImage(CamImage *image, int width, int height); /// BGR image allocation with alpha channel int camAllocateBGRAImage(CamImage *image, int width, int height); /// Image memory release int camDeallocateImage(CamImage *image); /// Image memory release int camFreeImage(CamImage *image); /* Other useful functions */ /// Set the ROI utility function int camSetROI(CamROI *roi, int coi, int xOffset, int yOffset, int width, int height); /// Set the ROI to the maximum size of the image int camSetMaxROI(CamROI *roi, CamImage *image); /// Reduce the roi by a given number of pixels on each side int camReduceROI(CamROI *roi, int pixels); /// Enlarge the roi by a given number of pixels on each side int camEnlargeROI(CamROI *roi, int pixels); /// Simple 2x Zoom functin (by pixels replication) int camZoom2x(CamImage *src, CamImage *dst); /// Simple nearest-neighbour decimation int camDecimateNN(CamImage *src, CamImage *dest, int factor); /// Set the image mask (Run-Length encoded mask) int camSetRLEMask(CamImage *image, CamRLEImage *mask); /// Set the image mask (::CamImage mask) int camSetMask(CamImage *image, CamImage *mask); #define camDownScaling2x2 camDownscaling2x2 /// 2x2 linear interpolation downscaling int camDownScaling2x2(CamImage *src, CamImage *dest); /// Copy function, without any color space conversion, but able to deal with planar/pixel oriented conversion, ROIs and even masking /** Supports grey scale to color conversion, as well as RGB to RGBA, and RGBA to RGB copying (adding and removing alpha channel) * * \return 0 (false) if an error occurs */ int camCopy(CamImage *source, CamImage *dest); /// Simple cloning function /** This function allocates the memory for the dest image. dest actual content is not considered by this function. * Beware not to have allocated an image in dest before, otherwise this will result in a memory leak. */ int camClone(CamImage *source, CamImage *dest); /// Reference copy /** This function doesn't copy the pixels, only the structure. Destination image will reference the same pixels as the source image. * The image will be freed when source will be deallocated through camDeallocateImage() function. */ int camRefCopy(CamImage *source, CamImage *dest); /// Set all the pixel values to fillValue int camSet(CamImage *image, int fillValue); /// Alpha channel compositing /** \param source1 must be a RGB image * \param source2 must be a RGBA image (with an alpha channel) * \param dest destination image */ int camAlphaComposite(CamImage *source1, CamImage *source2, CamImage *dest); /// Set the border value of an image int camSetBorder(CamImage *image, int borderValue); /// Clip the roi of an image int camClipROI(CamImage *image); /// Clip a ROI with respect to an image int camClip(CamROI *roi, CamImage *image); /// Compute intersection between ROIs int camROIIntersect(CamROI *roi1, CamROI *roi2, CamROI *dest); #endif //SWIG int camSetImageViewer(char *s); #ifndef SWIG /// View an image int camView(CamImage *image); /// Returns the version of the library const char *camVersion(); /* Drawing functions */ /// Draw a line int camDrawLine(CamImage *image, int x1, int y1, int x2, int y2, int color); /// Accumulate a line in a frame (very useful for Hough transforms) int camAccumulateLine(CamImage *image, int x1, int y1, int x2, int y2, int acc); /// Draw a rectangle int camDrawRectangle(CamImage *image, int x1, int y1, int x2, int y2, int color); /// Draw some text using 16 segments font (looks like an alarm clock...) int camDrawText16s(CamImage *image, char *text, int x, int y, int cwidth, int cheight, int orientation, int color); /// Draw a circle int camDrawCircle(CamImage *image, int x, int y, int r, int color); /// Draw an ellipse int camDrawEllipse(CamImage *image, int x, int y, int rx, int ry, int color); /// Plot /** Plots a point (\ref CAM_POINT), a cross (\ref CAM_CROSS), a circle (\ref CAM_CIRCLE) or a combination of them (CAM_CROSS|CAM_CIRCLE for instance) */ int camPlot(CamImage *image, int x, int y, int color, int kind); /// Fill a region with a color /** Try to fill the image with pixels as much possible pixels with the same color as the original pixel color in (x,y) * * \param x horizontal coordinate where to start the filling * \param y vertical coordinate where to start the filling * \param fillcolor filling color (use CAM_RGB or CAM_RGBA macros to set this color) * \param tolerance this sets where the filling should stop. The reference is the color of the original pixel color in (x,y), and all the pixels nearby that are within the * tolerance parameters get filled. If tolerance is set to -1, the filling stops with pixels having the same color as the filling color * (this mode is very useful for filling circles, rectangles, etc.) * * \return The number of colored pixels (at least 1 is function succeeds) */ int camFillColor(CamImage *image, int x, int y, int fillcolor, int tolerance); #endif // SWIG #ifdef __cplusplus /// The bitmap font structure struct CamBitmapFont { #else typedef struct { #endif int first_char; int nb_chars; int height; CamRLEImage *masks; CamImage *letters; #ifdef __cplusplus CamBitmapFont() {first_char=33; nb_chars=0; masks=NULL; letters=NULL;} CamBitmapFont(const char *filename); ~CamBitmapFont(); bool load(const char *filename); }; #else } CamBitmapFont; #endif #ifndef SWIG /// Load a bitmap font int camLoadBitmapFont(CamBitmapFont *font, char *filename); /// Deallocate a bitmap font int camFreeBitmapFont(CamBitmapFont *font); /// Draw some text using a bitmap font int camDrawTextBitmap(CamImage *image, char *text, int x, int y, CamBitmapFont *font); #endif // SWIG /// 24 bits integer color representation. Stricly equivalent to the Windows RGB macro. /** Please use this one in place of RGB for better portability of the code. */ int camRGB(int r, int g, int b); /// 32 bits integer color representation, including an alpha channel int camRGBA(int r, int g, int b, int a); #ifndef SWIG /* Load and save PGM images */ /// Load a PGM image int camLoadPGM(CamImage *image, char *fn); /// Save a PGM image int camSavePGM(CamImage *image, char *filename); /// Save a raw PGM image (8-bits only) int camSaveRawPGM(CamImage *image, char *filename); /* Load and save BMP images */ /// Load a BMP image int camLoadBMP(CamImage *image, char *fn); /// Save a BMP image int camSaveBMP(CamImage *image, char *filename); /* Load config files */ #define CAM_CONFIG_MAX_ENTRIES 256 typedef struct { int nbEntries; char parameter[CAM_CONFIG_MAX_ENTRIES][128]; char value[CAM_CONFIG_MAX_ENTRIES][128]; } CamConfig; int camLoadConfig(const char *filename, CamConfig *config); int camConfigInt(const CamConfig *config, const char *entry); float camConfigFloat(const CamConfig *config, const char *entry); const char *camConfigString(const CamConfig *config, const char *entry); /* Image capture functions */ void* camCaptureInit(int options); int camCapture(void *handle, CamImage *image); int camCaptureOver(void *handle); #endif #define CAM_CAPTURE_AUTO_SOURCE 1 #define CAM_CAPTURE_DISPLAY 2 #define CAM_CAPTURE_USE_READ 4 #ifdef __cplusplus class CamCapture { void *handle; public: bool capture(CamImage &capture); bool ready() {return (handle)?true:false;} CamCapture(int options=0); ~CamCapture(); }; #endif #ifndef SWIG /// Error management function void camError(char *module, char *error); typedef void (*camErrorFunct)(char *,char*); void camSetErrorFunct(camErrorFunct funct); //@} /** @name Color conversion functions */ //@{ int camYUV2RGB(CamImage* source, CamImage *dest); ///< Converts a YUV image to a RGB image int camRGB2YUV(CamImage* source, CamImage *dest); ///< Converts a RGB image to a YUV image int camRGB2Y(CamImage *source, CamImage *dest); ///< Converts a RGB image to a gray scale image int camRGB2HLS(CamImage* source, CamImage *dest); ///< Converts a RGB image to a HLS image //@} /** @name Motion estimation functions */ //@{ /* * Computes the Sum of Absolute Values between two 8x8 blocks * * This function takes into account the blocks lying partially outside the image. * MMX optimized if CAM_OPT_MMX compilation option is set (requires Intel C++ compiler). * * * \param image1 Current image * \param image2 Previous image * \param bleft The x coordinate of the current block * \param btop The y coordinate of the current block * \param dx The x offset to reach the candidate block * \param dy The y offset to reach the candidate block * * \return The SAD value between the given two blocks */ int camSAD8x8(CamImage *image1, CamImage *image2, int bleft, int btop, int dx, int dy); /* * Computes the Sum of Absolute Values between two 16x16 blocks * * This function takes into account the blocks lying partially outside the image. * MMX optimized if CAM_OPT_MMX compilation option is set (requires Intel C++ compiler). * * * \param image1 Current image * \param image2 Previous image * \param bleft The x coordinate of the current block * \param btop The y coordinate of the current block * \param dx The x offset to reach the candidate block * \param dy The y offset to reach the candidate block * * \return The SAD value between the given two blocks */ int camSAD16x16(CamImage *image1, CamImage *image2, int bleft, int btop, int dx, int dy); typedef struct { int niter; ///< Number of iterations (should be set to 0) int seed; ///< Seed for randomization int lsearch; ///< Number of pixels for searching around the blocks (small search) int rsearch; ///< Full random search parameter int blockSize; ///< Block size (8 or 16) int scans; ///< Number of scans int candidates; ///< Number of candidates (per scan) int test0; ///< Systematically test (0,0) motion vector } CamMotionEstimation3DRSParams; typedef struct { int vx[CAM_MAX_SCANLINE/8][CAM_MAX_FRAME_HEIGHT/8]; ///< Horizontal motion vectors int vy[CAM_MAX_SCANLINE/8][CAM_MAX_FRAME_HEIGHT/8]; ///< Vertical motion vectors int SAD[CAM_MAX_SCANLINE/8][CAM_MAX_FRAME_HEIGHT/8]; ///< SAD results } CamMotionEstimation3DRSResults; int camMotionEstimation3DRSInit(CamMotionEstimation3DRSParams *params, int seed, int lsearch, int rsearch, int bs, int scans, int candidates, int test0); int camMotionEstimation3DRS(CamImage *current, CamImage *previous, CamMotionEstimation3DRSParams *params, CamMotionEstimation3DRSResults *results); //@} /** @name 3D Projection/Retroprojection functions */ //@{ void camProject(const double extr[4][4], const double fc[2], const double cc[2], double x, double y, double z, int *xp, int *yp); void camBackproject(const double extr[4][4], const double fc[2], const double cc[2], int xp, int yp, double z, double *x, double *y); int camUndistort(CamImage *source, CamImage *dest, const float* intrinsic_matrix, const float* dist_coeffs); int camUndistortFixed(CamImage *source, CamImage *dest, const CAM_FIXED_POINT* intrinsic_matrix, const CAM_FIXED_POINT* dist_coeffs); int camUndistortBuildLUT(CamImage *source, const float* intrinsic_matrix, const float* dist_coeffs, CamImage *LUTX, CamImage *LUTY); int camUndistortLUT(CamImage *source, CamImage *dest, CamImage *LUTX, CamImage *LUTY); //@} #endif // SWIG #ifdef __cplusplus } #endif #endif