rcd_demosaic(): Fixed tiling bug. Small speedup

This commit is contained in:
heckflosse
2018-03-02 14:28:51 +01:00
parent 7e5f2ee19e
commit 9514ba713c

View File

@@ -44,15 +44,16 @@ void RawImageSource::rcd_demosaic()
{
BENCHFUN
volatile double progress = 0.0;
if (plistener) {
plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "rcd"));
plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCD)));
plistener->setProgress(0);
}
const int width = W, height = H;
constexpr int tileBorder = 8;
constexpr int tileSize = 220;
constexpr int tileSizeN = tileSize - 2 * tileBorder;
constexpr int rcdBorder = 9;
constexpr int tileSize = 214;
constexpr int tileSizeN = tileSize - 2 * rcdBorder;
const int numTh = H / (tileSizeN) + ((H % (tileSizeN)) ? 1 : 0);
const int numTw = W / (tileSizeN) + ((W % (tileSizeN)) ? 1 : 0);
constexpr int w1 = tileSize, w2 = 2 * tileSize, w3 = 3 * tileSize, w4 = 4 * tileSize;
@@ -64,6 +65,7 @@ void RawImageSource::rcd_demosaic()
#pragma omp parallel
#endif
{
int progresscounter = 0;
float *cfa = (float*) calloc(tileSize * tileSize, sizeof *cfa);
float (*rgb)[tileSize * tileSize] = (float (*)[tileSize * tileSize])malloc(3 * sizeof *rgb);
float *VH_Dir = (float*) calloc(tileSize * tileSize, sizeof *VH_Dir);
@@ -75,10 +77,19 @@ void RawImageSource::rcd_demosaic()
#endif
for(int tr = 0; tr < numTh; ++tr) {
for(int tc = 0; tc < numTw; ++tc) {
int rowStart = tr * tileSizeN;
int rowEnd = std::min(tr * tileSizeN + tileSize, H);
int colStart = tc * tileSizeN;
int colEnd = std::min(tc * tileSizeN + tileSize, W);
const int rowStart = tr * tileSizeN;
const int rowEnd = std::min(rowStart + tileSize, H);
if(rowStart + rcdBorder == rowEnd - rcdBorder) {
continue;
}
const int colStart = tc * tileSizeN;
const int colEnd = std::min(colStart + tileSize, W);
if(colStart + rcdBorder == colEnd - rcdBorder) {
continue;
}
const int tileRows = std::min(rowEnd - rowStart, tileSize);
const int tilecols = std::min(colEnd - colStart, tileSize);
for (int row = rowStart; row < rowEnd; row++) {
int indx = (row - rowStart) * tileSize;
@@ -99,12 +110,12 @@ void RawImageSource::rcd_demosaic()
* STEP 1: Find cardinal and diagonal interpolation directions
*/
for (int row = 4; row < tileSize - 4; row++) {
for (int col = 4, indx = row * tileSize + col; col < tileSize - 4; col++, indx++) {
for (int row = 4; row < tileRows - 4; row++) {
for (int col = 4, indx = row * tileSize + col; col < tilecols - 4; col++, indx++) {
const float cfai = cfa[indx];
//Calculate h/v local discrimination
float V_Stat = max(epssq, - 18.f * cfai * (cfa[indx - w1] + cfa[indx + w1] + 2.f * (cfa[indx - w2] + cfa[indx + w2]) - cfa[indx - w3] - cfa[indx + w3]) - 2.f * cfai * (cfa[indx - w4] + cfa[indx + w4] - 19.f * cfai) - cfa[indx - w1] * (70.f * cfa[indx + w1] + 12.f * cfa[indx - w2] - 24.f * cfa[indx + w2] + 38.f * cfa[indx - w3] - 16.f * cfa[indx + w3] - 12.f * cfa[indx - w4] + 6.f * cfa[indx + w4] - 46.f * cfa[indx - w1]) + cfa[indx + w1] * (24.f * cfa[indx - w2] - 12.f * cfa[indx + w2] + 16.f * cfa[indx - w3] - 38.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 12.f * cfa[indx + w4] + 46.f * cfa[indx + w1]) + cfa[indx - w2] * (14.f * cfa[indx + w2] - 12.f * cfa[indx + w3] - 2.f * cfa[indx - w4] + 2.f * cfa[indx + w4] + 11.f * cfa[indx - w2]) + cfa[indx + w2] * (-12.f * cfa[indx - w3] + 2.f * (cfa[indx - w4] - cfa[indx + w4]) + 11.f * cfa[indx + w2]) + cfa[indx - w3] * (2.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 10.f * cfa[indx - w3]) + cfa[indx + w3] * (-6.f * cfa[indx + w4] + 10.f * cfa[indx + w3]) + cfa[indx - w4] * cfa[indx - w4] + cfa[indx + w4] * cfa[indx + w4]);
float H_Stat = max(epssq, - 18.f * cfai * (cfa[indx - 1] + cfa[indx + 1] + 2.f * (cfa[indx - 2] + cfa[indx + 2]) - cfa[indx - 3] - cfa[indx + 3]) - 2.f * cfai * (cfa[indx - 4] + cfa[indx + 4] - 19.f * cfai) - cfa[indx - 1] * (70.f * cfa[indx + 1] + 12.f * cfa[indx - 2] - 24.f * cfa[indx + 2] + 38.f * cfa[indx - 3] - 16.f * cfa[indx + 3] - 12.f * cfa[indx - 4] + 6.f * cfa[indx + 4] - 46.f * cfa[indx - 1]) + cfa[indx + 1] * (24.f * cfa[indx - 2] - 12.f * cfa[indx + 2] + 16.f * cfa[indx - 3] - 38.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 12.f * cfa[indx + 4] + 46.f * cfa[indx + 1]) + cfa[indx - 2] * (14.f * cfa[indx + 2] - 12.f * cfa[indx + 3] - 2.f * cfa[indx - 4] + 2.f * cfa[indx + 4] + 11.f * cfa[indx - 2]) + cfa[indx + 2] * (-12.f * cfa[indx - 3] + 2.f * (cfa[indx - 4] - cfa[indx + 4]) + 11.f * cfa[indx + 2]) + cfa[indx - 3] * (2.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 10.f * cfa[indx - 3]) + cfa[indx + 3] * (-6.f * cfa[indx + 4] + 10.f * cfa[indx + 3]) + cfa[indx - 4] * cfa[indx - 4] + cfa[indx + 4] * cfa[indx + 4]);
float V_Stat = max(epssq, -18.f * cfai * (cfa[indx - w1] + cfa[indx + w1] + 2.f * (cfa[indx - w2] + cfa[indx + w2]) - cfa[indx - w3] - cfa[indx + w3]) - 2.f * cfai * (cfa[indx - w4] + cfa[indx + w4] - 19.f * cfai) - cfa[indx - w1] * (70.f * cfa[indx + w1] + 12.f * cfa[indx - w2] - 24.f * cfa[indx + w2] + 38.f * cfa[indx - w3] - 16.f * cfa[indx + w3] - 12.f * cfa[indx - w4] + 6.f * cfa[indx + w4] - 46.f * cfa[indx - w1]) + cfa[indx + w1] * (24.f * cfa[indx - w2] - 12.f * cfa[indx + w2] + 16.f * cfa[indx - w3] - 38.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 12.f * cfa[indx + w4] + 46.f * cfa[indx + w1]) + cfa[indx - w2] * (14.f * cfa[indx + w2] - 12.f * cfa[indx + w3] - 2.f * cfa[indx - w4] + 2.f * cfa[indx + w4] + 11.f * cfa[indx - w2]) + cfa[indx + w2] * (-12.f * cfa[indx - w3] + 2.f * (cfa[indx - w4] - cfa[indx + w4]) + 11.f * cfa[indx + w2]) + cfa[indx - w3] * (2.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 10.f * cfa[indx - w3]) + cfa[indx + w3] * (-6.f * cfa[indx + w4] + 10.f * cfa[indx + w3]) + cfa[indx - w4] * cfa[indx - w4] + cfa[indx + w4] * cfa[indx + w4]);
float H_Stat = max(epssq, -18.f * cfai * (cfa[indx - 1] + cfa[indx + 1] + 2.f * (cfa[indx - 2] + cfa[indx + 2]) - cfa[indx - 3] - cfa[indx + 3]) - 2.f * cfai * (cfa[indx - 4] + cfa[indx + 4] - 19.f * cfai) - cfa[indx - 1] * (70.f * cfa[indx + 1] + 12.f * cfa[indx - 2] - 24.f * cfa[indx + 2] + 38.f * cfa[indx - 3] - 16.f * cfa[indx + 3] - 12.f * cfa[indx - 4] + 6.f * cfa[indx + 4] - 46.f * cfa[indx - 1]) + cfa[indx + 1] * (24.f * cfa[indx - 2] - 12.f * cfa[indx + 2] + 16.f * cfa[indx - 3] - 38.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 12.f * cfa[indx + 4] + 46.f * cfa[indx + 1]) + cfa[indx - 2] * (14.f * cfa[indx + 2] - 12.f * cfa[indx + 3] - 2.f * cfa[indx - 4] + 2.f * cfa[indx + 4] + 11.f * cfa[indx - 2]) + cfa[indx + 2] * (-12.f * cfa[indx - 3] + 2.f * (cfa[indx - 4] - cfa[indx + 4]) + 11.f * cfa[indx + 2]) + cfa[indx - 3] * (2.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 10.f * cfa[indx - 3]) + cfa[indx + 3] * (-6.f * cfa[indx + 4] + 10.f * cfa[indx + 3]) + cfa[indx - 4] * cfa[indx - 4] + cfa[indx + 4] * cfa[indx + 4]);
VH_Dir[indx] = V_Stat / (V_Stat + H_Stat);
}
@@ -115,8 +126,8 @@ void RawImageSource::rcd_demosaic()
*/
// Step 2.1: Low pass filter incorporating green, red and blue local samples from the raw data
for (int row = 2; row < tileSize - 2; row++) {
for (int col = 2 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tileSize - 2; col += 2, indx += 2) {
for (int row = 2; row < tileRows - 2; row++) {
for (int col = 2 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 2; col += 2, indx += 2) {
lpf[indx>>1] = 0.25f * cfa[indx] + 0.125f * (cfa[indx - w1] + cfa[indx + w1] + cfa[indx - 1] + cfa[indx + 1]) + 0.0625f * (cfa[indx - w1 - 1] + cfa[indx - w1 + 1] + cfa[indx + w1 - 1] + cfa[indx + w1 + 1]);
}
}
@@ -125,8 +136,8 @@ void RawImageSource::rcd_demosaic()
* STEP 3: Populate the green channel
*/
// Step 3.1: Populate the green channel at blue and red CFA positions
for (int row = 4; row < tileSize - 4; row++) {
for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tileSize - 4; col += 2, indx += 2) {
for (int row = 4; row < tileRows - 4; row++) {
for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 4; col += 2, indx += 2) {
// Refined vertical and horizontal local discrimination
float VH_Central_Value = VH_Dir[indx];
@@ -160,8 +171,8 @@ void RawImageSource::rcd_demosaic()
*/
// Step 4.1: Calculate P/Q diagonal local discrimination
for (int row = 4; row < tileSize - 4; row++) {
for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tileSize - 4; col += 2, indx += 2) {
for (int row = rcdBorder - 4; row < tileRows - rcdBorder + 4; row++) {
for (int col = rcdBorder - 4 + (FC(row, rcdBorder) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder + 4; col += 2, indx += 2) {
const float cfai = cfa[indx];
float P_Stat = max(epssq, - 18.f * cfai * (cfa[indx - w1 - 1] + cfa[indx + w1 + 1] + 2.f * (cfa[indx - w2 - 2] + cfa[indx + w2 + 2]) - cfa[indx - w3 - 3] - cfa[indx + w3 + 3]) - 2.f * cfai * (cfa[indx - w4 - 4] + cfa[indx + w4 + 4] - 19.f * cfai) - cfa[indx - w1 - 1] * (70.f * cfa[indx + w1 + 1] - 12.f * cfa[indx - w2 - 2] + 24.f * cfa[indx + w2 + 2] - 38.f * cfa[indx - w3 - 3] + 16.f * cfa[indx + w3 + 3] + 12.f * cfa[indx - w4 - 4] - 6.f * cfa[indx + w4 + 4] + 46.f * cfa[indx - w1 - 1]) + cfa[indx + w1 + 1] * (24.f * cfa[indx - w2 - 2] - 12.f * cfa[indx + w2 + 2] + 16.f * cfa[indx - w3 - 3] - 38.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 12.f * cfa[indx + w4 + 4] + 46.f * cfa[indx + w1 + 1]) + cfa[indx - w2 - 2] * (14.f * cfa[indx + w2 + 2] - 12.f * cfa[indx + w3 + 3] - 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx - w2 - 2]) - cfa[indx + w2 + 2] * (12.f * cfa[indx - w3 - 3] + 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx + w2 + 2]) + cfa[indx - w3 - 3] * (2.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 10.f * cfa[indx - w3 - 3]) - cfa[indx + w3 + 3] * (6.f * cfa[indx + w4 + 4] + 10.f * cfa[indx + w3 + 3]) + cfa[indx - w4 - 4] * cfa[indx - w4 - 4] + cfa[indx + w4 + 4] * cfa[indx + w4 + 4]);
@@ -173,8 +184,8 @@ void RawImageSource::rcd_demosaic()
}
// Step 4.2: Populate the red and blue channels at blue and red CFA positions
for (int row = 4; row < tileSize - 4; row++) {
for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col, c = 2 - FC(row, col); col < tileSize - 4; col += 2, indx += 2) {
for (int row = rcdBorder - 3; row < tileRows - rcdBorder + 3; row++) {
for (int col = rcdBorder - 3 + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col, c = 2 - FC(row, col); col < tilecols - rcdBorder + 3; col += 2, indx += 2) {
// Refined P/Q diagonal local discrimination
float PQ_Central_Value = PQ_Dir[indx];
@@ -205,19 +216,24 @@ void RawImageSource::rcd_demosaic()
}
// Step 4.3: Populate the red and blue channels at green CFA positions
for (int row = 4; row < tileSize - 4; row++) {
for (int col = 4 + (FC(row, 1) & 1), indx = row * tileSize + col; col < tileSize - 4; col += 2, indx += 2) {
for (int row = rcdBorder; row < tileRows - rcdBorder; row++) {
for (int col = rcdBorder + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder; col += 2, indx += 2) {
// Refined vertical and horizontal local discrimination
float VH_Central_Value = VH_Dir[indx];
float VH_Neighbourhood_Value = 0.25f * ((VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1]) + (VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1]));
float VH_Disc = (std::fabs(0.5f - VH_Central_Value) < std::fabs(0.5f - VH_Neighbourhood_Value)) ? VH_Neighbourhood_Value : VH_Central_Value;
float N1 = eps + std::fabs(rgb[1][indx] - rgb[1][indx - w2]);
float S1 = eps + std::fabs(rgb[1][indx] - rgb[1][indx + w2]);
float W1 = eps + std::fabs(rgb[1][indx] - rgb[1][indx - 2]);
float E1 = eps + std::fabs(rgb[1][indx] - rgb[1][indx + 2]);
float rgb1 = rgb[1][indx];
float N1 = eps + std::fabs(rgb1 - rgb[1][indx - w2]);
float S1 = eps + std::fabs(rgb1 - rgb[1][indx + w2]);
float W1 = eps + std::fabs(rgb1 - rgb[1][indx - 2]);
float E1 = eps + std::fabs(rgb1 - rgb[1][indx + 2]);
float rgb1mw1 = rgb[1][indx - w1];
float rgb1pw1 = rgb[1][indx + w1];
float rgb1m1 = rgb[1][indx - 1];
float rgb1p1 = rgb[1][indx + 1];
for (int c = 0; c <= 2; c += 2) {
// Cardinal gradients
float SNabs = std::fabs(rgb[c][indx - w1] - rgb[c][indx + w1]);
@@ -228,30 +244,45 @@ void RawImageSource::rcd_demosaic()
float E_Grad = E1 + EWabs + std::fabs(rgb[c][indx + 1] - rgb[c][indx + 3]);
// Cardinal colour differences
float N_Est = rgb[c][indx - w1] - rgb[1][indx - w1];
float S_Est = rgb[c][indx + w1] - rgb[1][indx + w1];
float W_Est = rgb[c][indx - 1] - rgb[1][indx - 1];
float E_Est = rgb[c][indx + 1] - rgb[1][indx + 1];
float N_Est = rgb[c][indx - w1] - rgb1mw1;
float S_Est = rgb[c][indx + w1] - rgb1pw1;
float W_Est = rgb[c][indx - 1] - rgb1m1;
float E_Est = rgb[c][indx + 1] - rgb1p1;
// Vertical and horizontal estimations
float V_Est = (N_Grad * S_Est + S_Grad * N_Est) / (N_Grad + S_Grad);
float H_Est = (E_Grad * W_Est + W_Grad * E_Est) / (E_Grad + W_Grad);
// R@G and B@G interpolation
rgb[c][indx] = rgb[1][indx] + (1.f - VH_Disc) * V_Est + VH_Disc * H_Est;
rgb[c][indx] = rgb1 + (1.f - VH_Disc) * V_Est + VH_Disc * H_Est;
}
}
}
for (int row = rowStart + tileBorder; row < rowEnd - tileBorder; ++row) {
for (int col = colStart + tileBorder; col < colEnd - tileBorder; ++col) {
for (int row = rowStart + rcdBorder; row < rowEnd - rcdBorder; ++row) {
for (int col = colStart + rcdBorder; col < colEnd - rcdBorder; ++col) {
int idx = (row - rowStart) * tileSize + col - colStart ;
red[row][col] = CLIP(rgb[0][idx] * 65535.f);
green[row][col] = CLIP(rgb[1][idx] * 65535.f);
blue[row][col] = CLIP(rgb[2][idx] * 65535.f);
}
}
if(plistener) {
progresscounter++;
if(progresscounter % 32 == 0) {
#ifdef _OPENMP
#pragma omp critical (rcdprogress)
#endif
{
progress += (double)32 * ((tileSizeN) * (tileSizeN)) / (H * W);
progress = progress > 1.0 ? 1.0 : progress;
plistener->setProgress(progress);
}
}
}
}
}
@@ -261,7 +292,7 @@ void RawImageSource::rcd_demosaic()
free(PQ_Dir);
}
border_interpolate2(width, height, 8);
border_interpolate2(W, H, rcdBorder);
if (plistener) {
plistener->setProgress(1);