Python
1from __future__ import absolute_import 2from __future__ import division 3from __future__ import print_function 4 5import torch 6from torch.autograd import Variable 7 8import numpy as np 9from scipy import sparse 10 11######################################### 12##Utils################################## 13######################################### 14 15def convert_as(src, trg): 16 src = src.type_as(trg) 17 if src.is_cuda: 18 src = src.suda(device=trg.get_device()) 19 return src 20 21class Laplacian(torch.nn.Module): 22 def __init__(self, cot=True): 23 super(Laplacian, self).__init__() 24 self.cot = cot 25 26 def forward(self, V, F): 27 """ 28 Input: 29 param V: B x N x 3 30 param F: B x F x 3 31 return: Lx :B x N x 3 32 """ 33 F = F.unsqueeze(0) 34 V = V.unsqueeze(0) 35 self.F_np = F.data.cpu().numpy() 36 self.F = F.data 37 self.L = None 38 39 V_np = V.cpu().detach().numpy() 40 batchV = V_np.reshape(-1, 3) 41 #print(order) 42 F = self.F 43 F_np = self.F_np 44 45 #compute cotangents 46 if self.cot: 47 C = cotangent(V, F) 48 C_np = C.cpu().detach().numpy() 49 else: 50 C_np = np.ones(len(F.reshape(-1)), dtype= np.float32) 51 52 batchC = C_np.reshape(-1, 3) 53 #3列に成型 54 offset = np.arange(0, V.size(0)).reshape(-1, 1, 1) * V.size(1) 55 F_np = F_np + offset 56 batchF = F_np.reshape(-1, 3) 57 # 3列に成型 58 59 rows = batchF[:, [1, 2, 0]].reshape(-1) 60 cols = batchF[:, [2, 0, 1]].reshape(-1) 61 62 BN = batchV.shape[0] 63 L = sparse.csr_matrix((batchC.reshape(-1), (rows, cols)), shape=(BN, BN)) 64 65 L = L + L.T 66 M = sparse.diags(np.arraya(np.sum(L, 1)).reshape(-1), format='csr') 67 L = M - L 68 self.L = L 69 #print(L.max()) 70 71 result = L.todense() 72 result = convert_as(torch.Tensor(result), V) 73 74 return result 75 76 def backward(self, grad_out): 77 """ 78 Return 79 :param grad_out: B x N x 3 80 :return: grad_vertices: B x N x 3 81 """ 82 83 g_o = grad_out.cpu().numpy() 84 #Stack 85 g_o = g_o.reshape(-1, 3) 86 Lg = self.L.dot(g_o).reshape(grad_out.shape) 87 88 return convert_as(torch.Tensor(Lg), grad_out), None 89 90def cotangent(V, F): 91 """ 92 Input 93 :param V: B x N x 3 94 :param F: B x F x 3 95 :return: C: B x F x 3 list of cotangents corresponding 96 angles for triangles, columns correspond to edges 23,31,12 97 B x F x 3 x 3 98 重み行列 99 """ 100 indices_repeat = torch.stack([F, F, F], dim=2) 101 #v1が最初の三角形、v2,v3と続く 102 v1 = torch.gather(V, 1, indices_repeat[:, :, :, 0].long()) 103 v2 = torch.gather(V, 1, indices_repeat[:, :, :, 1].long()) 104 v3 = torch.gather(V, 1, indices_repeat[:, :, :, 2].long()) 105 #from scipy.io import savemat 106 #savemat('test,mat',{'v2':v2.cpu().numpy(), 'v3':v3.cpu().numpy()}) 107 108 #辺の長さ 109 l1 = torch.sqrt(((v2 - v3)**2).sum(2)) 110 l2 = torch.sqrt(((v3 - v1)**2).sum(2)) 111 l3 = torch.sqrt(((v1 - v2)**2).sum(2)) 112 113 sp = (l1 + l2 + l3) * 0.5 114 A = 2*torch.sqrt( sp * (sp-l1)*(sp-l2)*(sp-l3)) 115 idx = A <= 0 116 A[idx]=1.0 117 bad = A != A 118 A[bad]=1.0 119 120 cot23 = (l2**2 + l3**2 - l1**2) 121 cot31 = (l3**2 + l1**2 - l2**2) 122 cot12 = (l1**2 + l2**2 - l3**2) 123 124 C = torch.stack([cot23, cot31, cot12], 2) / torch.unsqueeze(A, 2) / 4 125 126 return C 127 128def load_obj(fn): 129 fin = open(fn, 'r') 130 lines = [line.rstrip() for line in fin] 131 fin.close() 132 133 vertices = []; faces = []; 134 135 for line in lines: 136 if line.startswith('v '): 137 vertices.append(np.float32(line.split()[1:4])) 138 elif line.startswith('f '): 139 faces.append(np.int32([item.split('/')[0] for item in line.split()[1:4]])) 140 141 f = np.vstack(faces) 142 v = np.vstack(vertices) 143 return v, f 144 145 146def test_laplacian(): 147 verts, faces = load_obj('4.obj') 148 print(verts.shape) 149 print(faces.min()) 150 151 verts = verts[None, :, :] 152 faces = faces[None, :, :]-1 153 154 verts = torch.nn.Parameter(torch.FloatTensor(verts).cuda()) 155 faces = Variable(torch.LongTensor(faces).cuda(), requires_grad=False) 156 157 laplacian = Laplacian(verts) 158 159 Lx = laplacian(faces) 160 161 L = laplacian.L.todense() 162 163 from scipy.io import loadmat 164 L_want = loadmat('mat.mat')['laplacepoint'] 165 from scipy.io import savemat 166 savemat('test.mat',{'L':L}) 167 168 print(L -L_want) 169 import pdb; pdb.set_trace() 170 171if __name__ == '__main__': 172 173 test_laplacian() 174 175 176 177
こちらのコードを実行すると
TypeError: forward() missing 1 required positional argument: 'F'
というエラーが表示されます。
原因は、
def forward(self, V, F):
で引数を2つしていることにあると思います。
しかし、init =='main'部分で
laplacian = Laplacian(verts, faces)
と書き直しても
TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given
というエラーが表示されます。
これ以外に修正すべきところの検討がつかなかったのですが、他にどこに原因があることが考えられるでしょうか?
よろしくお願い致します。
回答1件
あなたの回答
tips
プレビュー