python实现椭圆检测

最近在做一个跟测量有关的项目,进行椭圆检测用不到深度学习,仅仅是简单的图像处理,但是确实把我难到了。这里分享两个椭圆检测的思路。一个是通过openCV的椭圆检测器实现的,另一个是通过霍夫变化实现的。

有一说一,看到里面各种没见过的处理方法,我就好像挨了一巴掌,然后告诉我:你的视觉还没入门呢。

一、 完整的椭圆检测流程

拿到一张图片,我们首先需要进行预处理

1. 图像预处理

  • 灰度化:将彩色图像转换为灰度图像,简化处理过程。
  • 滤波:使用高斯滤波、中值滤波等方法去除图像噪声。
  • 边缘检测:应用Canny、Sobel等边缘检测算法来提取图像中的边缘信息。边缘是图像中物体轮廓的基础。

2. 轮廓检测

  • 轮廓查找 :使用OpenCV等库中的findContours函数来检测图像中的轮廓。
  • 轮廓筛选:根据轮廓的大小、形状等特征筛选出可能的椭圆轮廓。

3. 椭圆拟合

  • 最小二乘法拟合:对筛选出的轮廓,使用最小二乘法拟合椭圆。常用的方法有基于代数距离的最小二乘法(直接拟合椭圆方程)和基于几何距离的最小二乘法(如椭圆拟合的RANSAC算法)。
  • 椭圆检测器 :使用专门的椭圆检测器,如OpenCV中的fitEllipse函数,它可以直接在轮廓上拟合一个椭圆。

4. 验证和优化

  • 验证拟合结果:通过计算拟合椭圆的参数(如长短轴、中心点、旋转角度等)与图像中实际轮廓的匹配程度来验证拟合结果。
  • 优化参数:根据实际需求调整滤波、边缘检测、轮廓筛选等步骤的参数,以获得更好的识别效果。

二、 openCV的椭圆检测器操作示例

1. 图像预处理

js 复制代码
## 获取图像
imageSrc =  './images/droppy.png'
image = cv2.imread(imageSrc)

## 1. 灰度处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)



# 2. 边缘检测
edges = cv2.Canny(blurred, 50, 150)

## 侵蚀尺度设置
length = max(gray.shape)
# 膨胀和腐蚀可以帮助减少噪声和小轮廓
kernel = np.ones((int(length/20), int(length/20)), np.uint8)
edges = cv2.dilate(edges, kernel, iterations=1)
edges = cv2.erode(edges, kernel, iterations=1)

# 3. 轮廓追踪
_, contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

这里为了更好的排除一些小的轮廓,又加了一步侵蚀,效果确实不错。

这是原图、灰度和边缘检测后的对比图。

这是轮廓追踪后的效果图

2. 筛选检测椭圆

对于轮廓需要进行椭圆拟合,然后筛选不合规的椭圆。我这里进行了两步筛选。

  1. 检查椭圆中心是否在图像内部
  2. 对椭圆按照面积进行排序,找到面积最大椭圆

检测长宽比,因为范围不好界定我给注释掉了,需要的可以加上。

js 复制代码
ellipses = []
for contour in contours:
    # 1. 检测椭圆
    ellipse = cv2.fitEllipse(contour)
    # 椭圆中心坐标;椭圆长轴和短轴的长度(直径);椭圆旋转角度
    center, axes, orientation = ellipse

    # 2. 检查椭圆中心是否在图像内部
    if 0 <= center[0] <= image.shape[0] and 0 <= center[1] <= image.shape[1]:
        # min_aspect_ratio = 0.7
        # max_aspect_ratio = 1.3
        # # 检测长宽比
        # if min_aspect_ratio <= aspect_ratio <= max_aspect_ratio:
        ellipses.append(ellipse)
        # cv2.ellipse(image, ellipse, (0, 255, 255), 2) # 绘制黄色
# 3.筛选椭圆
# 对椭圆按照面积进行排序,找到面积最大的圆
sorted_ellipses = sorted(ellipses, key=lambda item: item[1][0] * item[1][1], reverse=True)

selectedEllipse = sorted_ellipses[0]
cv2.ellipse(image, selectedEllipse, (0, 255, 0), 2)
cv2.imshow('Ellipse', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 结果图

绿色就是我们筛选出的椭圆,可以说是非常完美

三、霍夫变换检测操作示例

基本操作方式与上面基本相同

1. 加载图片,转换成灰度图并检测边缘

js 复制代码
from skimage import data,draw,color,transform,feature
import cv2

#1. 加载图片,转换成灰度图并检测边缘
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)

2. 执行椭圆变换

js 复制代码
#2. 执行椭圆变换
result =transform.hough_ellipse(edges, accuracy=20, threshold=250,min_size=100, max_size=120)

3. 估计椭圆参数

js 复制代码
#3. 估计椭圆参数
result.sort(order='accumulator') #根据累加器排序
best = list(result[-1]) #排完序后取最后一个
yc, xc, a, b = [int(round(x)) for x in best[1:5]]
orientation = best[5]
selectedEllipse = ((xc,yc),(2*a,2*b),orientation)

4. 在原图上画出椭圆

js 复制代码
#4. 在原图上画出椭圆
cv2.ellipse(image_rgb, selectedEllipse, (0, 255, 0), 2)
cv2.imshow('Ellipse', image_rgb)
cv2.waitKey(0)
cv2.destroyAllWindows()

四、椭圆检测器和霍夫变换的优劣分析

  1. 椭圆检测器精度一般,速度较快。 他核心的原理是获得能够包围轮廓的最小椭圆,所以如果轮廓识别不精准,椭圆识别效果就会很差。

  2. 霍夫变换的精度很好,但是速度太慢,尤其是像素比较大的图片,会让你怀疑是不是程序卡死了。 霍夫变换更贴近我们想要识别的椭圆,但是需要注意对图片进行压缩。

相关推荐
敲代码不忘补水2 分钟前
Python 项目实践:简单的计算器
开发语言·python·json·项目实践
Zhangci]15 分钟前
Opencv图像预处理(三)
人工智能·opencv·计算机视觉
鸽芷咕1 小时前
【Python报错已解决】ModuleNotFoundError: No module named ‘paddle‘
开发语言·python·机器学习·bug·paddle
子午1 小时前
动物识别系统Python+卷积神经网络算法+TensorFlow+人工智能+图像识别+计算机毕业设计项目
人工智能·python·cnn
风等雨归期2 小时前
【python】【绘制小程序】动态爱心绘制
开发语言·python·小程序
Adolf_19932 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
冯宝宝^2 小时前
基于mongodb+flask(Python)+vue的实验室器材管理系统
vue.js·python·flask
叫我:松哥2 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
Eiceblue2 小时前
Python 复制Excel 中的行、列、单元格
开发语言·python·excel
NLP工程化3 小时前
对 Python 中 GIL 的理解
python·gil