CARLA
Loading...
Searching...
No Matches
test_image.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "test.h"
8
10#include <carla/image/ImageIO.h>
12
13#include <memory>
14
15template <typename ViewT, typename PixelT>
16struct TestImage {
17 using pixel_type = PixelT;
18 std::unique_ptr<PixelT[]> data;
19 ViewT view;
20};
21
22template <typename PixelT>
23static auto MakeTestImage(size_t width, size_t height) {
24 auto data = std::make_unique<PixelT[]>(sizeof(PixelT) * width * height);
25 auto view = boost::gil::interleaved_view(
26 width,
27 height,
28 reinterpret_cast<PixelT*>(data.get()),
29 static_cast<long>(sizeof(PixelT) * width));
30 return TestImage<decltype(view), PixelT>{std::move(data), view};
31}
32
33#ifndef PLATFORM_WINDOWS
34TEST(image, support) {
35 using namespace carla::image::io;
36 carla::logging::log("PNG support =", has_png_support());
37 carla::logging::log("JPEG support =", has_jpeg_support());
38 carla::logging::log("TIFF support =", has_tiff_support());
39}
40#endif // PLATFORM_WINDOWS
41
42TEST(image, depth) {
43#ifndef NDEBUG
44 carla::log_info("This test only happens in release (too slow).");
45#else
46 using namespace boost::gil;
47 using namespace carla::image;
48
49 constexpr auto width = 256 * 256 * 256;
50 constexpr auto height = 1u;
51
52 auto img_bgra8 = MakeTestImage<bgra8_pixel_t>(width, height);
53 auto img_gray8 = MakeTestImage<gray8_pixel_t>(width, height);
54
55 auto depth_view = ImageView::MakeColorConvertedView(
56 img_bgra8.view,
58 auto ldepth_view = ImageView::MakeColorConvertedView(
59 img_bgra8.view,
61
62 auto p = *depth_view.begin();
63 static_assert(std::is_same<decltype(p), gray8_pixel_t>::value, "Not the pixel I was looking for!");
64 auto lp = *ldepth_view.begin();
65 static_assert(std::is_same<decltype(lp), gray8_pixel_t>::value, "Not the pixel I was looking for!");
66
67 ASSERT_EQ(depth_view.size(), img_bgra8.view.size());
68 ASSERT_EQ(ldepth_view.size(), img_bgra8.view.size());
69
70 {
71 auto it_bgra8 = img_bgra8.view.begin();
72 auto it_gray8 = img_gray8.view.begin();
73
74 for (auto r = 0u; r < 256u; ++r) {
75 for (auto g = 0u; g < 256u; ++g) {
76 for (auto b = 0u; b < 256u; ++b) {
77 decltype(img_bgra8)::pixel_type &p_bgra8 = *it_bgra8;
78 decltype(img_gray8)::pixel_type &p_gray8 = *it_gray8;
79 get_color(p_bgra8, red_t()) = static_cast<uint8_t>(r);
80 get_color(p_bgra8, green_t()) = static_cast<uint8_t>(g);
81 get_color(p_bgra8, blue_t()) = static_cast<uint8_t>(b);
82 const float depth = static_cast<float>(r + (g * 256) + (b * 256 * 256));
83 const float normalized = depth / static_cast<float>(256 * 256 * 256 - 1);
84 p_gray8[0] = static_cast<uint8_t>(255.0 * normalized);
85
86 ++it_bgra8;
87 ++it_gray8;
88 }
89 }
90 }
91 }
92
93 auto img_copy = MakeTestImage<bgra8_pixel_t>(width, height);
94 ImageConverter::CopyPixels(img_bgra8.view, img_copy.view);
95 ImageConverter::ConvertInPlace(img_copy.view, ColorConverter::LogarithmicDepth());
96
97 {
98 auto it_gray8 = img_gray8.view.begin();
99 auto it_depth = depth_view.begin();
100 auto it_ldepth = ldepth_view.begin();
101 auto it_copy = img_copy.view.begin();
102
103 for (auto i = 0u; i < width; ++i) {
104 auto p_gray8 = *it_gray8;
105 auto p_depth = *it_depth;
106 auto p_ldepth = *it_ldepth;
107 auto p_copy = *it_copy;
108 ASSERT_NEAR(int(p_depth[0]), int(p_gray8[0]), 1)
109 << "at XY(" << i << ",0)";
110 decltype(p_copy) ld;
111 color_convert(p_ldepth, ld);
112 ASSERT_EQ(ld, p_copy)
113 << "at XY(" << i << ",0)";
114 ++it_gray8;
115 ++it_depth;
116 ++it_ldepth;
117 ++it_copy;
118 }
119 }
120#endif // NDEBUG
121}
122
123TEST(image, semantic_segmentation) {
124 using namespace boost::gil;
125 using namespace carla::image;
126
127 constexpr auto width = CityScapesPalette::GetNumberOfTags();
128 constexpr auto height = 1u;
129
130 auto img_bgra8 = MakeTestImage<bgra8_pixel_t>(width, height);
131 auto img_ss = MakeTestImage<rgb8_pixel_t>(width, height);
132
133 auto semseg_view = ImageView::MakeColorConvertedView(
134 img_bgra8.view,
136
137 auto p = *semseg_view.begin();
138 static_assert(std::is_same<decltype(p), bgra8_pixel_t>::value, "Not the pixel I was looking for!");
139
140 ASSERT_EQ(semseg_view.size(), img_bgra8.view.size());
141
142 {
143 auto it_bgra8 = img_bgra8.view.begin();
144 auto it_ss = img_ss.view.begin();
145
146 for (auto tag = 0u; tag < width; ++tag) {
147 decltype(img_bgra8)::pixel_type &p_bgra8 = *it_bgra8;
148 get_color(p_bgra8, red_t()) = static_cast<uint8_t>(tag);
149 get_color(p_bgra8, green_t()) = 0u;
150 get_color(p_bgra8, blue_t()) = 0u;
151 decltype(img_ss)::pixel_type &p_ss = *it_ss;
152 auto color = CityScapesPalette::GetColor(static_cast<uint8_t>(tag));
153 get_color(p_ss, red_t()) = color[0u];
154 get_color(p_ss, green_t()) = color[1u];
155 get_color(p_ss, blue_t()) = color[2u];
156 ++it_bgra8;
157 ++it_ss;
158 }
159 }
160
161 auto img_copy = MakeTestImage<rgba8_pixel_t>(width, height);
162 ImageConverter::CopyPixels(img_bgra8.view, img_copy.view);
163 ImageConverter::ConvertInPlace(img_copy.view, ColorConverter::CityScapesPalette());
164
165 {
166 auto it_ss = img_ss.view.begin();
167 auto it_ssv = semseg_view.begin();
168 auto it_copy = img_copy.view.begin();
169
170 for (auto i = 0u; i < width; ++i) {
171 auto p_ssv = *it_ssv;
172 auto p_copy = *it_copy;
173 auto _p_ss = *it_ss;
174 decltype(p_ssv) p_ss;
175 color_convert(_p_ss, p_ss);
176 ASSERT_EQ(p_ssv, p_ss)
177 << "at XY(" << i << ",0)";
178 decltype(p_copy) css;
179 color_convert(p_ssv, css);
180 ASSERT_EQ(p_ssv, p_copy)
181 << "at XY(" << i << ",0)";
182 ++it_ss;
183 ++it_ssv;
184 ++it_copy;
185 }
186 }
187}
static void log(Args &&... args)
Definition Logging.h:59
static void log_info(Args &&... args)
Definition Logging.h:82
std::unique_ptr< PixelT[]> data
PixelT pixel_type
TEST(image, support)
static auto MakeTestImage(size_t width, size_t height)