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