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

OpenCV+Python图像处理:固定直线X坐标稳定性优化求助

问题分析与代码优化方案

原代码核心问题

  1. 图像捕获与处理逻辑错误:captureImage函数返回随机生成的图像而非实际捕获帧,processImage混用随机图像和本地存储图像,导致处理对象混乱。
  2. 轮廓筛选缺失:直接返回第一个检测到的轮廓,未过滤噪声或非目标直线的轮廓,易受干扰。
  3. 未利用固定场景特性:相机和直线固定,但未对目标直线的位置、长度设置约束,导致坐标波动。
  4. 无坐标平滑机制:单次检测结果直接输出,未做时间维度的平滑处理。

优化后的完整代码

import time
import numpy as np
import cv2
from math import sqrt, atan, pi

# 固定场景约束参数(根据实际情况调整)
TARGET_Y_RANGE = (250, 256)  # 直线Y坐标稳定范围
TARGET_MIN_LENGTH = 5        # 目标直线最小长度
TARGET_X_RANGE = (170, 190)  # 直线X坐标大致范围(匹配你的输出示例)

# 滑动平均缓存,用于平滑坐标
coord_cache = []
CACHE_SIZE = 3  # 缓存3次检测结果做平均

def captureImage():
    print('Capturing image')
    videoCaptureObject = cv2.VideoCapture(1)
    # 跳过前3帧,让相机曝光稳定
    for _ in range(3):
        videoCaptureObject.read()
    ret, frame = videoCaptureObject.read()
    videoCaptureObject.release()
    if not ret:
        print("Failed to capture image")
        return None
    return frame

def processImage(im):
    print('Processing image')
    if im is None:
        return None, None, None, None, None
    
    # 转灰度图
    gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    
    # 增强高斯模糊,减少高频噪声
    blurred = cv2.GaussianBlur(gray, (7, 7), 1.5)
    
    # 调整Canny阈值,提升边缘检测稳定性
    edges = cv2.Canny(blurred, 30, 100)
    
    # 形态学闭运算,填补直线边缘间隙
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
    
    # 查找轮廓
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    target_contour = None
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        length = sqrt(w**2 + h**2)
        # 根据固定场景约束筛选目标轮廓
        if (TARGET_Y_RANGE[0] <= y <= TARGET_Y_RANGE[1] and
            TARGET_Y_RANGE[0] <= y+h <= TARGET_Y_RANGE[1] and
            length >= TARGET_MIN_LENGTH and
            TARGET_X_RANGE[0] <= x <= TARGET_X_RANGE[1] and
            TARGET_X_RANGE[0] <= x+w <= TARGET_X_RANGE[1]):
            target_contour = contour
            break
    
    if target_contour is not None:
        # 用轮廓极值点代替外接矩形,提升端点精度
        topmost = tuple(target_contour[target_contour[:, :, 1].argmin()][0])
        bottommost = tuple(target_contour[target_contour[:, :, 1].argmax()][0])
        # 确定上下端点
        x1, y1 = topmost
        x2, y2 = bottommost
        length = sqrt((x2 - x1)**2 + (y2 - y1)**2)
        return x1, y1, x2, y2, length
    else:
        return None, None, None, None, None

def smooth_coordinates(x1, y1, x2, y2):
    global coord_cache
    coord_cache.append((x1, y1, x2, y2))
    # 只保留最新的CACHE_SIZE个结果
    if len(coord_cache) > CACHE_SIZE:
        coord_cache.pop(0)
    # 计算平均值
    avg_x1 = int(np.mean([c[0] for c in coord_cache]))
    avg_y1 = int(np.mean([c[1] for c in coord_cache]))
    avg_x2 = int(np.mean([c[2] for c in coord_cache]))
    avg_y2 = int(np.mean([c[3] for c in coord_cache]))
    return avg_x1, avg_y1, avg_x2, avg_y2

N = 4
for i in range(N):
    frame = captureImage()
    x1, y1, x2, y2, length = processImage(frame)
    if x1 is not None:
        # 应用坐标平滑
        smoothed_x1, smoothed_y1, smoothed_x2, smoothed_y2 = smooth_coordinates(x1, y1, x2, y2)
        smoothed_length = sqrt((smoothed_x2 - smoothed_x1)**2 + (smoothed_y2 - smoothed_y1)**2)
        print(f"Original coordinates: ({x1}, {y1}) to ({x2}, {y2})")
        print(f"Smoothed coordinates: ({smoothed_x1}, {smoothed_y1}) to ({smoothed_x2}, {smoothed_y2})")
        print(f"Smoothed line length: {smoothed_length:.2f}")
        
        # 修复角度计算的边界问题
        if y1 != y2:
            azimuth = atan((x1 - x2) / (y1 - y2))
        else:
            azimuth = pi/2 if x1 < x2 else -pi/2
        altitude = atan(smoothed_length / 280)
        solaraltitude = np.degrees(altitude)
        solarazimuth = np.degrees(azimuth)
        print(f"Solar altitude: {solaraltitude:.2f}°")
        print(f"Solar azimuth: {solarazimuth:.2f}°")
    else:
        print("No line detected in the image.")
    
    time.sleep(5)

关键优化点说明

  • 修复图像捕获逻辑:移除随机图像生成,直接返回实际捕获帧;增加跳过前几帧的逻辑,让相机曝光稳定。
  • 增强噪声抑制:增大高斯模糊核尺寸,调整Canny阈值,添加形态学闭运算填补边缘间隙,减少噪声干扰。
  • 目标轮廓筛选:利用固定场景的Y坐标稳定、X坐标范围、直线长度等约束,过滤非目标轮廓。
  • 精准端点提取:使用轮廓的极值点(最上、最下)代替外接矩形,避免矩形带来的误差。
  • 坐标平滑:引入滑动平均缓存,对多次检测结果做平均,降低单次检测的波动。
  • 角度计算修复:处理Y坐标相等的边界情况,避免除零错误;使用np.degrees简化角度转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:38:11