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 ** bioinspired : 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 (bioinspired)
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 #include "precomp.hpp"
66
67 #include <iostream>
68 #include <cstdlib>
69 #include "basicretinafilter.hpp"
70 #include <cmath>
71
72
73 namespace cv
74 {
75 namespace bioinspired
76 {
77 // @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr Gipsa-Lab, France: www.gipsa-lab.inpg.fr/
78
79 //////////////////////////////////////////////////////////
80 // BASIC RETINA FILTER
81 //////////////////////////////////////////////////////////
82
83 // Constructor and Desctructor of the basic retina filter
BasicRetinaFilter(const unsigned int NBrows,const unsigned int NBcolumns,const unsigned int parametersListSize,const bool useProgressiveFilter)84 BasicRetinaFilter::BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize, const bool useProgressiveFilter)
85 :_filterOutput(NBrows, NBcolumns),
86 _localBuffer(NBrows*NBcolumns),
87 _filteringCoeficientsTable(3*parametersListSize),
88 _progressiveSpatialConstant(0),// pointer to a local table containing local spatial constant (allocated with the object)
89 _progressiveGain(0)
90 {
91 #ifdef T_BASIC_RETINA_ELEMENT_DEBUG
92 std::cout<<"BasicRetinaFilter::BasicRetinaFilter: new filter, size="<<NBrows<<", "<<NBcolumns<<std::endl;
93 #endif
94 _halfNBrows=_filterOutput.getNBrows()/2;
95 _halfNBcolumns=_filterOutput.getNBcolumns()/2;
96
97 if (useProgressiveFilter)
98 {
99 #ifdef T_BASIC_RETINA_ELEMENT_DEBUG
100 std::cout<<"BasicRetinaFilter::BasicRetinaFilter: _progressiveSpatialConstant_Tbuffer"<<std::endl;
101 #endif
102 _progressiveSpatialConstant.resize(_filterOutput.size());
103 #ifdef T_BASIC_RETINA_ELEMENT_DEBUG
104 std::cout<<"BasicRetinaFilter::BasicRetinaFilter: new _progressiveGain_Tbuffer"<<NBrows<<", "<<NBcolumns<<std::endl;
105 #endif
106 _progressiveGain.resize(_filterOutput.size());
107 }
108 #ifdef T_BASIC_RETINA_ELEMENT_DEBUG
109 std::cout<<"BasicRetinaFilter::BasicRetinaFilter: new filter, size="<<NBrows<<", "<<NBcolumns<<std::endl;
110 #endif
111
112 // set default values
113 _maxInputValue=256.0;
114
115 // reset all buffers
116 clearAllBuffers();
117
118 #ifdef T_BASIC_RETINA_ELEMENT_DEBUG
119 std::cout<<"BasicRetinaFilter::Init BasicRetinaElement at specified frame size OK, size="<<this->size()<<std::endl;
120 #endif
121
122 }
123
~BasicRetinaFilter()124 BasicRetinaFilter::~BasicRetinaFilter()
125 {
126
127 #ifdef BASIC_RETINA_ELEMENT_DEBUG
128 std::cout<<"BasicRetinaFilter::BasicRetinaElement Deleted OK"<<std::endl;
129 #endif
130
131 }
132
133 ////////////////////////////////////
134 // functions of the basic filter
135 ////////////////////////////////////
136
137
138 // resize all allocated buffers
resize(const unsigned int NBrows,const unsigned int NBcolumns)139 void BasicRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns)
140 {
141
142 std::cout<<"BasicRetinaFilter::resize( "<<NBrows<<", "<<NBcolumns<<")"<<std::endl;
143
144 // resizing buffers
145 _filterOutput.resizeBuffer(NBrows, NBcolumns);
146
147 // updating variables
148 _halfNBrows=_filterOutput.getNBrows()/2;
149 _halfNBcolumns=_filterOutput.getNBcolumns()/2;
150
151 _localBuffer.resize(_filterOutput.size());
152 // in case of spatial adapted filter
153 if (_progressiveSpatialConstant.size()>0)
154 {
155 _progressiveSpatialConstant.resize(_filterOutput.size());
156 _progressiveGain.resize(_filterOutput.size());
157 }
158 // reset buffers
159 clearAllBuffers();
160 }
161
162 // Change coefficients table
setLPfilterParameters(const float beta,const float tau,const float desired_k,const unsigned int filterIndex)163 void BasicRetinaFilter::setLPfilterParameters(const float beta, const float tau, const float desired_k, const unsigned int filterIndex)
164 {
165 float _beta = beta+tau;
166 float k=desired_k;
167 // check if the spatial constant is correct (avoid 0 value to avoid division by 0)
168 if (desired_k<=0)
169 {
170 k=0.001f;
171 std::cerr<<"BasicRetinaFilter::spatial constant of the low pass filter must be superior to zero !!! correcting parameter setting to 0,001"<<std::endl;
172 }
173
174 float _alpha = k*k;
175 float _mu = 0.8f;
176 unsigned int tableOffset=filterIndex*3;
177 if (k<=0)
178 {
179 std::cerr<<"BasicRetinaFilter::spatial filtering coefficient must be superior to zero, correcting value to 0.01"<<std::endl;
180 _alpha=0.0001f;
181 }
182
183 float _temp = (1.0f+_beta)/(2.0f*_mu*_alpha);
184 float a = _filteringCoeficientsTable[tableOffset] = 1.0f + _temp - (float)std::sqrt( (1.0f+_temp)*(1.0f+_temp) - 1.0f);
185 _filteringCoeficientsTable[1+tableOffset]=(1.0f-a)*(1.0f-a)*(1.0f-a)*(1.0f-a)/(1.0f+_beta);
186 _filteringCoeficientsTable[2+tableOffset] =tau;
187
188 //std::cout<<"BasicRetinaFilter::normal:"<<(1.0-a)*(1.0-a)*(1.0-a)*(1.0-a)/(1.0+_beta)<<" -> old:"<<(1-a)*(1-a)*(1-a)*(1-a)/(1+_beta)<<std::endl;
189
190 //std::cout<<"BasicRetinaFilter::a="<<a<<", gain="<<_filteringCoeficientsTable[1+tableOffset]<<", tau="<<tau<<std::endl;
191 }
192
setProgressiveFilterConstants_CentredAccuracy(const float beta,const float tau,const float alpha0,const unsigned int filterIndex)193 void BasicRetinaFilter::setProgressiveFilterConstants_CentredAccuracy(const float beta, const float tau, const float alpha0, const unsigned int filterIndex)
194 {
195 // check if dedicated buffers are already allocated, if not create them
196 if (_progressiveSpatialConstant.size()!=_filterOutput.size())
197 {
198 _progressiveSpatialConstant.resize(_filterOutput.size());
199 _progressiveGain.resize(_filterOutput.size());
200 }
201
202 float _beta = beta+tau;
203 float _mu=0.8f;
204 if (alpha0<=0)
205 {
206 std::cerr<<"BasicRetinaFilter::spatial filtering coefficient must be superior to zero, correcting value to 0.01"<<std::endl;
207 //alpha0=0.0001;
208 }
209
210 unsigned int tableOffset=filterIndex*3;
211
212 float _alpha=0.8f;
213 float _temp = (1.0f+_beta)/(2.0f*_mu*_alpha);
214 float a=_filteringCoeficientsTable[tableOffset] = 1.0f + _temp - (float)std::sqrt( (1.0f+_temp)*(1.0f+_temp) - 1.0f);
215 _filteringCoeficientsTable[tableOffset+1]=(1.0f-a)*(1.0f-a)*(1.0f-a)*(1.0f-a)/(1.0f+_beta);
216 _filteringCoeficientsTable[tableOffset+2] =tau;
217
218 float commonFactor=alpha0/(float)std::sqrt(_halfNBcolumns*_halfNBcolumns+_halfNBrows*_halfNBrows+1.0f);
219 //memset(_progressiveSpatialConstant, 255, _filterOutput.getNBpixels());
220 for (unsigned int idColumn=0;idColumn<_halfNBcolumns; ++idColumn)
221 for (unsigned int idRow=0;idRow<_halfNBrows; ++idRow)
222 {
223 // computing local spatial constant
224 float localSpatialConstantValue=commonFactor*std::sqrt((float)(idColumn*idColumn)+(float)(idRow*idRow));
225 if (localSpatialConstantValue>1.0f)
226 localSpatialConstantValue=1.0f;
227
228 _progressiveSpatialConstant[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localSpatialConstantValue;
229 _progressiveSpatialConstant[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localSpatialConstantValue;
230 _progressiveSpatialConstant[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localSpatialConstantValue;
231 _progressiveSpatialConstant[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localSpatialConstantValue;
232
233 // computing local gain
234 float localGain=(1-localSpatialConstantValue)*(1-localSpatialConstantValue)*(1-localSpatialConstantValue)*(1-localSpatialConstantValue)/(1+_beta);
235 _progressiveGain[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localGain;
236 _progressiveGain[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localGain;
237 _progressiveGain[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localGain;
238 _progressiveGain[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localGain;
239
240 //std::cout<<commonFactor<<", "<<std::sqrt((_halfNBcolumns-1-idColumn)+(_halfNBrows-idRow-1))<<", "<<(_halfNBcolumns-1-idColumn)<<", "<<(_halfNBrows-idRow-1)<<", "<<localSpatialConstantValue<<std::endl;
241 }
242 }
243
setProgressiveFilterConstants_CustomAccuracy(const float beta,const float tau,const float k,const std::valarray<float> & accuracyMap,const unsigned int filterIndex)244 void BasicRetinaFilter::setProgressiveFilterConstants_CustomAccuracy(const float beta, const float tau, const float k, const std::valarray<float> &accuracyMap, const unsigned int filterIndex)
245 {
246
247 if (accuracyMap.size()!=_filterOutput.size())
248 {
249 std::cerr<<"BasicRetinaFilter::setProgressiveFilterConstants_CustomAccuracy: error: input accuracy map does not match filter size, init skept"<<std::endl;
250 return ;
251 }
252
253 // check if dedicated buffers are already allocated, if not create them
254 if (_progressiveSpatialConstant.size()!=_filterOutput.size())
255 {
256 _progressiveSpatialConstant.resize(accuracyMap.size());
257 _progressiveGain.resize(accuracyMap.size());
258 }
259
260 float _beta = beta+tau;
261 float _alpha=k*k;
262 float _mu=0.8f;
263 if (k<=0)
264 {
265 std::cerr<<"BasicRetinaFilter::spatial filtering coefficient must be superior to zero, correcting value to 0.01"<<std::endl;
266 //alpha0=0.0001;
267 }
268 unsigned int tableOffset=filterIndex*3;
269 float _temp = (1.0f+_beta)/(2.0f*_mu*_alpha);
270 float a=_filteringCoeficientsTable[tableOffset] = 1.0f + _temp - (float)std::sqrt( (1.0f+_temp)*(1.0f+_temp) - 1.0f);
271 _filteringCoeficientsTable[tableOffset+1]=(1.0f-a)*(1.0f-a)*(1.0f-a)*(1.0f-a)/(1.0f+_beta);
272 _filteringCoeficientsTable[tableOffset+2] =tau;
273
274 //memset(_progressiveSpatialConstant, 255, _filterOutput.getNBpixels());
275 for (unsigned int idColumn=0;idColumn<_filterOutput.getNBcolumns(); ++idColumn)
276 for (unsigned int idRow=0;idRow<_filterOutput.getNBrows(); ++idRow)
277 {
278 // computing local spatial constant
279 unsigned int index=idColumn+idRow*_filterOutput.getNBcolumns();
280 float localSpatialConstantValue=_a*accuracyMap[index];
281 if (localSpatialConstantValue>1)
282 localSpatialConstantValue=1;
283
284 _progressiveSpatialConstant[index]=localSpatialConstantValue;
285
286 // computing local gain
287 float localGain=(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)/(1.0f+_beta);
288 _progressiveGain[index]=localGain;
289
290 //std::cout<<commonFactor<<", "<<std::sqrt((_halfNBcolumns-1-idColumn)+(_halfNBrows-idRow-1))<<", "<<(_halfNBcolumns-1-idColumn)<<", "<<(_halfNBrows-idRow-1)<<", "<<localSpatialConstantValue<<std::endl;
291 }
292 }
293
294 ///////////////////////////////////////////////////////////////////////
295 /// Local luminance adaptation functions
296 // run local adaptation filter and save result in _filterOutput
runFilter_LocalAdapdation(const std::valarray<float> & inputFrame,const std::valarray<float> & localLuminance)297 const std::valarray<float> &BasicRetinaFilter::runFilter_LocalAdapdation(const std::valarray<float> &inputFrame, const std::valarray<float> &localLuminance)
298 {
299 _localLuminanceAdaptation(get_data(inputFrame), get_data(localLuminance), &_filterOutput[0]);
300 return _filterOutput;
301 }
302 // run local adaptation filter at a specific output adress
runFilter_LocalAdapdation(const std::valarray<float> & inputFrame,const std::valarray<float> & localLuminance,std::valarray<float> & outputFrame)303 void BasicRetinaFilter::runFilter_LocalAdapdation(const std::valarray<float> &inputFrame, const std::valarray<float> &localLuminance, std::valarray<float> &outputFrame)
304 {
305 _localLuminanceAdaptation(get_data(inputFrame), get_data(localLuminance), &outputFrame[0]);
306 }
307 // run local adaptation filter and save result in _filterOutput with autonomous low pass filtering before adaptation
runFilter_LocalAdapdation_autonomous(const std::valarray<float> & inputFrame)308 const std::valarray<float> &BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame)
309 {
310 _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0]);
311 _localLuminanceAdaptation(get_data(inputFrame), &_filterOutput[0], &_filterOutput[0]);
312 return _filterOutput;
313 }
314 // run local adaptation filter at a specific output adress with autonomous low pass filtering before adaptation
runFilter_LocalAdapdation_autonomous(const std::valarray<float> & inputFrame,std::valarray<float> & outputFrame)315 void BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame)
316 {
317 _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0]);
318 _localLuminanceAdaptation(get_data(inputFrame), &_filterOutput[0], &outputFrame[0]);
319 }
320
321 // local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output
_localLuminanceAdaptation(float * inputOutputFrame,const float * localLuminance)322 void BasicRetinaFilter::_localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance)
323 {
324 _localLuminanceAdaptation(inputOutputFrame, localLuminance, inputOutputFrame, false);
325
326 /* const float *localLuminancePTR=localLuminance;
327 float *inputOutputFramePTR=inputOutputFrame;
328
329 for (unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputOutputFramePTR)
330 {
331 float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
332 *(inputOutputFramePTR) = (_maxInputValue+X0)**inputOutputFramePTR/(*inputOutputFramePTR +X0+0.00000000001);
333 }
334 */
335 }
336
337 // local luminance adaptation of the input in regard of localLuminance buffer
_localLuminanceAdaptation(const float * inputFrame,const float * localLuminance,float * outputFrame,const bool updateLuminanceMean)338 void BasicRetinaFilter::_localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean)
339 {
340 if (updateLuminanceMean)
341 { float meanLuminance=0;
342 const float *luminancePTR=inputFrame;
343 for (unsigned int i=0;i<_filterOutput.getNBpixels();++i)
344 meanLuminance+=*(luminancePTR++);
345 meanLuminance/=_filterOutput.getNBpixels();
346 //float tempMeanValue=meanLuminance+_meanInputValue*_tau;
347 updateCompressionParameter(meanLuminance);
348 }
349 #ifdef MAKE_PARALLEL
350 cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_localAdaptation(localLuminance, inputFrame, outputFrame, _localLuminanceFactor, _localLuminanceAddon, _maxInputValue));
351 #else
352 //std::cout<<meanLuminance<<std::endl;
353 const float *localLuminancePTR=localLuminance;
354 const float *inputFramePTR=inputFrame;
355 float *outputFramePTR=outputFrame;
356 for (unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputFramePTR, ++outputFramePTR)
357 {
358 float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
359 // TODO : the following line can lead to a divide by zero ! A small offset is added, take care if the offset is too large in case of High Dynamic Range images which can use very small values...
360 *(outputFramePTR) = (_maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0+0.00000000001);
361 //std::cout<<"BasicRetinaFilter::inputFrame[IDpixel]=%f, X0=%f, outputFrame[IDpixel]=%f\n", inputFrame[IDpixel], X0, outputFrame[IDpixel]);
362 }
363 #endif
364 }
365
366 // local adaptation applied on a range of values which can be positive and negative
_localLuminanceAdaptationPosNegValues(const float * inputFrame,const float * localLuminance,float * outputFrame)367 void BasicRetinaFilter::_localLuminanceAdaptationPosNegValues(const float *inputFrame, const float *localLuminance, float *outputFrame)
368 {
369 const float *localLuminancePTR=localLuminance;
370 const float *inputFramePTR=inputFrame;
371 float *outputFramePTR=outputFrame;
372 float factor=_maxInputValue*2.0f/(float)CV_PI;
373 for (unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputFramePTR)
374 {
375 float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon;
376 *(outputFramePTR++) = factor*atan(*inputFramePTR/X0);//(_maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0);
377 //std::cout<<"BasicRetinaFilter::inputFrame[IDpixel]=%f, X0=%f, outputFrame[IDpixel]=%f\n", inputFrame[IDpixel], X0, outputFrame[IDpixel]);
378 }
379 }
380
381 ///////////////////////////////////////////////////////////////////////
382 /// Spatio temporal Low Pass filter functions
383 // run LP filter and save result in the basic retina element buffer
runFilter_LPfilter(const std::valarray<float> & inputFrame,const unsigned int filterIndex)384 const std::valarray<float> &BasicRetinaFilter::runFilter_LPfilter(const std::valarray<float> &inputFrame, const unsigned int filterIndex)
385 {
386 _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0], filterIndex);
387 return _filterOutput;
388 }
389
390 // run LP filter for a new frame input and save result at a specific output adress
runFilter_LPfilter(const std::valarray<float> & inputFrame,std::valarray<float> & outputFrame,const unsigned int filterIndex)391 void BasicRetinaFilter::runFilter_LPfilter(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const unsigned int filterIndex)
392 {
393 _spatiotemporalLPfilter(get_data(inputFrame), &outputFrame[0], filterIndex);
394 }
395
396 // run LP filter on the input data and rewrite it
runFilter_LPfilter_Autonomous(std::valarray<float> & inputOutputFrame,const unsigned int filterIndex)397 void BasicRetinaFilter::runFilter_LPfilter_Autonomous(std::valarray<float> &inputOutputFrame, const unsigned int filterIndex)
398 {
399 unsigned int coefTableOffset=filterIndex*3;
400
401 /**********/
402 _a=_filteringCoeficientsTable[coefTableOffset];
403 _gain=_filteringCoeficientsTable[1+coefTableOffset];
404 _tau=_filteringCoeficientsTable[2+coefTableOffset];
405
406 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
407 _horizontalCausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBrows());
408 _horizontalAnticausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBrows());
409 _verticalCausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBcolumns());
410 _verticalAnticausalFilter_multGain(&inputOutputFrame[0], 0, _filterOutput.getNBcolumns());
411
412 }
413 // run LP filter for a new frame input and save result at a specific output adress
_spatiotemporalLPfilter(const float * inputFrame,float * outputFrame,const unsigned int filterIndex)414 void BasicRetinaFilter::_spatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex)
415 {
416 unsigned int coefTableOffset=filterIndex*3;
417 /**********/
418 _a=_filteringCoeficientsTable[coefTableOffset];
419 _gain=_filteringCoeficientsTable[1+coefTableOffset];
420 _tau=_filteringCoeficientsTable[2+coefTableOffset];
421
422 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
423 _horizontalCausalFilter_addInput(inputFrame, outputFrame, 0,_filterOutput.getNBrows());
424 _horizontalAnticausalFilter(outputFrame, 0, _filterOutput.getNBrows());
425 _verticalCausalFilter(outputFrame, 0, _filterOutput.getNBcolumns());
426 _verticalAnticausalFilter_multGain(outputFrame, 0, _filterOutput.getNBcolumns());
427
428 }
429
430 // run SQUARING LP filter for a new frame input and save result at a specific output adress
_squaringSpatiotemporalLPfilter(const float * inputFrame,float * outputFrame,const unsigned int filterIndex)431 float BasicRetinaFilter::_squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex)
432 {
433 unsigned int coefTableOffset=filterIndex*3;
434 /**********/
435 _a=_filteringCoeficientsTable[coefTableOffset];
436 _gain=_filteringCoeficientsTable[1+coefTableOffset];
437 _tau=_filteringCoeficientsTable[2+coefTableOffset];
438
439 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
440
441 _squaringHorizontalCausalFilter(inputFrame, outputFrame, 0, _filterOutput.getNBrows());
442 _horizontalAnticausalFilter(outputFrame, 0, _filterOutput.getNBrows());
443 _verticalCausalFilter(outputFrame, 0, _filterOutput.getNBcolumns());
444 return _verticalAnticausalFilter_returnMeanValue(outputFrame, 0, _filterOutput.getNBcolumns());
445 }
446
447 /////////////////////////////////////////////////
448 // standard version of the 1D low pass filters
449
450 // horizontal causal filter which adds the input inside
_horizontalCausalFilter(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)451 void BasicRetinaFilter::_horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
452 {
453
454
455 //#pragma omp parallel for
456 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
457 {
458 float* outputPTR=outputFrame+(IDrowStart+IDrow)*_filterOutput.getNBcolumns();
459 float result=0;
460 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
461 {
462 result = *(outputPTR)+ _a* result;
463 *(outputPTR++) = result;
464 }
465 }
466 }
467 // horizontal causal filter which adds the input inside
_horizontalCausalFilter_addInput(const float * inputFrame,float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)468 void BasicRetinaFilter::_horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
469 {
470 #ifdef MAKE_PARALLEL
471 cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalCausalFilter_addInput(inputFrame, outputFrame, IDrowStart, _filterOutput.getNBcolumns(), _a, _tau));
472 #else
473 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
474 {
475 float* outputPTR=outputFrame+(IDrowStart+IDrow)*_filterOutput.getNBcolumns();
476 const float* inputPTR=inputFrame+(IDrowStart+IDrow)*_filterOutput.getNBcolumns();
477 float result=0;
478 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
479 {
480 result = *(inputPTR++) + _tau**(outputPTR)+ _a* result;
481 *(outputPTR++) = result;
482 }
483 }
484 #endif
485 }
486
487 // horizontal anticausal filter (basic way, no add on)
_horizontalAnticausalFilter(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)488 void BasicRetinaFilter::_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
489 {
490
491 #ifdef MAKE_PARALLEL
492 cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalAnticausalFilter(outputFrame, IDrowEnd, _filterOutput.getNBcolumns(), _a ));
493 #else
494 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
495 {
496 float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(_filterOutput.getNBcolumns())-1;
497 float result=0;
498 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
499 {
500 result = *(outputPTR)+ _a* result;
501 *(outputPTR--) = result;
502 }
503 }
504 #endif
505 }
506
507 // horizontal anticausal filter which multiplies the output by _gain
_horizontalAnticausalFilter_multGain(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)508 void BasicRetinaFilter::_horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
509 {
510
511 //#pragma omp parallel for
512 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
513 {
514 float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(_filterOutput.getNBcolumns())-1;
515 float result=0;
516 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
517 {
518 result = *(outputPTR)+ _a* result;
519 *(outputPTR--) = _gain*result;
520 }
521 }
522 }
523
524 // vertical anticausal filter
_verticalCausalFilter(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd)525 void BasicRetinaFilter::_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
526 {
527 #ifdef MAKE_PARALLEL
528 cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalCausalFilter(outputFrame, _filterOutput.getNBrows(), _filterOutput.getNBcolumns(), _a ));
529 #else
530 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
531 {
532 float result=0;
533 float *outputPTR=outputFrame+IDcolumn;
534
535 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
536 {
537 result = *(outputPTR) + _a * result;
538 *(outputPTR) = result;
539 outputPTR+=_filterOutput.getNBcolumns();
540
541 }
542 }
543 #endif
544 }
545
546
547 // vertical anticausal filter (basic way, no add on)
_verticalAnticausalFilter(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd)548 void BasicRetinaFilter::_verticalAnticausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
549 {
550 float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
551 //#pragma omp parallel for
552 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
553 {
554 float result=0;
555 float *outputPTR=offset+IDcolumn;
556
557 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
558 {
559 result = *(outputPTR) + _a * result;
560 *(outputPTR) = result;
561 outputPTR-=_filterOutput.getNBcolumns();
562
563 }
564 }
565 }
566
567 // vertical anticausal filter which multiplies the output by _gain
_verticalAnticausalFilter_multGain(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd)568 void BasicRetinaFilter::_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
569 {
570 #ifdef MAKE_PARALLEL
571 cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalAnticausalFilter_multGain(outputFrame, _filterOutput.getNBrows(), _filterOutput.getNBcolumns(), _a, _gain ));
572 #else
573 float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
574 //#pragma omp parallel for
575 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
576 {
577 float result=0;
578 float *outputPTR=offset+IDcolumn;
579
580 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
581 {
582 result = *(outputPTR) + _a * result;
583 *(outputPTR) = _gain*result;
584 outputPTR-=_filterOutput.getNBcolumns();
585
586 }
587 }
588 #endif
589 }
590
591 /////////////////////////////////////////
592 // specific modifications of 1D filters
593
594 // -> squaring horizontal causal filter
_squaringHorizontalCausalFilter(const float * inputFrame,float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)595 void BasicRetinaFilter::_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
596 {
597 float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns();
598 const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns();
599 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
600 {
601 float result=0;
602 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
603 {
604 result = *(inputPTR)**(inputPTR) + _tau**(outputPTR)+ _a* result;
605 *(outputPTR++) = result;
606 ++inputPTR;
607 }
608 }
609 }
610
611 // vertical anticausal filter that returns the mean value of its result
_verticalAnticausalFilter_returnMeanValue(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd)612 float BasicRetinaFilter::_verticalAnticausalFilter_returnMeanValue(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
613 {
614 float meanValue=0;
615 float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
616 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
617 {
618 float result=0;
619 float *outputPTR=offset+IDcolumn;
620
621 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
622 {
623 result = *(outputPTR) + _a * result;
624 *(outputPTR) = _gain*result;
625 meanValue+=*(outputPTR);
626 outputPTR-=_filterOutput.getNBcolumns();
627
628 }
629 }
630
631 return meanValue/(float)_filterOutput.getNBpixels();
632 }
633
634 // LP filter with integration in specific areas (regarding true values of a binary parameters image)
_localSquaringSpatioTemporalLPfilter(const float * inputFrame,float * LPfilterOutput,const unsigned int * integrationAreas,const unsigned int filterIndex)635 void BasicRetinaFilter::_localSquaringSpatioTemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex)
636 {
637 unsigned int coefTableOffset=filterIndex*3;
638 _a=_filteringCoeficientsTable[coefTableOffset+0];
639 _gain=_filteringCoeficientsTable[coefTableOffset+1];
640 _tau=_filteringCoeficientsTable[coefTableOffset+2];
641 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
642
643 _local_squaringHorizontalCausalFilter(inputFrame, LPfilterOutput, 0, _filterOutput.getNBrows(), integrationAreas);
644 _local_horizontalAnticausalFilter(LPfilterOutput, 0, _filterOutput.getNBrows(), integrationAreas);
645 _local_verticalCausalFilter(LPfilterOutput, 0, _filterOutput.getNBcolumns(), integrationAreas);
646 _local_verticalAnticausalFilter_multGain(LPfilterOutput, 0, _filterOutput.getNBcolumns(), integrationAreas);
647
648 }
649
650 // LP filter on specific parts of the picture instead of all the image
651 // same functions (some of them) but take a binary flag to allow integration, false flag means, no data change at the output...
652
653 // this function take an image in input and squares it befor computing
_local_squaringHorizontalCausalFilter(const float * inputFrame,float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd,const unsigned int * integrationAreas)654 void BasicRetinaFilter::_local_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas)
655 {
656 float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns();
657 const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns();
658 const unsigned int *integrationAreasPTR=integrationAreas;
659 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
660 {
661 float result=0;
662 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
663 {
664 if (*(integrationAreasPTR++))
665 result = *(inputPTR)**(inputPTR) + _tau**(outputPTR)+ _a* result;
666 else
667 result=0;
668 *(outputPTR++) = result;
669 ++inputPTR;
670
671 }
672 }
673 }
674
_local_horizontalAnticausalFilter(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd,const unsigned int * integrationAreas)675 void BasicRetinaFilter::_local_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas)
676 {
677
678 float* outputPTR=outputFrame+IDrowEnd*(_filterOutput.getNBcolumns())-1;
679 const unsigned int *integrationAreasPTR=integrationAreas;
680
681 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
682 {
683 float result=0;
684 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
685 {
686 if (*(integrationAreasPTR++))
687 result = *(outputPTR)+ _a* result;
688 else
689 result=0;
690 *(outputPTR--) = result;
691 }
692 }
693
694 }
695
_local_verticalCausalFilter(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd,const unsigned int * integrationAreas)696 void BasicRetinaFilter::_local_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas)
697 {
698 const unsigned int *integrationAreasPTR=integrationAreas;
699
700 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
701 {
702 float result=0;
703 float *outputPTR=outputFrame+IDcolumn;
704
705 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
706 {
707 if (*(integrationAreasPTR++))
708 result = *(outputPTR)+ _a* result;
709 else
710 result=0;
711 *(outputPTR) = result;
712 outputPTR+=_filterOutput.getNBcolumns();
713
714 }
715 }
716 }
717 // this functions affects _gain at the output
_local_verticalAnticausalFilter_multGain(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd,const unsigned int * integrationAreas)718 void BasicRetinaFilter::_local_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas)
719 {
720 const unsigned int *integrationAreasPTR=integrationAreas;
721 float* offset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
722
723 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
724 {
725 float result=0;
726 float *outputPTR=offset+IDcolumn;
727
728 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
729 {
730 if (*(integrationAreasPTR++))
731 result = *(outputPTR)+ _a* result;
732 else
733 result=0;
734 *(outputPTR) = _gain*result;
735 outputPTR-=_filterOutput.getNBcolumns();
736
737 }
738 }
739 }
740
741 ////////////////////////////////////////////////////
742 // run LP filter for a new frame input and save result at a specific output adress
743 // -> USE IRREGULAR SPATIAL CONSTANT
744
745 // irregular filter computed from a buffer and rewrites it
_spatiotemporalLPfilter_Irregular(float * inputOutputFrame,const unsigned int filterIndex)746 void BasicRetinaFilter::_spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex)
747 {
748 if (_progressiveGain.size()==0)
749 {
750 std::cerr<<"BasicRetinaFilter::runProgressiveFilter: cannot perform filtering, no progressive filter settled up"<<std::endl;
751 return;
752 }
753 unsigned int coefTableOffset=filterIndex*3;
754 /**********/
755 //_a=_filteringCoeficientsTable[coefTableOffset];
756 _tau=_filteringCoeficientsTable[2+coefTableOffset];
757
758 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
759 _horizontalCausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBrows());
760 _horizontalAnticausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBrows(), &_progressiveSpatialConstant[0]);
761 _verticalCausalFilter_Irregular(inputOutputFrame, 0, (int)_filterOutput.getNBcolumns(), &_progressiveSpatialConstant[0]);
762 _verticalAnticausalFilter_Irregular_multGain(inputOutputFrame, 0, (int)_filterOutput.getNBcolumns());
763
764 }
765 // irregular filter computed from a buffer and puts result on another
_spatiotemporalLPfilter_Irregular(const float * inputFrame,float * outputFrame,const unsigned int filterIndex)766 void BasicRetinaFilter::_spatiotemporalLPfilter_Irregular(const float *inputFrame, float *outputFrame, const unsigned int filterIndex)
767 {
768 if (_progressiveGain.size()==0)
769 {
770 std::cerr<<"BasicRetinaFilter::runProgressiveFilter: cannot perform filtering, no progressive filter settled up"<<std::endl;
771 return;
772 }
773 unsigned int coefTableOffset=filterIndex*3;
774 /**********/
775 //_a=_filteringCoeficientsTable[coefTableOffset];
776 _tau=_filteringCoeficientsTable[2+coefTableOffset];
777
778 // launch the serie of 1D directional filters in order to compute the 2D low pass filter
779 _horizontalCausalFilter_Irregular_addInput(inputFrame, outputFrame, 0, (int)_filterOutput.getNBrows());
780 _horizontalAnticausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBrows(), &_progressiveSpatialConstant[0]);
781 _verticalCausalFilter_Irregular(outputFrame, 0, (int)_filterOutput.getNBcolumns(), &_progressiveSpatialConstant[0]);
782 _verticalAnticausalFilter_Irregular_multGain(outputFrame, 0, (int)_filterOutput.getNBcolumns());
783
784 }
785 // 1D filters with irregular spatial constant
786 // horizontal causal filter wich runs on its input buffer
_horizontalCausalFilter_Irregular(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)787 void BasicRetinaFilter::_horizontalCausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
788 {
789 float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns();
790 const float* spatialConstantPTR=&_progressiveSpatialConstant[0]+IDrowStart*_filterOutput.getNBcolumns();
791 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
792 {
793 float result=0;
794 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
795 {
796 result = *(outputPTR)+ *(spatialConstantPTR++)* result;
797 *(outputPTR++) = result;
798 }
799 }
800 }
801
802 // horizontal causal filter with add input
_horizontalCausalFilter_Irregular_addInput(const float * inputFrame,float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd)803 void BasicRetinaFilter::_horizontalCausalFilter_Irregular_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd)
804 {
805 float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns();
806 const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns();
807 const float* spatialConstantPTR=&_progressiveSpatialConstant[0]+IDrowStart*_filterOutput.getNBcolumns();
808 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
809 {
810 float result=0;
811 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
812 {
813 result = *(inputPTR++) + _tau**(outputPTR)+ *(spatialConstantPTR++)* result;
814 *(outputPTR++) = result;
815 }
816 }
817
818 }
819
820 // horizontal anticausal filter (basic way, no add on)
_horizontalAnticausalFilter_Irregular(float * outputFrame,unsigned int IDrowStart,unsigned int IDrowEnd,const float * spatialConstantBuffer)821 void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const float *spatialConstantBuffer)
822 {
823 #ifdef MAKE_PARALLEL
824 cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_horizontalAnticausalFilter_Irregular(outputFrame, spatialConstantBuffer, IDrowEnd, _filterOutput.getNBcolumns()));
825 #else
826 float* outputPTR=outputFrame+IDrowEnd*(_filterOutput.getNBcolumns())-1;
827 const float* spatialConstantPTR=spatialConstantBuffer+IDrowEnd*(_filterOutput.getNBcolumns())-1;
828
829 for (unsigned int IDrow=IDrowStart; IDrow<IDrowEnd; ++IDrow)
830 {
831 float result=0;
832 for (unsigned int index=0; index<_filterOutput.getNBcolumns(); ++index)
833 {
834 result = *(outputPTR)+ *(spatialConstantPTR--)* result;
835 *(outputPTR--) = result;
836 }
837 }
838 #endif
839
840 }
841
842 // vertical anticausal filter
_verticalCausalFilter_Irregular(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd,const float * spatialConstantBuffer)843 void BasicRetinaFilter::_verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const float *spatialConstantBuffer)
844 {
845 #ifdef MAKE_PARALLEL
846 cv::parallel_for_(cv::Range(IDcolumnStart,IDcolumnEnd), Parallel_verticalCausalFilter_Irregular(outputFrame, spatialConstantBuffer, _filterOutput.getNBrows(), _filterOutput.getNBcolumns()));
847 #else
848 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
849 {
850 float result=0;
851 float *outputPTR=outputFrame+IDcolumn;
852 const float *spatialConstantPTR=spatialConstantBuffer+IDcolumn;
853 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
854 {
855 result = *(outputPTR) + *(spatialConstantPTR) * result;
856 *(outputPTR) = result;
857 outputPTR+=_filterOutput.getNBcolumns();
858 spatialConstantPTR+=_filterOutput.getNBcolumns();
859 }
860 }
861 #endif
862 }
863
864 // vertical anticausal filter which multiplies the output by _gain
_verticalAnticausalFilter_Irregular_multGain(float * outputFrame,unsigned int IDcolumnStart,unsigned int IDcolumnEnd)865 void BasicRetinaFilter::_verticalAnticausalFilter_Irregular_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd)
866 {
867 float* outputOffset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
868 const float* constantOffset=&_progressiveSpatialConstant[0]+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
869 const float* gainOffset=&_progressiveGain[0]+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns();
870 for (unsigned int IDcolumn=IDcolumnStart; IDcolumn<IDcolumnEnd; ++IDcolumn)
871 {
872 float result=0;
873 float *outputPTR=outputOffset+IDcolumn;
874 const float *spatialConstantPTR=constantOffset+IDcolumn;
875 const float *progressiveGainPTR=gainOffset+IDcolumn;
876 for (unsigned int index=0; index<_filterOutput.getNBrows(); ++index)
877 {
878 result = *(outputPTR) + *(spatialConstantPTR) * result;
879 *(outputPTR) = *(progressiveGainPTR)*result;
880 outputPTR-=_filterOutput.getNBcolumns();
881 spatialConstantPTR-=_filterOutput.getNBcolumns();
882 progressiveGainPTR-=_filterOutput.getNBcolumns();
883 }
884 }
885
886 }
887 }// end of namespace bioinspired
888 }// end of namespace cv
889