Python实现霍夫圆和椭圆变换代码详解


Posted in Python onJanuary 12, 2018

在极坐标中,圆的表示方式为:

x=x0+rcosθ

y=y0+rsinθ

圆心为(x0,y0),r为半径,θ为旋转度数,值范围为0-359

如果给定圆心点和半径,则其它点是否在圆上,我们就能检测出来了。在图像中,我们将每个非0像素点作为圆心点,以一定的半径进行检测,如果有一个点在圆上,我们就对这个圆心累加一次。如果检测到一个圆,那么这个圆心点就累加到最大,成为峰值。因此,在检测结果中,一个峰值点,就对应一个圆心点。

霍夫圆检测的函数:

skimage.transform.hough_circle(image, radius)

radius是一个数组,表示半径的集合,如[3,4,5,6]

返回一个3维的数组(radius index, M, N), 第一维表示半径的索引,后面两维表示图像的尺寸。

例1:绘制两个圆形,用霍夫圆变换将它们检测出来。

import numpy as np
import matplotlib.pyplot as plt
from skimage import draw,transform,feature

img = np.zeros((250, 250,3), dtype=np.uint8)
rr, cc = draw.circle_perimeter(60, 60, 50) #以半径50画一个圆
rr1, cc1 = draw.circle_perimeter(150, 150, 60) #以半径60画一个圆
img[cc, rr,:] =255
img[cc1, rr1,:] =255

fig, (ax0,ax1) = plt.subplots(1,2, figsize=(8, 5))

ax0.imshow(img) #显示原图
ax0.set_title('origin image')

hough_radii = np.arange(50, 80, 5) #半径范围
hough_res =transform.hough_circle(img[:,:,0], hough_radii) #圆变换 

centers = [] #保存所有圆心点坐标
accums = [] #累积值
radii = [] #半径

for radius, h in zip(hough_radii, hough_res):
 #每一个半径值,取出其中两个圆
 num_peaks = 2
 peaks =feature.peak_local_max(h, num_peaks=num_peaks) #取出峰值
 centers.extend(peaks)
 accums.extend(h[peaks[:, 0], peaks[:, 1]])
 radii.extend([radius] * num_peaks)

#画出最接近的圆
image =np.copy(img)
for idx in np.argsort(accums)[::-1][:2]:
 center_x, center_y = centers[idx]
 radius = radii[idx]
 cx, cy =draw.circle_perimeter(center_y, center_x, radius)
 image[cy, cx] =(255,0,0)

ax1.imshow(image)
ax1.set_title('detected image')

结果图如下:原图中的圆用白色绘制,检测出的圆用红色绘制。

Python实现霍夫圆和椭圆变换代码详解

例2,检测出下图中存在的硬币。

Python实现霍夫圆和椭圆变换代码详解

import numpy as np
import matplotlib.pyplot as plt
from skimage import data, color,draw,transform,feature,util

image = util.img_as_ubyte(data.coins()[0:95, 70:370]) #裁剪原图片
edges =feature.canny(image, sigma=3, low_threshold=10, high_threshold=50) #检测canny边缘

fig, (ax0,ax1) = plt.subplots(1,2, figsize=(8, 5))

ax0.imshow(edges, cmap=plt.cm.gray) #显示canny边缘
ax0.set_title('original iamge')

hough_radii = np.arange(15, 30, 2) #半径范围
hough_res =transform.hough_circle(edges, hough_radii) #圆变换 

centers = [] #保存中心点坐标
accums = [] #累积值
radii = [] #半径

for radius, h in zip(hough_radii, hough_res):
 #每一个半径值,取出其中两个圆
 num_peaks = 2
 peaks =feature.peak_local_max(h, num_peaks=num_peaks) #取出峰值
 centers.extend(peaks)
 accums.extend(h[peaks[:, 0], peaks[:, 1]])
 radii.extend([radius] * num_peaks)

#画出最接近的5个圆
image = color.gray2rgb(image)
for idx in np.argsort(accums)[::-1][:5]:
 center_x, center_y = centers[idx]
 radius = radii[idx]
 cx, cy =draw.circle_perimeter(center_y, center_x, radius)
 image[cy, cx] = (255,0,0)

ax1.imshow(image)
ax1.set_title('detected image')

Python实现霍夫圆和椭圆变换代码详解

椭圆变换是类似的,使用函数为:

skimage.transform.hough_ellipse(img,accuracy, threshold, min_size, max_size)

输入参数:

img: 待检测图像。

accuracy: 使用在累加器上的短轴二进制尺寸,是一个double型的值,默认为1

thresh: 累加器阈值,默认为4

min_size: 长轴最小长度,默认为4

max_size: 短轴最大长度,默认为None,表示图片最短边的一半。

返回一个 [(accumulator, y0, x0, a, b, orientation)] 数组,accumulator表示累加器,(y0,x0)表示椭圆中心点,(a,b)分别表示长短轴,orientation表示椭圆方向

例:检测出咖啡图片中的椭圆杯口

import matplotlib.pyplot as plt
from skimage import data,draw,color,transform,feature

#加载图片,转换成灰度图并检测边缘
image_rgb = data.coffee()[0:220, 160:420] #裁剪原图像,不然速度非常慢
image_gray = color.rgb2gray(image_rgb)
edges = feature.canny(image_gray, sigma=2.0, low_threshold=0.55, high_threshold=0.8)

#执行椭圆变换
result =transform.hough_ellipse(edges, accuracy=20, threshold=250,min_size=100, max_size=120)
result.sort(order='accumulator') #根据累加器排序

#估计椭圆参数
best = list(result[-1]) #排完序后取最后一个
yc, xc, a, b = [int(round(x)) for x in best[1:5]]
orientation = best[5]

#在原图上画出椭圆
cy, cx =draw.ellipse_perimeter(yc, xc, a, b, orientation)
image_rgb[cy, cx] = (0, 0, 255) #在原图中用蓝色表示检测出的椭圆

#分别用白色表示canny边缘,用红色表示检测出的椭圆,进行对比
edges = color.gray2rgb(edges)
edges[cy, cx] = (250, 0, 0) 

fig2, (ax1, ax2) = plt.subplots(ncols=2, nrows=1, figsize=(8, 4))

ax1.set_title('Original picture')
ax1.imshow(image_rgb)

ax2.set_title('Edge (white) and result (red)')
ax2.imshow(edges)

plt.show()

Python实现霍夫圆和椭圆变换代码详解

霍夫椭圆变换速度非常慢,应避免图像太大。

总结

以上就是本文关于Python实现霍夫圆和椭圆变换代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
linux系统使用python获取cpu信息脚本分享
Jan 15 Python
Python输出汉字字库及将文字转换为图片的方法
Jun 04 Python
python实现自动发送邮件发送多人、群发、多附件的示例
Jan 23 Python
Python 访问限制 private public的详细介绍
Oct 16 Python
django mysql数据库及图片上传接口详解
Jul 18 Python
用Cython加速Python到“起飞”(推荐)
Aug 01 Python
python plotly画柱状图代码实例
Dec 13 Python
python encrypt 实现AES加密的实例详解
Feb 20 Python
python GUI库图形界面开发之PyQt5信号与槽基本操作
Feb 25 Python
django前端页面下拉选择框默认值设置方式
Aug 09 Python
python 使用建议与技巧分享(四)
Aug 18 Python
如何利用Python 进行边缘检测
Oct 14 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
Python实现读取及写入csv文件的方法示例
Jan 12 #Python
You might like
PHP如何解决网站大流量与高并发的问题
2011/06/25 PHP
修改PHP的memory_limit限制的方法分享
2012/02/21 PHP
PDO::query讲解
2019/01/29 PHP
Laravel 简单实现Ajax滚动加载示例
2019/10/22 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
JavaScript中的noscript元素属性位置及作用介绍
2013/04/11 Javascript
jQuery插件的写法分享
2013/06/12 Javascript
jquery+css3实现网页背景花瓣随机飘落特效
2015/08/17 Javascript
jQuery热气球动画半透明背景的后台登录界面代码分享
2015/08/28 Javascript
jQuery3.0中的buildFragment私有函数详解
2016/08/16 Javascript
Angular @HostBinding()和@HostListener()用法
2018/03/05 Javascript
微信小程序分享功能之按钮button 边框隐藏和点击隐藏
2018/06/14 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
解决idea开发遇到javascript动态添加html元素时中文乱码的问题
2020/09/29 Javascript
[02:09:59]火猫TV国士无双dota2 6.82版本详解(下)
2014/09/29 DOTA
python 字符串split的用法分享
2013/03/23 Python
python实现的多线程端口扫描功能示例
2017/01/21 Python
PyChar学习教程之自定义文件与代码模板详解
2017/07/17 Python
Python使用Windows API创建窗口示例【基于win32gui模块】
2018/05/09 Python
python3爬虫获取html内容及各属性值的方法
2018/12/17 Python
Pycharm远程调试原理及具体配置详解
2019/08/08 Python
python实现知乎高颜值图片爬取
2019/08/12 Python
python 列表、字典和集合的添加和删除操作
2019/12/16 Python
使用matlab 判断两个矩阵是否相等的实例
2020/05/11 Python
利用keras使用神经网络预测销量操作
2020/07/07 Python
Pytest测试框架基本使用方法详解
2020/11/25 Python
Python xlwings插入Excel图片的实现方法
2021/02/26 Python
Linux如何压缩可执行文件
2014/03/27 面试题
升职自荐信范文
2013/10/05 职场文书
公司业务员管理制度
2015/08/05 职场文书
2019年暑期安全广播稿!
2019/07/03 职场文书
python tkinter Entry控件的焦点移动操作
2021/05/22 Python
Java SSM配置文件案例详解
2021/08/30 Java/Android
JavaScript实现队列结构过程
2021/12/06 Javascript
Python中的tkinter库简单案例详解
2022/01/22 Python
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL