You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV检测车轮图像中的椭圆以实现位姿估计

如何从车轮轮廓中提取有效椭圆点并计算椭圆参数

你已经通过阈值和轮廓检测定位到了车轮的最大轮廓,但冗余点的问题确实会影响椭圆参数的计算。这里有两个直接有效的解决方案,既能过滤冗余点,又能准确得到椭圆的位姿参数:


方案一:轮廓近似过滤冗余点

先通过多边形近似简化原始轮廓,去掉轮胎花纹、噪声带来的冗余点,再用简化后的轮廓拟合椭圆。

方案二:直接对原始轮廓做椭圆拟合(更推荐)

OpenCV的cv2.fitEllipse()函数本身就具备从点集中拟合最优椭圆的能力,它会自动忽略轮廓中的冗余噪声点,直接输出椭圆的关键参数,非常适合你的车轮位姿估计需求。


修改后的完整代码

import sys
import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage import img_as_ubyte

# 测试图片路径
filenames = [
    'back_wheel.png',
    'backwheel1.png',
    'backwheel2.png',
    'backwheel3.png',
    'frontwheel1.png',
    'frontwheel2.png'
]

def getWheel0(filename):
    image_rgb_orig = cv2.imread(filename)
    if image_rgb_orig is None:
        print(f"无法读取图片: {filename}")
        return
    image_rgb = image_rgb_orig.copy()
    print('Original Dimensions : ', image_rgb.shape)
    
    # 统一缩放图片,方便处理
    width = 350
    height = int(width * image_rgb.shape[0]/image_rgb.shape[1])
    dim = (width, height)
    image_rgb = cv2.resize(image_rgb, dim, interpolation=cv2.INTER_AREA)
    image_gray = cv2.cvtColor(image_rgb, cv2.COLOR_BGR2GRAY)
    
    # 直方图均衡化增强对比度
    equ = cv2.equalizeHist(image_gray)
    norm_image = cv2.normalize(equ, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
    
    # 阈值处理得到二值图
    ret, th = cv2.threshold(norm_image, 0.2, 1.0, cv2.THRESH_TOZERO_INV)
    th = img_as_ubyte(th)  # 转换为8位格式,方便轮廓检测
    
    # 寻找轮廓(只提取最外层轮廓)
    contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # 筛选最大面积的轮廓
    big_contour = None
    max_area = 0
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > max_area:
            max_area = area
            big_contour = cnt
    
    if big_contour is None:
        print(f"未找到有效轮廓: {filename}")
        return
    
    # ------------------- 核心处理部分 -------------------
    # 方法1:轮廓近似(可选,用于过滤冗余点)
    epsilon = 0.005 * cv2.arcLength(big_contour, True)
    approx_contour = cv2.approxPolyDP(big_contour, epsilon, True)
    
    # 方法2:直接拟合椭圆(推荐)
    ellipse = cv2.fitEllipse(big_contour)
    # 提取椭圆参数:(中心(x,y), (长轴长度, 短轴长度), 旋转角度)
    ell_center, ell_axes, ell_angle = ellipse
    
    # 在图像上绘制结果
    result = image_rgb.copy()
    # 绘制原始最大轮廓(细绿色线)
    cv2.drawContours(result, [big_contour], -1, (0, 255, 0), 1)
    # 绘制近似后的轮廓(细蓝色线,可选)
    cv2.drawContours(result, [approx_contour], -1, (255, 0, 0), 1)
    # 绘制拟合的椭圆(粗红色线)
    cv2.ellipse(result, ellipse, (0, 0, 255), 2)
    
    # 打印椭圆参数,用于位姿估计
    print(f"\n图片 {filename} 的椭圆参数:")
    print(f"中心坐标: {round(ell_center[0],2)}, {round(ell_center[1],2)}")
    print(f"长轴/短轴: {round(ell_axes[0],2)}, {round(ell_axes[1],2)}")
    print(f"旋转角度: {round(ell_angle,2)}°")
    
    # 显示结果
    fig2, (ax1, ax2, ax3) = plt.subplots(ncols=3, nrows=1, figsize=(12, 4), sharex=True, sharey=True)
    ax1.set_title('Original Image')
    ax1.imshow(cv2.cvtColor(image_rgb_orig, cv2.COLOR_BGR2RGB))
    ax2.set_title('Thresholded Image')
    ax2.imshow(th, cmap='gray')
    ax3.set_title('Ellipse Fitting Result')
    ax3.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
    plt.show()

# 处理所有测试图片
for fname in filenames:
    getWheel0(fname)

关键代码解释

  1. 轮廓近似:

    • cv2.arcLength()计算轮廓的周长,epsilon是近似精度,值越小保留的细节越多,值越大简化程度越高。你可以根据实际图片调整0.005这个系数,找到最适合的简化效果。
    • 近似后的轮廓点数量大幅减少,轮胎花纹、边缘噪声带来的冗余点会被过滤掉。
  2. 椭圆拟合:

    • cv2.fitEllipse()直接接收原始轮廓点集,基于最小二乘法拟合出最优椭圆,返回的元组包含所有位姿相关参数:
      • ell_center:椭圆中心坐标,对应车轮的中心位置
      • ell_axes:长轴和短轴的长度,结合相机内参就能计算车轮的实际尺寸
      • ell_angle:椭圆的旋转角度,对应车轮的姿态角
    • 这个函数会自动忽略轮廓中的噪声点,拟合结果稳定可靠,完全满足位姿估计的需求。
  3. 阈值优化:

    • 把原来的固定阈值改成了适配归一化图像的0.2,1.0,避免因为不同图片亮度差异导致检测失败,鲁棒性更强。

运行方式

保存修改后的代码为tire.py,然后在终端运行:

python tire.py

你会看到每张图片的原始图、阈值图和拟合结果图,同时控制台会输出每个车轮的椭圆参数,直接用于位姿估计即可。

内容的提问来源于stack exchange,提问作者user2996950

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:45:58