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字符串和字典
Jul 07 Python
python executemany的使用及注意事项
Mar 13 Python
python pycurl验证basic和digest认证的方法
May 02 Python
Python 找到列表中满足某些条件的元素方法
Jun 26 Python
win8下python3.4安装和环境配置图文教程
Jul 31 Python
使用Python开发SQLite代理服务器的方法
Dec 07 Python
Django中的静态文件管理过程解析
Aug 01 Python
django 快速启动数据库客户端程序的方法示例
Aug 16 Python
Python代码中如何读取键盘录入的值
May 27 Python
如何在mac版pycharm选择python版本
Jul 21 Python
django表单中的按钮获取数据的实例分析
Jul 31 Python
Python内置类型集合set和frozenset的使用详解
Apr 26 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中使用memcache存储session的三种配置方法
2014/04/05 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
Ecshop 后台添加新功能栏目及管理权限设置教程
2017/11/21 PHP
js实现页面打印功能实例代码(附去页眉页脚功能代码)
2009/12/15 Javascript
jquery UI 1.72 之datepicker
2009/12/29 Javascript
utf-8编码引起js输出中文乱码的解决办法
2010/06/23 Javascript
非常强大的 jQuery.AsyncBox 弹出对话框插件
2011/08/29 Javascript
jQuery Jcrop插件实现图片选取功能
2011/11/23 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
使用JavaScript实现点击循环切换图片效果
2017/09/03 Javascript
vue 组件使用中的一些细节点
2018/04/25 Javascript
node.js +mongdb实现登录功能
2020/06/18 Javascript
解决echarts echarts数据动态更新和dataZoom被重置问题
2020/07/20 Javascript
详解vue中v-model和v-bind绑定数据的异同
2020/08/10 Javascript
微信小程序淘宝首页双排图片布局排版代码(推荐)
2020/10/29 Javascript
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python中异常重试的解决方案详解
2017/05/05 Python
python代码实现ID3决策树算法
2017/12/20 Python
Python即时网络爬虫项目启动说明详解
2018/02/23 Python
Django基于客户端下载文件实现方法
2020/04/21 Python
tensorflow使用L2 regularization正则化修正overfitting过拟合方式
2020/05/22 Python
Python如何实现的二分查找算法
2020/05/27 Python
Python尾递归优化实现代码及原理详解
2020/10/09 Python
Pytorch自定义Dataset和DataLoader去除不存在和空数据的操作
2021/03/03 Python
澳大利亚家用电器在线商店:Billy Guyatts
2020/05/05 全球购物
介绍下Java的输入输出流
2014/01/22 面试题
一份Java笔试题
2012/02/21 面试题
怎样声明一个匿名的内部类
2016/06/01 面试题
模具设计与制造专业自荐书
2014/07/01 职场文书
巾帼文明岗事迹材料
2014/12/24 职场文书
煤矿百日安全活动总结
2015/05/07 职场文书
学雷锋活动简报
2015/07/20 职场文书
校长新学期致辞
2015/07/30 职场文书
解决pytorch读取自制数据集出现过的问题
2021/05/31 Python
Vue3.0 手写放大镜效果
2021/07/25 Vue.js
详解Python如何批量采集京东商品数据流程
2022/01/22 Python