红色高亮断线与黄色高亮虚线的检测及补全方案求助

可行解决方案
以下方案可同时解决红色区域断线被圆点拆分、黄色区域虚线无法拼接的问题:
1. 预处理:分离目标区域
先通过颜色阈值把红色、黄色标注的区域单独提取出来,排除其他无关内容的干扰:
- 将图像转换为HSV色彩空间,分别设置红色、黄色的HSV阈值生成掩码
- 用掩码和灰度原图做与运算,仅保留对应标注区域内的图形内容
2. 红色区域断线补全
针对红色区域内圆点打断主线段的问题,处理步骤如下:
- 对红色区域做3x3圆形核的形态学开运算,消除区域内的小圆点噪声,不会腐蚀主线段
- 用1x15的水平矩形核做形态学闭运算,填充被圆点打断的线段缝隙,将多段碎线连接为完整线段
- 做轮廓检测后过滤长度不足的短轮廓,对保留的长轮廓用
cv2.fitLine()做直线拟合,得到主线段参数后直接在对应位置绘制完整线条即可
3. 黄色区域虚线拼接
针对黄色区域虚线的拼接需求,处理步骤如下:
- 对黄色区域做二值化处理,提取虚线的短段为前景
- 调整概率霍夫变换的参数:将最小线段长度设为虚线单段的长度,最大线段间隙设为两段虚线之间的间隔,检测出所有属于虚线的短线段
- 对检测到的短线段做分类:斜率接近0的归为水平虚线类,斜率绝对值极大的归为垂直虚线类
- 对同一类的线段取坐标极值拼接:水平虚线取所有线段y坐标的平均值、x坐标的最小最大值,直接绘制完整水平线;垂直虚线取x坐标的平均值、y坐标的最小最大值,绘制完整垂直线
核心代码示例(Python + OpenCV)
import cv2 import numpy as np # 读取输入图像 img = cv2.imread("input.png") hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 生成红色区域掩码 lower_red1 = np.array([0, 120, 70]) upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 120, 70]) upper_red2 = np.array([180, 255, 255]) mask_red = cv2.inRange(hsv, lower_red1, upper_red1) + cv2.inRange(hsv, lower_red2, upper_red2) # 生成黄色区域掩码 lower_yellow = np.array([20, 100, 100]) upper_yellow = np.array([30, 255, 255]) mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow) # ---------------------- 红色区域处理 ---------------------- red_gray = cv2.bitwise_and(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), mask_red) # 开运算消除小圆点 kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) red_processed = cv2.morphologyEx(red_gray, cv2.MORPH_OPEN, kernel_open, iterations=1) # 水平闭运算连接断线 kernel_close = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 1)) red_processed = cv2.morphologyEx(red_processed, cv2.MORPH_CLOSE, kernel_close, iterations=2) # 拟合主线段 contours, _ = cv2.findContours(red_processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: # 过滤长度不足的短轮廓 if cv2.arcLength(cnt, closed=False) > 50: [vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01) # 计算直线两端点坐标 left_y = int((-x * vy / vx) + y) right_y = int(((img.shape[1] - x) * vy / vx) + y) cv2.line(img, (0, left_y), (img.shape[1] - 1, right_y), (0, 255, 0), 2) # ---------------------- 黄色区域处理 ---------------------- yellow_gray = cv2.bitwise_and(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), mask_yellow) _, yellow_bin = cv2.threshold(yellow_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 概率霍夫变换检测虚线短段 lines = cv2.HoughLinesP(yellow_bin, 1, np.pi / 180, threshold=10, minLineLength=8, maxLineGap=20) horizontal_segs = [] vertical_segs = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] if abs(y2 - y1) < 5: horizontal_segs.append((x1, y1, x2, y2)) elif abs(x2 - x1) < 5: vertical_segs.append((x1, y1, x2, y2)) # 拼接水平虚线 if horizontal_segs: y_avg = int(np.mean([seg[1] for seg in horizontal_segs])) x_min = min([min(seg[0], seg[2]) for seg in horizontal_segs]) x_max = max([max(seg[0], seg[2]) for seg in horizontal_segs]) cv2.line(img, (x_min, y_avg), (x_max, y_avg), (0, 255, 0), 2) # 拼接垂直虚线 if vertical_segs: x_avg = int(np.mean([seg[0] for seg in vertical_segs])) y_min = min([min(seg[1], seg[3]) for seg in vertical_segs]) y_max = max([max(seg[1], seg[3]) for seg in vertical_segs]) cv2.line(img, (x_avg, y_min), (x_avg, y_max), (0, 255, 0), 2)
内容的提问来源于stack exchange,提问作者Taarun Srinivas
相关产品推荐
相关产品推荐

