/** * @brief weightFunction computes weight functions for x in [0,1]. * @param x is an input value in [0, 1]. * @param type is the type of the function. * @return It returns a weight for x. */ PIC_INLINE float weightFunction(float x, CRF_WEIGHT type) { switch(type) { case CW_ROBERTSON: { // w(x) = exp(-4*(x*255 - 127.5)^2/(127.5)^2) = exp(-16.0 * (x - 0.5)^2) // (according to the paper it should be scaled and shifted s.t. w(0) = w(255) = 0 and w(127.5) = 1) static const double shift = exp(-4); static const double scaleDiv = (1.0 - shift); const double t = x - 0.5; return float((exp(-16.0 * (t * t) ) - shift) / scaleDiv); } break; case CW_HAT: { float val = (2.0f * x - 1.0f); float val_squared = val * val; float val_quartic = val_squared * val_squared; return (1.0f - val_quartic * val_quartic * val_quartic); } break; case CW_DEB97: { static const float Zmin = 0.0f; static const float Zmax = 1.0f; static const float tr = (Zmin + Zmax) / 2.0f; if(x <= tr) { return x - Zmin; } else { return Zmax - x; } } break; case CW_DEB97p01: { static const float Zmin = 0.01f; static const float Zmax = 0.99f; float tr = (Zmin + Zmax) / 2.0f; if(x <= tr) { return CLAMPi(x - Zmin, 0.0f, 1.0f); } else { return CLAMPi(Zmax - x, 0.0f, 1.0f); } } break; default: { return 1.0f; } break; } return 1.0f; }
/** * @brief convertToLDR * @param exposure * @param gammaCor * @return */ Color3 convertToLDR(float exposure = 1.0f, float gammaCor = 2.2f) { Color3 ret(x * exposure, y * exposure, z * exposure); ret.gamma(1.0f / gammaCor); ret.x = CLAMPi(ret.x, 0.0f, 1.0f); ret.y = CLAMPi(ret.y, 0.0f, 1.0f); ret.z = CLAMPi(ret.z, 0.0f, 1.0f); return ret; }
/** * @brief MSE computes the mean square error (MSE) between two HDR images with given exposure and gamma. * @param ori is the original image. * @param cmp is the distorted image. * @param gamma is the encoding gamma. * @param fstop is the f-stop value of the image. * @param nBit is the number of bits used for the discretization. * @return It returns the MSE value between ori and cmp. */ PIC_INLINE double MSE(Image *ori, Image *cmp, float gamma = 2.2f, float fstop = 0.0f, int nBit = 8) { if(ori == NULL || cmp == NULL) { return -2.0; } if(!ori->isValid() || !cmp->isValid()) { return -4.0; } if(!ori->isSimilarType(cmp)) { return -1.0; } float invGamma = 1.0f / gamma; float exposure = powf(2.0f, fstop); int area = ori->width * ori->height; int size = area * ori->channels; unsigned long long acc = 0; int nValues = (1 << nBit) - 1; float nValuesf = float(nValues); for(int i = 0; i < size; i++) { int oriLDR = int(nValuesf * (powf(ori->data[i] * exposure, invGamma))); int cmpLDR = int(nValuesf * (powf(cmp->data[i] * exposure, invGamma))); oriLDR = CLAMPi(oriLDR, 0, nValues); cmpLDR = CLAMPi(cmpLDR, 0, nValues); int delta = cmpLDR - oriLDR; acc += delta * delta; } return (double(acc) / double(area)); }
/** * @brief ProcessBBox * @param dst * @param src * @param box */ void ProcessBBox(Image *dst, ImageVec src, BBox *box) { int tmpChannel = CLAMPi(channel, 0, src[0]->channels); for(int p = box->z0; p < box->z1; p++) { for(int j = box->y0; j < box->y1; j++) { for(int i = box->x0; i < box->x1; i++) { float *dst_data = (*dst)(i, j, p); float *data = (*src[0])(i, j, p); dst_data[0] = data[tmpChannel]; } } } }