Slide 1

Slide 1 text

スケッチから3Dモデルを 検索してみた いなば @ キャディ株式会社 1

Slide 2

Slide 2 text

自己紹介 ● Masaki Inaba | @mi_spindel ○ お気軽にメッセージください ● 某光学機器メーカでマシン/ロボットビジョン 某自動車部品メーカで自動運転/運転支援向けの車載画像認識 某AIスタートアップで様々な受託AI開発 ● 2022/7/1にキャディ株式会社に入社しました AI Labで2D/3D図面の認識・検索技術の開発に関わっています 2

Slide 3

Slide 3 text

やりたいこと※この画像はイメージです クエリ 検索結果 3

Slide 4

Slide 4 text

スケッチからhogehogeという話は結構ある1 ● Sketch2Pose: Estimating a 3D Character Pose from a Bitmap Sketch, SIGGRAPH2022 4

Slide 5

Slide 5 text

スケッチからhogehogeという話は結構ある2 ● Free2CAD: Parsing Freehand Drawings into CAD Command, SIGGRAPH2022 5

Slide 6

Slide 6 text

スケッチから既存のCADモデルを 検索できたら嬉しいかもしれない ※工業部品希望 6

Slide 7

Slide 7 text

お、論文とデータセットがある! ● ‘CADSketchNet’ - An Annotated Sketch dataset for 3D CAD Model Retrieval with Deep Neural Networks, 3DOR2021 7

Slide 8

Slide 8 text

CADSketchNet, DatasetA ● Mechanical Components Benchmark: MCB, ECCV2020がベース ○ 58,696スケッチ(.png), 58,696モデル(.obj), 68クラス ● コンピュータにより生成されたスケッチ(computer-generated sketch: cgs) ○ 視線は20方向から機械工学で設計を学んだ学生に投票で一つに決めてもらったとのこと ○ (なぜ1視点しか作らなかったのだろう…) 8

Slide 9

Slide 9 text

● Engineering Shape Benchmark: ESB, Computer-Aided Design2006がベース ○ 800スケッチ(.png), 866モデル(.obj), 42クラス ● 手書きスケッチ(hand) ○ 視線はDatasetAと同様に決めて、学生に手書きスケッチを描いてもらった ○ (800か…少ないな…) CADSketchNet, DatasetB 9

Slide 10

Slide 10 text

CADSketchNet, Experiment ● 何か色々書いてあるけど、(Multi-view) CNN, Siamese-Networkの構成で DatasetA, BともにTop k-Accurasyは90%を超えるとのこと ● ただ、DatasetA内で学習・評価、DatasetB内で学習・評価した実験結果しかなく、 コンピュータ生成スケッチで学習し手書きスケッチを評価したものが気になる 10

Slide 11

Slide 11 text

実際にやってみた ● やったこと ○ CNN(スケッチ) - Multi-view CNN(3Dモデル)によるSiamese-Network ■ PyTorch3DによるMulti-view Rendering ○ DatasetA(コンピュータ生成スケッチ)による学習⇒DatasetB(手書きスケッチ)の評価 ○ DatasetB(コンピュータ生成スケッチ)による学習⇒DatasetB(手書きスケッチ)の評価 ● やらないこと ○ CADSketchNetの再現実験 ■ 公開コードも無く、実験条件の詳細も不明確なので無理。。。 ■ https://github.com/bharadwaj-manda/CADSketchNet ○ 検索精度の追及 README only 11

Slide 12

Slide 12 text

まずは、データセットをダウンロード! ● あれ…スケッチの画像データしかないな…(嫌な予感) ● MCB, ESBデータセットは別途ダウンロードか ● うん、モデルファイル(.obj)しかないよね 各視点のレンダリング画像は無いし、 レンダリング時の視線などのパラメタも無い 各引用論文と同じパラメタ使ってる云々と書いてあるな… DatasetBのファイル名が適当でスケッチとモデルの対応とれないし…悲しい… 12

Slide 13

Slide 13 text

マルチビューレンダリングをする ● Multi-view Convolutional Neural Networks for 3D Shape Recognition, ICCV2015では”Blender”を使ってるけど、せっかくなので”PyTorch3D”を試用 ○ 今回はパラメタ固定なので意味ないですが、微分可能(のはず) ○ 参考: PyTorch3Dチュートリアル, MVTN: Multi-View Transformation Network for 3D Shape Recognition, ICCV2021のコード ● レンダリング時のパラメタはMVCNNの条件を参考にする 13

Slide 14

Slide 14 text

PyTorch3Dによるマルチビューレンダリングコード例1 class MultiViewRenderer(nn.Module): def forward(self, meshes, azim, elev, dist): background_color = torch.tensor((1.0, 1.0, 1.0)) color = torch.tensor((1.0, 1.0, 1.0)) lights = DirectionalLights(direction = (0, 1.0, 0)) rendered_images, cameras = self.render_meshes( meshes=meshes, color=color, azim=azim, elev=elev, dist=dist, lights=lights, background_color=background_color) return rendered_images, cameras meshes: batch_size * [Pytorch3D.Mesh] azim: (batch_size, nb_views) elev: (batch_size, nb_views) dist: (batch_size, nb_views) rendered_images: (batch_size*nb_views, 3, width, height) 背景色 物体色 y方向無限遠にある点光源 Mathworks 方位角と仰角の視点の設定より 14

Slide 15

Slide 15 text

def render_meshes(self, meshes, color, azim, elev, dist, lights, background_color=(1.0, 1.0, 1.0)): c_batch_size = len(meshes) verts = [msh.verts_list()[0].cuda() for msh in meshes] faces = [msh.faces_list()[0].cuda() for msh in meshes] for i in range(len(verts)): verts[i] = verts[i] - torch.mean(verts[i], 0) # weighted mean based on face area is better mgn = 1.0 / torch.max(torch.max(verts[i], 0).values - torch.min(verts[i], 0).values) verts[i] = verts[i] * mgn new_meshes = Meshes( verts=verts, faces=faces, textures=None) max_vert = new_meshes.verts_padded().shape[1] new_meshes.textures = Textures( verts_rgb=color.cuda()*torch.ones((c_batch_size, max_vert, 3)).cuda()) R, T = look_at_view_transform(dist=batch_tensor(dist.T, dim=1, squeeze=True), elev=batch_tensor(elev.T, dim=1, squeeze=True), azim=batch_tensor(azim.T, dim=1, squeeze=True)) cameras = FoVPerspectiveCameras(device=meshes.device, R=R, T=T) PyTorch3Dによるマルチビューレンダリングコード例2 中心位置正規化 サイズ正規化 (タスクに依存) テクスチャを設定 元objにはテクスチャがない カメラ位置姿勢を設定 batch_size*nb_views 15

Slide 16

Slide 16 text

raster_settings = RasterizationSettings( image_size=self.image_size, # 224 blur_radius=0.0, bin_size = 0, faces_per_pixel=self.faces_per_pixel, # 1 cull_backfaces=self.cull_backfaces # False ) renderer = MeshRenderer( rasterizer=MeshRasterizer( cameras=cameras, raster_settings=raster_settings ), shader=SoftPhongShader( blend_params=BlendParams(background_color=background_color), device=meshes.device, cameras=cameras, lights=lights ) ) new_meshes = new_meshes.extend(self.nb_views) rendered_images = renderer(new_meshes, cameras=cameras, lights=lights) rendered_images = rendered_images[..., 0:3].transpose(1, 3).transpose(2, 3) return rendered_images, cameras PyTorch3Dによるマルチビューレンダリングコード例3 ラスタライズ設定 ポリゴンから画素生成 Phongの反射モデル メッシュをnb_viewsの数 コピーしてレンダリング alphaチャンネル削除 16

Slide 17

Slide 17 text

レンダリング実行 from pytorch3d.io import load_objs_as_meshes nb_views = 12 obj_path="test.obj" mvr = MultiViewRenderer(nb_views=nb_views) elev = torch.stack([torch.linspace(30, 30, nb_views)]) azim = torch.stack([torch.linspace(-180, 180-360/nb_views, nb_views)]) dist = torch.stack([torch.Tensor([2.0]*nb_views)]) meshes = load_objs_as_meshes(obj_path).cuda() images, cameras = mvr.forward(meshes, azim, elev, dist) MVCNNと同様の12視点 17

Slide 18

Slide 18 text

モデル ● CNN-MVCNNのSiamese Network風 ResNet18 ResNet18 ResNet18 ResNet18 ResNet18 … View max pooling Linear LeakyReLU Linear LeakyReLU 128次元 128次元 18

Slide 19

Slide 19 text

その他、学習条件など ● Dataset: DatasetA_cgs, DatasetB_cgs, DatasetB_hand ○ クラスインバランス対策にWeightedRandomSampler ● Optimizer: Adam, Learning Rate = 1.0e-4 ● Batch Size: 8 ● LeakyReLU negative slope = 0.01 ● Data Augmentation ○ スケッチのみHorizontal / Vertical Flip ● 評価 ○ Top-k Accuracy 各クラスのデータ数 左: DatasetA, 右: DatasetB 19

Slide 20

Slide 20 text

学習: DatasetA_cgs_train, 評価: DatasetA_cgs_test ● お、まぁまぁできてる ● デモ ○ 定性的にも悪くない k Top-k Accuracy@DatasetA_cgs_test 1 0.80 3 0.89 5 0.92 20

Slide 21

Slide 21 text

学習: DatasetA_cgs_train, 評価: DatasetB ● やっぱ、ダメだな… ● DatasetAとDatasetBでクラス分類の仕方が違うからだろうか k Top-k Accuracy@DatasetB_cgs Top-k Accuracy@DatasetB_hand 1 0.11 0.06 3 0.21 0.14 5 0.27 0.19 21

Slide 22

Slide 22 text

学習: DatasetB_cgs, 評価: DatasetB_hand ● うーむ、ダメですね… ● 単純にスケッチの違いを吸収できていないご様子 k Top-k Accuracy@DatasetB_hand 1 0.21 3 0.22 5 0.24 22

Slide 23

Slide 23 text

学習: DatasetB_hand_train, 評価: DatasetB_hand_test ● 手書きスケッチを直接学習すればそこそこできる ● デモ ○ 最初にお見せしたやりたいことイメージはこの結果でした ● 手書きスケッチを実際に集めるのは結構辛い… k Top-k Accuracy@DatasetB_hand_test 1 0.80 3 0.85 5 0.89 23

Slide 24

Slide 24 text

まとめ ● スケッチからの3Dモデル検索をやってみた過程を紹介しました ○ CADSketchNetのデータセットを利用し、 CNN-MVCNNのSiamese Network構成で実際にやってみた ■ PyTorch3Dによるマルチビューレンダリングの方法も紹介 ○ 結果、コンピュータ生成のスケッチではそれなりに上手くいった ○ ただ、ナイーブにコンピュータ生成のスケッチを学習したモデルで リアルな手書きのスケッチをクエリとして扱うのは難しいことが分かった ● データ拡張、手書き風変換、Domain Adaptationあたりを 頑張ると変わるかもしれない ● 手書きスケッチを描く側に制約を入れるのも大事だと思う ○ 視点位置姿勢の固定、Draw Strokeの補正など 24

Slide 25

Slide 25 text

ありがとうございました! ● CADDiでは2D図面だけでなく、3D図面認識・解析・検索・生成など 様々なことにチャレンジできる環境だと感じています ● CADDiのことや今回の話で気になることなどありましたら下記まで ● Masaki Inaba | @mi_spindel ○ お気軽にメッセージください 25