杰瑞科技汇

Python OpenCV2教程,如何快速入门?

Python OpenCV2 完整教程

OpenCV (Open Source Computer Vision Library) 是一个强大的、开源的计算机视觉和机器学习软件库,结合 Python,它变得异常简单和高效,非常适合快速原型开发、学术研究和实际应用。

Python OpenCV2教程,如何快速入门?-图1
(图片来源网络,侵删)

本教程将涵盖以下内容:

  1. 环境准备:安装 Python 和 OpenCV。
  2. 基础操作:读取、显示和保存图像。
  3. 图像处理:访问像素、图像变换(灰度、大小、旋转等)。
  4. 图像处理进阶:图像平滑、边缘检测。
  5. 视频处理:读取摄像头和视频文件。
  6. 绘制功能:在图像上画线、圆、矩形等。
  7. 形态学操作:腐蚀与膨胀。
  8. 直方图:分析图像亮度分布。
  9. 项目实战:人脸检测。

环境准备

在开始之前,请确保你已经安装了 Python,推荐使用 Python 3.x 版本。

安装 OpenCV

最简单的方式是使用 pip,在终端或命令提示符中运行以下命令:

# 安装 OpenCV-Python 主包
pip install opencv-python
# (可选但推荐) 安装 OpenCV 的额外模块,包含 SIFT, SURF 等高级功能
pip install opencv-python-headless
pip install opencv-contrib-python

注意opencv-python 包已经包含了 numpy,但如果你遇到 numpy 相关的错误,可以手动安装: pip install numpy

Python OpenCV2教程,如何快速入门?-图2
(图片来源网络,侵删)

基础操作:读取、显示、保存图像

这是使用 OpenCV 的第一步,我们将学习如何加载一张图片,在窗口中显示它,并保存处理后的结果。

代码示例

import cv2
import numpy as np
# --- 1. 读取图像 ---
# cv2.imread() 用于读取图像
# 第二个参数是读取模式:
# cv2.IMREAD_COLOR: 默认,加载彩色图像
# cv2.IMREAD_GRAYSCALE: 加载灰度图像
# cv2.IMREAD_UNCHANGED: 加载包含 alpha 通道的图像
image_path = 'path/to/your/image.jpg'  # <--- 替换为你的图片路径
img_color = cv2.imread(image_path, cv2.IMREAD_COLOR)
img_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 检查图像是否成功加载
if img_color is None:
    print(f"错误:无法加载图像,请检查路径: {image_path}")
else:
    print(f"彩色图像尺寸: {img_color.shape}")
    print(f"灰度图像尺寸: {img_gray.shape}")
# --- 2. 显示图像 ---
# cv2.imshow() 用于在窗口中显示图像
# 第一个参数是窗口的名称
cv2.imshow('Color Image', img_color)
cv2.imshow('Gray Image', img_gray)
# cv2.waitKey() 是一个关键的函数,它等待键盘输入。
# 参数 0 表示无限等待,直到有任意键被按下。
# 如果参数是正数,则等待指定的毫秒数。
cv2.waitKey(0)
# --- 3. 保存图像 ---
# cv2.imwrite() 用于将图像保存到文件
output_path_gray = 'output_gray.jpg'
cv2.imwrite(output_path_gray, img_gray)
print(f"灰度图像已保存到: {output_path_gray}")
# --- 4. 关闭所有窗口 ---
# cv2.destroyAllWindows() 用于关闭所有由 OpenCV 创建的窗口
cv2.destroyAllWindows()

图像处理基础

访问和修改像素

图像在 OpenCV 中被表示为一个 NumPy 数组,你可以像操作 NumPy 数组一样操作像素。

import cv2
img = cv2.imread('path/to/your/image.jpg')
# 获取图像的高度和宽度
height, width = img.shape[:2]
# 访问像素 BGR 值 (注意:OpenCV 使用 BGR 顺序,不是 RGB)
# 坐标格式是 (行, 列),也就是 (y, x)
pixel_BGR = img[100, 150]
print(f"像素 (100, 150) 的 BGR 值: {pixel_BGR}")
# 修改像素值
img[100, 150] = [255, 255, 255] # 将该像素设置为白色
# 修改一个区域 (ROI - Region of Interest)
roi = img[100:200, 300:400]
roi[:, :] = [0, 0, 255] # 将 ROI 区域设置为蓝色
cv2.imshow('Modified Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像变换

a. 调整大小

import cv2
img = cv2.imread('path/to/your/image.jpg')
# cv2.resize() 调整图像大小
# 参数: (图像, (新宽度, 新高度), 插值方法)
# 常用插值方法:
# cv2.INTER_NEAREST: 最近邻插值
# cv2.INTER_LINEAR: 双线性插值 (默认)
# cv2.INTER_CUBIC: 三次样条插值 (慢,但效果好)
resized_img = cv2.resize(img, (300, 200), interpolation=cv2.INTER_LINEAR)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

b. 旋转图像

import cv2
import numpy as np
img = cv2.imread('path/to/your/image.jpg')
# 获取图像的中心点
center = (img.shape[1] // 2, img.shape[0] // 2)
# 定义旋转矩阵
# cv2.getRotationMatrix2D(中心点, 角度, 缩放因子)
rotation_matrix = cv2.getRotationMatrix2D(center, 45, 1.0)
# 应用旋转
# cv2.warpAffine(图像, 旋转矩阵, (输出图像宽度, 输出图像高度))
rotated_img = cv2.warpAffine(img, rotation_matrix, (img.shape[1], img.shape[0]))
cv2.imshow('Rotated Image', rotated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像处理进阶

a. 图像平滑(模糊)

模糊通常用于降噪。

import cv2
img = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_COLOR)
# cv2.blur() - 均值模糊
# 参数: (图像, 核大小)
blurred_mean = cv2.blur(img, (15, 15))
# cv2.GaussianBlur() - 高斯模糊 (常用)
# 参数: (图像, 核大小, X方向标准差)
blurred_gaussian = cv2.GaussianBlur(img, (15, 15), 0)
# cv2.medianBlur() - 中值模糊 (对椒盐噪声效果好)
blurred_median = cv2.medianBlur(img, 15)
cv2.imshow('Original', img)
cv2.imshow('Mean Blur', blurred_mean)
cv2.imshow('Gaussian Blur', blurred_gaussian)
cv2.imshow('Median Blur', blurred_median)
cv2.waitKey(0)
cv2.destroyAllWindows()

b. 边缘检测

Canny 边缘检测是一种非常流行的边缘检测算法。

Python OpenCV2教程,如何快速入门?-图3
(图片来源网络,侵删)
import cv2
img = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_COLOR)
# 通常先转换为灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用高斯模糊降噪
blurred_gray = cv2.GaussianBlur(gray_img, (5, 5), 0)
# cv2.Canny() 边缘检测
# 参数: (灰度图, 低阈值, 高阈值)
# 阈值需要根据图像调整
edges = cv2.Canny(blurred_gray, 50, 150)
cv2.imshow('Original', img)
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

视频处理

视频本质上是一系列连续的图像帧。

a. 从摄像头读取

import cv2
# 打开默认摄像头 (通常是 0)
# 如果你的摄像头不是 0,可以尝试 1, 2 等
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("无法打开摄像头")
    exit()
while True:
    # cap.read() 读取一帧
    # ret 是一个布尔值,表示是否成功读取到帧
    # frame 是读取到的图像帧
    ret, frame = cap.read()
    if not ret:
        print("无法获取帧,退出...")
        break
    # 在帧上显示一些文本
    cv2.putText(frame, 'Press Q to quit', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    # 显示帧
    cv2.imshow('Camera Feed', frame)
    # 检查是否按下了 'q' 键
    # cv2.waitKey(1) 的返回值是按键的 ASCII 码
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# 释放摄像头资源
cap.release()
# 关闭所有窗口
cv2.destroyAllWindows()

b. 播放视频文件

播放视频文件和从摄像头读取几乎一样,只是 VideoCapture 的参数是文件路径。

import cv2
video_path = 'path/to/your/video.mp4'
cap = cv2.VideoCapture(video_path)
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("视频播放完毕或文件损坏。")
        break
    # 可以在这里对每一帧进行处理,例如边缘检测
    # gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # edges = cv2.Canny(gray_frame, 50, 150)
    # cv2.imshow('Video Edges', edges)
    # 或者直接显示原始帧
    cv2.imshow('Video Playback', frame)
    if cv2.waitKey(25) & 0xFF == ord('q'): # 25ms 是一个合理的帧率
        break
cap.release()
cv2.destroyAllWindows()

绘制功能

你可以在图像上绘制各种图形,这对于标注非常有用。

import cv2
import numpy as np
# 创建一个黑色的空白图像
img = np.zeros((512, 512, 3), np.uint8)
# 1. 画一条线
# cv2.line(图像, 起点, 终点, 颜色, 线条粗细)
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
# 2. 画一个矩形
# cv2.rectangle(图像, 左上角坐标, 右下角坐标, 颜色, 线条粗度)
# 如果线条粗度为 -1,则填充矩形
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
# 3. 画一个圆
# cv2.circle(图像, 圆心, 半径, 颜色, 线条粗度)
cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
# 4. 画一个椭圆
# cv2.ellipse(图像, 中心点, 长轴/短轴, 旋转角度, 起始角, 结束角, 颜色, 线条粗度)
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, (255, 255, 0), -1)
# 5. 画一个多边形
# 定义多边形的顶点
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2))
# cv2.polylines(图像, 顶点数组, 是否闭合, 颜色, 线条粗度)
cv2.polylines(img, [pts], True, (0, 255, 255), 3)
# 6. 添加文字
# cv2.putText(图像, 文本, 坐标, 字体, 大小, 颜色, 粗细)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv2.LINE_AA)
cv2.imshow('Drawings', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

形态学操作

形态学操作基于图像形状进行处理,常用于去除噪声、连接断开的物体等,它需要两个输入:原始图像和一个结构元素(Kernel)。

a. 腐蚀 与膨胀

import cv2
import numpy as np
# 创建一个带噪声的图像
img = np.zeros((50, 50), np.uint8)
cv2.rectangle(img, (10, 10), (40, 40), 255, -1)
cv2.circle(img, (25, 25), 5, 0, -1) # 添加一个黑色噪声点
# 定义一个结构元素 (一个 3x3 的矩形)
kernel = np.ones((3, 3), np.uint8)
# 腐蚀: 像素值与结构元素做与操作,会“腐蚀”掉白色部分的边界
eroded_img = cv2.erode(img, kernel, iterations=1)
# 膨胀: 像素值与结构元素做或操作,会“扩大”白色部分
dilated_img = cv2.dilate(img, kernel, iterations=1)
cv2.imshow('Original', img)
cv2.imshow('Eroded', eroded_img)
cv2.imshow('Dilated', dilated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

b. 开运算 与闭运算

  • 开运算 = 先腐蚀后膨胀,用于去除小的白色噪点,并平滑物体轮廓。
  • 闭运算 = 先膨胀后腐蚀,用于填充物体内部的小黑洞。
import cv2
import numpy as np
# 创建一个带噪声的图像
img = np.zeros((50, 50), np.uint8)
cv2.rectangle(img, (10, 10), (40, 40), 255, -1)
cv2.circle(img, (25, 25), 5, 0, -1) # 内部噪声
cv2.circle(img, (5, 5), 2, 255, -1) # 外部噪声
kernel = np.ones((3, 3), np.uint8)
# 开运算
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 闭运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('Original', img)
cv2.imshow('Opening', opening)
cv2.imshow('Closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图

直方图用于统计图像中像素强度(灰度值)的分布。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_COLOR)
# 计算直方图
# cv2.calcHist([图像列表], 通道索引, 掩码, 直方图大小, 范围)
# 对于彩色图像,我们需要分别计算每个通道的直方图
hist_b = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_g = cv2.calcHist([img], [1], None, [256], [0, 256])
hist_r = cv2.calcHist([img], [2], None, [256], [0, 256])
# 使用 Matplotlib 绘制直方图
plt.figure(figsize=(10, 5))'Color Histogram')
plt.xlabel('Pixel Value')
plt.ylabel('Count')
plt.plot(hist_b, color='blue', label='Blue Channel')
plt.plot(hist_g, color='green', label='Green Channel')
plt.plot(hist_r, color='red', label='Red Channel')
plt.legend()
plt.show()

项目实战:人脸检测

我们将使用 OpenCV 自带的 Haar 级联分类器来检测图像中的人脸。

准备工作

你需要下载 Haar 级联分类器的 XML 文件,最常用的是 haarcascade_frontalface_default.xml。 你可以从这里下载:OpenCV GitHub Repository

将下载的 XML 文件放在你的项目文件夹中。

代码示例

import cv2
# --- 1. 加载 Haar 级联分类器 ---
# 确保文件路径正确
face_cascade_path = 'haarcascade_frontalface_default.xml'
eye_cascade_path = 'haarcascade_eye.xml' # (可选) 检测眼睛
# 创建级联分类器对象
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
# 检查分类器是否加载成功
if face_cascade.empty():
    print(f"错误:无法加载人脸级联分类器,请检查路径: {face_cascade_path}")
    exit()
# --- 2. 读取图像 ---
image_path = 'path/to/your/people.jpg' # <--- 替换为包含人脸的图片路径
img = cv2.imread(image_path)
if img is None:
    print(f"错误:无法加载图像,请检查路径: {image_path}")
    exit()
# --- 3. 转换为灰度图 ---
# 人脸检测在灰度图上更快、更准确
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# --- 4. 检测人脸 ---
# detectMultiScale() 会返回检测到的人脸的列表
# 每个人脸是一个矩形 [x, y, w, h]
# 参数:
# - scaleFactor: 图像缩放比例,用于创建图像金字塔
# - minNeighbors: 检测矩形保留多少个邻近矩形才算有效
# - minSize: 可能的最小人脸尺寸
faces = face_cascade.detectMultiScale(gray_img, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
# --- 5. 在检测到的人脸上画矩形 ---
print(f"发现 {len(faces)} 张人脸。")
for (x, y, w, h) in faces:
    # 在原图上画一个矩形框
    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
    # (可选) 在人脸区域内检测眼睛
    roi_gray = gray_img[y:y+h, x:x+w]
    roi_color = img[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    for (ex, ey, ew, eh) in eyes:
        cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
# --- 6. 显示结果 ---
cv2.imshow('Face Detection', img)
# --- 7. 等待按键并关闭窗口 ---
cv2.waitKey(0)
cv2.destroyAllWindows()

总结与进阶

这份教程涵盖了 OpenCV 的核心功能,要深入学习,你可以:

  1. 官方文档OpenCV-Python Tutorials 是最权威的资源。
  2. 实战项目:尝试实现更复杂的项目,如物体识别、车牌识别、手势识别、图像风格迁移等。
  3. 学习机器学习:OpenCV 与机器学习(特别是 DNN 模块)结合,可以实现更强大的功能,如使用预训练的深度学习模型进行分类、检测等。
  4. 关注性能:对于实时应用,了解如何优化代码(例如使用多线程、GPU加速)非常重要。

希望这份教程能帮助你开启 OpenCV 的精彩世界!

分享:
扫描分享到社交APP
上一篇
下一篇