From dc02bc7d340376faa6271a5709dd02c5aeb71137 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 29 Sep 2022 15:30:20 -0700 Subject: [PATCH] Add support for 16 bit image format (#276) Signed-off-by: Ian Chen Co-authored-by: Michael Carroll --- src/CameraSensor.cc | 7 ++ test/integration/camera.cc | 110 ++++++++++++++++++++++++- test/sdf/camera_sensor_l16_builtin.sdf | 29 +++++++ 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 test/sdf/camera_sensor_l16_builtin.sdf diff --git a/src/CameraSensor.cc b/src/CameraSensor.cc index 6ea7688b..4fcf9b21 100644 --- a/src/CameraSensor.cc +++ b/src/CameraSensor.cc @@ -220,6 +220,9 @@ bool CameraSensor::CreateCamera() case sdf::PixelFormatType::L_INT8: this->dataPtr->camera->SetImageFormat(ignition::rendering::PF_L8); break; + case sdf::PixelFormatType::L_INT16: + this->dataPtr->camera->SetImageFormat(ignition::rendering::PF_L16); + break; default: ignerr << "Unsupported pixel format [" << static_cast(pixelFormat) << "]\n"; @@ -447,6 +450,10 @@ bool CameraSensor::Update(const std::chrono::steady_clock::duration &_now) format = ignition::common::Image::L_INT8; msgsPixelFormat = msgs::PixelFormatType::L_INT8; break; + case ignition::rendering::PF_L16: + format = ignition::common::Image::L_INT16; + msgsPixelFormat = msgs::PixelFormatType::L_INT16; + break; default: ignerr << "Unsupported pixel format [" << this->dataPtr->camera->ImageFormat() << "]\n"; diff --git a/test/integration/camera.cc b/test/integration/camera.cc index 36dcd1b9..a5ef6e7d 100644 --- a/test/integration/camera.cc +++ b/test/integration/camera.cc @@ -51,7 +51,7 @@ std::mutex g_mutex; unsigned int g_imgCounter = 0; -void OnGrayscaleImage(const ignition::msgs::Image &_msg) +void OnGrayscale8bitImage(const ignition::msgs::Image &_msg) { std::lock_guard lock(g_mutex); EXPECT_EQ(ignition::msgs::PixelFormatType::L_INT8, _msg.pixel_format_type()); @@ -60,6 +60,15 @@ void OnGrayscaleImage(const ignition::msgs::Image &_msg) g_imgCounter++; } +void OnGrayscale16bitImage(const ignition::msgs::Image &_msg) +{ + std::lock_guard lock(g_mutex); + EXPECT_EQ(ignition::msgs::PixelFormatType::L_INT16, _msg.pixel_format_type()); + EXPECT_EQ(256u, _msg.width()); + EXPECT_EQ(256u, _msg.height()); + g_imgCounter++; +} + class CameraSensorTest: public testing::Test, public testing::WithParamInterface { @@ -74,6 +83,9 @@ class CameraSensorTest: public testing::Test, // Create a 8 bit grayscale camera sensor and verify image format public: void ImageFormatLInt8(const std::string &_renderEngine); + + // Create a 16 bit grayscale camera sensor and verify image format + public: void ImageFormatLInt16(const std::string &_renderEngine); }; void CameraSensorTest::ImagesWithBuiltinSDF(const std::string &_renderEngine) @@ -217,9 +229,11 @@ void CameraSensorTest::ImageFormatLInt8(const std::string &_renderEngine) EXPECT_TRUE(helper.WaitForMessage()) << helper; + g_imgCounter = 0u; + // subscribe to the camera topic ignition::transport::Node node; - node.Subscribe(topic, &OnGrayscaleImage); + node.Subscribe(topic, &OnGrayscale8bitImage); // wait for a few camera frames mgr.RunOnce(std::chrono::steady_clock::duration::zero(), true); @@ -258,6 +272,98 @@ TEST_P(CameraSensorTest, LInt8ImagesWithBuiltinSDF) ImageFormatLInt8(GetParam()); } +////////////////////////////////////////////////// +void CameraSensorTest::ImageFormatLInt16(const std::string &_renderEngine) +{ + // get the darn test data + std::string path = ignition::common::joinPaths(PROJECT_SOURCE_PATH, "test", + "sdf", "camera_sensor_l16_builtin.sdf"); + sdf::SDFPtr doc(new sdf::SDF()); + sdf::init(doc); + ASSERT_TRUE(sdf::readFile(path, doc)); + ASSERT_NE(nullptr, doc->Root()); + ASSERT_TRUE(doc->Root()->HasElement("model")); + auto modelPtr = doc->Root()->GetElement("model"); + ASSERT_TRUE(modelPtr->HasElement("link")); + auto linkPtr = modelPtr->GetElement("link"); + ASSERT_TRUE(linkPtr->HasElement("sensor")); + auto sensorPtr = linkPtr->GetElement("sensor"); + + // Setup empty scene + auto *engine = ignition::rendering::engine(_renderEngine); + if (!engine) + { + igndbg << "Engine '" << _renderEngine + << "' is not supported" << std::endl; + return; + } + + ignition::rendering::ScenePtr scene = engine->CreateScene("scene"); + + // do the test + ignition::sensors::Manager mgr; + + ignition::sensors::CameraSensor *sensor = + mgr.CreateSensor(sensorPtr); + ASSERT_NE(sensor, nullptr); + sensor->SetScene(scene); + + ASSERT_NE(sensor->RenderingCamera(), nullptr); + EXPECT_NE(sensor->Id(), sensor->RenderingCamera()->Id()); + EXPECT_EQ(256u, sensor->ImageWidth()); + EXPECT_EQ(256u, sensor->ImageHeight()); + + std::string topic = "/images_l16"; + WaitForMessageTestHelper helper(topic); + + // Update once to create image + mgr.RunOnce(std::chrono::steady_clock::duration::zero()); + + EXPECT_TRUE(helper.WaitForMessage()) << helper; + + g_imgCounter = 0u; + + // subscribe to the camera topic + ignition::transport::Node node; + node.Subscribe(topic, &OnGrayscale16bitImage); + + // wait for a few camera frames + mgr.RunOnce(std::chrono::steady_clock::duration::zero(), true); + + // run to get image and check image format in callback + bool done = false; + int sleep = 0; + int maxSleep = 10; + while (!done && sleep++ < maxSleep) + { + std::lock_guard lock(g_mutex); + done = (g_imgCounter > 0); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + // test removing sensor + // first make sure the sensor objects do exist + auto sensorId = sensor->Id(); + auto cameraId = sensor->RenderingCamera()->Id(); + EXPECT_EQ(sensor, mgr.Sensor(sensorId)); + EXPECT_EQ(sensor->RenderingCamera(), scene->SensorById(cameraId)); + // remove and check sensor objects no longer exist in both sensors and + // rendering + EXPECT_TRUE(mgr.Remove(sensorId)); + EXPECT_EQ(nullptr, mgr.Sensor(sensorId)); + EXPECT_EQ(nullptr, scene->SensorById(cameraId)); + + // Clean up + engine->DestroyScene(scene); + ignition::rendering::unloadEngine(engine->Name()); +} + +////////////////////////////////////////////////// +TEST_P(CameraSensorTest, LInt16ImagesWithBuiltinSDF) +{ + ImageFormatLInt16(GetParam()); +} + INSTANTIATE_TEST_CASE_P(CameraSensor, CameraSensorTest, RENDER_ENGINE_VALUES, ignition::rendering::PrintToStringParam()); diff --git a/test/sdf/camera_sensor_l16_builtin.sdf b/test/sdf/camera_sensor_l16_builtin.sdf new file mode 100644 index 00000000..8b812bce --- /dev/null +++ b/test/sdf/camera_sensor_l16_builtin.sdf @@ -0,0 +1,29 @@ + + + + + + 10 + base_camera + /images_l16 + + 1.05 + + 256 + 256 + L_INT16 + + + 0.1 + 10.0 + + + gaussian + 0.0 + 0.007 + + + + + +