MSE: 均方误差
峰值信噪比: PSNR
假定图像大小为NxN
MSE = 1/(N*N) sum((xi- x)*(xi-x))
PSNR = 10 * log10(255*255/MSE)
具体C代码如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4
5 typedef unsigned char uint8_t;
6
7 typedef struct{
8 uint8_t *y;
9 uint8_t *u;
10 uint8_t *v;
11 }image_t;
12
13 #define MALLC_AND_CHECK(p, size) p = malloc(size);/
14 if (p == NULL)/
15 {/
16 printf("malloc "#p" error/n");/
17 goto error_out;/
18 }
19
20 #define CHECK_AND_FREE(p) if (p != NULL)/
21 {/
22 free(p);/
23 }
24
25 double calc_mse(image_t *img_org, image_t *img_dec, int width, int height)
26 {
27 int i, j;
28 double sum;
29 uint8_t *py_org, *py_dec;
30 uint8_t *pu_org, *pu_dec;
31 uint8_t *pv_org, *pv_dec;
32 int diff_val;
33
34 py_org = img_org->y;
35 py_dec = img_dec->y;
36 pu_org = img_org->u;
37 pu_dec = img_dec->u;
38 pv_org = img_org->v;
39 pv_dec = img_dec->v;
40
41 sum = 0;
42 for (i = 0; i < height; i++)
43 {
44 for (j = 0; j < width; j++)
45 {
46 diff_val = *py_org - *py_dec;
47 sum += diff_val * diff_val;
48 py_org++;
49 py_dec++;
50 }
51 }
52 for (i = 0; i < height/2; i++)
53 {
54 for (j = 0; j < width/2; j++)
55 {
56 diff_val = *pu_org - *pu_dec;
57 sum += diff_val * diff_val;
58 diff_val = *pv_org - *pv_dec;
59 sum += diff_val * diff_val;
60 pu_org++;
61 pu_dec++;
62 pv_org++;
63 pv_dec++;
64 }
65 }
66 sum = sum / (3 * width * height / 2);
67 return sum;
68 }
69
70 double psnr(double mse)
71 {
72 return 10 * log10f(255.0 * 255.0 / mse);
73 }
74
75 int main(int argc, char **argv)
76 {
77 image_t *img_org;
78 image_t *img_dec;
79 int width, height;
80 FILE *fp_org;
81 FILE *fp_dec;
82 int i;
83 int ret_val;
84 int frame_cnt = 0;
85 double mse;
86 double psnr_sum = 0;
87
88 if (argc < 7)
89 {
90 printf("Not enough parameters!/n");
91 printf("/tUseage: calc_psnr -w 352 -h 288 infile1 infile2/n");
92 printf("/t-w: width/n");
93 printf("/t-h: height/n");
94 return -1;
95 }
96
97 width = 0;
98 height = 0;
99 fp_org = NULL;
100 fp_dec = NULL;
101 for (i = 1; i < 7; i++)
102 {
103 if (strcmp(argv[i], "-w") == 0)
104 {
105 width = atoi(argv[i+1]);
106 i++;
107 continue;
108 }
109 else if (strcmp(argv[i], "-h") == 0)
110 {
111 height = atoi(argv[i+1]);
112 i++;
113 continue;
114 }
115 else if (fp_org == NULL)
116 {
117 fp_org = fopen(argv[i], "rb");
118 if (fp_org == NULL)
119 {
120 printf("can't open file %s/n", argv[i]);
121 goto error_out;
122 }
123 }
124 else if (fp_dec == NULL)
125 {
126 fp_dec = fopen(argv[i], "rb");
127 if (fp_dec == NULL)
128 {
129 printf("can't open file %s./n", argv[i]);
130 goto error_out;
131 }
132 }
133 }
134
135 if (width < 0 || width > 2048)
136 {
137 printf("illeagle width!/n");
138 goto error_out;
139 }
140 if (height < 0 || height > 2048)
141 {
142 printf("illedgle height!/n");
143 goto error_out;
144 }
145
146 MALLC_AND_CHECK(img_org, sizeof(image_t));
147 MALLC_AND_CHECK(img_dec, sizeof(image_t));
148 MALLC_AND_CHECK(img_org->y, width*height);
149 MALLC_AND_CHECK(img_org->u, width*height/4);
150 MALLC_AND_CHECK(img_org->v, width*height/4);
151 MALLC_AND_CHECK(img_dec->y, width*height);
152 MALLC_AND_CHECK(img_dec->u, width*height/4);
153 MALLC_AND_CHECK(img_dec->v, width*height/4);
154
155 while (1)
156 {
157 ret_val = fread(img_org->y, 1, width * height, fp_org);
158 if (ret_val != width * height)
159 {
160 break;
161 }
162 ret_val = fread(img_org->u, 1, width * height / 4, fp_org);
163 if (ret_val != width * height / 4)
164 {
165 break;
166 }
167 ret_val = fread(img_org->v, 1, width * height /4, fp_org);
168 if (ret_val != width * height / 4)
169 {
170 break;
171 }
172 ret_val = fread(img_dec->y, 1, width * height, fp_dec);
173 if (ret_val != width * height)
174 {
175 break;
176 }
177 ret_val = fread(img_dec->u, 1, width * height / 4, fp_dec);
178 if (ret_val != width * height / 4)
179 {
180 break;
181 }
182 ret_val = fread(img_dec->v, 1, width * height /4, fp_dec);
183 if (ret_val != width * height / 4)
184 {
185 break;
186 }
187 frame_cnt++;
188 mse = calc_mse(img_org, img_dec, width, height);
189 psnr_sum += psnr(mse);
190 }
191 printf("frame_cnt = %d./n", frame_cnt);
192 printf("average psnr = %f/n", psnr_sum/frame_cnt);
193
194 error_out:
195 if (fp_org != NULL)
196 {
197 fclose(fp_org);
198 }
199 if (fp_dec != NULL)
200 {
201 fclose(fp_dec);
202 }
203
204 CHECK_AND_FREE(img_org->y);
205 CHECK_AND_FREE(img_org->u);
206 CHECK_AND_FREE(img_org->v);
207 CHECK_AND_FREE(img_dec->y);
208 CHECK_AND_FREE(img_dec->u);
209 CHECK_AND_FREE(img_dec->v);
210 CHECK_AND_FREE(img_org);
211 CHECK_AND_FREE(img_dec);
212
213 return 0;
214 }
215