Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,24 @@ class BaseProcessor
return std::get<T>(parameters_.at(key));
}

/**
* @brief Set camera info, note that this function does nothing unless overridden.
*/
virtual void set_camera_info(const common::CameraInfo &) {}

/**
* @brief Return the rectified camera information if it has value, otherwise std::nullopt.
*/
const std::optional<common::CameraInfo> & camera_info() const { return camera_info_; }

protected:
/**
* @brief Process the input image.
* @param image The input image.
* @return The processed image.
*/
virtual Image process_impl(const Image & image) = 0;

std::optional<common::CameraInfo> camera_info_{std::nullopt}; //!< [maybe unused] Camera info
};
} // namespace accelerated_image_processor::common
17 changes: 13 additions & 4 deletions src/accelerated_image_processor_pipeline/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ endif()

add_library(
${PROJECT_NAME} SHARED
src/builder.cpp src/rectifier/cpu.cpp src/rectifier/npp.cpp
src/rectifier/opencv_cuda.cpp src/rectifier/utility.cpp)
src/builder.cpp src/sequential.cpp src/rectifier/cpu.cpp
src/rectifier/npp.cpp src/rectifier/opencv_cuda.cpp src/rectifier/utility.cpp)

target_compile_definitions(
${PROJECT_NAME}
Expand All @@ -55,7 +55,8 @@ target_link_libraries(
$<$<TARGET_EXISTS:CUDA::nppig>:CUDA::nppig>
$<$<TARGET_EXISTS:CUDA::nppisu>:CUDA::nppisu>
$<$<TARGET_EXISTS:CUDA::cudart>:CUDA::cudart>)
ament_target_dependencies(${PROJECT_NAME} accelerated_image_processor_common)
ament_target_dependencies(${PROJECT_NAME} accelerated_image_processor_common
accelerated_image_processor_compression)

set_property(TARGET ${PROJECT_NAME} PROPERTY INTERFACE_INCLUDE_DIRECTORIES
$<INSTALL_INTERFACE:include>)
Expand All @@ -64,12 +65,20 @@ install(DIRECTORY include/${PROJECT_NAME} DESTINATION include)

if(BUILD_TESTING)
set(test_files test/builder.cpp test/cpu_rectifier.cpp test/npp_rectifier.cpp
test/opencv_cuda_rectifier.cpp)
test/opencv_cuda_rectifier.cpp test/sequential.cpp)
foreach(test_file IN LISTS test_files)
get_filename_component(test_file_name ${test_file} NAME)
ament_auto_add_gtest(${test_file_name}_${PROJECT_NAME} ${test_file})
target_link_libraries(${test_file_name}_${PROJECT_NAME} ${PROJECT_NAME})
endforeach()

# Examples
set(example_files examples/example_sequential.cpp)
foreach(example_file IN LISTS example_files)
get_filename_component(example_name ${example_file} NAME_WE)
ament_auto_add_executable(${example_name} ${example_file})
target_link_libraries(${example_name} ${PROJECT_NAME})
endforeach()
endif()

ament_export_include_directories(include)
Expand Down
9 changes: 9 additions & 0 deletions src/accelerated_image_processor_pipeline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ This package provides functionalities for image processing pipelines using vario
| | `OpenCvCudaRectifier` | [OpenCV CUDA](https://opencv.org/platforms/cuda/) | GPU |
| | `CpuRectifier` | [OpenCV](https://opencv.org/) | CPU |

## Sequential Processor

`Sequential` can compose multiple processors and execute them sequentially.
By chaining `Sequential::append(...)` methods, you can add multiple processors.

With `Sequential::register_callback(...)` methods, you can also add the postprocess callback to be executed after all processors are finished as the usual processor.

For the example usage, see the [example_sequential.cpp](./examples/example_sequential.cpp).

## Example Usage in ROS 2

The following code demonstrates how to use each processor in your ROS 2 codebase.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2025 TIER IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "accelerated_image_processor_pipeline/rectifier.hpp"
#include "accelerated_image_processor_pipeline/sequential.hpp"

#include <accelerated_image_processor_common/datatype.hpp>
#include <accelerated_image_processor_compression/builder.hpp>

#include <iostream>
#include <string>
#include <utility>

namespace accelerated_image_processor
{
namespace
{
std::string format_to_str(common::ImageFormat format)
{
switch (format) {
case common::ImageFormat::RAW:
return "RAW";
case common::ImageFormat::JPEG:
return "JPEG";
default:
return "UNKNOWN";
}
}

void print_info(const common::Image & image)
{
std::cout << "[INFO]:\n"
<< " (width, height) = (" << image.width << ", " << image.height << ")\n"
<< " format = " << format_to_str(image.format) << std::endl;
}

void print_finish(const common::Image &)
{
std::cout << ">>> 🎉 All processing finished!!" << std::endl;
}

std::pair<common::Image, common::CameraInfo> make_image_and_info(uint32_t width, uint32_t height)
{
const std::string frame_id = "camera";
constexpr int64_t timestamp = 123456789;

common::Image image;
image.frame_id = frame_id;
image.timestamp = timestamp;
image.width = width;
image.height = height;
image.step = width * 3;
image.encoding = common::ImageEncoding::RGB;
image.format = common::ImageFormat::RAW;
image.data.resize(image.step * image.height);

for (uint32_t y = 0; y < image.height; ++y) {
for (uint32_t x = 0; x < image.width; ++x) {
image.data[y * image.step + x * 3 + 0] = static_cast<uint8_t>(x % 256);
image.data[y * image.step + x * 3 + 1] = static_cast<uint8_t>(y % 256);
image.data[y * image.step + x * 3 + 2] = static_cast<uint8_t>((x + y) % 256);
}
}

common::CameraInfo camera_info;
camera_info.frame_id = frame_id;
camera_info.timestamp = timestamp;
camera_info.width = width;
camera_info.height = height;
camera_info.distortion_model = common::DistortionModel::PLUMB_BOB;
camera_info.d = {0.0, 0.0, 0.0, 0.0, 0.0}; // (k1, k2, p1, p2, k3)
camera_info.k = {1.0, 0.0, width / 2.0, // (fx, 0, cx)
0.0, 1.0, height / 2.0, // (0, fy, cy)
0.0, 0.0, 1.0}; // (0, 0, 1.0)
camera_info.r = {1.0, 0.0, 0.0, // (r11, r12, r13)
0.0, 1.0, 0.0, // (r21, r22, r23)
0.0, 0.0, 1.0}; // (r31, r32, r33)
camera_info.p = {1.0, 0.0, width / 2.0, 0.0, // (fx', 0, cx', tx)
0.0, 1.0, height / 2.0, 0.0, // (0, fy', cy', ty)
0.0, 0.0, 1.0, 0.0}; // (0, 0, 1.0, tz)
camera_info.binning_x = 1;
camera_info.binning_y = 1;
camera_info.roi = {0, 0, width, height, false};
return std::make_pair(image, camera_info);
}
} // namespace

void run_sequential()
{
const auto [image, camera_info] = make_image_and_info(1920, 1080);

pipeline::Sequential sequential;

// Pipeline: Rectification -> [Info] -> JPEG Compression -> [Info] -> [Finish]
sequential.append<pipeline::Rectifier>("rectifier", &print_info)
.append<compression::Compressor>("compressor", &print_info, "jpeg")
.register_postprocess(&print_finish);

// Set camera info for rectification
sequential.set_camera_info(camera_info);

sequential.process(image);
}
} // namespace accelerated_image_processor

int main()
{
accelerated_image_processor::run_sequential();
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,11 @@ class Rectifier : public common::BaseProcessor
* @brief Set camera information before rectified, and compute the rectified camera information
* under the hood.
*/
void set_camera_info(const common::CameraInfo & camera_info)
void set_camera_info(const common::CameraInfo & camera_info) override
{
camera_info_ = prepare_maps(camera_info);
}

/**
* @brief Return the rectified camera information if it has value, otherwise std::nullopt.
*/
const std::optional<common::CameraInfo> & camera_info() const { return camera_info_; }

/**
* @brief Return true if Rectifier::set_camera_info() was invoked and the rectified camera
* information has been set.
Expand All @@ -82,8 +77,6 @@ class Rectifier : public common::BaseProcessor
*/
virtual common::CameraInfo prepare_maps(const common::CameraInfo & camera_info) = 0;

std::optional<common::CameraInfo> camera_info_{std::nullopt}; //!< Rectified camera info.

private:
const RectifierBackend backend_; //!< Rectification backend type.
};
Expand Down
Loading