1 /*#******************************************************************************
2 ** IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 ** By downloading, copying, installing or using the software you agree to this license.
5 ** If you do not agree to this license, do not download, install,
6 ** copy or use the software.
9 ** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab.
10 ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping.
12 ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
14 ** Creation - enhancement process 2007-2011
15 ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
17 ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr).
18 ** Refer to the following research paper for more information:
19 ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011
20 ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book:
21 ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891.
23 ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
24 ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
25 ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
26 ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions.
27 ** ====> more informations in the above cited Jeanny Heraults's book.
30 ** For Open Source Computer Vision Library
32 ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
33 ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
35 ** For Human Visual System tools (hvstools)
36 ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
38 ** Third party copyrights are property of their respective owners.
40 ** Redistribution and use in source and binary forms, with or without modification,
41 ** are permitted provided that the following conditions are met:
43 ** * Redistributions of source code must retain the above copyright notice,
44 ** this list of conditions and the following disclaimer.
46 ** * Redistributions in binary form must reproduce the above copyright notice,
47 ** this list of conditions and the following disclaimer in the documentation
48 ** and/or other materials provided with the distribution.
50 ** * The name of the copyright holders may not be used to endorse or promote products
51 ** derived from this software without specific prior written permission.
53 ** This software is provided by the copyright holders and contributors "as is" and
54 ** any express or implied warranties, including, but not limited to, the implied
55 ** warranties of merchantability and fitness for a particular purpose are disclaimed.
56 ** In no event shall the Intel Corporation or contributors be liable for any direct,
57 ** indirect, incidental, special, exemplary, or consequential damages
58 ** (including, but not limited to, procurement of substitute goods or services;
59 ** loss of use, data, or profits; or business interruption) however caused
60 ** and on any theory of liability, whether in contract, strict liability,
61 ** or tort (including negligence or otherwise) arising in any way out of
62 ** the use of this software, even if advised of the possibility of such damage.
63 *******************************************************************************/
66 * @class RetinaColor a color multilexing/demultiplexing (demosaicing) based on a human vision inspiration. Different mosaicing strategies can be used, included random sampling !
67 * => please take a look at the nice and efficient demosaicing strategy introduced by B.Chaix de Lavarene, take a look at the cited paper for more mathematical details
68 * @brief Retina color sampling model which allows classical bayer sampling, random and potentially several other method ! Low color errors on corners !
69 * -> Based on the research of:
70 * .Brice Chaix Lavarene (chaix@lis.inpg.fr)
71 * .Jeanny Herault (herault@lis.inpg.fr)
72 * .David Alleyson (david.alleyson@upmf-grenoble.fr)
73 * .collaboration: alexandre benoit (benoit.alexandre.vision@gmail.com or benoit@lis.inpg.fr)
74 * Please cite: B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
75 * @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC / Gipsa-Lab, France: www.gipsa-lab.inpg.fr/
79 #ifndef RETINACOLOR_HPP_
80 #define RETINACOLOR_HPP_
82 #include "basicretinafilter.hpp"
84 //#define __RETINACOLORDEBUG //define RETINACOLORDEBUG in order to display debug data
89 class RetinaColor: public BasicRetinaFilter
93 * @typedef which allows to select the type of photoreceptors color sampling
97 * constructor of the retina color processing model
98 * @param NBrows: number of rows of the input image
99 * @param NBcolumns: number of columns of the input image
100 * @param samplingMethod: the chosen color sampling method
102 RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_DIAGONAL);
105 * standard destructor
107 virtual ~RetinaColor();
110 * function that clears all buffers of the object
112 void clearAllBuffers();
115 * resize retina color filter object (resize all allocated buffers)
116 * @param NBrows: the new height size
117 * @param NBcolumns: the new width size
119 void resize(const unsigned int NBrows, const unsigned int NBcolumns);
123 * color multiplexing function: a demultiplexed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue
124 * @param inputRGBFrame: the input RGB frame to be processed
125 * @return, nothing but the multiplexed frame is available by the use of the getMultiplexedFrame() function
127 inline void runColorMultiplexing(const std::valarray<float> &inputRGBFrame){runColorMultiplexing(inputRGBFrame, *_multiplexedFrame);};
130 * color multiplexing function: a demultipleed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue if using RGB images
131 * @param demultiplexedInputFrame: the demultiplexed input frame to be processed of size M*N*3
132 * @param multiplexedFrame: the resulting multiplexed frame
134 void runColorMultiplexing(const std::valarray<float> &demultiplexedInputFrame, std::valarray<float> &multiplexedFrame);
137 * color demultiplexing function: a multiplexed frame of size M*N*1 pixels is transformed into a RGB demultiplexed M*N*3 pixels frame
138 * @param multiplexedColorFrame: the input multiplexed frame to be processed
139 * @param adaptiveFiltering: specifies if an adaptive filtering has to be perform rather than standard filtering (adaptive filtering allows a better rendering)
140 * @param maxInputValue: the maximum input data value (should be 255 for 8 bits images but it can change in the case of High Dynamic Range Images (HDRI)
141 * @return, nothing but the output demultiplexed frame is available by the use of the getDemultiplexedColorFrame() function, also use getLuminance() and getChrominance() in order to retreive either luminance or chrominance
143 void runColorDemultiplexing(const std::valarray<float> &multiplexedColorFrame, const bool adaptiveFiltering=false, const float maxInputValue=255.0);
146 * activate color saturation as the final step of the color demultiplexing process
147 * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image.
148 * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
149 * @param colorSaturationValue: the saturation factor
151 void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue;};
154 * set parameters of the low pass spatio-temporal filter used to retreive the low chrominance
155 * @param beta: gain of the filter (generally set to zero)
156 * @param tau: time constant of the filter (unit is frame for video processing), typically 0 when considering static processing, 1 or more if a temporal smoothing effect is required
157 * @param k: spatial constant of the filter (unit is pixels), typical value is 2.5
159 void setChrominanceLPfilterParameters(const float beta, const float tau, const float k){setLPfilterParameters(beta, tau, k);};
162 * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space
163 * @param result: the input buffer to fill with the transformed colorspace retina output
164 * @return true if process ended successfully
166 bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray<float> &result);
169 * apply to the retina color output the CIE Lab color transformation
170 * @param result: the input buffer to fill with the transformed colorspace retina output
171 * @return true if process ended successfully
173 bool applyLMS2LabTransform(std::valarray<float> &result);
176 * @return the multiplexed frame result (use this after function runColorMultiplexing)
178 inline const std::valarray<float> &getMultiplexedFrame() const {return *_multiplexedFrame;};
181 * @return the demultiplexed frame result (use this after function runColorDemultiplexing)
183 inline const std::valarray<float> &getDemultiplexedColorFrame() const {return _demultiplexedColorFrame;};
186 * @return the luminance of the processed frame (use this after function runColorDemultiplexing)
188 inline const std::valarray<float> &getLuminance() const {return *_luminance;};
191 * @return the chrominance of the processed frame (use this after function runColorDemultiplexing)
193 inline const std::valarray<float> &getChrominance() const {return _chrominance;};
196 * standard 0 to 255 image clipping function appled to RGB images (of size M*N*3 pixels)
197 * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
198 * @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
200 void clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxOutputValue=255.0);
203 * standard 0 to 255 image normalization function appled to RGB images (of size M*N*3 pixels)
204 * @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped
206 void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue=255.0);
209 * return the color sampling map: a Nrows*Mcolumns image in which each pixel value is the ofsset adress which gives the adress of the sampled pixel on an Nrows*Mcolumns*3 color image ordered by layers: layer1, layer2, layer3
211 inline const std::valarray<unsigned int> &getSamplingMap() const {return _colorSampling;};
214 * function used (to bypass processing) to manually set the color output
215 * @param demultiplexedImage: the color image (luminance+chrominance) which has to be written in the object buffer
217 inline void setDemultiplexedColorFrame(const std::valarray<float> &demultiplexedImage){_demultiplexedColorFrame=demultiplexedImage;};
222 RETINA_COLORSAMPLINGMETHOD _samplingMethod;
223 bool _saturateColors;
224 float _colorSaturationValue;
225 // links to parent buffers (more convienient names
226 TemplateBuffer<float> *_luminance;
227 std::valarray<float> *_multiplexedFrame;
229 std::valarray<unsigned int> _colorSampling; // table (size (_nbRows*_nbColumns) which specifies the color of each pixel
230 std::valarray<float> _RGBmosaic;
231 std::valarray<float> _tempMultiplexedFrame;
232 std::valarray<float> _demultiplexedTempBuffer;
233 std::valarray<float> _demultiplexedColorFrame;
234 std::valarray<float> _chrominance;
235 std::valarray<float> _colorLocalDensity;// buffer which contains the local density of the R, G and B photoreceptors for a normalization use
236 std::valarray<float> _imageGradient;
239 float _pR, _pG, _pB; // probabilities of color R, G and B
242 // protected functions
243 void _initColorSampling();
244 void _interpolateImageDemultiplexedImage(float *inputOutputBuffer);
245 void _interpolateSingleChannelImage111(float *inputOutputBuffer);
246 void _interpolateBayerRGBchannels(float *inputOutputBuffer);
247 void _applyRIFfilter(const float *sourceBuffer, float *destinationBuffer);
248 void _getNormalizedContoursImage(const float *inputFrame, float *outputFrame);
249 // -> special adaptive filters dedicated to low pass filtering on the chrominance (skeeps filtering on the edges)
250 void _adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame);
251 void _adaptiveHorizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, const unsigned int IDrowStart, const unsigned int IDrowEnd); // TBB parallelized
252 void _adaptiveVerticalAnticausalFilter_multGain(float *outputFrame, const unsigned int IDcolumnStart, const unsigned int IDcolumnEnd);
253 void _computeGradient(const float *luminance);
254 void _normalizeOutputs_0_maxOutputValue(void);
256 // color space transform
257 void _applyImageColorSpaceConversion(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const float *transformTable);
260 /******************************************************
261 ** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors
262 ** ==> main idea parallelize main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelized methods as necessary
263 ** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelized
264 ** ==> functors constructors can differ from the parameters used with their related serial functions
268 class Parallel_ : public cv::ParallelLoopBody
276 virtual void operator()( const cv::Range& r ) const {
281 class Parallel_adaptiveHorizontalCausalFilter_addInput: public cv::ParallelLoopBody
285 const float *inputFrame, *imageGradient;
286 unsigned int nbColumns;
288 Parallel_adaptiveHorizontalCausalFilter_addInput(const float *inputImg, float *bufferToProcess, const float *imageGrad, const unsigned int nbCols)
289 :outputFrame(bufferToProcess), inputFrame(inputImg), imageGradient(imageGrad), nbColumns(nbCols) {};
291 virtual void operator()( const Range& r ) const {
292 register float* outputPTR=outputFrame+r.start*nbColumns;
293 register const float* inputPTR=inputFrame+r.start*nbColumns;
294 register const float *imageGradientPTR= imageGradient+r.start*nbColumns;
295 for (int IDrow=r.start; IDrow!=r.end; ++IDrow)
297 register float result=0;
298 for (unsigned int index=0; index<nbColumns; ++index)
300 result = *(inputPTR++) + (*imageGradientPTR++)* result;
301 *(outputPTR++) = result;
307 class Parallel_adaptiveVerticalAnticausalFilter_multGain: public cv::ParallelLoopBody
311 const float *imageGradient;
312 unsigned int nbRows, nbColumns;
313 float filterParam_gain;
315 Parallel_adaptiveVerticalAnticausalFilter_multGain(float *bufferToProcess, const float *imageGrad, const unsigned int nbRws, const unsigned int nbCols, const float gain)
316 :outputFrame(bufferToProcess), imageGradient(imageGrad), nbRows(nbRws), nbColumns(nbCols), filterParam_gain(gain){}
318 virtual void operator()( const Range& r ) const {
319 float* offset=outputFrame+nbColumns*nbRows-nbColumns;
320 const float* gradOffset= imageGradient+nbColumns*nbRows-nbColumns;
321 for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn)
323 register float result=0;
324 register float *outputPTR=offset+IDcolumn;
325 register const float *imageGradientPTR=gradOffset+IDcolumn;
326 for (unsigned int index=0; index<nbRows; ++index)
328 result = *(outputPTR) + *(imageGradientPTR) * result;
329 *(outputPTR) = filterParam_gain*result;
330 outputPTR-=nbColumns;
331 imageGradientPTR-=nbColumns;
340 #endif /*RETINACOLOR_HPP_*/