Opencv 学习笔记:边缘检测 + 霍夫变换精准查找直线

在工业检测、文档分析等场景中,从图像中提取边缘并精准查找直线是核心需求。本文通过 "Canny 边缘检测 + 形态学闭运算 + 霍夫变换" 的组合流程,演示直线提取的完整实现,新手可直接复用。

核心代码实现

python 复制代码
import cv2 as cv
import numpy as np

# 1. 读取图像并转灰度
src = cv.imread('.\image\11.bmp')
if src is None:
    print('could not load image')
    exit()
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. Canny边缘检测(双阈值:100/200)
threshold1 = 100
edges = cv.Canny(gray, threshold1, threshold1*2, apertureSize=3)

# 3. 闭运算优化边缘:填补边缘断裂,强化直线特征
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 3))
closed1 = cv.morphologyEx(edges, cv.MORPH_CLOSE, kernel)

# 4. 概率霍夫变换查找直线
lines = cv.HoughLinesP(closed1, 1, np.pi/180, 10, minLineLength=200, maxLineGap=100)

# 5. 创建纯白画布绘制检测到的直线
outimage = np.zeros((src.shape[0], src.shape[1]), np.uint8)
outimage.fill(255)

# 6. 绘制直线并显示
cv.imshow('edges', closed1)
print(f"检测到的直线数量:{len(lines)}")  # 打印直线数量便于调试

if lines is not None:
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv.line(outimage, (x1, y1), (x2, y2), (0, 0, 0), 2)  # 黑色直线更清晰

# 自适应窗口显示(匹配原图尺寸)
cv.namedWindow('outimage', cv.WINDOW_NORMAL)
cv.resizeWindow('outimage', src.shape[1], src.shape[0])
cv.imshow('outimage', outimage)

cv.waitKeyEx(0)
cv.destroyAllWindows()

关键知识点解析

1. 核心流程拆解

步骤 核心 API 作用说明
边缘检测 cv.Canny() 提取图像边缘,双阈值(1:2)是经验值,apertureSize=3 为默认卷积核
边缘优化 cv.morphologyEx(..., MORPH_CLOSE) 闭运算填补边缘断裂,让直线特征更连续
直线查找 cv.HoughLinesP() 概率霍夫变换,高效查找直线,避免传统霍夫变换计算量大的问题
直线绘制 cv.line() 在纯白画布上绘制检测到的直线,直观展示结果

2. 霍夫变换关键参数

  • rho=1:距离分辨率(像素);
  • theta=np.pi/180:角度分辨率(弧度);
  • threshold=10:检测阈值(投票数≥此值才判定为直线);
  • minLineLength=200:最小直线长度(过滤短杂线);
  • maxLineGap=100:直线段最大间隙(间隙内的线段视为同一直线)。

3. 优化与避坑点

  • Canny 阈值调整:若边缘漏检,降低 threshold1;若噪点多,提高 threshold1;
  • 闭运算核尺寸:核越大,边缘填补效果越强,需根据直线粗细调整;
  • 空值判断 :新增if lines is not None,避免无直线时索引报错;
  • 颜色适配 :灰度画布用(0,0,0)(黑色)绘制直线,比绿色更清晰。

总结

  1. 直线提取核心流程:Canny 边缘检测→闭运算优化→霍夫变换查找;
  2. 霍夫变换的minLineLengthmaxLineGap是过滤杂线、合并线段的关键;
  3. 闭运算可有效填补边缘断裂,大幅提升直线检测准确率。
相关推荐
AOwhisky22 分钟前
Python 学习笔记(第十三期)——运维自动化(下·前篇):远程命令执行——paramiko基础篇
运维·python·学习·云原生·自动化·运维开发·paramiko
前端世界32 分钟前
MySQL 基础入门(学习第4天)——约束与 DML 操作详解
数据库·学习·mysql
dear_bi_MyOnly36 分钟前
【SpringBoot配置文件】
java·spring boot·后端·学习·spring·java-ee·学习方法
AOwhisky1 小时前
Python 学习笔记(第十四期)——运维自动化(下·中篇):远程文件传输——paramiko进阶篇
运维·python·学习·云原生·自动化·文件传输·paramiko
math_hongfan1 小时前
鸿蒙Flutter setState机制深入理解
学习·flutter·华为·harmonyos·鸿蒙
其实防守也摸鱼1 小时前
补天SRC新手入门指南:从0到1的漏洞挖掘之路
网络·python·学习·安全·web安全·数据挖掘·挖洞
星恒随风2 小时前
C++ STL 栈详解:stack 的使用、经典题目与简单模拟实现
开发语言·数据结构·c++·笔记·学习
玖玥拾4 小时前
Unity 3D 笔记(十一)UI 框架进阶:栈弹窗交互、BasePanel 基类虚方法、DoTween 界面动画
笔记·3d·unity
FellAveal4 小时前
【Go语言入门学习笔记】Part13.结构体与接口
笔记·学习·golang
学计算机的计算基4 小时前
回溯算法下篇:四道经典题讲透约束剪枝、原地标记、预计算与状态压缩
java·笔记·算法