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 3.6.5 安装配置方法图文教程
Sep 18 Python
Python对象与引用的介绍
Jan 24 Python
Python3.5模块的定义、导入、优化操作图文详解
Apr 27 Python
pyqt5使用按钮进行界面的跳转方法
Jun 19 Python
Python中的self用法详解
Aug 06 Python
python openCV获取人脸部分并存储功能
Aug 28 Python
python socket通信编程实现文件上传代码实例
Dec 14 Python
手动安装python3.6的操作过程详解
Jan 13 Python
Matplotlib使用字符串代替变量绘制散点图的方法
Feb 17 Python
PythonPC客户端自动化实现原理(pywinauto)
May 28 Python
使用python实现下载我们想听的歌曲,速度超快
Jul 09 Python
Python如何读取、写入CSV数据
Jul 28 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 网页游戏开发入门教程一(webgame+design)
2009/10/26 PHP
PHP中include与require使用方法区别详解
2013/10/19 PHP
php+ajax无刷新上传图片实例代码
2015/11/17 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
PHP7创建销毁session的实例方法
2020/02/03 PHP
简单的JS多重继承示例
2008/03/13 Javascript
javascript字符串函数汇总
2015/12/06 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
用Nodejs搭建服务器访问html、css、JS等静态资源文件
2017/04/28 NodeJs
Angular4学习笔记之准备和环境搭建项目
2017/08/01 Javascript
JS手机端touch事件计算滑动距离的方法示例
2017/10/26 Javascript
vue组件中使用iframe元素的示例代码
2017/12/13 Javascript
Vue单页及多页应用全局配置404页面实践记录
2018/05/22 Javascript
jQuery实现基本隐藏与显示效果的方法详解
2018/09/05 jQuery
vuejs点击class变化的实例
2018/09/05 Javascript
python连接字符串的方法小结
2015/07/13 Python
python使用turtle绘制国际象棋棋盘
2019/05/23 Python
Python函数参数匹配模型通用规则keyword-only参数详解
2019/06/10 Python
详解使用python绘制混淆矩阵(confusion_matrix)
2019/07/14 Python
Python编程学习之如何判断3个数的大小
2019/08/07 Python
Python随机函数库random的使用方法详解
2019/08/21 Python
python numpy之np.random的随机数函数使用介绍
2019/10/06 Python
Python3 把一个列表按指定数目分成多个列表的方式
2019/12/25 Python
pytorch使用tensorboardX进行loss可视化实例
2020/02/24 Python
Django实现任意文件上传(最简单的方法)
2020/06/03 Python
Keras官方中文文档:性能评估Metrices详解
2020/06/15 Python
安装pyinstaller遇到的各种问题(小结)
2020/11/20 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
Python字节单位转换(将字节转换为K M G T)
2021/03/02 Python
用CSS3写的模仿iPhone中的返回按钮
2015/04/04 HTML / CSS
元旦联欢会主持词
2014/03/26 职场文书
村抢险救灾方案
2014/05/09 职场文书
任命书怎么写
2014/06/04 职场文书
文明礼貌主题班会
2015/08/14 职场文书
《分数乘法》教学反思
2016/02/24 职场文书
element tree树形组件回显数据问题解决
2022/08/14 Javascript