python+opencv实现霍夫变换检测直线

OpenCV 简介:

Python 处理图像有 OpenCV 库。OpenCV 可以运行在 Linux,windows,macOS 上,由 C 函数和 C++ 类构成,用于实现计算机图像、视频的编辑,应用于图像识别、运动跟踪、机器视觉等领域。

OpenCV 安装:

OpenCV 无法用 pip 或easy_install 安装,需要手动下载 .whl 文件安装。

实际应用中安装的OpenCV 库版本为 2.4.13。之所以用 2.4.13 版本的OpenCV,不采用 3.4 版本,是因为项目中用到的直线检测算法——霍夫变换,在OpenCV 3.4 中只能检测到一条结果,这条结果是所有线段中最长的一条。
从以下网址获取 OpenCV 的安装包(网页加载的速度比较慢,需要静候)
https://www.lfd.uci.edu/~gohlke/pythonlibs/
打开链接,待加载完毕后,搜索 OpenCV,可以找到如下页面
在这里插入图片描述
根据实际安装的 python 环境,下载对应的 OpenCV 安装包。

输入命令,完成 OpenCV 的安装。

pip install opencv_python‑2.4.13.5‑cp27‑cp27m‑win_amd64.whl

OpenCV 使用:

我对图像的处理是对灰度图像进行处理,不考虑 RGB 值,为了减轻实际的计算量。OpenCV 提供的 RGB 转灰度值的接口是

gray = cv2.cvtColor(cut_img, cv2.COLOR_BGR2GRAY)

在这里插入图片描述

要得到图片的线段,在灰度图上继续做后续操作。对图像线段进行检测的算法,是通过算子进行边缘检测,常用算子有Prewitt 算子、sobel 算子、Laplace 算子以及 Canny 算子。这里就不对这些算子的检测结果进行详述了,因为我也不是很明白几种算子实际效果的区别。本例中使用的是 canny 算子。
OpenCV 中调用 canny 算子的方式如下:

edge = cv2.Canny(image, threshold1,threshold2[, edges[, apertureSize[, L2gradient ]]])

必要参数:

第一个参数是需要处理的原图像,该图像必须为单通道的灰度图;

第二个参数是阈值1;

第三个参数是阈值2。

其中较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。

可选参数中apertureSize就是Sobel算子的大小。而L2gradient参数是一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),否则使用L1范数(直接将两个方向导数的绝对值相加)。

随后进行霍夫变换,得到线段的坐标。

霍夫变换是经典的检测直线的算法。其最初用来检测图像中的直线,同时也可以将其扩展,以用来检测图像中简单的结构。

cv2.HoughLines函数输出的是[float,float]形式的ndarray,其中每个值表示检测到的线(ρ , θ)中浮点点值的参数。在本例中,函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线。然而用这种方法检测出来的是贯穿整张图像的直线,需要检测线段时,则要采用概率霍夫变换。

lines = cv2.HoughLinesP(edges, 1,np.pi/180, 80, minLineLength, maxLineGap)
HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None) 
  • image: 必须是二值图像,推荐使用canny边缘检测的结果图像;
  • rho: 线段以像素为单位的距离精度,double类型的,推荐用1.0
  • theta: 线段以弧度为单位的角度精度,推荐用numpy.pi/180
  • threshod: 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试
  • lines:这个参数的意义未知,发现不同的lines对结果没影响,但是不要忽略了它的存在
  • minLineLength:线段以像素为单位的最小长度,根据应用场景设置
  • maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔(断裂),超过了设定值,则把两条线段当成一条线段,值越大,允许线段上的断裂越大,越有可能检出潜在的直线段

最后将找到的线段均显示在图片上,即完成直线检测。

由于图片画质因素,很多看似是直线的也未检测出是直线,还有许多散碎的直线并没有连接成长线。有待后续研究解决。
在这里插入图片描述

import cv2
import numpy as np
 
#img = cv2.imread("C:/AE_PUFF/python_vision/2018_04_27/kk-3.jpg")
img = cv2.imread("test.jpg")
cv2.imshow('origin_img', img)
height = img.shape[0]  # 高度
width  = img.shape[1]  # 宽度
cut_img = img
 
gray = cv2.cvtColor(cut_img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray_img', gray)
cv2.waitKey(0)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# lines = cv2.HoughLines(edges, 1, np.pi / 180, 110)
result = cut_img.copy()
# lines1 = lines[:, 0, :]  # 提取为为二维
# for rho, theta in lines1[:]:
#     a = np.cos(theta)
#     b = np.sin(theta)
#     x0 = a * rho
#     y0 = b * rho
#     x1 = int(x0 + 1000 * (-b))
#     y1 = int(y0 + 1000 * a)
#     x2 = int(x0 - 1000 * (-b))
#     y2 = int(y0 - 1000 * a)
#     cv2.line(result, (x1, y1), (x2, y2), (255, 0, 0), 1)

minLineLength = 70  # height/32
maxLineGap = 2  # height/40
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 50, minLineLength=minLineLength, maxLineGap=maxLineGap)

for x1, y1, x2, y2 in lines[0]:
    cv2.line(result, (x1, y1), (x2, y2), (0, 255, 0), 2)

cv2.imshow('result', result)
cv2.waitKey(0)

在这里插入图片描述

import cv2
import numpy as np
img = cv2.imread("origin.jpg")
# cv2.imshow('origin_img', img)
height = img.shape[0]  # 高度
width = img.shape[1]  # 宽度
cut_img = img

gray = cv2.cvtColor(cut_img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray_img', gray)
# cv2.waitKey(0)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# lines = cv2.HoughLines(edges, 1, np.pi / 180, 110)
result = cut_img.copy()
# lines1 = lines[:, 0, :]  # 提取为为二维
# for rho, theta in lines1[:]:
#     a = np.cos(theta)
#     b = np.sin(theta)
#     x0 = a * rho
#     y0 = b * rho
#     x1 = int(x0 + 1000 * (-b))
#     y1 = int(y0 + 1000 * a)
#     x2 = int(x0 - 1000 * (-b))
#     y2 = int(y0 - 1000 * a)
#     cv2.line(result, (x1, y1), (x2, y2), (255, 0, 0), 1)

minLineLength = 5  # height/32
maxLineGap = 0  # height/40
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 80, minLineLength=minLineLength, maxLineGap=maxLineGap)
line1 = lines[:, 0, :]  # 提取为二维

for x1, y1, x2, y2 in line1[:]:
    cv2.line(result, (x1, y1), (x2, y2), (0, 255, 0), 1)

cv2.imshow('result', result)
cv2.waitKey(0)

区别是
line1 = lines[:, 0, :] # 提取为二维

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用OpenCV Python实现霍夫变换检测直线段并在图像中显示,请按照以下步骤进行: 1. 导入必要的库 ```python import cv2 import numpy as np ``` 2. 读取图像并将其转换为灰度图像 ```python img = cv2.imread('image.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ``` 3. 对图像进行边缘检测 ```python edges = cv2.Canny(gray,50,150,apertureSize = 3) ``` 4. 进行霍夫变换 ```python lines = cv2.HoughLines(edges,1,np.pi/180,200) ``` 其中,`1` 和 `np.pi/180` 分别表示距离和角度的精度,`200` 表示阈值,即认为是一条直线的最小投票数。 5. 在图像中绘制直线 ```python for line in lines: rho,theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a*rho y0 = b*rho x1 = int(x0 + 1000*(-b)) y1 = int(y0 + 1000*(a)) x2 = int(x0 - 1000*(-b)) y2 = int(y0 - 1000*(a)) cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2) ``` 6. 显示图像 ```python cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 完整代码如下: ```python import cv2 import numpy as np img = cv2.imread('image.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray,50,150,apertureSize = 3) lines = cv2.HoughLines(edges,1,np.pi/180,200) for line in lines: rho,theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a*rho y0 = b*rho x1 = int(x0 + 1000*(-b)) y1 = int(y0 + 1000*(a)) x2 = int(x0 - 1000*(-b)) y2 = int(y0 - 1000*(a)) cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 注意:在实际使用中,可能需要调整Canny边缘检测霍夫变换的参数以获得更好的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值