OpenCV 核心功能详解教程(Python版)从基础到进阶第二章
OpenCV是计算机视觉领域的“瑞士军刀”,支持图像/视频处理、特征提取、目标检测等核心功能。
本教程以基础篇 和 进阶篇 2部分对OpenCV 功能进行详解,结合 Python 代码、参数说明及原理讲解,带你系统掌握OpenCV的核心技能
内容摘要
轮廓检测,模板匹配,图像平滑(滤波),形态学操作
-
轮廓检测
用途:提取图像中连通区域的轮廓,用于形状分析。
核心函数:
cv2.findContours(image, mode, method):
mode 如 cv2.RETR_TREE
method 如 cv2.CHAIN_APPROX_SIMPLE检索模式(mode):
方法名称 用途 参数说明 原理 cv2.RETR_EXTERNAL 只检测最外层轮廓 适用于提取简单物体的外轮廓(如一个独立物体 仅返回没有父轮廓的轮廓(层级结构中的顶层) cv2.RETR_LIST 检测所有轮廓,不建立层级关系 适用于无需分析轮廓父子关系的场景 所有轮廓存储在列表中,无层级嵌套关系 cv2.RETR_CCOMP 检测所有轮廓,并将轮廓组织为两级结构(外层和内孔) 适用于需要区分物体和外孔的场景(如带孔的零件) 所有轮廓分为两级:顶层是外部轮廓,第二层是内孔轮廓 cv2.RETR_TREE 检测所有轮廓,并建立完整的层级树结构 适用于需要分析轮廓嵌套关系的场景(如嵌套的几何图形) 生成完整的父子层级关系树 近似方法(method):
方法名称 用途 参数说明 原理 cv2.CHAIN_APPROX_NONE 存储轮廓所有点的坐标 保留完整轮廓细节,适用于需要精确坐标的场景 轮廓点以连续坐标形式存储(内存占用较大) cv2.CHAIN_APPROX_SIMPLE 压缩水平、垂直和对角线段,仅保留端点 减少轮廓点数量,适用于矩形、多边形等规则形状 删除冗余点,仅保留线段转折点(内存优化) cv2.CHAIN_APPROX_TC89_L1 使用 Teh-Chin 链逼近算法(L1 范数) 适用于复杂曲线的高效逼近 基于链式近似算法,平衡精度与效率 cv2.CHAIN_APPROX_TC89_KCOS 使用 Teh-Chin 链逼近算法(K-COS 范数) 同上,但使用不同范数计算 同上,但逼近方式略有不同 实际应用场景举例
名称 应用场景 RETR_EXTERNAL OCR 文字轮廓检测(仅需外框) RETR_CCOMP 工业零件孔洞检测(区分物体和孔) RETR_TREE 医学图像中嵌套器官分析 CHAIN_APPROX_SIMPLE 矩形/多边形物体识别(减少计算量) 示例代码:
import cv2 import numpy as np # 1. 读取图像并二值化 img = cv2.imread('shapes.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 2. 轮廓检测(使用RETR_TREE和CHAIN_APPROX_SIMPLE) contours, hierarchy = cv2.findContours( binary, mode=cv2.RETR_TREE, # 检索模式:层级树结构 method=cv2.CHAIN_APPROX_SIMPLE # 近似方法:压缩冗余点 ) # 3. 绘制轮廓 cv2.drawContours(img, contours, -1, (0, 0, 255), 2) cv2.imshow('Contours', img) cv2.waitKey(0)
-
模板匹配
用途:在图像中查找模板位置,用于目标定位。
核心函数:
cv2.matchTemplate(image, templ, method):
method 如 cv2.TM_CCOEFF_NORMED。方法名称 函数名称 数学原理 适用场景 平方差匹配法 cv2.TM_SQDIFF 计算模板与图像区域的平方差,值越小匹配度越高。 适用于模板与图像区域的亮度差异较大的场景,匹配结果越接近0越好 归一化平方差匹配法 cv2.TM_SQDIFF_NORMED 对平方差进行归一化处理,值范围 [0, 1]。 对光照变化鲁棒,适合模板和图像亮度不一致的情况 相关匹配法 cv2.TM_CCORR 计算模板与图像区域的互相关,值越大匹配度越高 对亮度敏感,若图像亮度整体偏高可能导致误匹配。 归一化相关匹配法 cv2.TM_CCORR_NORMED 归一化互相关,值范围 [0, 1] 减少亮度变化的影响,适合光照不均匀但图案相似的情况 相关系数匹配法 cv2.TM_CCOEFF 基于模板和图像的均值计算相关性,值越大匹配度越高。 对模板和图像的亮度变化不敏感,适合复杂背景下的匹配 归一化相关系数匹配法 cv2.TM_CCOEFF_NORMED 归一化相关系数,值范围 [-1, 1],1表示完全匹配。 最常用方法,对光照、对比度变化鲁棒,适合大多数场景。 示例代码:
import cv2 import numpy as np # 读取图像和模板 img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) template = cv2.imread('template.jpg', cv2.IMREAD_GRAYSCALE) h, w = template.shape # 执行模板匹配(以归一化相关系数法为例) result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED) # 获取最佳匹配位置 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) top_left = max_loc # TM_CCOEFF_NORMED取最大值位置 bottom_right = (top_left[0] + w, top_left[1] + h) # 绘制矩形框 cv2.rectangle(img, top_left, bottom_right, 255, 2) cv2.imshow('Match Result', img) cv2.waitKey(0)
-
图像平滑(滤波)
用途:去除噪声,提升图像质量。方法名称 函数名称 核心参数 数学原理 优点 缺点 适用场景 均值滤波 cv2.blur() 或 cv2.boxFilter() ksize: 滤波核大小(如 (5,5))normalize: 是否归一化(仅 boxFilter) 邻域内像素值的算术平均 计算简单、速度快 边缘模糊,噪声抑制能力弱 快速去除轻微噪声,对计算资源要求低 高斯滤波 cv2.GaussianBlur() ksize: 高斯核大小(正奇数,如 (5,5))sigmaX: X方向标准差(0表示自动计算) 邻域内像素的高斯加权平均,权重随距离中心点增加而衰减。 保留边缘较好,抗高斯噪声强 计算量较大 图像预处理(如边缘检测前)、高斯噪声去除 中值滤波 cv2.medianBlur() ksize: 滤波核大小(正奇数,如 5) 邻域内像素值排序后取中值。 有效去除椒盐噪声,保护边缘 对大面积连续噪声效果差 椒盐噪声、脉冲噪声去除(如老旧照片修复) 双边滤波 cv2.bilateralFilter() d: 邻域直径sigmaColor: 颜色空间标准差sigmaSpace: 坐标空间标准差 结合空间邻近度和像素值相似性的加权平均,保留边缘的同时平滑 保持边缘清晰,去噪效果好 计算速度极慢 高精度图像去噪(如人像美化)、边缘敏感场景 方框滤波 cv2.boxFilter() ksize: 核大小normalize: 归一化开关(默认True,同均值滤波) 邻域内像素值的和(可归一化为均值滤波) 灵活性高(可控制是否归一化) 非归一化时易导致数值溢出 特殊需求(如积分图计算)、快速均值滤波替代 示例代码
import cv2 import numpy as np img = cv2.imread('noisy_image.jpg') # 1. 均值滤波 blur = cv2.blur(img, (5,5)) # 2. 高斯滤波 gaussian = cv2.GaussianBlur(img, (5,5), sigmaX=0) # 3. 中值滤波 median = cv2.medianBlur(img, 5) # 4. 双边滤波 bilateral = cv2.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75) # 5. 方框滤波(未归一化) box_filter = cv2.boxFilter(img, -1, (5,5), normalize=False) # 显示结果(示例) cv2.imshow('Original', img) cv2.imshow('Mean Blur', blur) cv2.imshow('Gaussian Blur', gaussian) cv2.imshow('Median Blur', median) cv2.imshow('Bilateral Filter', bilateral) cv2.waitKey(0)
-
形态学操作
用途:处理二值图像,用于去噪、连接区域。方法名称 函数名称 参数说明 原理/作用 适用场景 腐蚀 (Erosion) cv2.erode(src, kernel, iterations=1) - kernel: 结构元素(如矩形、椭圆)- iterations: 操作次数 用结构元素扫描图像,取邻域内最小值,消除小物体或细化边缘 去除噪声、分离粘连物体 膨胀 (Dilation) cv2.dilate(src, kernel, iterations=1) - kernel: 结构元素- iterations: 操作次数 取邻域内最大值,扩大亮区域,连接断裂部分 填充孔洞、连接相邻区域 开运算 (Opening) cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel) - kernel: 结构元素 先腐蚀后膨胀,消除小噪声并保留原形状。 去除亮背景中的暗噪声(如斑点) 闭运算 (Closing) cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel) - kernel: 结构元素 先膨胀后腐蚀,填充孔洞并保留原形状 填充暗区域中的亮孔洞(如指纹断裂 形态学梯度 (Morphological Gradient) cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel) - kernel: 结构元素 膨胀图与腐蚀图的差值,提取物体边缘 边缘检测、轮廓增强。 顶帽 (Top Hat) cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel) - kernel: 结构元素 原图与开运算的差值,突出比原图更亮的微小区域。 检测亮背景中的暗细节(如文本增强) 黑帽 (Black Hat) cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel) - kernel: 结构元素 闭运算与原图的差值,突出比原图更暗的微小区域。 检测暗背景中的亮细节(如医学图像中的微小病灶) 参数补充说明
结构元素 (kernel):
可通过 cv2.getStructuringElement(shape, size) 创建,shape 可选:
cv2.MORPH_RECT(矩形)
cv2.MORPH_ELLIPSE(椭圆)
cv2.MORPH_CROSS(十字形)
示例:kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
边界处理:
默认使用 cv2.BORDER_CONSTANT 填充边界,可通过 borderType 参数修改。示例代码:
import cv2 import numpy as np # 读取图像并二值化 img = cv2.imread('input.png', cv2.IMREAD_GRAYSCALE) _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 创建矩形结构元素 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) # 腐蚀 eroded = cv2.erode(binary, kernel, iterations=1) # 开运算 opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) # 形态学梯度 gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel) # 显示结果 cv2.imshow('Original', binary) cv2.imshow('Erosion', eroded) cv2.imshow('Opening', opening) cv2.imshow('Gradient', gradient) cv2.waitKey(0)
总结
本文介绍了轮廓检测,模板匹配,图像平滑(滤波),形态学操作,建议大家结合实际情况选择适合的函数多练习比较.