Skip to content

Commit c4d51b3

Browse files
authored
Add files via upload
1 parent 7e590f0 commit c4d51b3

File tree

1 file changed

+272
-0
lines changed

1 file changed

+272
-0
lines changed

cd_normal_fscore.cu

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#include <stdio.h>
2+
#include <ctime>
3+
#include <cstdio>
4+
#include <cstdlib>
5+
#include <cuda.h>
6+
#include <cuda_runtime.h>
7+
#include <vector>
8+
#include <string>
9+
10+
#define N 1111111
11+
#define B 1
12+
#define MESH 5555555
13+
14+
__global__ void NmDistanceKernel(int b,int n,const float * xyz,int m,const float * xyz2,float * result,int * result_i){
15+
const int batch=512;
16+
__shared__ float buf[batch*3];
17+
for (int i=blockIdx.x;i<b;i+=gridDim.x){
18+
for (int k2=0;k2<m;k2+=batch){
19+
int end_k=min(m,k2+batch)-k2;
20+
for (int j=threadIdx.x;j<end_k*3;j+=blockDim.x){
21+
buf[j]=xyz2[(i*m+k2)*3+j];
22+
}
23+
__syncthreads();
24+
for (int j=threadIdx.x+blockIdx.y*blockDim.x;j<n;j+=blockDim.x*gridDim.y){
25+
float x1=xyz[(i*n+j)*3+0], y1=xyz[(i*n+j)*3+1], 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+
for (int k=0;k<end_ka;k+=4){
30+
{
31+
float x2=buf[k*3+0]-x1, y2=buf[k*3+1]-y1, z2=buf[k*3+2]-z1;
32+
float d=x2*x2+y2*y2+z2*z2;
33+
if (k==0 || d<best){
34+
best=d; best_i=k+k2;}
35+
}
36+
{
37+
float x2=buf[k*3+3]-x1, y2=buf[k*3+4]-y1, z2=buf[k*3+5]-z1;
38+
float d=x2*x2+y2*y2+z2*z2;
39+
if (d<best){
40+
best=d; best_i=k+k2+1;}
41+
}
42+
{
43+
float x2=buf[k*3+6]-x1, y2=buf[k*3+7]-y1, z2=buf[k*3+8]-z1;
44+
float d=x2*x2+y2*y2+z2*z2;
45+
if (d<best){
46+
best=d; best_i=k+k2+2;}
47+
}
48+
{
49+
float x2=buf[k*3+9]-x1, y2=buf[k*3+10]-y1, z2=buf[k*3+11]-z1;
50+
float d=x2*x2+y2*y2+z2*z2;
51+
if (d<best){
52+
best=d; best_i=k+k2+3;}
53+
}
54+
}
55+
for (int k=end_ka;k<end_k;k++){
56+
float x2=buf[k*3+0]-x1, y2=buf[k*3+1]-y1, z2=buf[k*3+2]-z1;
57+
float d=x2*x2+y2*y2+z2*z2;
58+
if (k==0 || d<best){
59+
best=d; best_i=k+k2;}
60+
}
61+
if (k2==0 || result[(i*n+j)]>best){
62+
result[(i*n+j)]=best;
63+
result_i[(i*n+j)]=best_i;
64+
}
65+
}
66+
__syncthreads();
67+
}
68+
}
69+
}
70+
void chamfer_cuda_forward(int b, int n, float * xyz1, int m, float * xyz2, float * dist1, int * idx1,float * dist2, int * idx2, cudaStream_t stream){
71+
NmDistanceKernel<<<dim3(32,16,1),512>>>(b, n, xyz1, m, xyz2, dist1, idx1);
72+
cudaDeviceSynchronize();
73+
NmDistanceKernel<<<dim3(32,16,1),512>>>(b, m, xyz2, n, xyz1, dist2, idx2);
74+
cudaDeviceSynchronize();
75+
return ;
76+
}
77+
78+
79+
float xyz1[B][N][3], xyz2[B][N][3];
80+
float dist1[B][N], dist2[B][N];
81+
int idx1[B][N], idx2[B][N];
82+
83+
float *xyz1_gpu, *xyz2_gpu, *dist1_gpu, *dist2_gpu;
84+
int *idx1_gpu, *idx2_gpu;
85+
86+
87+
struct Point {
88+
double x, y, z;
89+
Point() {};
90+
Point (double _x, double _y, double _z) {
91+
x = _x; y = _y; z = _z;
92+
};
93+
Point operator - (const Point& v) const {
94+
return Point(x - v.x, y - v.y, z - v.z);}
95+
96+
Point operator + (const Point& v) const {
97+
return Point(x + v.x, y + v.y, z + v.z);}
98+
99+
Point operator * (const double t) const {
100+
return Point(x * t, y * t, z * t);}
101+
102+
double length() {
103+
return sqrt(x * x + y * y + z * z);}
104+
105+
void normalize() {
106+
double l = length();
107+
x /= l; y /= l; z /= l;}
108+
109+
float dot(const Point& v) const {
110+
return x * v.x + y * v.y + z * v.z;}
111+
112+
Point cross(const Point& v) const {
113+
return Point(
114+
y * v.z - z * v.y,
115+
z * v.x - x * v.z,
116+
x * v.y - y * v.x);}
117+
118+
}vertices1[MESH], vertices2[MESH], normal1[MESH], normal2[MESH];
119+
120+
struct Face {
121+
int a, b, c;
122+
double s;
123+
Face() {};
124+
Face (int _a, int _b, int _c) {
125+
a = _a; b = _b; c = _c;
126+
};
127+
}faces1[MESH], faces2[MESH];
128+
129+
int n_vertices_1, n_vertices_2, n_faces_1, n_faces_2;
130+
int n = 0, m = 0;
131+
int resolution = 1000000;
132+
133+
Point randomPointTriangle(Point a, Point b, Point c) {
134+
double r1 = (double) rand() / RAND_MAX;
135+
double r2 = (double) rand() / RAND_MAX;
136+
double r1sqr = std::sqrt(r1);
137+
double OneMinR1Sqr = (1 - r1sqr);
138+
double OneMinR2 = (1 - r2);
139+
a = a * OneMinR1Sqr;
140+
b = b * OneMinR2;
141+
return (c * r2 + b) * r1sqr + a;
142+
}
143+
144+
int main(int argc, char ** argv) {
145+
std::string mesh1_file = argv[1];
146+
std::string mesh2_file = argv[2];
147+
std::string model_id = argv[3];
148+
149+
freopen(mesh1_file.c_str(), "r", stdin);
150+
scanf("%d%d", &n_vertices_1, &n_faces_1);
151+
for (int i = 0; i < n_vertices_1; i++) {
152+
double x, y, z;
153+
scanf("%lf %lf %lf", &x, &y, &z);
154+
vertices1[i] = Point(x, y, z);
155+
}
156+
double sum_area = 0;
157+
for (int i = 0; i < n_faces_1; i++) {
158+
int _, a, b, c;
159+
scanf("%d %d %d %d", &_, &a, &b, &c);
160+
faces1[i] = Face(a, b, c);
161+
faces1[i].s = (vertices1[c] - vertices1[a]).cross((vertices1[b] - vertices1[a])).length() / 2;
162+
if (std::isnan(faces1[i].s))
163+
faces1[i].s=0;
164+
sum_area += faces1[i].s;
165+
}
166+
for (int i = 0; i < n_faces_1; i++) {
167+
int a = faces1[i].a, b = faces1[i].b, c = faces1[i].c;
168+
int t = round(resolution * (faces1[i].s / sum_area));
169+
Point normal = (vertices1[c] - vertices1[a]).cross(vertices1[b] - vertices1[a]);
170+
normal.normalize();
171+
for (int j = 0; j < t; j++) {
172+
Point p = randomPointTriangle(vertices1[a], vertices1[b], vertices1[c]);
173+
xyz1[0][n][0] = p.x; xyz1[0][n][1] = p.y; xyz1[0][n][2] = p.z;
174+
normal1[n] = normal;
175+
n++;
176+
}
177+
}
178+
179+
freopen(mesh2_file.c_str(), "r", stdin);
180+
scanf("%d%d", &n_vertices_2, &n_faces_2);
181+
for (int i = 0; i < n_vertices_2; i++) {
182+
double x, y, z;
183+
scanf("%lf %lf %lf", &x, &y, &z);
184+
vertices2[i] = Point(x, y, z);
185+
}
186+
sum_area = 0;
187+
for (int i = 0; i < n_faces_2; i++) {
188+
int _, a, b, c;
189+
scanf("%d %d %d %d", &_, &a, &b, &c);
190+
faces2[i] = Face(a, b, c);
191+
faces2[i].s = (vertices2[c] - vertices2[a]).cross((vertices2[b] - vertices2[a])).length() / 2;
192+
sum_area += faces2[i].s;
193+
}
194+
for (int i = 0; i < n_faces_2; i++) {
195+
int a = faces2[i].a, b = faces2[i].b, c = faces2[i].c;
196+
int t = round(resolution * (faces2[i].s / sum_area));
197+
Point normal = (vertices2[c] - vertices2[a]).cross(vertices2[b] - vertices2[a]);
198+
normal.normalize();
199+
for (int j = 0; j < t; j++) {
200+
Point p = randomPointTriangle(vertices2[a], vertices2[b], vertices2[c]);
201+
xyz2[0][m][0] = p.x; xyz2[0][m][1] = p.y; xyz2[0][m][2] = p.z;
202+
normal2[m] = normal;
203+
m++;
204+
}
205+
}
206+
207+
size_t xyz_size = max(n, m) * 3 * sizeof(float);
208+
size_t dis_size = max(n, m) * sizeof(float);
209+
size_t idx_size = max(n, m) * sizeof(int);
210+
cudaMalloc((void **) &xyz1_gpu, xyz_size);
211+
cudaMalloc((void **) &xyz2_gpu, xyz_size);
212+
cudaMalloc((void **) &dist1_gpu, dis_size);
213+
cudaMalloc((void **) &dist2_gpu, dis_size);
214+
cudaMalloc((void **) &idx1_gpu, idx_size);
215+
cudaMalloc((void **) &idx2_gpu, idx_size);
216+
217+
cudaMemcpy(xyz1_gpu, &xyz1[0][0], xyz_size, cudaMemcpyHostToDevice);
218+
cudaMemcpy(xyz2_gpu, &xyz2[0][0], xyz_size, cudaMemcpyHostToDevice);
219+
220+
chamfer_cuda_forward(1, n, xyz1_gpu, m, xyz2_gpu, dist1_gpu, idx1_gpu, dist2_gpu, idx2_gpu, NULL);
221+
222+
cudaMemcpy(&dist1[0][0], dist1_gpu, dis_size, cudaMemcpyDeviceToHost);
223+
cudaMemcpy(&dist2[0][0], dist2_gpu, dis_size, cudaMemcpyDeviceToHost);
224+
225+
cudaMemcpy(&idx1[0][0], idx1_gpu, idx_size, cudaMemcpyDeviceToHost);
226+
cudaMemcpy(&idx2[0][0], idx2_gpu, idx_size, cudaMemcpyDeviceToHost);
227+
228+
cudaError_t err = cudaGetLastError();
229+
if (err != cudaSuccess) {
230+
printf("error in nnd updateOutput: %s\n", cudaGetErrorString(err));
231+
return 0;
232+
}
233+
234+
double sum = 0;
235+
236+
double sum_normal = 0;
237+
238+
// normal consistency
239+
for (int i = 0; i < n; i++) {
240+
sum_normal += abs(normal1[i].dot(normal2[idx1[0][i]]));
241+
}
242+
243+
for (int i = 0; i < m; i++) {
244+
sum_normal += abs(normal2[i].dot(normal1[idx2[0][i]]));
245+
}
246+
247+
// f-score for different threshold
248+
for (int k = 0; k <= 40; k++) {
249+
double threashold = sqrt(sum_area / resolution) * (1.0 + (double)k / 20);
250+
int cnt1 = n, cnt2 = m;
251+
for (int i = 0; i < n; i++) {
252+
double d = sqrt(dist1[0][i]);
253+
if (d > threashold)
254+
cnt1--;
255+
if (k == 0) sum += d;
256+
}
257+
for (int i = 0; i < m; i++) {
258+
double d = sqrt(dist2[0][i]);
259+
if (d > threashold)
260+
cnt2--;
261+
if (k == 0) sum += d;
262+
}
263+
double t1 = (double) cnt1 / n;
264+
double t2 = (double) cnt2 / m;
265+
double f1 = 2 * t1 * t2 / (t1 + t2 + 1e-9);
266+
printf("%lf ", f1);
267+
}
268+
269+
// chamfer distance & normal consistency
270+
printf("%lf %lf %s\n", sum / (n + m), sum_normal / (n + m), model_id.c_str());
271+
return 0;
272+
}

0 commit comments

Comments
 (0)