なんでも立体化スクリプト
https://gyazo.com/f969ed5b84a5428d7213ffff46dc358e
hr.icon
材料:
ストレージの残量 …2GBぐらい
/icons/hrd.icon
🄐
小栗先生の写真 …1枚
プロジェクター …一基
hr.icon
作り方:
⑴とりあえず動かす
まずはgithubのreadmeを見てセッティングをします。
code:setup.sh
cd Depth-Anything-V2
pip install -r requirements.txt
これをやって、
https://gyazo.com/98ce4ab4fd849652aa4f695cbed1c008
↑ここからいい感じのやつをダウンロードして、
code:run.sh
python run.py \
--encoder <vits | vitb | vitl | vitg> \
--img-path <path> --outdir <outdir> \
↑ここからいい感じにオプションを選んだりして
https://gyazo.com/b78797bde8d0f46a6ba70eb640147c87
↑コイツを食わせて動かすとこんな感じになります。
https://gyazo.com/e9c2be63933e4c894362fe71d8ce7998
⑵コピペ
READMEからコイツをコピペ:
code:sample.py
import cv2
import torch
from depth_anything_v2.dpt import DepthAnythingV2
DEVICE = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
model_configs = {
}
encoder = 'vitl' # or 'vits', 'vitb', 'vitg'
model = DepthAnythingV2(**model_configsencoder) model.load_state_dict(torch.load(f'checkpoints/depth_anything_v2_{encoder}.pth', map_location='cpu'))
model = model.to(DEVICE).eval()
raw_img = cv2.imread('your/image/path')
depth = model.infer_image(raw_img) # HxW raw depth map in numpy
encoderをダウンロードしたモデルに変更してcv2.imreadのパスを例の写真に変更
最終行にcv2.imwrite('depth_map.png', (depth / depth.max() * 255).astype('uint8'))を追加して実行すると…
https://gyazo.com/d16a137843efbf1cbf1074b4e31a434e
比較のために元画像
https://scrapbox.io/files/694a45024b3133942f918532.webp
いい感じ
⑴モデルを作る
stlモデルを作ります:
今の状態のイメージは
table:image
1 19 32 14 21 13 12
24 20 50 24 32 21 15
24 30 70 89 24 100 120
2 8 40 ....
みたいな感じで画素ごとに推定された深度が表示されてます。
最大で255最小で0です。
これをレリーフに改造していきます
こんな感じで:
https://gyazo.com/f459f8a6b2cf0e848e6d44931178e372
copilot使ったりなんやかんやしてこんな感じのスクリプトができます
code:show.py
import cv2
import torch
import numpy as np
from stl import mesh
from depth_anything_v2.dpt import DepthAnythingV2
DEVICE = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
model_configs = {
}
encoder = 'vitb' # or 'vits', 'vitb', 'vitg'
model = DepthAnythingV2(**model_configsencoder) model.load_state_dict(torch.load(f'checkpoints/depth_anything_v2_{encoder}.pth', map_location='cpu'))
model = model.to(DEVICE).eval()
raw_img = cv2.imread('../WPj2AAk.webp') # HxWx3 BGR image
depth = model.infer_image(raw_img) # HxW raw depth map in numpy
cv2.imwrite('depth_map.png', (depth / depth.max() * 255).astype('uint8'))
#===== Generate 3D mesh from depth map and save as STL =====# # variables
bottom_clip = 0.5
gradient = 300
depth_normalized = (depth - depth.min()) / (depth.max() - depth.min())
H, W = depth.shape0, depth.shape1 bottomVertexes = np.array([x, 1-y, 0.0 for y in range(H) for x in range(W)]) topVertexes = np.array([[x, 1-y, (depth_normalizedy, x- bottom_clip) * gradient ] for y in range(H) for x in range(W)]) for y in range(H):
for x in range(W):
allVertexes = np.vstack((topVertexes, bottomVertexes))
# Top surface faces (consistent CCW when viewed from +Z)
faces = []
for y in range(H - 1):
for x in range(W - 1):
tl = y * W + x
tr = tl + 1
bl = (y + 1) * W + x
br = bl + 1
# Bottom surface faces (reverse winding so normals face -Z)
offset = H * W
for y in range(H - 1):
for x in range(W - 1):
tl = offset + (y * W + x)
tr = tl + 1
bl = offset + ((y + 1) * W + x)
br = bl + 1
# Side walls: build perimeter once and create quads between consecutive perimeter vertices
perim = []
# top row left->right
for x in range(0, W):
perim.append(0 * W + x)
# right column top->bottom (skip top)
for y in range(1, H):
perim.append(y * W + (W - 1))
# bottom row right->left (skip corner already added)
if H > 1:
for x in range(W - 2, -1, -1):
perim.append((H - 1) * W + x)
# left column bottom->top (skip corners)
if W > 1:
for y in range(H - 2, 0, -1):
perim.append(y * W + 0)
perim = np.array(perim, dtype=int)
for i in range(perim_len):
bot_a = offset + a
bot_b = offset + b
# reverse winding so normals point outward from the solid
faces = np.array(faces)
# Flip winding for all faces (reverse vertex order) so every polygon is inverted
depth_mesh = mesh.Mesh(np.zeros(faces.shape0, dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces):
depth_mesh.vectorsi = allVertexesf, : depth_mesh.save('depth_mesh.stl')
可読性?何それ
そしてできたのがこれ
https://gyazo.com/1cbe15185e96c83f4c57c92938be469f
⑶プリント
そして印刷したのがこれ
https://gyazo.com/b705d131dfa6ca681dabd7e877a897ee
右は失敗作
あとはこれにプロジェクターで写真を写すだけ
https://scrapbox.io/files/694a4ffaad44a53a6ee1085e.mov
完成!