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];
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];
00033 int targetBrightPixels = cdf[b-1]/50;
00034 int maxSaturatedPixels = cdf[b-1]/200;
00035 int saturatedPixels = cdf[b-1] - cdf[b-6];
00036
00037
00038 float adjustment = 1.0f;
00039
00040 if (saturatedPixels > maxSaturatedPixels) {
00041
00042 adjustment = 1.0f - ((float)(saturatedPixels - maxSaturatedPixels))/cdf[b-1];
00043 } else if (brightPixels < targetBrightPixels) {
00044
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
00053 adjustment = float(b-11+1)/(l+1);
00054 } else {
00055
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
00067 float shotBrightness = s->gain * s->exposure;
00068 desiredBrightness = shotBrightness * smoothness + desiredBrightness * (1-smoothness);
00069
00070
00071
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
00083 if (gain > maxGain) {
00084 exposure = desiredBrightness/maxGain;
00085 gain = maxGain;
00086 }
00087
00088
00089 if (exposure > maxExposure) {
00090 exposure = maxExposure;
00091 }
00092
00093 s->exposure = exposure;
00094 s->gain = gain;
00095 }
00096 }