视频质量评价PSNR

匿名 (未验证) 提交于 2019-12-03 00:18:01

一幅MxN尺寸的图像的PSNR的计算公式如下所示:


其中xij 和yij 分别表示失真图像和原始图像对应像素点的灰度值;

i,j 分别代表图像的行和列;

L 是图像灰度值可到达的动态范围,8位的灰度图像的L=2^8-1=255。

如果已知SSD,MxN尺寸图像的PSNR公式如下所示。

MSE=SSD*1/(M*N)

PSNR=10*lg(255^2/MSE)




dp:17

dp:28

dp:32

dp:36


代码:

// PSNR_CAL.cpp : 定义控制台应用程序的入口点。 //PSNR (Peak Signal to Noise Ratio) //峰值信噪比PSNR衡量图像失真或是噪声水平的客观标准。2个图像之间PSNR值越大,则越相似。普遍基准为30dB,30dB以下的图像劣化较为明显。 #include "stdafx.h" #include <stdlib.h> #include <stdio.h> #include <time.h> #include <math.h>  #define VIDEO_WIDTH			1280 #define VIDEO_HEIGHT		720 #define VIDEO_FRAME_NUM			10 //frame number //编码解码YUV #define DEC_YUV_PATH			"E:\\yuv\\\\bs3.yuv" //原YUV #define REF_YUV_PATH			"E:\\yuv\\BasketballDrive_1920x1080_25_250.yuv" #define REF_YUV_422			0 //1:reference yuv is 422 format, 0:reference yuv is 420 format #define VIDEO_SIZE_Y		VIDEO_HEIGHT*VIDEO_WIDTH #define VIDEO_SIZE_UV		(VIDEO_HEIGHT*VIDEO_WIDTH)>>1 #define VIDEO_SIZE_YUV		(VIDEO_SIZE_Y + VIDEO_SIZE_UV) #define CONV422	0 #define CAL_PSNR 1  int main() { 	FILE *fp_dec; 	FILE *fp_ref; 	int i, j, k, comp;  #if CAL_PSNR 	unsigned char line_dec[5000]; 	unsigned char line_ref[5000]; 	int  idiff; 	unsigned long diff_sum; 	int width, height; 	double psnr_frame; 	double psnr_sum[VIDEO_FRAME_NUM][3]; 	double psnr_total[3]; 	 	fp_dec = fopen(DEC_YUV_PATH, "rb"); 	fp_ref = fopen(REF_YUV_PATH, "rb"); 	 	if (fp_dec == NULL) 	{ 		printf("\n DEC YUV file not found\n"); 		return 0; 	}  	if (fp_ref == NULL) 	{ 		printf("\n REF YUV file not found\n"); 		return 0; 	}  	for (i = 0; i < VIDEO_FRAME_NUM; i++) 	{	//Y 		for (comp = 0; comp < 3; comp++) 		{ 			diff_sum = 0; 			if(comp ==0) 			{ 				width = VIDEO_WIDTH; 				height = VIDEO_HEIGHT; 			} 			else 			{ 				width = VIDEO_WIDTH /2; 				height = VIDEO_HEIGHT /2; 			}  			for (j = 0; j < height; j++) 			{ 				fread(line_dec, 1, width, fp_dec); 				fread(line_ref, 1, width, fp_ref);  				//fwrite(line_ref, 1, width, fp_ref_422);  				//if(comp != 0)							//UV 				//	fwrite(line_ref, 1, width, fp_ref_422);  				for (k = 0; k < width; k++) 				{ 					idiff = (int)(line_dec[k] - line_ref[k]); 					diff_sum += idiff*idiff;  					//if (k == 0 && j == 5 ) 					//	printf("stop at %d", k); 				} 				//if (comp != 0 && REF_YUV_422 == 1) // if 422 format, skip one chroma line 				//	fread(line_dec, 1, width, fp_dec); 			} 			psnr_frame = (double)255 * 255 * width* height; 			psnr_sum[i][comp] = 10.0 * log10(psnr_frame / (double)diff_sum); 		} 		printf("frame %d, Y PSNR is %f, Cb PSNR is %f,Cr PSNR is %f \n", i, psnr_sum[i][0], psnr_sum[i][1], psnr_sum[i][2]); 	} 	psnr_total[0] = 0; 	psnr_total[1] = 0; 	psnr_total[2] = 0;  	for (i = 0; i<VIDEO_FRAME_NUM; i++) 	{ 		psnr_total[0] += psnr_sum[i][0]; 		psnr_total[1] += psnr_sum[i][1]; 		psnr_total[2] += psnr_sum[i][2]; 	}  	psnr_total[0] = psnr_total[0] / (VIDEO_FRAME_NUM); 	psnr_total[1] = psnr_total[1] / (VIDEO_FRAME_NUM); 	psnr_total[2] = psnr_total[2] / (VIDEO_FRAME_NUM);	 	printf("average PSNR of sequence is:\n Y PSNR is %f, U PSNR is %f,V PSNR is %f\n", psnr_total[0], psnr_total[1], psnr_total[2]);  	fclose(fp_dec); 	fclose(fp_ref); 	system("pause"); #endif  #if CONV422 	//convert ref 4:2:0 yuv to interleave 4:2:2 yuv 	unsigned char Y_plane[VIDEO_SIZE_YUV]; 	unsigned char U_plane[VIDEO_SIZE_Y / 4]; 	unsigned char V_plane[VIDEO_SIZE_Y / 4]; 	unsigned char YUV_plane[2 * VIDEO_SIZE_Y];  	unsigned char *pt0; 	unsigned char *pt1; 	unsigned char *pt2; 	unsigned char *pt3; 	 	fp_ref = fopen(REF_YUV_PATH, "rb"); 	fp_ref_422 = fopen(REF_YUV422_ITLV_PATH, "wb");  	if (fp_ref == NULL) 	{ 		printf("\n REF YUV file not found\n"); 		return 0; 	}  	if (fp_ref_422 == NULL) 	{ 		printf("\n REF 422 YUV file not found\n"); 		return 0; 	}  	for (i = 0; i < VIDEO_FRAME_NUM_CONV; i++) 	{ 		fread(Y_plane, 1, VIDEO_SIZE_Y, fp_ref); 		fread(U_plane, 1, VIDEO_SIZE_Y / 4, fp_ref); 		fread(V_plane, 1, VIDEO_SIZE_Y / 4, fp_ref);  		pt0 = Y_plane; 		pt1 = U_plane; 		pt2 = V_plane; 		pt3 = YUV_plane;  		for (j = 0; j < VIDEO_HEIGHT / 2; j++) 		{ 			for (k = 0; k < VIDEO_WIDTH / 2; k++)	//the row size of YUV_plane is 2*VIDEO_WIDTH 			{ 				*pt3++ = *pt0++;	//Y0 				*pt3++ = *pt1++;	//U0 				*pt3++ = *pt0++;	//Y1 				*pt3++ = *pt2++;	//V0 			}  			pt1 = pt1 - VIDEO_WIDTH / 2; 			pt2 = pt2 - VIDEO_WIDTH / 2;  			for (k = 0; k < VIDEO_WIDTH / 2; k++)	//the row size of YUV_plane is 2*VIDEO_WIDTH 			{ 				*pt3++ = *pt0++;	//Y(WIDTH+0) 				*pt3++ = *pt1++;	//U0 				*pt3++ = *pt0++;	//Y(WIDTH+1) 				*pt3++ = *pt2++;	//V0 			}  		}  		fwrite(YUV_plane, 1, 2* VIDEO_SIZE_Y, fp_ref_422); 	} #endif	  }   

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!