【opencv学习】【Hough直线检测】

请添加图片描述
请添加图片描述

import cv2
import numpy as np


# 展示图像,封装成函数
def cv_show_image(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)  # 等待时间,单位是毫秒,0代表任意键终止
    cv2.destroyAllWindows()


# 总流程
# 1.获取灰度图像,转成二值图像
# 2.canny边缘检测,获取图像边缘信息。减少计算量
# 3.获取霍夫直线信息,可以使用HoughLines 或者 HoughLinesP函数
# 4.算出直线位置,根据不同的使用函数,获取相应的值,画出每条直线

# 第一步:读取图像
img = cv2.imread("images/build.jpeg")
height = img.shape[0]  # 高度
width = img.shape[1]  # 宽度

# 第二步:转成灰度图和二值图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, gray = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show_image('gray_img', gray)

# 第三步:使用canny边缘检测,检测出所有的边缘信息
edges = cv2.Canny(gray, threshold1=20, threshold2=100, apertureSize=3)  # apertureSize 是sobel算子的大小
cv_show_image('canny_img', edges)

# 第四步:使用直线检测,并画出直线。
# 第四步第一种方法:使用HoughLines
# dst:    输出图像. 它应该是个灰度图 (但事实上是个二值化图)
# lines:  返回值:储存着检测到的直线的参数对 (x_{start}, y_{start}, x_{end}, y_{end}) 的容器,结构如[[[x1,y1,x2,y2]],[[...]]]
# rho :   参数极半径 r 以像素值为单位的分辨率. 我们使用 1 像素为步长.
# theta:  参数极角 theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)为步长.
# threshold:  控制检测出线段的条件。设置阈值: 一条直线所需最少的的曲线在一点相交,超过设定阈值才被检测出线段,值越大,
#           基本上意味着检出的线段越长,检出的线段个数越少。因为阈值越大,超过阈值的点越少,即xy平面的直线越少,但是因为阈值越大,说明检测出在同一条直线上的点越多,即直线越长。这个参数是针对参数空间而言的,在参数空间中一条曲线就代表在xy平面上的一个点
# minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃,其实这个参数的意义跟上一个很类似,只是这个参数是针对xy平面而言的,即当组成直线的点达到一点数量的时候才被检测出为线段,否则过滤掉
# maxLineGap:   控制检测出直线长短,在同一条直线上的点,能够被连接的最大距离,越大得到的线越长,如下图,点在直线上,若此时距离maxlineGap小于设定的值,则连接,否则就不连接
lines = cv2.HoughLines(image=edges, rho=1, theta=np.pi / 180, threshold=100)  # #函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
print(lines.shape)

result = img.copy()
for line in lines:
    # print(type(line))   #多维数组
    rho, theta = line[0]  # 获取极值ρ长度和θ角度
    a = np.cos(theta)  # 获取角度cos值
    b = np.sin(theta)  # 获取角度sin值
    x0 = a * rho  # 获取x轴值
    y0 = b * rho  # 获取y轴值  x0和y0是直线的中点
    x1 = int(x0 + 1000 * (-b))  # 获取这条直线最大值点x1
    y1 = int(y0 + 1000 * (a))  # 获取这条直线最大值点y1
    x2 = int(x0 - 1000 * (-b))  # 获取这条直线最小值点x2  
    y2 = int(y0 - 1000 * (a))  # 获取这条直线最小值点y2  其中*1000是内部规则
    cv2.line(result, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 开始划线
cv_show_image('HoughLines_result_img', result)

# 第四步方法二:使用HoughLinesP
# HoughLinesP概率霍夫变换(是加强版)使用简单,效果更好,检测图像中分段的直线(而不是贯穿整个图像的直线)
minLineLength = 30  # height/32
maxLineGap = 10  # height/40
lines = cv2.HoughLinesP(image=edges, rho=1, theta=np.pi / 180, threshold=80,
                        minLineLength=minLineLength, maxLineGap=maxLineGap)
print(lines.shape)

result = img.copy()
for line in lines:
    # print(type(line))  # 多维数组
    x1,y1,x2,y2 = line[0]
    cv2.line(result, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 开始划线
cv_show_image('HoughLinesP_result_img', result)

效果展示
二值图像:
请添加图片描述
canny边缘检测
请添加图片描述
使用 HoughLines 函数得到的结果,发现这个直线会穿过整个图像
请添加图片描述
使用 HoughLinesP 函数得到的结果,发现这个直线就是图像中的直线长度
请添加图片描述
最后是参考的资料地址
参考:
霍夫(Hough)变换之直线检测

OpenCV—直线检测

霍夫线变换

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值