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命令行解析模块详解
Feb 01 Python
Python DataFrame设置/更改列表字段/元素类型的方法
Jun 09 Python
Django打印出在数据库中执行的语句问题
Jul 25 Python
Python中print函数简单使用总结
Aug 05 Python
python函数的作用域及关键字详解
Aug 20 Python
python 实现字符串下标的输出功能
Feb 13 Python
python如何判断IP地址合法性
Apr 05 Python
python matplotlib实现将图例放在图外
Apr 17 Python
关于tensorflow softmax函数用法解析
Jun 30 Python
Python hashlib模块的使用示例
Oct 09 Python
Python文件名匹配与文件复制的实现
Dec 11 Python
python 基于opencv操作摄像头
Dec 24 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 反射机制实现动态代理的代码
2008/10/22 PHP
解析php常用image图像函数集
2013/06/24 PHP
PHP生成指定长度随机数最简洁的方法
2014/07/14 PHP
PDO::beginTransaction讲解
2019/01/27 PHP
如何在Laravel5.8中正确地应用Repository设计模式
2019/11/26 PHP
类似CSDN图片切换效果脚本
2009/09/17 Javascript
各种页面定时跳转(倒计时跳转)代码总结
2013/10/24 Javascript
javascript利用apply和arguments复用方法
2013/11/25 Javascript
javascript 获取HTML DOM父、子、临近节点
2014/06/16 Javascript
JavaScript中提前声明变量或函数例子
2014/11/12 Javascript
jQuery实现自定义事件的方法
2015/04/17 Javascript
JavaScript生成带有缩进的表格代码
2016/06/15 Javascript
AngularJS ng-controller 指令简单实例
2016/08/01 Javascript
原生Javascript插件开发实践
2017/01/09 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
2018/11/27 jQuery
layui实现左侧菜单点击右侧内容区显示
2019/07/26 Javascript
详细分析React 表单与事件
2020/07/08 Javascript
在django中使用自定义标签实现分页功能
2017/07/04 Python
在python中使用正则表达式查找可嵌套字符串组
2017/10/24 Python
Python+request+unittest实现接口测试框架集成实例
2018/03/16 Python
Python使用re模块正则提取字符串中括号内的内容示例
2018/06/01 Python
使用Python实现微信提醒备忘录功能
2018/12/04 Python
详解Python with/as使用说明
2018/12/13 Python
对python读取CT医学图像的实例详解
2019/01/24 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
Python虚拟环境venv用法详解
2020/05/25 Python
python tqdm库的使用
2020/11/30 Python
localStorage 设置过期时间的方法实现
2018/12/21 HTML / CSS
日本最大美瞳直送网:Morecontact(中文)
2019/04/03 全球购物
大三自我鉴定范文
2013/10/05 职场文书
电子商务专业推荐信范文
2013/12/02 职场文书
办公室文员工作职责
2014/01/31 职场文书
抄作业检讨书
2014/02/17 职场文书
迎七一演讲稿
2014/09/12 职场文书
SpringBoot整合Mybatis Generator自动生成代码
2021/08/23 Java/Android
Python学习之迭代器详解
2022/04/01 Python