Skip to content
Merged
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
16 changes: 16 additions & 0 deletions cuda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# CUDA tutorial

## Setup

The Sensing-Dev SDK install script introduced in [Sensing-Dev](https://sensing-dev.github.io/doc/) has ion-kit but target-CUDA feature is not available.

**After installing either Sensing-Dev v24.05 or v25.01**, please run the `cuda-ion-setup.sh` which build and install ion-kit with the option of CUDA.

```bash
sudo bash cuda-ion-setup.sh
```
If you are using Sensing-Dev v24.05, please add the option of `--version v1.8.10`.

Note that this install script is designed for Linux x86_64.

After setting up, you can remove the directory called `cuda-setup`.
135 changes: 135 additions & 0 deletions cuda/cuda-ion-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash
set -e

: '
SYNOPSIS
build_install_lib.sh [OPTIONS]

DESCRIPTION
This script installs VCPKG, fetches a library from GitHub, builds it, and installs it.

OPTIONS
--vcpkg-dir DIR Set the installation directory for VCPKG (default: $HOME/vcpkg)
--lib-dir DIR Set the directory for library installation (default: $HOME/libs)
--tag TAG Specify the branch or tag to checkout (default: latest release)
--install-path DIR Set the installation directory for Sensing-Dev (ion-kit)
'
# DEFAULT ######################################################################
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKING_DIR="$SCRIPT_DIR/cuda-setup"
VCPKG_DIR="$WORKING_DIR/vcpkg"
GITHUB_REPO="fixstars/ion-kit"
BRANCH_OR_TAG="latest"
SDK_DIR="/opt/sensing-dev"


# VCPKG ########################################################################
while [[ "$#" -gt 0 ]]; do
case "$1" in
--vcpkg-dir)
VCPKG_DIR="$2"
shift 2
;;
--lib-dir)
LIBRARY_DIR="$2"
shift 2
;;
--version)
BRANCH_OR_TAG="$2"
shift 2
;;
--install-path)
SDK_DIR="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done

if [[ "$BRANCH_OR_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "$BRANCH_OR_TAG" == "latest" ]]; then
echo "Valid --version: $BRANCH_OR_TAG"
else
echo "Error: --version must be in the format 'vX.Y.Z' (e.g., v1.8.10)"
exit 1
fi

# Get git ######################################################################
sudo apt install git-all -y

# Set working directory ########################################################
mkdir -p "$WORKING_DIR"

# VCPKG ########################################################################
if [ ! -d "$VCPKG_DIR" ]; then
echo "Cloning VCPKG..."
git clone https://github.com/microsoft/vcpkg.git "$VCPKG_DIR"
cd "$VCPKG_DIR" || exit
./bootstrap-vcpkg.sh
else
echo "VCPKG already installed in $VCPKG_DIR"
fi
export PATH=$VCPKG_DIR:$PATH

# Get Halide ###################################################################
cd "$WORKING_DIR"
echo $BRANCH_OR_TAG
if [[ "$BRANCH_OR_TAG" =~ ^v1\.8\.[0-9]+$ ]]; then
# v1.8.xx の場合
curl -L https://github.com/halide/Halide/releases/download/v16.0.0/Halide-16.0.0-x86-64-linux-1e963ff817ef0968cc25d811a25a7350c8953ee6.tar.gz --output halide.tar.gz
tar -xvzf halide.tar.gz
cd Halide-16.0.0-x86-64-linux
export HALIDE_PATH="$WORKING_DIR/Halide-16.0.0-x86-64-linux"
else
# それ以外の場合(デフォルト)
curl -L https://github.com/halide/Halide/releases/download/v17.0.1/Halide-17.0.1-x86-64-linux-52541176253e74467dabc42eeee63d9a62c199f6.tar.gz --output halide.tar.gz
tar -xvzf halide.tar.gz
cd Halide-17.0.1-x86-64-linux
export HALIDE_PATH="$WORKING_DIR/Halide-17.0.1-x86-64-linux"
fi

# Get ion-kit ##################################################################
cd "$WORKING_DIR" || exit
echo "Fetching library from GitHub..."
if [ "$BRANCH_OR_TAG" = "latest" ]; then
LATEST_TAG=$(curl -s "https://api.github.com/repos/$GITHUB_REPO/releases/latest" | grep 'tag_name' | cut -d '"' -f 4)
BRANCH_OR_TAG="$LATEST_TAG"
fi
echo "ion-kit $BRANCH_OR_TAG will be installed..."
if [ -d "$WORKING_DIR/ion-kit" ]; then
rm -r "$WORKING_DIR/ion-kit"
fi

git clone --branch "$BRANCH_OR_TAG" --depth 1 "https://github.com/$GITHUB_REPO.git"


# Build and Install ############################################################
cd "$WORKING_DIR/ion-kit"
# Set minimum CMake 3.22
CMAKE_FILE="$WORKING_DIR/ion-kit/CMakeLists.txt"
if [ -f "$CMAKE_FILE" ]; then
sed -i 's/cmake_minimum_required(VERSION 3\.25)/cmake_minimum_required(VERSION 3.22)/' "$CMAKE_FILE"
echo "Updated cmake_minimum_required version in CMakeLists.txt"
fi
# Set up dependencies
vcpkg install
# Build
mkdir -p build && cd build
cmake -D CMAKE_TOOLCHAIN_FILE=${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake \
-D Halide_DIR=${HALIDE_PATH}/lib/cmake/Halide \
-D HalideHelpers_DIR=${HALIDE_PATH}/lib/cmake/HalideHelpers \
-DCMAKE_BUILD_TYPE=Release -D ION_BUILD_TEST=OFF -D BUILD_DOC=OFF -D ION_BUILD_EXAMPLE=OFF \
-D CMAKE_INSTALL_PREFIX=${SDK_DIR} ..
# Install
cmake --build . --target install

echo "Library installation completed."

VERSION_INFO_FILE="$SDK_DIR/version_info.json"
if [ -f "$VERSION_INFO_FILE" ]; then
sed -i "s/\"ion-kit\": \"v[0-9]*\\.[0-9]*\\.[0-9]*\"/\"ion-kit\": \"$BRANCH_OR_TAG(CUDA)\"/" "$VERSION_INFO_FILE"
sed -i "s/\"ion-kit\": \"[0-9]*\\.[0-9]*\\.[0-9]*\"/\"ion-kit\": \"$BRANCH_OR_TAG(CUDA)\"/" "$VERSION_INFO_FILE"
echo "Updated $SDK_DIR/version_info.json"
fi
151 changes: 151 additions & 0 deletions cuda/src/load_and_process.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*

g++ src/load_and_process.cpp -o load_and_process \
-I /opt/sensing-dev/include -I /opt/sensing-dev/include/aravis-0.8 \
-I /opt/sensing-dev/include/opencv4 \
-L /opt/sensing-dev/lib \
-L /opt/sensing-dev/lib/x86_64-linux-gnu \
-lHalide -lion-core -ldl -lpthread -lopencv_core \
-lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc \
-laravis-0.8 -lgobject-2.0 \
`pkg-config --cflags --libs glib-2.0`

*/

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <ion/ion.h>

#include <exception>
#include <string>
#include <map>
#include <iostream>
#include <chrono>

using namespace ion;
std::map<std::string, int32_t> bit_width_map{
{"BayerBG8", 8}, {"BayerBG10", 16}, {"BayerBG12", 16}};
std::map<std::string, int32_t> num_bit_shift_map{
{"BayerBG8", 0}, {"BayerBG10", 6}, {"BayerBG12", 4}};
std::map<std::string, std::string> bb_name{
{"BayerBG8", "image_io_binaryloader_u8x2"},
{"BayerBG10", "image_io_binaryloader_u16x2"},
{"BayerBG12", "image_io_binaryloader_u16x2"}};


void pipeline_acquisition_and_process(bool use_cuda, bool display_image, std::string output_directory, std::string prefix, int width, int height, std::string pixelformat, int num_frames){
std::vector< int > buf_size = std::vector < int >{3, width, height};

std::vector<Halide::Buffer<uint8_t>> outputs;
outputs.push_back(Halide::Buffer<uint8_t>(buf_size));

Buffer<bool> finished(1);

Builder b;
if (use_cuda){
b.set_target(get_host_target().with_feature(Target::CUDA).with_feature(Target::Profile));
}else{
b.set_target(get_host_target().with_feature(Target::Profile));
}
b.with_bb_module("ion-bb");

// add binary loader BB to pipeline
Node n = b.add(bb_name[pixelformat])(&width, &height)
.set_param(
Param("output_directory", output_directory),
Param("prefix", prefix)
);
n["finished"].bind(finished);

if (bit_width_map[pixelformat] == 8){
n = b.add("base_cast_2d_uint8_to_uint16")(n["output"]);
}

n = b.add("image_processing_normalize_raw_image")(n["output"])
.set_param(
Param("bit_width", bit_width_map[pixelformat]),
Param("bit_shift", num_bit_shift_map[pixelformat])
);

n = b.add("image_processing_bayer_demosaic_linear")(n["output"])
.set_param(
Param("bayer_pattern", "BGGR"),
Param("width", width),
Param("height", height)
); // output(x, y, c)

n = b.add("base_denormalize_3d_uint8") (n["output"]);
n = b.add("base_reorder_buffer_3d_uint8")(n["output"])
.set_param(
Param("dim0", "2"),
Param("dim1", "0"),
Param("dim2", "1")
); // output(c, x, y)
n["output"].bind(outputs[0]);

int count_run = 1;
while (true) {
b.run();
bool is_finished = finished(0);

cv::Mat img(height, width, CV_8UC3);
std::memcpy(img.ptr(), outputs[0].data(), outputs[0].size_in_bytes());
if (display_image){
cv::imshow("image" + std::to_string(0), img);
cv::waitKey(1);
}

if (count_run == num_frames || is_finished) {
break;
}
count_run += 1;
}
std::cout << "Total number of frames to process: " << count_run << std::endl;
}

int main(int argc, char *argv[])
{
try{
// if prefix is imageX if the name of the config is imageX-config.json
std::string prefix = "image0-";
// check imageX-config.json
const int32_t width = 1920;
const int32_t height = 1080;
std::string pixelformat = "BayerBG8";

bool use_cuda = false;
bool display_image = false;
std::string output_directory = ".";
int num_frames = 0;

if (argc > 1){
for (int i = 1; i < argc; i++){
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--target-cuda") == 0){
use_cuda = true;
}else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--display") == 0){
display_image = true;
}else if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--input") == 0){
output_directory = argv[++i];
}else if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--prefix") == 0){
prefix = argv[++i];
}else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--num-frames") == 0){
num_frames = strtol(argv[++i], NULL, 10);
}else{
std::cerr << "wrong format of command option." << std::endl;
}
}
}

pipeline_acquisition_and_process(use_cuda, display_image, output_directory, prefix, width, height, pixelformat, num_frames);

} catch(std::exception& e){
std::cerr << e.what() << std::endl;
return 1;
} catch (const ion::Error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Loading