Spaces:
Running
on
Zero
Running
on
Zero
Commit
·
5b3fc44
1
Parent(s):
1c78eb8
v1
Browse files- P3-SAM/utils/chamfer3D/chamfer3D.cu +0 -196
- P3-SAM/utils/chamfer3D/chamfer_cuda.cpp +0 -29
- P3-SAM/utils/chamfer3D/dist_chamfer_3D.py +0 -81
- P3-SAM/utils/chamfer3D/setup.py +0 -14
- app.py +13 -11
P3-SAM/utils/chamfer3D/chamfer3D.cu
DELETED
|
@@ -1,196 +0,0 @@
|
|
| 1 |
-
|
| 2 |
-
#include <stdio.h>
|
| 3 |
-
#include <ATen/ATen.h>
|
| 4 |
-
|
| 5 |
-
#include <cuda.h>
|
| 6 |
-
#include <cuda_runtime.h>
|
| 7 |
-
|
| 8 |
-
#include <vector>
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
__global__ void NmDistanceKernel(int b,int n,const float * xyz,int m,const float * xyz2,float * result,int * result_i){
|
| 13 |
-
const int batch=512;
|
| 14 |
-
__shared__ float buf[batch*3];
|
| 15 |
-
for (int i=blockIdx.x;i<b;i+=gridDim.x){
|
| 16 |
-
for (int k2=0;k2<m;k2+=batch){
|
| 17 |
-
int end_k=min(m,k2+batch)-k2;
|
| 18 |
-
for (int j=threadIdx.x;j<end_k*3;j+=blockDim.x){
|
| 19 |
-
buf[j]=xyz2[(i*m+k2)*3+j];
|
| 20 |
-
}
|
| 21 |
-
__syncthreads();
|
| 22 |
-
for (int j=threadIdx.x+blockIdx.y*blockDim.x;j<n;j+=blockDim.x*gridDim.y){
|
| 23 |
-
float x1=xyz[(i*n+j)*3+0];
|
| 24 |
-
float y1=xyz[(i*n+j)*3+1];
|
| 25 |
-
float z1=xyz[(i*n+j)*3+2];
|
| 26 |
-
int best_i=0;
|
| 27 |
-
float best=0;
|
| 28 |
-
int end_ka=end_k-(end_k&3);
|
| 29 |
-
if (end_ka==batch){
|
| 30 |
-
for (int k=0;k<batch;k+=4){
|
| 31 |
-
{
|
| 32 |
-
float x2=buf[k*3+0]-x1;
|
| 33 |
-
float y2=buf[k*3+1]-y1;
|
| 34 |
-
float z2=buf[k*3+2]-z1;
|
| 35 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 36 |
-
if (k==0 || d<best){
|
| 37 |
-
best=d;
|
| 38 |
-
best_i=k+k2;
|
| 39 |
-
}
|
| 40 |
-
}
|
| 41 |
-
{
|
| 42 |
-
float x2=buf[k*3+3]-x1;
|
| 43 |
-
float y2=buf[k*3+4]-y1;
|
| 44 |
-
float z2=buf[k*3+5]-z1;
|
| 45 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 46 |
-
if (d<best){
|
| 47 |
-
best=d;
|
| 48 |
-
best_i=k+k2+1;
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
{
|
| 52 |
-
float x2=buf[k*3+6]-x1;
|
| 53 |
-
float y2=buf[k*3+7]-y1;
|
| 54 |
-
float z2=buf[k*3+8]-z1;
|
| 55 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 56 |
-
if (d<best){
|
| 57 |
-
best=d;
|
| 58 |
-
best_i=k+k2+2;
|
| 59 |
-
}
|
| 60 |
-
}
|
| 61 |
-
{
|
| 62 |
-
float x2=buf[k*3+9]-x1;
|
| 63 |
-
float y2=buf[k*3+10]-y1;
|
| 64 |
-
float z2=buf[k*3+11]-z1;
|
| 65 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 66 |
-
if (d<best){
|
| 67 |
-
best=d;
|
| 68 |
-
best_i=k+k2+3;
|
| 69 |
-
}
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
}else{
|
| 73 |
-
for (int k=0;k<end_ka;k+=4){
|
| 74 |
-
{
|
| 75 |
-
float x2=buf[k*3+0]-x1;
|
| 76 |
-
float y2=buf[k*3+1]-y1;
|
| 77 |
-
float z2=buf[k*3+2]-z1;
|
| 78 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 79 |
-
if (k==0 || d<best){
|
| 80 |
-
best=d;
|
| 81 |
-
best_i=k+k2;
|
| 82 |
-
}
|
| 83 |
-
}
|
| 84 |
-
{
|
| 85 |
-
float x2=buf[k*3+3]-x1;
|
| 86 |
-
float y2=buf[k*3+4]-y1;
|
| 87 |
-
float z2=buf[k*3+5]-z1;
|
| 88 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 89 |
-
if (d<best){
|
| 90 |
-
best=d;
|
| 91 |
-
best_i=k+k2+1;
|
| 92 |
-
}
|
| 93 |
-
}
|
| 94 |
-
{
|
| 95 |
-
float x2=buf[k*3+6]-x1;
|
| 96 |
-
float y2=buf[k*3+7]-y1;
|
| 97 |
-
float z2=buf[k*3+8]-z1;
|
| 98 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 99 |
-
if (d<best){
|
| 100 |
-
best=d;
|
| 101 |
-
best_i=k+k2+2;
|
| 102 |
-
}
|
| 103 |
-
}
|
| 104 |
-
{
|
| 105 |
-
float x2=buf[k*3+9]-x1;
|
| 106 |
-
float y2=buf[k*3+10]-y1;
|
| 107 |
-
float z2=buf[k*3+11]-z1;
|
| 108 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 109 |
-
if (d<best){
|
| 110 |
-
best=d;
|
| 111 |
-
best_i=k+k2+3;
|
| 112 |
-
}
|
| 113 |
-
}
|
| 114 |
-
}
|
| 115 |
-
}
|
| 116 |
-
for (int k=end_ka;k<end_k;k++){
|
| 117 |
-
float x2=buf[k*3+0]-x1;
|
| 118 |
-
float y2=buf[k*3+1]-y1;
|
| 119 |
-
float z2=buf[k*3+2]-z1;
|
| 120 |
-
float d=x2*x2+y2*y2+z2*z2;
|
| 121 |
-
if (k==0 || d<best){
|
| 122 |
-
best=d;
|
| 123 |
-
best_i=k+k2;
|
| 124 |
-
}
|
| 125 |
-
}
|
| 126 |
-
if (k2==0 || result[(i*n+j)]>best){
|
| 127 |
-
result[(i*n+j)]=best;
|
| 128 |
-
result_i[(i*n+j)]=best_i;
|
| 129 |
-
}
|
| 130 |
-
}
|
| 131 |
-
__syncthreads();
|
| 132 |
-
}
|
| 133 |
-
}
|
| 134 |
-
}
|
| 135 |
-
// int chamfer_cuda_forward(int b,int n,const float * xyz,int m,const float * xyz2,float * result,int * result_i,float * result2,int * result2_i, cudaStream_t stream){
|
| 136 |
-
int chamfer_cuda_forward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor dist1, at::Tensor dist2, at::Tensor idx1, at::Tensor idx2){
|
| 137 |
-
|
| 138 |
-
const auto batch_size = xyz1.size(0);
|
| 139 |
-
const auto n = xyz1.size(1); //num_points point cloud A
|
| 140 |
-
const auto m = xyz2.size(1); //num_points point cloud B
|
| 141 |
-
|
| 142 |
-
NmDistanceKernel<<<dim3(32,16,1),512>>>(batch_size, n, xyz1.data<float>(), m, xyz2.data<float>(), dist1.data<float>(), idx1.data<int>());
|
| 143 |
-
NmDistanceKernel<<<dim3(32,16,1),512>>>(batch_size, m, xyz2.data<float>(), n, xyz1.data<float>(), dist2.data<float>(), idx2.data<int>());
|
| 144 |
-
|
| 145 |
-
cudaError_t err = cudaGetLastError();
|
| 146 |
-
if (err != cudaSuccess) {
|
| 147 |
-
printf("error in nnd updateOutput: %s\n", cudaGetErrorString(err));
|
| 148 |
-
//THError("aborting");
|
| 149 |
-
return 0;
|
| 150 |
-
}
|
| 151 |
-
return 1;
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
}
|
| 155 |
-
__global__ void NmDistanceGradKernel(int b,int n,const float * xyz1,int m,const float * xyz2,const float * grad_dist1,const int * idx1,float * grad_xyz1,float * grad_xyz2){
|
| 156 |
-
for (int i=blockIdx.x;i<b;i+=gridDim.x){
|
| 157 |
-
for (int j=threadIdx.x+blockIdx.y*blockDim.x;j<n;j+=blockDim.x*gridDim.y){
|
| 158 |
-
float x1=xyz1[(i*n+j)*3+0];
|
| 159 |
-
float y1=xyz1[(i*n+j)*3+1];
|
| 160 |
-
float z1=xyz1[(i*n+j)*3+2];
|
| 161 |
-
int j2=idx1[i*n+j];
|
| 162 |
-
float x2=xyz2[(i*m+j2)*3+0];
|
| 163 |
-
float y2=xyz2[(i*m+j2)*3+1];
|
| 164 |
-
float z2=xyz2[(i*m+j2)*3+2];
|
| 165 |
-
float g=grad_dist1[i*n+j]*2;
|
| 166 |
-
atomicAdd(&(grad_xyz1[(i*n+j)*3+0]),g*(x1-x2));
|
| 167 |
-
atomicAdd(&(grad_xyz1[(i*n+j)*3+1]),g*(y1-y2));
|
| 168 |
-
atomicAdd(&(grad_xyz1[(i*n+j)*3+2]),g*(z1-z2));
|
| 169 |
-
atomicAdd(&(grad_xyz2[(i*m+j2)*3+0]),-(g*(x1-x2)));
|
| 170 |
-
atomicAdd(&(grad_xyz2[(i*m+j2)*3+1]),-(g*(y1-y2)));
|
| 171 |
-
atomicAdd(&(grad_xyz2[(i*m+j2)*3+2]),-(g*(z1-z2)));
|
| 172 |
-
}
|
| 173 |
-
}
|
| 174 |
-
}
|
| 175 |
-
// int chamfer_cuda_backward(int b,int n,const float * xyz1,int m,const float * xyz2,const float * grad_dist1,const int * idx1,const float * grad_dist2,const int * idx2,float * grad_xyz1,float * grad_xyz2, cudaStream_t stream){
|
| 176 |
-
int chamfer_cuda_backward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor gradxyz1, at::Tensor gradxyz2, at::Tensor graddist1, at::Tensor graddist2, at::Tensor idx1, at::Tensor idx2){
|
| 177 |
-
// cudaMemset(grad_xyz1,0,b*n*3*4);
|
| 178 |
-
// cudaMemset(grad_xyz2,0,b*m*3*4);
|
| 179 |
-
|
| 180 |
-
const auto batch_size = xyz1.size(0);
|
| 181 |
-
const auto n = xyz1.size(1); //num_points point cloud A
|
| 182 |
-
const auto m = xyz2.size(1); //num_points point cloud B
|
| 183 |
-
|
| 184 |
-
NmDistanceGradKernel<<<dim3(1,16,1),256>>>(batch_size,n,xyz1.data<float>(),m,xyz2.data<float>(),graddist1.data<float>(),idx1.data<int>(),gradxyz1.data<float>(),gradxyz2.data<float>());
|
| 185 |
-
NmDistanceGradKernel<<<dim3(1,16,1),256>>>(batch_size,m,xyz2.data<float>(),n,xyz1.data<float>(),graddist2.data<float>(),idx2.data<int>(),gradxyz2.data<float>(),gradxyz1.data<float>());
|
| 186 |
-
|
| 187 |
-
cudaError_t err = cudaGetLastError();
|
| 188 |
-
if (err != cudaSuccess) {
|
| 189 |
-
printf("error in nnd get grad: %s\n", cudaGetErrorString(err));
|
| 190 |
-
//THError("aborting");
|
| 191 |
-
return 0;
|
| 192 |
-
}
|
| 193 |
-
return 1;
|
| 194 |
-
|
| 195 |
-
}
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P3-SAM/utils/chamfer3D/chamfer_cuda.cpp
DELETED
|
@@ -1,29 +0,0 @@
|
|
| 1 |
-
#include <torch/torch.h>
|
| 2 |
-
#include <vector>
|
| 3 |
-
|
| 4 |
-
/// TMP
|
| 5 |
-
// #include "common.h"
|
| 6 |
-
/// NOT TMP
|
| 7 |
-
|
| 8 |
-
int chamfer_cuda_forward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor dist1, at::Tensor dist2,
|
| 9 |
-
at::Tensor idx1, at::Tensor idx2);
|
| 10 |
-
|
| 11 |
-
int chamfer_cuda_backward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor gradxyz1,
|
| 12 |
-
at::Tensor gradxyz2, at::Tensor graddist1, at::Tensor graddist2,
|
| 13 |
-
at::Tensor idx1, at::Tensor idx2);
|
| 14 |
-
|
| 15 |
-
int chamfer_forward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor dist1, at::Tensor dist2,
|
| 16 |
-
at::Tensor idx1, at::Tensor idx2) {
|
| 17 |
-
return chamfer_cuda_forward(xyz1, xyz2, dist1, dist2, idx1, idx2);
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
int chamfer_backward(at::Tensor xyz1, at::Tensor xyz2, at::Tensor gradxyz1, at::Tensor gradxyz2,
|
| 21 |
-
at::Tensor graddist1, at::Tensor graddist2, at::Tensor idx1, at::Tensor idx2) {
|
| 22 |
-
|
| 23 |
-
return chamfer_cuda_backward(xyz1, xyz2, gradxyz1, gradxyz2, graddist1, graddist2, idx1, idx2);
|
| 24 |
-
}
|
| 25 |
-
|
| 26 |
-
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
|
| 27 |
-
m.def("forward", &chamfer_forward, "chamfer forward (CUDA)");
|
| 28 |
-
m.def("backward", &chamfer_backward, "chamfer backward (CUDA)");
|
| 29 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P3-SAM/utils/chamfer3D/dist_chamfer_3D.py
DELETED
|
@@ -1,81 +0,0 @@
|
|
| 1 |
-
from torch import nn
|
| 2 |
-
from torch.autograd import Function
|
| 3 |
-
import torch
|
| 4 |
-
import importlib
|
| 5 |
-
import os
|
| 6 |
-
chamfer_found = importlib.find_loader("chamfer_3D") is not None
|
| 7 |
-
if not chamfer_found:
|
| 8 |
-
## Cool trick from https://github.com/chrdiller
|
| 9 |
-
print("Jitting Chamfer 3D")
|
| 10 |
-
cur_path = os.path.dirname(os.path.abspath(__file__))
|
| 11 |
-
build_path = cur_path.replace('chamfer3D', 'tmp')
|
| 12 |
-
os.makedirs(build_path, exist_ok=True)
|
| 13 |
-
|
| 14 |
-
from torch.utils.cpp_extension import load
|
| 15 |
-
chamfer_3D = load(name="chamfer_3D",
|
| 16 |
-
sources=[
|
| 17 |
-
"/".join(os.path.abspath(__file__).split('/')[:-1] + ["chamfer_cuda.cpp"]),
|
| 18 |
-
"/".join(os.path.abspath(__file__).split('/')[:-1] + ["chamfer3D.cu"]),
|
| 19 |
-
], build_directory=build_path)
|
| 20 |
-
print("Loaded JIT 3D CUDA chamfer distance")
|
| 21 |
-
|
| 22 |
-
else:
|
| 23 |
-
import chamfer_3D
|
| 24 |
-
print("Loaded compiled 3D CUDA chamfer distance")
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
# Chamfer's distance module @thibaultgroueix
|
| 28 |
-
# GPU tensors only
|
| 29 |
-
class chamfer_3DFunction(Function):
|
| 30 |
-
@staticmethod
|
| 31 |
-
def forward(ctx, xyz1, xyz2):
|
| 32 |
-
batchsize, n, dim = xyz1.size()
|
| 33 |
-
assert dim==3, "Wrong last dimension for the chamfer distance 's input! Check with .size()"
|
| 34 |
-
_, m, dim = xyz2.size()
|
| 35 |
-
assert dim==3, "Wrong last dimension for the chamfer distance 's input! Check with .size()"
|
| 36 |
-
device = xyz1.device
|
| 37 |
-
|
| 38 |
-
device = xyz1.device
|
| 39 |
-
|
| 40 |
-
dist1 = torch.zeros(batchsize, n)
|
| 41 |
-
dist2 = torch.zeros(batchsize, m)
|
| 42 |
-
|
| 43 |
-
idx1 = torch.zeros(batchsize, n).type(torch.IntTensor)
|
| 44 |
-
idx2 = torch.zeros(batchsize, m).type(torch.IntTensor)
|
| 45 |
-
|
| 46 |
-
dist1 = dist1.to(device)
|
| 47 |
-
dist2 = dist2.to(device)
|
| 48 |
-
idx1 = idx1.to(device)
|
| 49 |
-
idx2 = idx2.to(device)
|
| 50 |
-
torch.cuda.set_device(device)
|
| 51 |
-
|
| 52 |
-
chamfer_3D.forward(xyz1, xyz2, dist1, dist2, idx1, idx2)
|
| 53 |
-
ctx.save_for_backward(xyz1, xyz2, idx1, idx2)
|
| 54 |
-
return dist1, dist2, idx1, idx2
|
| 55 |
-
|
| 56 |
-
@staticmethod
|
| 57 |
-
def backward(ctx, graddist1, graddist2, gradidx1, gradidx2):
|
| 58 |
-
xyz1, xyz2, idx1, idx2 = ctx.saved_tensors
|
| 59 |
-
graddist1 = graddist1.contiguous()
|
| 60 |
-
graddist2 = graddist2.contiguous()
|
| 61 |
-
device = graddist1.device
|
| 62 |
-
|
| 63 |
-
gradxyz1 = torch.zeros(xyz1.size())
|
| 64 |
-
gradxyz2 = torch.zeros(xyz2.size())
|
| 65 |
-
|
| 66 |
-
gradxyz1 = gradxyz1.to(device)
|
| 67 |
-
gradxyz2 = gradxyz2.to(device)
|
| 68 |
-
chamfer_3D.backward(
|
| 69 |
-
xyz1, xyz2, gradxyz1, gradxyz2, graddist1, graddist2, idx1, idx2
|
| 70 |
-
)
|
| 71 |
-
return gradxyz1, gradxyz2
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
class chamfer_3DDist(nn.Module):
|
| 75 |
-
def __init__(self):
|
| 76 |
-
super(chamfer_3DDist, self).__init__()
|
| 77 |
-
|
| 78 |
-
def forward(self, input1, input2):
|
| 79 |
-
input1 = input1.contiguous()
|
| 80 |
-
input2 = input2.contiguous()
|
| 81 |
-
return chamfer_3DFunction.apply(input1, input2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P3-SAM/utils/chamfer3D/setup.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
| 1 |
-
from setuptools import setup
|
| 2 |
-
from torch.utils.cpp_extension import BuildExtension, CUDAExtension
|
| 3 |
-
|
| 4 |
-
setup(
|
| 5 |
-
name='chamfer_3D',
|
| 6 |
-
ext_modules=[
|
| 7 |
-
CUDAExtension('chamfer_3D', [
|
| 8 |
-
"/".join(__file__.split('/')[:-1] + ['chamfer_cuda.cpp']),
|
| 9 |
-
"/".join(__file__.split('/')[:-1] + ['chamfer3D.cu']),
|
| 10 |
-
]),
|
| 11 |
-
],
|
| 12 |
-
cmdclass={
|
| 13 |
-
'build_ext': BuildExtension
|
| 14 |
-
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
|
@@ -11,13 +11,11 @@ import spaces
|
|
| 11 |
|
| 12 |
sys.path.append('P3-SAM')
|
| 13 |
from demo.auto_mask import AutoMask
|
| 14 |
-
# from demo.auto_mask_no_postprocess import AutoMask as AutoMaskNoPostProcess
|
| 15 |
sys.path.append('XPart')
|
| 16 |
from partgen.partformer_pipeline import PartFormerPipeline
|
| 17 |
from partgen.utils.misc import get_config_from_file
|
| 18 |
|
| 19 |
automask = AutoMask()
|
| 20 |
-
# automask_no_postprocess = AutoMaskNoPostProcess(automask_instance=automask)
|
| 21 |
|
| 22 |
def _load_pipeline():
|
| 23 |
pl.seed_everything(2026, workers=True)
|
|
@@ -41,17 +39,21 @@ _PIPELINE = _load_pipeline()
|
|
| 41 |
output_path = 'P3-SAM/results/gradio'
|
| 42 |
os.makedirs(output_path, exist_ok=True)
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
@spaces.GPU
|
| 45 |
-
def segment(mesh_path,
|
| 46 |
if mesh_path is None:
|
| 47 |
gr.Warning("No Input Mesh")
|
| 48 |
-
|
|
|
|
|
|
|
| 49 |
return None, None
|
| 50 |
mesh = trimesh.load(mesh_path, force='mesh', process=False)
|
| 51 |
-
|
| 52 |
-
aabb, face_ids, mesh = automask.predict_aabb(mesh, seed=seed, is_parallel=False, post_process=postprocess, threshold=postprocess_threshold)
|
| 53 |
-
else:
|
| 54 |
-
aabb, face_ids, mesh = automask_no_postprocess.predict_aabb(mesh, seed=seed, is_parallel=False, post_process=False)
|
| 55 |
color_map = {}
|
| 56 |
unique_ids = np.unique(face_ids)
|
| 57 |
for i in unique_ids:
|
|
@@ -76,7 +78,7 @@ def segment(mesh_path, connectivity=True, postprocess=True, postprocess_threshol
|
|
| 76 |
gr_state = [(aabb, mesh_path)]
|
| 77 |
return file_path, face_id_save_path, gr_state
|
| 78 |
|
| 79 |
-
@spaces.GPU
|
| 80 |
def generate(mesh_path, seed=42, gr_state=None):
|
| 81 |
if mesh_path is None:
|
| 82 |
gr.Warning("No Input Mesh")
|
|
@@ -114,6 +116,7 @@ with gr.Blocks() as demo:
|
|
| 114 |
# ☯️ Hunyuan3D Part:P3-SAM&XPart
|
| 115 |
This demo allows you to generate parts given a 3D model using Hunyuan3D-Part.
|
| 116 |
First segment the 3D model using P3-SAM and then generate parts using XPart.
|
|
|
|
| 117 |
'''
|
| 118 |
)
|
| 119 |
with gr.Row():
|
|
@@ -133,7 +136,6 @@ Input a mesh and push the "Segment" button to get the segmentation results.
|
|
| 133 |
p3sam_input = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Input Mesh")
|
| 134 |
p3sam_output = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Segmentation Result")
|
| 135 |
p3sam_face_id_output = gr.File(label='Face ID')
|
| 136 |
-
p3sam_conectivity = gr.Checkbox(value=True, label="Connectivity")
|
| 137 |
p3sam_postprocess = gr.Checkbox(value=True, label="Post-processing")
|
| 138 |
p3sam_postprocess_threshold = gr.Number(value=0.95, label="Post-processing Threshold")
|
| 139 |
p3sam_seed = gr.Number(value=42, label="Random Seed")
|
|
@@ -183,7 +185,7 @@ Input a mesh, segment it using P3-SAM on the left, and push the "Generate" butto
|
|
| 183 |
xpart_output_exploded = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Exploded Object")
|
| 184 |
xpart_seed = gr.Number(value=42, label="Random Seed")
|
| 185 |
gr_state = gr.State(value=[(None, None)])
|
| 186 |
-
p3sam_button.click(segment, inputs=[p3sam_input,
|
| 187 |
xpart_button.click(generate, inputs=[p3sam_input, xpart_seed, gr_state], outputs=[xpart_output, xpart_output_bbox, xpart_output_exploded])
|
| 188 |
|
| 189 |
|
|
|
|
| 11 |
|
| 12 |
sys.path.append('P3-SAM')
|
| 13 |
from demo.auto_mask import AutoMask
|
|
|
|
| 14 |
sys.path.append('XPart')
|
| 15 |
from partgen.partformer_pipeline import PartFormerPipeline
|
| 16 |
from partgen.utils.misc import get_config_from_file
|
| 17 |
|
| 18 |
automask = AutoMask()
|
|
|
|
| 19 |
|
| 20 |
def _load_pipeline():
|
| 21 |
pl.seed_everything(2026, workers=True)
|
|
|
|
| 39 |
output_path = 'P3-SAM/results/gradio'
|
| 40 |
os.makedirs(output_path, exist_ok=True)
|
| 41 |
|
| 42 |
+
def is_supported_3d_file(filename):
|
| 43 |
+
# 获取文件扩展名(小写),并去除开头的点
|
| 44 |
+
ext = os.path.splitext(filename)[1].lower()
|
| 45 |
+
return ext in ['.glb', '.ply', '.obj']
|
| 46 |
+
|
| 47 |
@spaces.GPU
|
| 48 |
+
def segment(mesh_path, postprocess=True, postprocess_threshold=0.95, seed=42):
|
| 49 |
if mesh_path is None:
|
| 50 |
gr.Warning("No Input Mesh")
|
| 51 |
+
return None, None
|
| 52 |
+
if not is_supported_3d_file(mesh_path):
|
| 53 |
+
gr.Warning("Only support glb ply obj.")
|
| 54 |
return None, None
|
| 55 |
mesh = trimesh.load(mesh_path, force='mesh', process=False)
|
| 56 |
+
aabb, face_ids, mesh = automask.predict_aabb(mesh, seed=seed, is_parallel=False, post_process=postprocess, threshold=postprocess_threshold)
|
|
|
|
|
|
|
|
|
|
| 57 |
color_map = {}
|
| 58 |
unique_ids = np.unique(face_ids)
|
| 59 |
for i in unique_ids:
|
|
|
|
| 78 |
gr_state = [(aabb, mesh_path)]
|
| 79 |
return file_path, face_id_save_path, gr_state
|
| 80 |
|
| 81 |
+
@spaces.GPU(duration=150)
|
| 82 |
def generate(mesh_path, seed=42, gr_state=None):
|
| 83 |
if mesh_path is None:
|
| 84 |
gr.Warning("No Input Mesh")
|
|
|
|
| 116 |
# ☯️ Hunyuan3D Part:P3-SAM&XPart
|
| 117 |
This demo allows you to generate parts given a 3D model using Hunyuan3D-Part.
|
| 118 |
First segment the 3D model using P3-SAM and then generate parts using XPart.
|
| 119 |
+
Please upload glb ply or obj 3D model files.
|
| 120 |
'''
|
| 121 |
)
|
| 122 |
with gr.Row():
|
|
|
|
| 136 |
p3sam_input = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Input Mesh")
|
| 137 |
p3sam_output = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Segmentation Result")
|
| 138 |
p3sam_face_id_output = gr.File(label='Face ID')
|
|
|
|
| 139 |
p3sam_postprocess = gr.Checkbox(value=True, label="Post-processing")
|
| 140 |
p3sam_postprocess_threshold = gr.Number(value=0.95, label="Post-processing Threshold")
|
| 141 |
p3sam_seed = gr.Number(value=42, label="Random Seed")
|
|
|
|
| 185 |
xpart_output_exploded = gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="Exploded Object")
|
| 186 |
xpart_seed = gr.Number(value=42, label="Random Seed")
|
| 187 |
gr_state = gr.State(value=[(None, None)])
|
| 188 |
+
p3sam_button.click(segment, inputs=[p3sam_input, p3sam_postprocess, p3sam_postprocess_threshold, p3sam_seed], outputs=[p3sam_output, p3sam_face_id_output, gr_state])
|
| 189 |
xpart_button.click(generate, inputs=[p3sam_input, xpart_seed, gr_state], outputs=[xpart_output, xpart_output_bbox, xpart_output_exploded])
|
| 190 |
|
| 191 |
|