🗄️

画像処理を使ってオリジナルの収納モジュールを作ってみた

に公開

3D プリンターを買うと、生活治具的なものを作ってみたり、むやみやたらと引き出しの中身を整理整頓してみたくなったりします。
ここでは、収納したいものの写真から、専用の Gridfinity モジュールを作成する方法を紹介します。

コードはこちら
https://github.com/shirarei24/image-to-step

Gridfinity って?

Gridfinityは、Zack Freedman さんが提案した、モジュール式の収納システムです。
https://www.youtube.com/watch?v=ra_9zU-mnl8

Baseと呼ばれる格子状のプレートと、その上に配置されるBinと呼ばれる容器で構成されています。
このサイズが規格化されており、Bin をカスタマイズすることで、自分の用途に合った収納を簡単に作成することができます。
今回は、このノギスを収納するための Bin を作ってみたいと思います。

Bin の設計

Bin を設計するにあたり、参考にしたのが次の動画です。

https://youtu.be/or2_79CTpPM?t=150&si=VQDEQwv87Dx5ItXB

動画で紹介されていた手法は以下のような流れでした:

  1. 収納したい道具の俯瞰写真を撮影
  2. 手動でシルエットをトレース(簡易的な形状で近似)
  3. そのシルエットを元に 3D モデルを作成

本記事では、画像から Bin 用の 3D モデルを作る作業を自動化します。

処理の流れ

次のような流れで行います。

  1. 写真撮影: スマートフォンで写真撮影
  2. 背景除去:rembg を使って自動的に背景を除去
  3. 輪郭抽出:OpenCV で物体の輪郭を検出
  4. 3D 化:抽出した輪郭を 3D メッシュに変換
  5. Gridfinity Bin の形に調整:モデリングソフトで最終調整

写真撮影

撮影は手持ちの iPhone で行いました。
動画によると、なるべく望遠で、かつ水平に撮ることがコツのようです。

こんな感じ
ノギスの撮影写真

背景除去

背景除去にはrembgを使いました。
元画像(背景あり)

先ほど撮影した画像から対象部分だけを切り抜きます。

from rembg import remove
import cv2

input = cv2.imread("nogisu_image.png")
output = remove(input)
cv2.imwrite("nogisu_image_bg_removed.png", output)

結果はこんな感じです。
背景除去後の画像

綺麗に背景が抜けています。
最近は、iPhone や Mac の標準機能等でも簡単に除去できるので、先に処理してしまってもいいですね。

輪郭抽出

次に、背景を除去した画像から輪郭を抽出します。

import cv2
import numpy as np

image = cv2.imread("nogisu_image_bg_removed.png")

# アルファチャンネルから二値化画像を生成
alpha_channel = image[:, :, 3]
_, binary_image = cv2.threshold(alpha_channel, 127, 255, cv2.THRESH_BINARY)

# ピッタリすぎると収納しづらいため、少しだけ大きくする
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
dilated = cv2.dilate(binary_image, kernel, iterations=1)

# 輪郭検出
contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 最大面積の輪郭を選択
largest_contour = max(contours, key=cv2.contourArea)

contour_filled_image = np.zeros_like(image)
cv2.fillPoly(contour_filled_image, [largest_contour], 255)

cv2.imwrite("nogisu_image_contour.png", output)

輪郭抽出結果

クリアランス(余裕)を取るために、輪郭を少しだけ大きくしています。

3D 化

抽出した 輪郭を STEP 形式の 3D データに変換します。単純に輪郭を押し出して厚みを持たせることにしました。
CadQueryを使うと簡単に処理できます。

import cadquery as cq

height = 100 # 適当な高さを設定

points = contour.squeeze()
cq_points = [(float(point[0]), float(point[1])) for point in points]
result = cq.Workplane("XY").polyline(cq_points).close().extrude(height)

cq.exporters.export(
    result,
    "nogisu_3d.step",
    exportType=cq.exporters.ExportTypes.STEP,
)

3D化結果

これで、写真から Bin の作成に使える 3D データを準備することができました!

Gridfinity Bin の作成

ここからは、作成した 3D モデルを Gridfinity の Bin の規格に合わせて仕上げていきます。

Bin のベース

Bin の形状を一からモデリングしてもいいのですが、Bin の形状を出力してくれる便利なジェネレータがたくさんあります。
今回は、Gridfinity Creatorを使わせていただきました。STEP ファイルで出力ができるので、後述のモデリングソフトで扱いやすいです。

2x4 サイズの solid bin として出力しました。

輪郭 3D モデルとの合成

作成した収納物の 3D モデルと、solid bin のモデルを合成させていきます。
モデリングには、shapr3Dを使いました。iPad で手軽に作業できるのが好きです。

写真から生成した 3D モデルには、サイズの情報がないので、スケールを調整する必要があります。
収納物の実寸をもとに、テストプリントしながら微調整しました。

3Dモデルの設計画面
テストプリントの結果

取り出しやすいように、手を入れる場所に凹みをつけました。
いい感じですね。

サイズが決まったので、solid bin に合成します。
Binの3Dデータ

最終的なプリント結果がこちら。
Binのプリント結果
オリジナルの Bin が完成しました!

まとめ

画像処理を使って、Gridfinity 用 Bin の設計補助ツールを作ってみました。
今後は、Bin の形として出力するところまで自動化したいですね。

Discussion