CARLA
 
载入中...
搜索中...
未找到
test_image.cpp
浏览该文件的文档.
1// Copyright (c) 2017 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 TestImage(TestImage &&) = default;
18 // 定义像素类型别名
19 using pixel_type = PixelT;
20 std::unique_ptr<PixelT[]> data;
21 ViewT view;
22};
23
24template <typename PixelT>
25static auto MakeTestImage(size_t width, size_t height) {
26 // 创建一个动态分配的像素数组
27 auto data = std::make_unique<PixelT[]>(sizeof(PixelT) * width * height);
28 // 创建一个交错视图,用于访问图像数据
29 auto view = boost::gil::interleaved_view(
30 width,
31 height,
32 reinterpret_cast<PixelT*>(data.get()),
33 static_cast<long>(sizeof(PixelT) * width));
34 return TestImage<decltype(view), PixelT>{std::move(data), view};
35}
36// 在非Windows平台下执行的测试用例,用于测试图像格式支持
37#ifndef PLATFORM_WINDOWS
38TEST(image, support){
39 using namespace carla::image::io;
40 // 记录PNG格式是否支持
41 carla::logging::log("PNG support =", has_png_support());
42 // 记录JPEG格式是否支持
43 carla::logging::log("JPEG support =", has_jpeg_support());
44 // 记录TIFF格式是否支持
45 carla::logging::log("TIFF support =", has_tiff_support());
46}
47#endif // PLATFORM_WINDOWS
48// 测试图像深度相关功能的测试用例
49TEST(image, depth) {
50#ifndef NDEBUG
51// 在调试模式下输出提示信息,表示该测试在发布模式下执行(因为在调试模式下太慢)
52 carla::log_info("This test only happens in release (too slow).");
53#else
54 using namespace boost::gil;
55 using namespace carla::image;
56// 定义图像宽度和高度的常量
57 constexpr auto width = 256 * 256 * 256;
58 constexpr auto height = 1u;
59// 创建一个bgra8像素类型的测试图像
60 auto img_bgra8 = MakeTestImage<bgra8_pixel_t>(width, height);
61 // 创建一个gray8像素类型的测试图像
62 auto img_gray8 = MakeTestImage<gray8_pixel_t>(width, height);
63 // 根据bgra8图像视图创建一个深度转换后的视图
64 auto depth_view = ImageView::MakeColorConvertedView(
65 img_bgra8.view,
67 // 根据bgra8图像视图创建一个对数深度转换后的视图
68 auto ldepth_view = ImageView::MakeColorConvertedView(
69 img_bgra8.view,
71 // 获取深度视图的第一个像素,用于类型检查
72 auto p = *depth_view.begin();
73 // 静态断言,确保像素类型符合预期
74 static_assert(std::is_same<decltype(p), gray8_pixel_t>::value, "Not the pixel I was looking for!");
75 // 获取对数深度视图的第一个像素,用于类型检查
76 auto lp = *ldepth_view.begin();
77 // 静态断言,确保像素类型符合预期
78 static_assert(std::is_same<decltype(lp), gray8_pixel_t>::value, "Not the pixel I was looking for!");
79// 断言深度视图和原始bgra8图像视图的大小相同
80 ASSERT_EQ(depth_view.size(), img_bgra8.view.size());
81 // 断言对数深度视图和原始bgra8图像视图的大小相同
82 ASSERT_EQ(ldepth_view.size(), img_bgra8.view.size());
83// 填充bgra8图像和gray8图像的数据
84 {
85 auto it_bgra8 = img_bgra8.view.begin();
86 auto it_gray8 = img_gray8.view.begin();
87
88 for (auto r = 0u; r < 256u; ++r) {
89 for (auto g = 0u; g < 256u; ++g) {
90 for (auto b = 0u; b < 256u; ++b) {
91 // 获取bgra8图像当前像素的引用
92 decltype(img_bgra8)::pixel_type &p_bgra8 = *it_bgra8;
93 // 获取gray8图像当前像素的引用
94 decltype(img_gray8)::pixel_type &p_gray8 = *it_gray8;
95 // 设置bgra8图像当前像素的红色通道值
96 get_color(p_bgra8, red_t()) = static_cast<uint8_t>(r);
97 // 设置bgra8图像当前像素的绿色通道值
98 get_color(p_bgra8, green_t()) = static_cast<uint8_t>(g);
99 // 设置bgra8图像当前像素的蓝色通道值
100 get_color(p_bgra8, blue_t()) = static_cast<uint8_t>(b);
101 // 计算深度值
102 const float depth = r + (g * 256) + (b * 256 * 256);
103 // 计算归一化深度值
104 const float normalized = depth / static_cast<float>(256 * 256 * 256 - 1);
105 // 设置gray8图像当前像素的值
106 p_gray8[0] = static_cast<uint8_t>(255.0 * normalized);
107
108 ++it_bgra8;
109 ++it_gray8;
110 }
111 }
112 }
113 }
114// 创建一个bgra8像素类型的图像副本
115 auto img_copy = MakeTestImage<bgra8_pixel_t>(width, height);
116 // 将原始bgra8图像的数据复制到副本中
117 ImageConverter::CopyPixels(img_bgra8.view, img_copy.view);
118 // 在副本图像上进行对数深度转换
119 ImageConverter::ConvertInPlace(img_copy.view, ColorConverter::LogarithmicDepth());
120 // 比较原始gray8图像、深度视图、对数深度视图和副本图像的数据
121
122 {
123 auto it_gray8 = img_gray8.view.begin();
124 auto it_depth = depth_view.begin();
125 auto it_ldepth = ldepth_view.begin();
126 auto it_copy = img_copy.view.begin();
127
128 for (auto i = 0u; i < width; ++i) {
129 auto p_gray8 = *it_gray8;
130 auto p_depth = *it_depth;
131 auto p_ldepth = *it_ldepth;
132 auto p_copy = *it_copy;
133 // 断言深度视图和gray8图像在当前位置的像素值相近
134 ASSERT_NEAR(int(p_depth[0]), int(p_gray8[0]), 1)
135 << "at XY(" << i << ",0)";
136 decltype(p_copy) ld;
137 color_convert(p_ldepth, ld);
138 // 断言对数深度视图转换后和副本图像在当前位置的像素值相等
139 ASSERT_EQ(ld, p_copy)
140 << "at XY(" << i << ",0)";
141 ++it_gray8;
142 ++it_depth;
143 ++it_ldepth;
144 ++it_copy;
145 }
146 }
147#endif // NDEBUG
148}
149// 测试图像语义分割相关功能的测试用例
150TEST(image, semantic_segmentation) {
151 using namespace boost::gil;
152 using namespace carla::image;
153// 定义图像宽度为CityScapesPalette标签数量,高度为1
154 constexpr auto width = CityScapesPalette::GetNumberOfTags();
155 constexpr auto height = 1u;
156// 创建一个bgra8像素类型的测试图像
157 auto img_bgra8 = MakeTestImage<bgra8_pixel_t>(width, height);
158 // 创建一个rgb8像素类型的测试图像
159 auto img_ss = MakeTestImage<rgb8_pixel_t>(width, height);
160// 根据bgra8图像视图创建一个语义分割转换后的视图
161 auto semseg_view = ImageView::MakeColorConvertedView(
162 img_bgra8.view,
164// 获取语义分割视图的第一个像素,用于类型检查
165 auto p = *semseg_view.begin();
166 // 静态断言,确保像素类型符合预期
167 static_assert(std::is_same<decltype(p), bgra8_pixel_t>::value, "Not the pixel I was looking for!");
168// 断言语义分割视图和原始bgra8图像视图的大小相同
169 ASSERT_EQ(semseg_view.size(), img_bgra8.view.size());
170 // 填充bgra8图像和rgb8图像的数据
171 {
172 auto it_bgra8 = img_bgra8.view.begin();
173 auto it_ss = img_ss.view.begin();
174
175 for (auto tag = 0u; tag < width; ++tag) {
176 decltype(img_bgra8)::pixel_type &p_bgra8 = *it_bgra8;
177 get_color(p_bgra8, red_t()) = static_cast<uint8_t>(tag);
178 get_color(p_bgra8, green_t()) = 0u;
179 get_color(p_bgra8, blue_t()) = 0u;
180 decltype(img_ss)::pixel_type &p_ss = *it_ss;
181 auto color = CityScapesPalette::GetColor(static_cast<uint8_t>(tag));
182 get_color(p_ss, red_t()) = color[0u];
183 get_color(p_ss, green_t()) = color[1u];
184 get_color(p_ss, blue_t()) = color[2u];
185 ++it_bgra8;
186 ++it_ss;
187 }
188 }
189// 创建一个rgba8像素类型的图像副本
190 auto img_copy = MakeTestImage<rgba8_pixel_t>(width, height);
191 // 将原始bgra8图像的数据复制到副本中
192 ImageConverter::CopyPixels(img_bgra8.view, img_copy.view);
193 // 在副本图像上进行语义分割转换
194 ImageConverter::ConvertInPlace(img_copy.view, ColorConverter::CityScapesPalette());
195// 比较原始rgb8图像、语义分割视图和副本图像的数据
196 {
197 auto it_ss = img_ss.view.begin();
198 auto it_ssv = semseg_view.begin();
199 auto it_copy = img_copy.view.begin();
200
201 for (auto i = 0u; i < width; ++i) {
202 auto p_ssv = *it_ssv;
203 auto p_copy = *it_copy;
204 auto _p_ss = *it_ss;
205 decltype(p_ssv) p_ss;
206 color_convert(_p_ss, p_ss);
207 // 断言语义分割视图和转换后的rgb8图像在当前位置的像素值相等
208 ASSERT_EQ(p_ssv, p_ss)
209 << "at XY(" << i << ",0)";
210 decltype(p_copy) css;
211 color_convert(p_ssv, css);
212 // 断言语义分割视图和副本图像在当前 instance:1:510
213 ASSERT_EQ(p_ssv, p_copy)
214 << "at XY(" << i << ",0)";
215 ++it_ss;
216 ++it_ssv;
217 ++it_copy;
218 }
219 }
220}
static void log(Args &&... args)
Definition Logging.h:61
static void log_info(Args &&... args)
Definition Logging.h:86
std::unique_ptr< PixelT[]> data
PixelT pixel_type
TestImage(TestImage &&)=default
TEST(image, support)
static auto MakeTestImage(size_t width, size_t height)