User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
isp:sample_awb_implementation_in_c [2018/06/14 22:25] – [Constructor AWB::AWB] Igor Yefmovisp:sample_awb_implementation_in_c [2022/04/04 23:32] (current) – external edit 127.0.0.1
Line 7: Line 7:
   * ''%%S2R::enum HIST_TYPE%%'' - a helper enum used as an index into histogram data arrays   * ''%%S2R::enum HIST_TYPE%%'' - a helper enum used as an index into histogram data arrays
  
-The code below conforms to C++14 standard but it is recommended to use the C++17 toolchain as this is the version the [[code::SUB2r-lib]] is targetting.+The code below conforms to C++17 standard and it is recommended to use the C++17 toolchain as this is the version the [[code::SUB2r-lib]] is targetting.
  
 ====== Helper one-liners ====== ====== Helper one-liners ======
 A few short functions for code readability, put into a local anonymous namespace (effectively making these function ''static'' and making sure we don't pollute/collide with the global namespace). A few short functions for code readability, put into a local anonymous namespace (effectively making these function ''static'' and making sure we don't pollute/collide with the global namespace).
 +
 +Side note: I'm fully aware of the ''std::clamp()'' template yet using my own ''_box()'' because of type conversions I need. In one case I'm limiting a ''double'' into an ''int'' range, returning an ''int'' result. In the second case the range is specified by ''[[#PerPart]]'' values that would otherwise need to be explicitly cast to ''double'' which looked too ugly, TBH.
  
 <code c++>namespace{ <code c++>namespace{
Line 121: Line 123:
 ===== Constructor AWB::AWB ===== ===== Constructor AWB::AWB =====
  
-A bulk of (quite simplistic) calculations is performed with data in ''_stats'' and the results are stored in the ''m_vars'' struct;+A bulk of (quite simplistic) calculations is performed with data in ''_stats'' and the results are stored in the ''m_vars'' struct:
  
 <code c++>AWB::AWB(IImgSensor * _ov, LumaCalc _alg, const ImgStats & _stats, const PerPart & _satTH) <code c++>AWB::AWB(IImgSensor * _ov, LumaCalc _alg, const ImgStats & _stats, const PerPart & _satTH)
Line 147: Line 149:
 Perform the analysis of available data and come up with a recommendation on how to adjust the sensor, if necessary. Perform the analysis of available data and come up with a recommendation on how to adjust the sensor, if necessary.
  
-<code c++>void S2R::AWB::_analyze()+<code c++>void AWB::_analyze()
 { {
     m_vars.op = Action::correctGains;     m_vars.op = Action::correctGains;
Line 171: Line 173:
 // A more generic definition of this special condition is: too much red overexposure relative to // A more generic definition of this special condition is: too much red overexposure relative to
 // green overexposure relative to overall brightness of the picture. The brighter the image the // green overexposure relative to overall brightness of the picture. The brighter the image the
-// more overexposure we can tolerate +// more overexposure we can tolerate, but to a certain point 
-bool S2R::AWB::_isRedOE() const+bool AWB::_isRedOE() const
 { {
     if(m_vars.oeR < m_pxUsed * 0.15 && m_vars.oeG < m_pxUsed * 0.01){     if(m_vars.oeR < m_pxUsed * 0.15 && m_vars.oeG < m_pxUsed * 0.01){
Line 181: Line 183:
     }else if(m_vars.avgY < 60){     }else if(m_vars.avgY < 60){
         return m_vars.oeR > m_vars.oeG * m_vars.avgY * 3;         return m_vars.oeR > m_vars.oeG * m_vars.avgY * 3;
 +    }else if(m_vars.avgY < 85){
 +        return m_vars.oeR > m_vars.oeG * m_vars.avgY;
     }else{     }else{
-        return m_vars.oeR > m_vars.oeG * m_vars.avgY * 7;+        return m_vars.oeR > m_vars.oeG * 8;
     }     }
 }</code> }</code>
Line 190: Line 194:
 If the red channel is way hot what we do is bring it almost half-way back to where the green gain is (''62.5%'' to be precise, but that number is just a convenient "slightly bigger than half" and easy to express as a simple fraction). If the red channel is way hot what we do is bring it almost half-way back to where the green gain is (''62.5%'' to be precise, but that number is just a convenient "slightly bigger than half" and easy to express as a simple fraction).
  
-<code c++>void S2R::AWB::_resetRed()+<code c++>void AWB::_resetRed()
 { {
-    const int gainG = m_ov[Val::GAIN_G]; +    const int gainG = m_ov[Val::gain_g]; 
-    const int gainR = m_ov[Val::GAIN_R];+    const int gainR = m_ov[Val::gain_r];
     if(gainR > gainG){     if(gainR > gainG){
         const auto diff = (gainG - gainR) * 5 / 8;  // 62.5% closer to green gain value         const auto diff = (gainG - gainR) * 5 / 8;  // 62.5% closer to green gain value
-        m_ov[Val::GAIN_R] = gainR + diff;+        m_ov[Val::gain_r] = gainR + diff;
     }     }
 }</code> }</code>
Line 206: Line 210:
 The channel's Gain correction is performed if it's corresponding chroma component's "global average" value (''U'' for Blue, ''V'' for Red) is more than ''precision'' further from ''0''. The channel's Gain correction is performed if it's corresponding chroma component's "global average" value (''U'' for Blue, ''V'' for Red) is more than ''precision'' further from ''0''.
  
-<code c++>void S2R::AWB::_correctGains()+<code c++>void AWB::_correctGains()
 { {
     assert(m_vars.op == Action::correctGains);     assert(m_vars.op == Action::correctGains);
  
-    const auto limit = m_ov.getLimit(Val::GAIN_G); // assume the same limit for all 3 channels +    const auto limit = m_ov.getLimit(Val::gain_g); // assume the same limit for all 3 channels 
-    const double precision = 0.1;+    const double precision = 0.01;
  
     if(abs(m_vars.avgU) > precision){     if(abs(m_vars.avgU) > precision){
Line 218: Line 222:
         //m_vars.avgB /= blueAdj;         //m_vars.avgB /= blueAdj;
         const auto gb = m_vars.avgB == 0 ? 0 : m_vars.avgG / m_vars.avgB;         const auto gb = m_vars.avgB == 0 ? 0 : m_vars.avgG / m_vars.avgB;
-        const int gainB = _box(m_ov[Val::GAIN_B] * gb, 10, limit); +        const int gainB = _box(m_ov[Val::gain_b] * gb, 10, limit); 
-        m_ov[Val::GAIN_B] = gainB;+        m_ov[Val::gain_b] = gainB;
     }     }
  
     if(abs(m_vars.avgV) > precision){     if(abs(m_vars.avgV) > precision){
         const auto gr = m_vars.avgR == 0 ? 0 : m_vars.avgG / m_vars.avgR;         const auto gr = m_vars.avgR == 0 ? 0 : m_vars.avgG / m_vars.avgR;
-        const int gainR = _box(m_ov[Val::GAIN_R] * gr, 10, limit); +        const int gainR = _box(m_ov[Val::gain_r] * gr, 10, limit); 
-        m_ov[Val::GAIN_R] = gainR;+        m_ov[Val::gain_r] = gainR;
     }     }
 } }
Line 234: Line 238:
 In cases when our stats collection yielded too little or too much data we need to adjust the "saturation tolerance" accordingly and try to bring the amount of collected data into a reasonable range. Experimentally we've determined that such range is [''16''..''35'']% which we try to reach by using a 'saturation tolerance" in [''1''..''60'']% range. In cases when our stats collection yielded too little or too much data we need to adjust the "saturation tolerance" accordingly and try to bring the amount of collected data into a reasonable range. Experimentally we've determined that such range is [''16''..''35'']% which we try to reach by using a 'saturation tolerance" in [''1''..''60'']% range.
  
-<code c++>void S2R::AWB::_adjTol(long double _adj)+<code c++>void AWB::_adjTol(long double _adj)
 { {
     auto diff = _adj * m_satTH;    // adjust proportionally to current Saturation tolerance     auto diff = _adj * m_satTH;    // adjust proportionally to current Saturation tolerance
Line 248: Line 252:
 ====== Sample usage ====== ====== Sample usage ======
  
-This is a copy-paste of the code used in [[manual:Aria]] utility for the POC. This code has minimal comments but should be fairly easy to comprehend nonetheless:+This is a copy-paste of the code used in [[manual:Aria]] utility for the POC. This code has minimal comments but should be fairly easy to follow:
  
 <code c++>void ImgAnalyzerDlg::_awbInfo() <code c++>void ImgAnalyzerDlg::_awbInfo()
Line 286: Line 290:
 } }
 </code> </code>
 +
 +
 +====== Initial values ======
 +
 +Following are the initial defaults for the variables that affect the process of automatic white balance adjustment:
 +^ Name (as seen in ''%%ImgAnalyzerDlg%%::_awbInfo()'' above) ^ Value ^
 +| ''currTolerance'' | ''15/100'', adjusted automagically based on last frame's stats |
 +

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information