一、定义

SSD:平方误差和 —— Sum of Squared Difference
MSE:均方误差 —— Mean Squared Error
SAD:绝对误差和 (时域)—— Sum of Absolute Difference
SATD:绝对误差和(频域,也可叫HAD) —— Sum of Absolute Transformed Difference
PSNR:峰值信噪比 —— Peak Signal to Noise Ratio

二、公式

假设M x N 为视频空间分辨率;
f(x,y) 为(x,y)处的原始像素值,g(x,y) 为(x,y)处的重构像素值。

python 实现失真度量值PSNR_复杂度

以上算式适用于空域,即在时域即可计算,而SATD应用于变换域。将残差信号先进行哈达玛变换到频域,设其矩阵为H

python 实现失真度量值PSNR_时域_02

计算PSNR的C++代码: 

double calculatePSNR(unsigned char* OrgC, unsigned char* PredC)
{
	double SSD =  0 ;
	double PSNR =  0 ;

	double height = BLOCKSIZE;
	double width = BLOCKSIZE;

	for (int h = 0; h < BLOCKSIZE; h++)
	{
		for (int w = 0; w < BLOCKSIZE; w++)
		{
			SSD +=  (OrgC[w + h * BLOCKSIZE] - PredC[w + h * BLOCKSIZE]) * (OrgC[w + h * BLOCKSIZE] - PredC[w + h * BLOCKSIZE]);
		}
	}
	double maxValue = 255.0 * 255.0;
	SSD = SSD /  (width * height);    
	PSNR = (SSD ? 10.0 * log10(maxValue / SSD) : 999.99);
	
	return PSNR;
}

 计算PSNR的Python代码;

def psnr1(img1, img2):
   mse = np.mean((img1/1.0 - img2/1.0) ** 2 )
   if mse < 1.0e-10:
      return 100
   return 10 * math.log10(255.0**2/mse)
 
def psnr2(img1, img2):
   mse = np.mean( (img1/255. - img2/255.) ** 2 )
   if mse < 1.0e-10:
      return 100
   PIXEL_MAX = 1
   return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))

 三、作用

SAD即绝对误差和,仅反映残差时域差异,影响PSNR值,不能有效反映码流的大小,类似的如SSD、MSE。

SATD即将残差经哈达玛变换后的残差绝对值总和,可以将其看作简单的时频变换,其值在一定程度上可以反映生成码流的大小。因此,不用率失真最优化时,可将其作为模式选择的依据。

SAD和SATD常用在视频编码的模式选择。

评价视频编码效率的有两大指标:码率PSNR。码流越小,则压缩率越大;PSNR越大,重建图像越好。在模式选择的时候,判别公式实质上也就是对二者的综合评价。

RDO是率失真代价,综合了码率和PSNR,公式为J(mode)=D+λ*R(ref,mode,mv,residual),D指的就是上述失真;λ是拉格朗日乘子;R就是该模式下宏块编码的实际码流,包括对参考帧、模式、运动矢量、残差等的比特总和。如果是帧内模式,就只有R(mode,residual)。

在帧内编码中,如果所有模式都使用J(mode)=SSD+λ*R(mode,residual)计算率失真代价,则其计算复杂度会非常高,式中SSD指的是原始像素与重构像素误差的平方和,R表示编码当前模式下所有信息(包括划分方式、预测模式编号、残差系数等)所需要的的比特数。为了减小模式选择的复杂度,H.265中使用更简单的方法计算率失真代价:

J(mode)=SATD+λ*R(mode),式中SATD即为残差的SATD,R(mode)仅为编码当前模式所需的比特数,这种方法省去了变换、量化、反量化、反变换以及熵编码的过程,极大的降低了复杂度。