/** \file * \brief Image Processing * * See Copyright Notice in im_lib.h * $Id: Exp $ */ #ifndef __IM_PROCESS_H #define __IM_PROCESS_H #include "im_image.h" #if defined(__cplusplus) extern "C" { #endif /** \defgroup process Image Processing * \par * Several image processing functions based on the \ref imImage structure. * \par * You must link the application with "im_process.lib/.a/.so". \n * Some complex operations use the \ref Counter.\n * There is no check on the input/output image properties, * check each function documentation before using it. * \par * See \ref im_process.h */ /** \defgroup resize Image Resize * \par * Operations to change the image size. * \par * See \ref im_process.h * \ingroup process */ /** Only reduze the image size using the given decimation order. \n * Supported interpolation orders: * \li 0 - zero order (mean) * \li 1 - first order (bilinear decimation) * Images must be of the same type. \n * Returns zero if the counter aborted. * \ingroup resize */ int imProcessReduce(const imImage* src_image, imImage* dst_image, int order); /** Change the image size using the given interpolation order. \n * Supported interpolation orders: * \li 0 - zero order (near neighborhood) * \li 1 - first order (bilinear interpolation) * \li 3 - third order (bicubic interpolation) * Images must be of the same type. \n * Returns zero if the counter aborted. * \ingroup resize */ int imProcessResize(const imImage* src_image, imImage* dst_image, int order); /** Reduze the image area by 4 (w/2,h/2). \n * Images must be of the same type. Destiny image size must be source image width/2, height/2. * \ingroup resize */ void imProcessReduceBy4(const imImage* src_image, imImage* dst_image); /** Reduze the image size by removing pixels. \n * Images must be of the same type. Destiny image size must be smaller than source image width-xmin, height-ymin. * \ingroup resize */ void imProcessCrop(const imImage* src_image, imImage* dst_image, int xmin, int ymin); /** Increase the image size by adding pixels with zero value. \n * Images must be of the same type. Destiny image size must be greatter than source image width+xmin, height+ymin. * \ingroup resize */ void imProcessAddMargins(const imImage* src_image, imImage* dst_image, int xmin, int ymin); /** \defgroup arithm Arithmetic Operations * \par * Simple math operations for images. * \par * See \ref im_process.h * \ingroup process */ /** Unary Arithmetic Operations. * \ingroup arithm */ enum imUnaryOp { IM_UN_EQL, /**< equal = a */ IM_UN_ABS, /**< abssolute = |a| */ IM_UN_LESS, /**< less = -a */ IM_UN_INC, /**< increment += a */ IM_UN_INV, /**< invert = 1/a */ IM_UN_SQR, /**< square = a*a */ IM_UN_SQRT, /**< square root = a^(1/2) */ IM_UN_LOG, /**< natural logarithm = ln(a) */ IM_UN_EXP, /**< exponential = exp(a) */ IM_UN_SIN, /**< sine = sin(a) */ IM_UN_COS, /**< cosine = cos(a) */ IM_UN_CONJ, /**< complex conjugate = ar - ai*i */ IM_UN_CPXNORM /**< complex normalization by magnitude = a / cpxmag(a) */ }; /** Apply an arithmetic unary operation. \n * Can be done in place, images must match size, does not need to match type. * \ingroup arithm */ void imProcessUnArithmeticOp(const imImage* src_image, imImage* dst_image, int op); /** Binary Arithmetic Operations. * \ingroup arithm */ enum imBinaryOp { IM_BIN_ADD, /**< add = a+b */ IM_BIN_SUB, /**< subtract = a-b */ IM_BIN_MUL, /**< multiply = a*b */ IM_BIN_DIV, /**< divide = a/b */ IM_BIN_DIFF, /**< difference = |a-b| */ IM_BIN_POW, /**< power = a^b */ IM_BIN_MIN, /**< minimum = (a < b)? a: b */ IM_BIN_MAX /**< maximum = (a > b)? a: b */ }; /** Apply a binary arithmetic operation. \n * Can be done in place, images must match size. \n * Source images must match type, destiny image can be: \n * \li byte -> byte, ushort, int, float * \li ushort -> ushort, int, float * \li int -> int, float * \li float -> float * \li complex -> complex * One exception is that you can combine complex with float resulting complex. * \ingroup arithm */ void imProcessArithmeticOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); /** Apply a binary arithmetic operation with a constant value. \n * Can be done in place, images must match size. \n * Destiny image can be: \n * \li byte -> byte, ushort, int, float * \li ushort -> byte, ushort, int, float * \li int -> byte, ushort, int, float * \li float -> float * \li complex -> complex * The constant value is type casted to an apropriate type before the operation. * \ingroup arithm */ void imProcessArithmeticConstOp(const imImage* src_image, float src_const, imImage* dst_image, int op); /** Blend two images using an alpha value = [a * alpha + b * (1 - alpha)]. \n * Can be done in place, images must match size and type. * \ingroup arithm */ void imProcessBlend(const imImage* src_image1, imImage* src_image2, imImage* dst_image, float alpha); /** Split a complex image into two images with real and imaginary parts \n * or magnitude and phase parts (polar = 1). \n * Source image must be IM_COMPLEX, destiny images must be IM_FLOAT. * \ingroup arithm */ void imProcessSplitComplex(const imImage* src_image, imImage* dst_image1, imImage* dst_image2, int polar); /** Merges two images as the real and imaginary parts of a complex image, \n * or as magnitude and phase parts (polar = 1). \n * Source images must be IM_FLOAT, destiny image must be IM_COMPLEX. * \ingroup arithm */ void imProcessMergeComplex(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int polar); /** Calculates the mean of multiple images. \n * Images must match size and type. * \ingroup arithm */ void imProcessMultipleMean(const imImage** src_image_list, int src_image_count, imImage* dst_image); /** Calculates the standard deviation of multiple images. \n * Images must match size and type. * \ingroup arithm */ void imProcessMultipleStdDev(const imImage** src_image_list, int src_image_count, const imImage *mean_image, imImage* dst_image); /** Calculates the auto-covariance of an image with the mean of a set of images. \n * Images must match size and type. Returns zero if the counter aborted. * \ingroup arithm */ int imProcessAutoCovariance(const imImage* src_image, const imImage* mean_image, imImage* dst_image); /** Multiplies the conjugate of one complex image with another complex image. \n * Images must match size. Conj(img1) * img2 \n * Can be done in-place. * \ingroup arithm */ void imProcessMultiplyConj(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); /** \defgroup geom Geometric Operations * \par * Operations to change the shape of the image. * \par * See \ref im_process.h * \ingroup process */ /** Calculates the size of the new image after rotation. * \ingroup geom */ void imProcessCalcRotateSize(int width, int height, int *new_width, int *new_height, double cos0, double sin0); /** Rotates the image using the given interpolation order (see imProcessResize). \n * Images must be of the same type. The destiny size can be calculated using \ref imProcessCalcRotateSize. \n * Returns zero if the counter aborted. * \ingroup geom */ int imProcessRotate(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int order); /** Rotate the image in 90 degrees counterclockwise or clockwise. Swap columns by lines. \n * Images must be of the same type. Destiny width and height must be source height and width. * \ingroup geom */ void imProcessRotate90(const imImage* src_image, imImage* dst_image, int dir); /** Rotate the image in 180 degrees. Swap columns and swap lines. \n * Images must be of the same type and size. * \ingroup geom */ void imProcessRotate180(const imImage* src_image, imImage* dst_image); /** Mirrors the image in a horizontal flip. Swap columns. \n * Images must be of the same type and size. * \ingroup geom */ void imProcessMirror(const imImage* src_image, imImage* dst_image); /** Apply a vertical flip. Swap lines. \n * Images must be of the same type and size. * \ingroup geom */ void imProcessFlip(const imImage* src_image, imImage* dst_image); /** Apply a radial distortion using the given interpolation order (see imProcessResize). \n * Images must be of the same type and size. Returns zero if the counter aborted. * \ingroup geom */ int imProcessRadial(const imImage* src_image, imImage* dst_image, float k1, int order); /** \defgroup stats Image Statistics Calculations * \par * Operations to calculate some statistics over images. * \par * See \ref im_process.h * \ingroup process */ /** Calculates the RMS error between 2 images (Root Mean Square Error). * \ingroup stats */ float imCalcRMSError(const imImage* image1, const imImage* image2); /** Calculates the SNR of an image and its noise (Signal Noise Ratio). * \ingroup stats */ float imCalcSNR(const imImage* src_image, const imImage* noise_image); /** Count the number of different colors in an image. \n * Image must be IM_BYTE, but all color spaces except IM_CMYK. * \ingroup stats */ unsigned long imCalcCountColors(const imImage* src_image); /** Calculates the histogram of a IM_BYTE data. \n * Histogram is always 256 positions long. \n * When accum is different from zero it calculates the accumulated histogram. * \ingroup stats */ void imCalcHistogram(const unsigned char* data, int count, unsigned long* histo, int accum); /** Calculates the gray histogram of an image. \n * Image must be IM_BYTE/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). \n * If the image is IM_RGB then the histogram of the luma component is calculated. \n * Histogram is always 256 positions long. \n * When accum is different from zero it calculates the accumulated histogram. * \ingroup stats */ void imCalcGrayHistogram(const imImage* src_image, unsigned long* histo, int accum); /** Numerical Statistics Structure * \ingroup stats */ typedef struct _imStats { float max; /**< Maximum value */ float min; /**< Minimum value */ unsigned long positive; /**< Number of Positive Values */ unsigned long negative; /**< Number of Negative Values */ unsigned long zeros; /**< Number of Zeros */ float mean; /**< Mean */ float stddev; /**< Standard Deviation */ } imStats; /** Calculates the statistics about the image data. \n * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n * Supports all data types except IM_COMPLEX. \n * \ingroup stats */ void imCalcImageStatistics(const imImage* src_image, imStats* stats); /** Calculates the statistics about the image histogram data.\n * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n * Only IM_BYTE images are supported. * \ingroup stats */ void imCalcHistogramStatistics(const imImage* src_image, imStats* stats); /** Calculates some extra statistics about the image histogram data.\n * There is one stats for each depth plane. \n * Only IM_BYTE images are supported. \n * mode will be -1 if more than one max is found. * \ingroup stats */ void imCalcHistoImageStatistics(const imImage* src_image, int* median, int* mode); /** \defgroup quantize Additional Image Quantization Operations * \par * Additionally operations to the \ref imConvertColorSpace function. * \par * See \ref im_process.h * \ingroup process */ /** Converts a RGB image to a MAP image using uniform quantization * with an optional 8x8 ordered dither. The RGB image must have data type IM_BYTE. * \ingroup quantize */ void imProcessQuantizeRGBUniform(const imImage* src_image, imImage* dst_image, int dither); /** Quantizes a gray scale image in less that 256 grays using uniform quantization. \n * Both images must be IM_BYTE/IM_GRAY. Can be done in place. * \ingroup quantize */ void imProcessQuantizeGrayUniform(const imImage* src_image, imImage* dst_image, int grays); /** \defgroup histo Histogram Based Operations * \par * See \ref im_process.h * \ingroup process */ /** Performs an histogram expansion. \n * Percentage defines an amount of pixels to include at start and end. * If its is zero only empty counts of the histogram will be considered. \n * Images must be IM_BYTE/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). Can be done in place. * \ingroup histo */ void imProcessExpandHistogram(const imImage* src_image, imImage* dst_image, float percent); /** Performs an histogram equalization. \n * Images must be IM_BYTE/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). Can be done in place. * \ingroup histo */ void imProcessEqualizeHistogram(const imImage* src_image, imImage* dst_image); /** \defgroup transform Domain Transform Operations * \par * FFT, Wavelts, Hough. * \par * FFTW Copyright Matteo Frigo, Steven G. Johnson and the MIT. \n * http://www.fftw.org \n * See fftw.h or fftw3.h * \par * Must link with "im_fftw.lib" for FFTW version 2.1.5, and "im_fftw3.lib" for version 3.0.1. \n * Both libraries are available because version 3 was not that fast from version 2, * and its file size is 3x bigger than version 2. But version 3 was not compiled using hardware * otimizations. * \par * The FFTW lib has a GPL license. The license of the "im_fftw.lib" library is automatically the GPL. * So you cannot use it for commercial applications without contacting the authors. * \par * See \ref im_process.h * \ingroup process */ /** Forward FFT. \n * The result has its lowest frequency at the center of the image. \n * This is an unnormalized fft. \n * Images must be of the same size. Destiny image must be of type complex. * \ingroup transform */ void imProcessFFT(const imImage* src_image, imImage* dst_image); /** Inverse FFT. \n * The image has its lowest frequency restored to the origin before the transform. \n * The result is normalized by (width*height). \n * Images must be of the same size and both must be of type complex. * \ingroup transform */ void imProcessIFFT(const imImage* src_image, imImage* dst_image); /** Raw in-place FFT (forward or inverse). \n * The lowest frequency can be centered after forward, or * can be restored to the origin before inverse. \n * The result can be normalized after the transform by sqrt(w*h) [1] or by (w*h) [2], * or left unnormalized [0]. \n * Images must be of the same size and both must be of type complex. * \ingroup transform */ void imProcessFFTraw(imImage* src_image, int inverse, int center, int normalize); /** Auxiliary function for the raw FFT. \n * This is the function used internally to change the lowest frequency position in the image. \n * If the image size has even dimensions the flag "center2origin" is useless. But if it is odd, * you must specify if its from center to origin (usually used before inverse) or * from origin to center (usually used after forward). \n * Notice that this function is used for images in the the frequency domain. \n * Image type must be complex. * \ingroup transform */ void imProcessSwapQuadrants(imImage* src_image, int center2origin); /** Hough Lines Transform. \n * It will detect white lines in a black background. So the source image must be a IM_BINARY image * with the white lines of interest enhanced. The better the threshold with the white lines the better * the line detection. \n * The destiny image must have IM_GRAY, IM_INT, width=180, height=2*rmax+1, where rmax is the image diagonal/2. \n * Returns zero if the counter aborted. \n * Inspired from ideas in XITE, Copyright 1991, Blab, UiO \n * http://www.ifi.uio.no/~blab/Software/Xite/ * \ingroup transform */ int imProcessHoughLines(const imImage* src_image, imImage* dst_image); /** Draw detected hough lines. \n * The source image must be IM_GRAY and IM_BYTE. The destiny image can be a clone of the source image or * it can be the source image for in place processing. \n * The hough points image is a hough transform image that was thresholded to a IM_BINARY image, * usually using a Local Max threshold operation. Again the better the threshold the better the results. \n * The destiny image will be set to IM_MAP, and the detected lines will be drawn using a red color. \n * Returns the number of detected lines. * \ingroup transform */ int imProcessHoughLinesDraw(const imImage* src_image, const imImage* hough_points, imImage* dst_image); /** Calculates the Cross Correlation in the frequency domain. \n * CrossCorr(a,b) = IFFT(Conj(FFT(a))*FFT(b)) \n * Images must be of the same size and only destiny image must be of type complex. * \ingroup transform */ void imProcessCrossCorrelation(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); /** Calculates the Auto Correlation in the frequency domain. \n * Uses the cross correlation. * Images must be of the same size and only destiny image must be of type complex. * \ingroup transform */ void imProcessAutoCorrelation(const imImage* src_image, imImage* dst_image); /** \defgroup effects Special Effects * \par * Operations to change image appearance. * \par * See \ref im_process.h * \ingroup process */ /** Generates a zoom in effect averaging colors inside a square region. \n * Operates only on IM_BYTE images. * \ingroup effects */ void imProcessPixelate(const imImage* src_image, imImage* dst_image, int box_size); /** A simple Posterize effect. It reduces the number of color in the image eliminating * less significant bit planes. Can have 1 to 7 levels. See \ref imProcessBitMask. \n * Image data type must be integer. * \ingroup effects */ void imProcessPosterize(const imImage* src_image, imImage* dst_image, int level); /** A negative effect. Uses \ref imProcessToneGamut with IM_GAMUT_INVERT for non MAP images. \n * Supports all color spaces and all data types except IM_COMPLEX. * \ingroup effects */ void imProcessNegative(const imImage* src_image, imImage* dst_image); /** Replaces the source color by the destiny color. \n * The color will be type casted to the image data type. \n * The colors must have the same number of components of the images. \n * Supports all color spaces and all data types except IM_COMPLEX. * \ingroup effects */ void imProcessReplaceColor(const imImage* src_image, imImage* dst_image, float* src_color, float* dst_color); /** \defgroup colorproc Color Processing Operations * \par * Operations to change the color components configuration. * \par * See \ref im_process.h * \ingroup process */ /** Split a RGB image into luma and chroma. \n * Chroma is calculated as R-Y,G-Y,B-Y. Source image must be IM_RGB/IM_BYTE. \n * luma image is IM_GRAY/IM_BYTE and chroma is IM_RGB/IM_BYTE. \n * Source and destiny have the same size. * \ingroup colorproc */ void imProcessSplitYChroma(const imImage* src_image, imImage* y_image, imImage* chroma_image); /** Split a RGB image into HSI planes. \n * Source image must be IM_RGB/IM_BYTE. Destiny images are all IM_GRAY/IM_BYTE. \n * Source and destiny have the same size. See \ref hsi . * \ingroup colorproc */ void imProcessSplitHSI(const imImage* src_image, imImage* h_image, imImage* s_image, imImage* i_image); /** Merge HSI planes into a RGB image. \n * Source images must be IM_GRAY/IM_BYTE. Destiny image is all IM_RGB/IM_BYTE. \n * Source and destiny have the same size. See \ref hsi . * \ingroup colorproc */ void imProcessMergeHSI(const imImage* h_image, const imImage* s_image, const imImage* i_image3, imImage* dst_image); /** Split a multicomponent image into separate components.\n * Destiny images must be IM_GRAY. Size and data types must be all the same.\n * The number of destiny images must match the depth of the source image. * \ingroup colorproc */ void imProcessSplitComponents(const imImage* src_image, imImage** dst_image); /** Merges separate components into a multicomponent image.\n * Destiny images must be IM_GRAY. Size and data types must be all the same.\n * The number of source images must match the depth of the destiny image. * \ingroup colorproc */ void imProcessMergeComponents(const imImage** src_image_list, imImage* dst_image); /** \defgroup logic Logical Arithmetic Operations * \par * Logical binary math operations for images. * \par * See \ref im_process.h * \ingroup process */ /** Logical Operations. * \ingroup logic */ enum imLogicOp { IM_BIT_AND, /**< and = a & b */ IM_BIT_OR, /**< or = a | b */ IM_BIT_XOR, /**< xor = ~(a | b) */ IM_BIT_NOT /**< not = ~(a) */ }; /** Apply a logical operation.\n * For the IM_BIT_NOT operation the second image is ignored. \n * Images must have data type IM_BYTE, IM_USHORT or IM_INT. Can be done in place. * \ingroup logic */ void imProcessBitwiseOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); /** Apply a bit mask. \n * The same as imProcessBitwiseOp but the second image is replaced by a fixed mask. \n * Images must have data type IM_BYTE. It is valid only for AND, OR and XOR. Can be done in place. * \ingroup logic */ void imProcessBitMask(const imImage* src_image, imImage* dst_image, unsigned char mask, int op); /** Extract or Reset a bit plane. For ex: 000X0000 or XXX0XXXX (plane=3).\n * Images must have data type IM_BYTE. Can be done in place. * \ingroup logic */ void imProcessBitPlane(const imImage* src_image, imImage* dst_image, int plane, int reset); /** \defgroup render Synthetic Image Render * \par * Renders some 2D mathematical functions as images. All the functions operates in place * and supports all data types except IM_COMPLEX. * \par * See \ref im_process.h * \ingroup process */ /** Render Funtion. * \ingroup render */ typedef float (*imRenderFunc)(int x, int y, int d, float* param); /** Render Conditional Funtion. * \ingroup render */ typedef float (*imRenderCondFunc)(int x, int y, int d, int *cond, float* param); /** Render a synthetic image using a render function. \n * plus will make the render be added to the current image data, * or else all data will be replaced. All the render functions use this or the conditional function. \n * Returns zero if the counter aborted. * \ingroup render */ int imProcessRenderOp(imImage* image, imRenderFunc render_func, char* render_name, float* param, int plus); /** Render a sintetic image using a conditional render function. \n * Data will be rendered only if the condional param is true. \n * Returns zero if the counter aborted. * \ingroup render */ int imProcessRenderCondOp(imImage* image, imRenderCondFunc render_func, char* render_name, float* param); /** Render speckle noise on existing data. Can be done in place. * \ingroup render */ int imProcessRenderAddSpeckleNoise(const imImage* src_image, imImage* dst_image, float percent); /** Render gaussian noise on existing data. Can be done in place. * \ingroup render */ int imProcessRenderAddGaussianNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); /** Render uniform noise on existing data. Can be done in place. * \ingroup render */ int imProcessRenderAddUniformNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); /** Render random noise. * \ingroup render */ int imProcessRenderRandomNoise(imImage* image); /** Render a constant. The number of values must match the depth of the image. * \ingroup render */ int imProcessRenderConstant(imImage* image, float* value); /** Render a centered wheel. * \ingroup render */ int imProcessRenderWheel(imImage* image, int int_radius, int ext_radius); /** Render a centered cone. * \ingroup render */ int imProcessRenderCone(imImage* image, int radius); /** Render a centered tent. * \ingroup render */ int imProcessRenderTent(imImage* image, int width, int height); /** Render a ramp. Direction can be vertical (1) or horizontal (0). * \ingroup render */ int imProcessRenderRamp(imImage* image, int start, int end, int dir); /** Render a centered box. * \ingroup render */ int imProcessRenderBox(imImage* image, int width, int height); /** Render a centered sinc. * \ingroup render */ int imProcessRenderSinc(imImage* image, float xperiod, float yperiod); /** Render a centered gaussian. * \ingroup render */ int imProcessRenderGaussian(imImage* image, float stddev); /** Render the laplacian of a centered gaussian. * \ingroup render */ int imProcessRenderLapOfGaussian(imImage* image, float stddev); /** Render a centered cosine. * \ingroup render */ int imProcessRenderCosine(imImage* image, float xperiod, float yperiod); /** \defgroup tonegamut Tone Gamut Operations * \par * Operations that try to preserve the min-max interval in the output (the dynamic range). * \par * See \ref im_process.h * \ingroup process */ /** Tone Gamut Operations. * \ingroup render */ enum imToneGamut { IM_GAMUT_NORMALIZE, /**< normalize = (a-min) / (max-min) (destiny image must be IM_FLOAT) */ IM_GAMUT_POW, /**< pow = ((a-min) / (max-min))^gamma * (max-min) + min \n param[0]=gamma */ IM_GAMUT_LOG, /**< log = log(K * (a-min) / (max-min) + 1))*(max-min)/log(K+1) + min \n param[0]=K (K>0) */ IM_GAMUT_EXP, /**< exp = (exp(K * (a-min) / (max-min)) - 1))*(max-min)/(exp(K)-1) + min \n param[0]=K */ IM_GAMUT_INVERT, /**< invert = max - (a-min) */ IM_GAMUT_ZEROSTART, /**< zerostart = a - min */ IM_GAMUT_SOLARIZE, /**< solarize = a < level ? a: (level * (max-min) - a * (level-min)) / (max-level) \n param[0]=level percentage (0-100) relative to min-max \n photography solarization effect. */ IM_GAMUT_SLICE, /**< slice = start < a < end ? min: binarize? max: a \n param[0]=start, param[1]=end, param[2]=binarize */ IM_GAMUT_EXPAND, /**< expand = a < start ? start: a > end ? end : (a-start)*(max-min)/(end-start) + min \n param[0]=start, param[1]=end */ IM_GAMUT_CROP, /**< crop = a < start ? start: a > end ? end : a \n param[0]=start, param[1]=end */ IM_GAMUT_BRIGHTCONT /**< brightcont = a < min ? min: a > max ? max: a * tan(c_a) + b_s + (max-min)*(1 - tan(c_a))/2 \n param[0]=bright_shift, param[1]=contrast_angle (-90..+90) \n change brightness and contrast simultaneously. */ }; /** Apply a gamut operation with arguments. \n * Supports all data types except IM_COMPLEX. \n * The linear operation do a special convertion when min > 0 and max < 1, it forces min=0 and max=1. \n * IM_BYTE images have min=0 and max=255 always. \n * Can be done in place. When there is no extra params use NULL. * \ingroup tonegamut */ void imProcessToneGamut(const imImage* src_image, imImage* dst_image, int op, float* param); /** Converts from (0-1) to (0-255), crop out of bounds values. \n * Source image must be IM_FLOAT, and destiny image must be IM_BYTE. * \ingroup tonegamut */ void imProcessUnNormalize(const imImage* src_image, imImage* dst_image); /** Directly converts IM_USHORT, IM_INT and IM_FLOAT into IM_BYTE images. \n * This can also be done using \ref imConvertDataType with IM_CAST_DIRECT. * \ingroup tonegamut */ void imProcessDirectConv(const imImage* src_image, imImage* dst_image); /** \defgroup threshold Threshold Operations * \par * Operations that converts a IM_GRAY/IM_BYTE image into a IM_BINARY image using several threshold techniques. * \par * See \ref im_process.h * \ingroup process */ /** Apply a manual threshold. \n * threshold = a <= level ? 0: value \n * Usually value is 1 but another common value is 255. Can be done in place. * \ingroup threshold */ void imProcessThreshold(const imImage* src_image, imImage* dst_image, int level, unsigned char value); /** Apply a threshold by the difference of two images. \n * threshold = a1 <= a2 ? 0: 1 \n * Can be done in place. * \ingroup threshold */ void imProcessThresholdByDiff(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); /** Apply a threshold by the Hysteresis method. \n * Hysteresis thersholding of edge pixels. Starting at pixels with a * value greater than the HIGH threshold, trace a connected sequence * of pixels that have a value greater than the LOW threhsold. \n * Note: could not find the original source code author name. * \ingroup threshold */ void imProcessHysteresisThreshold(const imImage* src_image, imImage* dst_image, int low_thres, int high_thres); /** Estimates hysteresis low and high threshold levels. * \ingroup threshold */ void imProcessHysteresisThresEstimate(const imImage* src_image, int *low_thres, int *high_thres); /** Calculates the threshold level for manual threshold using an uniform error approach. \n * Extracted from XITE, Copyright 1991, Blab, UiO \n * http://www.ifi.uio.no/~blab/Software/Xite/ \verbatim Reference: S. M. Dunn & D. Harwood & L. S. Davis: "Local Estimation of the Uniform Error Threshold" IEEE Trans. on PAMI, Vol PAMI-6, No 6, Nov 1984. Comments: It only works well on images whith large objects. Author: Olav Borgli, BLAB, ifi, UiO Image processing lab, Department of Informatics, University of Oslo \endverbatim * Returns the used level. * \ingroup threshold */ int imProcessUniformErrThreshold(const imImage* src_image, imImage* dst_image); /** Apply a threshold by using a difusion error method. \n * It can be applied on IM_RGB/IM_BYTE images. * \ingroup threshold */ void imProcessDifusionErrThreshold(const imImage* src_image, imImage* dst_image, int level); /** Calculates the threshold level for manual threshold using a percentage of pixels * that should stay bellow the threshold. \n * Returns the used level. * \ingroup threshold */ int imProcessPercentThreshold(const imImage* src_image, imImage* dst_image, float percent); /** Calculates the threshold level for manual threshold using the Otsu approach. \n * Returns the used level. \n * Original implementation by Flavio Szenberg. * \ingroup threshold */ int imProcessOtsuThreshold(const imImage* src_image, imImage* dst_image); /** Calculates the threshold level for manual threshold using (max-min)/2. \n * Returns the used level. * \ingroup threshold */ int imProcessMinMaxThreshold(const imImage* src_image, imImage* dst_image); /** Estimates Local Max threshold level. * \ingroup threshold */ void imProcessLocaMaxThresEstimate(const imImage* src_image, int *thres); /** \defgroup morphgray Morphology Operations for Gray Images * \par * See \ref im_process.h * \ingroup process */ /** Base gray morphology convolution. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. \n * Kernel is always IM_INT. Use kernel size odd for better results. \n * You can use the maximum value or else the minimum value. \n * The border is mirrored when the kernel reaches it. All the gray morphology operations use this function. \n * If the kernel image attribute "Description" exists it is used by the counter. * \ingroup morphgray */ int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int ismax); /** Gray morphology convolution with a kernel full of "0"s and use minimum value. * \ingroup morphgray */ int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size); /** Gray morphology convolution with a kernel full of "0"s and use maximum value. * \ingroup morphgray */ int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size); /** Erode+Dilate. * \ingroup morphgray */ int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size); /** Dilate+Erode. * \ingroup morphgray */ int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size); /** Open+Difference. * \ingroup morphgray */ int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size); /** Close+Difference. * \ingroup morphgray */ int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size); /** Difference(Erode, Dilate). * \ingroup morphgray */ int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size); /** \defgroup morphbin Morphology Operations for Binary Images * \par * See \ref im_process.h * \ingroup process */ /** Base binary morphology convolution. \n * Images are all IM_BINARY. Kernel is IM_INT. Use kernel size odd for better results. \n * Hit white means hit=1 and miss=0, or else hit=0 and miss=1. \n * Use -1 for don't care positions in kernel. \n * The operation can be repeated by a number of iterations. The border is mirrored when the kernel reaches it. \n * Almost all the binary morphology operations use this function.\n * If the kernel image attribute "Description" exists it is used by the counter. * \ingroup morphbin */ int imProcessBinMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int hit_white, int iter); /** Binary morphology convolution with a kernel full of "1"s and hit white. * \ingroup morphbin */ int imProcessBinMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); /** Binary morphology convolution with a kernel full of "0"s and hit black. * \ingroup morphbin */ int imProcessBinMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); /** Erode+Dilate. * When iteration is more than one it means Erode+Erode+Erode+...+Dilate+Dilate+Dilate+... * \ingroup morphbin */ int imProcessBinMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); /** Dilate+Erode. * \ingroup morphbin */ int imProcessBinMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); /** Erode+Difference. \n * The difference from the source image is applied only once. * \ingroup morphbin */ int imProcessBinMorphOutline(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); /** Thins the supplied binary image using Rosenfeld's parallel thinning algorithm. \n * Reference: \n * "Efficient Binary Image Thinning using Neighborhood Maps" \n * by Joseph M. Cychosz, 3ksnn64@ecn.purdue.edu \n * in "Graphics Gems IV", Academic Press, 1994 * \ingroup morphbin */ void imProcessBinMorphThin(const imImage* src_image, imImage* dst_image); /** \defgroup rank Rank Convolution Operations * \par * See \ref im_process.h * \ingroup process */ /** Rank convolution using the median value. \n * Returns zero if the counter aborted. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. * \ingroup rank */ int imProcessMedianConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Rank convolution using (maximum-minimum) value. \n * Returns zero if the counter aborted. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. * \ingroup rank */ int imProcessRangeConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Rank convolution using the closest maximum or minimum value. \n * Returns zero if the counter aborted. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. * \ingroup rank */ int imProcessRankClosestConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Rank convolution using the maximum value. \n * Returns zero if the counter aborted. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. * \ingroup rank */ int imProcessRankMaxConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Rank convolution using the minimum value. \n * Returns zero if the counter aborted. \n * Supports all data types except IM_COMPLEX. Can be applied on color images. * \ingroup rank */ int imProcessRankMinConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Threshold using a rank convolution with a range contrast function. \n * Supports only IM_BYTE/IM_GRAY to IM_BINARY. \n * Local variable threshold by the method of Bernsen. \n * Extracted from XITE, Copyright 1991, Blab, UiO \n * http://www.ifi.uio.no/~blab/Software/Xite/ \verbatim Reference: Bernsen, J: "Dynamic thresholding of grey-level images" Proc. of the 8th ICPR, Paris, Oct 1986, 1251-1255. Author: Oivind Due Trier \endverbatim * Returns zero if the counter aborted. * \ingroup threshold */ int imProcessRangeContrastThreshold(const imImage* src_image, imImage* dst_image, int ks, int min_range); /** Threshold using a rank convolution with a local max function. \n * Returns zero if the counter aborted. \n * Supports only IM_BYTE/IM_GRAY to IM_BINARY. * \ingroup threshold */ int imProcessLocalMaxThreshold(const imImage* src_image, imImage* dst_image, int ks, int min_thres); /** \defgroup convolve Convolution Operations * \par * See \ref im_process.h * \ingroup process */ /** Base Convolution with a kernel. \n * Kernel can be IM_INT or IM_FLOAT, but always IM_GRAY. Use kernel size odd for better results. \n * Supports all data types. The border is mirrored when the kernel reaches it. \n * Returns zero if the counter aborted. Most of the convolutions use this function.\n * If the kernel image attribute "Description" exists it is used by the counter. * \ingroup convolve */ int imProcessConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel); /** Repeats the convolution a number of times. \n * Returns zero if the counter aborted.\n * If the kernel image attribute "Description" exists it is used by the counter. * \ingroup convolve */ int imProcessConvolveRep(const imImage* src_image, imImage* dst_image, const imImage* kernel, int count); /** Convolve with a kernel rotating it 8 times and getting the maximum value. \n * Kernel must be square. \n * The rotation is implemented only for kernel sizes 3x3, 5x5 and 7x7. \n * Supports all data types except IM_COMPLEX. * Returns zero if the counter aborted.\n * If the kernel image attribute "Description" exists it is used by the counter. * \ingroup convolve */ int imProcessCompassConvolve(const imImage* src_image, imImage* dst_image, imImage* kernel); /** Utility function to rotate a kernel one time. * \ingroup convolve */ void imProcessRotateKernel(imImage* kernel); /** Difference(Gaussian1, Gaussian2). \n * Supports all data types, * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. * \ingroup convolve */ int imProcessDiffOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev1, float stddev2); /** Convolution with a laplacian of a gaussian kernel. \n * Supports all data types, * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. * \ingroup convolve */ int imProcessLapOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); /** Convolution with a kernel full of "1"s inside a circle. \n * Supports all data types. * \ingroup convolve */ int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int ks); /** Convolution with a gaussian kernel. The gaussian in obtained by repetition of a base 3x3 IM_INT kernel. \n * Supports all data types. * \ingroup convolve */ int imProcessGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); /** Magnitude of the sobel convolution. \n * Supports all data types except IM_COMPLEX. * \ingroup convolve */ int imProcessSobelConvolve(const imImage* src_image, imImage* dst_image); /** Finds the zero crossings of IM_INT and IM_FLOAT images. Crossings are marked with non zero values * indicating the intensity of the edge. It is usually used after a second derivative, laplace. \n * Extracted from XITE, Copyright 1991, Blab, UiO \n * http://www.ifi.uio.no/~blab/Software/Xite/ * \ingroup convolve */ void imProcessZeroCrossing(const imImage* src_image, imImage* dst_image); /** First part of the Canny edge detector. Includes the gaussian filtering and the nonmax suppression. \n * After using this you could apply a Hysteresis Threshold, see \ref imProcessHysteresisThreshold. \n * Image must be IM_BYTE/IM_GRAY. \n * Implementation from the book: \verbatim J. R. Parker "Algoritms for Image Processing and Computer Vision" WILEY \endverbatim * \ingroup convolve */ void imProcessCanny(const imImage* im, imImage* NewImage, float stddev); #if defined(__cplusplus) } #endif #endif