Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| isp:sample_ae_implementation_in_c [2018/06/16 22:28] – [Helpers] Igor Yefmov | isp:sample_ae_implementation_in_c [2022/04/04 23:32] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 36: | Line 36: | ||
| return 0; | return 0; | ||
| } | } | ||
| + | |||
| + | }</ | ||
| + | |||
| + | ====== PerPart ====== | ||
| + | This helper class is to avoid stupid arithmetic errors when mixing various ratios, like absolute ratios, percentages (%), per-milles(‰), | ||
| + | |||
| + | In addition a few helpful user-defined literals are provided for better code readability when it comes to constants. | ||
| + | |||
| + | This is a super-minimalistic class that doesn' | ||
| + | |||
| + | <code c++> | ||
| + | |||
| + | struct PerPart{ | ||
| + | PerPart(long double _val = 0.f) : m_val(_val) {} // 1.0f == 100_pcnt | ||
| + | PerPart(unsigned long long int _val, unsigned long long int _div) | ||
| + | : PerPart(_div == 0 ? 0.f : static_cast< | ||
| + | {} | ||
| + | operator long double() const { return m_val; } | ||
| + | int pcnt() const { return static_cast< | ||
| + | |||
| + | private: | ||
| + | long double m_val = 0.f; | ||
| + | }; | ||
| + | |||
| + | PerPart operator"" | ||
| + | PerPart operator"" | ||
| + | PerPart operator"" | ||
| }</ | }</ | ||
| Line 85: | Line 112: | ||
| using Val = IImgSensor:: | using Val = IImgSensor:: | ||
| IImgSensor & m_ov; // OmniVision sensor interface | IImgSensor & m_ov; // OmniVision sensor interface | ||
| + | const PerPart m_hysteresis; | ||
| struct{ | struct{ | ||
| Line 102: | Line 130: | ||
| A bulk of (quite simplistic) calculations is performed with data in '' | A bulk of (quite simplistic) calculations is performed with data in '' | ||
| - | <code c++> | + | <code c++> |
| : m_ov(*_ov) | : m_ov(*_ov) | ||
| - | , m_stats(_stats) | + | , m_hysteresis(_hysteresis) |
| { | { | ||
| m_vars.underExposed = _triggeredLeft(_stats, | m_vars.underExposed = _triggeredLeft(_stats, | ||
| Line 159: | Line 187: | ||
| m_vars.adjY += (1 - m_vars.adjY) * 5 / 8; // be 62.5% less aggressive than requested to avoid oscillations | m_vars.adjY += (1 - m_vars.adjY) * 5 / 8; // be 62.5% less aggressive than requested to avoid oscillations | ||
| - | if(m_vars.overExposed > 60 && m_vars.adjY < 1){ | + | if(m_vars.overExposed > 60 && m_vars.adjY < 1 - m_hysteresis){ |
| m_vars.actionRH = Action:: | m_vars.actionRH = Action:: | ||
| - | }else if(m_vars.overExposed > 250 && m_vars.adjY <= 1){ | + | }else if(m_vars.overExposed > 250 && m_vars.adjY <= 1 - m_hysteresis){ |
| m_vars.actionRH = Action:: | m_vars.actionRH = Action:: | ||
| - | }else if(m_vars.overExposed < 250 && m_vars.adjY > 1){ | + | }else if(m_vars.overExposed < 250 && m_vars.adjY > 1 + m_hysteresis){ |
| m_vars.actionRH = Action:: | m_vars.actionRH = Action:: | ||
| }else{ | }else{ | ||
| Line 264: | Line 292: | ||
| }</ | }</ | ||
| + | ====== Sample usage ====== | ||
| + | |||
| + | This is a copy-paste of the code used in [[manual: | ||
| + | |||
| + | <code c++> | ||
| + | |||
| + | static CString _corrOp2Txt(AE:: | ||
| + | using op = AE::CorrOp; | ||
| + | switch(_op){ | ||
| + | case op:: | ||
| + | case op:: | ||
| + | case op:: | ||
| + | case op:: | ||
| + | case op:: | ||
| + | case op:: | ||
| + | case op:: | ||
| + | } | ||
| + | return {}; | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | void ImgAnalyzerDlg:: | ||
| + | { | ||
| + | if(((CButton *)(GetDlgItem(IDC_CHECK_ISA_AE)))-> | ||
| + | return; | ||
| + | } | ||
| + | const auto & stats = m_analyzer.getStats(); | ||
| + | const auto correct = ((CButton*)(GetDlgItem(IDC_CHECK_ISA_AE_CORRECT)))-> | ||
| + | const auto aeTolerance = PerPart(GetDlgItemInt(IDC_EDIT_ISA_AE_RIGHT, | ||
| + | const int aeTgtLuma = GetDlgItemInt(IDC_EDIT_ISA_AE_BRIGHTNESS, | ||
| + | const PerPart aeHysteresis{GetDlgItemInt(IDC_EDIT_ISA_AE_HYSTERESIS, | ||
| + | AE ae{m_fx3.sensor(), | ||
| + | const auto rez = ae(correct); | ||
| + | |||
| + | // display the information | ||
| + | { | ||
| + | const PerPart pxUsed{stats.ae.pixels, | ||
| + | CString msg; | ||
| + | msg.AppendFormat(L" | ||
| + | msg.AppendFormat(L" | ||
| + | msg.AppendFormat(L" | ||
| + | msg.AppendFormat(L" | ||
| + | msg.AppendFormat(L" | ||
| + | msg += _corrOp2Txt(ae.details().op); | ||
| + | SetDlgItemTextW(IDC_STATIC_ISA_AE, | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ====== Initial values ====== | ||
| + | |||
| + | Following are the initial defaults for the variables that affect the process of automatic image brightness (Black Level, Exposure, Gains) adjustment: | ||
| + | ^ Name (as seen in '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | " | ||