I don't have a strong mathematics/Matlab background. I would like to convert this Black level correction function from Matlab to C++. Please comment about on the code style and correctness of my equation.
Matlab
function output = calculateBlackLevel(blStruct, AG, ET)
blLut = zeros(length(blStruct), size(blStruct{1}.black_level,2));
etLut = zeros(length(blStruct), 1);
for k = 1 : length(blStruct)
bl = blStruct{k};
if length(bl.analog_gain) == 1
blLut(k, :) = bl.black_level;
elseif AG > max(bl.analog_gain) || AG < min(bl.analog_gain)
blLut(k, :) = interp1(bl.analog_gain, bl.black_level, AG, 'nearest', 'extrap');
else
blLut(k, :) = interp1(bl.analog_gain, bl.black_level, AG);
end
etLut(k) = bl.exposure_time;
end
if length(etLut) == 1
output = blLut;
elseif ET > max(etLut) || ET < min(etLut)
output = interp1(etLut, blLut, ET, 'nearest', 'extrap');
else
output = interp1(etLut, blLut, ET);
end
end
C++
void Preprocessor::CalculateBlackLevel(black_level* blackLevelDataNative, double analogGain, double exposureTime, double output[])
{
const int NUMBER_OF_CHANNELS = 4;
std::vector<double> exposureTimeLut;
std::vector<std::array<int, NUMBER_OF_CHANNELS> > blackLevelLut;
if (blackLevelDataNative->num_bl_luts == 1 )
{
std::array<int, NUMBER_OF_CHANNELS> arr;
arr[0] = blackLevelDataNative->black_level_luts[0]->black_level[0];
arr[1] = blackLevelDataNative->black_level_luts[0]->black_level[1];
arr[2] = blackLevelDataNative->black_level_luts[0]->black_level[2];
arr[3] = blackLevelDataNative->black_level_luts[0]->black_level[3];
blackLevelLut.push_back(arr);
}
else
{
double maxAnalogGain = blackLevelDataNative->black_level_luts[0]->analog_gain;
double minAnalogGain = blackLevelDataNative->black_level_luts[0]->analog_gain;
for (int num = 0; num < blackLevelDataNative->num_bl_luts; num++)
{
maxAnalogGain = std::max(maxAnalogGain, blackLevelDataNative->black_level_luts[num]->analog_gain);
minAnalogGain = std::min(minAnalogGain, blackLevelDataNative->black_level_luts[num]->analog_gain);
}
if (analogGain >= maxAnalogGain || analogGain <= minAnalogGain)
{
for (int k = 0; k < blackLevelDataNative->num_bl_luts; k++)
{
//find which points you need to interpolate
if(analogGain >= blackLevelDataNative->black_level_luts[k]->analog_gain && analogGain <=blackLevelDataNative->black_level_luts[k+1]->analog_gain)
{
std::array<int, NUMBER_OF_CHANNELS> arr;
for (int ch = 0; ch < NUMBER_OF_CHANNELS; ch++)
{
//y = y0 + (y1-y0)*(x-x0)/(x1-x0);
double y0 = blackLevelDataNative->black_level_luts[k]->black_level[ch];
double y1 = blackLevelDataNative->black_level_luts[k+1]->black_level[ch];
double x = analogGain;
double x0 = blackLevelDataNative->black_level_luts[k]->analog_gain;
double x1 = blackLevelDataNative->black_level_luts[k + 1]->analog_gain;
arr[ch] = y0 + (y1-y0)*(x-x0)/(x1-x0);
}
blackLevelLut.push_back(arr);
//if the vector does not contains the exposure, add if to the vector
if (std::find(exposureTimeLut.begin(), exposureTimeLut.end(), blackLevelDataNative->black_level_luts[k]->exposure_time) == exposureTimeLut.end())
{
exposureTimeLut.push_back(blackLevelDataNative->black_level_luts[k]->exposure_time);
}
}
}
}
else //extrapolate nearest neighbor
{
for (int k = 0; k < blackLevelDataNative->num_bl_luts; k++)
{
if (analogGain > maxAnalogGain)
{
if(blackLevelDataNative->black_level_luts[k]->analog_gain == maxAnalogGain)
{
std::array<int, NUMBER_OF_CHANNELS> arr;
for (int ch = 0; ch < NUMBER_OF_CHANNELS; ch++)
{
arr[ch] = blackLevelDataNative->black_level_luts[k]->black_level[ch];
}
blackLevelLut.push_back(arr);
//if the vector does not contains the exposure, add if to the vector
if (std::find(exposureTimeLut.begin(), exposureTimeLut.end(), blackLevelDataNative->black_level_luts[k]->exposure_time) == exposureTimeLut.end())
{
exposureTimeLut.push_back(blackLevelDataNative->black_level_luts[k]->exposure_time);
}
}
}
else //analogGain < minAnalogGain
{
if(blackLevelDataNative->black_level_luts[k]->analog_gain == minAnalogGain)
{
std::array<int, NUMBER_OF_CHANNELS> arr;
for (int ch = 0; ch < NUMBER_OF_CHANNELS; ch++)
{
arr[ch] = arr[ch] = blackLevelDataNative->black_level_luts[k]->black_level[ch];
}
blackLevelLut.push_back(arr);
//if the vector does not contains the exposure, add if to the vector
if (std::find(exposureTimeLut.begin(), exposureTimeLut.end(), blackLevelDataNative->black_level_luts[k]->exposure_time) == exposureTimeLut.end())
{
exposureTimeLut.push_back(blackLevelDataNative->black_level_luts[k]->exposure_time);
}
}
}
}
}
}
if(exposureTimeLut.size() == 1 )
{
return;
}
else
{
std::vector<double>::iterator iterMax = std::max_element(exposureTimeLut.begin(), exposureTimeLut.end());
std::vector<double>::iterator iterMin = std::min_element(exposureTimeLut.begin(), exposureTimeLut.end());
for (int k = 0; k < exposureTimeLut.size(); k++)
{
if(exposureTime <= *iterMax && exposureTime >= *iterMin ) //interpolate
{
//find which points you need to interpolate
if(exposureTime >= exposureTimeLut[k] && exposureTime <= exposureTimeLut[k+1])
{
for (int ch = 0; ch < NUMBER_OF_CHANNELS; ch++)
{
//y = y0 + (y1-y0)*(x-x0)/(x1-x0);
double y0 = blackLevelLut[k][ch];
double y1 = blackLevelLut[k+1][ch];
double x = exposureTime;
double x0 = exposureTimeLut[k];
double x1 = exposureTimeLut[k +1];
output[ch] = y0 + (y1-y0)*(x-x0)/(x1-x0);
}
return; //break the loop
}
}
else //extrapolate nearest neighbor
{
for (int ch = 0; ch < NUMBER_OF_CHANNELS; ch++)
{
if(exposureTime > *iterMax )
{
output[ch] = blackLevelLut[exposureTimeLut.size()-1][ch];
}
else
{
output[ch] = blackLevelLut[0][ch];
}
}
return;
}
}
}
}