daerduoCarey / structurenet

StructureNet: Hierarchical Graph Networks for 3D Shape Generation
https://cs.stanford.edu/~kaichun/structurenet/
Other
258 stars 45 forks source link

Code for fitting oriented minimum-volume bounding box? #3

Closed ChrisWu1997 closed 4 years ago

ChrisWu1997 commented 4 years ago

Love this work! But I do need some help. As mentioned in Section 6 in the paper, you obtained OBB for each part. Can you release that code or provide the library that you used?

Thanks in advance!

Dustinpro commented 4 years ago

I think the link below is the API for OBB: https://github.com/daerduoCarey/structurenet/blob/5da0736fbf86cf3282a3a49efa6b64b2a8eff801/code/compute_sym.py#L155 If you prefer to use a library, trimesh is a nice alternative. But, it may not produce exactly the same bounding boxes.

ChrisWu1997 commented 4 years ago

Thanks a lot!

daerduoCarey commented 4 years ago

Thanks @Dustinpro for the reply. Yes, this compute_obb function can be used to compute the bounding box. However, we find it has a small bug that the point cloud center may not match the bounding box center, so the OBB may not encompass the point cloud geometry exactly for some hightly unbalanced geometry. But it doesn't affect the StructureNet paper as the extracted boxes are still good to use. Any follow-up papers should use the data provided here (https://docs.google.com/forms/d/1MVajyDDBzqs13aI9sGH32pRmakTWPMnM_kHoQ_q7hvs/edit?usp=forms_home&ths=true) to download the extracted OBBs to compare to the paper results.

daerduoCarey commented 4 years ago

Just posted it here in case someone else may need it.

75 def fit_box(points): 76 to_origin, size = trimesh.bounds.oriented_bounds(obj=points, angle_digits=1) 77 center = to_origin[:3, :3].transpose().dot(-to_origin[:3, 3]) 78 xdir = to_origin[0, :3] 79 ydir = to_origin[1, :3] 80 return np.hstack([center, size, xdir, ydir]).astype(np.float32).tolist() 81 from sklearn.decomposition import PCA 170 def pc_to_box_fourpoints(points): 171 pca = PCA() 172 pca.fit(points) 173 pcomps = pca.components 174 points_local = np.matmul(pcomps, points.transpose()).transpose() 175 all_max = points_local.max(axis=0) 176 all_min = points_local.min(axis=0) 177 center = np.dot(np.linalg.inv(pcomps), (all_max + all_min) / 2) 178 size = all_max - all_min 179 xdir = pcomps[0, :] 180 xdir /= np.linalg.norm(xdir) 181 ydir = pcomps[1, :] 182 ydir /= np.linalg.norm(ydir) 183 zdir = np.cross(xdir, ydir) 184 zdir /= np.linalg.norm(zdir)

3:06 here are two versions

3:06 the first one computes OBB using convex hull

3:06 the second one uses PCA

3:07 the first one produces better OBBs, but sometimes it fails, when the parts are too thin (have no volume)