MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
depthmap.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <algorithm>
11#include <vector>
12#include <list>
13#include <set>
14
15#include "math/defines.h"
16#include "math/matrix.h"
17#include "mve/mesh_info.h"
18#include "mve/depthmap.h"
19#include "mve/mesh_tools.h"
20
23
24void
26 std::vector<bool>& visited,
27 int64_t x, int64_t y, std::size_t thres)
28{
29 typedef std::list<int64_t> PixelQueue;
30 typedef std::set<int64_t> PixelBag;
31
32 int64_t w = dm->width();
33 int64_t h = dm->height();
34 int64_t idx = y * w + x;
35 int64_t max_idx = w * h;
36 int64_t const MAX_ST = -1;
37
38 PixelQueue queue;
39 PixelBag collected;
40
41 queue.push_front(idx);
42 collected.insert(idx);
43
44 /* Process queue of pixel until either thres is reached or no more
45 * pixels are available for growing. If thres is reached, mark as
46 * visited and leave pixels. If no more pixels are available, an
47 * isolated small island has been found and pixels are set to zero.
48 */
49 while (!queue.empty())
50 {
51 /* Take queue element and process... */
52 int64_t cur = queue.back();
53 queue.pop_back();
54
55 /* Define 4-neighborhood for region growing. Y-1, Y+1, X-1, X+1. */
56 int64_t n[4];
57 n[0] = (cur < w ? MAX_ST : cur - w);
58 n[1] = (cur < max_idx - w ? cur + w : MAX_ST);
59 n[2] = (cur % w > 0 ? cur - 1 : MAX_ST);
60 n[3] = (cur % w < w - 1 ? cur + 1 : MAX_ST);
61
62 /* Invalidate unreconstructed neighbors. */
63 for (int i = 0; i < 4; ++i)
64 if (n[i] != MAX_ST && dm->at(n[i], 0) == 0.0f)
65 n[i] = MAX_ST;
66
67 /* Add uncollected pixels to queue. */
68 for (int i = 0; i < 4; ++i)
69 if (n[i] != MAX_ST && collected.find(n[i]) == collected.end())
70 {
71 queue.push_front(n[i]);
72 collected.insert(n[i]);
73 }
74 }
75
76 /* Mark collected region as visited and set depth values to zero
77 * if amount of collected pixels is less than threshold.
78 */
79 for (PixelBag::iterator i = collected.begin(); i != collected.end(); i++)
80 {
81 visited[*i] = true;
82 if (collected.size() < thres)
83 ret->at(*i, 0) = 0.0f;
84 }
85}
86
87/* ---------------------------------------------------------------- */
88
91{
92 FloatImage::Ptr ret(FloatImage::create(*dm));
93
94 int64_t const width = ret->width();
95 int64_t const height = ret->height();
96 std::vector<bool> visited;
97 visited.resize(width * height, false);
98
99 int64_t i = 0;
100 for (int64_t y = 0; y < height; ++y)
101 for (int64_t x = 0; x < width; ++x, ++i)
102 {
103 if (dm->at(i, 0) == 0.0f)
104 continue;
105 if (visited[i])
106 continue;
107 depthmap_cleanup_grow(dm, ret, visited, x, y, thres);
108 }
109
110 return ret;
111}
112
113/* ---------------------------------------------------------------- */
114
115void
117{
118 if (dm == nullptr || cm == nullptr)
119 throw std::invalid_argument("Null depth or confidence map");
120
121 if (dm->width() != cm->width() || dm->height() != cm->height())
122 throw std::invalid_argument("Image dimensions do not match");
123
124 int64_t cnt = dm->get_pixel_amount();
125 for (int64_t i = 0; i < cnt; ++i)
126 if (cm->at(i, 0) <= 0.0f)
127 dm->at(i, 0) = 0.0f;
128}
129
132
133/* ---------------------------------------------------------------- */
134
137
138float
139pixel_footprint (int64_t x, int64_t y, float depth,
140 math::Matrix3f const& invproj)
141{
142 math::Vec3f v = invproj * math::Vec3f
143 ((float)x + 0.5f, (float)y + 0.5f, 1.0f);
144 return invproj[0] * depth / v.norm();
145}
146
147/* ---------------------------------------------------------------- */
148
150pixel_3dpos (int64_t x, int64_t y, float depth,
151 math::Matrix3f const& invproj)
152{
153 math::Vec3f ray = invproj * math::Vec3f
154 ((float)x + 0.5f, (float)y + 0.5f, 1.0f);
155 return ray.normalized() * depth;
156}
157
158/* ---------------------------------------------------------------- */
159
160void
162 FloatImage const* dm, math::Matrix3f const& invproj,
163 std::size_t i, int* tverts)
164{
165 int64_t const width = vidx.width();
168
169 for (int64_t j = 0; j < 3; ++j)
170 {
171 int64_t iidx = i + (tverts[j] % 2) + width * (tverts[j] / 2);
172 int64_t x = iidx % width;
173 int64_t y = iidx / width;
174 if (vidx.at(iidx) == MATH_MAX_UINT)
175 {
176 /* Add vertex for depth pixel. */
177 vidx.at(iidx) = verts.size();
178 float depth = dm->at(iidx, 0);
179 verts.push_back(pixel_3dpos(x, y, depth, invproj));
180 }
181 faces.push_back(vidx.at(iidx));
182 }
183}
184
185/* ---------------------------------------------------------------- */
186
187bool
188dm_is_depthdisc (float* widths, float* depths, float dd_factor, int i1, int i2)
189{
190 /* Find index that corresponds to smaller depth. */
191 int i_min = i1;
192 int i_max = i2;
193 if (depths[i2] < depths[i1])
194 std::swap(i_min, i_max);
195
196 /* Check if indices are a diagonal. */
197 if (i1 + i2 == 3)
198 dd_factor *= MATH_SQRT2;
199
200 /* Check for depth discontinuity. */
201 if (depths[i_max] - depths[i_min] > widths[i_min] * dd_factor)
202 return true;
203
204 return false;
205}
206
207/* ---------------------------------------------------------------- */
208
211 float dd_factor, mve::Image<unsigned int>* vids)
212{
213 if (dm == nullptr)
214 throw std::invalid_argument("Null depthmap given");
215
216 int64_t const width = dm->width();
217 int64_t const height = dm->height();
218
219 /* Prepare triangle mesh. */
220 TriangleMesh::Ptr mesh(TriangleMesh::create());
221
222 /* Generate image that maps image pixels to vertex IDs. */
223 mve::Image<unsigned int> vidx(width, height, 1);
224 vidx.fill(MATH_MAX_UINT);
225
226 /* Iterate over 2x2-blocks in the depthmap and create triangles. */
227 int64_t i = 0;
228 for (int64_t y = 0; y < height - 1; ++y, ++i)
229 {
230 for (int64_t x = 0; x < width - 1; ++x, ++i)
231 {
232 /* Cache the four depth values. */
233 float depths[4] = { dm->at(i, 0), dm->at(i + 1, 0),
234 dm->at(i + width, 0), dm->at(i + width + 1, 0) };
235
236 /* Create a mask representation of the available depth values. */
237 int mask = 0;
238 int pixels = 0;
239 for (int j = 0; j < 4; ++j)
240 if (depths[j] > 0.0f)
241 {
242 mask |= 1 << j;
243 pixels += 1;
244 }
245
246 /* At least three valid depth values are required. */
247 if (pixels < 3)
248 continue;
249
250 /* Possible triangles, vertex indices relative to 2x2 block. */
251 int tris[4][3] = {
252 { 0, 2, 1 }, { 0, 3, 1 }, { 0, 2, 3 }, { 1, 2, 3 }
253 };
254
255 /* Decide which triangles to issue. */
256 int tri[2] = { 0, 0 };
257
258 switch (mask)
259 {
260 case 7: tri[0] = 1; break;
261 case 11: tri[0] = 2; break;
262 case 13: tri[0] = 3; break;
263 case 14: tri[0] = 4; break;
264 case 15:
265 {
266 /* Choose the triangulation with smaller diagonal. */
267 float ddiff1 = std::abs(depths[0] - depths[3]);
268 float ddiff2 = std::abs(depths[1] - depths[2]);
269 if (ddiff1 < ddiff2)
270 { tri[0] = 2; tri[1] = 3; }
271 else
272 { tri[0] = 1; tri[1] = 4; }
273 break;
274 }
275 default: continue;
276 }
277
278 /* Omit depth discontinuity detection if dd_factor is zero. */
279 if (dd_factor > 0.0f)
280 {
281 /* Cache pixel footprints. */
282 float widths[4];
283 for (int j = 0; j < 4; ++j)
284 {
285 if (depths[j] == 0.0f)
286 continue;
287 widths[j] = pixel_footprint(x + (j % 2), y + (j / 2),
288 depths[j], invproj);// w, h, focal_len);
289 }
290
291 /* Check for depth discontinuities. */
292 for (int j = 0; j < 2 && tri[j] != 0; ++j)
293 {
294 int* tv = tris[tri[j] - 1];
295 #define DM_DD_ARGS widths, depths, dd_factor
296 if (dm_is_depthdisc(DM_DD_ARGS, tv[0], tv[1])) tri[j] = 0;
297 if (dm_is_depthdisc(DM_DD_ARGS, tv[1], tv[2])) tri[j] = 0;
298 if (dm_is_depthdisc(DM_DD_ARGS, tv[2], tv[0])) tri[j] = 0;
299 }
300 }
301
302 /* Build triangles. */
303 for (int j = 0; j < 2; ++j)
304 {
305 if (tri[j] == 0) continue;
306 #define DM_MAKE_TRI_ARGS mesh.get(), vidx, dm.get(), invproj, i
307 dm_make_triangle(DM_MAKE_TRI_ARGS, tris[tri[j] - 1]);
308 }
309 }
310 }
311
312 /* Provide the vertex ID mapping if requested. */
313 if (vids != nullptr)
314 std::swap(vidx, *vids);
315
316 return mesh;
317}
318
319/* ---------------------------------------------------------------- */
320
323 math::Matrix3f const& invproj, float dd_factor,
324 mve::Image<unsigned int>* vertex_ids)
325{
326 if (dm == nullptr)
327 throw std::invalid_argument("Null depthmap given");
328
329 int64_t const width = dm->width();
330 int64_t const height = dm->height();
331
332 if (ci != nullptr && (ci->width() != width || ci->height() != height))
333 throw std::invalid_argument("Color image dimension mismatch");
334
335 /* Triangulate depth map. */
338 mesh = mve::geom::depthmap_triangulate(dm, invproj, dd_factor, &vids);
339
340 if (ci == nullptr)
341 return mesh;
342
343 /* Use vertex index mapping to color the mesh. */
344 mve::TriangleMesh::ColorList& colors(mesh->get_vertex_colors());
345 mve::TriangleMesh::VertexList const& verts(mesh->get_vertices());
346 colors.resize(verts.size());
347
348 int64_t num_pixel = vids.get_pixel_amount();
349 for (int64_t i = 0; i < num_pixel; ++i)
350 {
351 if (vids[i] == MATH_MAX_UINT)
352 continue;
353
354 math::Vec4f color(ci->at(i, 0), 0.0f, 0.0f, 255.0f);
355 if (ci->channels() >= 3)
356 {
357 color[1] = ci->at(i, 1);
358 color[2] = ci->at(i, 2);
359 }
360 else
361 {
362 color[1] = color[2] = color[0];
363 }
364 colors[vids[i]] = color / 255.0f;
365 }
366
367 /* Provide the vertex ID mapping if requested. */
368 if (vertex_ids != nullptr)
369 std::swap(vids, *vertex_ids);
370
371 return mesh;
372}
373
374/* ---------------------------------------------------------------- */
375
378 CameraInfo const& cam, float dd_factor,
379 mve::Image<unsigned int>* vertex_ids)
380{
381 if (dm == nullptr)
382 throw std::invalid_argument("Null depthmap given");
383 if (cam.flen == 0.0f)
384 throw std::invalid_argument("Invalid camera given");
385
386 /* Triangulate depth map. */
387 math::Matrix3f invproj;
388 cam.fill_inverse_calibration(*invproj, dm->width(), dm->height());
390 mesh = mve::geom::depthmap_triangulate(dm, ci, invproj, dd_factor, vertex_ids);
391
392 /* Transform mesh to world coordinates. */
393 math::Matrix4f ctw;
394 cam.fill_cam_to_world(*ctw);
395 mve::geom::mesh_transform(mesh, ctw);
396 mesh->recalc_normals(false, true); // Remove this?
397
398 return mesh;
399}
400
401/* ---------------------------------------------------------------- */
402
403bool
405 math::Vec3f const& v2, math::Vec3f const& v3)
406{
407 float const angle_threshold = MATH_DEG2RAD(15.0f);
408 /* Depth discontinuity detection based on minimal angle in triangle. */
409 math::Vec3f e[3] = { (v2 - v1).normalized(),
410 (v3 - v2).normalized(), (v1 - v3).normalized() };
411 float min_angle = angle_threshold;
412 for (int i = 0; i < 3; ++i)
413 min_angle = std::min(min_angle, std::acos(e[i].dot(-e[(i + 1) % 3])));
414 //std::cout << "Min angle is " << MATH_RAD2DEG(min_angle) << ", "
415 // << (min_angle < ANGLE_THRES) << std::endl;
416 return min_angle < angle_threshold;
417}
418
419void
421{
422 if (mesh == nullptr)
423 throw std::invalid_argument("Null mesh given");
424
425 int64_t w = grid.width();
426 int64_t h = grid.height();
427
428 TriangleMesh::VertexList const& verts(mesh->get_vertices());
429 TriangleMesh::FaceList& faces(mesh->get_faces());
430
431 for (int64_t y = 0; y < h - 1; ++y)
432 for (int64_t x = 0; x < w - 1; ++x)
433 {
434 int64_t i = y * w + x;
435
436 unsigned int vid[4] = { grid[i], grid[i + 1],
437 grid[i + w], grid[i + w + 1] };
438
439 /* Create a mask representation of the available indices. */
440 int mask = 0;
441 int indices = 0;
442 for (int j = 0; j < 4; ++j)
443 if (vid[j] != static_cast<unsigned int>(-1))
444 {
445 mask |= 1 << j;
446 indices += 1;
447 }
448
449 /* At least three valid depth values are required. */
450 if (indices < 3)
451 continue;
452
453 /* Decide which triangles to issue.
454 * Triangle 1: (0,2,1), 2: (0,3,1), 3: (0,2,3), 4: (1,2,3) */
455 int tri[2] = { 0, 0 };
456
457 switch (mask)
458 {
459 case 7: tri[0] = 1; break;
460 case 11: tri[0] = 2; break;
461 case 13: tri[0] = 3; break;
462 case 14: tri[0] = 4; break;
463 case 15:
464 {
465 /* Choose the triangulation with smaller diagonal. */
466 if ((verts[vid[0]] - verts[vid[3]]).square_norm() <
467 (verts[vid[1]] - verts[vid[2]]).square_norm())
468 { tri[0] = 2; tri[1] = 3; }
469 else
470 { tri[0] = 1; tri[1] = 4; }
471 break;
472 }
473 default: continue;
474 }
475
476 /* Check for depth discontinuities and issue triangles. */
477 for (int j = 0; j < 2; ++j)
478 {
479 switch (tri[j])
480 {
481#define VERT(id) verts[vid[id]]
482#define DEPTHDISC(a,b,c) dm_is_depth_disc(VERT(a), VERT(b), VERT(c))
483#define ADDTRI(a,c,b) faces.push_back(vid[a]); faces.push_back(vid[b]); faces.push_back(vid[c])
484 case 1: if (!DEPTHDISC(0,2,1)) { ADDTRI(0,2,1); } break;
485 case 2: if (!DEPTHDISC(0,3,1)) { ADDTRI(0,3,1); } break;
486 case 3: if (!DEPTHDISC(0,2,3)) { ADDTRI(0,2,3); } break;
487 case 4: if (!DEPTHDISC(1,2,3)) { ADDTRI(1,2,3); } break;
488 default: break;
489 }
490 }
491 }
492}
493
494/* ---------------------------------------------------------------- */
495
496void
498{
499 if (mesh == nullptr)
500 throw std::invalid_argument("Null mesh given");
501
502 if (iterations < 0)
503 throw std::invalid_argument("Invalid amount of iterations");
504
505 if (iterations == 0)
506 return;
507
508 TriangleMesh::ConfidenceList& confs(mesh->get_vertex_confidences());
509 TriangleMesh::VertexList const& verts(mesh->get_vertices());
510 confs.clear();
511 confs.resize(verts.size(), 1.0f);
512
513 /* Find boundary vertices and remember them. */
514 std::vector<std::size_t> vidx;
515 MeshInfo mesh_info(mesh);
516
517 for (std::size_t i = 0; i < mesh_info.size(); ++i)
518 {
519 if (mesh_info[i].vclass == MeshInfo::VERTEX_CLASS_BORDER)
520 vidx.push_back(i);
521 }
522
523 /* Iteratively expand the current region and update confidences. */
524 for (int current = 0; current < iterations; ++current)
525 {
526 /* Calculate confidence for that iteration. */
527 float conf = (float)current / (float)iterations;
528 //conf = math::algo::fastpow(conf, 3);
529
530 /* Assign current confidence to all vertices. */
531 for (std::size_t i = 0; i < vidx.size(); ++i)
532 confs[vidx[i]] = conf;
533
534 /* Replace vertex list with adjacent vertices. */
535 std::vector<std::size_t> cvidx;
536 std::swap(vidx, cvidx);
537 for (std::size_t i = 0; i < cvidx.size(); ++i)
538 {
539 MeshInfo::VertexInfo info = mesh_info[cvidx[i]];
540 for (std::size_t j = 0; j < info.verts.size(); ++j)
541 if (confs[info.verts[j]] == 1.0f)
542 vidx.push_back(info.verts[j]);
543 }
544 }
545}
546
547/* ---------------------------------------------------------------- */
548
549void
551{
552 if (mesh == nullptr)
553 throw std::invalid_argument("Null mesh given");
554
555 if (iterations < 0)
556 throw std::invalid_argument("Invalid amount of iterations");
557
558 if (iterations == 0)
559 return;
560
561 TriangleMesh::FaceList& faces(mesh->get_faces());
562 std::vector<bool> delete_list;
563 delete_list.resize(faces.size(), false);
564
565 /* Iteratively invalidate triangles at the boundary. */
566 for (int iter = 0; iter < iterations; ++iter)
567 {
568 MeshInfo mesh_info(mesh);
569 for (std::size_t i = 0; i < mesh_info.size(); ++i)
570 {
571 MeshInfo::VertexInfo const& info(mesh_info[i]);
572 if (info.vclass == MeshInfo::VERTEX_CLASS_BORDER)
573 for (std::size_t j = 0; j < info.faces.size(); ++j)
574 for (int k = 0; k < 3; ++k)
575 {
576 unsigned int fidx = info.faces[j] * 3 + k;
577 faces[fidx] = 0;
578 delete_list[fidx] = true;
579 }
580 }
581 }
582
583 /* Remove invalidated faces. */
584 math::algo::vector_clean(delete_list, &faces);
585}
586
Matrix class for arbitrary dimensions and types.
Definition matrix.h:54
Vector class for arbitrary dimensions and types.
Definition vector.h:87
T norm(void) const
Computes the norm (length) of the vector.
Definition vector.h:434
Vector< T, N > normalized(void) const
Returns a normalized copy of self.
Definition vector.h:456
int64_t height(void) const
Returns the height of the image.
Definition image_base.h:207
int64_t width(void) const
Returns the width of the image.
Definition image_base.h:201
Multi-channel image class of arbitrary but homogenous data type.
Definition image.h:40
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
std::shared_ptr< Image< T > const > ConstPtr
Definition image.h:43
T const & at(int64_t index) const
Linear indexing of image data.
Definition image.h:307
std::vector< math::Vec3f > VertexList
Definition mesh.h:33
VertexList const & get_vertices(void) const
Returns the mesh vertices.
Definition mesh.h:199
std::vector< float > ConfidenceList
Definition mesh.h:35
std::vector< math::Vec4f > ColorList
Definition mesh.h:34
std::size_t size(void) const
Definition mesh_info.h:128
Triangle mesh representation.
Definition mesh.h:90
std::shared_ptr< TriangleMesh > Ptr
Definition mesh.h:92
std::vector< VertexID > FaceList
Definition mesh.h:97
FaceList const & get_faces(void) const
Returns the triangle indices.
Definition mesh.h:331
int64_t get_pixel_amount(void) const
Returns the amount of pixels in the image (w * h).
Definition image_base.h:500
void fill(T const &value)
Fills the data with a constant value.
Definition image_base.h:423
#define DM_DD_ARGS
#define ADDTRI(a, c, b)
#define DM_MAKE_TRI_ARGS
#define DEPTHDISC(a, b, c)
#define MATH_SQRT2
Definition defines.h:49
#define MATH_DEG2RAD(x)
Definition defines.h:78
#define MATH_MAX_UINT
Definition defines.h:111
#define MVE_IMAGE_NAMESPACE_END
Definition defines.h:17
#define MVE_NAMESPACE_BEGIN
Definition defines.h:13
#define MVE_IMAGE_NAMESPACE_BEGIN
Definition defines.h:16
#define MVE_NAMESPACE_END
Definition defines.h:14
#define MVE_GEOM_NAMESPACE_END
Definition defines.h:20
#define MVE_GEOM_NAMESPACE_BEGIN
Definition defines.h:19
void vector_clean(std::vector< bool > const &delete_list, std::vector< T > *vector)
Erases all elements from 'vector' that are marked with 'true' in 'delete_list'.
Definition algo.h:166
Vector< float, 3 > Vec3f
Definition vector.h:31
void dm_make_triangle(TriangleMesh *mesh, mve::Image< unsigned int > &vidx, FloatImage const *dm, math::Matrix3f const &invproj, std::size_t i, int *tverts)
Definition depthmap.cc:161
void rangegrid_triangulate(Image< unsigned int > const &grid, TriangleMesh::Ptr mesh)
Algorithm to triangulate range grids.
Definition depthmap.cc:420
void mesh_transform(mve::TriangleMesh::Ptr mesh, math::Matrix3f const &rot)
Transforms the vertices and normals of the mesh using the specified rotation matrix.
Definition mesh_tools.cc:46
math::Vec3f pixel_3dpos(int64_t x, int64_t y, float depth, math::Matrix3f const &invproj)
Function that calculates the pixel 3D position in camera coordinates for pixel (x,...
Definition depthmap.cc:150
TriangleMesh::Ptr depthmap_triangulate(FloatImage::ConstPtr dm, math::Matrix3f const &invproj, float dd_factor, mve::Image< unsigned int > *vids)
Algorithm to triangulate depth maps.
Definition depthmap.cc:210
void depthmap_mesh_confidences(TriangleMesh::Ptr mesh, int iterations)
Algorithm to assign per-vertex confidence values to vertices of a triangulated depth map.
Definition depthmap.cc:497
bool dm_is_depth_disc(math::Vec3f const &v1, math::Vec3f const &v2, math::Vec3f const &v3)
Definition depthmap.cc:404
bool dm_is_depthdisc(float *widths, float *depths, float dd_factor, int i1, int i2)
Definition depthmap.cc:188
float pixel_footprint(int64_t x, int64_t y, float depth, math::Matrix3f const &invproj)
Function that calculates the pixel footprint (pixel width) in 3D coordinates for pixel (x,...
Definition depthmap.cc:139
void depthmap_mesh_peeling(TriangleMesh::Ptr mesh, int iterations)
Algorithm that peels away triangles at the mesh bounary of a triangulated depth map.
Definition depthmap.cc:550
void depthmap_confidence_clean(FloatImage::Ptr dm, FloatImage::ConstPtr cm)
Removes the backplane according to the confidence map IN-PLACE.
Definition depthmap.cc:116
FloatImage::Ptr depthmap_cleanup(FloatImage::ConstPtr dm, int64_t thres)
Algorithm to clean small confident islands in the depth maps.
Definition depthmap.cc:90
void depthmap_cleanup_grow(FloatImage::ConstPtr dm, FloatImage::Ptr ret, std::vector< bool > &visited, int64_t x, int64_t y, std::size_t thres)
Definition depthmap.cc:25
void swap(mve::Image< T > &a, mve::Image< T > &b)
Specialization of std::swap for efficient image swapping.
Definition image.h:478
Per-view camera information with various helper functions.
Definition camera.h:24
float flen
Focal length.
Definition camera.h:156
void fill_inverse_calibration(float *mat, float width, float height) const
Stores 3x3 inverse calibration (or inverse projection) matrix.
Definition camera.cc:180
void fill_cam_to_world(float *mat) const
Stores camera to world 4x4 matrix in array pointed to by mat.
Definition camera.cc:83
Per-vertex classification and adjacency information.
Definition mesh_info.h:43
AdjacentVertices verts
Definition mesh_info.h:45