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

Python实现噪声平面图线条降噪与实体化的技术求助

噪声平面图的线条降噪与实体化优化方案

问题背景

对噪声严重的平面图进行线条降噪及实体化处理,已尝试masking、bluring、HoughLinesP及前两者的组合方法。使用HoughLinesP可实现线条实体化,但文字区域线条严重重叠,且调整minLineLength、maxLineGap参数无法解决该问题。

原始处理代码

import cv2
import numpy as np
from tkinter import Tk     # from tkinter import Tk for Python 3.x
from tkinter.filedialog import askopenfilename
import os

Tk().withdraw() # 隐藏TK主窗口
filename = askopenfilename() # 打开文件选择对话框
print(filename)

filename3, file_extension = os.path.splitext(filename)

# 读取灰度图
img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)

# 初始化彩色输出图
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 中值模糊降噪并反转图像
img = 255 - cv2.medianBlur(img, 3)

# 检测并绘制线条
lines = cv2.HoughLinesP(img, 1, np.pi/180, 10, minLineLength=40, maxLineGap=30)
for line in lines:
    for x1, y1, x2, y2 in line:
        cv2.line(out, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow('out', out)
cv2.imwrite(filename3+' '+'69'+'.png', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

问题分析

文字区域的线条重叠本质是文字笔画被HoughLinesP误识别为线条,由于文字笔画短且密集,单纯调整长度或间隙参数会陷入“过滤文字则丢失有效短线条”的矛盾,需从预处理阶段分离文字与线条,或采用更精准的线条检测逻辑。

解决方案

方案1:形态学操作过滤文字区域

利用文字与线条的形态差异(线条为长条形,文字为小区域密集笔画),通过长条形核的开运算过滤文字,保留目标线条:

import cv2
import numpy as np
from tkinter import Tk
from tkinter.filedialog import askopenfilename
import os

Tk().withdraw()
filename = askopenfilename()
print(filename)

filename3, file_extension = os.path.splitext(filename)

# 读取灰度图并初始化输出
img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 反转图像(背景黑,线条白)
img_inv = 255 - img

# 用水平长核开运算,过滤文字保留水平线条
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 1))
img_horizontal = cv2.morphologyEx(img_inv, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)

# 用垂直长核开运算,保留垂直线条
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 30))
img_vertical = cv2.morphologyEx(img_inv, cv2.MORPH_OPEN, vertical_kernel, iterations=2)

# 合并水平与垂直线条
img_lines = cv2.addWeighted(img_horizontal, 0.5, img_vertical, 0.5, 0)

# 降噪后检测线条
img_blur = cv2.medianBlur(img_lines, 3)
lines = cv2.HoughLinesP(img_blur, 1, np.pi/180, threshold=20, minLineLength=40, maxLineGap=30)

if lines is not None:
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(out, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow('Processed Lines', out)
cv2.imwrite(filename3+'_processed.png', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案2:轮廓筛选替代HoughLinesP

通过Canny边缘检测提取轮廓,筛选长条形轮廓(线条),过滤小面积轮廓(文字):

import cv2
import numpy as np
from tkinter import Tk
from tkinter.filedialog import askopenfilename
import os

Tk().withdraw()
filename = askopenfilename()
print(filename)

filename3, file_extension = os.path.splitext(filename)

img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 降噪+Canny边缘检测
img_blur = cv2.GaussianBlur(img, (5,5), 0)
edges = cv2.Canny(img_blur, 50, 150)

# 提取轮廓并筛选长条形线条
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt)
    # 计算长宽比,保留长线条(可根据图像调整阈值)
    aspect_ratio = max(w, h) / min(w, h) if min(w, h) !=0 else 0
    if aspect_ratio > 10 and (w > 30 or h > 30):
        cv2.rectangle(out, (x,y), (x+w, y+h), (0,0,255), 2)

cv2.imshow('Contour-based Lines', out)
cv2.imwrite(filename3+'_contour.png', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案3:文字检测屏蔽区域

用OCR工具检测文字区域,在HoughLinesP检测时屏蔽这些区域(需安装pytesseract及Tesseract引擎):

import cv2
import numpy as np
import pytesseract
from tkinter import Tk
from tkinter.filedialog import askopenfilename
import os

# 配置Tesseract路径(根据实际安装路径调整)
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

Tk().withdraw()
filename = askopenfilename()
print(filename)

filename3, file_extension = os.path.splitext(filename)

img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 检测高置信度文字区域,生成掩码
d = pytesseract.image_to_data(img, output_type=pytesseract.Output.DICT)
mask = np.ones_like(img, dtype=np.uint8) * 255
n_boxes = len(d['text'])

for i in range(n_boxes):
    if int(d['conf'][i]) > 60:
        x, y, w, h = d['left'][i], d['top'][i], d['width'][i], d['height'][i]
        cv2.rectangle(mask, (x, y), (x+w, y+h), 0, -1)

# 应用掩码去除文字区域
img_no_text = cv2.bitwise_and(img, mask)

# 后续线条检测流程
img_inv = 255 - cv2.medianBlur(img_no_text, 3)
lines = cv2.HoughLinesP(img_inv, 1, np.pi/180, 10, minLineLength=40, maxLineGap=30)

if lines is not None:
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(out, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow('No Text Lines', out)
cv2.imwrite(filename3+'_no_text.png', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案选型建议

  • 形态学操作方案:无额外依赖,适合文字与线条形态差异明显的场景;
  • 轮廓筛选方案:自定义性强,可灵活调整轮廓特征过滤无效区域;
  • 文字检测方案:适合文字复杂但需精准屏蔽的场景,需额外安装OCR工具。

内容的提问来源于stack exchange,提问作者Luke-McDevitt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:40:27