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

src/AutoFocus.cpp

00001 #include <math.h>
00002 
00003 #include "FCam/AutoFocus.h"
00004 #include "FCam/Lens.h"
00005 #include "FCam/Frame.h"
00006 
00007 #include "Debug.h"
00008 
00009 namespace FCam {
00010 
00011     AutoFocus::AutoFocus(Lens *l, Rect r) : lens(l), state(IDLE), rect(r) {}
00012     
00013     void AutoFocus::startSweep() {
00014         if (!lens) return;
00015         state = HOMING;
00016         // focus at infinity
00017         lens->setFocus(lens->farFocus());
00018         stats.clear();
00019     }
00020 
00021     
00022     void AutoFocus::update(const Frame &f) {
00023         if (state == FOCUSED || state == IDLE) return;
00024         
00025         if (state == SETTING) {
00026             if (!lens->focusChanging()) {
00027                 state = FOCUSED;                
00028             }
00029             return;
00030         }
00031                 
00032         // we're sweeping or homing       
00033         if (!f.sharpness().valid()) return;
00034 
00035         // convert a rect on the screen to a subset of the sharpness map
00036         int minSx = 0;
00037         int minSy = 0;
00038         int maxSx = f.sharpness().size().width-1;
00039         int maxSy = f.sharpness().size().height-1;
00040         float w = f.shot().image.width();
00041         float h = f.shot().image.height();
00042         if (rect.width > 0 && rect.height > 0) {
00043             minSx = int(rect.x * f.sharpness().size().width / w + 0.5);
00044             minSy = int(rect.y * f.sharpness().size().height / h + 0.5);
00045             maxSx = int((rect.x + rect.width) * f.sharpness().size().width / w + 0.5);
00046             maxSy = int((rect.y + rect.height) * f.sharpness().size().height / h + 0.5);
00047             if (maxSx >= f.sharpness().size().width) maxSx = f.sharpness().size().width-1;
00048             if (maxSy >= f.sharpness().size().height) maxSy = f.sharpness().size().height-1;
00049             if (minSx >= f.sharpness().size().width) minSx = f.sharpness().size().width-1;
00050             if (minSy >= f.sharpness().size().height) minSy = f.sharpness().size().height-1;
00051             if (minSx < 0) minSx = 0;
00052             if (minSy < 0) minSy = 0;
00053             if (maxSx < 0) maxSx = 0;
00054             if (maxSy < 0) maxSy = 0;
00055         }
00056 
00057         Stats s;
00058         s.position = f["lens.focus"];
00059         s.sharpness = 0;
00060         for (int sy = minSy; sy <= maxSy; sy++) {
00061             for (int sx = minSx; sx <= maxSx; sx++) {
00062                 s.sharpness += f.sharpness()(sx, sy) >> 10;
00063             }
00064         }
00065         stats.push_back(s);
00066         dprintf(4, "Focus position %f, sharpness %d\n", s.position, s.sharpness);
00067         
00068         if (state == HOMING && !lens->focusChanging()) {
00069             // wait until we get a frame back with focus at infinity
00070             if (fabs(s.position - lens->farFocus()) < 0.01) {
00071                 lens->setFocus(lens->nearFocus(), (lens->nearFocus() - lens->farFocus()));
00072                 state = SWEEPING;
00073                 return;
00074             }
00075         }
00076         
00077         if (state == SWEEPING && stats.size() > 4) {
00078             bool gettingWorse = true;
00079             
00080             // check if the sharpness is just getting continuously
00081             // worse (by at least 1% per tick). If so, don't wait for
00082             // the sweep to terminate
00083             for (size_t i = stats.size()-1; i > stats.size()-4; i--) {
00084                 if (stats[i].position < stats[i-1].position ||
00085                     (stats[i].sharpness*101)/100 > stats[i-1].sharpness) {
00086                     gettingWorse = false;
00087                     break;
00088                 }
00089             }
00090             
00091             // Check if it's time to set the focus
00092             if (!lens->focusChanging() || gettingWorse) {
00093                 Stats best = stats[0];
00094                 for (size_t i = 1; i < stats.size(); i++) {
00095                     if (stats[i].sharpness > best.sharpness) best = stats[i];
00096                 }
00097                 
00098                 lens->setFocus(best.position);
00099                 state = SETTING;
00100                 stats.clear();
00101                 return;
00102             }
00103         }
00104         
00105         if (state == SETTING && !lens->focusChanging()) {
00106             state = FOCUSED;
00107             return;
00108         }
00109         
00110     }
00111 
00112 }

Generated on Fri Sep 24 2010 15:53:00 for FCam by  doxygen 1.7.1