计算机如何"看"图:像素、通道与张量
这是什么:计算机视觉(CV) = 让机器"看图"并认出货物的本事;图片在人眼里是画面,在机器眼里是一张巨大的数字表格。
为什么用:恭喜从 机器学习 毕业!你已经知道"模型从数据里学规律"。从这一章起进入图像识别——不懂像素和通道,后面的 CNN 和预训练模型全都无从下手。
如何用:本章先手算一遍灰度,再用 Pillow 造一张 2×2 的迷你图,把像素和通道一个个读出来。
图片 = 数字矩阵
把一张图片放大到极限,会看到一格一格的小方块,这就是像素(pixel)。每个像素本质是一个数字:0 是纯黑,255 是纯白。一张 1920×1080 的照片,就是 1920 行 × 1080 列的数字表格,约 200 万个数。计算机"看图",就是在读这张表。
RGB:三个通道叠出彩色
彩色照片的每个像素不是一个数,而是三个数:红(R)、绿(G)、蓝(B)各一个 0~255 的值。三种光按不同比例混合,能叠出人眼可见的几乎所有颜色:
- (255, 0, 0) → 纯红
- (0, 255, 0) → 纯绿
- (0, 0, 255) → 纯蓝
- (255, 255, 0) → 红 + 绿 → 黄色
- (255, 0, 255) → 红 + 蓝 → 品红
- (0, 255, 255) → 绿 + 蓝 → 青色
- (255, 255, 255) → 白
- (0, 0, 0) → 黑
每个数各占一路,就叫通道(channel):彩色图有 3 通道,黑白照片只有 1 通道。
灰度图:从三层压成一层
灰度图把 RGB 按人眼敏感度压成一个亮度值:
灰度 = 0.299×R + 0.587×G + 0.114×B
人眼对绿色最敏感,所以绿权重最大。很多识别任务第一步就是转灰度,先去掉颜色干扰。
手算一遍灰度
像素 (255, 0, 0) 纯红:
- 灰度 = 0.299 × 255 + 0.587 × 0 + 0.114 × 0 = 76.245 ≈ 76
像素 (0, 255, 0) 纯绿:
- 灰度 = 0.299 × 0 + 0.587 × 255 + 0.114 × 0 = 149.685 ≈ 150
纯绿看起来比纯红更亮,符合人眼直觉。
亲手读一读像素
光说不练假把式。先安装 Pillow(Python 最常用的图像库):
pip install pillow
然后造一张 2×2 像素的迷你图,再把它的数值读出来:
from PIL import Image
# 造一张 2x2 的图:左上红、右上绿、左下蓝、右下白
img = Image.new("RGB", (2, 2))
img.putpixel((0, 0), (255, 0, 0))
img.putpixel((1, 0), (0, 255, 0))
img.putpixel((0, 1), (0, 0, 255))
img.putpixel((1, 1), (255, 255, 255))
print(img.size) # 尺寸:宽 2、高 2
print(img.getpixel((0, 0))) # 读左上角像素
print(img.getpixel((1, 1))) # 读右下角像素
gray = img.convert("L") # 转灰度(L 即亮度)
print(gray.getpixel((0, 0))) # 红色像素的灰度值
print(gray.getpixel((1, 1))) # 白色像素的灰度值
你会看到(输出为示意):
(2, 2)
(255, 0, 0)
(255, 255, 255)
76
255
红色 (255, 0, 0) 按公式算灰度:0.299 × 255 ≈ 76,对上了!
分辨率与归一化
真实任务里还会做两件事:
- 统一分辨率:模型要求输入尺寸一致(常见 224×224),图片先被缩放。分辨率越大细节越多,但计算量也成倍上涨
- 归一化:把 0~255 除以 255 压到 0~1。数值变小、范围统一,模型学得更快更稳
最后把"一批图片"摞在一起——张数 × 通道 × 高 × 宽——就得到 AI 里天天出现的高维数组:张量(tensor)。ML 章节里数据是表格,到了 CV,数据变成了张量。
| 概念 | 含义 | 例子 |
|---|---|---|
| 像素 | 图片最小单元,本质是数字 | (255, 0, 0) 是纯红 |
| 通道 | 颜色分量数:灰度 1 个、彩色 3 个 | RGB 三通道 |
| 分辨率 | 像素格数,决定清晰度 | 1920×1080 |
| 归一化 | 把像素压到统一小范围 | 255 ÷ 255 = 1.0 |
| 张量 | 多维数组,AI 的标准数据格式 | [批次, 通道, 高, 宽] |
记忆口诀:图是数字表,彩色三通道;灰度压一层,缩放归一进张量。
❓ 常见问题
Q1:为什么像素值是 0~255?
因为一个像素每个通道用 1 个字节(8 位)存储,2^8 = 256 个取值,即 0~255。
Q2:灰度图和黑白图是一样的吗?
基本一样,但严格说灰度图有 256 级亮度,黑白图(二值化)只有 0 和 1 两个值。CV 里常说的"灰度"就是 0~255 的亮度图。
Q3:为什么要归一化到 0~1?
神经网络对数值范围敏感。0~255 和 0~1 只是缩放关系,但 0~1 梯度更稳,模型收敛更快。
⚠️ 新手翻车现场
翻车一:读错像素坐标顺序
# 错误:以为 (x, y) = (列, 行),实际 PIL 的 getpixel 是 (x, y) 但 x=列,y=行
print(img.getpixel((1, 0))) # 这是第 2 列、第 1 行(右上角)
print(img.getpixel((0, 1))) # 这是第 1 列、第 2 行(左下角)
修正:PIL 的 getpixel((x, y)),x 是横坐标(列),y 是纵坐标(行)。和数学坐标系一致,但和图像处理里常见的 (行, 列) 顺序相反,注意别搞反。
翻车二:灰度转换后以为还是 3 通道
gray = img.convert("L")
print(gray.mode) # 输出 'L',表示单通道灰度
print(gray.getpixel((0, 0))) # 返回一个数,不是 (R, G, B) 元组
修正:灰度图每个像素只有一个数值(亮度),读出来是单个整数,不是元组。
🎯 什么时候用这些概念
- 像素/通道:理解图像底层数据结构,做图像预处理
- 灰度:去除颜色干扰,降低计算量,做边缘检测等任务
- 分辨率与归一化:给深度学习模型喂图之前的标准操作
- 张量:理解深度学习框架(PyTorch/TensorFlow)的数据格式
📝 本章小结
- 图片在计算机眼里是数字矩阵,每个像素是一个或三个数(灰度/RGB)
- RGB 三通道叠出彩色,灰度按加权公式压成一层亮度值
- 真实任务要统一分辨率、做归一化,最后组成张量喂给模型
- 记忆口诀:图是数字表,彩色三通道;灰度压一层,缩放归一进张量。
动手改
- 把右下角像素改成 (0, 0, 0),先猜灰度值是多少,再运行验证
- 用
img.resize((4, 4))把图放大一倍,打印新尺寸,体会"分辨率"的变化 - 用
Image.open("你的照片.jpg")读一张自己的照片,打印它的尺寸和某个像素值
下一章:卷积神经网络入门,看看模型怎么从数字表里认出猫和狗 🐸