Spaces:
Runtime error
Runtime error
Upload hy3dgen/texgen/differentiable_renderer/mesh_processor.cpp with huggingface_hub
Browse files
hy3dgen/texgen/differentiable_renderer/mesh_processor.cpp
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <pybind11/pybind11.h>
|
2 |
+
#include <pybind11/numpy.h>
|
3 |
+
#include <pybind11/stl.h>
|
4 |
+
#include <vector>
|
5 |
+
#include <queue>
|
6 |
+
#include <cmath>
|
7 |
+
#include <algorithm>
|
8 |
+
|
9 |
+
namespace py = pybind11;
|
10 |
+
using namespace std;
|
11 |
+
|
12 |
+
std::pair<py::array_t<float>,
|
13 |
+
py::array_t<uint8_t>> meshVerticeInpaint_smooth(py::array_t<float> texture,
|
14 |
+
py::array_t<uint8_t> mask,
|
15 |
+
py::array_t<float> vtx_pos, py::array_t<float> vtx_uv,
|
16 |
+
py::array_t<int> pos_idx, py::array_t<int> uv_idx) {
|
17 |
+
auto texture_buf = texture.request();
|
18 |
+
auto mask_buf = mask.request();
|
19 |
+
auto vtx_pos_buf = vtx_pos.request();
|
20 |
+
auto vtx_uv_buf = vtx_uv.request();
|
21 |
+
auto pos_idx_buf = pos_idx.request();
|
22 |
+
auto uv_idx_buf = uv_idx.request();
|
23 |
+
|
24 |
+
int texture_height = texture_buf.shape[0];
|
25 |
+
int texture_width = texture_buf.shape[1];
|
26 |
+
int texture_channel = texture_buf.shape[2];
|
27 |
+
float* texture_ptr = static_cast<float*>(texture_buf.ptr);
|
28 |
+
uint8_t* mask_ptr = static_cast<uint8_t*>(mask_buf.ptr);
|
29 |
+
|
30 |
+
int vtx_num = vtx_pos_buf.shape[0];
|
31 |
+
float* vtx_pos_ptr = static_cast<float*>(vtx_pos_buf.ptr);
|
32 |
+
float* vtx_uv_ptr = static_cast<float*>(vtx_uv_buf.ptr);
|
33 |
+
int* pos_idx_ptr = static_cast<int*>(pos_idx_buf.ptr);
|
34 |
+
int* uv_idx_ptr = static_cast<int*>(uv_idx_buf.ptr);
|
35 |
+
|
36 |
+
vector<float> vtx_mask(vtx_num, 0.0f);
|
37 |
+
vector<vector<float>> vtx_color(vtx_num, vector<float>(texture_channel, 0.0f));
|
38 |
+
vector<int> uncolored_vtxs;
|
39 |
+
|
40 |
+
vector<vector<int>> G(vtx_num);
|
41 |
+
|
42 |
+
for (int i = 0; i < uv_idx_buf.shape[0]; ++i) {
|
43 |
+
for (int k = 0; k < 3; ++k) {
|
44 |
+
int vtx_uv_idx = uv_idx_ptr[i * 3 + k];
|
45 |
+
int vtx_idx = pos_idx_ptr[i * 3 + k];
|
46 |
+
int uv_v = round(vtx_uv_ptr[vtx_uv_idx * 2] * (texture_width - 1));
|
47 |
+
int uv_u = round((1.0 - vtx_uv_ptr[vtx_uv_idx * 2 + 1]) * (texture_height - 1));
|
48 |
+
|
49 |
+
if (mask_ptr[uv_u * texture_width + uv_v] > 0) {
|
50 |
+
vtx_mask[vtx_idx] = 1.0f;
|
51 |
+
for (int c = 0; c < texture_channel; ++c) {
|
52 |
+
vtx_color[vtx_idx][c] = texture_ptr[(uv_u * texture_width + uv_v) * texture_channel + c];
|
53 |
+
}
|
54 |
+
}else{
|
55 |
+
uncolored_vtxs.push_back(vtx_idx);
|
56 |
+
}
|
57 |
+
|
58 |
+
G[pos_idx_ptr[i * 3 + k]].push_back(pos_idx_ptr[i * 3 + (k + 1) % 3]);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
int smooth_count = 2;
|
63 |
+
int last_uncolored_vtx_count = 0;
|
64 |
+
while (smooth_count>0) {
|
65 |
+
int uncolored_vtx_count = 0;
|
66 |
+
|
67 |
+
for (int vtx_idx : uncolored_vtxs) {
|
68 |
+
|
69 |
+
vector<float> sum_color(texture_channel, 0.0f);
|
70 |
+
float total_weight = 0.0f;
|
71 |
+
|
72 |
+
array<float, 3> vtx_0 = {vtx_pos_ptr[vtx_idx * 3],
|
73 |
+
vtx_pos_ptr[vtx_idx * 3 + 1], vtx_pos_ptr[vtx_idx * 3 + 2]};
|
74 |
+
for (int connected_idx : G[vtx_idx]) {
|
75 |
+
if (vtx_mask[connected_idx] > 0) {
|
76 |
+
array<float, 3> vtx1 = {vtx_pos_ptr[connected_idx * 3],
|
77 |
+
vtx_pos_ptr[connected_idx * 3 + 1], vtx_pos_ptr[connected_idx * 3 + 2]};
|
78 |
+
float dist_weight = 1.0f / max(sqrt(pow(vtx_0[0] - vtx1[0], 2) + pow(vtx_0[1] - vtx1[1], 2) + \
|
79 |
+
pow(vtx_0[2] - vtx1[2], 2)), 1E-4);
|
80 |
+
dist_weight = dist_weight * dist_weight;
|
81 |
+
for (int c = 0; c < texture_channel; ++c) {
|
82 |
+
sum_color[c] += vtx_color[connected_idx][c] * dist_weight;
|
83 |
+
}
|
84 |
+
total_weight += dist_weight;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
if (total_weight > 0.0f) {
|
89 |
+
for (int c = 0; c < texture_channel; ++c) {
|
90 |
+
vtx_color[vtx_idx][c] = sum_color[c] / total_weight;
|
91 |
+
}
|
92 |
+
vtx_mask[vtx_idx] = 1.0f;
|
93 |
+
} else {
|
94 |
+
uncolored_vtx_count++;
|
95 |
+
}
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
if(last_uncolored_vtx_count==uncolored_vtx_count){
|
100 |
+
smooth_count--;
|
101 |
+
}else{
|
102 |
+
smooth_count++;
|
103 |
+
}
|
104 |
+
last_uncolored_vtx_count = uncolored_vtx_count;
|
105 |
+
}
|
106 |
+
|
107 |
+
// Create new arrays for the output
|
108 |
+
py::array_t<float> new_texture(texture_buf.size);
|
109 |
+
py::array_t<uint8_t> new_mask(mask_buf.size);
|
110 |
+
|
111 |
+
auto new_texture_buf = new_texture.request();
|
112 |
+
auto new_mask_buf = new_mask.request();
|
113 |
+
|
114 |
+
float* new_texture_ptr = static_cast<float*>(new_texture_buf.ptr);
|
115 |
+
uint8_t* new_mask_ptr = static_cast<uint8_t*>(new_mask_buf.ptr);
|
116 |
+
// Copy original texture and mask to new arrays
|
117 |
+
std::copy(texture_ptr, texture_ptr + texture_buf.size, new_texture_ptr);
|
118 |
+
std::copy(mask_ptr, mask_ptr + mask_buf.size, new_mask_ptr);
|
119 |
+
|
120 |
+
for (int face_idx = 0; face_idx < uv_idx_buf.shape[0]; ++face_idx) {
|
121 |
+
for (int k = 0; k < 3; ++k) {
|
122 |
+
int vtx_uv_idx = uv_idx_ptr[face_idx * 3 + k];
|
123 |
+
int vtx_idx = pos_idx_ptr[face_idx * 3 + k];
|
124 |
+
|
125 |
+
if (vtx_mask[vtx_idx] == 1.0f) {
|
126 |
+
int uv_v = round(vtx_uv_ptr[vtx_uv_idx * 2] * (texture_width - 1));
|
127 |
+
int uv_u = round((1.0 - vtx_uv_ptr[vtx_uv_idx * 2 + 1]) * (texture_height - 1));
|
128 |
+
|
129 |
+
for (int c = 0; c < texture_channel; ++c) {
|
130 |
+
new_texture_ptr[(uv_u * texture_width + uv_v) * texture_channel + c] = vtx_color[vtx_idx][c];
|
131 |
+
}
|
132 |
+
new_mask_ptr[uv_u * texture_width + uv_v] = 255;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
// Reshape the new arrays to match the original texture and mask shapes
|
138 |
+
new_texture.resize({texture_height, texture_width, 3});
|
139 |
+
new_mask.resize({texture_height, texture_width});
|
140 |
+
return std::make_pair(new_texture, new_mask);
|
141 |
+
}
|
142 |
+
|
143 |
+
|
144 |
+
std::pair<py::array_t<float>, py::array_t<uint8_t>> meshVerticeInpaint(py::array_t<float> texture,
|
145 |
+
py::array_t<uint8_t> mask,
|
146 |
+
py::array_t<float> vtx_pos, py::array_t<float> vtx_uv,
|
147 |
+
py::array_t<int> pos_idx, py::array_t<int> uv_idx, const std::string& method = "smooth") {
|
148 |
+
if (method == "smooth") {
|
149 |
+
return meshVerticeInpaint_smooth(texture, mask, vtx_pos, vtx_uv, pos_idx, uv_idx);
|
150 |
+
} else {
|
151 |
+
throw std::invalid_argument("Invalid method. Use 'smooth' or 'forward'.");
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
PYBIND11_MODULE(mesh_processor, m) {
|
156 |
+
m.def("meshVerticeInpaint", &meshVerticeInpaint, "A function to process mesh",
|
157 |
+
py::arg("texture"), py::arg("mask"),
|
158 |
+
py::arg("vtx_pos"), py::arg("vtx_uv"),
|
159 |
+
py::arg("pos_idx"), py::arg("uv_idx"),
|
160 |
+
py::arg("method") = "smooth");
|
161 |
+
}
|