Download recipe/forma3d/geometry.py from Lucasgitguy-co/forma3d-tiny-4: direct link, hf CLI and curl.
- Browser
- Download file 2.66 kB
-
https://huggingface.co/Lucasgitguy-co/forma3d-tiny-4/resolve/main/recipe/forma3d/geometry.py
- Command line
-
hf download hf://Lucasgitguy-co/forma3d-tiny-4/recipe/forma3d/geometry.py
-
curl -L -o geometry.py https://huggingface.co/Lucasgitguy-co/forma3d-tiny-4/resolve/main/recipe/forma3d/geometry.py
2.66 kB
| """Orthographic geometry metrics; silhouettes do not depend on object colour.""" | |
| import numpy as np | |
| from PIL import Image, ImageDraw | |
| from scipy.spatial import cKDTree | |
| from scipy.spatial.transform import Rotation | |
| VIEWS = ((45,15),(135,15),(225,15),(315,15)) | |
| def rotation(yaw, pitch=0): | |
| y,x=np.deg2rad([yaw,pitch]) | |
| ry=np.array([[np.cos(y),0,np.sin(y)],[0,1,0],[-np.sin(y),0,np.cos(y)]]) | |
| rx=np.array([[1,0,0],[0,np.cos(x),-np.sin(x)],[0,np.sin(x),np.cos(x)]]) | |
| return (rx@ry).astype(np.float32) | |
| def rotate_splats(splats, matrix, scale=1.): | |
| from image3d_student.splats import Splats | |
| q=splats.quat[:,[1,2,3,0]] | |
| out=(Rotation.from_matrix(matrix)*Rotation.from_quat(q)).as_quat()[:,[3,0,1,2]] | |
| return Splats(splats.xyz@matrix.T*scale,splats.rgb,splats.scale*scale,out,splats.opacity) | |
| def chamfer(pred, reference): | |
| if not len(pred): | |
| return 2.0 # fixed maximum-error sentinel, also report empty=True | |
| # Symmetric mean Euclidean nearest-neighbour distance, in normalized object units. | |
| return float((cKDTree(reference).query(pred)[0].mean()+cKDTree(pred).query(reference)[0].mean())/2) | |
| def mesh_mask(vertices, faces, view, size=96): | |
| points=vertices@view.T | |
| points=points[:,:2]*np.array([1,-1])*(size/1.25)+size/2 | |
| image=Image.new("L",(size,size)) | |
| draw=ImageDraw.Draw(image) | |
| for triangle in points[faces]: | |
| draw.polygon([tuple(v) for v in triangle],fill=255) | |
| return np.asarray(image)>0 | |
| def splat_mask(splats, view, size=96): | |
| from image3d_student.splats import rotation_matrices | |
| if splats is None: | |
| return np.zeros((size,size),bool) | |
| xyz=splats.xyz@view.T | |
| rot=rotation_matrices(splats.quat) | |
| cov=(rot*(splats.scale**2)[:,None,:])@rot.transpose(0,2,1) | |
| cov=view[None]@cov@view.T[None] | |
| alpha=np.zeros((size,size),np.float32) | |
| flip=np.diag([1.,-1.]) | |
| for i in range(len(xyz)): | |
| center=xyz[i,:2]*np.array([1,-1])*(size/1.25)+size/2 | |
| c=flip@cov[i,:2,:2]@flip*(size/1.25)**2+np.eye(2)*.3 | |
| radius=min(size,int(np.ceil(3*np.sqrt(np.linalg.eigvalsh(c).max())))) | |
| lo=np.maximum(0,np.floor(center-radius).astype(int)) | |
| hi=np.minimum(size,np.ceil(center+radius+1).astype(int)) | |
| if np.any(hi<=lo): continue | |
| yy,xx=np.mgrid[lo[1]:hi[1],lo[0]:hi[0]] | |
| delta=np.stack([xx-center[0],yy-center[1]],axis=-1) | |
| a=(splats.opacity[i,0]*np.exp(-.5*np.einsum("...i,ij,...j->...",delta,np.linalg.inv(c),delta))).clip(0,.99) | |
| patch=alpha[lo[1]:hi[1],lo[0]:hi[0]] | |
| patch[:]=1-(1-patch)*(1-a) | |
| return alpha>=.5 | |
| def iou(a,b): | |
| return float(np.logical_and(a,b).sum()/max(1,np.logical_or(a,b).sum())) | |