OpenCV 图像操作入门:从零开始玩转计算机视觉
用 Python + OpenCV,10 个核心操作带你打开计算机视觉的大门 🎨
前言
OpenCV(Open Source Computer Vision Library)是计算机视觉领域最流行的开源库,支持 Python、C++、Java 等多种语言。无论是图像处理、人脸识别、目标检测,还是视频分析,OpenCV 都是绕不开的利器。
本文以 Python + OpenCV 为例,通过 10 个常用操作示例,带你快速上手图像处理的核心技能。
环境准备
安装依赖
bash
pip install opencv-python numpy matplotlib
说明:
opencv-python:OpenCV 核心库numpy:图像本质上是数组,numpy 是基础matplotlib:用于在 Jupyter/脚本中可视化展示图像
验证安装
python
import cv2
import numpy as np
print(f"OpenCV 版本:{cv2.__version__}")
输出类似 OpenCV 版本:4.9.0 即表示安装成功。
基础概念
在正式操作之前,有两个概念必须先搞清楚:
图像在 OpenCV 中的本质
在 OpenCV 里,一张图像就是一个 NumPy 多维数组:
- 灰度图 :形状为
(height, width),每个像素值范围0~255 - 彩色图 :形状为
(height, width, 3),三个通道分别是 B(蓝)、G(绿)、R(红)
⚠️ 注意:OpenCV 的通道顺序是 BGR,而不是我们常见的 RGB,这是一个高频踩坑点!
坐标系
OpenCV 的坐标原点在左上角,x 轴向右,y 轴向下。
操作一:读取、显示与保存图像
这是最基础的三板斧。
python
import cv2
# 读取图像(默认彩色模式)
img = cv2.imread("example.jpg")
# 读取为灰度图
img_gray = cv2.imread("example.jpg", cv2.IMREAD_GRAYSCALE)
# 显示图像(弹出窗口)
cv2.imshow("原图", img)
cv2.imshow("灰度图", img_gray)
# 等待按键后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存图像
cv2.imwrite("output.jpg", img_gray)
print("保存成功!")
常用读取模式:
| 参数 | 说明 |
|---|---|
cv2.IMREAD_COLOR |
彩色模式(默认) |
cv2.IMREAD_GRAYSCALE |
灰度模式 |
cv2.IMREAD_UNCHANGED |
原始模式(含 Alpha 通道) |
操作二:图像基本属性
python
import cv2
img = cv2.imread("example.jpg")
# 图像形状:(高度, 宽度, 通道数)
print(f"形状:{img.shape}") # 例:(480, 640, 3)
# 像素总数
print(f"像素总数:{img.size}") # 例:921600
# 数据类型
print(f"数据类型:{img.dtype}") # uint8
# 获取单个像素的 BGR 值
pixel = img[100, 200]
print(f"坐标(100,200)的像素:B={pixel[0]}, G={pixel[1]}, R={pixel[2]}")
# 修改单个像素
img[100, 200] = [255, 0, 0] # 改为纯蓝色
操作三:颜色空间转换
python
import cv2
img = cv2.imread("example.jpg")
# BGR → 灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# BGR → RGB(用于 matplotlib 显示)
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# BGR → HSV(色相-饱和度-亮度,常用于颜色检测)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 用 matplotlib 正确显示彩色图
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1); plt.imshow(rgb); plt.title("RGB 原图"); plt.axis("off")
plt.subplot(1, 3, 2); plt.imshow(gray, cmap="gray"); plt.title("灰度图"); plt.axis("off")
plt.subplot(1, 3, 3); plt.imshow(hsv); plt.title("HSV 图"); plt.axis("off")
plt.tight_layout()
plt.show()
💡 小技巧:用 matplotlib 显示 OpenCV 图像时,记得先把 BGR 转成 RGB,否则颜色会"蓝红反转"。
操作四:图像缩放与裁剪
python
import cv2
img = cv2.imread("example.jpg")
h, w = img.shape[:2]
print(f"原始尺寸:{w} x {h}")
# --- 缩放 ---
# 指定目标尺寸
resized = cv2.resize(img, (320, 240))
# 按比例缩放(缩小到 50%)
half = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
# 放大 1.5 倍,使用双三次插值(质量更好)
enlarged = cv2.resize(img, (0, 0), fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC)
# --- 裁剪(ROI:感兴趣区域)---
# 语法:img[y_start:y_end, x_start:x_end]
roi = img[50:200, 100:300] # 裁剪 y:50~200, x:100~300 的区域
cv2.imshow("缩放后", resized)
cv2.imshow("裁剪区域", roi)
cv2.waitKey(0)
cv2.destroyAllWindows()
插值方法对比:
| 插值方法 | 适用场景 |
|---|---|
cv2.INTER_NEAREST |
速度最快,质量最差 |
cv2.INTER_LINEAR |
默认,双线性,速度与质量均衡 |
cv2.INTER_CUBIC |
双三次,放大时质量好 |
cv2.INTER_AREA |
缩小时效果最佳 |
操作五:图像翻转与旋转
python
import cv2
img = cv2.imread("example.jpg")
# 翻转
flip_h = cv2.flip(img, 1) # 水平翻转(左右镜像)
flip_v = cv2.flip(img, 0) # 垂直翻转(上下翻转)
flip_b = cv2.flip(img, -1) # 同时水平 + 垂直翻转
# 旋转(以图像中心为轴,旋转 45 度,缩放比例 1.0)
h, w = img.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0)
rotated = cv2.warpAffine(img, M, (w, h))
cv2.imshow("水平翻转", flip_h)
cv2.imshow("旋转45度", rotated)
cv2.waitKey(0)
cv2.destroyAllWindows()
操作六:绘制图形与文字
OpenCV 提供了丰富的绘图函数,常用于标注检测结果。
python
import cv2
import numpy as np
# 创建一块黑色画布(500x500,3通道)
canvas = np.zeros((500, 500, 3), dtype=np.uint8)
# 画直线:起点、终点、颜色(BGR)、线宽
cv2.line(canvas, (50, 50), (450, 50), (0, 255, 0), 2)
# 画矩形:左上角、右下角、颜色、线宽(-1 表示填充)
cv2.rectangle(canvas, (100, 100), (300, 250), (0, 0, 255), 3)
# 画圆:圆心、半径、颜色、线宽
cv2.circle(canvas, (400, 350), 80, (255, 0, 0), -1) # 填充蓝色圆
# 画多边形
pts = np.array([[250, 300], [350, 400], [150, 400]], dtype=np.int32)
cv2.polylines(canvas, [pts], isClosed=True, color=(0, 255, 255), thickness=2)
# 写文字:文本、位置、字体、字号、颜色、线宽
cv2.putText(
canvas, "Hello OpenCV!",
(80, 470),
cv2.FONT_HERSHEY_SIMPLEX,
1.2,
(255, 255, 255),
2
)
cv2.imshow("绘图示例", canvas)
cv2.waitKey(0)
cv2.destroyAllWindows()
操作七:图像滤波(模糊与锐化)
滤波是图像预处理的核心步骤,用于去噪或增强细节。
python
import cv2
img = cv2.imread("example.jpg")
# 均值模糊:内核越大越模糊
blur_avg = cv2.blur(img, (5, 5))
# 高斯模糊:更自然的模糊效果(常用于降噪)
blur_gauss = cv2.GaussianBlur(img, (5, 5), 0)
# 中值模糊:对椒盐噪声效果极好
blur_median = cv2.medianBlur(img, 5)
# 双边滤波:保留边缘的同时去噪(效果好但速度慢)
blur_bilateral = cv2.bilateralFilter(img, 9, 75, 75)
# 锐化(使用自定义卷积核)
import numpy as np
kernel_sharpen = np.array([
[ 0, -1, 0],
[-1, 5, -1],
[ 0, -1, 0]
])
sharpened = cv2.filter2D(img, -1, kernel_sharpen)
cv2.imshow("原图", img)
cv2.imshow("高斯模糊", blur_gauss)
cv2.imshow("锐化", sharpened)
cv2.waitKey(0)
cv2.destroyAllWindows()
操作八:边缘检测
边缘检测是目标识别的重要前处理步骤。
python
import cv2
img = cv2.imread("example.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Canny 边缘检测(最常用)
# 参数:输入图、低阈值、高阈值
edges_canny = cv2.Canny(gray, 50, 150)
# Sobel 算子(分别检测 X、Y 方向边缘)
sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
sobel = cv2.magnitude(sobel_x, sobel_y)
sobel = cv2.convertScaleAbs(sobel)
# Laplacian 算子
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
cv2.imshow("原图(灰度)", gray)
cv2.imshow("Canny 边缘", edges_canny)
cv2.imshow("Sobel 边缘", sobel)
cv2.imshow("Laplacian 边缘", laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()
💡 Canny 参数调优建议:低阈值 = 高阈值 × 1/3,高阈值从 100~200 开始尝试。
操作九:阈值分割与轮廓检测
python
import cv2
import numpy as np
img = cv2.imread("example.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 全局阈值(大于127的像素变白,其余变黑)
_, thresh_global = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值(对光照不均的图像效果更好)
thresh_adaptive = cv2.adaptiveThreshold(
gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
# Otsu 自动阈值(自动确定最佳阈值)
_, thresh_otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# --- 轮廓检测 ---
contours, hierarchy = cv2.findContours(
thresh_otsu,
cv2.RETR_EXTERNAL, # 只检测外轮廓
cv2.CHAIN_APPROX_SIMPLE
)
# 在原图上绘制所有轮廓
img_contours = img.copy()
cv2.drawContours(img_contours, contours, -1, (0, 255, 0), 2)
print(f"共检测到 {len(contours)} 个轮廓")
cv2.imshow("Otsu 阈值", thresh_otsu)
cv2.imshow("轮廓检测", img_contours)
cv2.waitKey(0)
cv2.destroyAllWindows()
操作十:综合实战------提取图像中的红色区域
将前面学到的知识组合起来,做一个实用的颜色检测小程序。
python
import cv2
import numpy as np
def detect_red_region(image_path):
"""检测图像中的红色区域并标注"""
# 1. 读取图像并转换到 HSV 空间
img = cv2.imread(image_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 2. 定义红色的 HSV 范围(红色在 HSV 中分两段)
lower_red1 = np.array([0, 120, 70])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([170, 120, 70])
upper_red2 = np.array([180, 255, 255])
# 3. 创建掩码
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = cv2.bitwise_or(mask1, mask2)
# 4. 形态学处理(去除噪点)
kernel = np.ones((5, 5), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # 开运算去小噪点
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 闭运算填补空洞
# 5. 找轮廓并绘制边界框
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
result = img.copy()
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 500: # 过滤掉太小的区域
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(result, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(result, f"Red Area: {area:.0f}px",
(x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# 6. 显示结果
cv2.imshow("原图", img)
cv2.imshow("红色掩码", mask)
cv2.imshow("检测结果", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
return len([c for c in contours if cv2.contourArea(c) > 500])
# 调用
count = detect_red_region("example.jpg")
print(f"共检测到 {count} 个红色区域")
常用速查表
颜色转换
python
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 彩色 → 灰度
cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR → RGB
cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR → HSV
cv2.cvtColor(img, cv2.COLOR_BGR2LAB) # BGR → LAB
几何变换
python
cv2.resize(img, (w, h)) # 缩放
cv2.flip(img, 1) # 翻转
cv2.warpAffine(img, M, (w, h)) # 仿射变换
cv2.warpPerspective(img, M, (w, h)) # 透视变换
滤波
python
cv2.GaussianBlur(img, (5, 5), 0) # 高斯模糊
cv2.medianBlur(img, 5) # 中值模糊
cv2.Canny(gray, 50, 150) # 边缘检测
cv2.filter2D(img, -1, kernel) # 自定义卷积
形态学操作
python
cv2.erode(img, kernel) # 腐蚀
cv2.dilate(img, kernel) # 膨胀
cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 开运算
cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 闭运算
常见踩坑汇总
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 图像颜色异常(蓝红互换) | OpenCV 使用 BGR,matplotlib 使用 RGB | 显示前转换:cv2.cvtColor(img, cv2.COLOR_BGR2RGB) |
imread 返回 None |
文件路径错误或文件不存在 | 检查路径,避免中文路径,用 os.path.exists() 验证 |
| 旋转后图像被裁剪 | warpAffine 输出尺寸不够 |
计算旋转后的新尺寸并传入 |
| 轮廓检测结果异常 | 输入图像不是二值图 | 先进行阈值处理再检测轮廓 |
imshow 窗口一闪而过 |
没有 waitKey |
加上 cv2.waitKey(0) |
小结
本文覆盖了 OpenCV 图像操作的 10 个核心知识点:
- 📂 读取、显示、保存------三板斧
- 📐 基本属性------shape、dtype、像素访问
- 🎨 颜色空间转换------BGR/RGB/HSV/灰度
- ✂️ 缩放与裁剪------resize、ROI
- 🔄 翻转与旋转------flip、warpAffine
- ✏️ 绘图与标注------line、rectangle、putText
- 🌫️ 滤波------模糊与锐化
- 🔍 边缘检测------Canny、Sobel
- 🎯 阈值与轮廓------threshold、findContours
- 🛠️ 综合实战------颜色区域检测
掌握这些基础操作后,你就可以进一步探索人脸检测、目标识别、OCR 文字识别等更高级的计算机视觉应用了。
延伸阅读
本文示例基于 OpenCV 4.x + Python 3.8+,最后更新:2026 年 3 月