优秀的编程知识分享平台

网站首页 > 技术文章 正文

2D电气图(非矢量图)一键转为CAD图纸

nanyue 2024-09-11 05:20:31 技术文章 4 ℃

00、背景

设计院提供2D的电气图,如何快速进行二次修改?

如果直接提供CAD矢量图,那就很方便。但设计院为了知识版权,一般只会提供pdf或图片文件。

那有没好的办法,进行一键转换为CAD图纸?

正好最近看OpenCV相关的书籍,有些思路。

01、实现原理

使用本文的代码会一键将 2D 图像转换为 DXF 文件。

主要利用了 OpenCV 进行图像处理并使用 Potrace 进行矢量化,简化了转换过程,使其成为 CAD 应用程序的理想选择,轻松高效地简化从图像到 DXF 的工作流程。

生成的 DXF 文件与各种 CAD 软件兼容,可以进一步编辑或查看。

重点步骤分解

  1. 输入:用户提供双电源接线图文件的路径。
  2. 图像处理:包括灰度转换、边缘检测和使用形态学操作进行细化。
  3. 矢量化:使用 Potrace 将处理后的 BMP 图像转换为 SVG。
  4. DXF 转换:将 SVG 路径转换为 DXF 格式。
  5. 输出:将最终的 DXF 文件保存为 final.dxf

02、执行效果

输入图片:test.jpg

中间输出svg文件:

最终输出CAD图纸:final.dxf

运行前置条件

Python Libraries Python 库

  • NumPy:与 OpenCV 结合使用进行数值运算。
  • ezdxf:创建和操作 DXF 文件。
  • svgpathtools:用于解析 SVG 文件。
  • 子进程:用于运行外部命令,本文用到了 Potrace。下载地址:https://potrace.sourceforge.net/#downloading

安装所需的软件包

使用 pip 安装所需的软件包:

pip install opencv-python-headless
pip install numpy
pip install ezdxf
pip install svgpathtools

03、主要库和函数介绍

OpenCV (cv2)

用于图像处理任务的强大库。

  • cv2.imread :从文件中读取图像。
  • cv2.cvtColor :将图像转换为不同的颜色空间;这里用于灰度转换。
  • cv2.Canny :执行边缘检测。
  • cv2.GaussianBlur :减少图像中的噪点。
  • cv2.threshold :对图像应用固定级别的阈值。
  • cv2.erodecv2.dilate :执行形态学操作。

Subprocess 子流程

用于在 Python 中运行外部命令。

  • subprocess.run :执行 Potrace 命令以对图像进行矢量化。

ezdxf

用于创建和修改 DXF 绘图的 Python 包。

  • ezdxf.new :初始化一个新的DXF文档。
  • doc.modelspace() :访问图形实体的绘图空间。

svgpathtools

操作和分析 SVG 路径。

04、完整代码

代码简单,注释完整。

import cv2
import numpy as np
import os
import subprocess
import ezdxf
from svgpathtools import svg2paths

# 提示用户输入图像的路径
input_image_path = input("输入您要转换图片的文件路径: ")

# 检查提供的路径是否有效
if not os.path.exists(input_image_path):
    print("指定的文件不存在。 请检查路径并重试。")
else:
    # 读取图片
    image = cv2.imread(input_image_path)

    # 将图像转换为灰度
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 应用边缘检测
    edges = cv2.Canny(gray_image, threshold1=50, threshold2=150)

    # 应用高斯模糊来降噪
    blurred = cv2.GaussianBlur(edges, (5, 5), 0)

    # 对图像设置阈值以确保其是二进制的
    _, binary_image = cv2.threshold(blurred, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

    # 使用形态学运算来减少线条的粗细
    eroded = cv2.erode(binary_image, np.ones((2,2), np.uint8), iterations=1)
    dilated = cv2.dilate(eroded, np.ones((3,3), np.uint8), iterations=1)

    # 通过用 .bmp 替换原始扩展名来构造输出文件名
    output_bmp_path = os.path.splitext(input_image_path)[0] + '_refined_edges.bmp'

    # 将精化边缘图像保存为 .bmp 文件
    cv2.imwrite(output_bmp_path, dilated)

    # 定义输出 SVG 的路径
    output_svg_path = os.path.splitext(input_image_path)[0] + '_vectorized.svg'

    # 运行 Potrace,将位图转换为 SVG
    subprocess.run(['potrace', '-s', output_bmp_path, '-o', output_svg_path])

    # 检查SVG是否创建成功
    if os.path.exists(output_svg_path):
        print(f"SVG 文件已成功创建于: {output_svg_path}")
        
        # 将 SVG 转换为 DXF
        paths, attributes = svg2paths(output_svg_path)

        # 创建新的 DXF 文档
        doc = ezdxf.new(dxfversion='R2010')
        msp = doc.modelspace()

        for path in paths:
            for line in path:
                start_point = (line.start.real, line.start.imag)
                end_point = (line.end.real, line.end.imag)
                msp.add_line(start_point, end_point)

        # 保存文档
        output_dxf_path = os.path.join(os.path.dirname(input_image_path),'final.dxf')
        doc.saveas(output_dxf_path)
        print(f"DXF 文件已成功创建于:{output_dxf_path}")
    else:
        print("SVG 文件创建失败。")

05、小结

  • 以上代码适用于简单的 2D 图像。输入图像的质量会影响输出。
  • 对于复杂或详细的图像,还需要在 CAD 程序中进行额外的手动编辑。

Tags:

最近发表
标签列表