DPCM编码原理及代码实现

本文详细介绍了DPCM编码的工作原理,包括基于预测的编码方式,以及通过C++代码实现的DPCM编码器和解码器。通过实例展示了如何压缩和重构图像,并计算了PSNR作为质量评估指标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、DPCM编码

DPCM编码,英文名称Differential pulse-code modulation,是一种信号编码器,它以脉冲编码调制(PCM)为基础,基于信号样本的预测添加了一些功能。DPCM的输入信号可以是模拟信号,也可以是数字信号。

二、DPCM编码原理

DPCM并不是对每个抽样值进行独立编码,而是对根据前一个抽样值的预测值与当前抽样值的差值进行编码。因为相邻抽样值之间相关性较大,因此预测值与抽样值会很接近,其差值也会很小,因此对这个小的差值进行编码可以很有效的压缩数据量。

三、DPCM编码器

DPCM编码器:

image-20220710173716771

四、DPCM解码器

DPCM解码器:

image-20220710173936471

五、DPCM代码实现

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
int main()
{
	unsigned int width = 256;
	unsigned int height = 256;
	
	// 读取文件 
	char *yuvtest = NULL;
	char *newyuvtest = NULL;
	FILE* yuvFile = NULL;
	FILE* newyuvFile = NULL;
	char *pname = NULL;
	FILE* pFile = NULL;
    
    unsigned char* yuvbuffer = NULL;
	unsigned char* ubuffer = NULL;
	unsigned char* vbuffer = NULL;
    unsigned char * pbuffer = NULL;
	float* dbuffer = NULL;
	unsigned char* rbuffer = NULL;
    
	yuvtest = "···/test.yuv";
	newyuvtest = "···/testrebuild.yuv";
	pname= "···/error.yuv";
	yuvFile = fopen(yuvtest, "rb");
	if (!yuvFile)
		printf("YUV测试文件打开失败\n");
	else
		printf("成功打开YUV测试文件\n");
	newyuvFile = fopen(newyuvtest, "wb");
	if (!newyuvFile)
		printf("重建YUV文件打开失败\n");
	else
		printf("重建YUV文件打开成功\n");
	pFile = fopen(pname, "wb");
	if (!pFile)
		printf("误差文件打开失败\n");
	else
		printf("误差文件打开成功\n");
		
	
	yuvbuffer = (unsigned char*)malloc(width*height);
	ubuffer = (unsigned char*)malloc(width*height / 4);
	vbuffer = (unsigned char*)malloc(width*height / 4);
	pbuffer = (unsigned char*)malloc(width*height);//预测误差的量化值
	rbuffer = (unsigned char*)malloc(width*height);//重现图像
	dbuffer = (float*)malloc(width*height*4);//输入预测误差
	unsigned char* dobuffer = (unsigned char*)malloc(width*height * 4);
	
	if (yuvbuffer == NULL || ubuffer == NULL || vbuffer == NULL || pbuffer == NULL)
	{
		printf("ERROR");
	}
 
	fread(yuvbuffer, 1, width * height * 1, yuvFile);
 
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (j == 0) {
				pbuffer[i*width + j] = 0;
				rbuffer[i*width + j] = yuvbuffer[i*width + j];
				dbuffer[i*width + j] = 0;
			}
			else {
				dbuffer[(i*width + j)] = float(yuvbuffer[i*width + j]) - float(rbuffer[i*width + j - 1]);
				if (dbuffer[ (i*width + j)] >= 0) {
					pbuffer[i*width + j] = floor(dbuffer[(i*width + j)] + 0.5);
					rbuffer[i*width + j] = rbuffer[i*width + j - 1] + pbuffer[i*width + j] * 1;
				}
				else {
					pbuffer[i*width + j] = floor(fabs(float(dbuffer[i*width + j]) + 0.5));
					rbuffer[i*width + j] = rbuffer[i*width + j - 1] - pbuffer[i*width + j] * 1;
				}
			}
		}
	}
    
    //计算误差
	int sum=0;
	for (int i = 0; i < height; i++) {
 
		for (int j = 0; j < width; j++) {
			sum += abs(pbuffer[i*width + j]);
		}
	}
	float MSE = float(sum) / float(width*height);
	float PSNR = 10 * log10(65025 / MSE);
	printf("PSNR=%f", PSNR);
	
	// 写入重建YUV文件和预测误差文件 
	for (int i = 0; i < width*height / 4; i++) {
		ubuffer[i] = 128;
		vbuffer[i] = 128;
	}
	fwrite(rbuffer, 1, width*height, newyuvFile);
	fwrite(ubuffer, 1, width*height / 4, newyuvFile);
	fwrite(vbuffer, 1, width*height / 4, newyuvFile);
	
	for (int i = 0; i < width*height ; i++) {
		dobuffer[i] = (unsigned char)(dbuffer[i])+128;
	}
	fwrite(dobuffer, 1, width*height, pFile);
	fwrite(ubuffer, 1, width*height / 4, pFile);
	fwrite(vbuffer, 1, width*height / 4, pFile);
	
	fclose(newyuvFile);
	fclose(yuvFile);
	fclose(pFile);
 
	return 0;
}

六、代码结果

原图像:

image-20220712092334820

重建图像:

image-20220712092441014

误差图像:

image-20220712092734180

### 使用Simulink实现DPCM编码解码系统的设计与仿真 #### 模型建立 在构建DPCM(差分脉冲编码调制)系统时,需创建一个能够处理输入信号并执行预测、量化和反量化的模型。此过程涉及多个模块间的交互。 1. **信号源** 创建一个正弦波发生器作为测试信号源,设定幅度为1,频率为1Hz,即 \(x(t)=\sin(2 \pi f t)\)[^2]。这可以通过`Sine Wave`模块完成配置。 2. **延迟单元** 添加一个单位延迟(`Unit Delay`)用于存储前一时刻的样本值以便计算当前样本与其之差。 3. **减法运算** 利用`Subtract`模块连接至上述两个组件间,以获取相邻样本之间的差异。 4. **量化器** 插入自定义或内置的量化函数来逼近实际硬件行为;对于非均匀量化可采用特定算法如A律压缩特性[^1]。 5. **逆量化器** 构造相应的去量化环节恢复原始电平范围内的数值表示形式。 6. **加法器** 将重建后的增量加上先前重构出的声音片段重现完整的音频流。 7. **显示设备** 运用`Scope`工具实时观察各阶段输出变化情况,并最终比较初始输入同经过整个链路传递后得到的结果是否一致。 8. **反馈路径** 设立一条从输出端返回到输入侧适当位置处形成闭环结构,确保每次迭代都能基于最新估计调整后续操作。 ```matlab % MATLAB脚本示例:初始化参数及绘制图形 f = 1; % 频率(Hz) t = linspace(0, 2*pi*f*1e-3, 100); % 时间向量(ms级时间轴上取点) original_signal = sin(2 * pi * f .* t); figure; subplot(3, 1, 1); plot(t, original_signal,'b'); title('Original Signal'); % 假设此处已运行过一次完整流程... reconstructed_signal = ... ; % 来源于scope捕获的数据或其他方式保存下来的变量名 subplot(3, 1, 3); plot(t, reconstructed_signal,'r'); title('Reconstructed Signal After DPCM Process'); ``` #### 参数设置 针对不同应用场景下的需求优化各项属性: - 调整`Quantizer`内部参数控制精度损失程度; - 修改`Predictor`逻辑适应不同类型的时间序列特征; - 设置合适的缓冲区大小平衡速度与资源占用关系。 #### 性能分析方法和技术 为了评估所搭建架构的有效性和可靠性,可以采取如下措施: - 计算信噪比(SNR),衡量噪声干扰水平; - 统计误码率(BER),反映通信质量好坏; - 对比频谱分布曲线判断失真状况; - 应用统计学检验手段确认两者相似度达到预期标准。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值