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外星人入侵游戏编程完整版
Mar 30 Python
Ubuntu安装Jupyter Notebook教程
Oct 18 Python
基于numpy.random.randn()与rand()的区别详解
Apr 17 Python
Python中利用aiohttp制作异步爬虫及简单应用
Nov 29 Python
CentOS6.9 Python环境配置(python2.7、pip、virtualenv)
May 06 Python
python字典的setdefault的巧妙用法
Aug 07 Python
python 进程 进程池 进程间通信实现解析
Aug 23 Python
NumPy中的维度Axis详解
Nov 26 Python
Numpy与Pytorch 矩阵操作方式
Dec 27 Python
Python包和模块的分发详细介绍
Jun 19 Python
Pycharm 设置默认解释器路径和编码格式的操作
Feb 05 Python
Python3+Django get/post请求实现教程详解
Feb 16 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
水质对咖图啡风味的影响具体有哪些
2021/03/03 冲泡冲煮
php文件读取方法实例分析
2015/06/20 PHP
PHP实现对png图像进行缩放的方法(支持透明背景)
2015/07/15 PHP
理解 JavaScript 预解析
2009/10/25 Javascript
javascript开发技术大全 第4章 直接量与字符集
2011/07/03 Javascript
jQuery操作checkbox选择(list/table)
2013/04/07 Javascript
JS 去除Array中的null值示例代码
2013/11/20 Javascript
Jquery实现控件的隐藏和显示实例
2014/02/08 Javascript
如何让你的Lightbox支持滚轮缩放及Base64图片
2014/12/04 Javascript
Angularjs基础知识及示例汇总
2015/01/22 Javascript
Javascript中常用类型的格式化方法小结
2016/12/26 Javascript
vue2手机APP项目添加开屏广告或者闪屏广告
2017/11/28 Javascript
vue项目实战总结篇
2018/02/11 Javascript
vue2中使用sass并配置全局的sass样式变量的方法
2018/09/04 Javascript
VUE兄弟组件传值操作实例分析
2019/10/26 Javascript
基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能
2021/02/23 Vue.js
[52:57]2014 DOTA2国际邀请赛中国区预选赛 LGD-CDEC VS HGT
2014/05/21 DOTA
[00:31]DOTA2上海特级锦标赛 Fnatic战队宣传片
2016/03/04 DOTA
教你如何在Django 1.6中正确使用 Signal
2014/06/22 Python
Python判断操作系统类型代码分享
2014/11/22 Python
Python3实现从文件中读取指定行的方法
2015/05/22 Python
python语言使用技巧分享
2016/05/31 Python
Python判断文件或文件夹是否存在的三种方法
2017/07/27 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
python使用Plotly绘图工具绘制气泡图
2019/04/01 Python
wxPython实现绘图小例子
2019/11/19 Python
TensorFlow:将ckpt文件固化成pb文件教程
2020/02/11 Python
python实现文法左递归的消除方法
2020/05/22 Python
详解BeautifulSoup获取特定标签下内容的方法
2020/12/07 Python
缅甸网上购物:Shop.com.mm
2017/12/05 全球购物
Needle & Thread官网:英国仙女品牌
2018/01/13 全球购物
2014年母亲节寄语
2014/05/07 职场文书
禁止高声喧哗的标语
2014/06/11 职场文书
赡养老人协议书范本
2015/08/06 职场文书
科学家研发出新型速效酶,可在 24 小时内降解塑料制品
2022/04/29 数码科技
SQL Server中搜索特定的对象
2022/05/25 SQL Server