在数字图像处理领域,图像压缩是一个永恒的话题,我们常常需要在保证图像质量的前提下,尽可能地减小文件大小,以节省存储空间、加快网络传输速度,除了常见的JPEG、PNG等有损或无损压缩格式外,从图像数据本身的位深度入手进行压缩,是一种简单而高效的精简方法,本文将详细介绍如何利用MATLAB中的bitget函数,通过降低图像位深度来实现图像压缩,并探讨其原理、实现步骤与效果。
在开始之前,我们首先要理解两个核心概念:

位深度:位深度指的是存储一个像素点颜色所使用的二进制位数,位数越多,能表示的颜色范围就越广,图像色彩层次就越丰富,常见的位深度有:
图像压缩:图像压缩的目的是减少表示图像所需的数据量,它分为两类:
我们今天要讨论的位深度压缩,本质上是一种有损压缩,通过减少表示像素的位数,我们直接丢弃了最低位的颜色信息,从而减小了图像的数据量。
bitget函数MATLAB的bitget函数是实现位深度压缩的关键,它的作用是从一个整数中提取指定位的值。
语法: c = bitget(A, bit)
参数说明:
A:输入的整数数组(在我们的场景中,就是图像矩阵)。bit:要提取的位的位置,从1(最低位)到最高位。返回值:

c:一个与A大小相同的数组,其元素是A中对应元素指定位的值(0或1)。简单示例: 假设我们有一个像素值 A = 200(二进制为 11001000)。
bitget(200, 1) 提取最低位,得到 0。bitget(200, 8) 提取最高位,得到 1。bitget函数就像一个精密的“数字镊子”,能精准地操作图像数据中的每一位,这正是我们进行位深度压缩的基础。
bitget进行图片压缩的步骤下面我们通过一个具体的例子,将一幅标准的24位彩色图(每个通道8位)压缩到4位,来演示整个流程。
第一步:读取原始图像
我们使用imread函数读取一张图片,为了清晰展示效果,我们选择一张色彩丰富的图片。
% 读取原始图像
original_img = imread('peppers.png');
% 假设原始图像是 uint8 类型,每个通道8位
% 显示原始图像
figure;
subplot(1, 2, 1);
imshow(original_img);'原始图像 (8-bit per channel)');
第二步:确定目标位深度并进行数据截断
假设我们的目标是将每个颜色通道从8位压缩到4位,这意味着我们只需要保留原始8位数据中的高4位,而丢弃低4位。

如何实现?我们可以利用bitget提取高4位(即第5位到第8位),然后将它们重新组合成一个4位的整数。
% 目标位深度 target_bits = 4; % 提取高4位 (第5, 6, 7, 8位) % 注意:bit的位置从1开始计数 high_4_bit = bitget(original_img, 8:-1:8-target_bits 1); % 将逻辑数组 (true/false) 转换为 double (0/1) high_4_bit = double(high_4_bit); % 将4位数据重新组合成一个整数 % [b8, b7, b6, b5] -> b8*8 b7*4 b6*2 b5*1 compressed_img = uint8(high_4_bit(:,:,1) * 2^3 high_4_bit(:,:,2) * 2^2 high_4_bit(:,:,3) * 2^1 high_4_bit(:,:,4) * 2^0);
代码解释:
bitget(original_img, 8:-1:8-target_bits 1):一次性提取了每个像素值的高4位。8:-1:5 表示从第8位提取到第5位。double(high_4_bit):bitget返回的是逻辑类型(logical),我们需要将其转换为double类型以便进行后续的数学运算。compressed_img = ...:这一步是核心,我们将提取出的4个位(现在它们是0或1的矩阵)通过加权求和的方式,重新组合成一个0到15之间的整数,如果高4位是1101,计算结果就是 1*8 1*4 0*2 1*1 = 13。第三步:显示并比较结果
我们将原始图像和压缩后的图像放在一起进行对比。
% 显示压缩后的图像
subplot(1, 2, 2);
imshow(compressed_img);['压缩图像 (', num2str(target_bits), '-bit per channel)']);
% 计算压缩率
original_size = numel(original_img); % 像素总数
compressed_size = numel(compressed_img);
compression_ratio = (1 - compressed_size / original_size) * 100;
fprintf('原始图像大小: %d 像素\n', original_size);
fprintf('压缩后图像大小: %d 像素\n', compressed_size);
fprintf('数据量减少了: %.2f%%\n', compression_ratio);
效果分析: 运行上述代码,你会发现压缩后的图像出现了明显的色带或轮廓效应,这是因为从256个级别锐减到16个级别,色彩过渡不再平滑,图像的主体结构和内容依然可辨,控制台会输出压缩率,对于从8位到4位的压缩,数据量正好减少了一半(50%)。
为了方便重复使用,我们可以将上述逻辑封装成一个函数。
function compressed_img = compress_image_by_bits(original_img, target_bits)
% COMPRESS_IMAGE_BYBITS 通过降低位深度来压缩图像
% compressed_img = compress_image_bybits(original_img, target_bits)
% 将原始图像的每个通道压缩到 target_bits 位。
% 检查输入有效性
if ~ismember(class(original_img), {'uint8', 'uint16'})
error('输入图像必须是 uint8 或 uint16 类型。');
end
if target_bits <= 0 || target_bits >= 16
error('目标位深度应在1到15之间。');
end
% 获取原始位深度
original_bits = intmax(class(original_img)); % 对于uint8是255, uint16是65535
% 提取目标的高位
bits_to_get = original_bits:-1:original_bits-target_bits 1;
high_bits = bitget(original_img, bits_to_get);
% 转换并重组
high_bits = double(high_bits);
weights = 2.^(target_bits-1:-1:0);
% 对每个通道进行计算
if size(high_bits, 3) == 1 % 灰度图
compressed_img = uint8(sum(high_bits .* weights, 3));
else % 彩色图
compressed_img = uint8(sum(high_bits .* weights, 4));
end
end
使用这个函数非常简单:
% 使用通用函数进行压缩 compressed_img_5bit = compress_image_by_bits(original_img, 5); figure; imshow(compressed_img_5bit);['压缩图像 (5-bit per channel)']);
利用bitget函数进行位深度压缩,是MATLAB中一种非常直观且强大的图像处理技巧,它的优点在于: