【开源项⽬经验】之计算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;
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 *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:
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 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;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论