コード例 #1
0
ファイル: Metric.cpp プロジェクト: LawrenceWeng/openholdembot
bool Yee_Compare(CompareArgs &args) {
	if ((args.ImgA->Get_Width() != args.ImgB->Get_Width()) ||
		(args.ImgA->Get_Height() != args.ImgB->Get_Height())) {
    // args.ErrorStr = "Image dimensions do not match\n";
		args.PixelsFailed = 0xffffffff;
		return false;
	}
	int dim = args.ImgA->Get_Width() * args.ImgA->Get_Height();
	bool identical = true;
	for (int i = 0; i < dim; i++) {
		if (args.ImgA->Get(i) != args.ImgB->Get(i)) {
		  identical = false;
		  break;
		}
	}
	if (identical) {
    // args.ErrorStr = "Images are binary identical\n";
		args.PixelsFailed = 0;
		return true;
	}
	// assuming colorspaces are in Adobe RGB (1998) convert to XYZ
	float *aX = new float[dim];
	float *aY = new float[dim];
	float *aZ = new float[dim];
	float *bX = new float[dim];
	float *bY = new float[dim];
	float *bZ = new float[dim];
	float *aLum = new float[dim];
	float *bLum = new float[dim];
	
	float *aA = new float[dim];
	float *bA = new float[dim];
	float *aB = new float[dim];
	float *bB = new float[dim];

	if (args.Verbose) printf("Converting RGB to XYZ\n");
	
	unsigned int x, y, w, h;
	w = args.ImgA->Get_Width();
	h = args.ImgA->Get_Height();
	for (y = 0; y < h; y++) {
		for (x = 0; x < w; x++) {
			float r, g, b, l;
			int i = x + y * w;
			r = powf(args.ImgA->Get_Red(i) / 255.0f, args.Gamma);
			g = powf(args.ImgA->Get_Green(i) / 255.0f, args.Gamma);
			b = powf(args.ImgA->Get_Blue(i) / 255.0f, args.Gamma);						
			AdobeRGBToXYZ(r,g,b,aX[i],aY[i],aZ[i]);			
			XYZToLAB(aX[i], aY[i], aZ[i], l, aA[i], aB[i]);
			r = powf(args.ImgB->Get_Red(i) / 255.0f, args.Gamma);
			g = powf(args.ImgB->Get_Green(i) / 255.0f, args.Gamma);
			b = powf(args.ImgB->Get_Blue(i) / 255.0f, args.Gamma);						
			AdobeRGBToXYZ(r,g,b,bX[i],bY[i],bZ[i]);
			XYZToLAB(bX[i], bY[i], bZ[i], l, bA[i], bB[i]);
			aLum[i] = aY[i] * args.Luminance;
			bLum[i] = bY[i] * args.Luminance;
		}
	}
	
	if (args.Verbose) printf("Constructing Laplacian Pyramids\n");
	
	LPyramid *la = new LPyramid(aLum, w, h);
	LPyramid *lb = new LPyramid(bLum, w, h);
	
	float num_one_degree_pixels = (float) (2 * tan( args.FieldOfView * 0.5 * M_PI / 180) * 180 / M_PI);
	float pixels_per_degree = w / num_one_degree_pixels;
	
	if (args.Verbose) printf("Performing test\n");
	
	float num_pixels = 1;
	unsigned int adaptation_level = 0;
	for (int i = 0; i < MAX_PYR_LEVELS; i++) {
		adaptation_level = i;
		if (num_pixels > num_one_degree_pixels) break;
		num_pixels *= 2;
	}
	
	float cpd[MAX_PYR_LEVELS];
	cpd[0] = 0.5f * pixels_per_degree;
	for (int i = 1; i < MAX_PYR_LEVELS; i++) cpd[i] = 0.5f * cpd[i - 1];
	float csf_max = csf(3.248f, 100.0f);
	
	float F_freq[MAX_PYR_LEVELS - 2];
	for (int i = 0; i < MAX_PYR_LEVELS - 2; i++) F_freq[i] = csf_max / csf( cpd[i], 100.0f);
	
	unsigned int pixels_failed = 0;
	for (y = 0; y < h; y++) {
	  for (x = 0; x < w; x++) {
		int index = x + y * w;
		float contrast[MAX_PYR_LEVELS - 2];
		float sum_contrast = 0;
		for (int i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			float n1 = fabsf(la->Get_Value(x,y,i) - la->Get_Value(x,y,i + 1));
			float n2 = fabsf(lb->Get_Value(x,y,i) - lb->Get_Value(x,y,i + 1));
			float numerator = (n1 > n2) ? n1 : n2;
			float d1 = fabsf(la->Get_Value(x,y,i+2));
			float d2 = fabsf(lb->Get_Value(x,y,i+2));
			float denominator = (d1 > d2) ? d1 : d2;
			if (denominator < 1e-5f) denominator = 1e-5f;
			contrast[i] = numerator / denominator;
			sum_contrast += contrast[i];
		}
		if (sum_contrast < 1e-5) sum_contrast = 1e-5f;
		float F_mask[MAX_PYR_LEVELS - 2];
		float adapt = la->Get_Value(x,y,adaptation_level) + lb->Get_Value(x,y,adaptation_level);
		adapt *= 0.5f;
		if (adapt < 1e-5) adapt = 1e-5f;
		for (int i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			F_mask[i] = mask(contrast[i] * csf(cpd[i], adapt)); 
		}
		float factor = 0;
		for (int i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			factor += contrast[i] * F_freq[i] * F_mask[i] / sum_contrast;
		}
		if (factor < 1) factor = 1;
		if (factor > 10) factor = 10;
		float delta = fabsf(la->Get_Value(x,y,0) - lb->Get_Value(x,y,0));
		bool pass = true;
		// pure luminance test
		if (delta > factor * tvi(adapt)) {
			pass = false;
		} else {
			// CIE delta E test with modifications
			float color_scale = 1.0f;
			// ramp down the color test in scotopic regions
			if (adapt < 10.0f) {
				color_scale = 1.0f - (10.0f - color_scale) / 10.0f;
				color_scale = color_scale * color_scale;
			}
			float da = aA[index] - bA[index];
			float db = aB[index] - bB[index];
			da = da * da;
			db = db * db;
			float delta_e = (da + db) * color_scale;
			if (delta_e > factor) {
				pass = false;
			}
		}
		if (!pass) {
			pixels_failed++;
//			if (args.ImgDiff) {
//				args.ImgDiff->Set(255, 0, 0, 255, index);
//			}
		} else {
//			if (args.ImgDiff) {
//				args.ImgDiff->Set(0, 0, 0, 255, index);
//			}
		}
	  }
	}
	
	if (aX) delete[] aX;
	if (aY) delete[] aY;
	if (aZ) delete[] aZ;
	if (bX) delete[] bX;
	if (bY) delete[] bY;
	if (bZ) delete[] bZ;
	if (aLum) delete[] aLum;
	if (bLum) delete[] bLum;
	if (la) delete la;
	if (lb) delete lb;
	if (aA) delete aA;
	if (bA) delete bA;
	if (aB) delete aB;
	if (bB) delete bB;
	
	args.PixelsFailed = pixels_failed;
	return true;

/*
	if (pixels_failed < args.ThresholdPixels) {
		args.ErrorStr = "Images are perceptually indistinguishable\n";
		return true;
	}
	
	char different[100];
	sprintf(different, "%d pixels are different\n", pixels_failed);

	args.ErrorStr = "Images are visibly different\n";
	args.ErrorStr += different;
	
	if (args.ImgDiff) {
		if (args.ImgDiff->WritePPM()) {
			args.ErrorStr += "Wrote difference image to ";
			args.ErrorStr+= args.ImgDiff->Get_Name();
			args.ErrorStr += "\n";
		} else {
			args.ErrorStr += "Could not write difference image to ";
			args.ErrorStr+= args.ImgDiff->Get_Name();
			args.ErrorStr += "\n";
		}
	}
	return false;
*/
}
コード例 #2
0
ファイル: metric.cpp プロジェクト: yangzhengxing/luxrender
unsigned int slg::Yee_Compare(
		const float *rgbA,
		const float *rgbB,
		std::vector<bool> *diff,
		float *tviBuffer,
		const unsigned int width,
		const unsigned int height,
		const bool LuminanceOnly,
		const float FieldOfView,
		const float Gamma,
		const float Luminance,
		const float ColorFactor,
		const unsigned int DownSample)
{
	unsigned int i, dim;
	dim = width * height;
	bool identical = true;
	for (i = 0; i < 3 * dim; i++) {
		if (rgbA[i] != rgbB[i]) {
		  identical = false;
		  break;
		}
	}
	if (identical) {
		// Images are binary identical
		return true;
	}
	
	// assuming colorspaces are in Adobe RGB (1998) convert to XYZ
	float *aX = new float[dim];
	float *aY = new float[dim];
	float *aZ = new float[dim];
	float *bX = new float[dim];
	float *bY = new float[dim];
	float *bZ = new float[dim];
	float *aLum = new float[dim];
	float *bLum = new float[dim];
	
	float *aA = new float[dim];
	float *bA = new float[dim];
	float *aB = new float[dim];
	float *bB = new float[dim];
	
	unsigned int x, y;
	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			float r, g, b, l;
			i = x + y * width;
			r = powf(rgbA[3 * i], Gamma);
			g = powf(rgbA[3 * i + 1], Gamma);
			b = powf(rgbA[3 * i + 2], Gamma);						
			AdobeRGBToXYZ(r,g,b,aX[i],aY[i],aZ[i]);			
			XYZToLAB(aX[i], aY[i], aZ[i], l, aA[i], aB[i]);
			r = powf(rgbB[3 * i], Gamma);
			g = powf(rgbB[3 * i + 1], Gamma);
			b = powf(rgbB[3 * i + 2], Gamma);						
			AdobeRGBToXYZ(r,g,b,bX[i],bY[i],bZ[i]);
			XYZToLAB(bX[i], bY[i], bZ[i], l, bA[i], bB[i]);
			aLum[i] = aY[i] * Luminance;
			bLum[i] = bY[i] * Luminance;
		}
	}

	// Constructing Laplacian Pyramids
	
	LPyramid *la = new LPyramid(aLum, width, height);
	LPyramid *lb = new LPyramid(bLum, width, height);
	
	float num_one_degree_pixels = (float) (2 * tan(FieldOfView * 0.5 * M_PI / 180) * 180 / M_PI);
	float pixels_per_degree = width / num_one_degree_pixels;
	
	// Performing test
	
	float num_pixels = 1;
	unsigned int adaptation_level = 0;
	for (i = 0; i < MAX_PYR_LEVELS; i++) {
		adaptation_level = i;
		if (num_pixels > num_one_degree_pixels) break;
		num_pixels *= 2;
	}
	
	float cpd[MAX_PYR_LEVELS];
	cpd[0] = 0.5f * pixels_per_degree;
	for (i = 1; i < MAX_PYR_LEVELS; i++) cpd[i] = 0.5f * cpd[i - 1];
	float csf_max = csf(3.248f, 100.0f);
	
	float F_freq[MAX_PYR_LEVELS - 2];
	for (i = 0; i < MAX_PYR_LEVELS - 2; i++) F_freq[i] = csf_max / csf( cpd[i], 100.0f);
	
	unsigned int pixels_failed = 0;
	for (y = 0; y < height; y++) {
	  for (x = 0; x < width; x++) {
		int index = x + y * width;
		float contrast[MAX_PYR_LEVELS - 2];
		float sum_contrast = 0;
		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			float n1 = fabsf(la->Get_Value(x,y,i) - la->Get_Value(x,y,i + 1));
			float n2 = fabsf(lb->Get_Value(x,y,i) - lb->Get_Value(x,y,i + 1));
			float numerator = (n1 > n2) ? n1 : n2;
			float d1 = fabsf(la->Get_Value(x,y,i+2));
			float d2 = fabsf(lb->Get_Value(x,y,i+2));
			float denominator = (d1 > d2) ? d1 : d2;
			if (denominator < 1e-5f) denominator = 1e-5f;
			contrast[i] = numerator / denominator;
			sum_contrast += contrast[i];
		}
		if (sum_contrast < 1e-5) sum_contrast = 1e-5f;
		float F_mask[MAX_PYR_LEVELS - 2];
		float adapt = la->Get_Value(x,y,adaptation_level) + lb->Get_Value(x,y,adaptation_level);
		adapt *= 0.5f;
		if (adapt < 1e-5) adapt = 1e-5f;
		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			F_mask[i] = mask(contrast[i] * csf(cpd[i], adapt)); 
		}
		float factor = 0;
		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) {
			factor += contrast[i] * F_freq[i] * F_mask[i] / sum_contrast;
		}
		if (factor < 1) factor = 1;
		if (factor > 10) factor = 10;
		float delta = fabsf(la->Get_Value(x,y,0) - lb->Get_Value(x,y,0));
		bool pass = true;
		// pure luminance test
		const float tviValue = tvi(adapt);
		if (tviBuffer)
			tviBuffer[x + y * width] = tviValue;
		if (delta > factor * tviValue) {
			pass = false;
		} else if (!LuminanceOnly) {
			// CIE delta E test with modifications
			float color_scale = ColorFactor;
			// ramp down the color test in scotopic regions
			if (adapt < 10.0f) {
				// Don't do color test at all.
				color_scale = 0.0;
			}
			float da = aA[index] - bA[index];
			float db = aB[index] - bB[index];
			da = da * da;
			db = db * db;
			float delta_e = (da + db) * color_scale;
			if (delta_e > factor) {
				pass = false;
			}
		}
		if (!pass) {
			pixels_failed++;

			if (diff)
				(*diff)[index] = false;
		} else {
			if (diff)
				(*diff)[index] = true;
		}
	  }
	}
	
	if (aX) delete[] aX;
	if (aY) delete[] aY;
	if (aZ) delete[] aZ;
	if (bX) delete[] bX;
	if (bY) delete[] bY;
	if (bZ) delete[] bZ;
	if (aLum) delete[] aLum;
	if (bLum) delete[] bLum;
	if (la) delete la;
	if (lb) delete lb;
	if (aA) delete[] aA;
	if (bA) delete[] bA;
	if (aB) delete[] aB;
	if (bB) delete[] bB;
	
	return pixels_failed;
}