Sampler *RandomSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new RandomSampler(x0, x1, y0, y1, nSamples, shutterOpen, shutterClose); }
Sampler* StratifiedSampler::GetSubSampler(int num, int count){ int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new StratifiedSampler(x0, x1, y0, y1, x_pixel_samples, y_pixel_samples, jitter_samples); }
// HaltonSampler Method Definitions Sampler *HaltonSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new HaltonSampler(x0, x1, y0, y1, samplesPerPixel, shutterOpen, shutterClose, num * 1024); }
Sampler *BestCandidateSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new BestCandidateSampler(x0, x1, y0, y1, samplesPerPixel, shutterOpen, shutterClose); }
Sampler *StratifiedSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new StratifiedSampler(x0, x1, y0, y1, xPixelSamples, yPixelSamples, jitterSamples, shutterOpen, shutterClose); }
Sampler* RandomSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return nullptr; return new RandomSampler(x0, x1, y0, y1, nSamples); }
Sampler *AdaptiveSampler::GetSubSampler(int num, int count) { int x0, x1, y0, y1; ComputeSubWindow(num, count, &x0, &x1, &y0, &y1); if (x0 == x1 || y0 == y1) return NULL; return new AdaptiveSampler(x0, x1, y0, y1, minSamples, maxSamples, method == ADAPTIVE_CONTRAST_THRESHOLD ? "contrast" : "shapeid", shutterOpen, shutterClose); }
void CrossNLMFilter::Apply( float sigmaR, const vector<TwoDArray<float> > &mseArray, const vector<TwoDArray<float> > &priArray, const TwoDArray<Color> &rImg, const TwoDArray<Feature> &featureImg, const TwoDArray<Feature> &featureVarImg, vector<TwoDArray<float> > &outMSE, vector<TwoDArray<float> > &outPri) const { float mseScaleR = -0.5f/(sigmaR*sigmaR); #pragma omp parallel for num_threads(PbrtOptions.nCores) schedule(static) for(int taskId = 0; taskId < nTasks; taskId++) { int txs, txe, tys, tye; ComputeSubWindow(taskId, nTasks, width, height, &txs, &txe, &tys, &tye); for(int y = tys; y < tye; y++) for(int x = txs; x < txe; x++) { vector<float> mseSum(mseArray.size(), 0.f); vector<float> priSum(priArray.size(), 0.f); vector<float> wSum(mseArray.size(), 0.f); Feature feature = featureImg(x, y); Feature featureVar = featureVarImg(x, y); // Filter using pixels within search range for(int dy = -searchRadius; dy <= searchRadius; dy++) for(int dx = -searchRadius; dx <= searchRadius; dx++) { int xx = x + dx; int yy = y + dy; if(xx < 0 || yy < 0 || xx >= width || yy >= height) continue; Color diffSqSum(0.f, 0.f, 0.f); // Calculate block distance for(int by = -patchRadius; by <= patchRadius; by++) for(int bx = -patchRadius; bx <= patchRadius; bx++) { int xbx = x + bx; int yby = y + by; int xxbx = xx + bx; int yyby = yy + by; if( xbx < 0 || xbx >= width || yby < 0 || yby >= height || xxbx < 0 || xxbx >= width || yyby < 0 || yyby >= height) continue; Color diff = rImg(xbx, yby) - rImg(xxbx, yyby); diffSqSum += (diff*diff); } diffSqSum *= invPatchSize; float dist = Avg(diffSqSum); Feature fDiff = feature - featureImg(xx, yy); Feature fVarSum = featureVar + featureVarImg(xx, yy); Feature fDist = (fDiff*fDiff)/fVarSum.Max(c_VarMax); float weight = fmath::exp(dist*mseScaleR + Sum(fDist*scaleF)); for(size_t i = 0; i < mseArray.size(); i++) { mseSum[i] += weight * mseArray[i](xx, yy); priSum[i] += weight * priArray[i](xx, yy); wSum[i] += weight; } } for(size_t i = 0; i < mseArray.size(); i++) { outMSE[i](x, y) = mseSum[i] / wSum[i]; outPri[i](x, y) = priSum[i] / wSum[i]; } } } }
void CrossNLMFilter::Apply(const TwoDArray<Color> &img, const TwoDArray<Feature> &featureImg, const TwoDArray<Feature> &featureVarImg, const TwoDArray<Color> &rImg, const TwoDArray<Color> &varImg, vector<TwoDArray<Color> > &fltArray, vector<TwoDArray<float> > &mseArray, vector<TwoDArray<float> > &priArray) const { #pragma omp parallel for num_threads(PbrtOptions.nCores) schedule(static) for(int taskId = 0; taskId < nTasks; taskId++) { int txs, txe, tys, tye; ComputeSubWindow(taskId, nTasks, width, height, &txs, &txe, &tys, &tye); for(int y = tys; y < tye; y++) for(int x = txs; x < txe; x++) { vector<Color> sum(scaleR.size(), Color(0.f)); vector<Color> rSum(scaleR.size(), Color(0.f)); vector<Color> rSumSq(scaleR.size(), Color(0.f)); vector<float> wSum(scaleR.size(), 0.f); vector<vector<float> > wArray(scaleR.size()); for(size_t p = 0; p < wArray.size(); p++) { wArray[p].resize(patchWidth*patchWidth); } Feature feature = featureImg(x, y); Feature featureVar = featureVarImg(x, y); // Filter using pixels within search range for(int dy = -searchRadius; dy <= searchRadius; dy++) for(int dx = -searchRadius; dx <= searchRadius; dx++) { int xx = x + dx; int yy = y + dy; if(xx < 0 || yy < 0 || xx >= width || yy >= height) continue; Color diffSqSum(0.f, 0.f, 0.f); // Calculate block distance for(int by = -patchRadius; by <= patchRadius; by++) for(int bx = -patchRadius; bx <= patchRadius; bx++) { int xbx = x + bx; int yby = y + by; int xxbx = xx + bx; int yyby = yy + by; if( xbx < 0 || xbx >= width || yby < 0 || yby >= height || xxbx < 0 || xxbx >= width || yyby < 0 || yyby >= height) continue; Color diff = rImg(xbx, yby) - rImg(xxbx, yyby); diffSqSum += (diff*diff); } diffSqSum *= invPatchSize; float dist = Avg(diffSqSum); Feature fDiff = feature - featureImg(xx, yy); Feature fVarSum = featureVar + featureVarImg(xx, yy); Feature fDist = (fDiff*fDiff)/fVarSum.Max(c_VarMax); // For each parameter, calculate information necessary for // filtering and SURE estimation for(size_t p = 0; p < scaleR.size(); p++) { if(scaleR[p] == 0.f) { continue; } float weight = fmath::exp(dist*scaleR[p] + Sum(fDist*scaleF)); sum[p] += weight * img(xx, yy); rSum[p] += weight * rImg(xx, yy); rSumSq[p] += weight * rImg(xx, yy) * rImg(xx, yy); wSum[p] += weight; if(dy >= -patchRadius && dy <= patchRadius && dx >= -patchRadius && dx <= patchRadius) { wArray[p][(dy+patchRadius)*patchWidth+(dx+patchRadius)] = weight; } } } for(size_t p = 0; p < scaleR.size(); p++) { if(scaleR[p] == 0.f) { fltArray[p](x, y) = img(x, y); mseArray[p](x, y) = Avg(2.f*varImg(x, y)); continue; } float invWSum = 1.f/wSum[p]; Color xl = sum[p] * invWSum; Color rxl = rSum[p] * invWSum; Color rxlSq = rSumSq[p] * invWSum; Color ryl = rImg(x, y); Color dxdy = (-2.f*scaleR[p])*(rxlSq - rxl*rxl)*invPatchSize + Color(invWSum); Color tmp; for(int by = -patchRadius; by <= patchRadius; by++) for(int bx = -patchRadius; bx <= patchRadius; bx++) { int xbpx = x+bx; int ybpy = y+by; int xbmx = x-bx; int ybmy = y-by; if( xbpx < 0 || xbpx >= width || ybpy < 0 || ybpy >= height || xbmx < 0 || xbmx >= width || ybmy < 0 || ybmy >= height) continue; Color rylpb = rImg(xbpx, ybpy); Color rylmb = rImg(xbmx, ybmy); float w = wArray[p][(-by+patchRadius)*patchWidth+(-bx+patchRadius)]; tmp += w*(ryl - rylpb)*(rxl - rylmb); } tmp *= (-2.f*scaleR[p])*invPatchSize*invWSum; dxdy += tmp; Color mse = (rxl-ryl)*(rxl-ryl) + 2.f*varImg(x, y)*dxdy - varImg(x, y); Color pri = (mse + varImg(x, y)); fltArray[p](x, y) = xl; mseArray[p](x, y) = Avg(mse); priArray[p](x, y) = Avg(pri) / (xl.Y()*xl.Y() + 1e-2f); } } } }