博客

  • OpenCV 从入门到精通教程-第5章 形态学操作

    第5章 形态学操作

    形态学操作基于形状,通常作用于二值图像,也可用于灰度图。

    5.1 腐蚀与膨胀

    • 腐蚀(Erosion):减小前景物体,消除细小噪声。
    • 膨胀(Dilation):扩大前景区域,填充空洞。

    python

    kernel = np.ones((5,5), np.uint8)
    erosion = cv2.erode(img, kernel, iterations=1)
    dilation = cv2.dilate(img, kernel, iterations=1)

    5.2 开运算、闭运算、形态学梯度、顶帽、黑帽

    • 开运算 = 先腐蚀再膨胀 → 消除小物体、分离连接区域。
    • 闭运算 = 先膨胀再腐蚀 → 填充前景物体内部的小孔、连接邻近区域。
    • 形态学梯度 = 膨胀图 – 腐蚀图 → 提取边缘。
    • 顶帽(Top Hat) = 原图 – 开运算 → 提取比周围亮的区域。
    • 黑帽(Black Hat) = 闭运算 – 原图 → 提取比周围暗的区域。

    python

    opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
    closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
    gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
    tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
    blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

    5.3 应用实例

    提取物体边界 = 膨胀图 – 腐蚀图,或者使用形态学梯度。
    去除小噪声:先开运算去掉白点,如果噪声是黑点则可使用闭运算。


    第6章 图像阈值与分割

    6.1 全局阈值与自适应阈值

    阈值处理是将灰度图转换为二值图的基本操作。

    python

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 全局固定阈值 (阈值, 最大值, 类型)
    _, thresh_binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    _, thresh_inv = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)

    自适应阈值:根据像素邻域局部计算阈值,适合光照不均的图像。

    python

    adaptive = cv2.adaptiveThreshold(gray, 255, 
                    cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                    cv2.THRESH_BINARY, 11, 2)   # 块大小11,常数C=2

    6.2 Otsu 二值化

    Otsu 方法自动计算最佳阈值,适用于双峰直方图图像。

    python

    _, otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    不必手动指定阈值,算法自动寻找最小化类内方差的阈值。

    6.3 分水岭算法简介

    分水岭算法是一种基于拓扑的图像分割方法,可分离相互接触的物体。简要步骤:

    1. 通过距离变换获取“种子”区域(前景标记)。
    2. 生成未知区域,使用 cv2.watershed

    python

    # 简单示例(需要预处理)
    ret, markers = cv2.connectedComponents(sure_fg)
    markers = markers + 1
    markers[unknown==255] = 0
    markers = cv2.watershed(img, markers)
    img[markers == -1] = [0,0,255]   # 边界标注为红色

    分水岭算法对噪声较敏感,通常需要预处理降噪。


    第7章 轮廓分析

    轮廓是图像中连续点的集合,常用于形状分析、目标检测。

    7.1 查找与绘制轮廓

    python

    # 使用二值图像查找轮廓
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 绘制所有轮廓(-1 表示所有轮廓, (0,255,0) 为绿色, 线宽2)
    cv2.drawContours(img, contours, -1, (0,255,0), 2)

    7.2 轮廓特征

    对于每个轮廓,可以计算诸多特征:

    python

    cnt = contours[0]
    area = cv2.contourArea(cnt)               # 面积
    perimeter = cv2.arcLength(cnt, True)      # 周长(True表示闭合)
    x, y, w, h = cv2.boundingRect(cnt)        # 直边界矩形
    rect = cv2.minAreaRect(cnt)               # 最小外接旋转矩形
    box = cv2.boxPoints(rect)                 # 获取四个顶点坐标(float)
    box = np.int0(box)                        # 取整
    (x_c,y_c), radius = cv2.minEnclosingCircle(cnt)  # 最小外接圆

    获取矩(moments)可计算质心:

    python

    M = cv2.moments(cnt)
    cx = int(M['m10'] / M['m00'])
    cy = int(M['m01'] / M['m00'])

    7.3 轮廓近似与凸包

    轮廓近似(Douglas-Peucker 算法):

    python

    epsilon = 0.01 * cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)

    可用于形状识别,例如一个四边形 approx 长度为4。

    凸包(Convex Hull):

    python

    hull = cv2.convexHull(cnt)

    用于凸缺陷检测。

    7.4 形状匹配

    使用 cv2.matchShapes 基于 Hu 矩比较形状相似度,返回值越小越相似。

    python

    ret = cv2.matchShapes(cnt1, cnt2, cv2.CONTOURS_MATCH_I2, 0.0)

  • OpenCV 从入门到精通教程-第3章 图像几何变换

    第3章 图像几何变换

    3.1 缩放、平移、旋转

    缩放

    python

    resized = cv2.resize(img, (width, height))   # 指定尺寸
    resized = cv2.resize(img, None, fx=0.5, fy=0.5)   # 比例缩放

    常用插值方法:cv2.INTER_LINEAR(默认)、cv2.INTER_CUBICcv2.INTER_AREA(适合缩小)。

    平移:通过构建平移矩阵实现。

    python

    rows, cols = img.shape[:2]
    # x 方向平移 50,y 方向平移 100
    M = np.float32([[1, 0, 50], [0, 1, 100]])
    translated = cv2.warpAffine(img, M, (cols, rows))

    旋转

    python

    # 获取围绕图像中心的旋转矩阵(角度为正表示逆时针)
    M = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1.0)
    rotated = cv2.warpAffine(img, M, (cols, rows))

    3.2 仿射变换与透视变换

    仿射变换:平行线保持平行。需要原图中三个不共线的点和目标图中对应的三个点。

    python

    pts1 = np.float32([[50,50],[200,50],[50,200]])
    pts2 = np.float32([[10,100],[200,50],[100,250]])
    M = cv2.getAffineTransform(pts1, pts2)
    affine = cv2.warpAffine(img, M, (cols, rows))

    透视变换:任意四边形到矩形的变换。需要四个对应点。

    python

    pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
    pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
    M = cv2.getPerspectiveTransform(pts1, pts2)
    perspective = cv2.warpPerspective(img, M, (300,300))

    透视变换在文档扫描、车牌校正中非常常用。

    3.3 图像金字塔

    图像金字塔是同一图像不同分辨率的集合,常用于图像融合、特征检测。

    • 高斯金字塔:向下采样(缩小)
    • 拉普拉斯金字塔:由高斯金字塔计算而得,常用于图像恢复

    python

    lower_res = cv2.pyrDown(img)   # 宽度和高度减半
    higher_res = cv2.pyrUp(img)    # 宽度和高度加倍

    示例:反复执行下采样得到的图像金字塔。


    第4章 图像滤波与增强

    4.1 平滑滤波

    平滑(模糊)可以去除噪声,但也可能丢失边缘细节。

    • 均值滤波:简单平均
    • 高斯滤波:加权平均,中心权重大,去噪同时保留边缘更多
    • 中值滤波:取邻域中值,有效去除椒盐噪声
    • 双边滤波:保持边缘的平滑,考虑空间邻近度和像素相似度

    python

    # 均值滤波 (5x5 核)
    blur = cv2.blur(img, (5,5))
    # 高斯滤波 (核大小必须为正奇数)
    gaussian = cv2.GaussianBlur(img, (5,5), 0)
    # 中值滤波 (核大小取奇数)
    median = cv2.medianBlur(img, 5)
    # 双边滤波 (直径, sigmaColor, sigmaSpace)
    bilateral = cv2.bilateralFilter(img, 9, 75, 75)

    4.2 边缘检测

    边缘是图像中亮度急剧变化的区域。OpenCV 提供了多种边缘检测算子。

    • Sobel 算子:计算一阶导数,可指定方向。
    • Laplacian 算子:计算二阶导数。
    • Canny 边缘检测:最常用的方法,低错误率、良好定位。

    python

    # Sobel
    sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)   # x方向
    sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)   # y方向
    sobel_absx = cv2.convertScaleAbs(sobelx)              # 转为 uint8
    sobel_combined = cv2.addWeighted(sobel_absx, 0.5, cv2.convertScaleAbs(sobely), 0.5, 0)
    
    # Laplacian
    laplacian = cv2.Laplacian(img, cv2.CV_64F)
    laplacian_abs = cv2.convertScaleAbs(laplacian)
    
    # Canny(推荐使用灰度图)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 100, 200)   # 阈值1, 阈值2

    Canny 中较小的阈值用于边缘连接,较大的阈值用于检测强边缘。通常阈值2是阈值1的2~3倍。

    4.3 图像锐化

    通过增强高频成分使图像边缘更清晰。可以自定义一个锐化核:

    python

    kernel = np.array([[0, -1, 0],
                       [-1, 5,-1],
                       [0, -1, 0]])
    sharpened = cv2.filter2D(img, -1, kernel)

  • OpenCV 从入门到精通详细教程

      • 1.2 安装 OpenCV-Python
      • 1.3 第一个程序:读取并显示图像
    1. 图像基础操作
      • 2.1 图像读取、显示与保存
      • 2.2 图像属性与像素访问
      • 2.3 颜色空间转换
      • 2.4 图像算术运算与位运算
    2. 图像几何变换
      • 3.1 缩放、平移、旋转
      • 3.2 仿射变换与透视变换
      • 3.3 图像金字塔
    3. 图像滤波与增强
      • 4.1 平滑滤波(均值、高斯、中值、双边)
      • 4.2 边缘检测(Sobel、Laplacian、Canny)
      • 4.3 图像锐化
    4. 形态学操作
      • 5.1 腐蚀与膨胀
      • 5.2 开运算、闭运算、形态学梯度、顶帽、黑帽
      • 5.3 应用实例:提取边界、消除噪声
    5. 图像阈值与分割
      • 6.1 全局阈值与自适应阈值
      • 6.2 Otsu 二值化
      • 6.3 分水岭算法简介
    6. 轮廓分析
      • 7.1 查找与绘制轮廓
      • 7.2 轮廓特征(面积、周长、外接矩形等)
      • 7.3 轮廓近似与凸包
      • 7.4 形状匹配
    7. 直方图
      • 8.1 计算与绘制直方图
      • 8.2 直方图均衡化
      • 8.3 直方图比较与反向投影
    8. 模板匹配
    9. 特征检测与匹配
      • 10.1 Harris 角点检测
      • 10.2 SIFT 特征检测
      • 10.3 ORB 特征检测与匹配
      • 10.4 特征匹配与单应性查找
    10. 视频处理与分析
      • 11.1 读取视频与摄像头
      • 11.2 视频写入
      • 11.3 运动检测(帧差分、背景减除)
    11. 目标跟踪
      • 12.1 MeanShift 与 CamShift
      • 12.2 基于 KCF 等跟踪器 API
    12. 深度学习模块(DNN)
      • 13.1 加载预训练模型
      • 13.2 使用 YOLO 进行目标检测
    13. 综合项目实战
      • 14.1 人脸检测与识别
      • 14.2 文档扫描仪
      • 14.3 手势识别

    详细教程内容

    第1章 OpenCV 简介与环境搭建

    1.1 OpenCV 概述

    OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它提供了数千种算法,涵盖图像处理、视频分析、目标检测、人脸识别、三维重建等众多领域。OpenCV 支持 C++、Python、Java 等多种语言,可在 Windows、Linux、macOS、Android、iOS 等平台上运行。

    本教程使用 Python 语言,配合 opencv-python 包进行讲解。Python 语法简洁,适合快速原型开发和学习。

    1.2 安装 OpenCV-Python

    最简单的方式是通过 pip 安装主模块和扩展模块:

    bash

    pip install opencv-python opencv-contrib-python
    • opencv-python:包含核心模块。
    • opencv-contrib-python:包含额外的贡献模块(如 SIFT、SURF 等算法)。

    验证安装:

    python

    import cv2
    print(cv2.__version__)

    如果输出类似 4.8.0 的版本号,则安装成功。

    1.3 第一个程序:读取并显示图像

    python

    import cv2
    
    # 读取图像(路径中不能有中文)
    img = cv2.imread('test.jpg')
    
    # 检查是否读取成功
    if img is None:
        print("图像读取失败")
    else:
        # 显示图像窗口
        cv2.imshow('My Image', img)
        # 等待按键,0 表示无限等待
        cv2.waitKey(0)
        # 销毁所有窗口
        cv2.destroyAllWindows()

    运行后会弹出窗口显示图片,按任意键关闭。OpenCV 的窗口管理简单直接,适合调试。


    第2章 图像基础操作

    2.1 图像读取、显示与保存

    python

    # 读取为彩色图像(默认)
    img_color = cv2.imread('test.jpg', cv2.IMREAD_COLOR)
    # 读取为灰度图
    img_gray  = cv2.imread('test.jpg', cv2.IMREAD_GRAYSCALE)
    # 保存图像
    cv2.imwrite('gray.jpg', img_gray)

    常用标志:cv2.IMREAD_COLOR(1)、cv2.IMREAD_GRAYSCALE(0)、cv2.IMREAD_UNCHANGED(-1,包含 alpha 通道)。

    2.2 图像属性与像素访问

    OpenCV 中图像以 NumPy 数组形式存储,因此可以使用 NumPy 的所有操作。

    python

    img = cv2.imread('test.jpg')
    # 形状:(高度, 宽度, 通道数)
    print(img.shape)   # 例如 (480, 640, 3)
    # 总像素数
    print(img.size)    # 480*640*3 = 921600
    # 数据类型
    print(img.dtype)   # uint8
    
    # 访问某个像素:img[y, x, channel] (注意:先纵坐标后横坐标)
    pixel = img[100, 200]        # BGR 三个通道的值
    b = pixel[0]                 # 蓝色分量
    g = img[100, 200, 1]         # 绿色分量
    
    # 修改像素
    img[100, 200] = [0, 0, 255]  # 设为红色(BGR)
    
    # 取出 ROI(感兴趣区域)
    roi = img[50:200, 100:300]  # 行范围,列范围

    注意:OpenCV 默认颜色顺序是 BGR,而非 RGB,显示或保存时要留心。

    2.3 颜色空间转换

    python

    img = cv2.imread('test.jpg')
    # 转为灰度
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 转为 HSV
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    # 转为 RGB
    rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    HSV 空间在颜色筛选时非常有用,例如提取蓝色物体:

    python

    # 定义蓝色的 HSV 范围
    lower_blue = np.array([100, 50, 50])
    upper_blue = np.array([130, 255, 255])
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    # 显示原图中蓝色区域
    result = cv2.bitwise_and(img, img, mask=mask)
    cv2.imshow('Blue regions', result)

    2.4 图像算术运算与位运算

    两幅图像相加(需要尺寸和通道数相同):

    python

    img1 = cv2.imread('a.jpg')
    img2 = cv2.imread('b.jpg')
    add = cv2.add(img1, img2)            # 饱和运算
    weighted = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)  # 混合

    位运算(常用于掩膜操作):

    python

    # 创建矩形掩膜
    mask = np.zeros(img.shape[:2], np.uint8)
    cv2.rectangle(mask, (100,100), (300,300), 255, -1)
    masked_img = cv2.bitwise_and(img, img, mask=mask)

  • 世界,您好!

    欢迎使用 WordPress。这是您的第一篇文章。编辑或删除它,然后开始写作吧!