Non-uniformity correction of infrared images by midway equalization
|
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