Add OpenCV source code
[platform/upstream/opencv.git] / modules / contrib / src / retinacolor.hpp
1 /*#******************************************************************************
2 ** IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
3 **
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.
7 **
8 **
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.
11 **
12 ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
13 **
14 **  Creation - enhancement process 2007-2011
15 **      Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
16 **
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.
22 **
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.
28 **
29 **                          License Agreement
30 **               For Open Source Computer Vision Library
31 **
32 ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
33 ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
34 **
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.
37 **
38 ** Third party copyrights are property of their respective owners.
39 **
40 ** Redistribution and use in source and binary forms, with or without modification,
41 ** are permitted provided that the following conditions are met:
42 **
43 ** * Redistributions of source code must retain the above copyright notice,
44 **    this list of conditions and the following disclaimer.
45 **
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.
49 **
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.
52 **
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 *******************************************************************************/
64
65 /**
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/
76 * Creation date 2007
77 */
78
79 #ifndef RETINACOLOR_HPP_
80 #define RETINACOLOR_HPP_
81
82 #include "basicretinafilter.hpp"
83
84 //#define __RETINACOLORDEBUG //define RETINACOLORDEBUG in order to display debug data
85
86 namespace cv
87 {
88
89     class RetinaColor: public BasicRetinaFilter
90     {
91     public:
92         /**
93         * @typedef which allows to select the type of photoreceptors color sampling
94         */
95
96         /**
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
101         */
102         RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const RETINA_COLORSAMPLINGMETHOD samplingMethod=RETINA_COLOR_DIAGONAL);
103
104         /**
105         * standard destructor
106         */
107         virtual ~RetinaColor();
108
109         /**
110         * function that clears all buffers of the object
111         */
112         void clearAllBuffers();
113
114         /**
115         * resize retina color filter object (resize all allocated buffers)
116         * @param NBrows: the new height size
117         * @param NBcolumns: the new width size
118         */
119         void resize(const unsigned int NBrows, const unsigned int NBcolumns);
120
121
122         /**
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
126         */
127         inline void runColorMultiplexing(const std::valarray<float> &inputRGBFrame){runColorMultiplexing(inputRGBFrame, *_multiplexedFrame);};
128
129         /**
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
133         */
134         void runColorMultiplexing(const std::valarray<float> &demultiplexedInputFrame, std::valarray<float> &multiplexedFrame);
135
136         /**
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
142         */
143         void runColorDemultiplexing(const std::valarray<float> &multiplexedColorFrame, const bool adaptiveFiltering=false, const float maxInputValue=255.0);
144
145         /**
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
150         * */
151         void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue;};
152
153         /**
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
158         */
159         void setChrominanceLPfilterParameters(const float beta, const float tau, const float k){setLPfilterParameters(beta, tau, k);};
160
161         /**
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
165         */
166         bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray<float> &result);
167
168         /**
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
172         */
173         bool applyLMS2LabTransform(std::valarray<float> &result);
174
175         /**
176         * @return the multiplexed frame result (use this after function runColorMultiplexing)
177         */
178         inline const std::valarray<float> &getMultiplexedFrame() const {return *_multiplexedFrame;};
179
180         /**
181         * @return the demultiplexed frame result (use this after function runColorDemultiplexing)
182         */
183         inline const std::valarray<float> &getDemultiplexedColorFrame() const {return _demultiplexedColorFrame;};
184
185         /**
186         * @return the luminance of the processed frame (use this after function runColorDemultiplexing)
187         */
188         inline const std::valarray<float> &getLuminance() const {return *_luminance;};
189
190         /**
191         * @return the chrominance of the processed frame (use this after function runColorDemultiplexing)
192         */
193         inline const std::valarray<float> &getChrominance() const {return _chrominance;};
194
195         /**
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
199         */
200         void clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxOutputValue=255.0);
201
202         /**
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
205         */
206         void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue=255.0);
207
208         /**
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
210         */
211         inline const std::valarray<unsigned int> &getSamplingMap() const {return _colorSampling;};
212
213         /**
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
216         */
217         inline void setDemultiplexedColorFrame(const std::valarray<float> &demultiplexedImage){_demultiplexedColorFrame=demultiplexedImage;};
218
219     protected:
220
221         // private functions
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;
228         // instance buffers
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;
237
238         // variables
239         float _pR, _pG, _pB; // probabilities of color R, G and B
240         bool _objectInit;
241
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);
255
256         // color space transform
257         void _applyImageColorSpaceConversion(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const float *transformTable);
258
259 #ifdef MAKE_PARALLEL
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
265         */
266
267         /* Template :
268         class Parallel_ : public cv::ParallelLoopBody
269         {
270         private:
271
272         public:
273         Parallel_()
274         : {}
275
276         virtual void operator()( const cv::Range& r ) const {
277
278         }
279         }:
280         */
281         class Parallel_adaptiveHorizontalCausalFilter_addInput: public cv::ParallelLoopBody
282         {
283         private:
284             float *outputFrame;
285             const float *inputFrame, *imageGradient;
286             unsigned int nbColumns;
287         public:
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) {};
290
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)
296                 {
297                     register float result=0;
298                     for (unsigned int index=0; index<nbColumns; ++index)
299                     {
300                         result = *(inputPTR++) + (*imageGradientPTR++)* result;
301                         *(outputPTR++) = result;
302                     }
303                 }
304             }
305         };
306
307         class Parallel_adaptiveVerticalAnticausalFilter_multGain: public cv::ParallelLoopBody
308         {
309         private:
310             float *outputFrame;
311             const float *imageGradient;
312             unsigned int nbRows, nbColumns;
313             float filterParam_gain;
314         public:
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){}
317
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)
322                 {
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)
327                     {
328                         result = *(outputPTR) + *(imageGradientPTR) * result;
329                         *(outputPTR) = filterParam_gain*result;
330                         outputPTR-=nbColumns;
331                         imageGradientPTR-=nbColumns;
332                     }
333                 }
334             }
335         };
336 #endif
337     };
338 }
339
340 #endif /*RETINACOLOR_HPP_*/