/**
 * Define video types according to the size.
 */
public static enum videoType {
	//----- 176 * 144
	QCIF,
	//----- QCIF * 2 = 352 * 288
	CIF,
	//----- CIF * 2 = 704 * 576
	FCIF
}
 
/**
 * Convert MSE to PSNR.
 * @param MSE
 * @param max the maximum value for each pixel
 * @return
 */
public static double videoMSEtoPSNR(double MSE, double max) {
	return 10 * Math.log10((max * max) / MSE);
}
 
/**
 * Calculate MSE for all components.
 * @param original the original image/video
 * @param result the other image/video that is compared to original one
 * @return
 */
public static double videoCalcMSE(byte[] original, byte[] result) {
	long sum = 0;
	int diff;
	for (int i = 0; i < original.length; i++) {
		int ioriginal = original[i] & 0xFF;
		int iresult = result[i] & 0xFF;
		diff = ioriginal - iresult;
		sum += diff * diff;
	}
	double MSE = sum / original.length;
	return MSE;
}
 
/**
 * Calculate PSNR for all components.
 * @param original the original image/video
 * @param result the other image/video that is compared to original one
 * @return
 */
public static double videoCalcPSNR(byte[] original, byte[] result) {
	double MSE = videoCalcMSE(original, result);
	double PSNR = videoMSEtoPSNR(MSE, 255.0);
	return PSNR;
}
 
/**
 * Calculate MSE only for Y component.
 * @param original the original image/video
 * @param result the other image/video that is compared to original one
 * @param type the size of image or video frame
 * @return
 */
public static double videoCalcMSEY(byte[] original, byte[] result, videoType type) {
	//----- decide the width and height according to the video type
	int width = 176;
	int height = 144;
	if (type == videoType.CIF) {
		width *= 2;
		height *= 2;
	}
	if (type == videoType.FCIF) {
		width *= 4;
		height *= 4;
	}
	//----- calculate the sum of diff^2
	double sum = 0;
	int diff;
	int y_size = width * height;
	int frame_size = (int) (y_size * 1.5);
	//----- consider if the length of original and result is different
	int length = Math.min(original.length, result.length);
	if (length == 0) {
		printErr("the length of data is zero : calcMSE_y_general");
		return -1;
	}
	for (int i = 0; i < length; i++) {
		if (i % frame_size < y_size) {
			int ioriginal = original[i] & 0xFF;
			int iresult = result[i] & 0xFF;
			diff = ioriginal - iresult;
			sum += diff * diff;
		}
	}
	//----- calculate the MSE and PSNR
	double MSE = sum / (original.length * 2.0 / 3.0);
	return MSE;
}
 
/**
 * Calculate the PSNR only for Y component.
 * @param original the original image/video
 * @param result the other image/video that is compared to original one
 * @param type the size of image or video frame
 * @return
 */
public static double videoCalcPSNRY(byte[] original, byte[] result, videoType type) {
	//----- calculate the MSE and PSNR
	double MSE = videoCalcMSEY(original, result, type);
	//----- the maximum value on each pixel is "255"
	double PSNR = videoMSEtoPSNR(MSE, 255.0);
	return PSNR;
}


Back to JavaHowTo

Alumni Liaison

Basic linear algebra uncovers and clarifies very important geometry and algebra.

Dr. Paul Garrett