OpenCV 阈值与模糊:全局/自适应阈值、Canny 边缘检测与三种模糊

OpenCV 阈值与模糊:全局/自适应阈值、Canny 边缘检测与三种模糊

OpenCV 图像处理课程 · 第 6 章「Threshold and Blurring」学习笔记

环境:Python 3.10 + opencv-python 4.5.5.64 + PyCharm(chapter6 目录)

包含 4 课:全局阈值 / 自适应阈值 / Canny 边缘检测 / 图像模糊


章节总览

课 主题 核心函数 文件
01 全局阈值 cv2.threshold() global_threshold.py
02 自适应阈值 cv2.adaptiveThreshold() adaptive_threshold.py
03 Canny 边缘检测 cv2.Canny() canny_image.py
04 图像模糊 cv2.blur() / GaussianBlur() / medianBlur() image_blur.py

本章说明 :阈值用于创建二值图像 (0~255 黑白);模糊(平滑)用于去噪。两者都是图像预处理的核心步骤。


第 1 课 · 全局阈值(cv2.threshold)

概念

  • 每个像素与一个固定阈值比较:小于阈值 → 0,大于 → 255
  • 用于把物体从背景中分离(前景/背景)
  • 必须在灰度图像上做(若为 BGR 要先转灰度)

函数签名

python 复制代码
cv2.threshold(src, thresh, maxval, type)
参数 含义
src 输入灰度图像
thresh 阈值(0~255)
maxval 像素大于阈值时设置的最大值(如 255)
type 阈值类型(cv2.THRESH_BINARY 等)

完整代码(global_threshold.py)

python 复制代码
import cv2

image_path = "../data/balloon.jpg"
image = cv2.imread(image_path)

image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)   # 转灰度

thresh, image_bin = cv2.threshold(image_gray, 127, 255,
                                  cv2.THRESH_BINARY)

cv2.imshow("image", image_gray)
cv2.imshow("image binary", image_bin)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.threshold 返回 两个值 :(阈值, 二值图像)。

常见阈值类型

类型 效果
THRESH_BINARY 像素>阈值设为 maxval,否则 0
THRESH_BINARY_INV 反相:像素>阈值设为 0,否则 maxval
THRESH_TRUNC 超过阈值截断为 maxval
THRESH_TOZERO 低于阈值置 0,否则不变

阈值曲线示意

#mermaid-svg-68nLfIRcuJUp2miG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-68nLfIRcuJUp2miG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-68nLfIRcuJUp2miG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-68nLfIRcuJUp2miG .error-icon{fill:#552222;}#mermaid-svg-68nLfIRcuJUp2miG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-68nLfIRcuJUp2miG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-68nLfIRcuJUp2miG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-68nLfIRcuJUp2miG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-68nLfIRcuJUp2miG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-68nLfIRcuJUp2miG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-68nLfIRcuJUp2miG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-68nLfIRcuJUp2miG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-68nLfIRcuJUp2miG .marker.cross{stroke:#333333;}#mermaid-svg-68nLfIRcuJUp2miG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-68nLfIRcuJUp2miG p{margin:0;}#mermaid-svg-68nLfIRcuJUp2miG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-68nLfIRcuJUp2miG .cluster-label text{fill:#333;}#mermaid-svg-68nLfIRcuJUp2miG .cluster-label span{color:#333;}#mermaid-svg-68nLfIRcuJUp2miG .cluster-label span p{background-color:transparent;}#mermaid-svg-68nLfIRcuJUp2miG .label text,#mermaid-svg-68nLfIRcuJUp2miG span{fill:#333;color:#333;}#mermaid-svg-68nLfIRcuJUp2miG .node rect,#mermaid-svg-68nLfIRcuJUp2miG .node circle,#mermaid-svg-68nLfIRcuJUp2miG .node ellipse,#mermaid-svg-68nLfIRcuJUp2miG .node polygon,#mermaid-svg-68nLfIRcuJUp2miG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-68nLfIRcuJUp2miG .rough-node .label text,#mermaid-svg-68nLfIRcuJUp2miG .node .label text,#mermaid-svg-68nLfIRcuJUp2miG .image-shape .label,#mermaid-svg-68nLfIRcuJUp2miG .icon-shape .label{text-anchor:middle;}#mermaid-svg-68nLfIRcuJUp2miG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-68nLfIRcuJUp2miG .rough-node .label,#mermaid-svg-68nLfIRcuJUp2miG .node .label,#mermaid-svg-68nLfIRcuJUp2miG .image-shape .label,#mermaid-svg-68nLfIRcuJUp2miG .icon-shape .label{text-align:center;}#mermaid-svg-68nLfIRcuJUp2miG .node.clickable{cursor:pointer;}#mermaid-svg-68nLfIRcuJUp2miG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-68nLfIRcuJUp2miG .arrowheadPath{fill:#333333;}#mermaid-svg-68nLfIRcuJUp2miG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-68nLfIRcuJUp2miG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-68nLfIRcuJUp2miG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-68nLfIRcuJUp2miG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-68nLfIRcuJUp2miG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-68nLfIRcuJUp2miG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-68nLfIRcuJUp2miG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-68nLfIRcuJUp2miG .cluster text{fill:#333;}#mermaid-svg-68nLfIRcuJUp2miG .cluster span{color:#333;}#mermaid-svg-68nLfIRcuJUp2miG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-68nLfIRcuJUp2miG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-68nLfIRcuJUp2miG rect.text{fill:none;stroke-width:0;}#mermaid-svg-68nLfIRcuJUp2miG .icon-shape,#mermaid-svg-68nLfIRcuJUp2miG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-68nLfIRcuJUp2miG .icon-shape p,#mermaid-svg-68nLfIRcuJUp2miG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-68nLfIRcuJUp2miG .icon-shape .label rect,#mermaid-svg-68nLfIRcuJUp2miG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-68nLfIRcuJUp2miG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-68nLfIRcuJUp2miG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-68nLfIRcuJUp2miG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 二值图像
cv2.threshold(thresh, maxval)
输入灰度图 (0~255)
pixel < thresh
pixel ≥ thresh
比较每个像素
置 0(黑)
置 maxval(白)

真实演示图:

灰度输入 二值输出(THRESH_BINARY) 反相(INV)

阈值 127:亮圆和渐变亮部变白,暗部变黑;反相则黑白互换。


第 2 课 · 自适应阈值(cv2.adaptiveThreshold)

概念

  • 全局阈值对有阴影/多物体的场景效果差(整个图像只有一个阈值)
  • 自适应阈值把图像分成小的邻域区域,每个区域单独计算阈值 → 更精准

函数签名

python 复制代码
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType,
                      blockSize, C)
参数 含义
src 输入灰度图像
maxValue 像素最大值(255)
adaptiveMethod cv2.ADAPTIVE_THRESH_MEAN_C(邻域均值)或 ADAPTIVE_THRESH_GAUSSIAN_C(加权和)
thresholdType THRESH_BINARY 或 THRESH_BINARY_INV
blockSize 邻域大小(必须是奇数,如 21)
C 从阈值减去的常数(微调)

完整代码(adaptive_threshold.py)

python 复制代码
import cv2

image_path = "../data/doc.png"
image = cv2.imread(image_path)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

thresh = cv2.adaptiveThreshold(image_gray, 255,
                               cv2.ADAPTIVE_THRESH_MEAN_C,
                               cv2.THRESH_BINARY, 21, 10)

cv2.imshow("image", image_gray)
cv2.imshow("adaptive threshold", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

自适应算法

#mermaid-svg-0YPHV2CNEokOtqnT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0YPHV2CNEokOtqnT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0YPHV2CNEokOtqnT .error-icon{fill:#552222;}#mermaid-svg-0YPHV2CNEokOtqnT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0YPHV2CNEokOtqnT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0YPHV2CNEokOtqnT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0YPHV2CNEokOtqnT .marker.cross{stroke:#333333;}#mermaid-svg-0YPHV2CNEokOtqnT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0YPHV2CNEokOtqnT p{margin:0;}#mermaid-svg-0YPHV2CNEokOtqnT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0YPHV2CNEokOtqnT .cluster-label text{fill:#333;}#mermaid-svg-0YPHV2CNEokOtqnT .cluster-label span{color:#333;}#mermaid-svg-0YPHV2CNEokOtqnT .cluster-label span p{background-color:transparent;}#mermaid-svg-0YPHV2CNEokOtqnT .label text,#mermaid-svg-0YPHV2CNEokOtqnT span{fill:#333;color:#333;}#mermaid-svg-0YPHV2CNEokOtqnT .node rect,#mermaid-svg-0YPHV2CNEokOtqnT .node circle,#mermaid-svg-0YPHV2CNEokOtqnT .node ellipse,#mermaid-svg-0YPHV2CNEokOtqnT .node polygon,#mermaid-svg-0YPHV2CNEokOtqnT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0YPHV2CNEokOtqnT .rough-node .label text,#mermaid-svg-0YPHV2CNEokOtqnT .node .label text,#mermaid-svg-0YPHV2CNEokOtqnT .image-shape .label,#mermaid-svg-0YPHV2CNEokOtqnT .icon-shape .label{text-anchor:middle;}#mermaid-svg-0YPHV2CNEokOtqnT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0YPHV2CNEokOtqnT .rough-node .label,#mermaid-svg-0YPHV2CNEokOtqnT .node .label,#mermaid-svg-0YPHV2CNEokOtqnT .image-shape .label,#mermaid-svg-0YPHV2CNEokOtqnT .icon-shape .label{text-align:center;}#mermaid-svg-0YPHV2CNEokOtqnT .node.clickable{cursor:pointer;}#mermaid-svg-0YPHV2CNEokOtqnT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0YPHV2CNEokOtqnT .arrowheadPath{fill:#333333;}#mermaid-svg-0YPHV2CNEokOtqnT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0YPHV2CNEokOtqnT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0YPHV2CNEokOtqnT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0YPHV2CNEokOtqnT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0YPHV2CNEokOtqnT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0YPHV2CNEokOtqnT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0YPHV2CNEokOtqnT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0YPHV2CNEokOtqnT .cluster text{fill:#333;}#mermaid-svg-0YPHV2CNEokOtqnT .cluster span{color:#333;}#mermaid-svg-0YPHV2CNEokOtqnT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0YPHV2CNEokOtqnT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0YPHV2CNEokOtqnT rect.text{fill:none;stroke-width:0;}#mermaid-svg-0YPHV2CNEokOtqnT .icon-shape,#mermaid-svg-0YPHV2CNEokOtqnT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0YPHV2CNEokOtqnT .icon-shape p,#mermaid-svg-0YPHV2CNEokOtqnT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0YPHV2CNEokOtqnT .icon-shape .label rect,#mermaid-svg-0YPHV2CNEokOtqnT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0YPHV2CNEokOtqnT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0YPHV2CNEokOtqnT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0YPHV2CNEokOtqnT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 每个区域各自二值化
adaptiveThreshold(blockSize, C)
输入灰度图(含阴影/多物体)
区域1
区域2
区域N
分块=按邻域算阈值

MEAN_C: 邻域均值

GAUSSIAN_C: 加权和
不同区域不同阈值

结果更精准

真实演示图(带噪声的渐变图,全局 vs 自适应):

带噪声灰度图 自适应二值化

自适应阈值能更好处理光照不均/阴影场景(比全局阈值更稳健)。


第 3 课 · Canny 边缘检测(cv2.Canny)

概念

Canny 算法包含四步 :降噪 → 计算图像梯度 → 非极大值抑制 → 滞后阈值(用上下两个阈值)。

判定 结果
梯度 > 上阈值 接受为边缘
梯度 < 下阈值 拒绝
处于两阈值之间 仅当连接到高于上阈值的像素时接受

函数签名

python 复制代码
cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
参数 含义
image 输入灰度图像
threshold1 下阈值
threshold2 上阈值
apertureSize Sobel 孔径(默认 3,范围 3~7,越大越细)
L2gradient bool;True 用 L2 梯度(更精细),False 用 L1

完整代码(canny_image.py)

python 复制代码
import cv2

image_path = "../data/balloon.jpg"
image = cv2.imread(image_path)

image_edges = cv2.Canny(image, 100, 200)   # 下100, 上200

cv2.imshow("image", image)
cv2.imshow("image edges", image_edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

边缘检测流程

#mermaid-svg-TxXF2uSLTtzz4Nq8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .error-icon{fill:#552222;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .marker.cross{stroke:#333333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 p{margin:0;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster-label text{fill:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster-label span{color:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster-label span p{background-color:transparent;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .label text,#mermaid-svg-TxXF2uSLTtzz4Nq8 span{fill:#333;color:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .node rect,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node circle,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node ellipse,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node polygon,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .rough-node .label text,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node .label text,#mermaid-svg-TxXF2uSLTtzz4Nq8 .image-shape .label,#mermaid-svg-TxXF2uSLTtzz4Nq8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .rough-node .label,#mermaid-svg-TxXF2uSLTtzz4Nq8 .node .label,#mermaid-svg-TxXF2uSLTtzz4Nq8 .image-shape .label,#mermaid-svg-TxXF2uSLTtzz4Nq8 .icon-shape .label{text-align:center;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .node.clickable{cursor:pointer;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .arrowheadPath{fill:#333333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TxXF2uSLTtzz4Nq8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TxXF2uSLTtzz4Nq8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster text{fill:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .cluster span{color:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TxXF2uSLTtzz4Nq8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .icon-shape,#mermaid-svg-TxXF2uSLTtzz4Nq8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .icon-shape p,#mermaid-svg-TxXF2uSLTtzz4Nq8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .icon-shape .label rect,#mermaid-svg-TxXF2uSLTtzz4Nq8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TxXF2uSLTtzz4Nq8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TxXF2uSLTtzz4Nq8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TxXF2uSLTtzz4Nq8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 边缘图像
Canny 四步
输入图像
灰度图

  1. 高斯降噪
  2. 计算梯度
  3. 非极大值抑制
  4. 滞后阈值

(下100/上200)
物体边界轮廓

真实演示图:

输入图像 Canny 边缘输出

Canny 清晰勾勒出亮圆的轮廓和暗矩形的边界线------这就是自动驾驶中检测车道标记的基础。


第 4 课 · 图像模糊(Image Blurring)

概念

  • 图像模糊也叫图像平滑 ,用低通滤波器处理图像
  • 目的:去除噪声(使像素亮度/发生变化的异常点)
  • 模糊通过降低像素差异减少清晰度,让图像更平滑

三种模糊函数

函数 原理 参数 示例
cv2.blur() 平均模糊:邻域像素平均值 (src, ksize) (img, (5,5))
cv2.GaussianBlur() 高斯模糊:加权(中心权重高) (src, ksize, sigmaX) (img, (7,7), 0)
cv2.medianBlur() 中值模糊:邻域像素中值 (src, ksize)(单数) (img, 5)

完整代码(image_blur.py)

python 复制代码
import cv2

image_path = "../data/balloon.jpg"
image = cv2.imread(image_path)

# 平均模糊
image_blur = cv2.blur(image, (5, 5))

# 高斯模糊(注释平均模糊后放开)
image_blur = cv2.GaussianBlur(image, (7, 7), 0)

# 中值模糊(注释后放开)
image_blur = cv2.medianBlur(image, 5)

cv2.imshow("image", image)
cv2.imshow("image blur", image_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

模糊原理示意

#mermaid-svg-m8XQPeCzn0eGTnkt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-m8XQPeCzn0eGTnkt .error-icon{fill:#552222;}#mermaid-svg-m8XQPeCzn0eGTnkt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-m8XQPeCzn0eGTnkt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-m8XQPeCzn0eGTnkt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-m8XQPeCzn0eGTnkt .marker.cross{stroke:#333333;}#mermaid-svg-m8XQPeCzn0eGTnkt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-m8XQPeCzn0eGTnkt p{margin:0;}#mermaid-svg-m8XQPeCzn0eGTnkt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster-label text{fill:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster-label span{color:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster-label span p{background-color:transparent;}#mermaid-svg-m8XQPeCzn0eGTnkt .label text,#mermaid-svg-m8XQPeCzn0eGTnkt span{fill:#333;color:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt .node rect,#mermaid-svg-m8XQPeCzn0eGTnkt .node circle,#mermaid-svg-m8XQPeCzn0eGTnkt .node ellipse,#mermaid-svg-m8XQPeCzn0eGTnkt .node polygon,#mermaid-svg-m8XQPeCzn0eGTnkt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-m8XQPeCzn0eGTnkt .rough-node .label text,#mermaid-svg-m8XQPeCzn0eGTnkt .node .label text,#mermaid-svg-m8XQPeCzn0eGTnkt .image-shape .label,#mermaid-svg-m8XQPeCzn0eGTnkt .icon-shape .label{text-anchor:middle;}#mermaid-svg-m8XQPeCzn0eGTnkt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-m8XQPeCzn0eGTnkt .rough-node .label,#mermaid-svg-m8XQPeCzn0eGTnkt .node .label,#mermaid-svg-m8XQPeCzn0eGTnkt .image-shape .label,#mermaid-svg-m8XQPeCzn0eGTnkt .icon-shape .label{text-align:center;}#mermaid-svg-m8XQPeCzn0eGTnkt .node.clickable{cursor:pointer;}#mermaid-svg-m8XQPeCzn0eGTnkt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-m8XQPeCzn0eGTnkt .arrowheadPath{fill:#333333;}#mermaid-svg-m8XQPeCzn0eGTnkt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-m8XQPeCzn0eGTnkt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-m8XQPeCzn0eGTnkt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8XQPeCzn0eGTnkt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-m8XQPeCzn0eGTnkt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8XQPeCzn0eGTnkt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster text{fill:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt .cluster span{color:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-m8XQPeCzn0eGTnkt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-m8XQPeCzn0eGTnkt rect.text{fill:none;stroke-width:0;}#mermaid-svg-m8XQPeCzn0eGTnkt .icon-shape,#mermaid-svg-m8XQPeCzn0eGTnkt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8XQPeCzn0eGTnkt .icon-shape p,#mermaid-svg-m8XQPeCzn0eGTnkt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-m8XQPeCzn0eGTnkt .icon-shape .label rect,#mermaid-svg-m8XQPeCzn0eGTnkt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8XQPeCzn0eGTnkt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-m8XQPeCzn0eGTnkt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-m8XQPeCzn0eGTnkt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 平滑图像
低通滤波
图像(含噪声)
噪点像素
blur: 邻域平均

Gaussian: 加权平均

median: 邻域中值
噪点被清除/中和

真实演示图(带噪声输入 vs 三种模糊):

带噪声原图 平均模糊 (5×5) 高斯模糊 (7×7) 中值模糊 (5)

三种模糊都能减小噪点、让图像更平滑;测试图中椒盐噪声被中和。


本章小结(速查表)

操作 函数 关键点
全局阈值 cv2.threshold(src, thresh, maxval, type) 固定阈值,需灰度图,返回(thresh, bin)
自适应阈值 cv2.adaptiveThreshold(src, maxval, method, type, block, C) blockSize 必须奇数
边缘检测 cv2.Canny(img, t1, t2, ksize, L2) 上下两阈值,滞后阈值
平均模糊 cv2.blur(img, ksize) 邻域均值
高斯模糊 cv2.GaussianBlur(img, ksize, sigmaX) 加权均值,中心权重大
中值模糊 cv2.medianBlur(img, ksize) 邻域中值,ksize 单数

核心易错点

  1. 阈值/边缘检测在灰度图上做 (BGR 先 cvtColor 转灰度)
  2. threshold 返回两个值 :(阈值, 二值图像)
  3. 自适应阈值的 blockSize 必须为奇数(如 21)
  4. Canny 上下阈值:高于上阈值是边缘,低于下阈值被拒,中间看连接
  5. 中值模糊的 ksize 也要单数
相关推荐
for_ever_love__2 小时前
函数——参数、lambda、*args与作用域
python·函数·大模型开发·编程基础
东莞市云毅网络有限公司2 小时前
企业资料时效性判定:Last-Modified、正文日期与版本字段三路交叉
python·sqlite·自动化运维·geo·数据监测
Query*2 小时前
深入浅出LangGraph【一】_基础篇
python·ai·langchain
能源革命2 小时前
Hermes Agent 常用命令速查表
人工智能
福兮说2 小时前
canvas 旋转图片的六个坑:四角被裁、Math.ceil 多出 1px 黑边、JPG 角发黑、翻转方向反了
前端·javascript·图像处理·canvas
XiaoMaqqqq2 小时前
市面上正规的IP驱动产业新场景新工具哪家强
运维·python·网络协议·tcp/ip
zhizhizhuzhuxia2 小时前
电视剧解说配音怎么选工具,从情绪表现到长文本稳定性的一次实测梳理
人工智能·语音识别
阿部多瑞 ABU2 小时前
复杂社会关系、三层结构与自反性
大数据·人工智能·ai写作
诺伦2 小时前
Manus 2.0 Cascade降本拆解:Token少用23.2%、成本降32%的工程手段,营销Agent编排能迁移什么 | RiseClaw玄策
人工智能·llm·ai agent·agent编排·增长运营
AI码农小姐姐3 小时前
一站式 AI 漫剧生产方案:知漫剧,降低多模态内容创作门槛
人工智能