「キャラのアイコンとQRコードを両面に入れた、ポーカーチップ風のMaker Chipを刷りたい」。
そう思ってBambu Studioで作りはじめたのですが、思ったほど素直には進みませんでした。
画像をそのまま取り込むと立方体になり、ベクター化したQRはスライスすると読み取れず、線画アイコンは輪郭だけで中身が塗り潰されない。最後は1層目で必ず失敗する、という壁にもぶつかりました。
この記事では、画像(ラスタ)を3Dプリント用のSVGに変換する途中でつまずいた点を中心に、原因と対処を残しておきます。同じように絵を立体にしたい方の遠回りが、少しでも減れば幸いです。
最終的に刷り上がったのが、こちらの両面コインです。表にキャラのアイコン、裏にQRコードを2色で入れています。
コイン本体は、MakerWorldで公開されている MakerChip (Maker Chip) - the new MakerCoin をベースにしています。すばらしい元データに感謝しつつ、表裏の図柄を自分のアイコンとQRに差し替えました(ライセンスや作者は元モデルページをご確認ください)。
環境: Bambu Studio / プリンター Bambu Lab P1S・X1 Carbon / ノズル0.4mm / PLA
使ったツール: ImageMagick (magick)、potrace、zbar (zbarimg)、Python (trimesh)
今回使ったプリンター:Bambu Lab P1S
本題の前に、今回メインで使ったBambu Lab P1Sを紹介しておきます。
密閉型でスピードの速いCoreXY機を、手の届く価格で出してきた一台です。
| 項目 | スペック |
|---|---|
| 構造 | CoreXY(密閉エンクロージャー付き) |
| 造形サイズ | 256 × 256 × 256 mm |
| 最高速度 | 500 mm/s |
| 最大加速度 | 20,000 mm/s² |
| ノズル最高温度 | 300 ℃ |
| マルチカラー | AMS / AMS 2 Pro 対応(最大4台で16色) |
今回の用途で効いてきたのは、主に密閉構造とAMSでした。
庫内の温度が安定するので、今回はPLAですが反りの心配が少なく刷れます。ABSやASA、PA、PCといった反りやすい素材にも手を出しやすいのも密閉型の利点です。
そしてAMSがあると、土台と模様を別の色で刷り分けるときに色替えを自動でやってくれるので、複数枚を並べても途中で手が止まりません。CoreXYでヘッドが軽く速いのも、Maker Chipのような小物を量産するときには地味に効きます。
上位機のX1 Carbonとの主な違いは、LiDARによる自動キャリブレーションや高精細カメラの有無あたりです。今回のような2色のMaker Chipなら、P1S + AMSで十分でした。
なお、P1SとX1 Carbonは機種タイプが違うため、スライスした機種と送信先の機種が食い違うと警告が出ます。実機に合わせてプリンターを選び直し、再スライスしてから送るのが安全です。
全体の流れ
最終的に必要だった作業は、ざっくり次の4つでした。
- キャラ画像をモノトーンのSVGに変換する
- QRコードを0.4mmノズルで刷れるモジュールサイズのSVGにする
- 線画アイコンを塗り潰せる線幅に太らせる
- スライス時の1層目失敗(モデルの浮き)を直す
順番に振り返ります。
1. 画像をモノトーンSVGに変換する
最初の入口は、カラー画像を白黒2値のSVGにすることでした。
やり方はシンプルで、ImageMagickで2値化してから、potraceでベクター化します。
# グレースケール化 → しきい値で2値化 → potraceでSVG
magick input.jpg -colorspace Gray -threshold 45% mono.pbm
potrace mono.pbm -s -o icon_mono.svg
しきい値(-threshold)を 45 / 50 / 55 / 60% と振って、結果を見比べて選びました。
線画なら45%前後で輪郭がきれいに出ますし、シルエットを強く出したいなら高めにすると黒ベタが増えます。
元のカラー画像(左)を2値化・ベクター化すると、次のようなモノトーンSVGになります(右)。
ここまでは順調でした。問題はこの先です。
2. つまずき①:SVGを取り込んだら立方体になる
SVGをBambu Studioに取り込むと、平面の図形に自動で厚みがついて立体化(extrude)されます。
このとき、QRの背景の白い四角や、押し出しの厚み設定によっては、ただの塊に見えてしまいます。
対処はシンプルでした。
- 真上から見て模様が出ているか確認する(横から見ると塊に見えるだけのことが多い)
- 取り込み時のダイアログで押し出しの厚みを調整する
これは仕様なので、慌てなくて大丈夫でした。模様自体は出ていたので次へ進みます。
3. つまずき②:QRがスライスすると読み取れない
ここが一番の難所でした。
QRコード自体は QRコード作成(クル) で生成し、そのPNG画像をベクター化して使っています。
このQRをコインに乗せてスライスすると、黒モジュールがくねくねした1本線になり、形が崩れて読み取れません。
原因:1モジュールが小さすぎた
きれいな正方形に造形するには、1モジュール(最小の四角)がノズル幅の3本分以上、つまり 0.4×3=1.2mm 以上は欲しいところでした。
これより小さいと、スライサーが正方形を作れず、1本の線がさまよってしまいます。
| 1モジュールのサイズ | 結果 |
|---|---|
| 0.4mm(1本) | ❌ くねくね線になる |
| 0.8mm(2本) | △ 不安定 |
| 1.2mm(3本) | ✅ 最低ライン |
| 1.5mm(4本) | ✅◎ 安全 |
対処:モジュールサイズを固定したSVGを生成する
potraceに任せると角が丸まってQRが崩れます。そこで、元画像のモジュールグリッドを正確に読み取り、1モジュール=固定mmの正方形でSVGを組み立てる方針にしました。
まず、画像が何ピクセルで1モジュールかを調べます。
magick QR.png -trim info:
# 例: データ部 150x150px。150/25=6 → 6px=1モジュール、25x25モジュール(QRバージョン2)
次に、正確なモジュールグリッドへ点サンプリングで縮小します。補間なし(-filter point)が要点です。
# 余白込み31x31モジュールを 1px/モジュール へ
magick QR.png -filter point -resize 31x31 -threshold 50% grid.png
このグリッドから、1モジュール=1.5mmの正方形を並べたSVGをPythonで生成します。
# 黒モジュールを横方向にまとめて矩形化し、1.5mm/モジュールで出力
N = 31; module_mm = 1.5; bleed = 0.04
# ... (grid.png の各画素を読み、黒なら <rect> を出力) ...
# 物理サイズを width/height に mm で埋め込む
見落としがちな罠:レンダリングの隙間
ここで一度ハマりました。生成したSVGをラスタライズして読み取り検証すると、デコードに失敗したのです。
原因は、縦に隣り合うモジュールの境界に、レンダラーが髪の毛ほどの隙間を作っていたことでした。
そこで各黒モジュールを、ごくわずか(0.04mm)だけ重ねて描くようにしたら、隙間が消えて解決しました。3Dにしたときも、この重なりのおかげで継ぎ目なく1つの面に融合します。
# 各矩形を四辺に bleed(0.04mm) だけ拡張して隣と重ねる
x = rx - bleed; w = rw + 2*bleed # 同様に y, h も
必ず読み取り検証する
見た目が合っていることと、読み取れることは別物です。
SVGをPNGにして、zbarimg でデコードできるか毎回確認しました。
magick -density 1200 -background white qr_clean.svg -resize 600x600 check.png
zbarimg -q --raw check.png
# → https://x.com/... ← 正しくデコードできればOK
最終的に、1モジュール=1.5mmで作り直したQRがこちらです。モジュールがくっきりした正方形になり、読み取りも安定しました。
おまけ:余白(静寂帯)はSVGから外す
QRには周囲の余白(クワイエットゾーン)が要りますが、これをSVGに含めず、コインの明るい地色に任せる手もあります。
余白3モジュール分を外すと 31×31 から 25×25 になり、同じ面積でも1モジュールを大きく取れました。
QRまわりの教訓
- 1モジュールは1.2mm以上、できれば1.5mm
- Bambu Studioで縮小しない(小さくすると同じ失敗が再発する)
- 余白はコインの地色に任せる
- 黒モジュールは0.04mmだけ重ねる
zbarimgで必ず読み取り検証する
4. つまずき③:線画アイコンが塗り潰されない
QRと同じ問題が、線画アイコンでも形を変えて出てきました。
スライスすると、輪郭は出るのに線の中が塗り潰されず、白い点々(隙間)だらけになります。
原因:線が細くて2本目の壁が入らない
線幅が0.6mm(ノズル1.5本分)しかないと、スライサーは線の中に2本目の壁(perimeter)を入れられず、1本の線がさまよって隙間が空きます。
塗り潰すには、線幅を0.8mm(ノズル2本分)以上にする必要がありました。
対処:線を太らせてから再ベクター化する
ImageMagickのモルフォロジー処理で、途切れを補修(Close)してから線を太らせ(Dilate)、potraceで再ベクター化します。
# 1200px(=40mm想定)でレンダリング → 線を太らせる → 再トレース
magick icon_mono.svg -resize 1200x1200 -threshold 50% raw.png
magick raw.png -negate \
-morphology Close Disk:3 \
-morphology Dilate Disk:9 \
-negate thick.png
magick thick.png thick.pbm
potrace thick.pbm -s -t 12 -a 1 -W 40mm -H 40mm -o icon_bold.svg
Dilate Disk:9 の値を 7 / 9 / 11 と振り、最小線幅が0.8mm以上になり、かつ目の白などの細部が潰れない値を、目で見て選びました。
太らせすぎると目や口の白い隙間が潰れるので、ここはさじ加減です。
アイコンを大きく配置するのも手で、同じ細さでもサイズを上げれば線幅は相対的に太くなります。
線を太らせた結果がこちらです。線幅が確保され、スライスしても中まで塗り潰せるようになりました。
線画まわりの教訓
- 塗り潰すには線幅0.8mm(ノズル2本分)以上
- 太らせるか、大きく配置するかの二択
- Bambu Studio側の「薄い壁を検出」をONにすると取りこぼしが減る
5. つまずき④:1層目で必ず失敗する
SVGの問題が片付いた後、青い外周(リム)の1層目で必ず失敗する、という壁が最後に残りました。
これはSVGではなく、STLモデルの形状が原因でした。
原因:外周リムが0.45mm浮いていた
STLの座標を解析すると、底面の高さが部分ごとに違っていました。
| 部分 | 底面のZ | 状態 |
|---|---|---|
| 本体(中央) | 0.0mm | ✅ 接地 |
| 外周リム | 0.45mm | ❌ 浮いている |
外周リムの真下が空洞で、1層目でリムが空中からスタートし、樹脂が垂れて毎回失敗していました。
ブリムやラフトでは直りません。接地不足ではなく、そもそも宙に浮いていたからです。
STLの解析にはPythonのtrimeshを使いました。
import trimesh, numpy as np
m = trimesh.load("MakerChip.stl")
v = m.vertices
cx, cy = (v[:,0].min()+v[:,0].max())/2, (v[:,1].min()+v[:,1].max())/2
r = np.hypot(v[:,0]-cx, v[:,1]-cy)
# 外周(r>R-3)の最小Zを見ると 0.45mm浮いているのが分かる
print(v[r > r.max()-3, 2].min()) # → 0.452
対処:空洞を円柱で埋めて底面を平らにする
リムの真下の空洞を、外周と同じ半径の円柱で埋めました。
元STLがwatertight(閉じた立体)ではなくboolean unionが失敗したので、円柱を別立体として同梱(concatenate)し、スライサー側の自動結合に任せています。
cyl = trimesh.creation.cylinder(radius=R, height=gap+0.1, sections=256)
cyl.apply_translation([cx, cy, (gap+0.1)/2]) # 底を z=0 に
combo = trimesh.util.concatenate([m, cyl]) # boolではなく同梱
combo.export("MakerChip_FIXED.stl")
これで底面全体がz=0で接地し、1層目が欠けのない円盤になりました。
モデルまわりの教訓
- 1層目失敗は、接地不良だけでなく浮きも疑う
- STLは座標を直接解析すると原因が一発で分かる
- 根本的にはCAD側で底面をz=0に揃えるのが理想
仕上げ:AMSでパーツごとに色を割り当てる
ここまでで形は整いました。最後に、Maker Chipを複数色に塗り分けます。
今回はAMSにフィラメントをセットし、パーツ単位で色を割り当てる方法を使いました。
前提:AMSに色をセットする
AMSの各スロットにフィラメントを入れ、Bambu Studioの「プロジェクトフィラメント」に色が並んでいる状態にします。
今回のコインで使った色の対応は、次のとおりです。
| スロット | 色 |
|---|---|
| 1 | 青 |
| 3 | 白 |
| 4 | 濃いグレー |
パーツごとに色を割り当てる手順
- 左のオブジェクトリストで、コインのアセンブリを
▶で展開します - 色を変えたいパーツを選び、右クリックからフィラメント変更(Change filament)
- 割り当てたいスロット番号を選びます
- すべてのパーツに色を指定したら、プレビューのフィラメント別表示で塗り分けを確認します
今回は、パーツを次のように分けて割り当てました。リムの青白ストライプは、青パーツと白パーツに分けて作っています。
| パーツ | スロット | 役割 |
|---|---|---|
K2_MakerChip_v1 |
1(青) | 本体・リムの青 |
K2_MakerChip_Back |
3(白) | 地・リムの白 |
QR_Tsukasansan |
4(グレー) | QR・模様 |
パーツが分かれていないと、この方法は使えません。
▶を展開して、パーツが個別に並んでいるか確認してください。
1つに融合している場合は、塗り分けツール(N)や、高さでのフィラメント切替で対応します。
パージ(廃材)が想像以上に多い
スライスしてみて驚いたのが、色替えで捨てられる材料の多さでした。
スライス結果のフィラメント別内訳がこちらです。
数字にすると、はっきりします。
| 区分 | 使用量 |
|---|---|
| モデル本体 | 3.80 g |
| フラッシュ(色替えのパージ) | 19.23 g |
| ワイプタワー | 2.78 g |
| 合計 | 25.80 g |
合計の約8割(22g)が、色替えのために捨てられている計算です。フィラメントの交換回数は40回にのぼりました。
印刷を見ていて、なぜかグレーが大量にパージされていると感じたのですが、内訳を見て腑に落ちました。
いちばんフラッシュが多いのは、実は白の10.41gです。濃いグレーから白へ替えるとき、白側でたっぷり押し出してグレーの色を抜く必要があるためでした。
濃い色は、次の薄い色に切り替えるときの洗い流しコストが高い。暗から明への切り替えほど、パージが増えていきます。
スライス・印刷時の工夫(AMS)
- 色数を絞るほど、交換回数とパージが減ります
- 濃い色と薄い色の往復を減らすようにレイヤー構成や色配置を考えると、洗浄のパージを抑えられます
- 設定でフラッシュ量(purge volumes)を見直したり、捨てる材料をインフィルやワイプタワーに使い回す設定も効きます
- 1層目の色は底面に出る色です。今回は底を平らにしたので、底面の色は最初に使うフィラメントになる点に注意します
まとめ
絵を立体にするだけのつもりが、ラスタからベクター、スライスへと進む各段階で、それぞれ別の壁がありました。
振り返ると、効いたのは一つの考え方だけでした。ノズル幅(0.4mm)を基準に、最小ディテールのサイズを決める、ということです。
- QRのモジュールは1.2mm以上
- 線画の線幅は0.8mm以上
- そして、スライサーで縮小しない
これを最初から意識しておけば、何度も刷り直さずに済んだはずです。
冒頭の完成写真は、ここまでの試行錯誤を一つずつ潰していった先にありました。色の塗り分けは前章のとおり、AMSとパーツ単位の割り当てで仕上げています。
使ったツールまとめ
| ツール | 用途 |
|---|---|
ImageMagick (magick) |
2値化・縮小・モルフォロジー(線の太らせ) |
| potrace | ラスタからSVGへのベクター化 |
zbar (zbarimg) |
QRの読み取り検証 |
| Python + trimesh | STLの座標解析・形状修正 |








