前言
身為一個平時寫後端的工程師,偶爾玩玩 maker 專案是我放鬆的方式。最近我開始嘗試把 AI 生成的圖案拿去雷射切割,結果發現中間有不少眉角要處理。AI 生成的圖是點陣圖(raster),但雷切機要的是向量圖(vector),這中間的轉換如果沒處理好,切出來的東西會慘不忍睹。
這篇文章記錄我從「AI 生圖」到「實際雷切成品」的完整流程,包括向量化工具的選擇、路徑清理、以及一些踩過的坑。
整體工作流
[AI 生成圖案] → [後處理/清理] → [向量化] → [路徑優化] → [雷切軟體] → [實際切割]
Midjourney Photoshop potrace Inkscape LightBurn
DALL-E GIMP vectorizer.ai 自訂腳本 LaserGRBL
SD + ControlNet
每一步都有需要注意的地方,讓我們一步步來。
Step 1:AI 生成適合雷雕的圖案
不是所有 AI 生成的圖都適合拿去雷切。雷切需要的是高對比、邊緣清晰、結構簡潔的圖案。
好的 Prompt 策略
# Midjourney 風格的 prompt
"geometric wolf logo, black and white, clean lines, vector style,
no gradients, high contrast, minimal detail, suitable for laser cutting"
# Stable Diffusion 用的 prompt
"(line art:1.3), (black and white:1.2), geometric pattern, mandala design,
clean edges, no shading, simple shapes, vector illustration"
# 負面 prompt(很重要!)
"gradient, shading, realistic, photograph, complex texture, watercolor,
soft edges, blurry, 3d render"
生成後的初步處理
from PIL import Image, ImageFilter, ImageOps
import numpy as np
def prepare_for_vectorization(input_path, output_path, threshold=128):
"""將 AI 生成的圖處理成適合向量化的黑白圖"""
img = Image.open(input_path)
# 轉灰階
gray = img.convert("L")
# 提高對比度
# 用 autocontrast 自動拉開黑白範圍
enhanced = ImageOps.autocontrast(gray, cutoff=5)
# 輕微模糊去除 AI 生成的細碎雜訊
blurred = enhanced.filter(ImageFilter.GaussianBlur(radius=1))
# 二值化
binary = blurred.point(lambda x: 255 if x > threshold else 0, mode="1")
# 儲存為 BMP(potrace 偏好的格式)
binary.save(output_path)
print(f"處理完成: {output_path}")
print(f"圖片尺寸: {binary.size}")
prepare_for_vectorization("ai_generated.png", "cleaned.bmp", threshold=140)
Step 2:向量化工具比較
Potrace(開源免費)
Potrace 是最經典的點陣轉向量工具,完全免費開源。
# 安裝 potrace
# macOS
brew install potrace
# Ubuntu
sudo apt-get install potrace
# 基本用法:BMP → SVG
potrace cleaned.bmp -s -o output.svg
# 進階參數
potrace cleaned.bmp \
-s \ # 輸出 SVG
-o output.svg \ # 輸出檔名
-t 5 \ # turdsize: 忽略小於 5 像素的碎片
-a 1.0 \ # alphamax: 角的平滑度 (0=尖角, 1.334=最平滑)
-O 0.2 \ # opttolerance: 曲線優化容差
--flat \ # 不要群組,每個路徑獨立
-r 300 # 解析度 (DPI)
# 用 Python 批次處理
import subprocess
import os
from pathlib import Path
def batch_vectorize(input_dir, output_dir, turdsize=5, alphamax=1.0):
"""批次將 BMP 檔案向量化為 SVG"""
Path(output_dir).mkdir(parents=True, exist_ok=True)
for bmp_file in Path(input_dir).glob("*.bmp"):
svg_file = Path(output_dir) / f"{bmp_file.stem}.svg"
cmd = [
"potrace",
str(bmp_file),
"-s",
"-o", str(svg_file),
"-t", str(turdsize),
"-a", str(alphamax),
"-O", "0.2",
"--flat",
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f"OK: {bmp_file.name} → {svg_file.name}")
else:
print(f"Error: {bmp_file.name}: {result.stderr}")
batch_vectorize("./cleaned_images", "./svg_output")
Vectorizer.ai(線上服務)
Vectorizer.ai 是目前品質最好的 AI 向量化服務。它不只是描邊,而是真正「理解」圖形結構。
import requests
def vectorize_with_api(input_path, output_path, api_key):
"""使用 vectorizer.ai API 進行向量化"""
with open(input_path, "rb") as f:
response = requests.post(
"https://api.vectorizer.ai/api/v1/vectorize",
files={"image": f},
data={
"mode": "production",
"output.file_format": "svg",
"output.gap_filler.enabled": True,
"processing.max_colors": 2, # 黑白雷雕只需要 2 色
},
headers={"Authorization": f"Basic {api_key}"},
)
if response.status_code == 200:
with open(output_path, "wb") as out:
out.write(response.content)
print(f"向量化完成: {output_path}")
else:
print(f"錯誤: {response.status_code} - {response.text}")
兩者比較
| 特性 | Potrace | Vectorizer.ai |
|——|———|—————|
| 價格 | 免費 | 付費 API |
| 品質 | 好(簡單圖形) | 優秀(複雜圖形也行) |
| 速度 | 極快 | 需要上傳等待 |
| 離線使用 | 可以 | 不行 |
| 曲線平滑度 | 普通 | 很好 |
| 適合場景 | 簡潔線條圖 | 複雜有細節的圖 |
Step 3:路徑清理與優化
向量化之後的 SVG 往往有很多問題:多餘的節點、重複路徑、太小的碎片。這些都需要清理。
from lxml import etree
import re
def clean_svg_for_laser(input_svg, output_svg, min_path_length=10):
"""清理 SVG,讓它適合雷切"""
tree = etree.parse(input_svg)
root = tree.getroot()
ns = {"svg": "http://www.w3.org/2000/svg"}
removed_count = 0
# 1. 移除太短的路徑(碎片)
for path in root.findall(".//svg:path", ns):
d = path.get("d", "")
# 簡單估算路徑長度(計算座標點數量)
coords = re.findall(r"[-+]?\d*\.?\d+", d)
if len(coords) < min_path_length:
path.getparent().remove(path)
removed_count += 1
# 2. 移除不可見元素
for elem in root.findall(".//*[@opacity='0']", ns):
elem.getparent().remove(elem)
removed_count += 1
# 3. 統一線條顏色(雷切通常只需要一種顏色)
for path in root.findall(".//svg:path", ns):
path.set("stroke", "#000000")
path.set("fill", "none")
path.set("stroke-width", "0.5")
tree.write(output_svg, pretty_print=True, xml_declaration=True)
print(f"清理完成,移除了 {removed_count} 個元素")
clean_svg_for_laser("raw_output.svg", "laser_ready.svg")
用 Inkscape 命令列進一步優化
# Inkscape 命令列操作(無需開啟 GUI)
# 簡化路徑,減少節點數量
inkscape laser_ready.svg \
--actions="select-all;path-simplify;export-filename:simplified.svg;export-do" \
--batch-process
# 轉換所有物件為路徑
inkscape input.svg \
--actions="select-all;object-to-path;export-filename:paths_only.svg;export-do" \
--batch-process
# 設定文件尺寸(配合雷切機的工作範圍)
inkscape simplified.svg \
--actions="select-all;transform-scale:50,50;export-filename:scaled.svg;export-do" \
--batch-process
Step 4:送進雷切軟體
LightBurn(付費,推薦)
# LightBurn 的 CLI 匯入(如果有支援的話)
# 通常是直接 GUI 操作,但可以用 gcode 前處理
# 基本雷切參數建議(3mm 椴木合板)
# 切割:Power 80%, Speed 10mm/s
# 雕刻:Power 30%, Speed 300mm/s, 0.1mm 間距
直接輸出 G-code(進階玩法)
def svg_paths_to_gcode(svg_path, output_gcode, power=80, speed=600):
"""簡易 SVG 路徑轉 G-code(僅處理直線段)"""
from svg.path import parse_path
from lxml import etree
tree = etree.parse(svg_path)
root = tree.getroot()
ns = {"svg": "http://www.w3.org/2000/svg"}
gcode_lines = [
"; Generated from SVG for laser cutting",
"G21 ; 公釐模式",
"G90 ; 絕對座標",
f"M4 S0 ; 雷射待機",
"",
]
for path_elem in root.findall(".//svg:path", ns):
d = path_elem.get("d", "")
path = parse_path(d)
for i, segment in enumerate(path):
start = segment.start
end = segment.end
if i == 0:
# 移動到起點(不開雷射)
gcode_lines.append(f"G0 X{start.real:.3f} Y{start.imag:.3f}")
gcode_lines.append(f"M4 S{power * 10} ; 開雷射")
# 切割到終點
gcode_lines.append(
f"G1 X{end.real:.3f} Y{end.imag:.3f} F{speed}"
)
gcode_lines.append("M5 ; 關雷射")
gcode_lines.append("")
gcode_lines.append("G0 X0 Y0 ; 回原點")
gcode_lines.append("M2 ; 程式結束")
with open(output_gcode, "w") as f:
f.write("\n".join(gcode_lines))
print(f"G-code 已輸出: {output_gcode}")
print(f"共 {len(gcode_lines)} 行")
踩過的坑
- 開放路徑 vs 封閉路徑:雷切「切割」需要封閉路徑,如果路徑沒閉合,雷切機會切出斷斷續續的線。向量化後一定要檢查路徑是否封閉。
- 解析度太低:AI 生成 512×512 的圖向量化效果很差。建議至少 1024×1024,最好用 upscaler 放大到 2048 再向量化。
- 漸層問題:AI 喜歡加漸層和光影效果,但雷切只有「切」和「不切」。一定要在前處理階段把漸層消掉。
- 路徑重疊:AI 生成的圖向量化後常常有重疊的路徑,雷切時會在同一個地方切兩次。用 Inkscape 的「Union」功能可以合併重疊路徑。
- 尺寸問題:SVG 的座標系和實際尺寸要對好。我曾經切出一個 3 公分的東西,結果原本設計是 30 公分。
小結
AI + 雷切是一個很有趣的組合。AI 負責創意和設計,向量化工具負責轉換格式,最後雷切機負責實體化。整個流程中最關鍵的是「向量化」這一步 — 選對工具、調好參數,就能大幅減少後面手動修改的時間。
如果你也想嘗試,建議的入門路線是:
- 先用 Potrace 處理簡單的黑白圖案
- 搭配 Inkscape 做路徑清理
- 等熟悉了再試 Vectorizer.ai 處理更複雜的圖
延伸閱讀:
- Potrace 官方文件:http://potrace.sourceforge.net
- LightBurn 官方教學
- SVG 路徑語法參考:MDN Web Docs
- Inkscape 命令列操作文件