【开源项目经验】之计算PSNR

1、计算PNSR

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <math.h> 
 

//计算MSE及PSNR
float cal_psnr(unsigned char *yuv0, unsigned char *yuv1, int stride_yuv0, int stride_yuv1, int width, int height)
{
	int i, j;
	double diff;
	double diff_sum = 0.0;
	unsigned int max_pix_value_sqd[3] = {255*255, 255*255, 255*255};
	
	for(j = 0; j < height; j++)
	{
		for (i = 0; i < width; i++)
		{
			diff = *(yuv0 + j * stride_yuv0 + i) - *(yuv1 + j * stride_yuv1 + i);
			diff_sum += diff * diff;
		}
	}
	return (float)(diff_sum  == 0.0 ? 100.0:(10.0 * log10(max_pix_value_sqd[0] * (double)((double)(width * height) / diff_sum))));
}


//src0.yuv width height src1.yuv
int main(int argc, char **argv)
{
	FILE *pYUVSrc0, *pYUVSrc1;
	FILE *pYUVDst0, *pYUVDst1;
	unsigned char *u8YUVSrc0, *u8YUVSrc1;
	
	int ret;
	int frameIdx = 0;
	int iwidth, iheight, iframeSize;
	double psnr[3] = {0.0, 0.0, 0.0};
	char dstYUVName[2][256];
	
	iwidth  = atoi(argv[2]);	//YUV文件的宽
	iheight = atoi(argv[3]);	//YUV文件的高
	iframeSize = iwidth * iheight * 3 / 2; //YUV的一帧大小

	pYUVSrc0 = fopen(argv[1], "rb"); //打开输入YUV文件1
	pYUVSrc1 = fopen(argv[4], "rb"); //打开输入YUV文件2


	u8YUVSrc0 = (unsigned char*)malloc(iframeSize * sizeof(unsigned char));
	u8YUVSrc1 = (unsigned char*)malloc(iframeSize * sizeof(unsigned char));

	sprintf(&dstYUVName[0][0], "%s%s", argv[1], "_onlyY.yuv");
	sprintf(&dstYUVName[1][0], "%s%s", argv[2], "_onlyY.yuv");

	pYUVDst0 = fopen(dstYUVName[0], "wb"); //打开输出YUV文件1
	pYUVDst1 = fopen(dstYUVName[1], "wb"); //打开输出YUV文件2

	while(1)
	{
		ret = fread(u8YUVSrc0, 1, iframeSize, pYUVSrc0);
		if(ret == 0){ //等于0,表示YUV0文件已经读完了
			break;
		} 
		ret = fread(u8YUVSrc1, 1, iframeSize, pYUVSrc1);
		if(ret == 0){ //等于0,表示YUV1文件已经读完了
			break;
		} 
		psnr[0] = cal_psnr(u8YUVSrc0, u8YUVSrc1, iwidth, iwidth, iwidth, iheight); //Y
		psnr[1] = cal_psnr(u8YUVSrc0 + iwidth * iheight, u8YUVSrc1 + iwidth * iheight, iwidth / 2, iwidth / 2, iwidth / 2, iheight / 2); //U
		psnr[2] = cal_psnr(u8YUVSrc0 + iwidth * iheight * 5 / 4, u8YUVSrc1 + iwidth * iheight * 5 / 4, iwidth / 2, iwidth / 2, iwidth / 2, iheight / 2); //V	
		
		memset(u8YUVSrc0 + iwidth * iheight, 0, iwidth * iheight / 2 * sizeof(unsigned char));
		memset(u8YUVSrc1 + iwidth * iheight, 0, iwidth * iheight / 2 * sizeof(unsigned char));
		fwrite(u8YUVSrc0, 1, iframeSize, pYUVDst0);
		fwrite(u8YUVSrc1, 1, iframeSize, pYUVDst1);
		printf("Frame Idx: %d Y-PSNR: %4.3f , U-PSNR: %4.3f, V-PSNR: %4.3f\n", frameIdx++, psnr[0],  psnr[1],  psnr[2]);
	}
	fclose(pYUVSrc0);
	fclose(pYUVSrc1);
	fclose(pYUVDst1);
	fclose(pYUVDst1);
	free(u8YUVSrc0);
	free(u8YUVSrc1);	
}

2、YUV420上采样

/*  
* File:        scale.c  
* Description: scale YUV420 video frames with cubic, bilinear & cubic convolution interpolation algorithms  
*              highly optimized algorithm  
*/   
   
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <math.h> 
  
#define ABS(x) (x > 0 ? (x) : (-x))  
#define clip(a, min, max) (a > max ? max : (a > min ? a : min))  
#define INTEGER 1  
#define NO_CB	1//色度分量直接赋值为0
  

int gcd(int a, int b)  
{  
    if(b)   
    {  
        return gcd(b, a%b);  
    }  
    else    
    {  
        return a;  
    }  
}  
  

  
int scale(unsigned char algorithm,  
           int input_pixel_format,   
           unsigned char *pYIn, int lineY,   
           unsigned char *pCbIn, int lineCb,   
           unsigned char *pCrIn, int lineCr,   
           int srcWidth, int srcHeight,   
           int outWidth, int outHeight,  
           int output_pixel_format,   
           unsigned char *pYOut,   
           unsigned char *pCbOut,   
           unsigned char *pCrOut)  
{  
    float rx = (float)outWidth/(float)srcWidth;  
    float ry = (float)outHeight/(float)srcHeight;  
    int x = 0, y = 0;  
    int xx = 0, yy = 0;  
    int outWidth_cr = outWidth / 2;  
    int outHeight_cr = outHeight / 2;  
    int srcWidth_cr = srcWidth / 2;  
    int srcHeight_cr = srcHeight / 2;  
    float c0, c1, c2, c3;  

    unsigned char *p = NULL, *p1 = NULL;  
  
    int *C0=NULL, *C1=NULL, *C2=NULL, *C3=NULL;  
    unsigned char* pend = pYIn + lineY * srcHeight - 1;  
      
    int x_ratio = (int) (((srcWidth - 1) << 8) / outWidth);  
    int y_ratio = (int) (((srcHeight - 1) << 8) / outHeight);   
  
    // Rational ratio  
    int gcdw = gcd(outWidth, srcWidth);  
    int gcdh = gcd(outHeight, srcHeight);  
    int rx_num = outWidth/gcdw;  
    int rx_den = srcWidth/gcdw;  
    int ry_num = outHeight/gcdh;  
    int ry_den = srcHeight/gcdh;  
  
    switch(algorithm)  
    {  
        case 0:  
            // cubic  
            for(y=0; y<outHeight; y++)  
            {  
                for(x=0; x<outWidth; x++)  
                {  
                    //g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)  
                    xx = clip((int)((float)x / rx), 0, srcWidth-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight-1);  
                    pYOut[y*outWidth+x] = pYIn[yy*lineY + xx];  
                }  
            }  
            for(y=0; y<outHeight_cr; y++)  
            {  
                for(x=0; x<outWidth_cr; x++)  
                {  
                    //g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)  
                    xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight_cr-1);  
                    pCbOut[y*outWidth_cr+x] = pCbIn[yy*lineCb + xx];  
                }  
            }  
            for(y=0; y<outHeight_cr; y++)  
            {  
                for(x=0; x<outWidth_cr; x++)  
                {  
                    //g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)  
                    xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight_cr-1);  
					pCrOut[y*outWidth_cr+x] = pCrIn[yy*lineCr + xx];  
                }  
            }  
            break;  
        case 1:  
            // bilinear  
            for(y=0; y<outHeight; y++)  
            {  
                for(x=0; x<outWidth; x++)  
                {  
                    //g(x, y) = (1-c0)(1-c2)f(xx,yy) + (1-c2)(1-c1)f(xx,yy+1) + (1-c1)(1-c3)f(xx+1,yy) + (1-c0)(1-c3)f(xx+1,yy+1)  
                    c0 = (((float)y / ry) - (int)((float)y / ry));  
                    c1 = ((int)((float)y / ry) + 1 - ((float)y / ry));  
                    c2 = (((float)x / rx) - (int)((float)x / rx));  
                    c3 = ((int)((float)x / rx) + 1 - ((float)x / rx));  
                    xx = clip((int)((float)x / rx), 0, srcWidth-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight-1);  
                    pYOut[y*outWidth+x] = (float)((1.0-c0)*(1.0-c2)*pYIn[yy*lineY+xx]   
                                                + (1.0-c1)*(1.0-c2)*pYIn[clip(yy+1,0,srcHeight-1)*lineY+xx]   
                                                + (1.0-c1)*(1.0-c3)*pYIn[yy*lineY+clip(xx,0,srcWidth-1)]  
                                                + (1.0-c0)*(1.0-c3)*pYIn[clip(yy+1,0,srcHeight-1)*lineY+clip(xx,0,srcWidth-1)]);  
                }  
            }  
            for(y=0; y<outHeight_cr; y++)  
            {  
                for(x=0; x<outWidth_cr; x++)  
                {  
                    c0 = (((float)y / ry) - (int)((float)y / ry));  
                    c1 = ((int)((float)y / ry) + 1 - ((float)y / ry));  
                    c2 = (((float)x / rx) - (int)((float)x / rx));  
                    c3 = ((int)((float)x / rx) + 1 - ((float)x / rx));  
                    xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight_cr-1); 
                    pCbOut[y*outWidth_cr+x] = (float)((1.0-c0)*(1.0-c2)*pCbIn[yy*lineCb+xx]   
                                                + (1.0-c1)*(1.0-c2)*pCbIn[clip(yy+1,0,srcHeight_cr-1)*lineCb+xx]   
                                                + (1.0-c1)*(1.0-c3)*pCbIn[yy*lineCb+clip(xx,0,srcWidth_cr-1)]  
                                                + (1.0-c0)*(1.0-c3)*pCbIn[clip(yy+1,0,srcHeight_cr-1)*lineCb+clip(xx,0,srcWidth_cr-1)]); 
                }  
            }  
            for(y=0; y<outHeight_cr; y++)  
            {  
                for(x=0; x<outWidth_cr; x++)  
                {  
                    c0 = (((float)y / ry) - (int)((float)y / ry));  
                    c1 = ((int)((float)y / ry) + 1 - ((float)y / ry));  
                    c2 = (((float)x / rx) - (int)((float)x / rx));  
                    c3 = ((int)((float)x / rx) + 1 - ((float)x / rx));  
                    xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);  
                    yy = clip((int)((float)y / ry), 0, srcHeight_cr-1);  
                    pCrOut[y*outWidth_cr+x] = (float)((1.0-c0)*(1.0-c2)*pCrIn[yy*lineCr+xx]   
                                                + (1.0-c1)*(1.0-c2)*pCrIn[clip(yy+1,0,srcHeight_cr-1)*lineCr+xx]   
                                                + (1.0-c1)*(1.0-c3)*pCrIn[yy*lineCr+clip(xx,0,srcWidth_cr-1)]  
                                                + (1.0-c0)*(1.0-c3)*pCrIn[clip(yy+1,0,srcHeight_cr-1)*lineCr+clip(xx,0,srcWidth_cr-1)]);  
                }  
            }  
            break;  
        default:  
            printf("Not supported scaling algorithm\n");  
            return -1;  
    }    
      
    return 0;  
}  
int main(int argc, char** argv)  
{  
    int w, h, tw, th;  
    FILE* fin=NULL, *fout=NULL;  
    unsigned char* src=NULL;  
    unsigned char* dst=NULL;  
    int algorithm = 0; 
    int frameidx = 0; 
  
    if(argc != 8)  
    {  
        printf("Usage: <%s> <in file> <out file> <src width> <src height> <target width> <target height> <algorithm>\n", argv[0]);  
        printf("Algorithm list: 0--cubic, 1--bilinear\n");  
        return -1;  
    }  
  
    fin = fopen(argv[1], "rb");  
    fout = fopen(argv[2], "wb");  
    if(!fin || !fout)  
    {  
        printf("File Open Fail!\n");  
        return -1;  
    }  
    w = atoi(argv[3]);  
    h = atoi(argv[4]);  
    tw = atoi(argv[5]);  
    th = atoi(argv[6]);  
    algorithm = atoi(argv[7]);  
    src = (unsigned char*)malloc(w*h*3/2);  
    dst = (unsigned char*)malloc(tw*th*3/2);  
    memset(dst, 0, tw*th);  
    memset(dst, 0, tw*th/2);  
   
    fseek(fin, 0, SEEK_SET);  
    while( fread(src, 1, w*h*3/2, fin)!= 0)
   {
       // scale   
       scale(algorithm, 420, src, w, src+w*h, w/2, src+w*h*5/4, w/2, w, h, tw, th, 420, dst, dst+tw*th, dst+tw*th*5/4);  
  
       fwrite(dst, 1, tw*th*3/2, fout); 
       printf("%d successful\n", frameidx++);
   }
 
    if(fin)fclose(fin);  
    if(fout)fclose(fout);  
    if(src)free(src);  
    if(dst)free(dst);  
    return 0;  
}  

摘抄网址:http://read.pudn.com/downloads505/sourcecode/graph/texture_mapping/2100905/scale.c__.htm

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值