00001
00002 #include "gevd_noise.h"
00003
00004
00005
00006 #include <vcl_cmath.h>
00007
00008 #include "gevd_pixel.h"
00009 #include "gevd_float_operators.h"
00010
00011 const int INVALID = -1;
00012 const int KRADIUS = 10;
00013
00014
00015 gevd_noise::gevd_noise(const float* data, const int n,
00016 const int number_of_bins)
00017 : hist(new float[number_of_bins]),
00018 nbin(number_of_bins)
00019 {
00020
00021 float range = 0;
00022 for (int i = 0; i < n; i++)
00023 range += data[i];
00024 range /= n;
00025 binsize = range/(nbin-1);
00026 #ifdef DEBUG
00027 vcl_cout << "Find mean of h(x) at: " << range << vcl_endl;
00028 #endif
00029
00030
00031 while (true) {
00032 for (int i = 0; i < nbin; i++)
00033 hist[i] = 0;
00034 for (int i = 0; i < n; i++) {
00035 float strength = data[i];
00036 if (strength < range)
00037 hist[int(strength/binsize)] += 1;
00038 }
00039 float peakh = 0; int peaki = INVALID;
00040 for (int i = 0; i < nbin; i++)
00041 if (hist[i] > peakh) {
00042 peakh = hist[i];
00043 peaki = i;
00044 }
00045 #ifdef DEBUG
00046 vcl_cout << "Find peak of h(x) at: " << peaki*binsize
00047 << " " << peakh << vcl_endl;
00048 #endif
00049 if (peaki < 10) {
00050 range /= 10.0, binsize /= 10.0;
00051 } else if (peaki >= nbin-5) {
00052 range *= 1.5, binsize *= 1.5;
00053 } else {
00054 range = peaki*binsize*2;
00055 binsize = range/(nbin-1);
00056 break;
00057 }
00058 }
00059
00060
00061 for (int i = 0; i < nbin; i++)
00062 hist[i] = 0;
00063 for (int i = 0; i < n; i++) {
00064 float strength = data[i];
00065 if (strength < range)
00066 hist[int(strength/binsize)] += 1;
00067 }
00068 gevd_float_operators::RunningSum(hist, hist, nbin, KRADIUS);
00069 #ifdef DEBUG
00070 for (int i = 0; i < nbin; i++)
00071 vcl_cout << hist[i] << ' ';
00072 vcl_cout << vcl_endl << vcl_endl;
00073 #endif
00074 }
00075
00076
00077
00078 gevd_noise::~gevd_noise()
00079 {
00080 delete [] hist;
00081 }
00082
00083
00084
00085
00086
00087
00088 float*
00089 gevd_noise::EdgelsInCenteredROI(const gevd_bufferxy& magnitude,
00090 const gevd_bufferxy& dirx, const gevd_bufferxy& diry,
00091 int& nedgel, const int
00092 #ifdef MINROI
00093 roiArea
00094 #endif
00095 )
00096 {
00097 nedgel = 0;
00098 #ifdef MINROI
00099 int area = magnitude.GetSizeX() * magnitude.GetSizeY();
00100 if (area < roiArea) {
00101 vcl_cerr << "Image is smaller than minimum ROI\n";
00102 return NULL;
00103 }
00104 float k = vcl_sqrt(float(roiArea) / area);
00105 #else
00106 float k = 1.0;
00107 #endif
00108 const int sx = int(k*magnitude.GetSizeX()), sy = int(k*magnitude.GetSizeY());
00109 float* edgels = new float [sx*sy];
00110 const int xmin = (magnitude.GetSizeX() - sx) / 2;
00111 const int xmax = xmin + sx;
00112 const int ymin = (magnitude.GetSizeY() - sy) / 2;
00113 const int ymax = ymin + sy;
00114 for (int j = ymin; j < ymax; j++)
00115 for (int i = xmin; i < xmax; i++) {
00116 float strength = floatPixel(magnitude, i, j);
00117 if (strength) {
00118 float x_s, s_x;
00119 float dx = floatPixel(dirx, i, j);
00120 float dy = floatPixel(diry, i, j);
00121 if (dy < 0) dx = -dx, dy = -dy;
00122 if (dx > 0) {
00123 if (dx > dy) {
00124 float r = dy / dx;
00125 x_s = (r*floatPixel(magnitude, i-1, j-1) +
00126 (1-r)*floatPixel(magnitude, i-1, j));
00127 s_x = (r*floatPixel(magnitude, i+1, j+1) +
00128 (1-r)*floatPixel(magnitude, i+1, j));
00129 } else {
00130 float r = dx / dy;
00131 x_s = (r*floatPixel(magnitude, i-1, j-1) +
00132 (1-r)*floatPixel(magnitude, i, j-1));
00133 s_x = (r*floatPixel(magnitude, i+1, j+1) +
00134 (1-r)*floatPixel(magnitude, i, j+1));
00135 }
00136 } else {
00137 dx = -dx;
00138 if (dy > dx) {
00139 float r = dx / dy;
00140 x_s = (r*floatPixel(magnitude, i-1, j+1) +
00141 (1-r)*floatPixel(magnitude, i, j+1));
00142 s_x = (r*floatPixel(magnitude, i+1, j-1) +
00143 (1-r)*floatPixel(magnitude, i, j-1));
00144 } else {
00145 float r = dy / dx;
00146 x_s = (r*floatPixel(magnitude, i+1, j-1) +
00147 (1-r)*floatPixel(magnitude, i+1, j));
00148 s_x = (r*floatPixel(magnitude, i-1, j+1) +
00149 (1-r)*floatPixel(magnitude, i-1, j));
00150 }
00151 }
00152 if (x_s < strength && strength > s_x)
00153 edgels[nedgel++] = strength;
00154 }
00155 }
00156 return edgels;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 bool
00171 gevd_noise::EstimateSensorTexture(float& sensor, float& texture) const
00172 {
00173
00174 float* dhist = new float[nbin];
00175 #ifdef DEBUG
00176 float mag =
00177 #endif
00178 gevd_float_operators::Slope(hist, dhist, nbin);
00179 #ifdef DEBUG
00180 mag *=
00181 #endif
00182 gevd_float_operators::RunningSum(dhist, dhist, nbin, KRADIUS);
00183 #ifdef DEBUG
00184 for (int i = 0; i < nbin; i++)
00185 vcl_cout << dhist[i]/mag << ' ';
00186 vcl_cout << vcl_endl << vcl_endl;
00187 #endif
00188
00189
00190 if (!WouldBeZeroCrossing(dhist, nbin, sensor)) {
00191 vcl_cerr << "Can not estimate sensor\n";
00192 return false;
00193 }
00194 sensor *= binsize;
00195
00196
00197 if (!RealZeroCrossing(dhist, nbin, texture)) {
00198 vcl_cerr << "Can not estimate texture\n";
00199 return false;
00200 }
00201 texture *= binsize;
00202
00203
00204 if (sensor == 0 ||
00205 sensor > texture)
00206 sensor = texture;
00207 delete [] dhist;
00208 return true;
00209 }
00210
00211
00212
00213
00214
00215 bool
00216 gevd_noise::WouldBeZeroCrossing(const float* dhist, const int nbin,
00217 float& index)
00218 {
00219 int imax=INVALID, i1=INVALID, i2=INVALID;
00220 float maxdh = 0, dh1 = 0, dh2 = 0;
00221 for (int i = 0; i < nbin; i++) {
00222 if (dhist[i] > maxdh) {
00223 maxdh = dhist[i];
00224 imax = i;
00225 }
00226 }
00227 if (imax == INVALID)
00228 return false;
00229 #ifdef DEBUG
00230 vcl_cout << "Find max of dh(x) at: " << imax << vcl_endl;
00231 #endif
00232 for (int i = imax; i < nbin; i++)
00233 if (dhist[i] < 0.5*maxdh) {
00234 dh2 = dhist[i];
00235 i2 = i;
00236 break;
00237 }
00238 if (i2 == INVALID)
00239 return false;
00240 #ifdef DEBUG
00241 vcl_cout << "Find end of downward dh(x) at: " << i2 << ", " << dh2 << vcl_endl;
00242 #endif
00243 for (int i = i2; i > 0; i--)
00244 if (dhist[i] > 0.9*maxdh) {
00245 dh1 = dhist[i];
00246 i1 = i;
00247 break;
00248 }
00249 if (i1 == INVALID)
00250 return false;
00251 #ifdef DEBUG
00252 vcl_cout << "Find start of downward dh(x) at: " << i1 << ", " << dh1 << vcl_endl;
00253 #endif
00254 if (i1 >= i2 || dh1 <= dh2)
00255 index = 0;
00256 else
00257 index = i2 + (i2-i1)*dh2/(dh1-dh2);
00258 #ifdef DEBUG
00259 vcl_cout << "Find would be zero-crossing dh(x) at: " << index << vcl_endl;
00260 #endif
00261 return true;
00262 }
00263
00264
00265
00266
00267
00268 bool
00269 gevd_noise::RealZeroCrossing(const float* dhist, const int nbin,
00270 float& index)
00271 {
00272 int i3=INVALID, imin=INVALID;
00273 float dh3 = 0, mindh = 0;
00274 for (int i = 0; i < nbin; i++) {
00275 if (dhist[i] < mindh) {
00276 mindh = dhist[i];
00277 imin = i;
00278 }
00279 }
00280 if (imin == INVALID)
00281 return false;
00282 #ifdef DEBUG
00283 vcl_cout << "Find min of dh(x) at: " << imin << vcl_endl;
00284 #endif
00285 for (int i = imin; i > 0; i--)
00286 if (dhist[i] >= 0) {
00287 dh3 = dhist[i];
00288 i3 = i;
00289 break;
00290 }
00291 if (i3 == INVALID)
00292 return false;
00293 index = (float)i3;
00294 if (dh3 > 0) {
00295 int i4 = i3+1;
00296 float dh4 = (float)vcl_fabs(dhist[i4]);
00297 index = (i3*dh4 + i4*dh3) / (dh3 + dh4);
00298 }
00299 #ifdef DEBUG
00300 vcl_cout << "Find real zero-crossing dh(x) at: " << index << vcl_endl;
00301 #endif
00302 return true;
00303 }