Non-uniformity correction of infrared images by midway equalization
MIRE.cpp
Go to the documentation of this file.
00001 /*
00002 * Copyright 2012 IPOL Image Processing On Line http://www.ipol.im/
00003 *
00004 * This program is free software: you can redistribute it and/or modify
00005 * it under the terms of the GNU General Public License as published by
00006 * the Free Software Foundation, either version 3 of the License, or
00007 * (at your option) any later version.
00008 *
00009 * This program is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 * GNU General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU General Public License
00015 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00024 #ifdef _OPENMP
00025 #include <omp.h>
00026 #endif
00027 
00028 #include <stdio.h>
00029 #include <list>
00030 #include <vector>
00031 #include <algorithm>
00032 #include <cmath>
00033 #include "MIRE.h"
00034 
00035 #define ABS(x)    (((x) > 0) ? (x) : (-(x)))
00036 #ifndef M_PI
00037 using namespace std;
00041 #define M_PI 3.14159265358979323846
00042 #endif
00043 
00044 
00045 
00061 void MIRE_automatic(float *IMAGE, int w1, int h1,int SIGMA_MIN, int SIGMA_MAX,
00062                     float DELTA)
00063 {
00068     float sigma_current;
00069     float sigma_best;
00070     float TV_current;
00071     float* Imtemp = new float[h1*w1];
00072     float TV_min;
00073 
00077 
00078     sigma_best=SIGMA_MIN;
00079     for (int i=0;i<w1*h1;i++)
00080         Imtemp[i]=IMAGE[i];
00081 
00082 
00083     if (SIGMA_MIN==0)
00084     {
00085         TV_current=TV_column_norm(Imtemp,w1,h1,4*SIGMA_MAX);
00086     }
00087     else
00088     {
00089         TV_current=TV_column_norm(MIRE(Imtemp,SIGMA_MIN,w1,h1),w1,h1,
00090                                   4*SIGMA_MAX);
00091     }
00092     TV_min=TV_current;
00093     sigma_current=SIGMA_MIN;
00094 
00095 
00096 
00100 
00101 
00102 
00103     int T=round(((SIGMA_MAX-SIGMA_MIN)/DELTA))+1;
00104 
00105 #pragma omp for
00106     for ( int i=0;i<T; i++)
00107     {
00108 
00109         for (int i=0;i<w1*h1;i++)
00110             Imtemp[i]=IMAGE[i];
00111 
00112         TV_current=TV_column_norm(MIRE(Imtemp,sigma_current,w1,h1),w1,h1,
00113                                   4*SIGMA_MAX);
00114 
00115         if (TV_current<TV_min)
00116         {
00117             sigma_best=sigma_current;
00118             TV_min=TV_current;
00119         }
00120         sigma_current=sigma_current+DELTA;
00121     }
00122     delete [] Imtemp;
00123 
00124 
00125 
00126 
00127 
00131     if (sigma_best!=0) MIRE(IMAGE,sigma_best,w1,h1);
00132     printf("SIGMA_BEST: %f\n", sigma_best);
00133 }
00134 
00135 
00136 
00137 
00138 
00139 
00150 float *MIRE(float *IMAGE,float sigma, int w1, int h1)
00151 {
00154 
00155     std::vector <std::vector<float> > v;
00156     std::vector <std::vector<float> > c_sorted;
00157     c_sorted=column_sorting(IMAGE,w1,h1);  //permits to sorts all columns.
00158     v=target_histogram(c_sorted,w1,h1,sigma);
00159 
00160     int N=round(4*sigma);
00161     for (int column=N; column<w1-N;column++)
00162     {
00163 // avoiding parts added by mirror-symetrization
00164 
00165 // v is the target histogram in the sense of a midway weighted histogram
00166         specify_column(IMAGE,w1,h1,column,v[column-N]);
00167 //Giving the column "column" the histogram v
00168 
00169     }
00170     return(IMAGE);
00171 
00172 }
00173 
00174 
00175 
00176 
00189 float TV_column_norm(float *IMAGE, int w1, int h1,float B)
00190 {
00195     float TV=0;
00196     for (int column=B;column<w1-B;column++)
00197     {
00198         for (int line=0;line<h1;line++)
00199         {
00200 
00201 
00202             TV=TV+ABS((IMAGE[line*w1+column+1])-IMAGE[line*w1+column]);
00203 
00204         }
00205     }
00206 
00207     return(TV);
00208 }
00209 
00210 
00211 
00219 float gaussian(int x,float sigma)
00220 {
00221 //return gaussian function with std-dev sigma evaluated at x
00222     return(1/(sigma*sqrt(2*M_PI))*exp(-(x*x)/(2*sigma*sigma)));
00223 }
00224 
00225 
00226 
00246 void specify_column(float *IMAGE, int w1, int h1,int column_current,
00247                     std::vector <float> target_values)
00248 {
00258 
00259 
00260 
00261 
00262 
00266 
00267     std::vector <float> column_sorted;
00268     for (int i=0;i<h1;i++)
00269     {
00270 //for all lines.
00271         column_sorted.push_back(IMAGE[i*w1+column_current]);
00272     }
00273     std::sort (column_sorted.begin(), column_sorted.end());
00274 
00275 
00276 
00280 
00281 
00282     for (int i=0;i<h1;i++)
00283     {
00284         float temp= IMAGE[i*w1+column_current] ; //IMAGE[i*w1+column_current]
00285         //is v_column(i) in the above description
00286         for (int j=0;j<h1;j++)
00287         {
00288             if (temp==column_sorted[j])
00289             {
00290                 IMAGE[i*w1+column_current]=target_values[j];
00291             }
00292         }
00293     }
00294 
00295 
00296 }
00297 
00298 
00316 std::vector <std::vector<float> >  target_histogram(std::vector
00317         <std::vector<float> > V_HISTOS,int w1,int h1, float sigma)
00318 {
00325 
00333 
00334 
00335 
00339 
00340 
00341     std::vector <std::vector<float> > FINAL;
00342 
00343 //Radius in pixels
00344     int N=round(4*sigma); // (depending on delta) could be non-integer.
00345 
00346 
00350 
00351 
00352     for (int CENTER=N; CENTER<w1-N;CENTER++)
00353     {
00354         std::vector <float> v;
00355         for (int vline=0;vline<h1;vline++)  //for each line of the "matrix"
00356         {
00357             float temp=0;
00358             for (int vcolumn=CENTER-N; vcolumn<CENTER+N+1;vcolumn++)
00359             {
00360                 temp=temp+gaussian((CENTER-vcolumn),sigma)
00361                      *(V_HISTOS[vcolumn][vline]);
00362             }
00363             v.push_back(temp);
00364         }
00365         FINAL.push_back(v);
00366     }
00367     return(FINAL);
00368 }
00369 
00370 
00371 
00372 
00373 
00374 
00385 std::vector <float> histo_column(float *IMAGE,int w1,int h1, int column)
00386 {
00388 
00389     std::vector <float> v;
00390     for (int line=0;line<h1;line++)
00391     {
00392         v.push_back(IMAGE[line*w1+column]);
00393 // adding the value for each line of column "column" in the vector
00394     }
00395     std::sort (v.begin(), v.end());
00396     return(v);
00397 }
00398 
00399 
00409 std::vector <std::vector<float> >  column_sorting(float *IMAGE,int w1,int h1)
00410 {
00411 
00412 
00413 
00414 //Radius in pixels
00415 //int N=round(4*sigma); // (depending on delta) could be non-integer.
00416 
00417     std::vector <std::vector<float> > V_HISTOS;
00418 // Vectors of vectors (matrix) such that
00419 //V_HISTOS[i] is the histogram of the column v (which is also a vector)
00420     for (int i=0;i <w1;i++)   //processing all columns in the radius
00421     {
00422         V_HISTOS.push_back(histo_column(IMAGE, w1, h1,  i));
00423 //step 2 is done in histo_column
00424     }
00425     return(V_HISTOS);
00426 }
00427 
00428 
00429 
00430 
00431 
 All Files Functions Defines