3、Python与OpenCV基础回顾:图像读取、显示、保存,色彩空间转换,图像几何变换,ROI提取
各位同学,欢迎来到第三章。在正式开始人脸识别和姿态估计之前,咱们得先把地基打牢。OpenCV 和 Python 的组合,说白了就是边缘设备上做视觉处理的「倚天剑」。这一章我会带大家快速过一遍最核心的基础操作,这些都是我这些年做项目时天天用的东西,一个都跑不掉。
3.1 图像读取、显示与保存
这是最基础的三板斧。我刚开始接触 OpenCV 时,第一件事就是验证这三步能不能跑通。你想想看,如果连图片都读不进来,后面的一切都是空谈。
3.1.1 读取图像
用 cv2.imread() 就行。路径对了,一切好说。路径错了,程序直接崩给你看。我个人习惯用绝对路径,或者用 os.path.join() 拼接,避免在 Windows 和 Linux 之间来回切换时踩坑。
import cv2
# 读取图像,默认是彩色模式
img = cv2.imread('test.jpg')
print(img.shape) # (高度, 宽度, 通道数)
3.1.2 显示图像
用 cv2.imshow() 配合 cv2.waitKey()。嗯,这里有个细节:waitKey(0) 表示等待按键按下,waitKey(1) 表示等待 1 毫秒。在视频处理中,我通常用 waitKey(1) 来保持画面刷新。
cv2.imshow('窗口标题', img)
cv2.waitKey(0) # 按任意键关闭
cv2.destroyAllWindows()
3.1.3 保存图像
用 cv2.imwrite()。格式由文件后缀决定,比如 .jpg、.png。我在项目中经常用它来保存中间结果,方便调试。
cv2.imwrite('output.jpg', img)
3.2 色彩空间转换
为什么需要色彩空间转换?说白了,BGR 格式在颜色识别时并不友好。比如你要检测肤色,用 HSV 空间就比 BGR 稳定得多。我曾经在做一个手势识别项目时,用 BGR 做肤色分割,结果灯光一变就全乱了。换成 HSV 之后,鲁棒性明显提升。
3.2.1 BGR 转灰度
灰度图只有单通道,计算量小,适合做边缘检测、人脸检测的前处理。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
3.2.2 BGR 转 HSV
HSV 把颜色分解成色调、饱和度、明度三个维度。做颜色识别时,你只需要关注色调范围就行。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
3.3 图像几何变换
几何变换在姿态估计中特别常用。比如你要把检测到的人脸对齐到标准位置,就需要用到仿射变换。
3.3.1 缩放
用 cv2.resize()。注意插值方法的选择:缩小用 INTER_AREA,放大用 INTER_LINEAR 或 INTER_CUBIC。
resized = cv2.resize(img, (224, 224)) # 固定尺寸
3.3.2 旋转
旋转需要先获取旋转矩阵,然后用 cv2.warpAffine() 执行。我习惯用 cv2.getRotationMatrix2D() 来生成矩阵。
h, w = img.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0) # 旋转45度
rotated = cv2.warpAffine(img, M, (w, h))
3.3.3 平移与仿射变换
平移也是用 warpAffine,只是矩阵不同。仿射变换可以同时实现旋转、缩放、平移,是姿态估计中的核心操作。
# 平移矩阵
M_trans = np.float32([[1, 0, 50], [0, 1, 100]])
translated = cv2.warpAffine(img, M_trans, (w, h))
3.4 ROI 提取
ROI,也就是感兴趣区域。在人脸识别中,我们通常只关心人脸那一小块区域,而不是整张图片。提取 ROI 其实就是数组切片,简单但极其高效。
# 假设人脸区域在 (x, y, w, h) 范围内
face_roi = img[y:y+h, x:x+w]
你可能会问:ROI 提取后怎么用?举个例子,你可以把提取到的人脸区域单独保存,或者送入神经网络做特征提取。在姿态估计中,ROI 通常就是人体或人脸所在的 bounding box。
3.5 综合示例:人脸 ROI 提取与保存
下面这个例子,我会把前面讲的内容串起来。先用 Haar 级联检测人脸,然后提取 ROI,最后保存到本地。
import cv2
# 加载人脸检测器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 读取图像
img = cv2.imread('group_photo.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = face_cascade.detectMultiScale(gray, 1.1, 5)
# 提取并保存每个人脸
for i, (x, y, w, h) in enumerate(faces):
face_roi = img[y:y+h, x:x+w]
cv2.imwrite(f'face_{i}.jpg', face_roi)
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow('Detected Faces', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.6 本章小结
这一章的内容,说白了就是 OpenCV 的「基本功」。图像读写、色彩转换、几何变换、ROI 提取,这四个模块在后续的人脸识别和姿态估计中会反复出现。我个人建议你把这些代码亲手敲一遍,不要复制粘贴。敲代码的过程中,你会遇到各种小问题——路径不对、类型不匹配、坐标越界——这些都是宝贵的经验。
下一章,我们会进入人脸检测的核心算法。到时候你会发现,今天学的 ROI 提取和色彩空间转换,就是检测流程中的关键拼图。好了,先练好基本功,咱们下章见。