14  位图与计算机图像存储

14.1 什么是位图?

位图(Bitmap)是计算机中存储图像的一种基本格式。在这种格式中,图像被分割成一个个小方格(像素),每个方格用二进制数字来存储颜色信息。

14.1.1 计算机如何存储位图?

  1. 存储结构
    • 计算机使用二进制(0和1)存储所有数据
    • 位图将图像分解成规则的网格,每个网格点就是一个像素
    • 每个像素占用固定的存储空间(比特数)
  2. 常见的位图格式
    • BMP:最基本的位图格式
    • PNG:支持无损压缩的位图格式
    • JPEG:支持有损压缩的图片格式
  3. 不同类型图片的存储方式
import numpy as np
import matplotlib.pyplot as plt

# 1. 黑白图片(1位/像素)
bw_image = np.zeros((10, 10))  # 只用0和1表示
bw_image[2:8, 2:8] = 1

# 2. 灰度图片(8位/像素)
gray_image = np.zeros((10, 10))
gray_image[2:8, 2:8] = 128  # 0-255之间的值

# 3. 彩色图片(24位/像素 = 3×8位)
color_image = np.zeros((10, 10, 3))  # 3个通道:红、绿、蓝
color_image[2:8, 2:8, 0] = 1  # 红色通道

# 创建一个包含3个子图的图表
plt.figure(figsize=(15, 5))

# 显示黑白图像
plt.subplot(1, 3, 1)
plt.imshow(bw_image, cmap='binary')
plt.title('Black and White Image')
plt.axis('off')  # 关闭坐标轴

# 显示灰度图像
plt.subplot(1, 3, 2)
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')

# 显示彩色图像
plt.subplot(1, 3, 3)
plt.imshow(color_image)
plt.title('Color Image (Red)')
plt.axis('off')

# 调整子图之间的间距
plt.tight_layout()

# 显示图表
plt.show()

14.2 手写数字图像示例

让我们通过实际的手写数字图像来理解位图:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits

# 加载手写数字数据集
digits = load_digits()
X = digits.images  # 图像数据
y = digits.target  # 标签(实际的数字)

# 选择第一个数字作为示例
sample = X[0]

# 展示图像及其矩阵值
plt.figure(figsize=(10, 4))
plt.subplot(121)
plt.imshow(sample, cmap='gray')
plt.title(f'Handwritten Digit: {y[0]}')

plt.subplot(122)
plt.imshow(sample[2:6, 2:6], cmap='gray')
plt.title('Local Matrix (4x4)')
plt.colorbar()
plt.show()

print("图像局部(4x4区域)的实际矩阵值:")
print(sample[2:6, 2:6])

图像局部(4x4区域)的实际矩阵值:
[[15.  2.  0. 11.]
 [12.  0.  0.  8.]
 [ 8.  0.  0.  9.]
 [11.  0.  1. 12.]]

14.3 理解图像矩阵

在这个数据集中: - 每个图像是 8×8 像素的矩阵 - 每个像素值范围是 0-16: - 0 表示最暗(黑色) - 16 表示最亮(白色) - 中间值表示不同程度的灰色

14.4 基本图像处理示例

让我们看看一些简单的矩阵运算如何改变图像:

plt.figure(figsize=(15, 3))

# 原始图像
plt.subplot(141)
plt.imshow(sample, cmap='gray')
plt.title('Original Image')

# 水平翻转
plt.subplot(142)
flipped = np.fliplr(sample)  # 矩阵左右翻转
plt.imshow(flipped, cmap='gray')
plt.title('Horizontal Flip')

# 旋转90度
plt.subplot(143)
rotated = np.rot90(sample)  # 矩阵旋转
plt.imshow(rotated, cmap='gray')
plt.title('Rotate 90°')

# 增加亮度
plt.subplot(144)
brighter = np.clip(sample * 1.5, 0, 16)  # 所有值乘以1.5
plt.imshow(brighter, cmap='gray')
plt.title('Brightness ×1.5')

plt.show()

print("让我们看看这些操作如何改变矩阵的值:")
local_area = sample[2:6, 2:6]
print("\n原始区域的矩阵值:")
print(local_area)
print("\n增加亮度后的矩阵值(×1.5):")
print(np.clip(local_area * 1.5, 0, 16))

让我们看看这些操作如何改变矩阵的值:

原始区域的矩阵值:
[[15.  2.  0. 11.]
 [12.  0.  0.  8.]
 [ 8.  0.  0.  9.]
 [11.  0.  1. 12.]]

增加亮度后的矩阵值(×1.5):
[[16.   3.   0.  16. ]
 [16.   0.   0.  12. ]
 [12.   0.   0.  13.5]
 [16.   0.   1.5 16. ]]

14.5 多个数字示例

让我们看看不同的手写数字是如何存储的:

# 显示前5个数字
plt.figure(figsize=(15, 3))
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(X[i], cmap='gray')
    plt.title(f'Digit: {y[i]}')
    plt.axis('off')
plt.show()

14.6 小结

  1. 图像在计算机中是以数字矩阵的形式存储的
  2. 每个像素对应矩阵中的一个数字:
    • 数字越大,像素越亮
    • 数字越小,像素越暗
  3. 图像处理实际上就是对矩阵进行数学运算:
    • 翻转矩阵 = 翻转图像
    • 旋转矩阵 = 旋转图像
    • 矩阵数值变化 = 图像亮度变化
  4. 这种表示方法让计算机能够:
    • 存储图像信息
    • 处理图像
    • 识别图像内容