一、一张照片 = 一个数字数组
"小陈,视觉开发的第一课:彻底搞懂'图像'在电脑里的表示。"老周打开 Jupyter Notebook:
import cv2
import numpy as np
# 读一张图(灰度图)
img = cv2.imread("book_cover.jpg", cv2.IMREAD_GRAYSCALE)
print(img.shape) # (800, 600) —— 高 800,宽 600
print(img[100, 200]) # 128 —— 第100行第200列的像素亮度(0-255)
# 显示
cv2.imshow("image", img)
cv2.waitKey(0)
灰度图(Grayscale):
shape = (高, 宽) 的二维数组
每个元素 = 一个像素的亮度(0=纯黑,255=纯白)
0-255 共 256 个灰度级(8 位)
彩色图(RGB):
shape = (高, 宽, 3) 的三维数组
每个像素 = 3 个值(红R、绿G、蓝B)
[ [[245, 23, 12], [250, 20, 10]],
[[247, 21, 15], [249, 22, 11]], ... ]
第一个像素:R=245 G=23 B=12(红色系)
颜色合成:
(255, 0, 0) = 纯红 (0, 255, 0) = 纯绿
(0, 0, 255) = 纯蓝 (255, 255, 255) = 白
(0, 0, 0) = 黑 (128, 128, 128) = 灰
一张 1920×1080 彩色图 = 1920×1080×3 ≈ 620 万个数字
"图像在电脑里 = 多维数字数组。 所有图像处理,本质都是'对数组做数学运算'。理解了这一点,后面所有技术都好懂了。"
二、色彩空间:同一个图,不同的"坐标系"
"颜色可以用不同方式描述——这就是色彩空间(Color Space)。"老周说:
常见色彩空间:
RGB:红/绿/蓝三通道(显示用)
HSV:色相Hue/饱和度Sat/明度Value(人眼感知,处理用)
HLS:类似 HSV(亮度 Lightness)
Lab:L亮度/a红绿/b蓝黄(感知均匀,颜色分析用)
YUV:亮度Y + 色度UV(视频压缩用)
为什么要转色彩空间?
例子:检测"红色书封"
在 RGB 里判断"红"很难(受光线影响大)
在 HSV 里:只看 H(色相)在红色范围就行(更稳定)
OpenCV 注意:
cv2 默认是 BGR 不是 RGB!(历史原因)
→ 显示/保存前要转换:cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
→ 新手最常见坑之一!
转换示例:
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
"色彩空间是'看待颜色的不同角度'——显示用 RGB,分析用 HSV,压缩用 YUV。视觉开发里'换个色彩空间'常常是解决问题的第一步。"
三、图像 IO 与像素操作:视觉开发的基本功
"读图、存图、改像素——这几招要练熟。"老周演示:
import cv2
import numpy as np
# 图像 IO
img = cv2.imread("photo.jpg") # 读图(BGR)
cv2.imwrite("out.jpg", img) # 存图
print(img.shape) # (高, 宽, 通道)
# 像素操作
pixel = img[50, 100] # 取像素 (B,G,R)
img[50, 100] = [0, 0, 255] # 改像素(变红)
# 区域操作(切片)
img[100:200, 150:250] = [255, 255, 255] # 把一块区域涂白
region = img[100:200, 150:250] # 裁剪一块区域
# 缩放 / 旋转 / 翻转
resized = cv2.resize(img, (400, 300)) # 缩放
rotated = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE) # 旋转
flipped = cv2.flip(img, 1) # 水平翻转
# 叠加文字/框(可视化用)
cv2.rectangle(img, (50, 50), (200, 200), (0, 255, 0), 2) # 画框
cv2.putText(img, "Yunjian", (50, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
"OpenCV(Open Source Computer Vision Library)是视觉开发的事实标准工具库——读图、处理、画框、算法,全都有。'会 OpenCV'是视觉工程师的基本功,就像'会 Git'是程序员的标配。"
四、NumPy 是视觉开发的"幕后英雄"
"OpenCV 处理图像,底层全靠 NumPy。"老周强调:
NumPy 与图像:
OpenCV 的图 = NumPy 的 ndarray
所有图像操作,都可以直接用 NumPy 数学运算
常用 NumPy 图像操作:
np.zeros((h, w, 3)) # 创建黑色画布
img + 50 # 整体变亮(像素值+50)
img * 0.5 # 整体变暗
np.clip(img, 0, 255) # 把值限制在 0-255
np.mean(img) # 平均亮度
img[::-1] # 上下翻转
数据流向:
NumPy(数组运算)←→ OpenCV(图像算法)
深度学习(PyTorch 张量)← 图像也要转成张量
"记住这条链:图 → NumPy 数组 → 各种运算 → 视觉算法。 NumPy 处理数组的功夫,决定了你写视觉代码的上限。"
五、视频的本质:连续的图像帧
"咱们后面要做客流统计(视频),提前讲一下视频的本质。"老周说:
视频 = 连续的图像帧(Frame)
视频 = 每秒 N 张图(如 25 FPS = 每秒 25 帧)
视频处理 = 循环读帧 → 每帧做图像处理
OpenCV 读视频:
cap = cv2.VideoCapture("video.mp4")
while True:
ret, frame = cap.read() # 读一帧
if not ret:
break # 视频结束
# 对 frame 做图像处理
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 显示
cv2.imshow("video", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
摄像头(实时):
cap = cv2.VideoCapture(0) # 0 = 默认摄像头
# 之后循环一样(实时流 = 一帧一帧读)
"视频处理 = '逐帧图像处理'的循环——理解了这个,'客流统计'其实就是在'每一帧里数人',再用跟踪技术把同一个人连续起来(第十一章)。"
六、章末:老周的第二章总结
第一层:图像基础与 OpenCV
├── 图像 = NumPy 数字数组(灰度二维 / 彩色三维)
├── 色彩空间:RGB(显示)/HSV(分析)/YUV(压缩)
│ OpenCV 默认 BGR(新手坑!)
├── 图像 IO:imread/imwrite + 像素/区域操作
├── 几何操作:缩放/旋转/翻转/裁剪
├── 可视化:画框、写文字(调试神器)
├── NumPy:图像底层运算(视觉基本功)
└── 视频 = 逐帧图像(VideoCapture 循环)
第三层(预告):图像处理 —— 让模糊的照片变清晰
"小陈,现在你手里有'像素'这把钥匙了。"老周说,"但你拿手机拍的图书封面,往往又暗又糊又歪——直接丢给识别程序,效果会很难看。下一章,我们学图像处理基础:灰度化、滤波、边缘检测、形态学——让'脏图'变'干净图'。这是所有视觉任务的第一道工序。"