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实现数通设备端口监控示例
Apr 02 Python
在Python中测试访问同一数据的竞争条件的方法
Apr 23 Python
Python实现的排列组合计算操作示例
Oct 13 Python
快速了解Python中的装饰器
Jan 11 Python
深入浅析Python中的yield关键字
Jan 24 Python
python中for用来遍历range函数的方法
Jun 08 Python
python爬虫之urllib库常用方法用法总结大全
Nov 14 Python
python读取txt文件,去掉空格计算每行长度的方法
Dec 20 Python
解决Pytorch 加载训练好的模型 遇到的error问题
Jan 10 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
Sep 21 Python
如何在scrapy中捕获并处理各种异常
Sep 28 Python
浅谈Python响应式类库RxPy
Jun 14 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调用数据库的存贮过程!
2006/10/09 PHP
PHP反转字符串函数strrev()函数的用法
2012/02/04 PHP
php实现的双向队列类实例
2014/09/24 PHP
PHP+MYSQL实现用户的增删改查
2015/03/24 PHP
PHP7.0安装笔记整理
2015/08/28 PHP
阿里云PHP SMS短信服务验证码发送方法
2017/07/11 PHP
PHP多进程编程之僵尸进程问题的理解
2017/10/15 PHP
Laravel 队列使用的实现
2019/01/08 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
2020/02/22 PHP
用jscript实现新建word文档
2007/06/15 Javascript
不要在cookie中使用特殊字符的原因分析
2010/07/13 Javascript
Jquery ThickBox插件使用心得(不建议使用)
2010/09/08 Javascript
javascript中删除指定数组中指定的元素的代码
2011/02/12 Javascript
js实现仿Windows风格选项卡和按钮效果实例
2015/05/13 Javascript
JS实现IE状态栏文字缩放效果代码
2015/10/24 Javascript
Javascrip实现文字跳动特效
2016/11/27 Javascript
jQuery模拟窗口抖动效果
2017/03/15 Javascript
Vue.js 插件开发详解
2017/03/29 Javascript
Vue之Watcher源码解析(1)
2017/07/19 Javascript
vue+elementui实现点击table中的单元格触发事件--弹框
2020/07/18 Javascript
记录Django开发心得
2014/07/16 Python
浅析python中SQLAlchemy排序的一个坑
2017/02/24 Python
在IPython中进行Python程序执行时间的测量方法
2018/11/01 Python
详解python中init方法和随机数方法
2019/03/13 Python
详解Python中pandas的安装操作说明(傻瓜版)
2019/04/08 Python
Python实现滑动平均(Moving Average)的例子
2019/08/24 Python
Python + selenium + crontab实现每日定时自动打卡功能
2020/03/31 Python
python3跳出一个循环的实例操作
2020/08/18 Python
python+appium+yaml移动端自动化测试框架实现详解
2020/11/24 Python
使用html5新特性轻松监听任何App自带返回键的示例
2018/03/13 HTML / CSS
如何在存储过程中使用Loop
2016/01/05 面试题
公司授权委托书范文
2014/08/02 职场文书
暂停营业通知
2015/04/25 职场文书
2016父亲节感恩话语
2015/12/09 职场文书
Spring boot应用启动后首次访问很慢的解决方案
2021/06/23 Java/Android
MySQL创建管理子分区
2022/04/13 MySQL