OpenCV2
水平方向卷积核:-1 & 0 & 1垂直方向卷积核:1 & 2 & 1计算原理:通过卷积运算检测图像中像素值的突变,分别捕捉水平和垂直方向的边缘信息。
课时11:Sobel算子_笔记
知识小结表格
| 知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
|---|---|---|---|
| 图像梯度计算 | 通过Sobel算子计算图像梯度,分别计算水平方向(gx)和垂直方向(gy)的像素差异 | 边界点梯度计算逻辑(左右/上下像素差异) | ⭐⭐ |
| Sobel算子原理 | 使用卷积核(如[1, 2, 1]和[-1, -2, -1])进行加权差分计算,离中心点越近权重越高 | 核函数定义(正负值分配与高斯权重关系) | ⭐⭐⭐ |
| 梯度方向与边缘检测 | 梯度大的位置对应图像边缘(如白黑交界处),梯度小的区域为均匀像素(如纯色区域) | 梯度与边缘的关联性(非边缘区域梯度为零) | ⭐⭐ |
| OpenCV实现 | cv2.Sobel()函数参数解析:dx/dy控制方向、ksize定义核大小、CV_64F保留负梯度值 |
负值截断问题(需手动取绝对值) | ⭐⭐⭐ |
| 实验演示 | 对黑白圆形图像应用Sobel算子,水平梯度(gx)结果中白点为有效边缘 | 边界点可视化验证(梯度仅出现在颜色突变处) | ⭐⭐ |
课时12:梯度计算方法_笔记
Sobel算子边缘检测
函数参数解析

函数原型:dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth:输出图像的深度,常用cv2.CV_64F保留负数计算结果dx/dy:求导阶数,1表示计算该方向梯度(dx=1为水平方向,dy=1为垂直方向)ksize:Sobel核大小,通常取3(3×3卷积核)
梯度计算原理
计算规则:始终采用“右边减左边”的差分方法
- 水平梯度(
dx=1):每个像素点用其右侧像素值减去左侧像素值 - 垂直梯度(
dy=1):每个像素点用其下方像素值减去上方像素值
数值特性:
- 白到黑过渡:产生正数(如255-0=255)
- 黑到白过渡:产生负数(如0-255=-255)
- 截断问题:OpenCV默认将负数截断为0,导致部分边缘信息丢失
绝对值转换技巧 
必要性:保留负梯度信息,避免边缘缺失
实现方法:
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx_abs = cv2.convertScaleAbs(sobelx)
效果对比:
- 原始结果:仅显示正梯度对应的边缘(如圆形左半边)
- 转换后:完整显示所有边缘(圆形左右半边均可见)
多方向梯度合成

分步计算:
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
合成方法:加权相加
combined = cv2.addWeighted(sobelx_abs, 0.5, sobely_abs, 0.5, 0)
注意事项:
- 不建议直接使用
dx=1, dy=1参数计算,效果不如分步计算准确 - 权重系数可根据实际需求调整(通常各取0.5保持平衡)
图像梯度
Sobel算子介绍
算子结构:
- 水平方向卷积核:
[
\begin{bmatrix}
-1 & 0 & 1 \
-2 & 0 & 2 \
-1 & 0 & 1
\end{bmatrix}
] - 垂直方向卷积核:
[
\begin{bmatrix}
-1 & -2 & -1 \
0 & 0 & 0 \
1 & 2 & 1
\end{bmatrix}
]
计算原理:通过卷积运算检测图像中像素值的突变,分别捕捉水平和垂直方向的边缘信息。
Sobel算子计算过程

函数原型:dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth:输出图像的深度,常用cv2.CV_64F保留负数结果dx/dy:求导阶数,1表示计算该方向梯度ksize:卷积核大小,通常为3
绝对值转换:
sobelx_abs = cv2.convertScaleAbs(sobelx)
sobely_abs = cv2.convertScaleAbs(sobely)
梯度求和的方法

求和公式:
[
G = \sqrt{G_x^2 + G_y^2}
]
或
[
G = |G_x| + |G_y|
]
OpenCV实现:
combined = cv2.addWeighted(sobelx_abs, 0.5, sobely_abs, 0.5, 0)
优势:比直接计算(dx=1,dy=1)效果更好,能保留更多边缘细节
最佳实践
- 始终采用分别计算后加权求和的方式
- 权重调整:根据实际任务需求调整x/y方向权重比例
Sobel算子图像梯度计算

梯度计算实现方法

函数原型:dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth:输出图像深度(推荐使用cv2.CV_64F保留负值)dx/dy:求导阶数(1表示计算该方向梯度)ksize:卷积核大小(通常为3)
绝对值转换:
sobelx_abs = cv2.convertScaleAbs(sobelx)
sobely_abs = cv2.convertScaleAbs(sobely)
组合梯度计算方法

推荐方法:分别计算x和y方向梯度
combined = cv2.addWeighted(sobelx_abs, 0.5, sobely_abs, 0.5, 0)
不推荐方法:直接设置dx=1, dy=1同时计算
问题:会产生重影和模糊
实际应用示例

操作步骤:
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobelx_abs = cv2.convertScaleAbs(sobelx)
sobely_abs = cv2.convertScaleAbs(sobely)
combined = cv2.addWeighted(sobelx_abs, 0.5, sobely_abs, 0.5, 0)
注意事项:原始图像应先转换为灰度图处理
梯度计算与边界检测知识小结
核心内容与技术实现
| 知识点 | 关键操作 | 技术难点 |
|---|---|---|
| 水平梯度计算原理 | gx = right - left |
负数截断导致信息丢失 |
| 垂直梯度计算原理 | gy = bottom - top |
对称性保持 |
| 梯度方向信息保留 | cv2.convertScaleAbs() |
负值转换为绝对值 |
| 梯度融合 | cv2.addWeighted(gx, 0.5, gy, 0.5, 0) |
权重分配优化 |
卷积核与数学表达
| 类型 | 卷积核示例 | 数学公式 | 输出效果 |
|---|---|---|---|
| 水平(x) | [1, 0, -1] |
gx = I(x+1,y) - I(x-1,y) |
垂直边界突出 |
| 垂直(y) | [1; 0; -1] |
gy = I(x,y+1) - I(x,y-1) |
水平边界突出 |
| 组合梯度 | - | sqrt(gx² + gy²) |
完整轮廓检测 |
常见问题与解决方案
| 现象 | 原因分析 | 解决方案 | 效果验证 |
|---|---|---|---|
| 右侧边界缺失 | 负梯度值被截断 | 绝对值转换 | 边界完整显示 |
| 轮廓断裂 | 单方向梯度局限 | 双梯度融合 | 连续性提升 |
| 重影现象 | 直接合并计算 | 分别计算后加权 | 边界清晰度优化 |
课时13:scharr与lapkacian算子_笔记
Scharr算子

核结构
水平方向核:
垂直方向核:
特点:
- 数值差异:相比Sobel算子核值更大(如-10替代-2),对边缘变化更敏感
- 计算方式:与Sobel算子相同,但能捕捉更细微的梯度变化
- 应用场景:适合需要检测弱边缘或精细纹理的图像处理任务
Laplacian算子

核结构:
计算原理:
- 二阶导数:通过中心点与周围四点比较,公式为
- 边界检测:直接比较中心像素与邻域像素的差异
特性:
- 高敏感性:对噪声和边缘变化都极为敏感
- 使用限制:通常需与其他方法结合使用,单独使用易受噪声干扰
- 计算优势:无需分别计算x和y方向梯度,直接输出结果
算子对比

函数调用差异:
- Sobel:
cv2.Sobel(img, cv2.CV_64F, dx, dy, ksize=3) - Scharr:
cv2.Scharr(img, cv2.CV_64F, dx, dy) - Laplacian:
cv2.Laplacian(img, cv2.CV_64F)
结果处理:
- 均需使用
convertScaleAbs()转换负值为绝对值 - Sobel/Scharr需用
addWeighted()合并x/y方向结果
实例分割:
- Sobel结果:能检测主要边界但会遗漏部分细节(如头发丝纹理),对中等强度边缘响应较好
- Scharr结果:线条更丰富,能捕捉更细小的边缘(如面部细微纹理),对弱边缘的检测能力显著优于Sobel
- Laplacian结果:噪声响应明显,边界识别效果较差,需配合降噪预处理才能有效使用
实践建议:
- 优先使用Scharr算子获取精细边缘
- Laplacian算子需结合高斯滤波等降噪手段
- 实时系统可选用Sobel平衡性能与效果
以下是关于边缘检测算子的结构化对比分析,采用表格形式呈现:
核心特性对比
| 维度 | Sobel算子 | Scharr算子 | Laplacian算子 |
|---|---|---|---|
| 类型 | 一阶微分 | 优化一阶微分 | 二阶微分 |
| 核结构示例 | 横向核:[-1,0,1] 纵向核:[-1,-2,-1] | [-3,0,3; -10,0,10; -3,0,3] | [0,1,0; 1,-4,1; 0,1,0] |
| 数学表达 | Gx + Gy | 加权差分 | ∇²f = ∂²f/∂x² + ∂²f/∂y² |
| 敏感度 | 中等 | 高 | 极高 |
性能评估
| 评估指标 | Sobel算子 | Scharr算子 | Laplacian算子 |
|---|---|---|---|
| 边缘连续性 | 中等 | 优秀 | 碎片化 |
| 噪声抑制 | 一般 | 一般 | 较差 |
| 细节保留 | 基础层次 | 多层级 | 过度突出 |
| 计算效率 | 高 | 中高 | 高 |
OpenCV实现参数
| 函数 | 关键参数 | 输出类型 | 后处理要求 |
|---|---|---|---|
cv2.Sobel() |
dx/dy分步计算 | 单通道梯度 | 加权融合 |
cv2.Scharr() |
自动增强系数 | 强化梯度 | 绝对值转换 |
cv2.Laplacian() |
直接二阶计算 | 零交叉图 | 阈值过滤 |
适用场景与局限
| 算子类型 | 最佳应用场景 | 主要局限性 |
|---|---|---|
| Sobel | 基础边缘检测 | 对噪声较敏感 |
| Scharr | 精细边缘提取 | 可能保留过多细节 |
| Laplacian | 突变区域检测 | 噪声放大明显 |
课时14:边缘检测_笔记
Canny边缘检测流程

使用高斯滤波器平滑图像,滤除噪声。计算每个像素点的梯度强度和方向。应用非极大值抑制消除杂散响应。应用双阈值检测确定真实和潜在边缘。抑制孤立的弱边缘完成最终检测。
高斯滤波器

作用:平滑图像并滤除噪声,避免噪音点影响梯度计算。
核结构:使用归一化处理的3×3高斯核,中心值最大(0.1538),边缘值逐渐减小。
计算方式:对所有像素进行加权求和。
梯度和方向

算子选择:使用Sobel算子,分别计算x和y方向的梯度。
水平方向算子,检测垂直边缘。
垂直方向算子,检测水平边缘。
梯度计算:幅值和方向。
非极大值抑制

目的:保留局部梯度最大值点,抑制非极大值响应。
两种方法:线性插值法和简化方法。
线性插值法:计算当前点梯度方向上的两个亚像素点(q,z)的梯度值,使用权重公式。
简化方法:将梯度方向离散为8个固定方向,直接比较当前点与固定方向上的相邻像素点。
判断标准:当前点梯度值必须大于相邻两个点的梯度值才能保留。
双阈值检测

阈值分类:强边缘、弱边缘和非边缘。
强边缘:梯度值 > maxVal(直接保留)。
弱边缘:minVal < 梯度值 < maxVal(需连接强边缘才保留)。
非边缘:梯度值 < minVal(直接舍弃)。
参数影响:阈值设置越大,检测到的边缘越少但更准确;阈值设置越小,检测到的边缘越多但可能包含噪声。
OpenCV边缘检测

函数调用:cv2.Canny(img, minVal, maxVal)。
典型值:低阈值(50-100),高阈值(100-250)。
效果对比:低阈值(50,100)检测更多边缘细节,但可能包含噪声;高阈值(80,150)/(120,250)保留主要边缘,减少噪声干扰。
选择原则:需要丰富边缘时使用较低阈值,需要精确边缘时使用较高阈值。
以下是关于Canny边缘检测算法的知识小结表格,涵盖核心流程、重点难点及OpenCV实现:
| 知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
|---|---|---|---|
| Canny边缘检测算法流程 | 1. 高斯滤波去噪 2. 计算梯度幅值与方向(Sobel算子) 3. 非极大值抑制(NMS) 4. 双阈值检测(MinVal/MaxVal) 5. 边界连接 |
- 梯度方向与边界的垂直关系 - 非极大值抑制的两种实现方法(线性插值法 vs 方向近似法) |
⭐⭐⭐⭐ |
| 高斯滤波的作用 | 平滑图像、抑制噪声,避免梯度计算受噪声干扰 | 滤波器权重分布规律(中心高、边缘低) | ⭐⭐ |
| 非极大值抑制(NMS) | - 比较当前点与梯度方向上的相邻点幅值 - 保留局部最大值(抑制非边界点) - 应用场景:人脸检测框去重 |
- 亚像素点插值计算(线性插值法) - 方向近似法的简化计算 |
⭐⭐⭐ |
| 双阈值检测原理 | - MaxVal:直接判定为强边界 - MinVal:直接舍弃 - 中间值:需连接强边界才保留 |
阈值设置对结果的影响: - 低阈值:边界更丰富(含噪声) - 高阈值:边界更稀疏(更严格) |
⭐⭐⭐⭐ |
| OpenCV实现 | cv2.Canny(image, minVal, maxVal) |
参数调优: - minVal=50, maxVal=100(敏感) - minVal=80, maxVal=150(严格) |
⭐⭐ |
| 梯度方向计算 | 通过Sobel算子的Gx和Gy分量计算arctan(Gy/Gx) |
边界方向与梯度方向垂直 | ⭐⭐⭐ |
课时15:图像金字塔定义和制作方法_笔记
图像金字塔
高斯金字塔

定义:将图像按金字塔形状分层处理,底层为原始尺寸(如800×800),每层尺寸递减(400×400→200×200→100×100→50×50)。
应用:多尺度特征提取、图像压缩处理。
向下采样方法
- 操作流程:
高斯滤波:使用核卷积删除偶数行/列,尺寸减半(如8×8→4×4)。 - 特点:每次采样面积变为原图的1/4,信息会逐步损失(模糊度增加)。
向上采样方法
- 操作流程:
像素扩充:每个方向扩大2倍,新增行列填0(如2×2→4×4)。
高斯滤波:使用相同核进行卷积。 - 示例:原始像素矩阵→扩充为。
拉普拉斯金字塔

计算公式:层级关系:→(Down)→→(Up)→。
特点:保留图像高频细节(边缘信息),常用于图像重建和特征分析。
金字塔应用示例

实验现象:原始图像清晰度>上采样+下采样结果,多次采样会导致累计信息损失。
OpenCV操作:
以下是整理后的知识小结表格:
| 主题 | 核心内容 | 关键操作 | 技术要点 |
|---|---|---|---|
| 高斯金字塔 | 图像多尺度表示方法 | 向下采样(缩小) | 1. 高斯滤波卷积 2. 删除偶数行/列 3. 面积缩减至1/4 |
| 向上采样(放大) | 1. 零值填充扩展 2. 高斯核卷积重建 3. 分辨率倍增 |
||
| 拉普拉斯金字塔 | 图像高频分量提取 | 差值计算 | Li=Gi−UP(DOWN(Gi))L_i = G_i - \text{UP(DOWN}(G_i))Li=Gi−UP(DOWN(Gi)) 保留边缘特征 |
| 应用场景 | 特征提取多尺度分析 | 金字塔层级联动 | 1. 不同层级特征融合 2. 信息补偿机制 |
| OpenCV实现 | 采样操作演示 | pyrUp/pyrDown函数 |
1. 上采样分辨率2倍 2. 下采样分辨率1/2 3. 累计信息损失 |
| 效果对比 | 采样重建测试 | 上采样+下采样组合 | 1. 图像模糊度增加 2. 色彩饱和度下降 |
公式说明
- 拉普拉斯金字塔计算:
Li=Gi−UP(DOWN(Gi))L_i = G_i - \text{UP(DOWN}(G_i))Li=Gi−UP(DOWN(Gi))
其中 GiG_iGi 为第i层高斯金字塔图像,UP\text{UP}UP 和 DOWN\text{DOWN}DOWN 分别表示上/下采样操作。
课时16:轮廓检测方法和检测结果_笔记轮廓检测方法
cv2.findContours 函数原型

cv2.findContours(img, mode, method)
参数说明
- img: 待检测的二值图像
- mode: 轮廓检索模式
RETR_EXTERNAL: 只检索最外面的轮廓RETR_LIST: 检索所有轮廓并保存到链表RETR_CCOMP: 检索所有轮廓并组织为两层结构RETR_TREE: 检索所有轮廓并重构嵌套层次(最常用)
- method: 轮廓逼近方法
CHAIN_APPROX_NONE: 以Freeman链码方式输出轮廓CHAIN_APPROX_SIMPLE: 压缩水平、垂直和斜的部分,只保留终点
参数解释
- 轮廓与边缘区别
- 边缘: 零散的线段,反映梯度变化
- 轮廓: 整体连通的边界,反映物体形状
- 模式选择建议: 推荐使用
RETR_TREE,它能完整保存所有轮廓的嵌套关系 - 方法选择:
CHAIN_APPROX_NONE保留所有轮廓点CHAIN_APPROX_SIMPLE进行压缩优化(如长方形只需4个顶点)
轮廓检测步骤
- 读取图像:
img = cv2.imread('image.png') - 灰度转换:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - 二值化处理
- 轮廓检测
轮廓检测操作
注意事项
- 必须使用二值图像作为输入
- 阈值处理时建议使用127作为阈值分界点
- 结果显示前需要复制原图
draw_img = img.copy(),避免修改原始图像
绘制轮廓cv2.drawContours(draw_img, contours, -1, (0,0,255), 2)
- 参数说明:
-1: 绘制所有轮廓(0,0,255): BGR颜色格式(红色)2: 线条粗细
层级访问
- 通过索引访问特定轮廓(如
contours[0]) - 负索引表示绘制所有轮廓
可视化技巧
- 不同轮廓可用不同颜色区分
- 线条粗细影响显示效果,建议使用2-3像素
应用案例

例题: 轮廓绘制操作流程
- 加载并预处理图像
- 检测轮廓
- 复制原图后绘制
- 显示结果
常见错误
- 忘记图像复制导致原图被修改
- 使用灰度图而非二值图作为输入
例题
: 轮廓检测层级分析
- 索引0对应最外层轮廓
- 索引1对应第二层轮廓
- 通过改变索引值可查看不同层级的轮廓
面积计算
(内容保持不变)
知识小结表格
| 知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
|---|---|---|---|
| 轮廓与边缘的区别 | 边缘是零散的线段,轮廓是连成整体的闭合形状 | 边缘检测≠轮廓检测,轮廓需闭合 | ⭐⭐ |
| 轮廓检测步骤 | 1. 读取图像→2. 转灰度图→3. 二值化处理→4. 调用cv2.findContours() |
二值化是必要前提(阈值处理) | ⭐⭐⭐ |
| findContours参数 | image(二值图)、mode(检测模式)、method(逼近方法) |
常用mode=RETR_TREE(检测所有轮廓并保存层级) |
⭐⭐⭐⭐ |
| 轮廓逼近方法 | CHAIN_APPROX_NONE(保留所有点) vs CHAIN_APPROX_SIMPLE(压缩冗余点) |
长方形轮廓:SIMPLE仅需4个角点 |
⭐⭐ |
| 轮廓绘制技巧 | 使用cv2.drawContours(),需先copy()原图避免覆盖 |
contourIdx=-1绘制全部轮廓,正数按索引绘制 |
⭐⭐⭐ |
| 层级结构 | 返回的hierarchy参数描述轮廓嵌套关系(如外轮廓包含内轮廓) |
实际应用需结合mode理解层级 |
⭐⭐⭐⭐ |
| 课时17:轮廓特征与近似_笔记 |
轮廓特征与近似
轮廓特征计算

提取方法
计算轮廓特征时需要先提取单个轮廓,如 cnt = contours[0] 获取第 0 个轮廓。
面积计算
使用 cv2.contourArea(cnt) 函数,示例结果为 8500.5。
周长计算
使用 cv2.arcLength(cnt, True) 函数,True 表示闭合轮廓,示例结果为 437.94826519489291。
轮廓近似
原理
通过直线段逼近曲线轮廓,采用递归二分法:
- 连接曲线端点 AB,找曲线上到 AB 直线距离最大的点 C。
- 若距离 d 小于阈值 t,则用 AB 直线近似。
- 否则将曲线分为 AC 和 CB 两段重复判断。

实现函数cv2.approxPolyDP(cnt, epsilon, True)
epsilon:关键参数,通常取周长的百分比(如 0.1 倍周长)。- 参数越小,近似结果越接近原轮廓。
效果对比
0.01倍周长:轮廓变化不明显。0.1倍周长:轮廓明显简化。0.15倍周长:近似为三角形。0.2倍周长:过度简化可能失真。
轮廓外接矩形

获取方法x, y, w, h = cv2.boundingRect(cnt),返回矩形左上角坐标 (x, y) 和宽高 (w, h)。
绘制方法cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)。
应用示例
计算轮廓面积与外接矩形面积比:area / rect_area,示例比值为 0.515,反映轮廓填充程度。
轮廓外接圆

获取方法(x, y), radius = cv2.minEnclosingCircle(cnt),返回圆心坐标和半径。
绘制方法cv2.circle(img, center, radius, (0, 255, 0), 2)。
特点
适用于不规则轮廓的最小包围圆计算。
以下是整理后的知识小结表格,涵盖轮廓特征计算的核心内容:
| 类别 | 核心内容 | 应用场景/功能 | 技术要点 |
|---|---|---|---|
| 轮廓特征计算 | OpenCV提供的轮廓处理函数 | 图像分析/特征提取 | cv2.contourArea()计算面积cv2.arcLength()计算周长 |
| 轮廓近似算法 | Douglas-Peucker算法 | 轮廓简化/规则化处理 | 通过阈值控制近似精度 递归分割最大偏移点 |
| 外接几何图形 | 最小外接矩形/圆 | 目标特征增强/几何分析 | cv2.boundingRect()矩形cv2.minEnclosingCircle()圆 |
| 轮廓面积比 | 轮廓面积与外接矩形比值 | 形状特征量化 | 面积比=轮廓面积/(w×h) 反映形状紧凑度 |
| 多轮廓处理 | 轮廓层级关系管理 | 复杂形状分析 | 通过索引访问不同轮廓 处理嵌套轮廓结构 |
| 参数化控制 | 近似阈值设置技巧 | 精度与效率平衡 | 推荐使用周长百分比 典型值0.01-0.1 |
| 可视化验证 | 轮廓绘制与标注 | 算法效果验证 | cv2.drawContours()绘制不同颜色区分原始/近似轮廓 |
| 课时18:模板匹配方法_笔记 |
模板匹配原理
读入图像
基本原理:模板在原图像上从原点开始滑动,计算模板与图像被覆盖区域的差别程度,每次计算结果存入矩阵。输出矩阵大小计算公式:若原图尺寸为A×B,模板尺寸为a×b,输出矩阵大小为(A-a+1)×(B-b+1)。匹配过程类似卷积操作,通过逐个像素点比较差异,可计算像素值平方差或相关系数。
OpenCV模板匹配方法

- TM_SQDIFF:计算平方不同,值越小越相关
- TM_CCORR:计算相关性,值越大越相关
- TM_CCOEFF:计算相关系数,值越大越相关
- TM_SQDIFF_NORMED:归一化平方不同,值越接近0越相关
- TM_CCORR_NORMED:归一化相关性,值越接近1越相关
- TM_CCOEFF_NORMED:归一化相关系数,值越接近1越相关
建议优先使用归一化方法(带_NORMED后缀),结果更可靠。
读入模板示例

示例图像lena.jpg(263×263灰度图)与模板face.jpg(110×85人脸区域),输出结果尺寸为154×179矩阵。
结果分析与可视化
结果矩阵每个位置存储对应窗口的匹配程度值,值含义因方法而异(最小值或最大值代表最佳匹配)。可通过热力图观察匹配程度分布。
关键函数与返回值
使用cv2.minMaxLoc(res)返回四个值:
min_val:最小值max_val:最大值min_loc:最小值坐标max_loc:最大值坐标
选择策略:- 平方差方法(SQDIFF)取最小值位置
- 相关方法(CCORR/CCOEFF)取最大值位置
模板匹配操作步骤
读入图像
读取原始图像和模板图像并转为灰度图,确保模板尺寸不大于原图。
模板匹配函数
调用cv2.matchTemplate(img, templ, method),参数说明:
img:待搜索图像(8位或32位浮点型)templ:搜索模板(同类型且不大于img)method:匹配方法枚举值
结果分析
不同方法的结果值范围差异较大,归一化方法结果在固定范围内(如0-1),便于比较。
定位最佳匹配
通过minMaxLoc函数获取最佳匹配点坐标(匹配区域左上角),根据模板宽高(w,h)绘制矩形框。
多方法对比
可循环测试不同方法的效果差异,观察匹配结果变化。
模板匹配技术要点
核心原理
模板匹配通过滑动窗口方式计算模板图像与目标图像局部区域的相似度,常用算法包括平方差匹配(TM_SQDIFF)、归一化平方差(TM_SQDIFF_NORMED)、相关性匹配(TM_CCORR)等。匹配结果矩阵尺寸遵循公式:
(W - w + 1) × (H - h + 1)
其中W/H为目标图像宽高,w/h为模板宽高。
实现流程
使用OpenCV的cv2.matchTemplate()函数时需注意:
- 输入图像和模板需统一为灰度图
- 匹配方法选择影响极值方向(TM_SQDIFF取最小值,TM_CCORR取最大值)
- 边界效应处理需预留边缘空间
关键代码示例
import cv2
img = cv2.imread('target.png', 0)
templ = cv2.imread('template.png', 0)
res = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc # 假设使用相关系数法
h, w = templ.shape
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img, top_left, bottom_right, 255, 2)
性能优化方案
- 图像金字塔:分层降采样减少计算量
- 并行计算:利用多线程处理不同区域
- 算法选择:TM_SQDIFF_NORMED对光照变化鲁棒性更强
典型问题处理
多目标匹配需设定阈值筛选结果:
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(img, pt, (pt[0]+w, pt[1]+h), (0,0,255), 2)
参数对照表
| 匹配方法 | 极值方向 | 适用场景 | 归一化需求 |
|---|---|---|---|
| TM_SQDIFF | 最小值 | 精确匹配 | 否 |
| TM_CCORR_NORMED | 最大值 | 亮度变化场景 | 是 |
| TM_CCOEFF | 最大值 | 纹理匹配 | 否 |
注意事项
- 模板尺寸过大时计算量呈指数增长
- 旋转或尺度变化需结合其他算法(如SIFT)
- 目标图像中存在多个相似区域时可能产生误匹配
课时19:匹配效果展示_笔记
模板匹配方法展示

方法参数
OpenCV的cv2.matchTemplate()函数需要传入图像、模板和匹配方法参数,方法参数可以是数值或OpenCV常量(如cv2.TM_SQDIFF),但不能是字符串形式。
使用cv2.minMaxLoc()获取匹配结果的最小/最大值及其位置,对于平方差匹配(TM_SQDIFF)和归一化平方差匹配(TM_SQDIFF_NORMED)应取最小值位置,其他方法取最大值位置。
通过模板宽度w和高度h,结合匹配位置的左上角坐标top_left,计算右下角坐标bottom_right = (top_left[0]+w, top_left[1]+h)。
匹配方法比较
TM_CCOEFF:计算相关系数。TM_CCOEFF_NORMED:计算归一化相关系数(值越接近1越相关)。TM_CCORR:计算互相关。TM_CCORR_NORMED:计算归一化互相关。TM_SQDIFF:计算平方差。TM_SQDIFF_NORMED:计算归一化平方差。
带归一化的方法(如TM_CCOEFF_NORMED、TM_CCORR_NORMED、TM_SQDIFF_NORMED)结果更稳定,建议优先使用。
结果可视化
使用Matplotlib显示匹配结果和标记矩形,左侧子图显示匹配结果矩阵(res),右侧子图显示在原图上绘制的匹配矩形。
通过plt.xticks([])和plt.yticks([])隐藏坐标轴。
在匹配结果图像中,最亮的位置表示与模板最匹配的区域。
多对象匹配问题
标准模板匹配只能找到单个最佳匹配位置,当图像中存在多个相似对象时需要特殊处理。
可以通过设置阈值并查找所有超过阈值的局部极值点来实现多对象检测。
匹配多个对象

实现步骤
读取原始图像和模板图像。
将原始图像转换为灰度图。
获取模板的高度和宽度。
使用cv2.matchTemplate()进行模板匹配。
设置匹配阈值(如0.8)。
使用np.where()找出所有匹配位置。
遍历匹配位置并绘制矩形框。
阈值选择
使用归一化相关系数法(TM_CCOEFF_NORMED)时,值越接近1表示匹配度越高。
示例中设置阈值为0.8,表示只保留匹配度大于80%的结果。
多对象处理
不同于单对象匹配只找最大/最小值。
通过阈值筛选所有符合条件的匹配位置。
对每个匹配位置单独绘制矩形框。
实际应用
示例中使用马里奥游戏中的金币作为模板,成功匹配并标记出场景中的所有金币。
演示了如何同时处理多个相似对象的识别。
核心参数
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8 # 可根据实际需求调整
loc = np.where(res >= threshold) # 获取所有匹配位置
注意事项
模板大小会影响匹配结果。
阈值设置过高可能导致漏检。
阈值设置过低可能导致误检。
对于旋转或缩放的目标需要额外处理。
工作原理
类似卷积操作,模板在图像上滑动计算模板与图像局部区域的相似度。
输出结果矩阵大小为(A-a+1)×(B-b+1),其中A×B是原图大小,a×b是模板大小。
匹配方法比较TM_SQDIFF:值越小越相关。TM_CCORR:值越大越相关。TM_CCOEFF:值越大越相关。TM_SQDIFF_NORMED:值越接近0越相关。TM_CCORR_NORMED:值越接近1越相关。TM_CCOEFF_NORMED:值越接近1越相关。
模板匹配方法
| 核心内容 | 关键操作/参数 | 注意事项 |
|---|---|---|
| CV2多种匹配算法对比 | method参数接受数值或CV2常量 |
禁止使用字符串传参 |
| 匹配结果处理 | 极值位置判定(min/max location) |
minVal/maxVal阈值判断需区分检测任务 |
| 多对象匹配 | 阈值筛选(如>0.8) |
需自定义阈值替代极值查找 |
| 归一化优势 | cv2.TM_CCOEFF_NORMED等归一化方法 |
非归一化方法效果较差 |
实际应用案例
| 场景 | 实现方法 | 优化要点 |
|---|---|---|
| 超级玛丽金币检测 | 多模板匹配实现批量定位 | 需调整阈值适应不同场景 |
算法原理
| 技术要点 | 数学/代码关联 | 扩展说明 |
|---|---|---|
| 滑动窗口卷积运算 | 六种差异度计算方法 | 与深度学习卷积操作原理相似 |
代码示例
import cv2
import numpy as np
# 模板匹配核心代码
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(result >= threshold)
公式说明
- 归一化相关系数公式:
[
R(x, y) = \frac{\sum_{x’,y’} (T’(x’,y’) \cdot I’(x+x’, y+y’))}{\sqrt{\sum_{x’,y’} T’(x’,y’)^2 \cdot \sum_{x’,y’} I’(x+x’, y+y’)^2}}
]
(其中 ( T’ ) 和 ( I’ ) 为均值归一化后的模板与图像区域)
课时20:直方图定义_笔记
直方图的构成

统计对象为图像中的像素点,将图像分解为单个像素点进行统计。
横坐标为像素值(0-255),纵坐标为对应像素值出现的次数。
统计原理是统计图像中每个灰度级(0-255)出现的次数,形成直方图。
例如,像素值109可能在图像中多个位置出现,直方图会统计所有109出现的总次数。
直方图的计算
直方图计算函数参数解释

函数原型为cv2.calcHist(images, channels, mask, histSize, ranges)。
参数详解如下:
images:输入图像,格式为uint8或float32,需用中括号[]括起来,如[img]。channels:统计的通道索引,灰度图为[0],彩色图可选[0][1][2]对应BGR通道。mask:掩模图像,None表示统计整图,可指定区域进行局部统计。histSize:BIN数目,需用中括号指定,如[256]表示分成256个区间。ranges:像素值范围,通常为[0,256](包含0不包含256)。
例题:计算直方图

注意事项:
- 所有参数必须用中括号
[]包裹。 - 返回值
shape为(256,1),表示256个灰度级及其出现次数。
可视化方法

关键点:
- 彩色图需分别计算BGR三个通道的直方图。
- 使用
enumerate遍历颜色通道,i对应通道索引(0:蓝,1:绿,2:红)。 matplotlib默认使用RGB顺序,而OpenCV使用BGR顺序,需注意。
结果分析
直方图可直观显示图像像素值分布情况。
非均匀分布说明图像可能存在对比度问题。
直方图知识小结
| 知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
|---|---|---|---|
| 直方图概念 | 统计图像中每个灰度级(0-255)的像素点出现频率,横坐标为灰度值,纵坐标为频数 | 直方图统计对象是像素点而非传统数值数据 | ⭐⭐ |
| OpenCV直方图计算 | cv2.calcHist()参数详解:- images:输入图像(通常为灰度图)- channels:指定统计通道(0/1/2对应BGR)- mask:掩码控制统计区域- bins:分组数量(默认256)- range:像素值范围(默认0-255)注:参数必须用中括号包裹 |
彩色图需分通道统计 | ⭐⭐⭐ |
| 直方图应用场景 | 分析图像灰度分布特征(如示例中150-200灰度级占比突出) | 直方图不均匀分布可触发图像增强操作 | ⭐⭐ |
| 掩码(Mask)技术 | 通过划定区域(红框/蓝框)实现局部统计,非必需参数 | 掩码矩阵需与原图同尺寸 | ⭐⭐⭐ |
| 可视化对比 | Matplotlib(RGB顺序)与OpenCV(BGR顺序)绘图差异 | 通道顺序转换是跨库操作关键 | ⭐⭐ |
关键说明
- 参数格式:调用
cv2.calcHist()时,输入参数需以列表形式传递,例如:hist = cv2.calcHist([image], [0], None, [256], [0, 256]) - 彩色图处理:统计多通道图像时需分通道计算或转换色彩空间。
- 掩码生成:掩码为二值图像,白色区域(255)表示统计范围,黑色区域(0)忽略。
更多推荐
所有评论(0)