// Functions of class Retinex Plane_FL &Retinex::Kernel(Plane_FL &dst, const Plane_FL &src) { const size_t scount = para.sigmaVector.size(); size_t s; for (s = 0; s < scount; ++s) { if (para.sigmaVector[s] > 0) break; } if (s >= scount) { dst = src; return dst; } PCType i, j, upper; PCType height = src.Height(); PCType width = src.Width(); PCType stride = src.Stride(); Plane_FL gauss(src, false); if (scount == 1 && para.sigmaVector[0] > 0) // single-scale Gaussian filter { RecursiveGaussian GFilter(para.sigmaVector[0], true); Plane_FL gauss = GFilter(src); for (j = 0; j < height; ++j) { i = j * stride; for (upper = i + width; i < upper; ++i) { dst[i] = gauss[i] <= 0 ? 0 : log(src[i] / gauss[i] + 1); } } } else // multi-scale Gaussian filter { if (dst.data() == src.data()) { DEBUG_FAIL("Retinex::Kernel: Data of Plane_FL \"dst\" and Plane_FL \"src\" can not be of the same address for multi-scale."); } dst.InitValue(1); for (s = 0; s < scount; ++s) { if (para.sigmaVector[s] > 0) { RecursiveGaussian GFilter(para.sigmaVector[s], true); GFilter.Filter(gauss, src); for (j = 0; j < height; ++j) { i = j * stride; for (upper = i + width; i < upper; ++i) { if (gauss[i] > 0) { dst[i] *= src[i] / gauss[i] + 1; } } } } else { for (j = 0; j < height; ++j) { i = j * stride; for (upper = i + width; i < upper; ++i) { dst[i] *= FLType(2); } } } } FLType scountRec = 1 / static_cast<FLType>(scount); for (j = 0; j < height; ++j) { i = j * stride; for (upper = i + width; i < upper; ++i) { dst[i] = log(dst[i]) * scountRec; } } } return dst; }
// Implementation of O(1) cross/joint Bilateral filter algorithm from "Qingxiong Yang, Kar-Han Tan, Narendra Ahuja - Real-Time O(1) Bilateral Filtering" Plane &Bilateral2D_1(Plane &dst, const Plane &src, const Plane &ref, const Bilateral2D_Data &d, int plane) { int i, j, upper; int k; int height = ref.Height(); int width = ref.Width(); int stride = ref.Width(); int pcount = ref.PixelCount(); double sigmaS = d.sigmaS[plane]; double sigmaR = d.sigmaR[plane]; int PBFICnum = d.PBFICnum[plane]; const LUT<FLType> &GR_LUT = d.GR_LUT[plane]; // Value range of Plane "ref" DType rLower, rUpper, rRange; rLower = ref.Floor(); rUpper = ref.Ceil(); rRange = rUpper - rLower; // Generate quantized PBFICs' parameters DType * PBFICk = new DType[PBFICnum]; for (k = 0; k < PBFICnum; ++k) { PBFICk[k] = static_cast<DType>(static_cast<double>(rRange)*k / (PBFICnum - 1) + rLower + 0.5); } // Generate recursive Gaussian filter object RecursiveGaussian GFilter(sigmaS, true); // Generate quantized PBFICs Plane_FL * PBFIC = new Plane_FL[PBFICnum]; Plane_FL Wk(ref, false); Plane_FL Jk(ref, false); for (k = 0; k < PBFICnum; ++k) { PBFIC[k] = Plane_FL(ref, false); for (j = 0; j < height; ++j) { i = stride * j; for (upper = i + width; i < upper; ++i) { Wk[i] = Gaussian_Distribution2D_Range_LUT_Lookup(GR_LUT, PBFICk[k], ref[i]); Jk[i] = Wk[i] * src[i]; } } GFilter(Wk, Wk); GFilter(Jk, Jk); for (j = 0; j < height; ++j) { i = stride * j; for (upper = i + width; i < upper; ++i) { PBFIC[k][i] = Wk[i] == 0 ? 0 : Jk[i] / Wk[i]; } } } // Generate filtered result from PBFICs using linear interpolation for (j = 0; j < height; ++j) { i = stride * j; for (upper = i + width; i < upper; ++i) { for (k = 0; k < PBFICnum - 2; ++k) { if (ref[i] < PBFICk[k + 1] && ref[i] >= PBFICk[k]) break; } dst[i] = dst.Quantize(((PBFICk[k + 1] - ref[i])*PBFIC[k][i] + (ref[i] - PBFICk[k])*PBFIC[k + 1][i]) / (PBFICk[k + 1] - PBFICk[k])); } } // Clear and output delete[] PBFIC; delete[] PBFICk; return dst; }