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之hello world
May 21 Python
Python模块搜索路径代码详解
Jan 29 Python
python监控键盘输入实例代码
Feb 09 Python
用Eclipse写python程序
Feb 10 Python
python语言中with as的用法使用详解
Feb 23 Python
解决pandas中读取中文名称的csv文件报错的问题
Jul 04 Python
flask框架实现连接sqlite3数据库的方法分析
Jul 16 Python
python使用Matplotlib绘制分段函数
Sep 25 Python
python如何读取bin文件并下发串口
Jul 05 Python
Django模板语言 Tags使用详解
Sep 09 Python
tensorflow图像裁剪进行数据增强操作
Jun 30 Python
pytorch 移动端部署之helloworld的使用
Oct 30 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表单提交问题的解决方法
2011/04/12 PHP
深入分析使用mysql_fetch_object()以对象的形式返回查询结果
2013/06/05 PHP
php下载文件源代码(强制任意文件格式下载)
2014/05/09 PHP
跟我学Laravel之视图 & Response
2014/10/15 PHP
php中FTP函数ftp_connect、ftp_login与ftp_chmod用法
2014/11/18 PHP
Laravel 5框架学习之模型、控制器、视图基础流程
2015/04/08 PHP
PHP实现一个简单url路由功能实例
2016/11/05 PHP
js 获取计算后的样式写法及注意事项
2013/02/25 Javascript
jqGrid增加时--判断开始日期与结束日期(实例解析)
2013/11/08 Javascript
详解JavaScript基于面向对象之创建对象(1)
2015/12/10 Javascript
jQuery弹层插件jquery.fancybox.js用法实例
2016/01/22 Javascript
JavaScript中匿名函数的递归调用
2017/01/22 Javascript
Angular父组件调用子组件的方法
2018/04/02 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
Vue如何基于es6导入外部js文件
2020/05/15 Javascript
vue 出现data-v-xxx的原因及解决
2020/08/04 Javascript
Python中Django 后台自定义表单控件
2017/03/28 Python
基于Python3 逗号代码 和 字符图网格(详谈)
2017/06/22 Python
python实现按长宽比缩放图片
2018/06/07 Python
python logging重复记录日志问题的解决方法
2018/07/12 Python
深入理解Django自定义信号(signals)
2018/10/15 Python
python+opencv实现霍夫变换检测直线
2020/10/23 Python
Python 实现域名解析为ip的方法
2019/02/14 Python
Python3实现二叉树的最大深度
2019/09/30 Python
使用Bazel编译TensorBoard教程
2020/02/15 Python
keras的ImageDataGenerator和flow()的用法说明
2020/07/03 Python
Matplotlib 折线图plot()所有用法详解
2020/07/28 Python
浅谈html5 响应式布局
2014/12/24 HTML / CSS
利用 Canvas实现绘画一个未闭合的带进度条的圆环
2019/07/26 HTML / CSS
技术总监岗位职责
2013/12/05 职场文书
上课说话检讨书大全
2014/01/22 职场文书
喷漆工的岗位职责
2014/03/17 职场文书
2014年有孩子的离婚协议书范本
2014/10/08 职场文书
优秀新员工事迹材料
2019/05/13 职场文书
能让Python提速超40倍的神器Cython详解
2021/06/24 Python
 Python 中 logging 模块使用详情
2022/03/03 Python