pull/265/head
Vitaliy Lyudvichenko 10 years ago
commit 24a9effd59
  1. 2
      modules/bioinspired/CMakeLists.txt
  2. 4
      modules/bioinspired/README.md
  3. 9
      modules/bioinspired/doc/bioinspired.bib
  4. BIN
      modules/bioinspired/doc/images/HDRtoneMapping_candleSample.jpg
  5. 120
      modules/bioinspired/doc/images/HDRtoneMapping_candleSample.svg
  6. BIN
      modules/bioinspired/doc/images/HDRtoneMapping_memorialSample.jpg
  7. 21675
      modules/bioinspired/doc/images/HDRtoneMapping_memorialSample.svg
  8. BIN
      modules/bioinspired/doc/images/VideoDemo_RGB_PETS2006.jpg
  9. 22615
      modules/bioinspired/doc/images/VideoDemo_RGB_PETS2006.svg
  10. BIN
      modules/bioinspired/doc/images/VideoDemo_thermal_park.jpg
  11. 5275
      modules/bioinspired/doc/images/VideoDemo_thermal_park.svg
  12. 445
      modules/bioinspired/doc/retina.markdown
  13. 119
      modules/bioinspired/include/opencv2/bioinspired/retina.hpp
  14. 67
      modules/bioinspired/include/opencv2/bioinspired/transientareassegmentationmodule.hpp
  15. 91
      modules/bioinspired/samples/basicRetina.cpp
  16. 30
      modules/bioinspired/src/retina.cpp
  17. 28
      modules/bioinspired/src/transientareassegmentationmodule.cpp
  18. 96
      modules/bioinspired/tutorials/retina_model.markdown
  19. 103
      modules/optflow/samples/motempl.cpp
  20. 46
      modules/text/README.md
  21. 4
      modules/text/src/erfilter.cpp
  22. 11
      modules/xfeatures2d/doc/xfeatures2d.bib
  23. 93
      modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
  24. 33
      modules/xfeatures2d/perf/perf_daisy.cpp
  25. 74
      modules/xfeatures2d/src/brief.cpp
  26. 1608
      modules/xfeatures2d/src/daisy.cpp
  27. 2
      modules/xfeatures2d/src/generated_16.i
  28. 2
      modules/xfeatures2d/src/generated_32.i
  29. 2
      modules/xfeatures2d/src/generated_64.i
  30. 7
      modules/xfeatures2d/test/test_features2d.cpp
  31. 44
      modules/xfeatures2d/test/test_rotation_and_scale_invariance.cpp
  32. 2
      modules/ximgproc/CMakeLists.txt
  33. 92
      modules/ximgproc/include/opencv2/ximgproc/disparity_filter.hpp
  34. 11
      modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp
  35. 258
      modules/ximgproc/samples/disparity_filtering.cpp
  36. 29
      modules/ximgproc/samples/findredlinedpolygonfromgooglemaps.py
  37. BIN
      modules/ximgproc/samples/polygonstanfordoutput.png
  38. BIN
      modules/ximgproc/samples/stanford.png
  39. 185
      modules/ximgproc/src/disparity_filters.cpp
  40. 284
      modules/ximgproc/src/wls_filter.cpp
  41. 2
      modules/xobjdetect/src/acffeature.cpp

@ -1,3 +1,3 @@
set(the_description "Biologically inspired algorithms")
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef)
ocv_define_module(bioinspired opencv_core OPTIONAL opencv_highgui opencv_ocl WRAP java)
ocv_define_module(bioinspired opencv_core OPTIONAL opencv_highgui opencv_ocl WRAP java python)

@ -1,2 +1,6 @@
Biologically inspired vision models and derivated tools
=======================================================
1. A biological retina model for image spatio-temporal noise and luminance changes enhancement
2. A transient areas (spatio-temporal events) segmentation tool to use at the output of the Retina
3. High Dynamic Range (HDR >8bit images) tone mapping to (conversion to 8bit) use cas of the retina

@ -9,6 +9,15 @@
publisher={Elsevier}
}
@INPROCEEDINGS{Benoit2014,
author={Strat, S.T. and Benoit, A. and Lambert, P.},
booktitle={Signal Processing Conference (EUSIPCO), 2014 Proceedings of the 22nd European},
title={Retina enhanced bag of words descriptors for video classification},
year={2014},
month={Sept},
pages={1307-1311}
}
@inproceedings{Strat2013,
title={Retina enhanced SIFT descriptors for video indexing},
author={Strat, Sabin Tiberius and Benoit, Alexandre and Lambert, Patrick},

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 894 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 390 KiB

@ -1,45 +1,65 @@
Bioinspired Module Retina Introduction {#bioinspired_retina}
======================================
Retina
------
Retina class overview
---------------------
@note do not forget that the retina model is included in the following namespace : cv::bioinspired
@note do not forget that the retina model is included in the following namespace : cv::bioinspired with C++ and in cv2.bioinspired with Python
### Introduction
Class which provides the main controls to the Gipsa/Listic labs human retina model. This is a non
This class provides the main controls of the Gipsa/Listic labs human retina model. This is a non
separable spatio-temporal filter modelling the two main retina information channels :
- foveal vision for detailled color vision : the parvocellular pathway.
- peripheral vision for sensitive transient signals detection (motion and events) : the
magnocellular pathway.
- foveal vision for detailed color vision : the parvocellular pathway.
- peripheral vision for sensitive transient signals detection (motion and events) : the magnocellular pathway.
From a general point of view, this filter whitens the image spectrum and corrects luminance thanks
to local adaptation. An other important property is its hability to filter out spatio-temporal noise
while enhancing details. This model originates from Jeanny Herault work @cite Herault2010 . It has been
involved in Alexandre Benoit phd and his current research @cite Benoit2010, @cite Strat2013 (he
currently maintains this module within OpenCV). It includes the work of other Jeanny's phd student
This model originates from Jeanny Herault work @cite Herault2010 . It has been
involved in Alexandre Benoit phd and his current research @cite Benoit2010, @cite Benoit2014 . He
currently maintains this module within OpenCV. It includes the work of other Jeanny's phd student
such as @cite Chaix2007 and the log polar transformations of Barthelemy Durette described in Jeanny's
book.
More into details here is an overview of the retina properties that are implemented here :
- regarding luminance and details enhancement :
- local logarithmic luminance compression (at the entry point by photoreceptors and at the output by ganglion cells).
- spectral whitening at the Outer Plexiform Layer level (photoreceptors and horizontal cells spatio-temporal filtering).
The former behavior compresses luminance range and allows very bright areas and very dark ones to be visible on the same picture with lots of details. The latter reduces low frequency luminance energy (mean luminance) and enhances mid-frequencies (details). Applied all together, retina well prepares visual signals prior high level analysis. Those properties are really interesting with videos where light changes are dramatically reduced with an interesting temporal consistency.
- regarding noise filtering :
- high frequency spatial and temporal noise is filtered out. Both outputs Parvo and Magno pathways benefit from this. Noise reduction benefits from the non separable spatio-temporal filtering.
- at the Parvo output, static textures are enhanced and noise is filtered (on videos, temporal noise is nicely removed). However, as human behaviors, moving textures are smoothed. Then, moving object details can be only enhanced if the retina tracks it and keeps it static from its point of view.
- at Magno output, it allows a cleaner detection of events (motion, changes) with reduced noise errors even in difficult lighting conditions. As a compromise, the Magno output is a low spatial frequency signal and allows events' blobs to be reliably extracted (check the TransientAreasSegmentationModule module for that).
### Use
This model can be used as a preprocessing stage in the aim of :
- performing texture analysis with enhanced signal to noise ratio and enhanced details which are robust
against input images luminance ranges (check out the parvocellular retina channel output, by
using the provided **getParvo** methods)
- performing motion analysis that is also taking advantage of the previously cited properties (check out the
magnocellular retina channel output, by using the provided **getMagno** methods)
- general image/video sequence description using either one or both channels. An example of the
use of Retina in a Bag of Words approach is given in @cite Benoit2014 .
@note
- For ease of use in computer vision applications, the two retina channels are applied
homogeneously on all the input images. This does not follow the real retina topology but this
can still be done using the log sampling capabilities proposed within the class.
- Extend the retina description and code use in the tutorial/contrib section for complementary
explanations.
on all the input images. This does not follow the real retina topology but it is practical from an image processing point of view. If retina mapping (foveal and parafoveal vision) is required, use the log sampling capabilities proposed within the class.
- Please do not hesitate to contribute by extending the retina description, code, use cases for complementary explanations and demonstrations.
### Preliminary illustration
### Use case illustrations
#### Image preprocessing using the Parvocellular pathway (parvo retina output)
As a preliminary presentation, let's start with a visual example. We propose to apply the filter on
a low quality color jpeg image with backlight problems. Here is the considered input... *"Well, my
eyes were able to see more that this strange black shadow..."*
a low quality color jpeg image with backlight problems. Here is the considered input... *"Well,i could see more with my eyes than what i captured with my camera..."*
![a low quality color jpeg image with backlight problems.](images/retinaInput.jpg)
Below, the retina foveal model applied on the entire image with default parameters. Here contours
are enforced, halo effects are voluntary visible with this configuration. See parameters discussion
Below, the retina foveal model applied on the entire image with default parameters. Details are enforced whatever the local luminance is. Here there contours
are strongly enforced but the noise level is kept low. Halo effects are voluntary visible with this configuration. See parameters discussion
below and increase horizontalCellsGain near 1 to remove them.
![the retina foveal model applied on the entire image with default parameters. Here contours are enforced, luminance is corrected and halo effects are voluntary visible with this configuration, increase horizontalCellsGain near 1 to remove them.](images/retinaOutput_default.jpg)
@ -48,27 +68,96 @@ Below, a second retina foveal model output applied on the entire image with a pa
focused on naturalness perception. *"Hey, i now recognize my cat, looking at the mountains at the
end of the day !"*. Here contours are enforced, luminance is corrected but halos are avoided with
this configuration. The backlight effect is corrected and highlight details are still preserved.
Then, even on a low quality jpeg image, if some luminance information remains, the retina is able to
reconstruct a proper visual signal. Such configuration is also usefull for High Dynamic Range
Then, even on a low quality jpeg image, if some luminance's information remains, the retina is able to
reconstruct a proper visual signal. Such configuration is also useful for High Dynamic Range
(*HDR*) images compression to 8bit images as discussed in @cite Benoit2010 and in the demonstration
codes discussed below. As shown at the end of the page, parameters change from defaults are :
codes discussed below. As shown at the end of the page, parameter changes from defaults are :
- horizontalCellsGain=0.3
- photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89.
![the retina foveal model applied on the entire image with 'naturalness' parameters. Here contours are enforced but are avoided with this configuration, horizontalCellsGain is 0.3 and photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89.](images/retinaOutput_realistic.jpg)
![the retina foveal model applied on the entire image with 'naturalness' parameters. Here contours are enforced but halo effects are avoided with this configuration, horizontalCellsGain is 0.3 and photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89.](images/retinaOutput_realistic.jpg)
As observed in this preliminary demo, the retina can be settled up with various parameters, by
default, as shown on the figure above, the retina strongly reduces mean luminance energy and
enforces all details of the visual scene. Luminance energy and halo effects can be modulated
(exagerated to cancelled as shown on the two examples). In order to use your own parameters, you can
(exaggerated to cancelled as shown on the two examples). In order to use your own parameters, you can
use at least one time the *write(String fs)* method which will write a proper XML file with all
default parameters. Then, tweak it on your own and reload them at any time using method
*setup(String fs)*. These methods update a *Retina::RetinaParameters* member structure that is
described hereafter. XML parameters file samples are shown at the end of the page.
Here is an overview of the abstract Retina interface, allocate one instance with the *createRetina*
functions.:
#### Tone mapping processing capability using the Parvocellular pathway (parvo retina output)
This retina model naturally handles luminance range compression. Local adaptation stages and spectral whitening contribute
to luminance range compression. In addition, high frequency noise that often corrupts tone mapped images is removed at early stages of the
process thus leading to natural perception and noise free tone mapping.
Compared to the demos shown above, setup differences are the following ones: (see bioinspired/samples/OpenEXRimages_HDR_Retina_toneMapping.cpp for more details)
* load HDR images (OpenEXR format is supported by OpenCV) and cut histogram borders at ~5% and 95% to eliminate salt&pepper like pixel's corruption.
* apply retina with default parameters along with the following changes (generic parameters used for the presented illustrations of the section) :
* retina Hcells gain =0.4 (the main change compared to the default configuration : it strongly reduces halo effects)
* localAdaptation_photoreceptors=0.99 (a little higher than default value to enforce local adaptation)
* localAdaptation_Gcells=0.95 (also slightly higher than default for local adaptation enforcement)
* get the parvo output using the *getParvo()* method.
Have a look at the end of this page to see how to specify these parameters in a configuration file.
The following two illustrations show the effect of such configuration on 2 image samples.
![HDR image tone mapping example with generic parameters. Original image comes from http://openexr.com/ samples (openexr-images-1.7.0/ScanLines/CandleGlass.exr)](images/HDRtoneMapping_candleSample.jpg)
![HDR image tone mapping example with the same generic parameters. Original image comes from http://www.pauldebevec.com/Research/HDR/memorial.exr)](images/HDRtoneMapping_memorialSample.jpg)
#### Motion and event detection using the Magnocellular pathway (magno retina output)
Spatio-temporal events can be easily detected using *magno* output of the retina (use the *getMagno()* method). Its energy linearly increases with motion speed.
An event blob detector is proposed with the TransientAreasSegmentationModule class also provided in the bioinspired module. The basic idea is to detect local energy drops with regard of the neighborhood and then to apply a threshold. Such process has been used in a bag of words description of videos on the TRECVid challenge @cite Benoit2014 and only allows video frames description on transient areas.
We present here some illustrations of the retina outputs on some examples taken from http://changedetection.net/ with RGB and thermal videos.
@note here, we use the default retina setup that generates halos around strong edges. Note that temporal constants allow a temporal effect to be visible on moting objects (useful for still image illustrations of a video). Halos can be removed by increasing retina Hcells gain while temporal effects can be reduced by decreasing temporal constant values.
Also take into account that the two retina outputs are rescaled in range [0:255] such that magno output can show a lot of "noise" when nothing moves while drawing it. However, its energy remains low if you retrieve it using *getMagnoRAW* getter instead.
![Retina processing on RGB image sequence : example from http://changedetection.net/ (baseline/PETS2006). Parvo enforces static signals but smooths moving persons since they do not remain static from its point of view. Magno channel highligths moving persons, observe the energy mapping on the one on top, partly behind a dark glass.](images/VideoDemo_RGB_PETS2006.jpg)
![Retina processing on gray levels image sequence : example from http://changedetection.net/ (thermal/park). On such grayscale images, parvo channel enforces contrasts while magno strongly reacts on moving pedestrians](images/VideoDemo_thermal_park.jpg)
### Literature
For more information, refer to the following papers :
- Model description : @cite Benoit2010
- Model use in a Bag of Words approach : @cite Benoit2014
- Please have a look at the reference work of Jeanny Herault that you can read in his book : @cite Herault2010
This retina filter code includes the research contributions of phd/research collegues from which
code has been redrawn by the author :
- take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color
mosaicing/demosaicing and his reference paper: @cite Chaix2007
- 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. More informations in the above cited
Jeanny Heraults's book.
- Meylan&al work on HDR tone mapping that is implemented as a specific method within the model : @cite Meylan2007
Retina programming interfaces
-----------------------------
The proposed class allows the [Gipsa](http://www.gipsa-lab.inpg.fr) (preliminary work) /
[Listic](http://www.listic.univ-savoie.fr) labs retina model to be used.
It can be applied on still images, images sequences and video sequences.
Here is an overview of the Retina interface, allocate one instance with the *createRetina*
functions (C++, Java, Python) :
@code{.cpp}
namespace cv{namespace bioinspired{
@ -76,7 +165,7 @@ functions.:
{
public:
// parameters setup instance
struct RetinaParameters; // this class is detailled later
struct RetinaParameters; // this class is detailed later
// main method for input frame processing (all use method, can also perform High Dynamic Range tone mapping)
void run (InputArray inputImage);
@ -84,20 +173,20 @@ functions.:
// specific method aiming at correcting luminance only (faster High Dynamic Range tone mapping)
void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage)
// output buffers retreival methods
// output buffers retrieval methods
// -> foveal color vision details channel with luminance and noise correction
void getParvo (OutputArray retinaOutput_parvo);
void getParvoRAW (OutputArray retinaOutput_parvo);// retreive original output buffers without any normalisation
const Mat getParvoRAW () const;// retreive original output buffers without any normalisation
void getParvoRAW (OutputArray retinaOutput_parvo);// retrieve original output buffers without any normalisation
const Mat getParvoRAW () const;// retrieve original output buffers without any normalisation
// -> peripheral monochrome motion and events (transient information) channel
void getMagno (OutputArray retinaOutput_magno);
void getMagnoRAW (OutputArray retinaOutput_magno); // retreive original output buffers without any normalisation
const Mat getMagnoRAW () const;// retreive original output buffers without any normalisation
void getMagnoRAW (OutputArray retinaOutput_magno); // retrieve original output buffers without any normalisation
const Mat getMagnoRAW () const;// retrieve original output buffers without any normalisation
// reset retina buffers... equivalent to closing your eyes for some seconds
void clearBuffers ();
// retreive input and output buffers sizes
// retrieve input and output buffers sizes
Size getInputSize ();
Size getOutputSize ();
@ -122,57 +211,261 @@ functions.:
}} // cv and bioinspired namespaces end
@endcode
### Description
### Setting up Retina
#### Managing the configuration file
When using the *Retina::write* and *Retina::load* methods, you create or load a XML file that stores Retina configuration.
The default configuration is presented below.
@code{.xml}
<?xml version="1.0"?>
<opencv_storage>
<OPLandIPLparvo>
<colorMode>1</colorMode>
<normaliseOutput>1</normaliseOutput>
<photoreceptorsLocalAdaptationSensitivity>7.5e-01</photoreceptorsLocalAdaptationSensitivity>
<photoreceptorsTemporalConstant>9.0e-01</photoreceptorsTemporalConstant>
<photoreceptorsSpatialConstant>5.7e-01</photoreceptorsSpatialConstant>
<horizontalCellsGain>0.01</horizontalCellsGain>
<hcellsTemporalConstant>0.5</hcellsTemporalConstant>
<hcellsSpatialConstant>7.</hcellsSpatialConstant>
<ganglionCellsSensitivity>7.5e-01</ganglionCellsSensitivity></OPLandIPLparvo>
<IPLmagno>
<normaliseOutput>1</normaliseOutput>
<parasolCells_beta>0.</parasolCells_beta>
<parasolCells_tau>0.</parasolCells_tau>
<parasolCells_k>7.</parasolCells_k>
<amacrinCellsTemporalCutFrequency>2.0e+00</amacrinCellsTemporalCutFrequency>
<V0CompressionParameter>9.5e-01</V0CompressionParameter>
<localAdaptintegration_tau>0.</localAdaptintegration_tau>
<localAdaptintegration_k>7.</localAdaptintegration_k></IPLmagno>
</opencv_storage>
@endcode
Class which allows the [Gipsa](http://www.gipsa-lab.inpg.fr) (preliminary work) /
[Listic](http://www.listic.univ-savoie.fr) (code maintainer and user) labs retina model to be used.
This class allows human retina spatio-temporal image processing to be applied on still images,
images sequences and video sequences. Briefly, here are the main human retina model properties:
Here are some words about all those parameters, tweak them as you wish to amplify or moderate retina effects (contours enforcement, halos effects, motion sensitivity, motion blurring, etc.)
#### Basic parameters
The simplest parameters are as follows :
- **colorMode** : let the retina process color information (if 1) or gray scale images (if 0). In
that last case, only the first channels of the input will be processed.
- **normaliseOutput** : each channel has such parameter: if the value is set to 1, then the considered
channel's output is rescaled between 0 and 255. Be aware at this case of the Magnocellular output
level (motion/transient channel detection). Residual noise will also be rescaled !
**Note :** using color requires color channels multiplexing/demultipexing which also demands more
processing. You can expect much faster processing using gray levels : it would require around 30
product per pixel for all of the retina processes and it has recently been parallelized for multicore
architectures.
#### Photo-receptors parameters
The following parameters act on the entry point of the retina - photo-receptors - and has impact on all
of the following processes. These sensors are low pass spatio-temporal filters that smooth temporal and
spatial data and also adjust their sensitivity to local luminance,thus, leads to improving details extraction
and high frequency noise canceling.
- **photoreceptorsLocalAdaptationSensitivity** between 0 and 1. Values close to 1 allow high
luminance log compression's effect at the photo-receptors level. Values closer to 0 provide a more
linear sensitivity. Increased alone, it can burn the *Parvo (details channel)* output image. If
adjusted in collaboration with **ganglionCellsSensitivity**,images can be very contrasted
whatever the local luminance there is... at the cost of a naturalness decrease.
- **photoreceptorsTemporalConstant** this setups the temporal constant of the low pass filter
effect at the entry of the retina. High value leads to strong temporal smoothing effect : moving
objects are blurred and can disappear while static object are favored. But when starting the
retina processing, stable state is reached later.
- **photoreceptorsSpatialConstant** specifies the spatial constant related to photo-receptors' low
pass filter's effect. Those parameters specify the minimum value of the spatial signal period allowed
in what follows. Typically, this filter should cut high frequency noise. On the other hand, a 0 value
cuts none of the noise while higher values start to cut high spatial frequencies, and progressively
lower frequencies... Be aware to not go to high levels if you want to see some details of the input images !
A good compromise for color images is a 0.53 value since such choice won't affect too much the color spectrum.
Higher values would lead to gray and blurred output images.
#### Horizontal cells parameters
This parameter set tunes the neural network connected to the photo-receptors, the horizontal cells.
It modulates photo-receptors sensitivity and completes the processing for final spectral whitening
(part of the spatial band pass effect thus favoring visual details enhancement).
- **horizontalCellsGain** here is a critical parameter ! If you are not interested with the mean
luminance and want just to focus on details enhancement, then, set this parameterto zero. However, if
you want to keep some environment luminance's data, let some low spatial frequencies pass into the system and set a
higher value (\<1).
- **hcellsTemporalConstant** similar to photo-receptors, this parameter acts on the temporal constant of a
low pass temporal filter that smoothes input data. Here, a high value generates a high retina
after effect while a lower value makes the retina more reactive. This value should be lower than
**photoreceptorsTemporalConstant** to limit strong retina after effects.
- **hcellsSpatialConstant** is the spatial constant of these cells filter's low pass one.
It specifies the lowest spatial frequency allowed in what follows. Visually, a high value leads
to very low spatial frequencies processing and leads to salient halo effects. Lower values
reduce this effect but has the limit of not go lower than the value of
**photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of
the retina.
**NOTE** Once the processing managed by the previous parameters is done, input data is cleaned from noise
and luminance is already partly enhanced. The following parameters act on the last processing stages
of the two outing retina signals.
#### Parvo (details channel) dedicated parameter
- **ganglionCellsSensitivity** specifies the strength of the final local adaptation occurring at
the output of this details' dedicated channel. Parameter values remain between 0 and 1. Low value
tend to give a linear response while higher values enforce the remaining low contrasted areas.
**Note :** this parameter can correct eventual burned images by favoring low energetic details of
the visual scene, even in bright areas.
#### IPL Magno (motion/transient channel) parameters
Once image's information are cleaned, this channel acts as a high pass temporal filter that
selects only the signals related to transient signals (events, motion, etc.). A low pass spatial filter
smoothes extracted transient data while a final logarithmic compression enhances low transient events
thus enhancing event sensitivity.
- **parasolCells_beta** generally set to zero, can be considered as an amplifier gain at the
entry point of this processing stage. Generally set to 0.
- **parasolCells_tau** the temporal smoothing effect that can be added
- **parasolCells_k** the spatial constant of the spatial filtering effect, set it at a high value
to favor low spatial frequency signals that are lower subject for residual noise.
- **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter.
High values let slow transient events to be selected.
- **V0CompressionParameter** specifies the strength of the log compression. Similar behaviors to
previous description but here enforces sensitivity of transient events.
- **localAdaptintegration_tau** generally set to 0, has no real use actually in here.
- **localAdaptintegration_k** specifies the size of the area on which local adaptation is
performed. Low values lead to short range local adaptation (higher sensitivity to noise), high
values secure log compression.
### Demos and experiments !
#### First time experiments
Here are some code snippets to shortly show how to use Retina with default parameters (with halo effects). Next section redirects to more complete demos provided with the main retina class.
Here is presented how to process a webcam stream with the following steps :
- load a frist input image to get its size
- allocate a retina instance with appropriate input size
- loop over grabbed frames :
- grab a new frame
- run on a frame
- call the two output getters
- display retina outputs
C++ version (see bioinspired/samples/basicRetina.cpp) :
- spectral whithening (mid-frequency details enhancement)
- high frequency spatio-temporal noise reduction (temporal noise and high frequency spatial noise
are minimized)
- low frequency luminance reduction (luminance range compression) : high luminance regions do not
hide details in darker regions anymore
- local logarithmic luminance compression allows details to be enhanced even in low light
conditions
@code{.cpp}
// include bioinspired module and OpenCV core utilities
#include "opencv2/bioinspired.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
// main function
int main(int argc, char* argv[]) {
// declare the retina input buffer.
cv::Mat inputFrame;
// setup webcam reader and grab a first frame to get its size
cv::VideoCapture videoCapture(0);
videoCapture>>inputFrame;
// allocate a retina instance with input size equal to the one of the loaded image
cv::Ptr<cv::bioinspired::Retina> myRetina = cv::bioinspired::createRetina(inputFrame.size());
/* retina parameters management methods use sample
-> save current (here default) retina parameters to a xml file (you may use it only one time to get the file and modify it)
*/
myRetina->write("RetinaDefaultParameters.xml");
// -> load parameters if file exists
myRetina->setup("RetinaSpecificParameters.xml");
// reset all retina buffers (open your eyes)
myRetina->clearBuffers();
// declare retina output buffers
cv::Mat retinaOutput_parvo;
cv::Mat retinaOutput_magno;
//main processing loop
while(true){
// if using video stream, then, grabbing a new frame, else, input remains the same
if (videoCapture.isOpened())
videoCapture>>inputFrame;
else
break;
imshow('input frame', inputImage)
// run retina on the input image
myRetina->run(inputFrame);
// grab retina outputs
myRetina->getParvo(retinaOutput_parvo);
myRetina->getMagno(retinaOutput_magno);
// draw retina outputs
cv::imshow("retina input", inputFrame);
cv::imshow("Retina Parvo", retinaOutput_parvo);
cv::imshow("Retina Magno", retinaOutput_magno);
cv::waitKey(5);
}
}
@endcode
Compile this C++ code with the following command :
@code{.sh}
// compile
g++ basicRetina.cpp -o basicRetina -lopencv_core -lopencv_highgui -lopencv_bioinspired -lopencv_videoio -lopencv_imgcodecs
@endcode
Use : this model can be used basically for spatio-temporal video effects but also in the aim of :
- performing texture analysis with enhanced signal to noise ratio and enhanced details robust
against input images luminance ranges (check out the parvocellular retina channel output, by
using the provided **getParvo** methods)
- performing motion analysis also taking benefit of the previously cited properties (check out the
magnocellular retina channel output, by using the provided **getMagno** methods)
- general image/video sequence description using either one or both channels. An example of the
use of Retina in a Bag of Words approach is given in @cite Strat2013 .
Python version
Literature
----------
@code{.py}
#import OpenCV module
import cv2
For more information, refer to the following papers :
#setup webcam reader
videoHandler = cv2.VideoCapture(0)
succeed, inputImage=videoHandler.read()
- Model description : @cite Benoit2010
#allocate a retina instance with input size equal to the one of the loaded image
retina = cv2.bioinspired.createRetina((inputImage.shape[1], inputImage.shape[0]))
- Model use in a Bag of Words approach : @cite Strat2013
#retina parameters management methods use sample
#-> save current (here default) retina parameters to a xml file (you may use it only one time to get the file and modify it)
retina.write('retinaParams.xml')
#-> load retina parameters from a xml file : here we load the default parameters that we just wrote to file
retina.setup('retinaParams.xml')
- Please have a look at the reference work of Jeanny Herault that you can read in his book : @cite Herault2010
#main processing loop
stillProcess=True
while stillProcess is True:
This retina filter code includes the research contributions of phd/research collegues from which
code has been redrawn by the author :
#grab a new frame and display it
stillProcess, inputImage=videoHandler.read()
cv2.imshow('input frame', inputImage)
- take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color
mosaicing/demosaicing and his reference paper: @cite Chaix2007
#run retina on the input image
retina.run(inputImage)
- 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. More informations in the above cited
Jeanny Heraults's book.
#grab retina outputs
retinaOut_parvo=retina.getParvo()
retinaOut_magno=retina.getMagno()
- Meylan&al work on HDR tone mapping that is implemented as a specific method within the model : @cite Meylan2007
#draw retina outputs
cv2.imshow('retina parvo out', retinaOut_parvo)
cv2.imshow('retina magno out', retinaOut_magno)
#wait a little to let the time for figures to be drawn
cv2.waitKey(2)
@endcode
Demos and experiments !
-----------------------
#### More complete demos
@note Complementary to the following examples, have a look at the Retina tutorial in the
tutorial/contrib section for complementary explanations.**
@ -195,7 +488,7 @@ Take a look at the provided C++ examples provided with OpenCV :
Then, take a HDR image using bracketing with your camera and generate an OpenEXR image and
then process it using the demo.
Typical use, supposing that you have the OpenEXR image such as *memorial.exr* (present in the
Typical use, assuming that you have the OpenEXR image such as *memorial.exr* (present in the
samples/cpp/ folder)
- **OpenCVReleaseFolder/bin/OpenEXRimages\_HDR\_Retina\_toneMapping memorial.exr [optional:
@ -205,6 +498,8 @@ Take a look at the provided C++ examples provided with OpenCV :
If not using the 'fast' option, then, tone mapping is performed using the full retina model
@cite Benoit2010 . It includes spectral whitening that allows luminance energy to be reduced.
When using the 'fast' option, then, a simpler method is used, it is an adaptation of the
algorithm presented in @cite Meylan2007 . This method gives also good results and is faster to
When using the 'fast' option, a simpler method is used, it is an adaptation of the
algorithm presented in @cite Meylan2007 . This method also gives good results and it is faster to
process but it sometimes requires some more parameters adjustement.

@ -11,7 +11,7 @@
**
** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
**
** Creation - enhancement process 2007-2013
** Creation - enhancement process 2007-2015
** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
**
** 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).
@ -33,7 +33,7 @@
** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
**
** For Human Visual System tools (bioinspired)
** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
** Copyright (C) 2007-2015, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
**
** Third party copyrights are property of their respective owners.
**
@ -86,36 +86,10 @@ enum {
RETINA_COLOR_BAYER//!< standard bayer sampling
};
/** @brief class which allows the Gipsa/Listic Labs model to be used with OpenCV.
This retina model allows spatio-temporal image processing (applied on still images, video sequences).
As a summary, these are the retina model properties:
- It applies a spectral whithening (mid-frequency details enhancement)
- high frequency spatio-temporal noise reduction
- low frequency luminance to be reduced (luminance range compression)
- local logarithmic luminance compression allows details to be enhanced in low light conditions
USE : this model can be used basically for spatio-temporal video effects but also for :
_using the getParvo method output matrix : texture analysiswith enhanced signal to noise ratio and enhanced details robust against input images luminance ranges
_using the getMagno method output matrix : motion analysis also with the previously cited properties
for more information, reer to the following papers :
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
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.
The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
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.
more informations in the above cited Jeanny Heraults's book.
*/
class CV_EXPORTS_W Retina : public Algorithm {
/** @brief retina model parameters structure
public:
/** @brief parameters structure
for better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel
For better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel
Here is the default configuration file of the retina module. It gives results such as the first
retina output shown on the top of this page.
@ -172,9 +146,9 @@ public:
</opencv_storage>
@endcode
*/
struct CV_EXPORTS_W RetinaParameters{
struct RetinaParameters{
//! Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters
struct CV_EXPORTS_W OPLandIplParvoParameters{
struct OPLandIplParvoParameters{
OPLandIplParvoParameters():colorMode(true),
normaliseOutput(true),
photoreceptorsLocalAdaptationSensitivity(0.75f),
@ -184,11 +158,11 @@ public:
hcellsTemporalConstant(0.5f),
hcellsSpatialConstant(7.f),
ganglionCellsSensitivity(0.75f) { } // default setup
CV_PROP_RW bool colorMode, normaliseOutput;
CV_PROP_RW float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity;
bool colorMode, normaliseOutput;
float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity;
};
//! Inner Plexiform Layer Magnocellular channel (IplMagno)
struct CV_EXPORTS_W IplMagnoParameters{
struct IplMagnoParameters{
IplMagnoParameters():
normaliseOutput(true),
parasolCells_beta(0.f),
@ -198,13 +172,43 @@ public:
V0CompressionParameter(0.95f),
localAdaptintegration_tau(0.f),
localAdaptintegration_k(7.f) { } // default setup
CV_PROP_RW bool normaliseOutput;
CV_PROP_RW float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k;
bool normaliseOutput;
float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k;
};
CV_PROP_RW OPLandIplParvoParameters OPLandIplParvo;
CV_PROP_RW IplMagnoParameters IplMagno;
OPLandIplParvoParameters OPLandIplParvo;
IplMagnoParameters IplMagno;
};
/** @brief class which allows the Gipsa/Listic Labs model to be used with OpenCV.
This retina model allows spatio-temporal image processing (applied on still images, video sequences).
As a summary, these are the retina model properties:
- It applies a spectral whithening (mid-frequency details enhancement)
- high frequency spatio-temporal noise reduction
- low frequency luminance to be reduced (luminance range compression)
- local logarithmic luminance compression allows details to be enhanced in low light conditions
USE : this model can be used basically for spatio-temporal video effects but also for :
_using the getParvo method output matrix : texture analysiswith enhanced signal to noise ratio and enhanced details robust against input images luminance ranges
_using the getMagno method output matrix : motion analysis also with the previously cited properties
for more information, reer to the following papers :
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
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.
The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
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.
more informations in the above cited Jeanny Heraults's book.
*/
class CV_EXPORTS_W Retina : public Algorithm {
public:
/** @brief Retreive retina input buffer size
@return the retina input buffer size
*/
@ -231,17 +235,17 @@ public:
@param fs the open Filestorage which contains retina parameters
@param applyDefaultSetupOnFailure set to true if an error must be thrown on error
*/
CV_WRAP virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0;
virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0;
/** @overload
@param newParameters a parameters structures updated with the new target configuration.
*/
CV_WRAP virtual void setup(RetinaParameters newParameters)=0;
virtual void setup(RetinaParameters newParameters)=0;
/**
@return the current parameters setup
@return the current parameters setup
*/
CV_WRAP virtual RetinaParameters getParameters()=0;
virtual RetinaParameters getParameters()=0;
/** @brief Outputs a string showing the used parameters setup
@return a string which contains formated parameters information
@ -255,23 +259,7 @@ public:
CV_WRAP virtual void write( String fs ) const=0;
/** @overload */
CV_WRAP virtual void write( FileStorage& fs ) const=0;
/**
setup the OPL and IPL parvo channels (see biologocal model)
OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy)
IPL parvo is the OPL next processing stage, it refers to Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision.
for more informations, please have a look at the paper 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
@param colorMode : specifies if (true) color is processed of not (false) to then processing gray level image
@param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false)
@param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases)
@param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame
@param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel
@param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0
@param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors
@param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model)
@param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230
*/
virtual void write( FileStorage& fs ) const=0;
/** @brief Setup the OPL and IPL parvo channels (see biologocal model)
@ -280,6 +268,7 @@ public:
(low frequency energy) IPL parvo is the OPL next processing stage, it refers to a part of the
Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. See
reference papers for more informations.
for more informations, please have a look at the paper 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
@param colorMode specifies if (true) color is processed of not (false) to then processing gray
level image
@param normaliseOutput specifies if (true) output is rescaled between 0 and 255 of not (false)
@ -306,7 +295,7 @@ public:
output, set a value between 0.6 and 1 for best results, a high value increases more the low
value sensitivity... and the output saturates faster, recommended value: 0.7
*/
CV_WRAP virtual void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7)=0;
CV_WRAP virtual void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7f, const float photoreceptorsTemporalConstant=0.5f, const float photoreceptorsSpatialConstant=0.53f, const float horizontalCellsGain=0.f, const float HcellsTemporalConstant=1.f, const float HcellsSpatialConstant=7.f, const float ganglionCellsSensitivity=0.7f)=0;
/** @brief Set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel
@ -333,7 +322,7 @@ public:
@param localAdaptintegration_k specifies the spatial constant of the low pas filter involved
in the computation of the local "motion mean" for the local adaptation computation
*/
CV_WRAP virtual void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7)=0;
CV_WRAP virtual void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0.f, const float parasolCells_tau=0.f, const float parasolCells_k=7.f, const float amacrinCellsTemporalCutFrequency=1.2f, const float V0CompressionParameter=0.95f, const float localAdaptintegration_tau=0.f, const float localAdaptintegration_k=7.f)=0;
/** @brief Method which allows retina to be applied on an input image,
@ -409,7 +398,7 @@ public:
@param colorSaturationValue the saturation factor : a simple factor applied on the chrominance
buffers
*/
CV_WRAP virtual void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0)=0;
CV_WRAP virtual void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0f)=0;
/** @brief Clears all retina buffers
@ -455,11 +444,11 @@ underscaled, then a reduction of the output is allowed without precision leak
@param samplingStrenght only usefull if param useRetinaLogSampling=true, specifies the strenght of
the log scale that is applied
*/
CV_EXPORTS_W Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
CV_EXPORTS_W Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
#ifdef HAVE_OPENCV_OCL
Ptr<Retina> createRetina_OCL(Size inputSize);
Ptr<Retina> createRetina_OCL(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
Ptr<Retina> createRetina_OCL(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
#endif
//! @}

@ -12,12 +12,12 @@
**
** Maintainers : Listic lab (code author current affiliation & applications)
**
** Creation - enhancement process 2007-2013
** Creation - enhancement process 2007-2015
** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
**
** 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).
** Refer to the following research paper for more information:
** Strat S. T. , Benoit A.Lambert P. , Caplier A., "Retina Enhanced SURF Descriptors for Spatio-Temporal Concept Detection", Multimedia Tools and Applications, 2012 (DOI: 10.1007/s11042-012-1280-0)
** Strat, S.T.; Benoit, A.; Lambert, P., "Retina enhanced bag of words descriptors for video classification," Signal Processing Conference (EUSIPCO), 2014 Proceedings of the 22nd European , vol., no., pp.1307,1311, 1-5 Sept. 2014 (http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6952461&isnumber=6951911)
** 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
** 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:
** 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.
@ -30,7 +30,7 @@
** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
**
** For Human Visual System tools (bioinspired)
** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
** Copyright (C) 2007-2015, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
**
** Third party copyrights are property of their respective owners.
**
@ -74,10 +74,37 @@ namespace cv
{
namespace bioinspired
{
//! @addtogroup bioinspired
//! @{
/** @brief parameter structure that stores the transient events detector setup parameters
*/
struct SegmentationParameters{ // CV_EXPORTS_W_MAP to export to python native dictionnaries
// default structure instance construction with default values
SegmentationParameters():
thresholdON(100),
thresholdOFF(100),
localEnergy_temporalConstant(0.5),
localEnergy_spatialConstant(5),
neighborhoodEnergy_temporalConstant(1),
neighborhoodEnergy_spatialConstant(15),
contextEnergy_temporalConstant(1),
contextEnergy_spatialConstant(75){};
// all properties list
float thresholdON;
float thresholdOFF;
//! the time constant of the first order low pass filter, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 0.5 frame
float localEnergy_temporalConstant;
//! the spatial constant of the first order low pass filter, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 5 pixel
float localEnergy_spatialConstant;
//! local neighborhood energy filtering parameters : the aim is to get information about the energy neighborhood to perform a center surround energy analysis
float neighborhoodEnergy_temporalConstant;
float neighborhoodEnergy_spatialConstant;
//! context neighborhood energy filtering parameters : the aim is to get information about the energy on a wide neighborhood area to filtered out local effects
float contextEnergy_temporalConstant;
float contextEnergy_spatialConstant;
};
/** @brief class which provides a transient/moving areas segmentation module
perform a locally adapted segmentation by using the retina magno input data Based on Alexandre
@ -96,30 +123,6 @@ class CV_EXPORTS_W TransientAreasSegmentationModule: public Algorithm
{
public:
//! parameters structure
struct CV_EXPORTS_W SegmentationParameters{
SegmentationParameters():
thresholdON(100),
thresholdOFF(100),
localEnergy_temporalConstant(0.5),
localEnergy_spatialConstant(5),
neighborhoodEnergy_temporalConstant(1),
neighborhoodEnergy_spatialConstant(15),
contextEnergy_temporalConstant(1),
contextEnergy_spatialConstant(75){};// default setup
CV_PROP_RW float thresholdON;
CV_PROP_RW float thresholdOFF;
//! the time constant of the first order low pass filter, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 0.5 frame
CV_PROP_RW float localEnergy_temporalConstant;
//! the spatial constant of the first order low pass filter, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 5 pixel
CV_PROP_RW float localEnergy_spatialConstant;
//! local neighborhood energy filtering parameters : the aim is to get information about the energy neighborhood to perform a center surround energy analysis
CV_PROP_RW float neighborhoodEnergy_temporalConstant;
CV_PROP_RW float neighborhoodEnergy_spatialConstant;
//! context neighborhood energy filtering parameters : the aim is to get information about the energy on a wide neighborhood area to filtered out local effects
CV_PROP_RW float contextEnergy_temporalConstant;
CV_PROP_RW float contextEnergy_spatialConstant;
};
/** @brief return the sze of the manage input and output images
*/
@ -141,7 +144,7 @@ public:
@param fs : the open Filestorage which contains segmentation parameters
@param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
*/
CV_WRAP virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0;
virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0;
/** @brief try to open an XML segmentation parameters file to adjust current segmentation instance setup
@ -149,11 +152,11 @@ public:
- warning, Exceptions are thrown if read XML file is not valid
@param newParameters : a parameters structures updated with the new target configuration
*/
CV_WRAP virtual void setup(SegmentationParameters newParameters)=0;
virtual void setup(SegmentationParameters newParameters)=0;
/** @brief return the current parameters setup
*/
CV_WRAP virtual SegmentationParameters getParameters()=0;
virtual SegmentationParameters getParameters()=0;
/** @brief parameters setup display method
@return a string which contains formatted parameters information
@ -168,7 +171,7 @@ public:
/** @brief write xml/yml formated parameters information
@param fs : a cv::Filestorage object ready to be filled
*/
CV_WRAP virtual void write( cv::FileStorage& fs ) const=0;
virtual void write( cv::FileStorage& fs ) const=0;
/** @brief main processing method, get result using methods getSegmentationPicture()
@param inputToSegment : the image to process, it must match the instance buffer size !

@ -0,0 +1,91 @@
//============================================================================
// Name : retinademo.cpp
// Author : Alexandre Benoit, benoit.alexandre.vision@gmail.com
// Version : 0.1
// Copyright : LISTIC/GIPSA French Labs, May 2015
// Description : Gipsa/LISTIC Labs quick retina demo in C++, Ansi-style
//============================================================================
// include bioinspired module and OpenCV core utilities
#include "opencv2/bioinspired.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <cstring>
// main function
int main(int argc, char* argv[]) {
// basic input arguments checking
if (argc>1)
{
std::cout<<"****************************************************"<<std::endl;
std::cout<<"* Retina demonstration : demonstrates the use of is a wrapper class of the Gipsa/Listic Labs retina model."<<std::endl;
std::cout<<"* This retina model allows spatio-temporal image processing (applied on a webcam sequences)."<<std::endl;
std::cout<<"* As a summary, these are the retina model properties:"<<std::endl;
std::cout<<"* => It applies a spectral whithening (mid-frequency details enhancement)"<<std::endl;
std::cout<<"* => high frequency spatio-temporal noise reduction"<<std::endl;
std::cout<<"* => low frequency luminance to be reduced (luminance range compression)"<<std::endl;
std::cout<<"* => local logarithmic luminance compression allows details to be enhanced in low light conditions\n"<<std::endl;
std::cout<<"* for more information, reer to the following papers :"<<std::endl;
std::cout<<"* 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"<<std::endl;
std::cout<<"* 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."<<std::endl;
std::cout<<"* => reports comments/remarks at benoit.alexandre.vision@gmail.com"<<std::endl;
std::cout<<"* => more informations and papers at : http://sites.google.com/site/benoitalexandrevision/"<<std::endl;
std::cout<<"****************************************************"<<std::endl;
std::cout<<" NOTE : this program generates the default retina parameters file 'RetinaDefaultParameters.xml'"<<std::endl;
std::cout<<" => you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<<std::endl;
if (strcmp(argv[1], "help")==0){
std::cout<<"No help provided for now, please test the retina Demo for a more complete program"<<std::endl;
}
}
std::string inputMediaType=argv[1];
// declare the retina input buffer.
cv::Mat inputFrame;
// setup webcam reader and grab a first frame to get its size
cv::VideoCapture videoCapture(0);
videoCapture>>inputFrame;
// allocate a retina instance with input size equal to the one of the loaded image
cv::Ptr<cv::bioinspired::Retina> myRetina = cv::bioinspired::createRetina(inputFrame.size());
/* retina parameters management methods use sample
-> save current (here default) retina parameters to a xml file (you may use it only one time to get the file and modify it)
*/
myRetina->write("RetinaDefaultParameters.xml");
// -> load parameters if file exists
myRetina->setup("RetinaSpecificParameters.xml");
// reset all retina buffers (open your eyes)
myRetina->clearBuffers();
// declare retina output buffers
cv::Mat retinaOutput_parvo;
cv::Mat retinaOutput_magno;
//main processing loop
bool stillProcess=true;
while(stillProcess){
// if using video stream, then, grabbing a new frame, else, input remains the same
if (videoCapture.isOpened())
videoCapture>>inputFrame;
else
stillProcess=false;
// run retina filter
myRetina->run(inputFrame);
// Retrieve and display retina output
myRetina->getParvo(retinaOutput_parvo);
myRetina->getMagno(retinaOutput_magno);
cv::imshow("retina input", inputFrame);
cv::imshow("Retina Parvo", retinaOutput_parvo);
cv::imshow("Retina Magno", retinaOutput_magno);
cv::waitKey(5);
}
}

@ -11,7 +11,7 @@
**
** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
**
** Creation - enhancement process 2007-2011
** Creation - enhancement process 2007-2015
** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
**
** 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).
@ -30,7 +30,7 @@
** For Open Source Computer Vision Library
**
** Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
** Copyright (C) 2008-2015, Willow Garage Inc., all rights reserved.
**
** For Human Visual System tools (bioinspired)
** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
@ -97,7 +97,7 @@ public:
* @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak
* @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied
*/
RetinaImpl(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
RetinaImpl(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
virtual ~RetinaImpl();
/**
@ -136,12 +136,12 @@ public:
* @param newParameters : a parameters structures updated with the new target configuration
* @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
*/
void setup(Retina::RetinaParameters newParameters);
void setup(RetinaParameters newParameters);
/**
* @return the current parameters setup
*/
struct Retina::RetinaParameters getParameters();
struct RetinaParameters getParameters();
/**
* parameters setup display method
@ -177,7 +177,7 @@ public:
* @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model)
* @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230
*/
void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7);
void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7f, const float photoreceptorsTemporalConstant=0.5f, const float photoreceptorsSpatialConstant=0.53f, const float horizontalCellsGain=0.f, const float HcellsTemporalConstant=1.f, const float HcellsSpatialConstant=7.f, const float ganglionCellsSensitivity=0.7f);
/**
* set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel
@ -191,7 +191,7 @@ public:
* @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
* @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
*/
void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7);
void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0.f, const float parasolCells_tau=0.f, const float parasolCells_k=7.f, const float amacrinCellsTemporalCutFrequency=1.2f, const float V0CompressionParameter=0.95f, const float localAdaptintegration_tau=0.f, const float localAdaptintegration_k=7.f);
/**
* method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods
@ -241,7 +241,7 @@ public:
* @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
* @param colorSaturationValue: the saturation factor
*/
void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0);
void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0f);
/**
* clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o)
@ -271,7 +271,7 @@ private:
RetinaFilter* _retinaFilter; //!< the pointer to the retina module, allocated with instance construction
//! private method called by constructors, gathers their parameters and use them in a unified way
void _init(const Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
void _init(const Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
/**
* exports a valarray buffer outing from bioinspired objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format
@ -296,7 +296,7 @@ private:
// smart pointers allocation :
Ptr<Retina> createRetina(Size inputSize){ return makePtr<RetinaImpl>(inputSize); }
Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght){
Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght){
return makePtr<RetinaImpl>(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght);
}
@ -308,7 +308,7 @@ RetinaImpl::RetinaImpl(const cv::Size inputSz)
_init(inputSz, true, RETINA_COLOR_BAYER, false);
}
RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght)
RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght)
{
_retinaFilter = 0;
_init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght);
@ -336,7 +336,7 @@ void RetinaImpl::setColorSaturation(const bool saturateColors, const float color
_retinaFilter->setColorSaturation(saturateColors, colorSaturationValue);
}
struct Retina::RetinaParameters RetinaImpl::getParameters(){return _retinaParameters;}
struct RetinaParameters RetinaImpl::getParameters(){return _retinaParameters;}
void RetinaImpl::setup(String retinaParameterFile, const bool applyDefaultSetupOnFailure)
{
@ -416,10 +416,10 @@ void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailur
printf("%s\n", printSetup().c_str());
}
void RetinaImpl::setup(Retina::RetinaParameters newConfiguration)
void RetinaImpl::setup(RetinaParameters newConfiguration)
{
// simply copy structures
memcpy(&_retinaParameters, &newConfiguration, sizeof(Retina::RetinaParameters));
memcpy(&_retinaParameters, &newConfiguration, sizeof(RetinaParameters));
// apply setup
setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity);
setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k);
@ -616,7 +616,7 @@ const Mat RetinaImpl::getParvoRAW() const {
}
// private method called by constructirs
void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght)
void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght)
{
// basic error check
if (inputSz.height*inputSz.width <= 0)

@ -12,12 +12,12 @@
**
** Maintainers : Listic lab (code author current affiliation & applications)
**
** Creation - enhancement process 2007-2013
** Creation - enhancement process 2007-2015
** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
**
** 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).
** Refer to the following research paper for more information:
** Strat S. T. , Benoit A.Lambert P. , Caplier A., "Retina Enhanced SURF Descriptors for Spatio-Temporal Concept Detection", Multimedia Tools and Applications, 2012 (DOI: 10.1007/s11042-012-1280-0)
** Strat, S.T.; Benoit, A.; Lambert, P., "Retina enhanced bag of words descriptors for video classification," Signal Processing Conference (EUSIPCO), 2014 Proceedings of the 22nd European , vol., no., pp.1307,1311, 1-5 Sept. 2014 (http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6952461&isnumber=6951911)
** 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
** 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:
** 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.
@ -30,7 +30,7 @@
** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
**
** For Human Visual System tools (bioinspired)
** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
** Copyright (C) 2007-2015, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
**
** Third party copyrights are property of their respective owners.
**
@ -132,12 +132,12 @@ public:
* @param newParameters : a parameters structures updated with the new target configuration
* @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
*/
void setup(TransientAreasSegmentationModule::SegmentationParameters newParameters);
void setup(SegmentationParameters newParameters);
/**
* @return the current parameters setup
*/
struct TransientAreasSegmentationModule::SegmentationParameters getParameters();
struct SegmentationParameters getParameters();
/**
* parameters setup display method
@ -203,7 +203,7 @@ protected:
*/
inline const std::valarray<float> &getMotionContextPicture() const {return _contextMotionEnergy;};
struct cv::bioinspired::TransientAreasSegmentationModule::SegmentationParameters _segmentationParameters;
struct cv::bioinspired::SegmentationParameters _segmentationParameters;
// template buffers and related acess pointers
std::valarray<float> _inputToSegment;
std::valarray<float> _contextMotionEnergy;
@ -221,7 +221,7 @@ protected:
void _convertValarrayBuffer2cvMat(const std::valarray<bool> &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, OutputArray outBuffer);
bool _convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray<float> &outputValarrayMatrix);
const TransientAreasSegmentationModuleImpl & operator = (const TransientAreasSegmentationModuleImpl &);
const TransientAreasSegmentationModuleImpl & operator = (const TransientAreasSegmentationModuleImpl &);
};
class TransientAreasSegmentationModuleImpl_: public TransientAreasSegmentationModule
@ -232,9 +232,9 @@ public:
inline virtual void write( cv::FileStorage& fs ) const{_segmTool.write(fs);};
inline virtual void setup(String segmentationParameterFile, const bool applyDefaultSetupOnFailure){_segmTool.setup(segmentationParameterFile, applyDefaultSetupOnFailure);};
inline virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure){_segmTool.setup(fs, applyDefaultSetupOnFailure);};
inline virtual void setup(TransientAreasSegmentationModule::SegmentationParameters newParameters){_segmTool.setup(newParameters);};
inline virtual void setup(SegmentationParameters newParameters){_segmTool.setup(newParameters);};
inline virtual const String printSetup(){return _segmTool.printSetup();};
inline virtual struct TransientAreasSegmentationModule::SegmentationParameters getParameters(){return _segmTool.getParameters();};
inline virtual struct SegmentationParameters getParameters(){return _segmTool.getParameters();};
inline virtual void write( String fs ) const{_segmTool.write(fs);};
inline virtual void run(InputArray inputToSegment, const int channelIndex){_segmTool.run(inputToSegment, channelIndex);};
inline virtual void getSegmentationPicture(OutputArray transientAreas){return _segmTool.getSegmentationPicture(transientAreas);};
@ -286,7 +286,7 @@ void TransientAreasSegmentationModuleImpl::clearAllBuffers()
_segmentedAreas=0;
}
struct TransientAreasSegmentationModule::SegmentationParameters TransientAreasSegmentationModuleImpl::getParameters()
struct SegmentationParameters TransientAreasSegmentationModuleImpl::getParameters()
{
return _segmentationParameters;
};
@ -305,7 +305,7 @@ void TransientAreasSegmentationModuleImpl::setup(String segmentationParameterFil
if (applyDefaultSetupOnFailure)
{
printf("Retina::setup: resetting retina with default parameters\n");
cv::bioinspired::TransientAreasSegmentationModule::SegmentationParameters defaults;
cv::bioinspired::SegmentationParameters defaults;
setup(defaults);
}
else
@ -344,7 +344,7 @@ void TransientAreasSegmentationModuleImpl::setup(cv::FileStorage &fs, const bool
std::cout<<"Retina::setup: resetting retina with default parameters"<<std::endl;
if (applyDefaultSetupOnFailure)
{
struct cv::bioinspired::TransientAreasSegmentationModule::SegmentationParameters defaults;
struct cv::bioinspired::SegmentationParameters defaults;
setup(defaults);
}
std::cout<<"SegmentationModule::setup: wrong/unappropriate xml parameter file : error report :`n=>"<<e.what()<<std::endl;
@ -356,11 +356,11 @@ void TransientAreasSegmentationModuleImpl::setup(cv::FileStorage &fs, const bool
}
// setup parameters for the 2 filters that allow the segmentation
void TransientAreasSegmentationModuleImpl::setup(cv::bioinspired::TransientAreasSegmentationModule::SegmentationParameters newParameters)
void TransientAreasSegmentationModuleImpl::setup(cv::bioinspired::SegmentationParameters newParameters)
{
// copy structure contents
memcpy(&_segmentationParameters, &newParameters, sizeof(cv::bioinspired::TransientAreasSegmentationModule::SegmentationParameters));
memcpy(&_segmentationParameters, &newParameters, sizeof(cv::bioinspired::SegmentationParameters));
// apply setup
// init local motion energy extraction low pass filter
BasicRetinaFilter::setLPfilterParameters(0, newParameters.localEnergy_temporalConstant, newParameters.localEnergy_spatialConstant);

@ -116,7 +116,7 @@ For more information, refer to the following papers : @cite Benoit2010
- Please have a look at the reference work of Jeanny Herault that you can read in his book @cite Herault2010
This retina filter code includes the research contributions of phd/research collegues from which
This retina filter code includes the research contributions of phd/research colleagues from which
code has been redrawn by the author :
- take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color
@ -141,7 +141,7 @@ read)* and opencv_bioinspired *(Retina description)* libraries to compile.
@code{.sh}
// compile
gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired
gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired -lopencv_videoio -lopencv_imgcodecs
// Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling)
// run on webcam
@ -205,7 +205,7 @@ by the Boolean flag *useLogSampling*.
// welcome message
std::cout<<"****************************************************"<<std::endl;
std::cout<<"* Retina demonstration : demonstrates the use of is a wrapper class of the Gipsa/Listic Labs retina model."<<std::endl;
std::cout<<"* This demo will try to load the file 'RetinaSpecificParameters.xml' (if exists).\nTo create it, copy the autogenerated template 'RetinaDefaultParameters.xml'.\nThen twaek it with your own retina parameters."<<std::endl;
std::cout<<"* This demo will try to load the file 'RetinaSpecificParameters.xml' (if exists).\nTo create it, copy the autogenerated template 'RetinaDefaultParameters.xml'.\nThen tweak it with your own retina parameters."<<std::endl;
// basic input arguments checking
if (argc<2)
{
@ -259,7 +259,7 @@ to manage the eventual log sampling option. The Retina constructor expects at le
object that shows the input data size that will have to be managed. One can activate other options
such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using
*enum cv::bioinspired::RETINA_COLOR_BAYER*). If using log sampling, the image reduction factor
(smaller output images) and log sampling strengh can be adjusted.
(smaller output images) and log sampling strength can be adjusted.
@code{.cpp}
// pointer to a retina object
cv::Ptr<cv::bioinspired::Retina> myRetina;
@ -381,96 +381,98 @@ Then, if the application target requires details enhancement prior to specific i
need to know if mean luminance information is required or not. If not, the the retina can cancel or
significantly reduce its energy thus giving more visibility to higher spatial frequency details.
### Basic parameters
The most simple parameters are the following :
#### Basic parameters
The simplest parameters are as follows :
- **colorMode** : let the retina process color information (if 1) or gray scale images (if 0). In
this last case, only the first channel of the input will be processed.
- **normaliseOutput** : each channel has this parameter, if value is 1, then the considered
channel output is rescaled between 0 and 255. Take care in this case at the Magnocellular output
that last case, only the first channels of the input will be processed.
- **normaliseOutput** : each channel has such parameter: if the value is set to 1, then the considered
channel's output is rescaled between 0 and 255. Be aware at this case of the Magnocellular output
level (motion/transient channel detection). Residual noise will also be rescaled !
**Note :** using color requires color channels multiplexing/demultipexing which requires more
**Note :** using color requires color channels multiplexing/demultipexing which also demands more
processing. You can expect much faster processing using gray levels : it would require around 30
product per pixel for all the retina processes and it has recently been parallelized for multicore
product per pixel for all of the retina processes and it has recently been parallelized for multicore
architectures.
### Photo-receptors parameters
#### Photo-receptors parameters
The following parameters act on the entry point of the retina - photo-receptors - and impact all the
following processes. These sensors are low pass spatio-temporal filters that smooth temporal and
spatial data and also adjust there sensitivity to local luminance thus improving details extraction
The following parameters act on the entry point of the retina - photo-receptors - and has impact on all
of the following processes. These sensors are low pass spatio-temporal filters that smooth temporal and
spatial data and also adjust their sensitivity to local luminance,thus, leads to improving details extraction
and high frequency noise canceling.
- **photoreceptorsLocalAdaptationSensitivity** between 0 and 1. Values close to 1 allow high
luminance log compression effect at the photo-receptors level. Values closer to 0 give a more
luminance log compression's effect at the photo-receptors level. Values closer to 0 provide a more
linear sensitivity. Increased alone, it can burn the *Parvo (details channel)* output image. If
adjusted in collaboration with **ganglionCellsSensitivity** images can be very contrasted
whatever the local luminance there is... at the price of a naturalness decrease.
adjusted in collaboration with **ganglionCellsSensitivity**,images can be very contrasted
whatever the local luminance there is... at the cost of a naturalness decrease.
- **photoreceptorsTemporalConstant** this setups the temporal constant of the low pass filter
effect at the entry of the retina. High value lead to strong temporal smoothing effect : moving
effect at the entry of the retina. High value leads to strong temporal smoothing effect : moving
objects are blurred and can disappear while static object are favored. But when starting the
retina processing, stable state is reached lately.
- **photoreceptorsSpatialConstant** specifies the spatial constant related to photo-receptors low
pass filter effect. This parameters specify the minimum allowed spatial signal period allowed in
the following. Typically, this filter should cut high frequency noise. Then a 0 value doesn't
cut anything noise while higher values start to cut high spatial frequencies and more and more
lower frequencies... Then, do not go to high if you wanna see some details of the input images !
A good compromise for color images is 0.53 since this won't affect too much the color spectrum.
retina processing, stable state is reached later.
- **photoreceptorsSpatialConstant** specifies the spatial constant related to photo-receptors' low
pass filter's effect. Those parameters specify the minimum value of the spatial signal period allowed
in what follows. Typically, this filter should cut high frequency noise. On the other hand, a 0 value
cuts none of the noise while higher values start to cut high spatial frequencies, and progressively
lower frequencies... Be aware to not go to high levels if you want to see some details of the input images !
A good compromise for color images is a 0.53 value since such choice won't affect too much the color spectrum.
Higher values would lead to gray and blurred output images.
### Horizontal cells parameters
#### Horizontal cells parameters
This parameter set tunes the neural network connected to the photo-receptors, the horizontal cells.
It modulates photo-receptors sensitivity and completes the processing for final spectral whitening
(part of the spatial band pass effect thus favoring visual details enhancement).
- **horizontalCellsGain** here is a critical parameter ! If you are not interested by the mean
luminance and focus on details enhancement, then, set to zero. But if you want to keep some
environment luminance data, let some low spatial frequencies pass into the system and set a
- **horizontalCellsGain** here is a critical parameter ! If you are not interested with the mean
luminance and want just to focus on details enhancement, then, set this parameterto zero. However, if
you want to keep some environment luminance's data, let some low spatial frequencies pass into the system and set a
higher value (\<1).
- **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a
low pass temporal filter that smooths input data. Here, a high value generates a high retina
- **hcellsTemporalConstant** similar to photo-receptors, this parameter acts on the temporal constant of a
low pass temporal filter that smoothes input data. Here, a high value generates a high retina
after effect while a lower value makes the retina more reactive. This value should be lower than
**photoreceptorsTemporalConstant** to limit strong retina after effects.
- **hcellsSpatialConstant** is the spatial constant of the low pass filter of these cells filter.
It specifies the lowest spatial frequency allowed in the following. Visually, a high value leads
- **hcellsSpatialConstant** is the spatial constant of these cells filter's low pass one.
It specifies the lowest spatial frequency allowed in what follows. Visually, a high value leads
to very low spatial frequencies processing and leads to salient halo effects. Lower values
reduce this effect but the limit is : do not go lower than the value of
reduce this effect but has the limit of not go lower than the value of
**photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of
the retina.
**NOTE** after the processing managed by the previous parameters, input data is cleaned from noise
and luminance in already partly enhanced. The following parameters act on the last processing stages
**NOTE** Once the processing managed by the previous parameters is done, input data is cleaned from noise
and luminance is already partly enhanced. The following parameters act on the last processing stages
of the two outing retina signals.
### Parvo (details channel) dedicated parameter
#### Parvo (details channel) dedicated parameter
- **ganglionCellsSensitivity** specifies the strength of the final local adaptation occurring at
the output of this details dedicated channel. Parameter values remain between 0 and 1. Low value
tend to give a linear response while higher values enforces the remaining low contrasted areas.
the output of this details' dedicated channel. Parameter values remain between 0 and 1. Low value
tend to give a linear response while higher values enforce the remaining low contrasted areas.
**Note :** this parameter can correct eventual burned images by favoring low energetic details of
the visual scene, even in bright areas.
### IPL Magno (motion/transient channel) parameters
#### IPL Magno (motion/transient channel) parameters
Once image information is cleaned, this channel acts as a high pass temporal filter that only
selects signals related to transient signals (events, motion, etc.). A low pass spatial filter
smooths extracted transient data and a final logarithmic compression enhances low transient events
Once image's information are cleaned, this channel acts as a high pass temporal filter that
selects only the signals related to transient signals (events, motion, etc.). A low pass spatial filter
smoothes extracted transient data while a final logarithmic compression enhances low transient events
thus enhancing event sensitivity.
- **parasolCells_beta** generally set to zero, can be considered as an amplifier gain at the
entry point of this processing stage. Generally set to 0.
- **parasolCells_tau** the temporal smoothing effect that can be added
- **parasolCells_k** the spatial constant of the spatial filtering effect, set it at a high value
to favor low spatial frequency signals that are lower subject to residual noise.
to favor low spatial frequency signals that are lower subject for residual noise.
- **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter.
High values let slow transient events to be selected.
- **V0CompressionParameter** specifies the strength of the log compression. Similar behaviors to
previous description but here it enforces sensitivity of transient events.
- **localAdaptintegration_tau** generally set to 0, no real use here actually
previous description but here enforces sensitivity of transient events.
- **localAdaptintegration_tau** generally set to 0, has no real use actually in here.
- **localAdaptintegration_k** specifies the size of the area on which local adaptation is
performed. Low values lead to short range local adaptation (higher sensitivity to noise), high
values secure log compression.

@ -13,21 +13,20 @@ using namespace cv::motempl;
static void help(void)
{
printf(
"\nThis program demonstrated the use of motion templates -- basically using the gradients\n"
"of thresholded layers of decaying frame differencing. New movements are stamped on top with floating system\n"
"time code and motions too old are thresholded away. This is the 'motion history file'. The program reads from the camera of your choice or from\n"
"a file. Gradients of motion history are used to detect direction of motoin etc\n"
"Usage :\n"
"./motempl [camera number 0-n or file name, default is camera 0]\n"
);
"\nThis program demonstrated the use of motion templates -- basically using the gradients\n"
"of thresholded layers of decaying frame differencing. New movements are stamped on top with floating system\n"
"time code and motions too old are thresholded away. This is the 'motion history file'. The program reads from the camera of your choice or from\n"
"a file. Gradients of motion history are used to detect direction of motion etc\n"
"Usage :\n"
"./motempl [camera number 0-n or file name, default is camera 0]\n"
);
}
// various tracking parameters (in seconds)
const double MHI_DURATION = 1;
const double MHI_DURATION = 5;
const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05;
// number of cyclic frame buffer used for motion detection
// (should, probably, depend on FPS)
const int N = 4;
// ring image buffer
vector<Mat> buf;
@ -41,9 +40,9 @@ vector<Rect> regions;
// img - input video frame
// dst - resultant motion picture
// args - optional parameters
static void update_mhi( const Mat& img, Mat& dst, int diff_threshold )
static void update_mhi(const Mat& img, Mat& dst, int diff_threshold)
{
double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
double timestamp = (double)clock() / CLOCKS_PER_SEC; // get current time in seconds
Size size = img.size();
int i, idx1 = last;
Rect comp_rect;
@ -55,57 +54,54 @@ static void update_mhi( const Mat& img, Mat& dst, int diff_threshold )
// allocate images at the beginning or
// reallocate them if the frame size is changed
if( mhi.size() != size )
if (mhi.size() != size)
{
mhi = Mat::zeros(size, CV_32F);
zplane = Mat::zeros(size, CV_8U);
buf.resize(N);
for( i = 0; i < N; i++ )
{
buf[i] = Mat::zeros(size, CV_8U);
}
buf[0] = Mat::zeros(size, CV_8U);
buf[1] = Mat::zeros(size, CV_8U);
}
cvtColor( img, buf[last], COLOR_BGR2GRAY ); // convert frame to grayscale
cvtColor(img, buf[last], COLOR_BGR2GRAY); // convert frame to grayscale
int idx2 = (last + 1) % N; // index of (last - (N-1))th frame
int idx2 = (last + 1) % 2; // index of (last - (N-1))th frame
last = idx2;
Mat silh = buf[idx2];
absdiff( buf[idx1], buf[idx2], silh ); // get difference between frames
absdiff(buf[idx1], buf[idx2], silh); // get difference between frames
threshold( silh, silh, diff_threshold, 1, THRESH_BINARY ); // and threshold it
updateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
threshold(silh, silh, diff_threshold, 1, THRESH_BINARY); // and threshold it
updateMotionHistory(silh, mhi, timestamp, MHI_DURATION); // update MHI
// convert MHI to blue 8u image
mhi.convertTo( mask, CV_8U, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION );
Mat planes[] = {mask, zplane, zplane};
mhi.convertTo(mask, CV_8U, 255. / MHI_DURATION, (MHI_DURATION - timestamp)*255. / MHI_DURATION);
Mat planes[] = { mask, zplane, zplane };
merge(planes, 3, dst);
// calculate motion gradient orientation and valid orientation mask
calcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );
calcMotionGradient(mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3);
// segment motion: get sequence of motion components
// segmask is marked motion components map. It is not used further
regions.clear();
segmentMotion(mhi, segmask, regions, timestamp, MAX_TIME_DELTA);
// iterate through the motion components,
// One more iteration (i == -1) corresponds to the whole image (global motion)
for( i = -1; i < (int)regions.size(); i++ ) {
for (i = -1; i < (int)regions.size(); i++) {
if( i < 0 ) { // case of the whole image
comp_rect = Rect( 0, 0, size.width, size.height );
color = Scalar(255,255,255);
if (i < 0) { // case of the whole image
comp_rect = Rect(0, 0, size.width, size.height);
color = Scalar(255, 255, 255);
magnitude = 100;
}
else { // i-th motion component
comp_rect = regions[i];
if( comp_rect.width + comp_rect.height < 100 ) // reject very small components
if (comp_rect.width + comp_rect.height < 100) // reject very small components
continue;
color = Scalar(0,0,255);
color = Scalar(0, 0, 255);
magnitude = 30;
}
@ -116,22 +112,22 @@ static void update_mhi( const Mat& img, Mat& dst, int diff_threshold )
Mat mask_roi = mask(comp_rect);
// calculate orientation
angle = calcGlobalOrientation( orient_roi, mask_roi, mhi_roi, timestamp, MHI_DURATION);
angle = calcGlobalOrientation(orient_roi, mask_roi, mhi_roi, timestamp, MHI_DURATION);
angle = 360.0 - angle; // adjust for images with top-left origin
count = norm( silh, 0, NORM_L1, 0 ); // calculate number of points within silhouette ROI
count = norm(silh_roi, NORM_L1);; // calculate number of points within silhouette ROI
// check for the case of little motion
if( count < comp_rect.width*comp_rect.height * 0.05 )
if (count < comp_rect.width*comp_rect.height * 0.05)
continue;
// draw a clock with arrow indicating the direction
center = Point( (comp_rect.x + comp_rect.width/2),
(comp_rect.y + comp_rect.height/2) );
center = Point((comp_rect.x + comp_rect.width / 2),
(comp_rect.y + comp_rect.height / 2));
circle( dst, center, cvRound(magnitude*1.2), color, 3, 16, 0 );
line( dst, center, Point( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, 16, 0 );
circle(img, center, cvRound(magnitude*1.2), color, 3, 16, 0);
line(img, center, Point(cvRound(center.x + magnitude*cos(angle*CV_PI / 180)),
cvRound(center.y - magnitude*sin(angle*CV_PI / 180))), color, 3, 16, 0);
}
}
@ -142,28 +138,29 @@ int main(int argc, char** argv)
help();
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
cap.open( argc == 2 ? argv[1][0] - '0' : 0 );
else if( argc == 2 )
cap.open( argv[1] );
if (argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
cap.open(argc == 2 ? argv[1][0] - '0' : 0);
else if (argc == 2)
cap.open(argv[1]);
if( !cap.isOpened() )
if (!cap.isOpened())
{
printf("Could not initialize video capture\n");
return 0;
}
buf.resize(2);
Mat image, motion;
for(;;)
for (;;)
{
cap >> image;
if( image.empty() )
if (image.empty())
break;
update_mhi( image, motion, 30 );
imshow( "Motion", motion );
update_mhi(image, motion, 30);
imshow("Image", image);
imshow("Motion", motion);
if( waitKey(10) >= 0 )
if (waitKey(10) >= 0)
break;
}

@ -1,3 +1,49 @@
Scene Text Detection and Recognition in Natural Scene Images
============================================================
The module contains algorithms to detect text, segment words and recognise the text.
It's mainly intended for the "text in the wild", i.e. short phrases and separate words that occur on navigation signs and such. It's not an OCR tool for scanned documents, do not treat it as such.
The detection part can in theory handle different languages, but will likely fail on hieroglyphic texts.
The recognition part currently uses open-source Tesseract OCR (https://code.google.com/p/tesseract-ocr/). If Tesseract OCR is not installed on your system, the corresponding part of the functionality will be unavailable.
Here are instructions on how to install Tesseract on your machine (Linux or Mac; Windows users should look for precompiled binaries or try to adopt the instructions below):
Tesseract installation instruction (Linux, Mac)
-----------------------------------------------
0. Linux users may try to install tesseract-3.03-rc1 (or later) and leptonica-1.70 (or later) with the corresponding developement packages using their package manager. Mac users may try brew. The instructions below are for those who wants to build tesseract from source.
1. download leptonica 1.70 tarball (helper image processing library, used by tesseract. Later versions might work too):
http://www.leptonica.com/download.html
unpack and build it:
cd leptonica-1.70
mkdir build && cd build && ../configure && make && sudo make install
leptonica will be installed to /usr/local.
2. download tesseract-3.03-rc1 tarball from https://drive.google.com/folderview?id=0B7l10Bj_LprhQnpSRkpGMGV2eE0&usp=sharing
unpack and build it:
# needed only to build tesseract
export LIBLEPT_HEADERSDIR=/usr/local/include/
cd tesseract-3.03
mkdir build && cd build
../configure --with-extra-includes=/usr/local --with-extra-libraries=/usr/local
make && sudo make install
tessract will be installed to /usr/local.
3. download the pre-trained classifier data for english language:
https://code.google.com/p/tesseract-ocr/downloads/detail?name=eng.traineddata.gz
unzip it (gzip -d eng.traineddata.gz) and copy to /usr/local/share/tessdata.
Notes
-----
1. Google announced that they close code.google.com, so at some moment in the future you may have to find Tesseract 3.03rc1 or later.
2. Tesseract configure script may fail to detect leptonica, so you may have to edit the configure script - comment off some if's around this message and retain only "then" branch.
3. You are encouraged to search the Net for some better pre-trained classifiers, as well as classifiers for other languages.

@ -1701,7 +1701,7 @@ public:
}
};
#if 0
/* Functions for the update of the dissimilarity array */
inline static void f_single( double * const b, const double a )
@ -1844,7 +1844,7 @@ static void NN_chain_core(const int_fast32_t N, double * const D, t_members * co
}
}
}
#endif
/*
Clustering methods for vector data

@ -53,3 +53,14 @@
year={2012}
publisher={NIPS}
}
@article{Tola10,
author = "E. Tola and V. Lepetit and P. Fua",
title = {{DAISY: An Efficient Dense Descriptor Applied to Wide Baseline Stereo}},
journal = "IEEE Transactions on Pattern Analysis and Machine Intelligence",
year = 2010,
month = "May",
pages = "815--830",
volume = "32",
number = "5"
}

@ -118,15 +118,14 @@ public:
/** @brief Class for computing BRIEF descriptors described in @cite calon2010 .
@note
- A complete BRIEF extractor sample can be found at
opencv_source_code/samples/cpp/brief_match_test.cpp
@param bytes legth of the descriptor in bytes, valid values are: 16, 32 (default) or 64 .
@param use_orientation sample patterns using keypoints orientation, disabled by default.
*/
class CV_EXPORTS_W BriefDescriptorExtractor : public Feature2D
{
public:
CV_WRAP static Ptr<BriefDescriptorExtractor> create( int bytes = 32 );
static Ptr<BriefDescriptorExtractor> create( int bytes = 32, bool use_orientation = false );
};
/** @brief Class implementing the locally uniform comparison image descriptor, described in @cite LUCID
@ -172,6 +171,92 @@ public:
static Ptr<LATCH> create(int bytes = 32, bool rotationInvariance = true, int half_ssd_size=3);
};
/** @brief Class implementing DAISY descriptor, described in @cite Tola10
@param radius radius of the descriptor at the initial scale
@param q_radius amount of radial range division quantity
@param q_theta amount of angular range division quantity
@param q_hist amount of gradient orientations range division quantity
@param norm choose descriptors normalization type, where
DAISY::NRM_NONE will not do any normalization (default),
DAISY::NRM_PARTIAL mean that histograms are normalized independently for L2 norm equal to 1.0,
DAISY::NRM_FULL mean that descriptors are normalized for L2 norm equal to 1.0,
DAISY::NRM_SIFT mean that descriptors are normalized for L2 norm equal to 1.0 but no individual one is bigger than 0.154 as in SIFT
@param H optional 3x3 homography matrix used to warp the grid of daisy but sampling keypoints remains unwarped on image
@param interpolation switch to disable interpolation for speed improvement at minor quality loss
@param use_orientation sample patterns using keypoints orientation, disabled by default.
*/
class CV_EXPORTS DAISY : public DescriptorExtractor
{
public:
enum
{
NRM_NONE = 100, NRM_PARTIAL = 101, NRM_FULL = 102, NRM_SIFT = 103,
};
static Ptr<DAISY> create( float radius = 15, int q_radius = 3, int q_theta = 8,
int q_hist = 8, int norm = DAISY::NRM_NONE, InputArray H = noArray(),
bool interpolation = true, bool use_orientation = false );
/** @overload
* @param image image to extract descriptors
* @param keypoints of interest within image
* @param descriptors resulted descriptors array
*/
virtual void compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) = 0;
virtual void compute( InputArrayOfArrays images,
std::vector<std::vector<KeyPoint> >& keypoints,
OutputArrayOfArrays descriptors );
/** @overload
* @param image image to extract descriptors
* @param roi region of interest within image
* @param descriptors resulted descriptors array for roi image pixels
*/
virtual void compute( InputArray image, Rect roi, OutputArray descriptors ) = 0;
/**@overload
* @param image image to extract descriptors
* @param descriptors resulted descriptors array for all image pixels
*/
virtual void compute( InputArray image, OutputArray descriptors ) = 0;
/**
* @param y position y on image
* @param x position x on image
* @param orientation orientation on image (0->360)
* @param descriptor supplied array for descriptor storage
*/
virtual void GetDescriptor( double y, double x, int orientation, float* descriptor ) const = 0;
/**
* @param y position y on image
* @param x position x on image
* @param orientation orientation on image (0->360)
* @param descriptor supplied array for descriptor storage
* @param H homography matrix for warped grid
*/
virtual bool GetDescriptor( double y, double x, int orientation, float* descriptor, double* H ) const = 0;
/**
* @param y position y on image
* @param x position x on image
* @param orientation orientation on image (0->360)
* @param descriptor supplied array for descriptor storage
*/
virtual void GetUnnormalizedDescriptor( double y, double x, int orientation, float* descriptor ) const = 0;
/**
* @param y position y on image
* @param x position x on image
* @param orientation orientation on image (0->360)
* @param descriptor supplied array for descriptor storage
* @param H homography matrix for warped grid
*/
virtual bool GetUnnormalizedDescriptor( double y, double x, int orientation, float* descriptor , double *H ) const = 0;
};
//! @}

@ -0,0 +1,33 @@
#include "perf_precomp.hpp"
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
using namespace perf;
using std::tr1::make_tuple;
using std::tr1::get;
typedef perf::TestBaseWithParam<std::string> daisy;
#define DAISY_IMAGES \
"cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\
"stitching/a3.png"
PERF_TEST_P(daisy, extract, testing::Values(DAISY_IMAGES))
{
string filename = getDataPath(GetParam());
Mat frame = imread(filename, IMREAD_GRAYSCALE);
ASSERT_FALSE(frame.empty()) << "Unable to load source image " << filename;
Mat mask;
declare.in(frame).time(90);
Ptr<DAISY> descriptor = DAISY::create();
vector<KeyPoint> points;
vector<float> descriptors;
// compute all daisies in image
TEST_CYCLE() descriptor->compute(frame, descriptors);
SANITY_CHECK(descriptors, 1e-4);
}

@ -61,7 +61,7 @@ public:
enum { PATCH_SIZE = 48, KERNEL_SIZE = 9 };
// bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
BriefDescriptorExtractorImpl( int bytes = 32 );
BriefDescriptorExtractorImpl( int bytes = 32, bool use_orientation = false );
virtual void read( const FileNode& );
virtual void write( FileStorage& ) const;
@ -73,67 +73,103 @@ public:
virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors);
protected:
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray);
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray, bool use_orientation );
int bytes_;
bool use_orientation_;
PixelTestFn test_fn_;
};
Ptr<BriefDescriptorExtractor> BriefDescriptorExtractor::create( int bytes )
Ptr<BriefDescriptorExtractor> BriefDescriptorExtractor::create( int bytes, bool use_orientation )
{
return makePtr<BriefDescriptorExtractorImpl>(bytes);
return makePtr<BriefDescriptorExtractorImpl>(bytes, use_orientation );
}
inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x)
inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x, bool use_orientation, Matx21f R)
{
static const int HALF_KERNEL = BriefDescriptorExtractorImpl::KERNEL_SIZE / 2;
int img_y = (int)(pt.pt.y + 0.5) + y;
int img_x = (int)(pt.pt.x + 0.5) + x;
if ( use_orientation )
{
int rx = (int)(((float)x)*R(1,0) - ((float)y)*R(0,0));
int ry = (int)(((float)x)*R(0,0) + ((float)y)*R(1,0));
if (rx > 24) rx = 24; if (rx < -24) rx = -24;
if (ry > 24) ry = 24; if (ry < -24) ry = -24;
x = rx; y = ry;
}
const int img_y = (int)(pt.pt.y + 0.5) + y;
const int img_x = (int)(pt.pt.x + 0.5) + x;
return sum.at<int>(img_y + HALF_KERNEL + 1, img_x + HALF_KERNEL + 1)
- sum.at<int>(img_y + HALF_KERNEL + 1, img_x - HALF_KERNEL)
- sum.at<int>(img_y - HALF_KERNEL, img_x + HALF_KERNEL + 1)
+ sum.at<int>(img_y - HALF_KERNEL, img_x - HALF_KERNEL);
}
static void pixelTests16(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests16(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation )
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI/180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_16.i"
}
}
static void pixelTests32(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests32(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation)
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI / 180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_32.i"
}
}
static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation)
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI/180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_64.i"
}
}
BriefDescriptorExtractorImpl::BriefDescriptorExtractorImpl(int bytes) :
BriefDescriptorExtractorImpl::BriefDescriptorExtractorImpl(int bytes, bool use_orientation) :
bytes_(bytes), test_fn_(NULL)
{
use_orientation_ = use_orientation;
switch (bytes)
{
case 16:
@ -212,7 +248,7 @@ void BriefDescriptorExtractorImpl::compute(InputArray image,
descriptors.create((int)keypoints.size(), bytes_, CV_8U);
descriptors.setTo(Scalar::all(0));
test_fn_(sum, keypoints, descriptors);
test_fn_(sum, keypoints, descriptors, use_orientation_);
}
}

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 16'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 32'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 64'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -1010,6 +1010,13 @@ TEST( Features2d_DescriptorExtractor_SURF, regression )
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_DAISY, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-daisy", 0.05f,
DAISY::create() );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_FREAK, regression )
{
// TODO adjust the parameters below

@ -660,6 +660,41 @@ TEST(Features2d_RotationInvariance_Descriptor_LATCH, regression)
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_DAISY, regression)
{
DescriptorRotationInvarianceTest test(BRISK::create(),
DAISY::create(15, 3, 8, 8, DAISY::NRM_NONE, noArray(), true, true),
NORM_L1,
0.79f);
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_64, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(64,true),
NORM_L1,
0.98f);
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_32, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(32,true),
NORM_L1,
0.97f);
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_16, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(16,true),
NORM_L1,
0.85f);
test.safe_run();
}
/*
* Detector's scale invariance check
@ -718,3 +753,12 @@ TEST(Features2d_RotationInvariance2_Detector_SURF, regression)
ASSERT_LT( fabs(keypoints[1].response - keypoints[3].response), 1e-6);
ASSERT_LT( fabs(keypoints[1].response - keypoints[4].response), 1e-6);
}
TEST(Features2d_ScaleInvariance_Descriptor_DAISY, regression)
{
DescriptorScaleInvarianceTest test(BRISK::create(),
DAISY::create(15, 3, 8, 8, DAISY::NRM_NONE, noArray(), true, true),
NORM_L1,
0.075f);
test.safe_run();
}

@ -1,5 +1,5 @@
set(the_description "Extended image processing module. It includes edge-aware filters and etc.")
set(OPENCV_MODULE_IS_PART_OF_WORLD OFF)
ocv_define_module(ximgproc opencv_imgproc opencv_core opencv_highgui WRAP python)
ocv_define_module(ximgproc opencv_imgproc opencv_core opencv_highgui opencv_calib3d WRAP python)
target_link_libraries(opencv_ximgproc)

@ -0,0 +1,92 @@
/*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
*
* License Agreement
* For Open Source Computer Vision Library
* (3 - clause BSD License)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met :
*
* *Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution.
*
* * Neither the names of the copyright holders nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided by the copyright holders and contributors "as is" and
* any express or implied warranties, including, but not limited to, the implied
* warranties of merchantability and fitness for a particular purpose are disclaimed.
* In no event shall copyright holders or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* (including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused
* and on any theory of liability, whether in contract, strict liability,
* or tort(including negligence or otherwise) arising in any way out of
* the use of this software, even if advised of the possibility of such damage.
*/
#ifndef __OPENCV_DISPARITYFILTER_HPP__
#define __OPENCV_DISPARITYFILTER_HPP__
#ifdef __cplusplus
#include <opencv2/core.hpp>
namespace cv {
namespace ximgproc {
class CV_EXPORTS_W DisparityFilter : public Algorithm
{
public:
CV_WRAP virtual void filter(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,Rect ROI) = 0;
};
/////////////////////////////////////////////////////////////////////////////////////////////////
class CV_EXPORTS_W DisparityDTFilter : public DisparityFilter
{
public:
CV_WRAP virtual double getSigmaSpatial() = 0;
CV_WRAP virtual void setSigmaSpatial(double _sigmaSpatial) = 0;
CV_WRAP virtual double getSigmaColor() = 0;
CV_WRAP virtual void setSigmaColor(double _sigmaColor) = 0;
};
CV_EXPORTS_W
Ptr<DisparityDTFilter> createDisparityDTFilter();
class CV_EXPORTS_W DisparityGuidedFilter : public DisparityFilter
{
public:
CV_WRAP virtual double getEps() = 0;
CV_WRAP virtual void setEps(double _eps) = 0;
CV_WRAP virtual int getRadius() = 0;
CV_WRAP virtual void setRadius(int _radius) = 0;
};
CV_EXPORTS_W
Ptr<DisparityGuidedFilter> createDisparityGuidedFilter();
class CV_EXPORTS_W DisparityWLSFilter : public DisparityFilter
{
CV_WRAP virtual double getLambda() = 0;
CV_WRAP virtual void setLambda(double _lambda) = 0;
CV_WRAP virtual double getSigmaColor() = 0;
CV_WRAP virtual void setSigmaColor(double _sigma_color) = 0;
};
CV_EXPORTS_W
Ptr<DisparityWLSFilter> createDisparityWLSFilter();
}
}
#endif
#endif

@ -318,6 +318,17 @@ void jointBilateralFilter(InputArray joint, InputArray src, OutputArray dst, int
//! @}
class CV_EXPORTS_W WeightedLeastSquaresFilter : public Algorithm
{
public:
CV_WRAP virtual void filter(InputArray src, OutputArray dst) = 0;
virtual ~WeightedLeastSquaresFilter();
};
CV_EXPORTS_W Ptr<WeightedLeastSquaresFilter> createWeightedLeastSquaresFilter(InputArray guide, double lambda, double sigma_color, int num_iter=3);
CV_EXPORTS_W void weightedLeastSquaresFilter(InputArray guide, InputArray src, OutputArray dst, double lambda, double sigma_color, int num_iter=3);
}
}
#endif

@ -0,0 +1,258 @@
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/ximgproc/disparity_filter.hpp"
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#if defined(_WIN32)
#include <direct.h>
#else
#include <sys/stat.h>
#endif
using namespace cv;
using namespace cv::ximgproc;
using namespace std;
#define UNKNOWN_DISPARITY 16320
static void print_help()
{
printf("\nDemo for disparity filtering, evaluating speed and performance of different filters\n");
printf("\nUsage: disparity_filtering.exe <path_to_dataset_folder> <path_to_results_folder>\n");
}
struct dataset_entry
{
string name;
string dataset_folder;
string left_file,right_file,GT_file;
dataset_entry(string _dataset_folder): dataset_folder(_dataset_folder){}
void readEntry(Mat& dst_left,Mat& dst_right,Mat& dst_GT)
{
dst_left = imread(dataset_folder+"/"+left_file, IMREAD_COLOR);
dst_right = imread(dataset_folder+"/"+right_file, IMREAD_COLOR);
Mat raw_disp = imread(dataset_folder+"/"+GT_file, IMREAD_COLOR);
dst_GT = Mat(raw_disp.rows,raw_disp.cols,CV_16S);
for(int i=0;i<raw_disp.rows;i++)
for(int j=0;j<raw_disp.cols;j++)
{
Vec3b bgrPixel = raw_disp.at<Vec3b>(i, j);
dst_GT.at<short>(i,j) = 64*bgrPixel.val[2]+bgrPixel.val[1]/4; //16-multiplied disparity
}
}
};
struct config
{
Ptr<StereoMatcher> matcher_instance;
Ptr<DisparityFilter> filter_instance;
config(Ptr<StereoMatcher> _matcher_instance,Ptr<DisparityFilter> _filter_instance)
{
matcher_instance = _matcher_instance;
filter_instance = _filter_instance;
}
config() {}
};
void operator>>(const FileNode& node,dataset_entry& entry);
double computeMSE(Mat& GT, Mat& src, Rect ROI);
double computeBadPixelPercent(Mat& GT, Mat& src, Rect ROI, int thresh=24/*1.5 pixels*/);
void getDisparityVis(Mat& disparity_map,Mat& dst);
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance);
void setConfigsForTesting(map<string,config>& cfgs);
void CreateDir(string path);
int main(int argc, char** argv)
{
if(argc < 3)
{
print_help();
return 0;
}
string dataset_folder(argv[1]);
string res_folder(argv[2]);
map<string,config> configs_for_testing;
setConfigsForTesting(configs_for_testing);
CreateDir(res_folder);
for (map<string,config>::iterator cfg = configs_for_testing.begin(); cfg != configs_for_testing.end(); cfg++)
{
string vis_folder = res_folder+"/vis_"+cfg->first;
CreateDir(vis_folder);
string cfg_file_name = res_folder+"/"+cfg->first+"_res.csv";
FILE* cur_cfg_res_file = fopen(cfg_file_name.c_str(),"w");
fprintf(cur_cfg_res_file,"Name,MSE,MSE after postfiltering,Percent bad,Percent bad after postfiltering,Matcher Execution Time(s),Filter Execution Time(s)\n");
printf("Processing configuration: %s\n",cfg->first.c_str());
FileStorage fs(dataset_folder + "/_dataset.xml", FileStorage::READ);
FileNode n = fs["data_set"];
double MSE_pre,percent_pre,MSE_post,percent_post,matching_time,filtering_time;
double average_MSE_pre=0,average_percent_pre=0,average_MSE_post=0,
average_percent_post=0,average_matching_time=0,average_filtering_time=0;
int cnt = 0;
for (FileNodeIterator it = n.begin(); it != n.end(); it++)
{
dataset_entry entry(dataset_folder);
(*it)>>entry;
printf("%s ",entry.name.c_str());
Mat left,right,GT;
entry.readEntry(left,right,GT);
Mat raw_disp;
Mat left_gray; cvtColor(left, left_gray, COLOR_BGR2GRAY );
Mat right_gray; cvtColor(right, right_gray, COLOR_BGR2GRAY );
matching_time = (double)getTickCount();
cfg->second.matcher_instance->compute(left_gray,right_gray,raw_disp);
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
Rect ROI = computeROI(left.size(),cfg->second.matcher_instance);
Mat filtered_disp;
filtering_time = (double)getTickCount();
cfg->second.filter_instance->filter(raw_disp,left,filtered_disp,ROI);
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
MSE_pre = computeMSE(GT,raw_disp,ROI);
percent_pre = computeBadPixelPercent(GT,raw_disp,ROI);
MSE_post = computeMSE(GT,filtered_disp,ROI);
percent_post = computeBadPixelPercent(GT,filtered_disp,ROI);
fprintf(cur_cfg_res_file,"%s,%.1f,%.1f,%.1f,%.1f,%.3f,%.3f\n",entry.name.c_str(),MSE_pre,MSE_post,
percent_pre,percent_post,matching_time,filtering_time);
average_matching_time+=matching_time; average_filtering_time+=filtering_time;
average_MSE_pre+=MSE_pre; average_percent_pre+=percent_pre;
average_MSE_post+=MSE_post; average_percent_post+=percent_post;
cnt++;
// dump visualizations:
imwrite(vis_folder + "/" + entry.name + "_left.png",left);
Mat GT_vis,raw_disp_vis,filtered_disp_vis;
getDisparityVis(GT,GT_vis);
getDisparityVis(raw_disp,raw_disp_vis);
getDisparityVis(filtered_disp,filtered_disp_vis);
imwrite(vis_folder + "/" + entry.name + "_disparity_GT.png",GT_vis);
imwrite(vis_folder + "/" + entry.name + "_disparity_raw.png",raw_disp_vis);
imwrite(vis_folder + "/" + entry.name + "_disparity_filtered.png",filtered_disp_vis);
printf("- Done\n");
}
fprintf(cur_cfg_res_file,"%s,%.1f,%.1f,%.1f,%.1f,%.3f,%.3f\n","average",average_MSE_pre/cnt,
average_MSE_post/cnt,average_percent_pre/cnt,average_percent_post/cnt,
average_matching_time/cnt,average_filtering_time/cnt);
fclose(cur_cfg_res_file);
}
return 0;
}
void operator>>(const FileNode& node,dataset_entry& entry)
{
node["name"] >> entry.name;
node["left_file"] >> entry.left_file;
node["right_file"] >> entry.right_file;
node["GT_file"] >> entry.GT_file;
}
double computeMSE(Mat& GT, Mat& src, Rect ROI)
{
double res = 0;
Mat GT_ROI(GT,ROI);
Mat src_ROI(src,ROI);
int cnt=0;
for(int i=0;i<src_ROI.rows;i++)
for(int j=0;j<src_ROI.cols;j++)
{
if(GT_ROI.at<short>(i,j)!=UNKNOWN_DISPARITY)
{
res += (GT_ROI.at<short>(i,j) - src_ROI.at<short>(i,j))*(GT_ROI.at<short>(i,j) - src_ROI.at<short>(i,j));
cnt++;
}
}
res /= cnt*256;
return res;
}
double computeBadPixelPercent(Mat& GT, Mat& src, Rect ROI, int thresh)
{
int bad_pixel_num = 0;
Mat GT_ROI(GT,ROI);
Mat src_ROI(src,ROI);
int cnt=0;
for(int i=0;i<src_ROI.rows;i++)
for(int j=0;j<src_ROI.cols;j++)
{
if(GT_ROI.at<short>(i,j)!=UNKNOWN_DISPARITY)
{
if( abs(GT_ROI.at<short>(i,j) - src_ROI.at<short>(i,j))>=thresh )
bad_pixel_num++;
cnt++;
}
}
return (100.0*bad_pixel_num)/cnt;
}
void getDisparityVis(Mat& disparity_map,Mat& dst)
{
dst = Mat(disparity_map.rows,disparity_map.cols,CV_8UC3);
for(int i=0;i<dst.rows;i++)
for(int j=0;j<dst.cols;j++)
{
if(disparity_map.at<short>(i,j)==UNKNOWN_DISPARITY)
dst.at<Vec3b>(i,j) = Vec3b(0,0,0);
else
dst.at<Vec3b>(i,j) = Vec3b(saturate_cast<unsigned char>(disparity_map.at<short>(i,j)/8),
saturate_cast<unsigned char>(disparity_map.at<short>(i,j)/8),
saturate_cast<unsigned char>(disparity_map.at<short>(i,j)/8));
}
}
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance)
{
int min_disparity = matcher_instance->getMinDisparity();
int num_disparities = matcher_instance->getNumDisparities();
int block_size = matcher_instance->getBlockSize();
int bs2 = block_size/2;
int minD = min_disparity, maxD = min_disparity + num_disparities - 1;
int xmin = maxD + bs2;
int xmax = src_sz.width - minD - bs2;
int ymin = bs2;
int ymax = src_sz.height - bs2;
Rect r(xmin, ymin, xmax - xmin, ymax - ymin);
return r;
}
void setConfigsForTesting(map<string,config>& cfgs)
{
Ptr<StereoBM> stereobm_matcher = StereoBM::create(128,21);
stereobm_matcher->setTextureThreshold(0);
stereobm_matcher->setUniquenessRatio(0);
Ptr<DisparityFilter> wls_filter = createDisparityWLSFilter();
Ptr<DisparityFilter> dt_filter = createDisparityDTFilter();
Ptr<DisparityFilter> guided_filter = createDisparityGuidedFilter();
cfgs["stereobm_wls"] = config(stereobm_matcher,wls_filter);
cfgs["stereobm_dtf"] = config(stereobm_matcher,dt_filter);
cfgs["stereobm_gf"] = config(stereobm_matcher,guided_filter);
}
void CreateDir(string path)
{
#if defined(_WIN32)
_mkdir(path.c_str());
#else
mkdir(path.c_str(), 0777);
#endif
}

@ -0,0 +1,29 @@
# USAGE - How to run this code ?
# python find_shapes.py --image shapes.png
#python findredlinedpolygonfromgooglemaps.py --image stanford.png
import numpy as np
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image file")
args = vars(ap.parse_args())
# load the image
image = cv2.imread(args["image"])
lower = np.array([20,0,155])
upper = np.array([255,120,250])
shapeMask = cv2.inRange(image, lower, upper)
# find the contours in the mask
(cnts, _) = cv2.findContours(shapeMask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow("Mask", shapeMask)
# loop over the contours
for c in cnts:
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.imshow("Image", image)
cv2.waitKey(0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 KiB

@ -0,0 +1,185 @@
/*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
*
* License Agreement
* For Open Source Computer Vision Library
* (3 - clause BSD License)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met :
*
* *Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution.
*
* * Neither the names of the copyright holders nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided by the copyright holders and contributors "as is" and
* any express or implied warranties, including, but not limited to, the implied
* warranties of merchantability and fitness for a particular purpose are disclaimed.
* In no event shall copyright holders or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* (including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused
* and on any theory of liability, whether in contract, strict liability,
* or tort(including negligence or otherwise) arising in any way out of
* the use of this software, even if advised of the possibility of such damage.
*/
#include "precomp.hpp"
#include "opencv2/ximgproc/disparity_filter.hpp"
#include <math.h>
namespace cv {
namespace ximgproc {
void setROI(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,
Mat& disp,Mat& src,Mat& dst,Rect ROI);
class DisparityDTFilterImpl : public DisparityDTFilter
{
protected:
double sigmaSpatial,sigmaColor;
void init(double _sigmaSpatial, double _sigmaColor)
{
sigmaColor = _sigmaColor;
sigmaSpatial = _sigmaSpatial;
}
public:
double getSigmaSpatial() {return sigmaSpatial;}
void setSigmaSpatial(double _sigmaSpatial) {sigmaSpatial = _sigmaSpatial;}
double getSigmaColor() {return sigmaColor;}
void setSigmaColor(double _sigmaColor) {sigmaColor = _sigmaColor;}
static Ptr<DisparityDTFilterImpl> create()
{
DisparityDTFilterImpl *dtf = new DisparityDTFilterImpl();
dtf->init(25.0,60.0);
return Ptr<DisparityDTFilterImpl>(dtf);
}
void filter(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,Rect ROI)
{
Mat disp,src,dst;
setROI(disparity_map,left_view,filtered_disparity_map,disp,src,dst,ROI);
Mat disp_32F,dst_32F;
disp.convertTo(disp_32F,CV_32F);
dtFilter(src,disp_32F,dst_32F,sigmaSpatial,sigmaColor);
dst_32F.convertTo(dst,CV_16S);
}
};
CV_EXPORTS_W
Ptr<DisparityDTFilter> createDisparityDTFilter()
{
return Ptr<DisparityDTFilter>(DisparityDTFilterImpl::create());
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
class DisparityGuidedFilterImpl : public DisparityGuidedFilter
{
protected:
int radius;
double eps;
void init(int _radius, double _eps)
{
radius = _radius;
eps = _eps;
}
public:
double getEps() {return eps;}
void setEps(double _eps) {eps = _eps;}
int getRadius() {return radius;}
void setRadius(int _radius) {radius = _radius;}
static Ptr<DisparityGuidedFilterImpl> create()
{
DisparityGuidedFilterImpl *gf = new DisparityGuidedFilterImpl();
gf->init(20,100.0);
return Ptr<DisparityGuidedFilterImpl>(gf);
}
void filter(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,Rect ROI)
{
Mat disp,src,dst;
setROI(disparity_map,left_view,filtered_disparity_map,disp,src,dst,ROI);
Mat disp_32F,dst_32F;
disp.convertTo(disp_32F,CV_32F);
guidedFilter(src,disp_32F,dst_32F,radius,eps);
dst_32F.convertTo(dst,CV_16S);
}
};
CV_EXPORTS_W
Ptr<DisparityGuidedFilter> createDisparityGuidedFilter()
{
return Ptr<DisparityGuidedFilter>(DisparityGuidedFilterImpl::create());
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
class DisparityWLSFilterImpl : public DisparityWLSFilter
{
protected:
double lambda,sigma_color;
void init(double _lambda, double _sigma_color)
{
lambda = _lambda;
sigma_color = _sigma_color;
}
public:
double getLambda() {return lambda;}
void setLambda(double _lambda) {lambda = _lambda;}
double getSigmaColor() {return sigma_color;}
void setSigmaColor(double _sigma_color) {sigma_color = _sigma_color;}
static Ptr<DisparityWLSFilterImpl> create()
{
DisparityWLSFilterImpl *wls = new DisparityWLSFilterImpl();
wls->init(500.0,2.0);
return Ptr<DisparityWLSFilterImpl>(wls);
}
void filter(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,Rect ROI)
{
Mat disp,src,dst;
setROI(disparity_map,left_view,filtered_disparity_map,disp,src,dst,ROI);
weightedLeastSquaresFilter(src,disp,dst,lambda,sigma_color);
}
};
CV_EXPORTS_W
Ptr<DisparityWLSFilter> createDisparityWLSFilter()
{
return Ptr<DisparityWLSFilter>(DisparityWLSFilterImpl::create());
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
void setROI(InputArray disparity_map, InputArray left_view, OutputArray filtered_disparity_map,
Mat& disp,Mat& src,Mat& dst,Rect ROI)
{
Mat disp_full_size = disparity_map.getMat();
Mat src_full_size = left_view.getMat();
CV_Assert( (disp_full_size.depth() == CV_16S) && (disp_full_size.channels() == 1) );
CV_Assert( (src_full_size.depth() == CV_8U) && (src_full_size.channels() <= 4) );
disp = Mat(disp_full_size,ROI);
src = Mat(src_full_size ,ROI);
filtered_disparity_map.create(disp_full_size.size(), disp_full_size.type());
Mat& dst_full_size = filtered_disparity_map.getMatRef();
dst = Mat(dst_full_size,ROI);
}
}
}

@ -0,0 +1,284 @@
/*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
*
* License Agreement
* For Open Source Computer Vision Library
* (3 - clause BSD License)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met :
*
* *Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution.
*
* * Neither the names of the copyright holders nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided by the copyright holders and contributors "as is" and
* any express or implied warranties, including, but not limited to, the implied
* warranties of merchantability and fitness for a particular purpose are disclaimed.
* In no event shall copyright holders or contributors be liable for any direct,
* indirect, incidental, special, exemplary, or consequential damages
* (including, but not limited to, procurement of substitute goods or services;
* loss of use, data, or profits; or business interruption) however caused
* and on any theory of liability, whether in contract, strict liability,
* or tort(including negligence or otherwise) arising in any way out of
* the use of this software, even if advised of the possibility of such damage.
*/
#include "precomp.hpp"
namespace cv {
namespace ximgproc {
class WeightedLeastSquaresFilterImpl : public WeightedLeastSquaresFilter
{
public:
static Ptr<WeightedLeastSquaresFilterImpl> create(InputArray guide, double lambda, double sigma_color, int num_iter);
void filter(InputArray src, OutputArray dst);
~WeightedLeastSquaresFilterImpl();
protected:
int w,h;
double sigmaColor,lambda;
int num_iter;
double *weights_LUT;
double *Ahor, *Bhor, *Chor,
*Avert, *Bvert, *Cvert;
double *interD,*interE,*cur_res;
void init(InputArray guide,double _lambda,double _sigmaColor,int _num_iter);
void buildCoefMatrices(Mat& guide);
void horizontalPass(double* cur);
void verticalPass(double* cur);
};
void WeightedLeastSquaresFilterImpl::init(InputArray guide,double _lambda,double _sigmaColor,int _num_iter)
{
//currently support only 3 channel 8bit images as guides
CV_Assert( !guide.empty() && _lambda >= 0 && _sigmaColor >= 0 && _num_iter >=1 );
CV_Assert( guide.depth() == CV_8U && guide.channels() == 3 );
sigmaColor = _sigmaColor;
lambda = _lambda;
num_iter = _num_iter;
int num_levels = 3*256*256;
weights_LUT = new double[num_levels];
for(int i=0;i<num_levels;i++)
weights_LUT[i] = exp(-sqrt((double)i)/sigmaColor);
w = guide.cols();
h = guide.rows();
int sz = w*h;
Ahor = new double[sz];Bhor = new double[sz];Chor = new double[sz];
Avert = new double[sz];Bvert = new double[sz];Cvert = new double[sz];
interD = new double[sz];interE = new double[sz];cur_res = new double[sz];
Mat guideMat = guide.getMat();
buildCoefMatrices(guideMat);
}
Ptr<WeightedLeastSquaresFilterImpl> WeightedLeastSquaresFilterImpl::create(InputArray guide, double lambda, double sigma_color, int num_iter)
{
WeightedLeastSquaresFilterImpl *wls = new WeightedLeastSquaresFilterImpl();
wls->init(guide,lambda,sigma_color,num_iter);
return Ptr<WeightedLeastSquaresFilterImpl>(wls);
}
WeightedLeastSquaresFilter::~WeightedLeastSquaresFilter(){}
WeightedLeastSquaresFilterImpl::~WeightedLeastSquaresFilterImpl()
{
delete[] weights_LUT;
delete[] Ahor; delete[] Bhor; delete[] Chor;
delete[] Avert; delete[] Bvert; delete[] Cvert;
delete[] interD;delete[] interE;delete[] cur_res;
}
void WeightedLeastSquaresFilterImpl::buildCoefMatrices(Mat& guide)
{
double hor_weight;
const unsigned char *row,*row_prev,*row_next;
for(int i=0;i<h;i++)
{
//compute horizontal coefs:
row = guide.ptr(i);
Ahor[i*w] = 0;
hor_weight = weights_LUT[ (row[0]-row[3])*(row[0]-row[3])+
(row[1]-row[4])*(row[1]-row[4])+
(row[2]-row[5])*(row[2]-row[5]) ];
Chor[i*w] = -lambda*hor_weight;
Bhor[i*w] = 1 - Ahor[i*w] - Chor[i*w];
row+=3;
for(int j=1;j<w-1;j++)
{
Ahor[i*w+j] = -lambda*hor_weight;
hor_weight = weights_LUT[ (row[0]-row[3])*(row[0]-row[3])+
(row[1]-row[4])*(row[1]-row[4])+
(row[2]-row[5])*(row[2]-row[5]) ];
Chor[i*w+j] = -lambda*hor_weight;
Bhor[i*w+j] = 1 - Ahor[i*w+j] - Chor[i*w+j];
row+=3;
}
Ahor[i*w+w-1] = -lambda*hor_weight;
Chor[i*w+w-1] = 0;
Bhor[i*w+w-1] = 1 - Ahor[i*w+w-1] - Chor[i*w+w-1];
//compute vertical coefs:
row = guide.ptr(i);
if(i==0)
{
row_next = guide.ptr(i+1);
for(int j=0;j<w;j++)
{
Avert[i*w+j] = 0;
Cvert[i*w+j] = -lambda*weights_LUT[ (row[0]-row_next[0])*(row[0]-row_next[0])+
(row[1]-row_next[1])*(row[1]-row_next[1])+
(row[2]-row_next[2])*(row[2]-row_next[2]) ];
Bvert[i*w+j] = 1 - Avert[i*w+j] - Cvert[i*w+j];
row+=3;
row_next+=3;
}
}
else if(i==h-1)
{
row_prev = guide.ptr(i-1);
for(int j=0;j<w;j++)
{
Avert[i*w+j] = -lambda*weights_LUT[ (row[0]-row_prev[0])*(row[0]-row_prev[0])+
(row[1]-row_prev[1])*(row[1]-row_prev[1])+
(row[2]-row_prev[2])*(row[2]-row_prev[2]) ];
Cvert[i*w+j] = 0;
Bvert[i*w+j] = 1 - Avert[i*w+j] - Cvert[i*w+j];
row+=3;
row_prev+=3;
}
}
else
{
row_prev = guide.ptr(i-1);
row_next = guide.ptr(i+1);
for(int j=0;j<w;j++)
{
Avert[i*w+j] = -lambda*weights_LUT[ (row[0]-row_prev[0])*(row[0]-row_prev[0])+
(row[1]-row_prev[1])*(row[1]-row_prev[1])+
(row[2]-row_prev[2])*(row[2]-row_prev[2]) ];
Cvert[i*w+j] = -lambda*weights_LUT[ (row[0]-row_next[0])*(row[0]-row_next[0])+
(row[1]-row_next[1])*(row[1]-row_next[1])+
(row[2]-row_next[2])*(row[2]-row_next[2]) ];
Bvert[i*w+j] = 1 - Avert[i*w+j] - Cvert[i*w+j];
row+=3;
row_prev+=3;
row_next+=3;
}
}
}
}
void WeightedLeastSquaresFilterImpl::filter(InputArray src, OutputArray dst)
{
//temporarily support only one-channel CV_16S src type (for disparity map filtering)
CV_Assert(!src.empty() && (src.depth() == CV_16S) && src.channels()==1);
if (src.rows() != h || src.cols() != w)
{
CV_Error(Error::StsBadSize, "Size of filtering image must be equal to size of guide image");
return;
}
Mat srcMat = src.getMat();
Mat& dstMat = dst.getMatRef();
short* row;
for(int i=0;i<h;i++)
{
row = (short*)srcMat.ptr(i);
for(int j=0;j<w;j++)
{
cur_res[i*w+j] = (double)(*row);
row++;
}
}
for(int n=0;n<num_iter;n++)
{
horizontalPass(cur_res);
verticalPass(cur_res);
}
for(int i=0;i<h;i++)
{
row = (short*)dstMat.ptr(i);
for(int j=0;j<w;j++)
{
*row = saturate_cast<short>(cur_res[i*w+j]);
row++;
}
}
}
void WeightedLeastSquaresFilterImpl::horizontalPass(double* cur)
{
double denom;
for(int i=0;i<h;i++)
{
//forward pass:
interD[i*w] = Chor[i*w]/Bhor[i*w];
interE[i*w] = cur[i*w] /Bhor[i*w];
for(int j=1;j<w;j++)
{
denom = Bhor[i*w+j]-interD[i*w+j-1]*Ahor[i*w+j];
interD[i*w+j] = Chor[i*w+j]/denom;
interE[i*w+j] = (cur[i*w+j]-interE[i*w+j-1]*Ahor[i*w+j])/denom;
}
//backward pass:
cur[i*w+w-1] = interE[i*w+w-1];
for(int j=w-2;j>=0;j--)
cur[i*w+j] = interE[i*w+j]-interD[i*w+j]*cur[i*w+j+1];
}
}
void WeightedLeastSquaresFilterImpl::verticalPass(double* cur)
{
double denom;
//forward pass:
for(int j=0;j<w;j++)
{
interD[j] = Cvert[j]/Bvert[j];
interE[j] = cur[j]/Bvert[j];
}
for(int i=1;i<h;i++)
{
for(int j=0;j<w;j++)
{
denom = Bvert[i*w+j]-interD[(i-1)*w+j]*Avert[i*w+j];
interD[i*w+j] = Cvert[i*w+j]/denom;
interE[i*w+j] = (cur[i*w+j]-interE[(i-1)*w+j]*Avert[i*w+j])/denom;
}
}
//backward pass:
for(int j=0;j<w;j++)
cur[(h-1)*w+j] = interE[(h-1)*w+j];
for(int i=h-2;i>=0;i--)
for(int j=w-1;j>=0;j--)
cur[i*w+j] = interE[i*w+j]-interD[i*w+j]*cur[(i+1)*w+j];
}
////////////////////////////////////////////////////////////////////////////////////////////////
CV_EXPORTS_W
Ptr<WeightedLeastSquaresFilter> createWeightedLeastSquaresFilter(InputArray guide, double lambda, double sigma_color, int num_iter)
{
return Ptr<WeightedLeastSquaresFilter>(WeightedLeastSquaresFilterImpl::create(guide, lambda, sigma_color, num_iter));
}
CV_EXPORTS_W
void weightedLeastSquaresFilter(InputArray guide, InputArray src, OutputArray dst, double lambda, double sigma_color, int num_iter)
{
Ptr<WeightedLeastSquaresFilter> wls = createWeightedLeastSquaresFilter(guide, lambda, sigma_color, num_iter);
wls->filter(src, dst);
}
}
}

@ -307,6 +307,8 @@ void computeChannels(InputArray image, vector<Mat>& channels)
for (int col = 0; col < grad.cols; ++col) {
//float angle = atan2(row_der(row, col), col_der(row, col)) * to_deg;
float angle = angles(row, col);
if (angle > 180)
angle -= 180;
if (angle < 0)
angle += 180;
int ind = (int)(angle / 30);

Loading…
Cancel
Save