Python数字图像处理之霍夫线变换实现详解


Posted in Python onJanuary 12, 2018

在图片处理中,霍夫变换主要是用来检测图片中的几何形状,包括直线、圆、椭圆等。

在skimage中,霍夫变换是放在tranform模块内,本篇主要讲解霍夫线变换。

对于平面中的一条直线,在笛卡尔坐标系中,可用y=mx+b来表示,其中m为斜率,b为截距。但是如果直线是一条垂直线,则m为无穷大,所有通常我们在另一坐标系中表示直线,即极坐标系下的r=xcos(theta)+ysin(theta)。即可用(r,theta)来表示一条直线。其中r为该直线到原点的距离,theta为该直线的垂线与x轴的夹角。如下图所示。

Python数字图像处理之霍夫线变换实现详解

对于一个给定的点(x0,y0), 我们在极坐标下绘出所有通过它的直线(r,theta),将得到一条正弦曲线。如果将图片中的所有非0点的正弦曲线都绘制出来,则会存在一些交点。所有经过这个交点的正弦曲线,说明都拥有同样的(r,theta), 意味着这些点在一条直线上。

Python数字图像处理之霍夫线变换实现详解

发上图所示,三个点(对应图中的三条正弦曲线)在一条直线上,因为这三个曲线交于一点,具有相同的(r, theta)。霍夫线变换就是利用这种方法来寻找图中的直线。

函数:skimage.transform.hough_line(img)

返回三个值:

h: 霍夫变换累积器

theta: 点与x轴的夹角集合,一般为0-179度

distance: 点到原点的距离,即上面的所说的r.

例:

import skimage.transform as st
import numpy as np
import matplotlib.pyplot as plt
 
# 构建测试图片
image = np.zeros((100, 100)) #背景图
idx = np.arange(25, 75)  #25-74序列
image[idx[::-1], idx] = 255 # 线条\
image[idx, idx] = 255    # 线条/
 
# hough线变换
h, theta, d = st.hough_line(image)
 
#生成一个一行两列的窗口(可显示两张图片).
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(8, 6))
plt.tight_layout()
 
#显示原始图片
ax0.imshow(image, plt.cm.gray)
ax0.set_title('Input image')
ax0.set_axis_off()
 
#显示hough变换所得数据
ax1.imshow(np.log(1 + h))
ax1.set_title('Hough transform')
ax1.set_xlabel('Angles (degrees)')
ax1.set_ylabel('Distance (pixels)')
ax1.axis('image')

Python数字图像处理之霍夫线变换实现详解

从右边那张图可以看出,有两个交点,说明原图像中有两条直线。

如果我们要把图中的两条直线绘制出来,则需要用到另外一个函数:

skimage.transform.hough_line_peaks(hspace, angles, dists)

用这个函数可以取出峰值点,即交点,也即原图中的直线。

返回的参数与输入的参数一样。我们修改一下上边的程序,在原图中将两直线绘制出来。

import skimage.transform as st
import numpy as np
import matplotlib.pyplot as plt
 
# 构建测试图片
image = np.zeros((100, 100)) #背景图
idx = np.arange(25, 75)  #25-74序列
image[idx[::-1], idx] = 255 # 线条\
image[idx, idx] = 255    # 线条/
 
# hough线变换
h, theta, d = st.hough_line(image)
 
#生成一个一行三列的窗口(可显示三张图片).
fig, (ax0, ax1,ax2) = plt.subplots(1, 3, figsize=(8, 6))
plt.tight_layout()
 
#显示原始图片
ax0.imshow(image, plt.cm.gray)
ax0.set_title('Input image')
ax0.set_axis_off()
 
#显示hough变换所得数据
ax1.imshow(np.log(1 + h))
ax1.set_title('Hough transform')
ax1.set_xlabel('Angles (degrees)')
ax1.set_ylabel('Distance (pixels)')
ax1.axis('image')
 
#显示检测出的线条
ax2.imshow(image, plt.cm.gray)
row1, col1 = image.shape
for _, angle, dist in zip(*st.hough_line_peaks(h, theta, d)):
  y0 = (dist - 0 * np.cos(angle)) / np.sin(angle)
  y1 = (dist - col1 * np.cos(angle)) / np.sin(angle)
  ax2.plot((0, col1), (y0, y1), '-r')
ax2.axis((0, col1, row1, 0))
ax2.set_title('Detected lines')
ax2.set_axis_off()

Python数字图像处理之霍夫线变换实现详解

注意,绘制线条的时候,要从极坐标转换为笛卡尔坐标,公式为:

Python数字图像处理之霍夫线变换实现详解

skimage还提供了另外一个检测直线的霍夫变换函数,概率霍夫线变换:

skimage.transform.probabilistic_hough_line(img, threshold=10, line_length=5,line_gap=3)

参数:

img: 待检测的图像。

threshold: 阈值,可先项,默认为10

line_length: 检测的最短线条长度,默认为50

line_gap: 线条间的最大间隙。增大这个值可以合并破碎的线条。默认为10

返回:

lines: 线条列表, 格式如((x0, y0), (x1, y0)),标明开始点和结束点。

下面,我们用canny算子提取边缘,然后检测哪些边缘是直线?

import skimage.transform as st
import matplotlib.pyplot as plt
from skimage import data,feature
 
#使用Probabilistic Hough Transform.
image = data.camera()
edges = feature.canny(image, sigma=2, low_threshold=1, high_threshold=25)
lines = st.probabilistic_hough_line(edges, threshold=10, line_length=5,line_gap=3)
 
# 创建显示窗口.
fig, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(16, 6))
plt.tight_layout()
 
#显示原图像
ax0.imshow(image, plt.cm.gray)
ax0.set_title('Input image')
ax0.set_axis_off()
 
#显示canny边缘
ax1.imshow(edges, plt.cm.gray)
ax1.set_title('Canny edges')
ax1.set_axis_off()
 
#用plot绘制出所有的直线
ax2.imshow(edges * 0)
for line in lines:
  p0, p1 = line
  ax2.plot((p0[0], p1[0]), (p0[1], p1[1]))
row2, col2 = image.shape
ax2.axis((0, col2, row2, 0))
ax2.set_title('Probabilistic Hough')
ax2.set_axis_off()
plt.show()

Python数字图像处理之霍夫线变换实现详解

总结

以上就是本文关于Python数字图像处理之霍夫线变换实现详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python多线程http下载实现示例
Dec 30 Python
介绍Python的@property装饰器的用法
Apr 28 Python
详解Python的Django框架中的模版相关知识
Jul 15 Python
Python面向对象程序设计之继承与多继承用法分析
Jul 13 Python
pygame实现雷电游戏雏形开发
Nov 20 Python
Django restframework 源码分析之认证详解
Feb 22 Python
Python之虚拟环境virtualenv,pipreqs生成项目依赖第三方包的方法
Jul 23 Python
TensorFlow实现checkpoint文件转换为pb文件
Feb 10 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
Jun 03 Python
celery在python爬虫中定时操作实例讲解
Nov 27 Python
关于多种方式完美解决Python pip命令下载第三方库的问题
Dec 21 Python
PyTorch中的torch.cat简单介绍
Mar 17 Python
Python实现霍夫圆和椭圆变换代码详解
Jan 12 #Python
微信跳一跳python自动代码解读1.0
Jan 12 #Python
Tornado 多进程实现分析详解
Jan 12 #Python
快速了解Python相对导入
Jan 12 #Python
Python实现翻转数组功能示例
Jan 12 #Python
Python实现求数列和的方法示例
Jan 12 #Python
python+matplotlib演示电偶极子实例代码
Jan 12 #Python
You might like
php你的验证码安全码?
2007/01/02 PHP
php 连接mssql数据库 初学php笔记
2010/03/01 PHP
PHP实现微信公众平台音乐点播
2014/03/20 PHP
php基于PDO连接MSSQL示例DEMO
2016/07/13 PHP
php实现的redis缓存类定义与使用方法示例
2017/08/09 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
dojo 之基础篇
2007/03/24 Javascript
formValidator3.3的ajaxValidator一些异常分析
2011/07/12 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
JS实现多物体缓冲运动实例代码
2013/11/29 Javascript
分享2个jQuery插件--jquery.fileupload与artdialog
2014/12/26 Javascript
整理AngularJS中的一些常用指令
2015/06/16 Javascript
JS验证邮件地址格式方法小结
2015/12/01 Javascript
利用D3.js实现最简单的柱状图示例代码
2016/12/09 Javascript
jQuery实现可编辑表格并生成json结果(实例代码)
2017/07/19 jQuery
微信小程序实现验证码获取倒计时效果
2018/02/08 Javascript
JS实现520 表白简单代码
2018/05/21 Javascript
一个简单的node.js界面实现方法
2018/06/01 Javascript
原生JS实现$.param() 函数的方法
2018/08/10 Javascript
JavaScript封装的常用工具类库bee.js用法详解【经典类库】
2018/09/03 Javascript
在Vue项目中用fullcalendar制作日程表的示例代码
2019/08/04 Javascript
JS实现提示框跟随鼠标移动
2019/08/27 Javascript
深入webpack打包原理及loader和plugin的实现
2020/05/06 Javascript
jQuery是用来干什么的 jquery其实就是一个js框架
2021/02/04 jQuery
Python机器学习之K-Means聚类实现详解
2018/02/22 Python
python基础梳理(一)(推荐)
2019/04/06 Python
pybind11在Windows下的使用教程
2019/07/04 Python
Python企业编码生成系统总体系统设计概述
2019/07/26 Python
python 用 xlwings 库 生成图表的操作方法
2019/12/22 Python
python实现同一局域网下传输图片
2020/03/20 Python
Python爬虫获取页面所有URL链接过程详解
2020/06/04 Python
函授本科自我鉴定
2013/11/03 职场文书
校园广播稿500字
2014/02/04 职场文书
你会写请假条吗?
2019/06/26 职场文书
MySQL系列之四 SQL语法
2021/07/02 MySQL
mysql数据库如何转移到oracle
2022/12/24 MySQL