1房のぶどうの3Dモデルを読み込んで、一粒ずつ球面近似をするプログラムを作りたいと思っています。
4か所クリックした部分を球近似してその球の中心を求める仕様にするつもりです。
1個の3Dモデルを球近似するプログラムは既出ですが、近似する物体が複数個画面上にあるような3Dモデルの時はどうするのだろうかと思い質問させていただきました。
以下のソースコードではvalueエラーが出てしまい機能しないので解決策を教えてほしいです。よろしくお願いします。
###ソースコード
python
1import pyvista as pv 2import numpy as np 3from stl import mesh 4 5spher_mode = False # 球近似計算モード 6count = 0 # 【ベクトル計算モード】クリックした回数をカウント 7vector = [] # 【ベクトル計算モード】入力したベクトル情報 8plotter = pv.Plotter() 9filename = "grape.stl" # 読み込むSTLファイル 10 11def approx(plot): 12 """ 13 入力 14 point_cloud: 点群のxyz座標のリスト numpyのarray形式で3x3xN行列 15 出力 16 radius : 近似球の半径 スカラー 17 sphere_center : 球の中心座標 xyz numpyのarray 18 """ 19 20 A_1 = np.zeros((3,3)) 21 #Aのカッコの中の1項目用に変数A_1をおく 22 v_1 = np.array([0.0,0.0,0.0]) 23 v_2 = 0.0 24 v_3 = np.array([0.0,0.0,0.0]) 25 #ベクトルの1乗、2乗、3乗平均の変数をv_1, v_2, v_3とする 26 #1乗、3乗はベクトル、2乗はスカラーとなる 27 28 N = len(point_cloud) 29 #Nは点群の数 30 31 """シグマの計算""" 32 for v in point_cloud: 33 v_1 += v 34 v_2 += np.dot(v, v) 35 v_3 += np.dot(v, v) * v 36 37 A_1 += np.dot(np.array([v]).T, np.array([v])) 38 39 v_1 /= N 40 v_2 /= N 41 v_3 /= N 42 A = 2 * (A_1 / N - np.dot(np.array([v_1]).T, np.array([v_1]))) 43 # 式② 44 b = v_3 - v_2 * v_1 45 # 式③ 46 sphere_center = np.dot(np.linalg.inv(A), b) 47 # 式① 48 return(sphere_center) 49 50 51"""半径と中心を定めて 点群ファイルに保存する""" 52def draw_sphere(radius,sphere_center): 53 54 """ 55 入力 56 sphere_center : 中心座標のxyz numpyのarray 57 """ 58 59 point_list = [] 60 61 """球面の点群を作成していく""" 62 for i in range(360): 63 i = i * np.pi / 180 #ラジアン表記にする 64 for j in range(360): 65 j = j * np.pi / 180 #ラジアン表記にする 66 point = radius * np.array([np.sin(i) * np.cos(j),np.sin(i) * np.sin(j), np.cos(i)]) + sphere_center 67 #座標点を追加していく 68 point_list.append(point) 69 70 print(np.array(point_list)) 71 72 return 73 74def right_click(data): 75 global spher_mode, count, vector 76 77 if(spher_mode is True): 78 count += 1 79 data = np.array(data) 80 plotter.add_points(data, render_points_as_spheres=True, point_size=10.0, color='yellow') # 指定した座標を黄色で表示 81 print('data:{} click:{}/4'.format(data, count)) 82 vector.append(data) # 指定した座標データを一時保存 83 84 if count == 4: # 4回目のクリック時に判定 85 while True: 86 try: 87 dic = {'y':True, 'yes':True, 'n':False, 'no':False} 88 res = input('確定しますか? (Yes/No) >> ') 89 res = dic[res] 90 break 91 except KeyError: 92 pass 93 94 if res == True: 95 print('OK!') 96 print(approx(vector)) 97 spher_mode = False 98 else: 99 print('リトライ') 100 vector = [] 101 102 count = 0 103 paint_meshdata() 104 105 sphere_stl = mesh.Mesh.from_file('grape.stl') 106 sphere_points = sphere_stl.points.reshape([0,1,2,3])#stlから点群を抽出 107 108 print(sphere_points) # 表面データの点群が代入される 109 radius, center = approx.sphere_fit(sphere_points) 110 111 print('中心の座標:',(center))#中心の座標 112 113 114 plotter.track_click_position(callback=right_click,side='right') # 右クリックを押したときの処理 115 116 plotter.add_key_event('a', press_akey) 117 118 plotter.show() 119
###エラー
WARNING:root:Encountered issue in callback (most recent call last): File "C:\Users\anaconda3\lib\site-packages\pyvista\plotting\render_window_interactor.py", line 133, in _click_callback callback(self._plotter.pick_click_position()) File "sample.py", line 115, in right_click print(approx(vector)) File "sample.py", line 78, in approx sphere_points = sphere_stl.points.reshape([0,1,2,3])#stl から点群を抽出 ValueError: cannot reshape array of size 2069388 into shape (0,1,2,3)
あなたの回答
tips
プレビュー