• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/AutoExposure.cpp

00001 #include <FCam/Frame.h>
00002 #include <FCam/Sensor.h>
00003 #include <FCam/Shot.h>
00004 
00005 #include <FCam/AutoExposure.h>
00006 
00007 #include "Debug.h"
00008 
00009 namespace FCam {
00010     void autoExpose(Shot *s, const Frame &f,
00011                     float maxGain,
00012                     int maxExposure,
00013                     float smoothness) {
00014         
00015 
00016         if (!s) return;
00017 
00018         int b = f.histogram().buckets();
00019 
00020         int cdf[256]; // a CDF for histograms of up to 256 buckets
00021 
00022         if (!f.histogram().valid()) return;
00023         if (b > 256 || b < 64) return;
00024 
00025         const Histogram &hist = f.histogram();
00026 
00027         cdf[0] = hist(0);
00028         for (int i = 1; i < b; i++) {
00029             cdf[i] = cdf[i-1] + hist(i);
00030         }
00031 
00032         int brightPixels = cdf[b-1] - cdf[b-21]; // top 20 buckets
00033         int targetBrightPixels = cdf[b-1]/50;
00034         int maxSaturatedPixels = cdf[b-1]/200;
00035         int saturatedPixels = cdf[b-1] - cdf[b-6]; // top 5 buckets
00036 
00037         // how much should I change brightness by 
00038         float adjustment = 1.0f;
00039 
00040         if (saturatedPixels > maxSaturatedPixels) {
00041             // first don't let things saturate too much
00042             adjustment = 1.0f - ((float)(saturatedPixels - maxSaturatedPixels))/cdf[b-1];
00043         } else if (brightPixels < targetBrightPixels) {
00044             // increase brightness to try and hit the desired number of well exposed pixels
00045             int l = b-11;
00046             while (brightPixels < targetBrightPixels && l > 0) {
00047                 brightPixels += cdf[l];
00048                 brightPixels -= cdf[l-1];
00049                 l--;
00050             }
00051             
00052             // that level is supposed to be at b-11;
00053             adjustment = float(b-11+1)/(l+1);
00054         } else {
00055             // we're not oversaturated, and we have enough bright pixels. Do nothing.
00056         }
00057 
00058         if (adjustment > 4.0) adjustment = 4.0;
00059         if (adjustment < 1/16.0f) adjustment = 1/16.0f;
00060 
00061         float brightness = f.gain() * f.exposure();
00062         float desiredBrightness = brightness * adjustment;        
00063         int exposure;
00064         float gain;
00065 
00066         // Apply the smoothness constraint
00067         float shotBrightness = s->gain * s->exposure;
00068         desiredBrightness = shotBrightness * smoothness + desiredBrightness * (1-smoothness);
00069 
00070         // whats the largest we can raise exposure without negatively
00071         // impacting frame-rate or introducing handshake. We use 1/30s
00072         int exposureKnee = 33333; 
00073 
00074         if (desiredBrightness > exposureKnee) {
00075             exposure = exposureKnee;
00076             gain = desiredBrightness / exposureKnee;
00077         } else {
00078             gain = 1.0f;
00079             exposure = desiredBrightness;
00080         }
00081 
00082         // Clamp the gain at max, and try to make up for it with exposure
00083         if (gain > maxGain) {
00084             exposure = desiredBrightness/maxGain;
00085             gain = maxGain;
00086         } 
00087 
00088         // Finally, clamp the exposure at max
00089         if (exposure > maxExposure) {
00090             exposure = maxExposure;
00091         }
00092 
00093         s->exposure  = exposure;
00094         s->gain      = gain;
00095     }
00096 }

Generated on Mon Aug 16 2010 14:25:45 for FCam by  doxygen 1.7.1