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

求助:如何从道路掩码二值图中提取左右边缘点集

解决方案

方法一:基于现有轮廓检测结果分割左右边缘

针对你当前轮廓包含道路底部边界、无法区分左右点集的问题,可通过两步处理解决:

  1. 过滤底部边界点:道路掩码的底部边缘通常靠近图像下边界,通过y坐标阈值过滤掉这部分无效点
  2. 按x坐标分割左右边缘:以图像中线为界,将剩余点分为左、右两个独立点集

修改后的代码如下:

import cv2
import numpy as np

image = cv2.imread('/home/user/Desktop/seg_output/1.jpg')
h, w = image.shape[:2]

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)

# 获取最大轮廓点集并去除冗余维度
contour_points = np.squeeze(contours[0])

# 过滤底部边界点:保留y坐标小于图像高度90%的点(可根据实际情况调整阈值)
y_threshold = int(h * 0.9)
filtered_points = contour_points[contour_points[:, 1] < y_threshold]

# 按图像中线分割左右边缘
mid_x = w // 2
left_edge_points = filtered_points[filtered_points[:, 0] < mid_x]
right_edge_points = filtered_points[filtered_points[:, 0] > mid_x]

# 可视化结果
vis_image = image.copy()
cv2.drawContours(vis_image, [left_edge_points], -1, (0, 0, 255), 2)
cv2.drawContours(vis_image, [right_edge_points], -1, (255, 0, 0), 2)

print("左边缘点数量:", len(left_edge_points))
print("右边缘点数量:", len(right_edge_points))

cv2.imshow('Left & Right Edges', vis_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

方法二:Sobel边缘检测+轮廓提取

你提到的Sobel兼容性问题,只需将Sobel输出转换为8位无符号整数,即可正常进行轮廓检测:

import cv2
import numpy as np

image = cv2.imread('/home/user/Desktop/seg_output/1.jpg')
h, w = image.shape[:2]
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Sobel边缘检测并转换为8位图像
sobel_x = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=3)
sobel_edges = cv2.convertScaleAbs(cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0))

# 二值化后提取轮廓
_, binary_sobel = cv2.threshold(sobel_edges, 50, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(binary_sobel, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 过滤小轮廓并分割左右边缘
contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 50]
all_points = np.concatenate([np.squeeze(cnt) for cnt in contours])
y_threshold = int(h * 0.9)
filtered_points = all_points[all_points[:, 1] < y_threshold]
mid_x = w // 2
left_edge = filtered_points[filtered_points[:, 0] < mid_x]
right_edge = filtered_points[filtered_points[:, 0] > mid_x]

# 可视化结果
vis_image = image.copy()
cv2.drawContours(vis_image, [left_edge], -1, (0,0,255), 2)
cv2.drawContours(vis_image, [right_edge], -1, (255,0,0), 2)
cv2.imshow('Sobel-based Edges', vis_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

补充说明

  • 若道路左右边缘有明显上下走向,也可通过轮廓点的排列顺序分割:OpenCV轮廓按顺时针/逆时针排列,左、右边缘通常连续分布,可通过x坐标变化趋势区分,但按中线分割更简单直接
  • 所有阈值参数(y坐标阈值、Sobel二值化阈值)可根据实际图像调整,以获得最优效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:35:03