9#include <ufo/map/color/map.hpp>
10#include <ufo/map/occupancy/map.hpp>
11#include <ufo/map/ufomap.hpp>
12#include <ufo/numeric/trans2.hpp>
13#include <ufo/vision/image.hpp>
15#include <ufo/execution/execution.hpp>
16#include <ufo/map/distance/map.hpp>
17#include <ufo/pcl/cloud.hpp>
18#include <ufo/vision/camera.hpp>
35#include <opencv2/core.hpp>
36#include <opencv2/highgui.hpp>
39#include <ufo/happly.h>
43static Color color(
double value,
double min_value,
double max_value,
double color_factor)
48 value = std::clamp((value - min_value) / (max_value - min_value), 0.0, 1.0);
50 double h = (1 - value) * color_factor;
54 int const i = std::floor(h);
56 double const f = (i & 1) ? h - i : 1 - (h - i);
58 double const m = v * (1 - s);
60 double const n = v * (1 - s * f);
64 case 0:
return Color(255 * m, 255 * n, 255 * v);
65 case 1:
return Color(255 * m, 255 * v, 255 * n);
66 case 2:
return Color(255 * n, 255 * v, 255 * m);
67 case 3:
return Color(255 * v, 255 * n, 255 * m);
68 case 4:
return Color(255 * v, 255 * m, 255 * n);
69 case 5:
return Color(255 * n, 255 * m, 255 * v);
70 default:
return Color(255 * 0.5, 255 * 0.5, 255 * 1);
74int main(
int argc,
char* argv[])
89 Vec3f max(-100000, -100000, -100000);
91 happly::PLYData ply_in(RESOURCE_DIR
"/scene0000_00_vh_clean.ply");
92 auto v_pos = ply_in.getVertexPositions();
93 auto v_col = ply_in.getVertexColors();
94 auto f_ind = ply_in.getFaceIndices<std::size_t>();
95 std::unordered_map<QuadCode, std::pair<std::vector<Vec2f>, std::vector<Color>>> points;
97 auto const t1 = std::chrono::high_resolution_clock::now();
98 for (
auto f : f_ind) {
100 Vec3f(v_pos[f[1]][0], v_pos[f[1]][1], v_pos[f[1]][2]),
101 Vec3f(v_pos[f[2]][0], v_pos[f[2]][1], v_pos[f[2]][2]));
103 std::array c{Color(v_col[f[0]][0], v_col[f[0]][1], v_col[f[0]][2]),
104 Color(v_col[f[1]][0], v_col[f[1]][1], v_col[f[1]][2]),
105 Color(v_col[f[2]][0], v_col[f[2]][1], v_col[f[2]][2])};
107 for (std::size_t i{}; 3 > i; ++i) {
111 auto& [
a,
b] = points[map.code(
Vec2f(t[i]))];
112 a.emplace_back(
Vec2f(t[i]));
113 b.emplace_back(c[i]);
118 auto const t2 = std::chrono::high_resolution_clock::now();
119 std::chrono::duration<double, std::milli>
const preprocess_ms = t2 - t1;
121 std::cout << std::setw(28) << std::left <<
"Preprocess: " << preprocess_ms.count()
124 auto f = std::async(std::launch::async, [&map, &points]() {
125 auto const t1 = std::chrono::high_resolution_clock::now();
127 for (
auto const& [code, elem] : points) {
128 auto const& [points, colors] = elem;
129 map.occupancySet(code, 1.0,
false);
130 map.colorSet(code, Color::blend(colors, ColorBlendingMode::SQ_MEAN),
false);
131 Vec2f p = std::accumulate(points.begin(), points.end(),
Vec2f());
133 map.distanceSet(code, p, points.size(),
false);
136 auto const t2 = std::chrono::high_resolution_clock::now();
138 map.propagateModified();
140 auto const t3 = std::chrono::high_resolution_clock::now();
141 std::chrono::duration<double, std::milli>
const set_ms = t2 - t1;
142 std::chrono::duration<double, std::milli>
const propagate_ms = t3 - t2;
143 std::chrono::duration<double, std::milli>
const total_ms = t3 - t1;
145 std::cout << std::setw(28) << std::left <<
"Set: " << set_ms.count()
147 std::cout << std::setw(28) << std::left <<
"Propagate: " << propagate_ms.count()
149 std::cout << std::setw(28) << std::left <<
"Total: " << total_ms.count()
184 auto inner_f = [&map](
auto node,
Ray2 ,
float ) ->
bool {
189 auto hit_f = [&map](
auto node,
Ray2 ray,
190 float distance) -> std::pair<
bool, std::pair<Vec2f, Color>> {
191 float max_distance = 7.0f;
195 auto d = map.distance<
false>(ray.origin);
196 Color c(255 * d / max_distance, 255 * d / max_distance, 255 * d / max_distance);
198 return std::make_pair(
true, std::make_pair(map.center(node), c));
222 camera.vertical_fov =
radians(60.0f);
223 camera.near_clip = 0.30310887f;
224 camera.far_clip = 4.7810888f;
225 camera.projection_type = ProjectionType::PERSPECTIVE;
227 std::size_t rows = 720;
228 std::size_t cols = 1280;
230 std::size_t output_rows = rows / 1;
231 std::size_t output_cols = cols / 1;
238 std::vector<std::size_t> row_idx(rows);
239 std::iota(row_idx.begin(), row_idx.end(), 0);
241 std::vector<std::size_t> output_row_idx(output_rows);
242 std::iota(output_row_idx.begin(), output_row_idx.end(), 0);
246 cv::Mat img(output_rows, output_cols * 2, CV_8UC3);
248 cv::Mat rgb(output_rows, output_cols, CV_8UC3);
249 cv::Mat mask(output_rows, output_cols, CV_8UC3);
251 double ufo_total_ms{};
252 double interpolate_total_ms{};
253 std::size_t iterations{};
255 float angle_x = 0.0f;
256 float angle_y = -0.0f;
259 for (iterations = 1;
true; ++iterations) {
260 auto const t1 = std::chrono::high_resolution_clock::now();
262 Vec3f eye(5.17831f, 4.56809f, 5.571f);
263 Vec3f target(5.17831f, 4.568091f, 0.0f);
266 float cx = std::cos(angle_x);
267 float cy = std::cos(angle_y);
268 float sx = std::sin(angle_x);
269 float sy = std::sin(angle_y);
270 Vec3f offset =
Vec3f(sy * cx, sy * sx, cy) * std::exp(-zoom);
275 camera.up =
Mat3f(roll_mat) * camera.up;
276 std::cout << roll_mat <<
'\n';
277 std::cout << camera.up <<
'\n';
278 camera.lookAt(eye, target);
283 execution::par, camera, image,
288 [&map, &max_dist](
auto node,
Ray3 ray,
289 float distance) -> std::pair<
bool, std::pair<Color, Color>> {
290 float max_distance = 9.07359f;
292 if (map.isLeaf(node)) {
293 float d = max_distance;
294 float d2 = max_distance;
306 max_dist = std::max(max_dist, d);
307 Color c = color(d, 0.0, max_distance, 0.7);
308 Color c2 = color(d2, 0.0, max_distance, 0.7);
311 c2 = map.color(node);
314 return std::make_pair(
true, std::make_pair(c2, c));
316 return std::make_pair(
false, std::make_pair(Color{}, Color{}));
319 std::make_pair(Color{}, Color{}));
321 std::cout << max_dist <<
'\n';
323 auto const t2 = std::chrono::high_resolution_clock::now();
325 double row_scale = image.rows() /
static_cast<double>(output_rows);
326 double col_scale = image.cols() /
static_cast<double>(output_cols);
328 auto f = [&](std::size_t i) {
329 for (std::size_t j{}; j < output_cols; ++j) {
330 std::size_t i_scaled = std::floor(i * row_scale);
331 std::size_t j_scaled = std::floor(j * col_scale);
332 img.at<cv::Vec3b>(i, j)[2] = image(i_scaled, j_scaled).first.red;
333 img.at<cv::Vec3b>(i, j)[1] = image(i_scaled, j_scaled).first.green;
334 img.at<cv::Vec3b>(i, j)[0] = image(i_scaled, j_scaled).first.blue;
335 img.at<cv::Vec3b>(i, output_cols + j)[2] = image(i_scaled, j_scaled).second.red;
336 img.at<cv::Vec3b>(i, output_cols + j)[1] = image(i_scaled, j_scaled).second.green;
337 img.at<cv::Vec3b>(i, output_cols + j)[0] = image(i_scaled, j_scaled).second.blue;
338 rgb.at<cv::Vec3b>(i, j)[2] = image(i_scaled, j_scaled).first.red;
339 rgb.at<cv::Vec3b>(i, j)[1] = image(i_scaled, j_scaled).first.green;
340 rgb.at<cv::Vec3b>(i, j)[0] = image(i_scaled, j_scaled).first.blue;
341 mask.at<cv::Vec3b>(i, j)[2] = image(i_scaled, j_scaled).first.empty() ? 0 : 255;
342 mask.at<cv::Vec3b>(i, j)[1] = image(i_scaled, j_scaled).first.empty() ? 0 : 255;
343 mask.at<cv::Vec3b>(i, j)[0] = image(i_scaled, j_scaled).first.empty() ? 0 : 255;
348 std::for_each(std::execution::par_unseq, output_row_idx.begin(), output_row_idx.end(),
352#pragma omp parallel for
354 for (std::size_t i = 0; i < output_rows; ++i) {
359 imwrite(
"/home/dduberg/ufo/render/topdown.png", rgb);
360 imwrite(
"/home/dduberg/ufo/render/topdown_mask.png", mask);
363 auto const t3 = std::chrono::high_resolution_clock::now();
364 std::chrono::duration<double, std::milli>
const ufo_ms = t2 - t1;
365 std::chrono::duration<double, std::milli>
const interpolate_ms = t3 - t2;
367 ufo_total_ms += ufo_ms.count();
368 interpolate_total_ms += interpolate_ms.count();
370 std::chrono::duration<double, std::milli>
const total_ms = t3 - t1;
372 std::cout << std::setw(28) << std::left
373 <<
"UFO took: " << (ufo_total_ms / iterations) <<
" ms\n";
374 std::cout << std::setw(28) << std::left
375 <<
"Interpolate took: " << (interpolate_total_ms / iterations) <<
" ms\n";
376 std::cout << std::setw(28) << std::left <<
"Total: "
377 << ((ufo_total_ms + interpolate_total_ms) / iterations) <<
" ms\n";
379 cv::imshow(
"UFOMap Rendered View", img);
381 << std::max(1,
static_cast<int>(1000 * (1.0 / fps) - total_ms.count()))
385 cv::waitKey(std::max(1,
static_cast<int>(1000 * (1.0 / fps) - total_ms.count())));
Image class for storing and manipulating 2D pixel data.
constexpr T radians(T deg) noexcept
Converts degrees to radians.
All vision-related classes and functions.
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
Mat< 4, 4, T > rotate(Mat< 4, 4, T > const &m, T angle, Vec< 3, T > const &v)
Applies an axis-angle rotation to a 4×4 matrix.
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > min(Geometry const &g)
Returns the minimum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
constexpr auto distance(A const &a, B const &b)
Computes the minimum distance between two shapes.
Ray in Dim-dimensional space.
Triangle in Dim-dimensional space.
static constexpr std::size_t size() noexcept
Returns the number of dimensions.