OpenCV 图像基本操作(长文解析)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在数字时代,图像处理技术已渗透到生活的方方面面,从社交媒体的滤镜到自动驾驶的视觉识别,都离不开图像算法的支持。OpenCV(Open Source Computer Vision Library) 作为全球最流行的计算机视觉库之一,为开发者提供了丰富的图像处理工具。对于编程初学者和中级开发者而言,掌握 OpenCV 图像基本操作 是探索计算机视觉领域的第一步。本文将通过循序渐进的方式,结合实际案例和代码示例,帮助读者理解图像处理的核心概念和实现方法。
安装与环境配置
在开始之前,需要确保已正确安装 OpenCV 库。对于 Python 用户,可以通过以下命令安装:
pip install opencv-python
安装完成后,可以通过以下代码验证是否成功:
import cv2
print(cv2.__version__)
若输出版本号(如 4.9.0
),则说明环境配置完成。
图像读取与显示
1. 图像读取
OpenCV 提供了 cv2.imread()
函数用于读取图像文件。默认情况下,该函数以 BGR(蓝绿红)格式加载图像,这与常见的 RGB 格式不同。例如:
image = cv2.imread("example.jpg")
if image is None:
print("Error: Could not read image.")
2. 图像显示
使用 cv2.imshow()
函数可以显示图像窗口。需要注意的是,必须配合 cv2.waitKey()
函数暂停程序,否则窗口会立即关闭:
cv2.imshow("Image Window", image)
cv2.waitKey(0) # 等待用户按键
cv2.destroyAllWindows() # 关闭所有窗口
比喻:
想象你正在整理一张照片,cv2.imread()
就像打开相册并选中一张照片,而 cv2.imshow()
则是将照片放在桌面上供你查看。
图像的基本操作
1. 图像裁剪(ROI)
通过索引操作可以提取图像的感兴趣区域(Region of Interest, ROI)。例如,裁剪图像左上角的 200x200 区域:
roi = image[0:200, 0:200] # [y1:y2, x1:x2]
cv2.imshow("ROI", roi)
2. 图像调整大小
使用 cv2.resize()
可以缩放图像,常用于统一尺寸或降低计算复杂度:
resized_image = cv2.resize(image, (0, 0), fx=0.5, fy=0.5)
3. 图像反转
cv2.flip()
函数可以沿水平或垂直方向翻转图像:
flipped_image = cv2.flip(image, 1) # 1 表示水平,0 表示垂直
颜色空间转换
BGR 与 RGB 的转换
由于 OpenCV 默认使用 BGR 格式,若需与常见的 RGB 格式匹配(如在 matplotlib 中显示),可使用 cv2.cvtColor()
:
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
灰度图像转换
将彩色图像转换为灰度图可以简化后续处理:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
比喻:
颜色空间转换就像给照片添加滤镜——灰度图是黑白滤镜,而 BGR 到 RGB 是调整色彩通道的“镜像滤镜”。
边缘检测与阈值处理
边缘检测(Canny 算子)
Canny 算子通过梯度分析检测图像中的边缘,常用于目标轮廓提取:
edges = cv2.Canny(gray_image, 100, 200) # 100 和 200 是高低阈值
cv2.imshow("Edges", edges)
阈值处理(Thresholding)
通过设置阈值分割图像区域,常用于二值化处理:
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
比喻:
边缘检测如同用铅笔勾勒图像的轮廓,而阈值处理则是用黑白两色“擦除”或“保留”特定区域。
形态学操作
形态学操作包括腐蚀(Erosion)和膨胀(Dilation),用于细化或增强图像中的目标区域。
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
eroded = cv2.erode(binary_image, kernel, iterations=1)
dilated = cv2.dilate(binary_image, kernel, iterations=1)
比喻:
腐蚀操作类似用砂纸打磨图像的边缘,而膨胀则是用橡皮擦扩大目标区域的边界。
实战案例:车牌识别预处理
案例背景
假设需要从车辆图像中提取车牌区域,可以通过以下步骤实现:
- 灰度转换:减少颜色干扰。
- 高斯模糊:降低噪声。
- 边缘检测:定位车牌边缘。
- 轮廓检测:筛选矩形区域。
完整代码示例
import cv2
def preprocess_license_plate(image_path):
# 读取图像
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Canny 边缘检测
edges = cv2.Canny(blurred, 50, 150)
# 查找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 筛选近似矩形的轮廓
for cnt in contours:
perimeter = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02 * perimeter, True)
if len(approx) == 4: # 车牌通常是四边形
cv2.drawContours(image, [approx], -1, (0, 255, 0), 3)
cv2.imshow("Result", image)
cv2.waitKey(0)
preprocess_license_plate("car.jpg")
输出效果:

性能优化与注意事项
1. 内存管理
处理大尺寸图像时,建议先调整图像大小以减少内存占用。
resized = cv2.resize(image, (640, 480)) # 缩小到 640x480 分辨率
2. 并行处理
对于批量图像处理,可以利用多线程或向量化操作提升效率。
3. 错误处理
在读取图像前,务必检查 image is None
,避免后续操作报错。
结论
通过本文的讲解,读者已掌握了 OpenCV 图像基本操作 的核心技能,包括图像读取、颜色空间转换、边缘检测及形态学操作等。从裁剪到边缘检测,这些基础工具为更复杂的任务(如目标检测、图像分类)奠定了坚实基础。建议读者通过实际项目(如车牌识别、文档扫描)巩固所学内容,并逐步探索 OpenCV 的高级功能。
计算机视觉的世界充满可能性,而 OpenCV 图像基本操作 是打开这扇门的钥匙。希望本文能激发你的兴趣,带领你在图像处理领域走得更远!