Full Code of prittt/YACCLAB for AI

master 54e43543a02f cached
222 files
11.4 MB
3.0M tokens
415 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (11,945K chars total). Download the full file to get everything.
Repository: prittt/YACCLAB
Branch: master
Commit: 54e43543a02f
Files: 222
Total size: 11.4 MB

Directory structure:
gitextract_j1r0m0pd/

├── .all-contributorsrc
├── .github/
│   └── workflows/
│       ├── linux64.yml
│       └── macos.yml
├── .gitignore
├── AUTHORS
├── CMakeLists.txt
├── Jenkinsfile
├── LICENSE
├── README.md
├── config.yaml
├── cuda/
│   ├── CMakeLists.txt
│   ├── include/
│   │   ├── CMakeLists.txt
│   │   ├── cuda_mat3.hpp
│   │   ├── cuda_mat3.inl.hpp
│   │   └── cuda_types3.hpp
│   └── src/
│       ├── CMakeLists.txt
│       ├── gpu_mat3.cu
│       ├── labeling_BE_3D_light.cu
│       ├── labeling_BE_3D_light_shared.cu
│       ├── labeling_BE_big_tex.cu
│       ├── labeling_BE_light.cu
│       ├── labeling_BKE_NoInlineCompression.cu
│       ├── labeling_BUF_2S.cu
│       ├── labeling_BUF_3D_NoInlineCompression.cu
│       ├── labeling_BUF_NoInlineCompression.cu
│       ├── labeling_KE4.cu
│       ├── labeling_KE_2S.cu
│       ├── labeling_OLE_tex.cu
│       ├── labeling_RADAR.cu
│       ├── labeling_TUF.cu
│       ├── labeling_UF_InlineCompression.cu
│       ├── labeling_UF_naive.cu
│       ├── labeling_allegretti_2018.cu
│       ├── labeling_allegretti_2019_BBDT.cu
│       ├── labeling_allegretti_2019_BKE.cu
│       ├── labeling_allegretti_2019_BKE_3D.cu
│       ├── labeling_allegretti_2019_BUF.cu
│       ├── labeling_allegretti_2019_BUF_3D.cu
│       ├── labeling_allegretti_2019_DRAG.cu
│       ├── labeling_allegretti_2019_SAUF.cu
│       ├── labeling_allegretti_2019_UF_3D.cu
│       ├── labeling_cabaret_2017.cu
│       ├── labeling_chen_2011.cu
│       ├── labeling_chen_2011_1024.cu
│       ├── labeling_chen_2011_2048.cu
│       ├── labeling_chen_2011_512.cu
│       ├── labeling_hennequin_2018_HA4.cu
│       ├── labeling_hennequin_2018_HA8.cu
│       ├── labeling_kalentev_2011.cu
│       ├── labeling_oliveira_2010.cu
│       ├── labeling_paravecino_2014.cu
│       ├── labeling_rasmusson_2013.cu
│       ├── labeling_soh_2014_8DLS.cu
│       ├── labeling_soh_2014_M8DLS.cu
│       ├── labeling_stava_2011.cu
│       ├── labeling_yonehara_2015.cu
│       ├── labeling_zavalishin_2016.cu
│       ├── labeling_zavalishin_2016_3D.cu
│       └── next_to_trash/
│           ├── labeling_CUDA_BKE_InlineCompression.cu
│           ├── labeling_CUDA_BUF_2S.cu
│           ├── labeling_CUDA_KE_2S.cu
│           └── labeling_CUDA_UF_InlineCompression.cu
├── doc/
│   ├── EPDT/
│   │   └── README.md
│   ├── README.txt
│   ├── config_2d.yaml
│   ├── config_3d.yaml
│   ├── config_base.yaml
│   ├── config_ci_cpu.yaml
│   ├── config_ci_cpu2d.yaml
│   ├── config_cuda_2d.yaml
│   ├── config_cuda_3d.yaml
│   ├── config_epdt_19c.yaml
│   ├── config_epdt_22c.yaml
│   ├── config_epdt_26c.yaml
│   └── config_jenkins.yaml
├── include/
│   ├── CMakeLists.txt
│   ├── bit_scan_forward.h
│   ├── check_labeling.h
│   ├── config_data.h
│   ├── file_manager.h
│   ├── labeling3D_EPDT_19c.h
│   ├── labeling3D_EPDT_19c_211b.h
│   ├── labeling3D_EPDT_19c_action_def.inc.h
│   ├── labeling3D_EPDT_19c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_19c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_19c_tree.inc.h
│   ├── labeling3D_EPDT_22c.h
│   ├── labeling3D_EPDT_22c_211b.h
│   ├── labeling3D_EPDT_22c_action_def.inc.h
│   ├── labeling3D_EPDT_22c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_22c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_22c_tree.inc.h
│   ├── labeling3D_EPDT_26c.h
│   ├── labeling3D_EPDT_26c_action_def.inc.h
│   ├── labeling3D_EPDT_26c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_26c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_26c_tree.inc.h
│   ├── labeling3D_EPDT_2829_action_undef.inc.h
│   ├── labeling3D_PRED_2021.h
│   ├── labeling3D_PRED_2021_cl_forest.inc.h
│   ├── labeling3D_PRED_2021_fl_forest.inc.h
│   ├── labeling3D_PRED_2021_ll_forest.inc.h
│   ├── labeling3D_PRED_2021_sl_forest.inc.h
│   ├── labeling3D_PREDpp_2021.h
│   ├── labeling3D_PREDpp_2021_cl_forest.inc.h
│   ├── labeling3D_PREDpp_2021_fl_forest.inc.h
│   ├── labeling3D_PREDpp_2021_ll_forest.inc.h
│   ├── labeling3D_PREDpp_2021_sl_forest.inc.h
│   ├── labeling3D_SAUF_2021.h
│   ├── labeling3D_SAUF_2021_tree.inc.h
│   ├── labeling3D_SAUFpp_2021.h
│   ├── labeling3D_SAUFpp_2021_tree.inc.h
│   ├── labeling3D_he_2011.h
│   ├── labeling3D_he_2011_run.h
│   ├── labeling3D_he_2011_tree.inc.h
│   ├── labeling3D_naive.h
│   ├── labeling_HT_CCL_Diaz2019_v1_2_0.h
│   ├── labeling_PREDpp_2021.h
│   ├── labeling_PREDpp_2021_cl_forest.inc.h
│   ├── labeling_PREDpp_2021_fl_forest.inc.h
│   ├── labeling_algorithms.h
│   ├── labeling_bolelli_2018.h
│   ├── labeling_bolelli_2018_drag.inc.h
│   ├── labeling_bolelli_2019.h
│   ├── labeling_bolelli_2019_forest.inc.h
│   ├── labeling_bolelli_2019_forest_fl.inc.h
│   ├── labeling_bolelli_2019_forest_ll.inc.h
│   ├── labeling_bolelli_2019_forest_sl.inc.h
│   ├── labeling_distefano_1999.h
│   ├── labeling_fchang_2003.h
│   ├── labeling_grana_2010.h
│   ├── labeling_grana_2010_tree.inc.h
│   ├── labeling_grana_2016.h
│   ├── labeling_grana_2016_forest.inc.h
│   ├── labeling_grana_2016_forest_0.inc.h
│   ├── labeling_he_2008.h
│   ├── labeling_he_2014.h
│   ├── labeling_he_2014_graph.inc.h
│   ├── labeling_lacassagne_2016.h
│   ├── labeling_lacassagne_2016_code.inc.h
│   ├── labeling_lee_2021_bmrs.h
│   ├── labeling_lee_2021_bmrs_no_zeroinit.h
│   ├── labeling_lee_2021_brts.h
│   ├── labeling_lee_2021_brts_no_zeroinit.h
│   ├── labeling_null.h
│   ├── labeling_sauf_4c.h
│   ├── labeling_sauf_4c_tree.inc.h
│   ├── labeling_sauf_background.h
│   ├── labeling_sauf_bg_tree.inc.h
│   ├── labeling_tagliatelle_2021.h
│   ├── labeling_tagliatelle_2021_cl_forest.inc.h
│   ├── labeling_tagliatelle_2021_fl_forest.inc.h
│   ├── labeling_tagliatelle_2021_ll_forest.inc.h
│   ├── labeling_tagliatelle_2021_sl_forest.inc.h
│   ├── labeling_wu_2009.h
│   ├── labeling_wu_2009_tree.inc.h
│   ├── labeling_wychang_2015.h
│   ├── labeling_wychang_2015_tree.inc.h
│   ├── labeling_wychang_2015_tree_0.inc.h
│   ├── labeling_zhao_2010.h
│   ├── labels_solver.h
│   ├── memory_tester.h
│   ├── performance_evaluator.h
│   ├── progress_bar.h
│   ├── register.h
│   ├── stream_demultiplexer.h
│   ├── system_info.h
│   ├── utilities.h
│   ├── volume_util.h
│   ├── yacclab_tensor.h
│   └── yacclab_tests.h
├── old/
│   ├── .travis.yml
│   ├── configurationReader.h
│   └── equivalenceSolverSuzuki.h
├── spike/
│   └── performanceEvaluator.h.chrono
├── src/
│   ├── CMakeLists.txt
│   ├── check_labeling.cc
│   ├── config_data.cc
│   ├── file_manager.cc
│   ├── labeling3D_EPDT_19c.cc
│   ├── labeling3D_EPDT_22c.cc
│   ├── labeling3D_EPDT_26c.cc
│   ├── labeling3D_PRED_2021.cc
│   ├── labeling3D_PREDpp_2021.cc
│   ├── labeling3D_SAUF_2021.cc
│   ├── labeling3D_SAUFpp_2021.cc
│   ├── labeling3D_he_2011.cc
│   ├── labeling3D_he_2011_run.cc
│   ├── labeling3D_naive.cc
│   ├── labeling_HT_CCL_Diaz2019_v1_2_0.cc
│   ├── labeling_PREDpp_2021.cc
│   ├── labeling_algorithms.cc
│   ├── labeling_bolelli_2018.cc
│   ├── labeling_bolelli_2019.cc
│   ├── labeling_distefano_1999.cc
│   ├── labeling_fchang_2003.cc
│   ├── labeling_grana_2010.cc
│   ├── labeling_grana_2016.cc
│   ├── labeling_he_2008.cc
│   ├── labeling_he_2014.cc
│   ├── labeling_lacassagne_2016.cc
│   ├── labeling_lee_2021_bmrs.cc
│   ├── labeling_lee_2021_brts.cc
│   ├── labeling_null.cc
│   ├── labeling_sauf_4c.cc
│   ├── labeling_sauf_background.cc
│   ├── labeling_tagliatelle_2021.cc
│   ├── labeling_wu_2009.cc
│   ├── labeling_wychang_2015.cc
│   ├── labeling_zhao_2010.cc
│   ├── labels_solver.cc
│   ├── main.cc
│   ├── system_info.cc
│   ├── utilities.cc
│   ├── volume_util.cc
│   ├── yacclab_tensor.cc
│   └── yacclab_tests.cc
└── tools/
    ├── actions-scripts/
    │   └── macos-before-install.sh
    ├── embed_pdf/
    │   └── embed.php
    ├── jenkins-scripts/
    │   └── run-script.sh
    └── travis-scripts/
        ├── before-install.sh
        └── run-script.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .all-contributorsrc
================================================
{
  "projectName": "YACCLAB",
  "projectOwner": "prittt",
  "files": [
    "README.md"
  ],
  "commit": false,
  "repoType": "github",
  "repoHost": "https://github.com",
  "imageSize": 100,
  "contributorsPerLine": 6,
  "contributorsSortAlphabetically": false,
  "badgeTemplate": "[![contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat)](#contributors)",
  "skipCi": true,
  "contributors": [
    {
      "login": "prittt",
      "name": "Federico Bolelli",
      "avatar_url": "https://avatars3.githubusercontent.com/u/6863130?v=4",
      "profile": "http://www.federicobolelli.it",
      "contributions": [
        "code",
        "projectManagement",
        "maintenance",
        "infra",
        "ideas"
      ]
    },
    {
      "login": "stal12",
      "name": "Stefano Allegretti",
      "avatar_url": "https://avatars2.githubusercontent.com/u/34423515?v=1",
      "profile": "https://github.com/stal12",
      "contributions": [
        "code",
        "maintenance",
        "bug",
        "ideas",
        "infra"
      ]
    },
    {
      "login": "CostantinoGrana",
      "name": "Costantino Grana",
      "avatar_url": "https://avatars2.githubusercontent.com/u/18437151?v=1",
      "profile": "https://github.com/CostantinoGrana",
      "contributions": [
        "code",
        "projectManagement",
        "ideas",
        "infra"
      ]
    },
    {
      "login": "MicheleCancilla",
      "name": "Michele Cancilla",
      "avatar_url": "https://avatars1.githubusercontent.com/u/22983812?v=4",
      "profile": "https://michelecancilla.github.io",
      "contributions": [
        "code",
        "platform",
        "maintenance"
      ]
    },
    {
      "login": "baraldilorenzo",
      "name": "Lorenzo Baraldi",
      "avatar_url": "https://avatars3.githubusercontent.com/u/8173533?v=4",
      "profile": "http://www.lorenzobaraldi.com",
      "contributions": [
        "code",
        "platform"
      ]
    },
    {
      "login": "msoechting",
      "name": "Maximilian Söchting",
      "avatar_url": "https://avatars1.githubusercontent.com/u/6423697?v=4",
      "profile": "http://msoechting.de",
      "contributions": [
        "code"
      ]
    },
    {
      "login": "patrickhwood",
      "name": "patrickhwood",
      "avatar_url": "https://avatars.githubusercontent.com/u/2100827?v=4",
      "profile": "https://github.com/patrickhwood",
      "contributions": [
        "bug"
      ]
    },
    {
      "login": "fengweichangzi",
      "name": "WalnutVision",
      "avatar_url": "https://avatars.githubusercontent.com/u/87119815?v=4",
      "profile": "https://github.com/fengweichangzi",
      "contributions": [
        "bug"
      ]
    }
  ]
}


================================================
FILE: .github/workflows/linux64.yml
================================================
name: linux64

on: [push]

jobs:
  build:
    runs-on: ubuntu-18.04
    container:
        image: docker://aimagelab/yacclab-test:linux64
    steps:
    - uses: actions/checkout@v2
    - name: configure
      run: mkdir build && cd build && cmake -DCMAKE_CXX_FLAGS="-m64" -DCMAKE_C_FLAGS="-m64" -DYACCLAB_CI_CPU=ON -DYACCLAB_INPUT_DATASET_PATH=/builds/input -DYACCLAB_ENABLE_3D=ON ..
    - name: build
      run: cmake --build build --config Release
    - name: run
      run: cd build && ./YACCLAB


================================================
FILE: .github/workflows/macos.yml
================================================
name: macos

on: [push]

jobs:
  build:
    runs-on: macos-10.15
    steps:
    - uses: actions/checkout@v2
    
    - name: cache cmake
      uses: actions/cache@v2
      with:
        path: /Users/runner/work/YACCLAB/YACCLAB/cmake-install
        key: cmake-3.18.0
        
    - name: cache opencv
      uses: actions/cache@v2
      with:
        path: /Users/runner/work/YACCLAB/YACCLAB/opencv-3.1.0/build/install_dir
        key: opencv-3.1.0
        
    - name: cache dataset
      uses: actions/cache@v2
      with:
        path: /Users/runner/work/YACCLAB/YACCLAB/input
        key: yacclab-dataset        
    
    - name: dependencies
      run: chmod +x tools/actions-scripts/macos-before-install.sh && tools/actions-scripts/macos-before-install.sh
    - name: configure
      run: DATASET_PATH=$(pwd)/input && OPENCV_DIR=$(pwd)/opencv-3.1.0/build/install_dir/share/OpenCV/ && mkdir bin && cd bin && cmake -DCMAKE_CXX_FLAGS="-m64" -DCMAKE_C_FLAGS="-m64" -DYACCLAB_CI_CPU=ON -DYACCLAB_INPUT_DATASET_PATH=$DATASET_PATH -DYACCLAB_ENABLE_3D=ON -DOpenCV_DIR=$OPENCV_DIR -DCMAKE_BUILD_TYPE=Release ..
    - name: build
      run: cd bin && make -j
    - name: run
      run: cd bin && ./YACCLAB


================================================
FILE: .gitignore
================================================
**/*.vcxproj
**/*.filters
**/*.sln
**/*.opensdf
**/*.suo
**/*.sdf
**/*.user

/Release
/Debug
/[Bb]in*
/[Bb]uild*

/CMakeCache.txt
/cmake_install.cmake
/CMakeFiles

**/*.jpg 

/MSVC*

================================================
FILE: AUTHORS
================================================
Copyright (c) 2020, Federico Bolelli, Costantino Grana, Michele Cancilla, Stefano Allegretti, Lorenzo Baraldi, Roberto Vezzani.

Moral rights:
  Federico Bolelli <federico.bolelli@unimore.it>, 
  Costantino Grana <costantino.grana@unimore.it>,
  Michele Cancilla <michele.cancilla@unimore.it>,
  Stefano Allegretti <stefano.allegretti@unimore.it>
  Lorenzo Baraldi <lorenzo.baraldi@unimore.it>,
  Roberto Vezzani <roberto.vezzani@unimore.it>,
    
The version control system provides attribution for specific lines of code.

================================================
FILE: CMakeLists.txt
================================================
# Copyright (c) 2021, the YACCLAB contributors, as 
# shown by the AUTHORS file. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

cmake_minimum_required(VERSION 3.18)
cmake_policy(SET CMP0091 NEW)

# ----------------------------------------------------------------------------
#  Base variables
# ----------------------------------------------------------------------------

set (ProjectName "YACCLAB")
project (${ProjectName})

# ----------------------------------------------------------------------------
#  YACCLAB and CMAKE variables
# ----------------------------------------------------------------------------
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE PATH "Install prefix" FORCE)

set(YACCLAB_ENABLE_CUDA OFF CACHE BOOL "Enable CUDA support if checked")
set(YACCLAB_ENABLE_3D OFF CACHE BOOL "Enable 3D support if checked")
set(YACCLAB_ENABLE_EPDT_19C OFF CACHE BOOL "Enable 3D algorithm based on Heuristic Decision Trees (may noticeably increase build time)")
set(YACCLAB_ENABLE_EPDT_22C OFF CACHE BOOL "Enable 3D algorithm based on Heuristic Decision Trees (may noticeably increase build time)")
set(YACCLAB_ENABLE_EPDT_26C OFF CACHE BOOL "Enable 3D algorithm based on Heuristic Decision Trees (may noticeably increase build time)")
set(YACCLAB_FORCE_CONFIG_GENERATION OFF CACHE BOOL "Force generation of config file, possibly overwriting the current one")
set(YACCLAB_DOWNLOAD_DATASET OFF CACHE BOOL "If flagged the YACCLAB dataset will be automatically downloaded")
set(YACCLAB_DOWNLOAD_DATASET_3D OFF CACHE BOOL "If flagged the YACCLAB 3D dataset will be automatically downloaded")
set(YACCLAB_INPUT_DATASET_PATH "${CMAKE_INSTALL_PREFIX}/input" CACHE PATH "'input' dataset path") 
set(YACCLAB_OUTPUT_RESULTS_PATH "${CMAKE_INSTALL_PREFIX}/output" CACHE PATH "'output' results path") 
set(YACCLAB_OS "${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION}" CACHE INTERNAL STRING)
set(YACCLAB_CI_CPU2D OFF CACHE INTERNAL "This variable is used to handle travis-ci parameters, do not change its value")
set(YACCLAB_IS_JENKINS OFF CACHE INTERNAL "This variable is used to handle jenkins parameters, do not change its value")
#set(YACCLAB_CXX_STANDARD 14 CACHE STRING "Version of the C++ standard (must be >= 14)") 
#set_property(CACHE YACCLAB_CXX_STANDARD PROPERTY STRINGS 14 17 20 23)

if(MSVC)
  set(CMAKE_USE_RELATIVE_PATHS ON CACHE INTERNAL "" FORCE)
endif()


# ----------------------------------------------------------------------------
#  Check for c++14 support
# ----------------------------------------------------------------------------

if(DEFINED CMAKE_BUILD_TYPE)
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES})
endif()

message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
#if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" OR CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
#    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
#    if(NOT CMAKE_CXX_FLAGS MATCHES "-m32" AND NOT CMAKE_CXX_FLAGS MATCHES "-m64")
#        set(CMAKE_CXX_FLAGS "-m32 ${CMAKE_CXX_FLAGS}" CACHE STRING "32-bit compiled" FORCE)
#    endif()
#    if(NOT CMAKE_C_FLAGS MATCHES "-m32" AND NOT CMAKE_C_FLAGS MATCHES "-m64")
#	set(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}" CACHE STRING "32-bit compiled" FORCE)
#    endif()
#endif()

# The following commands would serve to simplify the check on the compiler version but do not yet seem to work perfectly
set(CMAKE_CXX_STANDARD_REQUIRED YES) # Force the following command to generate an error when it fails
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_EXTENSIONS NO)
   
#if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
#    include(CheckCXXCompilerFlag)
#    CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
#
#	if(COMPILER_SUPPORTS_CXX14 AND NOT CMAKE_CXX_FLAGS MATCHES "-std=c\\+\\+14")
#		set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}" CACHE STRING "Enable c++14" FORCE)
#	elseif(NOT COMPILER_SUPPORTS_CXX14)
#		message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
#	endif()
#	
#	message(STATUS "C++ flags: ${CMAKE_CXX_FLAGS}")
#	message(STATUS "C flags: ${CMAKE_C_FLAGS}")
#elseif(MSVC)
#		if(MSVC_VERSION LESS 1900)
#			message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
#		endif()
#else()
#	message(STATUS "We are not able to check if ${CMAKE_CXX_COMPILER} compiler has C++14 support. YACCLAB may not work properly.")
#endif()

# ----------------------------------------------------------------------------
#  Check for CUDA support
# ----------------------------------------------------------------------------
if(YACCLAB_ENABLE_CUDA)
	include(CheckLanguage)
	check_language(CUDA)	
	if(CMAKE_CUDA_COMPILER)
		enable_language(CUDA)
		add_definitions(-DYACCLAB_WITH_CUDA)
        
        set(CMAKE_CUDA_STANDARD_REQUIRED YES) # Force the following command to generate an error when it fails
        set(CMAKE_CUDA_STANDARD 14)
        set(CMAKE_CUDA_EXTENSIONS NO)
        
		# Detect and set CUDA architecture
		include(FindCUDA/select_compute_arch)
		CUDA_DETECT_INSTALLED_GPUS(INSTALLED_GPU_CCS_1)
		string(STRIP "${INSTALLED_GPU_CCS_1}" INSTALLED_GPU_CCS_2)
		string(REPLACE " " ";" INSTALLED_GPU_CCS_3 "${INSTALLED_GPU_CCS_2}")
		string(REPLACE "." "" CUDA_ARCH_LIST "${INSTALLED_GPU_CCS_3}")
		SET(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_LIST})
		#SET(CMAKE_CUDA_ARCHITECTURES native)
		message(STATUS "CUDA detected architecture: ${CUDA_ARCH_LIST}")
		
        #find_package(CUDA)
        #CUDA_SELECT_NVCC_ARCH_FLAGS(ARCH_FLAGS)
        #message(STATUS ${ARCH_FLAGS})
        #SET(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${ARCH_FLAGS}")
        
        # This flag causes some kernel do not run, for some unknown reason
        #add_compile_options($<$<AND:$<COMPILE_LANGUAGE:CUDA>,$<CONFIG:Debug>>:-G>)
        add_link_options($<DEVICE_LINK:-dlink>)
                
	else()
		message(WARNING "No CUDA support")
	endif()
endif()


# ----------------------------------------------------------------------------
#  Build & install layouts
# ----------------------------------------------------------------------------
set(YACCLAB_EXECUTABLE_OUTPUT_PATH "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Output directory for applications")


# ----------------------------------------------------------------------------
# Solution folders
# ----------------------------------------------------------------------------

if(ENABLE_SOLUTION_FOLDERS)
  set_property(GLOBAL PROPERTY USE_FOLDERS ON)
  set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
endif()


# ----------------------------------------------------------------------------
# OpenCV 
# ----------------------------------------------------------------------------

#set(OpenCV_REQUIRED_PACKAGES "core;imgcodecs;imgproc" CACHE STRING "OpenCV packages required by YACCLAB are already set")
#string(FIND "${OpenCV_REQUIRED_PACKAGES}" "cudafeatures2d" cudafeatures2d_pos)
#if (YACCLAB_ENABLE_CUDA AND CMAKE_CUDA_COMPILER AND ${cudafeatures2d_pos} EQUAL -1) 
#	set(OpenCV_REQUIRED_PACKAGES "${OpenCV_REQUIRED_PACKAGES};cudafeatures2d" CACHE STRING "OpenCV packages required by YACCLAB are already set" FORCE)    
#endif()
set(OpenCV_REQUIRED_PACKAGES "core;imgcodecs;imgproc")
if (YACCLAB_ENABLE_CUDA AND CMAKE_CUDA_COMPILER) 
	set(OpenCV_REQUIRED_PACKAGES "${OpenCV_REQUIRED_PACKAGES};cudafeatures2d")    
endif()
message(STATUS "OpenCV required packages: ${OpenCV_REQUIRED_PACKAGES}")

FIND_PACKAGE(OpenCV REQUIRED ${OpenCV_REQUIRED_PACKAGES})
include_directories( ${OpenCV_INCLUDE_DIRS} )

if("${OpenCV_STATIC}" STREQUAL "ON" OR "${OpenCV_SHARED}" STREQUAL "OFF")
    message(STATUS "Setting static runtime for MSVC")
    set(YACCLAB_MSVC_RUNTIME_STATIC ON)	
endif()


# ----------------------------------------------------------------------------
# OpenMP
# ----------------------------------------------------------------------------

find_package(OpenMP)
message(STATUS "OpenMP found: ${OpenMP_CXX_FOUND}")
#if(OpenMP_CXX_FOUND)
#    add_compile_options("${OpenMP_CXX_FLAGS}")
#    include_directories(${OpenMP_CXX_INCLUDE_DIRS})
#endif()


# ----------------------------------------------------------------------------
# Utility
# ----------------------------------------------------------------------------
message(STATUS "OS: ${YACCLAB_OS}, OpenCV: ${OpenCV_VERSION}")
add_definitions(-DOPENCV_VERSION_MAJOR=${OpenCV_VERSION_MAJOR})
add_definitions(-DYACCLAB_OS="${YACCLAB_OS}")

# ----------------------------------------------------------------------------
# Project
# ----------------------------------------------------------------------------

include_directories("${CMAKE_SOURCE_DIR}/include")
include_directories("${CMAKE_SOURCE_DIR}/cuda/include")
include_directories("${CMAKE_INSTALL_PREFIX}") # To avoid linking error when a new file is added to the project directly from Visual Studio IDE

#SET_SOURCE_FILES_PROPERTIES("${CMAKE_SOURCE_DIR}/src/labeling_bolelli_2019.cc" PROPERTIES COMPILE_FLAGS "-O1")

add_definitions(-D_CRT_SECURE_NO_WARNINGS) #To suppress 'fopen' opencv warning/bug  


# ----------------------------------------------------------------------------
# Configuration file
# ----------------------------------------------------------------------------

if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/config.yaml" OR YACCLAB_FORCE_CONFIG_GENERATION)
    if(YACCLAB_CI_CPU)
        configure_file("${CMAKE_SOURCE_DIR}/doc/config_ci_cpu.yaml" "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp")
    elseif(YACCLAB_CI_CPU2D)
        configure_file("${CMAKE_SOURCE_DIR}/doc/config_ci_cpu2d.yaml" "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp")
    elseif(YACCLAB_IS_JENKINS)	
        configure_file("${CMAKE_SOURCE_DIR}/doc/config_jenkins.yaml" "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp")
    else()
        file(READ "${CMAKE_SOURCE_DIR}/doc/config_2d.yaml" YACCLAB_CONFIG_2D)

        if(YACCLAB_ENABLE_CUDA AND CMAKE_CUDA_COMPILER)
            file(READ "${CMAKE_SOURCE_DIR}/doc/config_cuda_2d.yaml" YACCLAB_CONFIG_CUDA_2D)
            if(YACCLAB_ENABLE_3D)
                file(READ "${CMAKE_SOURCE_DIR}/doc/config_cuda_3d.yaml" YACCLAB_CONFIG_CUDA_3D)
            endif()
        endif()

        if(YACCLAB_ENABLE_3D)
            if(YACCLAB_ENABLE_EPDT_19C)
                file(READ "${CMAKE_SOURCE_DIR}/doc/config_epdt_19c.yaml" YACCLAB_CONFIG_EPDT_19C)
            endif()
            if(YACCLAB_ENABLE_EPDT_22C)
                file(READ "${CMAKE_SOURCE_DIR}/doc/config_epdt_22c.yaml" YACCLAB_CONFIG_EPDT_22C)
            endif()
            if(YACCLAB_ENABLE_EPDT_26C)
                file(READ "${CMAKE_SOURCE_DIR}/doc/config_epdt_26c.yaml" YACCLAB_CONFIG_EPDT_26C)
            endif()
            set(YACCLAB_CONFIG_EPDT_ALGORITHMS "${YACCLAB_CONFIG_EPDT_19C}${YACCLAB_CONFIG_EPDT_22C}${YACCLAB_CONFIG_EPDT_26C}")
            configure_file("${CMAKE_SOURCE_DIR}/doc/config_3d.yaml" "${CMAKE_INSTALL_PREFIX}/config_3d.yaml.tmp")
            file(READ "${CMAKE_INSTALL_PREFIX}/config_3d.yaml.tmp" YACCLAB_CONFIG_3D)
            file(REMOVE "${CMAKE_INSTALL_PREFIX}/config_3d.yaml.tmp")
        endif()
        
        configure_file("${CMAKE_SOURCE_DIR}/doc/config_base.yaml" "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp")                
    endif()
    
    file(READ "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp" YACCLAB_CONFIG_FILE)
    file(REMOVE "${CMAKE_INSTALL_PREFIX}/config.yaml.tmp")
    
    #file(CONFIGURE OUTPUT "${CMAKE_INSTALL_PREFIX}/config.yaml" CONTENT "${YACCLAB_CONFIG_FILE}" NEWLINE_STYLE LF)     to be used with CMake >= 18
    file(GENERATE OUTPUT "${CMAKE_INSTALL_PREFIX}/config.yaml" CONTENT "${YACCLAB_CONFIG_FILE}")    
endif()

add_executable(${ProjectName} "${CMAKE_INSTALL_PREFIX}/config.yaml")
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${ProjectName}) # Set YACCLAB as startup group instead of ALL_BUILD
target_link_libraries (${ProjectName}  ${OpenCV_LIBS})
if(YACCLAB_MSVC_RUNTIME_STATIC)
    set_property(TARGET ${ProjectName} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
if(OpenMP_CXX_FOUND)
    target_link_libraries(${ProjectName} OpenMP::OpenMP_CXX)
endif()

# To be able to use __cplusplus macro to check C++ version
if(MSVC)
	target_compile_options(${ProjectName} PUBLIC $<$<COMPILE_LANGUAGE:CXX>:/Zc:__cplusplus>)
    #target_compile_options(${ProjectName} PUBLIC $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:__cplusplus>)
endif()

set_property(TARGET ${ProjectName} PROPERTY CUDA_SEPARABLE_COMPILATION ON)

# ----------------------------------------------------------------------------
# Output and datasets
# ----------------------------------------------------------------------------

# Set YACCLAB as startup group instead of ALL_BUILD
#set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT YACCLAB)

#target_link_libraries (${ProjectName} ${OpenCV_LIBS})

add_subdirectory(src)
add_subdirectory(include)
if(YACCLAB_ENABLE_CUDA AND CMAKE_CUDA_COMPILER)
    add_subdirectory(cuda/src)
    add_subdirectory(cuda/include)
    include_directories("${CUDA_INCLUDE_DIRS}")
    set_property(TARGET ${ProjectName} PROPERTY CUDA_SEPARABLE_COMPILATION ON)
endif()

source_group("Header Files" REGULAR_EXPRESSION "h$|hpp$")
source_group("Source Files" REGULAR_EXPRESSION "cc$|cpp$|c$")
source_group("Include Files" REGULAR_EXPRESSION "inc$|inc.h$")

if(YACCLAB_ENABLE_CUDA AND CMAKE_CUDA_COMPILER)
    source_group("Cuda Files" REGULAR_EXPRESSION "cu$")
endif()
# Creation of the output directory
if (NOT EXISTS "${YACCLAB_OUTPUT_RESULTS_PATH}")
		file(MAKE_DIRECTORY ${YACCLAB_OUTPUT_RESULTS_PATH})
endif()

message(STATUS ${CUDA_NVCC_FLAGS})

# Download and unpack dataset if necessary
if(YACCLAB_DOWNLOAD_DATASET)
    # Creation of input directory
    if (NOT EXISTS "${YACCLAB_INPUT_DATASET_PATH}")
        file(MAKE_DIRECTORY ${YACCLAB_INPUT_DATASET_PATH})
    endif()

    if (EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip")
        message(STATUS "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip already exists, download skipped!")
    else()
        message(STATUS "Downloading dataset...")
        file(DOWNLOAD http://imagelab.ing.unimore.it/files/YACCLAB_dataset_new.zip "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip" STATUS status SHOW_PROGRESS)
        list( GET status 0 error_code )
        if( error_code )
            message(ERROR " Cmake is not able to download the YACCLAB dataset. \nPlease, retry or download it manually and put all unzipped dataset directories in the 'input' path:\n'" ${YACCLAB_INPUT_DATASET_PATH} "'. \n(The dataset is available at http://imagelab.ing.unimore.it/files/YACCLAB_dataset_new.zip).")
            if(EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip")
                file(REMOVE "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip")
            endif()
        else()
            message(STATUS "Downloading done.")
        endif()

        if(EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip")
            message(STATUS "Unpacking (it may take a while)...")
            execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf "${YACCLAB_INPUT_DATASET_PATH}/dataset.zip" WORKING_DIRECTORY "${YACCLAB_INPUT_DATASET_PATH}" OUTPUT_QUIET)
            message(STATUS "Unpacking done.")
        endif()
    endif()

endif()

if (YACCLAB_DOWNLOAD_DATASET_3D)
	# Creation of input directory
	if (NOT EXISTS "${YACCLAB_INPUT_DATASET_PATH}")
		file(MAKE_DIRECTORY ${YACCLAB_INPUT_DATASET_PATH})
	endif()

	if (EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip")
		message(STATUS "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip already exists, download skipped!")
	else()
		message(STATUS "Downloading 3D dataset...")
		file(DOWNLOAD http://imagelab.ing.unimore.it/files/YACCLAB_dataset3D.zip "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip" STATUS status SHOW_PROGRESS)
		list( GET status 0 error_code )
		if( error_code )
			message(ERROR " Cmake is not able to download the YACCLAB 3D dataset. \nPlease, retry or download it manually and put all unzipped dataset directories in the 'input' path:\n'" ${YACCLAB_INPUT_DATASET_PATH} "'. \n(The dataset is available at http://imagelab.ing.unimore.it/files/YACCLAB_dataset3D.zip).")
			if(EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip")
				file(REMOVE "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip")
			endif()
		else()
			message(STATUS "Downloading done.")
		endif()
		
		if(EXISTS "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip")
			message(STATUS "Unpacking (it may take a while)...")
			execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf "${YACCLAB_INPUT_DATASET_PATH}/dataset3D.zip" WORKING_DIRECTORY "${YACCLAB_INPUT_DATASET_PATH}" OUTPUT_QUIET)
			message(STATUS "Unpacking done.")
		endif()
	endif()
endif()


================================================
FILE: Jenkinsfile
================================================
pipeline {
    agent none
    stages {
        stage('Parallel Stages') {
            parallel {
               stage('ubuntu16_gpu') {
                    agent {
                        docker { 
                            label 'docker && gpu'
                            image 'aimagelab/opencv4.4-cuda9.2-ubuntu16.04'
                            args '--gpus 1'
                        }
                    }
                    stages {
                        stage('Clean') {
                            steps {
                                timeout(15) {
                                    echo 'Cleaning..'
                                    sh 'rm -rf bin || true'
                                }
                            }
                        }
                        stage('Build') {
                            steps {
                                timeout(120) {
                                    echo 'Building..'
                                    sh 'chmod +x tools/jenkins-scripts/run-script.sh'
                                    sh 'export BUILD_TARGET=linux && tools/jenkins-scripts/run-script.sh'
                                }
                            }
                        }
                        stage('Run') {
                            steps {
                                timeout(600) {
                                    echo 'Running..'
                                    sh 'cd bin && ./YACCLAB'
                                }
                             }
                        }
                        stage('ubuntu16_gpu_end') {
                            steps {
                                echo 'Success!'
                            }
                        }
                    }
                }
                stage('ubuntu20_gpu') {
                    agent {
                        docker { 
                            label 'docker && gpu'
                            image 'aimagelab/opencv4.4-cuda11.4.1-ubuntu20.04'
                            args '--gpus 1'
                        }
                    }
                    stages {
                        stage('Clean') {
                            steps {
                                timeout(15) {
                                    echo 'Cleaning..'
                                    sh 'rm -rf bin || true'
                                }
                            }
                        }
                        stage('Build') {
                            steps {
                                timeout(120) {
                                    echo 'Building..'
                                    sh 'chmod +x tools/jenkins-scripts/run-script.sh'
                                    sh 'export BUILD_TARGET=linux && export CUDACXX=/usr/local/cuda/bin/nvcc && tools/jenkins-scripts/run-script.sh'
                                }
                            }
                        }
                        stage('Run') {
                            steps {
                                timeout(600) {
                                    echo 'Running..'
                                    sh 'cd bin && ./YACCLAB'
                                }
                            }
                        }
                        stage('ubuntu20_gpu_end') {
                            steps {
                                echo 'Success!'
                            }
                        }
                    }
                }
            }
        }
    }
}


================================================
FILE: LICENSE
================================================
BSD 3-Clause License

Copyright (c) 2020, the respective contributors, as shown by the AUTHORS file.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
# Yet Another Connected Components Labeling Benchmark
[![release](https://img.shields.io/github/v/release/prittt/YACCLAB)](https://github.com/prittt/YACCLAB/releases/latest/)
[![license](https://img.shields.io/github/license/prittt/YACCLAB)](https://github.com/prittt/YACCLAB/blob/master/LICENSE)<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END -->


<table>
<thead>
<tr>
    <th>OS</th>
    <th>Build</th>
    <th>Compiler</th>
    <th>OpenCV</th>
    <th>CMake</th>
    <th>GPU</th>
    <!--<th width="200px">Travis CI</th>-->
    <th width="200px">GitHub Actions</th>
    <th width="200px">Jenkins</th>
</tr>
<thead>
<tbody>
<!--
<tr>
    <td align="center">Ubuntu<br/>16.04 LTS</td>
    <td align="center">x32</td>
    <td align="center">gcc 5.4.0</td>
    <td align="center">3.0.0</td>
    <td align="center">3.13.5</td>
    <td align="center">None</td>
    <td align="center"><a href="https://github.com/prittt/YACCLAB/actions"><img src="https://github.com/prittt/YACCLAB/workflows/linux32/badge.svg?branch=master" alt="Build Status"/></a></td>
    <td align="center">N/A</td>
</tr>
-->
<tr>
    <td align="center">Ubuntu<br/>18.04 LTS</td>
    <td align="center">x64</td>
    <td align="center">gcc 9.3.0</td>
    <td align="center">4.1.2</td>
    <td align="center">3.13.5</td>
    <td align="center">None</td>
    <td align="center"><a href="https://github.com/prittt/YACCLAB/actions"><img src="https://github.com/prittt/YACCLAB/workflows/linux64/badge.svg?branch=master" alt="Build Status"/></a></td>
    <td align="center">N/A</td>
</tr>
<tr>
    <td align="center">MacOS<br/>(Darwin 19.6.0)</td>
    <td align="center">x64</td>
    <td align="center">AppleClang 12.0.0<br/>(Xcode-12)</td>
    <td align="center">3.1.0</td>
    <td align="center">3.13.0</td>
    <td align="center">None</td>
    <td align="center"><a href="https://github.com/prittt/YACCLAB/actions"><img src="https://github.com/prittt/YACCLAB/workflows/macos/badge.svg?branch=master" alt="Build Status"/></a></td>
    <td align="center">N/A</td>
</tr>
<tr>
    <td align="center">Ubuntu<br/>16.04 LTS</td>
    <td align="center">x64</td>
    <td align="center">gcc 5.4.0</td>
    <td align="center">4.4</td>
    <td align="center">3.10.3</td>
    <td align="center">2080Ti, CUDA 9.2</td>
    <td align="center">N/A</td>
    <td align="center"><a href="https://jenkins-master-deephealth-unix01.ing.unimore.it/job/YACCLAB/job/master/"><img src="https://jenkins-master-deephealth-unix01.ing.unimore.it/badge/job/YACCLAB/job/master/ubuntu16_gpu_end?" alt="Action Status"/></a></td>
</tr>
<tr>
    <td align="center">Ubuntu<br/>20.04.02 LTS</td>
    <td align="center">x64</td>
    <td align="center">gcc 9.3.0</td>
    <td align="center">4.4</td>
    <td align="center">3.10.3</td>
    <td align="center">2080Ti, CUDA 11.4</td>
    <td align="center">N/A</td>
    <td align="center"><a href="https://jenkins-master-deephealth-unix01.ing.unimore.it/job/YACCLAB/job/master/"><img src="https://jenkins-master-deephealth-unix01.ing.unimore.it/badge/job/YACCLAB/job/master/ubuntu20_gpu_end?" alt="Action Status"/></a></td>
</tr>
</tbody>
</table>

<p align="justify">Please include the following references when citing the YACCLAB project/dataset:</p>

- <p align="justify"> Allegretti, Stefano; Bolelli, Federico; Grana, Costantino "Optimized Block-Based Algorithms to Label Connected Components on GPUs." IEEE Transactions on Parallel and Distributed Systems, 2019. <a title="BibTex" href="https://federicobolelli.it/pub_files/2019tpds.html">BibTex</a>. <a title="Download" href="https://federicobolelli.it/pub_files/2019tpds.pdf">PDF</a>.</p>

- <p align="justify"> Bolelli, Federico; Cancilla, Michele; Baraldi, Lorenzo; Grana, Costantino "Towards Reliable Experiments on the Performance of Connected Components Labeling Algorithms" Journal of Real-Time Image Processing, 2018. <a title="BibTex" href="https://federicobolelli.it/pub_files/2018jrtip.html">BibTex</a>. <a title="Download" href="https://federicobolelli.it/pub_files/2018jrtip.pdf">PDF</a>.</p>

- <p align="justify"> Grana, Costantino; Bolelli, Federico; Baraldi, Lorenzo; Vezzani, Roberto "YACCLAB - Yet Another Connected Components Labeling Benchmark" Proceedings of the 23rd International Conference on Pattern Recognition, Cancun, Mexico, 4-8 Dec 2016. <a title="BibTex" href="https://federicobolelli.it/pub_files/2016icpr.html">BibTex</a>. <a title="Download" href="https://federicobolelli.it/pub_files/2016icpr.pdf">PDF</a>.</p>

<p align="justify">
YACCLAB is an open source <i>C++</i> project that enables researchers to test CCL algorithms under extremely variable points of view, running and testing algorithms on a collection of datasets described below. The benchmark performs the following tests which will be described later in this readme: <i>correctness</i>, average run-time (<i>average</i>), average run-time with steps (<i>average_ws</i>), <i>density</i>, <i>size</i>, <i>granularity</i> and memory accesses (<i>memory</i>).

Notice that 8-connectivity is always used in the project.
</p>

## Reproducible Research

<p align="justify">This project follows the Reproducible Research paradigms and received the <a href="https://github.com/RLPR">Reproducible Label in Pattern Recognition (RLPR)</a>.</p><img style="float: right;" src="/doc/EPDT/RRLPR.png">

## Requirements

<p align="justify">
To correctly install and run YACCLAB following packages, libraries and utilities are needed:

- CMake 3.18 or higher (https://cmake.org);
- OpenCV 3.0 or higher (http://opencv.org), required packages are `core`, `imgcodecs`, `imgproc`;
- Gnuplot (http://www.gnuplot.info/);
- One of your favourite IDE/compiler with C++14 support.

GPU algorithms also require:
- CUDA Toolkit 9.2 or higher (https://developer.nvidia.com/cuda-toolkit) and OpenCV `cudafeatures2d` package (as of OpenCV 4.5.3, package dependencies entail that required packages for CUDA algorithms are `core`, `cudafeatures2d`, `cudaarithm`, `cudafilters`, `cudaimgproc`, `cudawarping`, `cudev`, `features2d`, `imgcodecs`, `imgproc`).

Notes for gnuplot:
- on Windows system: be sure add gnuplot to system path if you want YACCLAB automatically generates charts.
- on MacOS system: 'pdf terminal' seems to be not available due to old version of cairo, 'postscript' is used instead.

</p>

## Installation (refer to the image below)

- <p align="justify">Clone the GitHub repository (HTTPS clone URL: https://github.com/prittt/YACCLAB.git) or simply download the full master branch zip file and extract it (e.g YACCLAB folder).</p>
- <p align="justify">Install software in YACCLAB/bin subfolder (suggested) or wherever you want using CMake (point 2 of the example image). Note that CMake should automatically find the OpenCV path whether correctly installed on your OS (3), download the YACCLAB Dataset (be sure to check the box if you want to download it (4a) and (4b) or to select the correct path if the dataset is already on your file system (7)), and create a C++ project for the selected IDE/compiler (9-10). Moreover, if you want to test 3D or GPU algorithms tick the corresponding boxes (5) and (6). </p>

![Cmake](doc/readme_github.png)

- <p align="justify">Set the <a href="#conf">configuration file (config.yaml)</a> placed in the installation folder (bin in this example) in order to select desired tests.</p>

- <p align="justify">Open the project, compile and run it: the work is done!</p>

### CMake Configuration Variables

| Name                                 | Meaning                     | Default | 
| ------------------------------------ |-----------------------------| --------|
| `YACCLAB_DOWNLOAD_DATASET`           | whether to automatically download the 2D YACCLAB dataset or not  | `OFF` |
| `YACCLAB_DOWNLOAD_DATASET_3D`        | whether to automatically download the 3D YACCLAB dataset or not  | `OFF` |
| `YACCLAB_ENABLE_3D`                  | enable/disable the support for 3D algorithms | `OFF` |
| `YACCLAB_ENABLE_CUDA`                | enable/disable CUDA support | `OFF`   |
| `YACCLAB_ENABLE_EPDT_19C`     | enable/disable the EPDT_19C 3D algorithm which is based on a heuristic decision tree generated from a 3D mask with 19 conditions (may noticeably increase compilation time), it has no effect when YACCLAB_ENABLE_3D is `OFF` | `OFF` |
| `YACCLAB_ENABLE_EPDT_22C`     | enable/disable the EPDT_22C 3D algorithm which is based on a heuristic decision tree generated from a 3D mask with 22 conditions (may noticeably increase compilation time), it has no effect when YACCLAB_ENABLE_3D is `OFF` | `OFF` |
| `YACCLAB_ENABLE_EPDT_26C`     | enable/disable the EPDT_26C 3D algorithm which is based on a heuristic decision tree generated from a 3D mask with 26 conditions (may noticeably increase compilation time), it has no effect when YACCLAB_ENABLE_3D is `OFF` | `OFF` |
| `YACCLAB_FORCE_CONFIG_GENERATION`     | whether to force the generation of the default configuration file (`config.yaml`) or not. When this flag is turned `OFF` any existing configuration file will not be overwritten   | `OFF` |
| `YACCLAB_INPUT_DATASET_PATH`         | path to the `input` dataset folder, where to find test datasets  | `${CMAKE_INSTALL_PREFIX}/input` |
| `YACCLAB_OUTPUT_RESULTS_PATH`        | path to the `output` folder, where to save output results  | `${CMAKE_INSTALL_PREFIX}/output` |
| `OpenCV_DIR`                         | OpenCV installation path    |  -      |

## How to include a YACCLAB algorithm into your own project?

<p align="justify">If your project requires a Connected Components Labeling algorithm and you are not interested in the whole YACCLAB benchmark you can use the <i>connectedComponent</i> function of the OpenCV library which implements the BBDT and SAUF algorithms since version 3.2., Spaghetti Labeling algorithm and BKE (for GPU only) since version 4.6.</p>
<p align="justify">Anyway, when the <i>connectedComponents</i> function is called, a lot of additional code will be executed together with the core function. If your project requires the best performance you can include an algorithm implemented in YACCLAB adding the following files to your project:</p>
<ol>
  <li><i>labeling_algorithms.h</i> and <i>labeling_algorithms.cc</i> which define the base class from which every algorithm derives from;</li>
  <li><i>yacclab_tensor.h</i>, <i>yacclab_tensor.cc</i> which define input and output data tensors;</li>
  <li><i>label_solver.h</i> and <i>label_solver.cc</i> which cointain the implementation of labels solving algorithms;</li>
  <li><i>memory_tester.h</i>, <i>performance_evaluator.h</i>, <i>volume_util.h</i>, <i>volume_util.cc</i>, <i>utilities.h</i>, <i>utilities.cc</i>, <i>system_info.h</i>, <i>system_info.cc</i>, <i>check_labeling.h</i>, <i>check_labeling.cc</i>, <i>file_manager.h</i>, <i>file_manager.cc</i>, <i>stream_demultiplexer.h</i>, <i>config_data.h</i>, <i>register.h</i>, <i>yacclab_test.h</i>, <i>progress_bar.h</i>, <i>cuda_mat3.hpp</i>, <i>cuda_types3.hpp</i>, and <i>cuda_mat3.inl.hpp</i> just to make things work without changing the code;</li>
  <li><i>headers</i> and <i>sources</i> files of the required algorithm/s. The association between algorithms and headers/sources files is reported in the tables below.</li>
</ol>  

### 2D/3D CPU Algorithms

 <table>
  <tr>
    <th>Algorithm Name</th>
    <th width="130">Authors</th>
    <th>Year</th>
    <th>Acronym</th>
    <th>Required Files</th>
    <th>Templated on Labels Solver</th>
  </tr>	
  <tr>
    <td align="center">-</td>
    <td align="center">L. Di Stefano,<br>A. Bulgarelli  <a href="#DiStefano">[3]</a></td>
    <td align="center">1999</td>
    <td align="center">DiStefano</td>
    <td align="center"><i>labeling_distefano_1999.h</i></td>
    <td align="center">❌</td>
  </tr>
  <tr>
    <td align="center">Contour Tracing</td>
    <td align="center">F. Chang,</br>C.J. Chen,</br>C.J. Lu  <a href="#CT">[1]</a></td>
    <td align="center">1999</td>
    <td align="center">CT</td>
    <td align="center"><i>labeling_fchang_2003.h</i></td>
    <td align="center">❌</td>
  </tr>
  <tr>
    <td align="center">Run-Based Two-Scan</td>
    <td align="center">L. He,</br>Y. Chao,</br>K. Suzuki  <a href="#RBTS">[30]</a></td>
    <td align="center">2008</td>
    <td align="center">RBTS</td>
    <td align="center"><i>labeling_he_2008.h</i></td>
    <td align="center">	✔</td>
  </tr>
  <tr>
    <td align="center">Scan Array-based with Union Find</td>
    <td align="center">K. Wu,</br>E. Otoo,</br>K. Suzuki  <a href="#SAUF">[6]</a></td>
    <td align="center">2009</td>
    <td align="center">SAUF</td>
    <td align="center"><i>labeling_wu_2009.h</i>, <i>labeling_wu_2009_tree.inc</i></td>
    <td align="center">	✔</td>
  </tr>
    <tr>
    <td align="center">Stripe-Based Labeling Algorithm</td>
    <td align="center">H.L. Zhao,</br>Y.B. Fan,</br>T.X. Zhang,</br>H.S. Sang  <a href="#SBLA">[8]</a></td>
    <td align="center">2010</td>
    <td align="center">SBLA</td>
    <td align="center"><i>labeling_zhao_2010.h</i></td>
    <td align="center">❌</td>
  </tr>
  <tr>
    <td align="center">Block-Based with Decision Tree</td>
    <td align="center">C. Grana,</br>D. Borghesani,</br>R. Cucchiara  <a href="#BBDT">[4]</a></td>
    <td align="center">2010</td>
    <td align="center">BBDT</td>
    <td align="center"><i>labeling_grana_2010.h</i>, <i>labeling_grana_2010_tree.inc</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Configuration Transition Based</td>
    <td align="center">L. He,</br>X. Zhao,</br>Y. Chao,</br>K. Suzuki  <a href="#CTB">[7]</a></td>
    <td align="center">2014</td>
    <td align="center">CTB</td>
    <td align="center"><i>labeling_he_2014.h</i>, <i>labeling_he_2014_graph.inc</i>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Block-Based with Binary Decision Trees</td>
    <td align="center">W.Y. Chang,</br>C.C. Chiu,</br>J.H. Yang  <a href="#CCIT">[2]</a></td>
    <td align="center">2015</td>
    <td align="center">CCIT</td>
    <td align="center"><i>labeling_wychang_2015.h</i>, <i>labeling_wychang_2015_tree.inc</i>, <i>labeling_wychang_2015_tree_0.inc</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Light Speed Labeling</td>
    <td align="center">L. Cabaret,</br>L. Lacassagne,</br>D. Etiemble  <a href="#LSL_STD">[5]</a></td>
    <td align="center">2016</td>
    <td align="center">LSL_STD<a href="#I"><sup>I</sup></a></br>LSL_STDZ<a href="#II"><sup>II</sup></a></br>LSL_RLE<a href="#III"><sup>III</sup></a></td>
    <td align="center"><i>labeling_lacassagne_2016.h</i>, <i>labeling_lacassagne_2016_code.inc</i></td>
    <td align="center">✔<a href="#IV"><sup>IV</sup></a></td>
  </tr>
  <tr>
    <td align="center">Pixel Prediction</td>
    <td align="center">C.Grana,</br>L. Baraldi,</br>F. Bolelli  <a href="#PRED">[9]</a></td>
    <td align="center">2016</td>
    <td align="center">PRED</td>
    <td align="center"><i>labeling_grana_2016.h</i>, <i>labeling_grana_2016_forest.inc</i>, <i>labeling_grana_2016_forest_0.inc</i>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Directed Rooted Acyclic Graph</td>
    <td align="center">F. Bolelli,</br>L. Baraldi,</br>M. Cancilla,</br>C. Grana  <a href="#DRAG">[23]</a></td>
    <td align="center">2018</td>
    <td align="center">DRAG</td>
    <td align="center"><i>labeling_bolelli_2018.h</i>, <i>labeling_grana_2018_drag.inc</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Spaghetti Labeling</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>L. Baraldi,</br>C. Grana <a href="#SPAGHETTI">[26]</a></td>
    <td align="center">2019</td>
    <td align="center">Spaghetti</td>
    <td align="center"><i>labeling_bolelli_2019.h</i>, <i>labeling_bolelli_2019_forest.inc</i>, <i>labeling_bolelli_2019_forest_firstline.inc</i>, <i>labeling_bolelli_2019_forest_lastline.inc</i>, <i>labeling_bolelli_2019_forest_singleline.inc</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">PRED++</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">PREDpp</td>
    <td align="center"><i>labeling_PREDpp_2021.h</i>, <i>labeling_PREDpp_2021_center_line_forest_code.inc.h</i>, <i>labeling_PREDpp_2021_first_line_forest_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Tagliatelle Labeling</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">Tagliatelle</td>
    <td align="center"><i>labeling_tagliatelle_2021.h</i>, <i>labeling_tagliatelle_2021_center_line_forest_code.inc.h</i>, <i>labeling_tagliatelle_2021_first_line_forest_code.inc.h</i>, <i>labeling_tagliatelle_2021_last_line_forest_code.inc.h</i>, <i>labeling_tagliatelle_2021_single_line_forest_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Bit-Run Two Scan</td>
    <td align="center">W. Lee,</br>F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#BRTS">[32]</a></td>
    <td align="center">2021</td>
    <td align="center">BRTS<a href="#VII"><sup>VII</sup></a></td>
    <td align="center"><i>labeling_lee_2021_brts.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">Bit-Merge-Run Scan</td>
    <td align="center">W. Lee,</br>F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#BRTS">[32]</a></td>
    <td align="center">2021</td>
    <td align="center">BMRS<a href="#VII"><sup>VII</sup></a></td>
    <td align="center"><i>labeling_lee_2021_bmrs.h</i></td>
    <td align="center">✔</td>
  </tr>
    <tr>
    <td align="center">Null Labeling</td>
    <td align="center">F. Bolelli,</br>M. Cancilla,</br>L. Baraldi,</br>C. Grana <a href="#YACCLAB_JRTIP">[13]</a></td> 
    <td align="center">-</td>
    <td align="center">NULL<a href="#V"><sup>V</sup></a></td>
    <td align="center"><i>labeling_null.h</i></td>
    <td align="center">❌</td>
  </tr>
  <tr style="border-top:5px solid black; !important">
    <td align="center">SAUF 3D</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">SAUF_3D</td>
    <td align="center"><i>labeling3D_SAUF_2021.h</i>, <i>labeling3D_SAUF_2021_tree_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">SAUF++ 3D</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">SAUFpp_3D</td>
    <td align="center"><i>labeling3D_SAUFpp_2021.h</i>, <i>labeling3D_SAUFpp_2021_tree_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">PRED 3D</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">PRED_3D</td>
    <td align="center"><i>labeling3D_PRED_2021.h</i>, <i>labeling3D_PRED_2021_center_line_forest_code.inc.h</i>, <i>labeling3D_PRED_2021_first_line_forest_code.inc.h</i>, <i>labeling3D_PRED_2021_last_line_forest_code.inc.h</i>, <i>labeling3D_PRED_2021_single_line_forest_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
  <tr>
    <td align="center">PRED++ 3D</td>
    <td align="center">F. Bolelli,</br>S. Allegretti,</br>C. Grana <a href="#DAG">[33]</a></td>
    <td align="center">2021</td>
    <td align="center">PREDpp_3D</td>
    <td align="center"><i>labeling3D_PREDpp_2021.h</i>, <i>labeling3D_PREDpp_2021_center_line_forest_code.inc.h</i>, <i>labeling3D_PREDpp_2021_first_line_forest_code.inc.h</i>, <i>labeling3D_PREDpp_2021_last_line_forest_code.inc.h</i>, <i>labeling3D_PREDpp_2021_single_line_forest_code.inc.h</i></td>
    <td align="center">✔</td>
  </tr>
<tr>
    <td align="center">Entropy Partitioning Decision Tree <a href="https://github.com/prittt/YACCLAB/tree/master/doc/EPDT">RLPR</a></td>
    <td align="center">M. Söchting,</br>S. Allegretti,</br>F. Bolelli,</br>C. Grana <a href="#EPDT">[31]</a></td>
    <td align="center">2021</td>
    <td align="center">EPDT_19c and EPDT_22c<a href="#VI"><sup>VI</sup></a></td>
    <td align="center"><i>labeling3D_BBDT_2019.h</i>, <i>labeling_bolelli_2019_forest.inc</i>, <i>labeling_bolelli_2019_forest_firstline.inc</i>, <i>labeling_bolelli_2019_forest_lastline.inc</i>, <i>labeling_bolelli_2019_forest_singleline.inc</i></td>
    <td align="center">✔</td>
  </tr>
</table>

<a name="I"><sup>I</sup></a> standard version. </br>
<a name="II"><sup>II</sup></a> with zero-offset optimization. </br>
<a name="III"><sup>III</sup></a> with RLE compression. </br>
<a name="IV"><sup>IV</sup></a> only on TTA and UF. </br>
<a name="V"><sup>V</sup></a> it only copies the pixels from the input image to the output one simply defining a lower bound limit for the execution time of CCL algorithms on a given machine and dataset.</br>
<a name="VI"><sup>VI</sup></a> EPDT_19c and EPDT_22c algorithms are based on very big decision trees that translate to many lines of C++ code. They may thus noticeably increase the build time. For this reason, a special flag (`YACCLAB_ENABLE_EPDT_ALGOS`) to enable/disable such algorithms is provided in the CMake file. By default the flag is OFF.</br>
<a name="VII"><sup>VII</sup></a> CCL algorithm for images in bitonal (1 bit per pixel) format. When applied to these algorithms, the <i>average</i> tests also consider the time for 1 byte to 1 bit per pixel conversion. On the other hand, when performing <i>average with steps</i> tests conversion time is ignored.

### 2D/3D GPU Algorithms
 <table>
  <tr>
    <th>Algorithm Name</th>
    <th width="130">Authors</th>
    <th>Year</th>
    <th>Acronym</th>
    <th>Required Files</th>
    <th>2D/3D</th>
  </tr>	
  <tr>
    <td align="center">Union Find</td>
    <td align="center">V. Oliveira,</br>R. Lotufo <a href="#UF">[18]</a></td>
    <td align="center">2010</td>
    <td align="center">UF</td>
    <td align="center"><i>labeling_oliveira_2010.cu</i></td>
    <td align="center">2D and 3D</td>
  </tr>
  <tr>
    <td align="center">Optimized</br>Label Equivalence</td>
    <td align="center">O. Kalentev,</br>A. Rai,</br>S. Kemnitz,</br>R. Schneider <a href="#OLE">[19]</a></td>
    <td align="center">2011</td>
    <td align="center">OLE</td>
    <td align="center"><i>labeling_kalentev_2011.cu</i></td>
    <td align="center">2D</td>
  </tr>
    <tr>
    <td align="center">Block-run-based</td>
    <td align="center">P. Chen,</br>H.L. Zhao,</br>C. Tao,</br>H.S. Sang <a href="#BRB">[25]</a></td>
    <td align="center">2011</td>
    <td align="center">BRB</td>
    <td align="center"><i>labeling_chen_2011.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Stava</td>
    <td align="center">O. Stava,</br>B. Benes <a href="#STAVA">[38]</a></td>
    <td align="center">2011</td>
    <td align="center">STAVA</td>
    <td align="center"><i>labeling_stava_2011.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Rasmusson</td>
    <td align="center">A. Rasmusson,</br>T.S. Sørensen,</br>G. Ziegler <a href="#RASMUSSON">[37]</a></td>
    <td align="center">2013</td>
    <td align="center">RASMUSSON</td>
    <td align="center"><i>labeling_rasmusson_2013.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Accelerated CCL</td>
    <td align="center">F. N. Paravecino,</br>D. Kaeli <a href="#ACCL">[34]</a></td>
    <td align="center">2014</td>
    <td align="center">ACCL</td>
    <td align="center"><i>labeling_paravecino_2014.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">8-Directional Label Selection</td>
    <td align="center">Y. Soh,</br>H. Ashraf,</br>Y. Hae,</br>I. Kim <a href="#8DLS">[36]</a></td>
    <td align="center">2014</td>
    <td align="center">DLS</td>
    <td align="center"><i>labeling_soh_2014_8DLS.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Modified 8-Directional Label Selection</td>
    <td align="center">Y. Soh,</br>H. Ashraf,</br>Y. Hae,</br>I. Kim <a href="#8DLS">[36]</a></td>
    <td align="center">2014</td>
    <td align="center">M8DLS</td>
    <td align="center"><i>labeling_soh_2014_M8DLS.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Line-based Union-Find</td>
    <td align="center">K. Yonehara,</br>K. Aizawa <a href="#LBUF">[39]</a></td>
    <td align="center">2015</td>
    <td align="center">LBUF</td>
    <td align="center"><i>labeling_yonehara_2015.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Block Equivalence</td>
    <td align="center">S. Zavalishin,</br>I. Safonov,</br>Y. Bekhtin,</br>I. Kurilin <a href="#BE">[20]</a></td>
    <td align="center">2016</td>
    <td align="center">BE</td>
    <td align="center"><i>labeling_zavalishin_2016.cu</i></td>
    <td align="center">2D and 3D</td>
  </tr>
  <tr>
    <td align="center">Distanceless</br>Label Propagation</td>
    <td align="center">L. Cabaret,</br>L. Lacassagne,</br>D. Etiemble <a href="#DLP">[21]</a></td>
    <td align="center">2017</td>
    <td align="center">DLP</td>
    <td align="center"><i>labeling_cabaret_2017.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Komura Equivalence (8-conn)</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>M. Cancilla,</br>C. Grana <a href="#KE">[22]</a></td>
    <td align="center">2018</td>
    <td align="center">KE</td>
    <td align="center"><i>labeling_allegretti_2018.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Hardware Accelerated</br>4-connected</td>
    <td align="center">A. Hennequin,</br>L. Lacassagne,</br>L. Cabaret,</br>Q. Meunier <a href="#HA4">[35]</a></td>
    <td align="center">2018</td>
    <td align="center">HA4</td>
    <td align="center"><i>labeling_hennequin_2018_HA4.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Hardware Accelerated</br>8-connected</td>
    <td align="center">A. Hennequin,</br>L. Lacassagne,</br>L. Cabaret,</br>Q. Meunier <a href="#HA4">[35]</a></td>
    <td align="center">2018</td>
    <td align="center">HA8</td>
    <td align="center"><i>labeling_hennequin_2018_HA8.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">CUDA SAUF</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>M. Cancilla,</br>C. Grana <a href="#CAIP">[29]</a></td>
    <td align="center">2019</td>
    <td align="center">C-SAUF</td>
    <td align="center"><i>labeling_allegretti_2019_SAUF.cu</i>,</br><i>labeling_wu_2009_tree.inc</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">CUDA BBDT</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>M. Cancilla,</br>C. Grana <a href="#CAIP">[29]</a></td>
    <td align="center">2019</td>
    <td align="center">C-BBDT</td>
    <td align="center"><i>labeling_allegretti_2019_BBDT.cu</i>, <i>labeling_grana_2010_tree.inc</i></td>
    <td align="center">2D</td>
  </tr>
    <tr>
    <td align="center">CUDA DRAG</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>M. Cancilla,</br>C. Grana <a href="#CAIP">[29]</a></td>
    <td align="center">2019</td>
    <td align="center">C-DRAG</td>
    <td align="center"><i>labeling_allegretti_2019_DRAG.cu</i></td>
    <td align="center">2D</td>
  </tr>
  <tr>
    <td align="center">Block-based Union Find</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>C. Grana <a href="#BUF_BKE">[24]</a></td>
    <td align="center">2019</td>
    <td align="center">BUF</td>
    <td align="center"><i>labeling_allegretti_2019_BUF.cu</i></td>
    <td align="center">2D and 3D</td>
  </tr>
    <tr>
    <td align="center">Block-based Komura Equivalence</td>
    <td align="center">S. Allegretti,</br>F. Bolelli,</br>C. Grana <a href="#BUF_BKE">[24]</a></td>
    <td align="center">2019</td>
    <td align="center">BKE</td>
    <td align="center"><i>labeling_allegretti_2019_BKE.cu</i></td>
    <td align="center">2D and 3D</td>
  </tr>
</table>

### Example of Algorithm Usage Outside the Benchmark

```c++
#include "labels_solver.h"
#include "labeling_algorithms.h"
#include "labeling_grana_2010.h" // To include the algorithm code (BBDT in this example)

#include <opencv2/opencv.hpp>

using namespace cv;

int main()
{
    BBDT<UFPC> BBDT_UFPC; // To create an object of the desired algorithm (BBDT in this example)
                          // templated on the labels solving strategy. See the README for the
                          // complete list of the available labels solvers, available algorithms
                          // (N.B. non all the algorithms are templated on the solver) and their
                          // acronyms.

    BBDT_UFPC.img_ = imread("test_image.png", IMREAD_GRAYSCALE); // To load into the CCL object
                                                                 // the BINARY image to be labeled

    threshold(BBDT_UFPC.img_, BBDT_UFPC.img_, 100, 1, THRESH_BINARY); // Just to be sure that the
                                                                      // loaded image is binary

    BBDT_UFPC.PerformLabeling(); // To perform Connected Components Labeling!

    Mat1i output = BBDT_UFPC.img_labels_; // To get the output labeled image  
    unsigned n_labels = BBDT_UFPC.n_labels_; // To get the number of labels found in the input img

    return EXIT_SUCCESS;
}
```

<a name="conf"></a>
## Configuration File
<p align="justify">A <tt>YAML</tt> configuration file placed in the installation folder lets you specify which kinds of tests should be performed, on which datasets and on which algorithms.
Four categories of algorithms are supported: 2D CPU, 2D GPU, 3D CPU and 3D GPU. For each of them, the configuration parameters are reported below. </p>

- <i>execute</i> - boolean value which specifies whether the current category of algorithms will be tested: 
```yaml
execute:    true
```

- <i>perform</i> - dictionary which specifies the <a href="#conf">kind of tests</a> to perform: 
```yaml
perform:
  correctness:        false
  average:            true
  average_with_steps: false
  density:            false
  granularity:        false
  memory:             false
  blocksize:          false 
```

- <i>correctness_tests</i> - dictionary indicating the kind of correctness tests to perform:
```yaml
correctness_tests:
  eight_connectivity_standard:  true
  eight_connectivity_steps:     true
  eight_connectivity_memory:    true
  eight_connectivity_blocksize: true      
```

- <i>tests_number</i> - dictionary which sets the number of runs for each test available:
```yaml
tests_number:
  average:            10
  average_with_steps: 10
  density:            10
  granularity:        10
```

- <i>algorithms</i> - list of algorithms on which apply the chosen tests:
```yaml
algorithms:
  - SAUF_RemSP
  - SAUF_TTA
  - BBDT_RemSP
  - BBDT_UFPC
  - CT
  - labeling_NULL
```

- <i>check_datasets</i>, <i>average_datasets</i>, <i>average_ws_datasets</i>, <i>memory_datasets</i> and <i>blocksize_datasets</i>- lists of <a href="#conf">datasets</a> on which, respectively, correctness, average, average_ws, memory and blocksize tests should be run:
<!--
- <i>check_datasets:</i> list of datasets on which CCL algorithms should be checked.
- <i>average_datasets:</i> list of datasets on which average test should be run.
- <i>average_ws_datasets:</i> list of datasets on which <i>average_ws</i> test should be run.
- <i>memory_datasets:</i> list of datasets on which memory test should be run.
-->
```yaml
...
average_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
...
```

- <i>blocksize</i> - only for the 2D GPU and 3D GPU categories, this dictionary configures <a href=#blocksize_test>blocksize test</a> parameters. For each axis, a list of three values specifies [\<first\>, \<last\>, \<step\>]:
```yaml
blocksize:
  x: [2, 64, 2]
  y: [2, 64, 2]
  z: [2, 64, 2]
```

<p style=text-align: justify;>Finally, the following configuration parameters are common to all categories.</p>

- <i>paths</i> - dictionary with both input (datasets) and output (results) paths. It is automatically filled by Cmake during the creation of the project:
```yaml
paths: {input: "<datasets_path>", output: "<output_results_path>"}
```

- <i>write_n_labels</i> - whether to report the number of connected components in the output files:
```yaml
write_n_labels: false
```

- <i>color_labels</i> - whether to output a colored version of labeled images during tests:
```yaml
color_labels: {average: false, density: false}
```

- <i>save_middle_tests</i> - dictionary specifying, separately for every test, whether to save the output of single runs, or only a summary of the whole test:
```yaml
save_middle_tests: {average: false, average_with_steps: false, density: false, granularity: false}
```

## How to Extend YACCLAB with New Algorithms

<p align="justify">YACCLAB has been designed with extensibility in mind, so that new resources can be easily integrated into the project. A CCL algorithm is coded with a <tt>.h</tt> header file (placed in the <tt>include</tt> folder), a <tt>.cc</tt> source file (placed in the <tt>src</tt> folder), and optional additional files containing a tree/drag definition (placed in the <tt>include</tt> folder).</p>

The source file should be as follows:
```c++
#include "<header_file_name>.h"

REGISTER_LABELING_WITH_EQUIVALENCES_SOLVERS(<algorithm_name>);
// Replace the above line with "REGISTER_LABELING(<algorithm_name>);" if the algorithm
// is not template on the equivalence solver algorithm.
```
The header file should follows the structure below (see <tt>include/labeling_bolelli_2018.h</tt> to have a complete example):
```c++

// [...]

template <typename LabelsSolver> // Remove this line if the algorithm is not template 
                                 // on the equivalence solver algorithm
class <algorithm_name> : public Labeling2D<Connectivity2D::CONN_8> { // the class must extend one of the labeling
                                                     // classes Labeling2D, Labeling3D, .. that
                                                     // are template on the connectivity type
                                                    
public:
    <algorithm_name>() {}

    // This member function should implement the labeling procedure reading data from the
    // input image "img_" (OpenCV Mat1b) and storing labels into the output one "img_labels_"
    // (OpenCV Mat1i)
    void PerformLabeling()
    {
      // [...]

      LabelsSolver::Alloc(UPPER_BOUND_8_CONNECTIVITY); // Memory allocation of the labels solver
      LabelsSolver::Setup(); // Labels solver initialization

      // [...]
      
      LabelsSolver::GetLabel(<label_id>) // To get label value from its index
      LabelsSolver::NewLabel(); // To create a new label

      LabelsSolver::Flatten(); // To flatten the equivalence solver array
    }

    // This member function should implement the with step version of the labeling procedure.
    // This is required to perform tests with steps.
    void PerformLabelingWithSteps()
    {

      double alloc_timing = Alloc(); // Alloc() should be a member function responsible
                                     // for memory allocation of the required data structures

      perf_.start();
      FirstScan(); // FirsScan should be a member function that implements the 
                   // first scan step of the algorithm (if it has one)
      perf_.stop();
      perf_.store(Step(StepType::FIRST_SCAN), perf_.last());

      perf_.start();
      SecondScan(); // SecondScan should be a member function that implements the 
                    // second scan step of the algorithm (if it has one)
      perf_.stop();
      perf_.store(Step(StepType::SECOND_SCAN), perf_.last());

      // If the algorithm does not have a distinct firs and second scan replace the lines
      // above with the following ones:
      // perf_.start();
      // AllScans(); // AllScans() should be a member function which implements the entire
                     // algorithm but the allocation/deallocation 
      // perf_.stop();
      // perf_.store(Step(StepType::ALL_SCANS), perf_.last());

      perf_.start();
      Dealloc(); // Dealloc() should be a member function responsible for memory
                 // deallocation.
      perf_.stop();
      perf_.store(Step(StepType::ALLOC_DEALLOC), perf_.last() + alloc_timing);

      // [...]
    }

    // This member function should implement the labeling procedure using the OpenCV Mat
    // wrapper (MemMat) implemented by YACCLAB 
    void PerformLabelingMem(std::vector<uint64_t>& accesses){
      // [...]
    }

}
```

When implementing a GPU algorithm only the <tt>.cu</tt> file is required. The file should be placed in the <tt>cuda/src</tt> folder. The general structure of a GPU algorithm is the following:
```c++

// [...]

// Kernel definitions:

__global__ void <kernel_name_1>(...)
{
  ...
}

__global__ void <kernel_name_2>(...)
{
  ...
}
                                 
class <algorithm_name> : public GpuLabeling2D<Connectivity2D::CONN_8> { // the class must extend one of the labeling
                                                     // classes GpuLabeling2D, GpuLabeling3D, .. that
                                                     // are template on the connectivity type
                                                    
public:
    <algorithm_name>() {}

    // This member function should implement the labeling procedure reading data from the
    // input image "d_img_" (OpenCV cuda::GpuMat) and storing labels into the output one "d_img_labels_"
    // (OpenCV cuda::GpuMat)
    void PerformLabeling()
    {
      // Create the output image
      d_img_labels_.create(d_img_.size(), CV_32SC1);

      // [...]

      // Call necessary kernels
      <kernel_name_1> <<<...>>> (...);

      <kernel_name_2> <<<...>>> (...);

      // [...]
      
      // Wait for the end of the last kernel
      cudaDeviceSynchronize();
    }

    // This member function should implement the with step version of the labeling procedure.
    // This is required to perform tests with steps.
    void PerformLabelingWithSteps()
    {

      double alloc_timing = Alloc(); // Alloc() should be a member function responsible
                                     // for memory allocation of the required data structures

      perf_.start();
      FirstScan(); // FirsScan should be a member function that implements the 
                   // first scan step of the algorithm (if it has one)
      perf_.stop();
      perf_.store(Step(StepType::FIRST_SCAN), perf_.last());

      perf_.start();
      SecondScan(); // SecondScan should be a member function that implements the 
                    // second scan step of the algorithm (if it has one)
      perf_.stop();
      perf_.store(Step(StepType::SECOND_SCAN), perf_.last());

      // If the algorithm does not have a distinct first and second scan replace the lines
      // above with the following ones:
      // perf_.start();
      // AllScans(); // AllScans() should be a member function which implements the entire
                     // algorithm but the allocation/deallocation 
      // perf_.stop();
      // perf_.store(Step(StepType::ALL_SCANS), perf_.last());

      perf_.start();
      Dealloc(); // Dealloc() should be a member function responsible for memory
                 // deallocation.
      perf_.stop();
      perf_.store(Step(StepType::ALLOC_DEALLOC), perf_.last() + alloc_timing);

      // [...]
    }

    void PerformLabelingBlocksize(int x, int y, int z)
    {
      // Create the output image
      d_img_labels_.create(d_img_.size(), CV_32SC1);

      // [...]

      // Call necessary kernels through a macro that measures times separately
      BLOCKSIZE_KERNEL(<kernel_name_1>, <grid_size>, <block_size>, <dynamic_shared_mem>, <arguments>...);

      BLOCKSIZE_KERNEL(<kernel_name_2>, <grid_size>, <block_size>, <dynamic_shared_mem>, <arguments>...);

      // [...]
    }

}

REGISTER_LABELING(<algorithm_name>);

// Only necessary for blocksize test
REGISTER_KERNELS(<algorithm_name>, <kernel_name_1>, <kernel_name_2>, ...);

```

<p align="justify">Once an algorithm has been added to YACCLAB, it is ready to be tested and compared to the others. Don't forget to update the configuration file! We look at YACCLAB as a growing effort towards better reproducibility of CCL algorithms, so implementations of new and existing labeling methods are very welcome.</p>

<a name="datasets"></a>
## The YACCLAB Dataset
<p align="justify">The YACCLAB dataset includes both synthetic and real images and it is suitable for a wide range of applications, ranging from document processing to surveillance, and features a significant variability in terms of resolution, image density, variance of density, and number of components. All images are provided in 1 bit per pixel PNG format, with 0 (black) being background and 1 (white) being foreground. The dataset will be automatically downloaded by CMake during the installation process as described in the <a href="#inst">installation</a> paragraph.</p>

### 2D Datasets

- <b>MIRflickr <a href="#MIRFLICKR">[10]</a>:</b><p align="justify"> Otsu-binarized version of the MIRflickr dataset, publicly available under a Creative Commons License. It contains 25,000 standard resolution images taken from Flickr. These images have an average resolution of 0.17 megapixels, there are few connected components (495 on average) and are generally composed of not too complex patterns, so the labeling is quite easy and fast.</p>

- <b>Hamlet:</b><p align="justify"> A set of 104 images scanned from a version of the Hamlet found on Project Gutenberg (http://www.gutenberg.org). Images have an average amount of 2.71 million of pixels to analyze and 1447 components to label, with an average foreground density of 0.0789. </p>

- <b>Tobacco800 <a href="#TOBACCO1">[11]</a>,<a href="#TOBACCO2">[12]</a>:</b><p align="justify"> A set of 1290 document images. It is a realistic database for document image analysis research as these documents were collected and scanned using a wide variety of equipment over time. Resolutions of documents in Tobacco800 vary significantly from 150 to 300 DPI and the dimensions of images range from 1200 by 1600 to 2500 by 3200 pixels. Since CCL is one of the initial preprocessing steps in most layout analysis or OCR algorithms, hamlet and tobacco800 allow to test the algorithm performance in such scenarios. </p>

- <b>3DPeS <a href="#3DPES">[14]</a>:</b> <p align="justify"> It comes from 3DPeS (3D People Surveillance Dataset), a surveillance dataset designed mainly for people re-identification in multi camera systems with non-overlapped fields of view. 3DPeS can be also exploited to test many other tasks, such as people detection, tracking, action analysis and trajectory analysis. The background models for all cameras are provided, so a very basic technique of motion segmentation has been applied to generate the foreground binary masks, i.e.,  background subtraction and fixed thresholding. The analysis of the foreground masks to remove small connected components and for nearest neighbor matching is a common application for CCL. </p>

- <b>Medical <a href="#MEDICAL">[15]</a>:</b><p align="justify"> This dataset is composed by histological images and allow us to cover this fundamental medical field. The process used for nuclei segmentation and binarization is described in  <a href="#MEDICAL">[15]</a>. The resulting dataset is a collection of 343 binary histological images with an average amount of 1.21 million of pixels to analyze and 484 components to label. </p>

- <b>Fingerprints <a href="#FINGERPRINTS">[16]</a>:</b><p align="justify"> This dataset counts 960 fingerprint images collected by using low-cost optical sensors or synthetically generated. These images were taken from the three Verification Competitions FCV2000, FCV2002 and FCV2004. In order to fit CCL application, fingerprints have been binarized using an adaptive threshold and then negated in order to have foreground pixel with value 255. Most of the original images have a resolution of 500 DPI and their dimensions range from 240 by 320 up to 640 by 480 pixels. </p>

<table>
<tr>
  <td align="center"><img src="doc/sample_2D_datasets.png"></td>
</tr>
<tr>
  <td >Samples of the YACCLAB 2D (real) datasets.  From left to right: 3DPeS, Fingerprints, Medical, MIRflickr, Tobacco800, XDOCS, Hamlet.</td>
</tr>
</table>

- <b>Synthetic Images</b>:
	- <b>Classical <a href="#BBDT">[4]</a></b>:<p align="justify"> A set of synthetic random noise images who contain black and white random noise with 9 different foreground densities (10% up to 90%), from a low resolution of 32x32 pixels to a maximum resolution of 4096x4096 pixels, allowing to test the scalability and the effectiveness of different approaches when the number of labels gets high. For every combination of size and density, 10 images are provided for a total of 720 images. The resulting subset allows to evaluate performance both in terms of scalability on the number of pixels and on the number of labels (density). </p>
	- <b>Granularity <a href="#LSL">[5]</a> </b>:<p align="justify"> This dataset allows to test algorithms varying not only the pixels density but also their granularity <i>g</i> (<i>i.e.</i>, dimension of minimum foreground block), underlying the behaviour of different proposals when the number of provisional labels changes. All the images have a resolution of 2048x2048 and are generated with the Mersenne Twister MT19937 random number generator implemented in the <i>C++</i> standard and starting with a "seed" equal to zero. Density of the images ranges from 0% to 100% with step of 1% and for every density value 16 images with pixels blocks of <i>gxg</i> with <i>g</i> ∈ [1,16] are generated. Moreover, the procedure has been repeated 10 times for every couple of density-granularity for a total of 16160 images.</p>

<table>
<tr>
  <td align="center"><img src="doc/granularity_2D_datasets.png"></td>
</tr>
<tr>
  <td>Samples of the YACCLAB 2D granularity dataset: reported images have a foreground density of 30% and, from left to right, granularities are 1, 2, 4, 6, 8, 12, 14, 16.</td>
</tr>
</table>

### 3D Datasets

- <b>OASIS <a href="#OASIS">[27]</a></b>: <p align="justify"> This is a dataset of medical MRI data taken from the Open Access Series of Imaging Studies (OASIS) project. It consists of 373 volumes of 256 × 256 × 128 pixels, binarized with the Otsu threshold.</p> 

- <b>Mitochondria <a href="#MIT1">[28]</a></b>: <p align="justify">It is the Electron Microscopy Dataset, which contains binary sections taken from the CA1 hippocampus for a total of three volumes composed by 165 slices with a resolution of 1024 × 768 pixels.</p>

- <b>Hilbert <a href="#TPDS">[24]</a></b>: <p align="justify">This dataset contains six volumes of 128 × 128 × 128 pixels, filled with the 3D Hilbert curve obtained at different iterations (1 to 6) of the construction method. The Hilbert curve is a fractal space-filling curve that representsa challenging test case for the labeling algorithms.</p>

<table style="position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
<tr>
  <td align="center"><img src="doc/sample_3D_datasets.png"></td>
</tr>
<tr>
  <td>Samples of the YACCLAB 3D datasets. From left to right we have the Hilbert space-filling curve, the OASIS dataset and Mitochondria medical imaging data.</td>
</tr>
</table>

- <b>Granularity <a href="#TPDS">[24]</a></b>: <p align="justify">It contains 3D synthetic images generated as described for the 2D version. In this case, images have a resolution of 256 x 256 x 256 pixels and only three different images for every couple of density-granularity have been generated.</p>

<table style="position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
<tr>
  <td align="center"><img src="doc/granularity_3D_datasets.png" ></td>
</tr>
<tr>
  <td>Samples of the YACCLAB 3D granularity dataset: reported images have a foreground density of 2% and, from left to right, granularities are 4, 8, 16.</td>
</tr>
</table>

<a name="tests"></a>
## Available Tests

- <b>Average run-time tests:</b> <p align="justify"> execute an algorithm on every image of a dataset. The process can be repeated more times in a single test, to get the minimum execution time for each image: this allows to get more reproducible results and overlook delays produced by other running processes. It is also possible to compare the execution speed of different algorithms on the same dataset: in this case, selected algorithms (see <a href="#conf">Configuration File</a> for more details) are executed sequentially on every image of the dataset. Results are presented in three different formats: a plain text file, histogram charts (.pdf/.ps), either in color or in gray-scale, and a LaTeX table, which can be directly included in research papers.</p>

- <b>Average run-time tests with steps:</b> <p align="justify"> evaluates the performance of an algorithm separating the allocation/deallocation time from the time required to compute labeling. Moreover, if an algorithm employs multiple scans to produce the correct output labels, YACCLAB will store the time of every scan and will display them separately. To understand how YACCLAB computes the memory allocation time for an algorithm on a reference image, it is important to underline the subtleties involved in the allocation process. Indeed, all modern operating systems (not real-time, nor embedded ones, but certainly Windows and Unix) handle virtual memory exploiting a demand paging technique, <i>i.e</i> demand paging with no pre-paging for most of Unix OS and cluster demand paging for Windows OS. This means that a disk page is copied into physical memory only when it is accessed by a process the first time, and not when the allocation function is called. Therefore, it is not possible to calculate the exact allocation time required by an algorithm, which computes CCL on a reference image, but its upper bound can be estimated using the following approach:</p>

  - forcing the allocation of the entire memory by reserving it (<tt>malloc</tt>), filling it with zeros (<tt>memset</tt>), and tracing the time;  
  - calculating the time required by the assignment operation (<tt>memset</tt>), and subtracting it from the one obtained at the previous step;
  - repeating the previous points for all data structures needed by an algorithm and summing times together.

  <p align="justify">This will produce an upper bound of the allocation time because caches may reduce the second assignment operation, increasing the estimated allocation time. Moreover, in real cases, CCL algorithms may reserve more memory than they really need, but the <tt>demand paging</tt>, differently from our measuring system, will allocate only the accessed pages.</p>

- <b>Density and size tests:</b> <p align="justify"> check the performance of different CCL algorithms when they are executed on images with varying foreground density and size. To this aim, a list of algorithms selected by the user is run sequentially on every image of the test_random dataset. As for run-time tests, it is possible to repeat this test for more than one run. The output is presented as both plain text and charts(.pdf/.ps). For a density test, the mean execution time of each algorithm is reported for densities ranging from 10% up to 90%, while for a size test the same is reported for resolutions ranging from 32 x 32 up to 4096 x 4096.</p>

- <b>Memory tests:</b> <p align="justify"> are useful to understand the reason for the good performances of an algorithm or in general to explain its behavior. Memory tests compute the average number of accesses to the label image (i.e the image used to store the provisional and then the final labels for the connected components), the average number of accesses to the binary image to be labeled, and, finally, the average number of accesses to data structures used to solve the equivalences between label classes. Moreover, if an algorithm requires extra data, memory tests summarize them as ``other'' accesses and return the average. Furthermore, all average contributions of an algorithm and dataset are summed together in order to show the total amount of memory accesses. Since counting the number of memory accesses imposes additional computations, functions implementing memory access tests are different from those implementing run-time and density tests, to keep run-time tests as objective as possible.</p>

- <b>Granularity tests:</b> <p align="justify"> evaluates an algorithm varying density (from 1% to 100%, using a 1% step) and pixels granularity, but not images resolution. The output results display the average execution time over images with the same density and granularity.</p>

<a name="blocksize_test"></a>
- <b>Blocksize tests:</b> <p align="justify"> this test, which only makes sense for CUDA algorithms, is aimed at finding the best block size for each kernel with grid search parameter optimization. The range of values for each block axis can be specified in the configuration file. Given a set of CUDA algorithms, the blocksize test reports execution times of each kernel on one or multiple datasets, repeating the measurement for every different block size. Results are presented in a csv file. For every kernel, dataset and block size, the total execution time in ms is reported.</p>

## Examples of YACCLAB Output Results

<table>
  <tr>
    <td align="center"><img src="doc/fingerprints.png"/></td>
    <td align="center"><img src="doc/xdocs.png"/></td>
  </tr>
  <tr>
    <td align="center">Fingerprints</td>
    <td align="center">XDOCS</td>
  </tr>
</table>

## Contributors

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="http://www.federicobolelli.it"><img src="https://avatars3.githubusercontent.com/u/6863130?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Federico Bolelli</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=prittt" title="Code">💻</a> <a href="#projectManagement-prittt" title="Project Management">📆</a> <a href="#maintenance-prittt" title="Maintenance">🚧</a> <a href="#infra-prittt" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-prittt" title="Ideas, Planning, & Feedback">🤔</a></td>
    <td align="center"><a href="https://github.com/stal12"><img src="https://avatars2.githubusercontent.com/u/34423515?v=1?s=100" width="100px;" alt=""/><br /><sub><b>Stefano Allegretti</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=stal12" title="Code">💻</a> <a href="#maintenance-stal12" title="Maintenance">🚧</a> <a href="https://github.com/prittt/YACCLAB/issues?q=author%3Astal12" title="Bug reports">🐛</a> <a href="#ideas-stal12" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-stal12" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
    <td align="center"><a href="https://github.com/CostantinoGrana"><img src="https://avatars2.githubusercontent.com/u/18437151?v=1?s=100" width="100px;" alt=""/><br /><sub><b>Costantino Grana</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=CostantinoGrana" title="Code">💻</a> <a href="#projectManagement-CostantinoGrana" title="Project Management">📆</a> <a href="#ideas-CostantinoGrana" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-CostantinoGrana" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
    <td align="center"><a href="https://michelecancilla.github.io"><img src="https://avatars1.githubusercontent.com/u/22983812?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michele Cancilla</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=MicheleCancilla" title="Code">💻</a> <a href="#platform-MicheleCancilla" title="Packaging/porting to new platform">📦</a> <a href="#maintenance-MicheleCancilla" title="Maintenance">🚧</a></td>
    <td align="center"><a href="http://www.lorenzobaraldi.com"><img src="https://avatars3.githubusercontent.com/u/8173533?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lorenzo Baraldi</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=baraldilorenzo" title="Code">💻</a> <a href="#platform-baraldilorenzo" title="Packaging/porting to new platform">📦</a></td>
    <td align="center"><a href="http://msoechting.de"><img src="https://avatars1.githubusercontent.com/u/6423697?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maximilian Söchting</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/commits?author=msoechting" title="Code">💻</a></td>
  </tr>
  <tr>
    <td align="center"><a href="https://github.com/patrickhwood"><img src="https://avatars.githubusercontent.com/u/2100827?v=4?s=100" width="100px;" alt=""/><br /><sub><b>patrickhwood</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/issues?q=author%3Apatrickhwood" title="Bug reports">🐛</a></td>
    <td align="center"><a href="https://github.com/fengweichangzi"><img src="https://avatars.githubusercontent.com/u/87119815?v=4?s=100" width="100px;" alt=""/><br /><sub><b>WalnutVision</b></sub></a><br /><a href="https://github.com/prittt/YACCLAB/issues?q=author%3Afengweichangzi" title="Bug reports">🐛</a></td>
  </tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome.



## References

<table style="border:0;">
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="CT">[1]</a>
    </td>
    <td>
      <p align="justify">F. Chang, C.-J. Chen, and C.-J. Lu, “A linear-time component-labeling algorithm using contour tracing technique,” Computer Vision and Image Understanding, vol. 93, no. 2, pp. 206–220, 2004.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="CCIT">[2]</a>
    </td>
    <td>
      <p align="justify">W.-Y.  Chang,  C.-C.  Chiu,  and  J.-H.  Yang,  “Block-based  connected-component  labeling  algorithm  using  binary  decision  trees,” Sensors, vol. 15, no. 9, pp. 23 763–23 787, 2015.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
        <a name="DiStefano">[3]</a>
    </td>
    <td>
      <p align="justify"> L.  Di  Stefano  and  A.  Bulgarelli,  “A  Simple  and  Efficient  Connected Components Labeling Algorithm,” in International Conference on Image Analysis and Processing. IEEE, 1999, pp. 322–327.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="BBDT">[4]</a>
    </td>
    <td>
      <p align="justify">C.  Grana,  D.  Borghesani,  and  R.  Cucchiara,  “Optimized  Block-based Connected Components Labeling with Decision Trees,” IEEE Transac-tions on Image Processing, vol. 19, no. 6, pp. 1596–1609, 2010.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="LSL_STD">[5]</a>
    </td>
    <td>
      <p align="justify">L. Lacassagne and B. Zavidovique, “Light speed labeling: efficient connected component labeling on risc architectures,” Journal of Real-Time Image Processing, vol. 6, no. 2, pp. 117–135, 2011.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="SAUF">[6]</a>
    </td>
    <td>
      <p align="justify"> K. Wu, E. Otoo, and K. Suzuki, "Optimizing two-pass connected-component labeling algorithms,” Pattern Analysis and Applications," vol. 12, no. 2, pp. 117–135, 2009.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="CTB">[7]</a>
    </td>
    <td>
      <p align="justify">L.  He,  X.  Zhao,  Y.  Chao,  and  K.  Suzuki, "Configuration-Transition-Based Connected-Component Labeling", IEEE  Transactions  on  Image Processing, vol. 23, no. 2, pp. 943–951, 2014.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="SBLA">[8]</a>
    </td>
    <td>
      <p align="justify">H.  Zhao,  Y.  Fan,  T.  Zhang,  and  H.  Sang, "Stripe-based  connected components labelling," Electronics  letters,  vol.  46,  no.  21,  pp.  1434–1436, 2010.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="PRED">[9]</a>
    </td>
    <td>
      <p align="justify">C. Grana, L. Baraldi, and F. Bolelli, "Optimized Connected Components Labeling with Pixel Prediction," in Advanced  Concepts  for  Intelligent Vision Systems, 2016, pp. 431-440.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="MIRFLICKR">[10]</a>
    </td>
    <td>
      <p align="justify">M. J. Huiskes and M. S. Lew, “The MIR Flickr Retrieval Evaluation,” in MIR ’08: Proceedings of the 2008 ACM International Conference on Multimedia Information Retrieval. New York, NY, USA: ACM, 2008.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="TOBACCO1">[11]</a>
    </td>
    <td>
      <p align="justify">G. Agam, S. Argamon, O. Frieder, D. Grossman, and D. Lewis, “The Complex Document Image Processing (CDIP) Test Collection Project,” Illinois Institute of Technology, 2006.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="TOBACCO2">[12]</a>
    </td>
    <td>
      <p align="justify"> D. Lewis, G. Agam, S. Argamon, O. Frieder, D. Grossman, and J. Heard, “Building a test collection for complex document information processing,” in Proceedings of the 29th annual international ACM SIGIR conference on Research and development in information retrieval. ACM, 2006, pp. 665–666.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="YACCLAB_JRTIP">[13]</a>
    </td>
    <td>
      <p align="justify">F. Bolelli, M. Cancilla, L. Baraldi, C. Grana, "Towards Reliable Experiments on the Performance of Connected Components Labeling Algorithms," Journal of Real-Time Image Processing, 2018.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="3DPES">[14]</a>
    </td>
    <td>
      <p align="justify">D. Baltieri, R. Vezzani, and R. Cucchiara, “3DPeS: 3D People Dataset for Surveillance and Forensics,” in Proceedings of the 2011 joint ACM workshop on Human gesture and behavior understanding. ACM, 2011, pp. 59–64.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="MEDICAL">[15]</a>
    </td>
    <td>
      <p align="justify">F. Dong, H. Irshad, E.-Y. Oh, M. F. Lerwill, E. F. Brachtel, N. C. Jones, N. W. Knoblauch, L. Montaser-Kouhsari, N. B. Johnson, L. K. Rao et al., “Computational Pathology to Discriminate Benign from Malignant Intraductal Proliferations of the Breast,” PloS one, vol. 9, no. 12, p. e114885, 2014.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="FINGERPRINTS">[16]</a>
    </td>
    <td>
      <p align="justify">D. Maltoni, D. Maio, A. Jain, and S. Prabhakar, "Handbook of fingerprint recognition", Springer Science & Business Media, 2009.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="YACCLAB">[17]</a>
    </td>
    <td>
      <p align="justify">C.Grana, F.Bolelli, L.Baraldi, and R.Vezzani, "YACCLAB - Yet Another Connected Components Labeling Benchmark," Proceedings of the 23rd International Conference on Pattern Recognition, Cancun, Mexico, 4-8 Dec 2016, 2016.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="UF">[18]</a>
    </td>
    <td>
      <p align="justify">V. Oliveira and R. Lotufo, "A study on connected components labeling algorithms using GPUs," in SIBGRAPI. vol. 3, p. 4, 2010.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="OLE">[19]</a>
    </td>
    <td> 
      <p align="justify">O. Kalentev, A. Rai, S. Kemnitz, R. Schneider," Connected component labeling on a 2D grid using CUDA," in Journal of Parallel and Distributed Computing 71(4), 615–620, 2011.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="BE">[20]</a>
    </td>
    <td>
      <p align="justify">S. Zavalishin, I. Safonov, Y. Bekhtin, I. Kurilin, "Block Equivalence Algorithm for Labeling 2D and 3D Images on GPU," in Electronic Imaging 2016(2), 1–7, 2016.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="DLP">[21]</a>
    </td>
    <td>
      <p align="justify">L. Cabaret, L. Lacassagne, D. Etiemble, "Distanceless Label Propagation: an Efficient Direct Connected Component Labeling Algorithm for GPUs," in Seventh International Conference on Image Processing Theory, Tools and Applications, IPTA, 2017.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="KE">[22]</a>
    </td>
    <td>
      <p align="justify">S. Allegretti, F. Bolelli, M. Cancilla, C. Grana, "Optimizing GPU-Based Connected Components Labeling Algorithms," in Third IEEE International Conference on Image Processing, Applications and Systems, IPAS, 2018.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="DRAG">[23]</a>
    </td>
    <td>
      <p align="justify">F. Bolelli, L. Baraldi, M. Cancilla, C. Grana, "Connected Components Labeling on DRAGs," in International Conference on Pattern Recognition, 2018, pp. 121-126.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="BUF_BKE">[24]</a>
    </td>
    <td>
      <p align="justify">S. Allegretti, F. Bolelli, C. Grana, "Optimized Block-Based Algorithms to Label Connected Components on GPUs," in IEEE Transactions on Parallel and Distributed Systems, 2019.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="BRB">[25]</a>
    </td>
    <td>
      <p align="justify">
P. Chen, H. Zhao, C. Tao, H. Sang, "Block-run-based connected component labelling algorithm for gpgpu using shared memory." Electronics Letters, 2011</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="SPAGHETTI">[26]</a>
    </td>
    <td>
      <p align="justify">F. Bolelli, S. Allegretti, L. Baraldi, and C. Grana, "Spaghetti Labeling: Directed Acyclic Graphs for Block-Based Bonnected Components Labeling," IEEE Transactions on Image Processing, vol. 29, no. 1, pp. 1999-2012, 2019.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="OASIS">[27]</a>
    </td>
    <td>
      <p align="justify">D. S. Marcus, A. F. Fotenos, J. G. Csernansky, J. C. Morris, R. L. Buckner, “Open Access Series of Imaging Studies (OASIS): Longitudinal MRI Data in  Nondemented and Demented OlderAdults,” J. Cognitive Neurosci., vol. 22, no. 12, pp. 2677–2684, 2010.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="MIT1">[28]</a>
    </td>
    <td>
      <p align="justify">A. Lucchi, Y. Li, and P. Fua, “Learning for Structured Prediction Using Approximate Subgradient Descent with Working Sets,” in Proceedings of the IEEE Conference  on Computer Vision and Pattern Recognition, 2013, pp. 1987–1994.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="CAIP">[29]</a>
    </td>
    <td>
      <p align="justify">S. Allegretti, F, Bolelli, M. Cancilla, F. Pollastri, L. Canalini, C. Grana, "How does Connected Components Labeling with Decision Trees perform on GPUs?," In 18th International Conference on Computer Analysis of Images and Patterns, 2019.</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="RBTS">[30]</a>
    </td>
    <td>
      <p align="justify">
	L. He,  Y. Chao, K. Suzuki. "A run-based two-scan labeling algorithm." IEEE Transactions on Image Processing, 2008.</p>
    </td>
</tr>	
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="EPDT">[31]</a>
    </td>
    <td>
      <p align="justify">
	M. Söchting, S. Allegretti, F. Bolelli, C. Grana. "A Heuristic-Based Decision Tree for Connected Components Labeling of 3D Volumes." 25th International Conference on Pattern Recognition, 2021</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="BRTS">[32]</a>
    </td>
    <td>
      <p align="justify">
	W. Lee, F. Bolelli, S. Allegretti, C. Grana. "Fast Run-Based Connected Components Labeling for Bitonal Images." 5th International Conference on Imaging, Vision & Pattern Recognition, 2021</p>
    </td>
</tr>	
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="DAG">[33]</a>
    </td>
    <td>
      <p align="justify">
	F. Bolelli, S. Allegretti, C. Grana. "One DAG to Rule Them All." IEEE Transactions on Pattern Analisys and Machine Intelligence, 2021</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="ACCL">[34]</a>
    </td>
    <td>
      <p align="justify">
F. N. Paravecino, D. Kaeli, "Accelerated Connected Component Labeling Using CUDA Framework." International Conference on Computer Vision and Graphics, ICCVG, 2014</p>
    </td>
</tr>	
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="HA4">[35]</a>
    </td>
    <td>
      <p align="justify">
A. Hennequin, L. Lacassagne, L. Cabaret, Q. Meunier, "A new Direct Connected Component Labeling and Analysis Algorithms for GPUs", DASIP, 2018</p>
    </td>
</tr>	
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="8DLS">[36]</a>
    </td>
    <td>
      <p align="justify">
Y. So, H. Ashraf, Y. Hae, I. Kim, "Fast Parallel Connected Component Labeling Algorithm Using CUDA Based On 8-Directional Label Selection", International Journal of Latest Research in Science and Technology, 2014</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="RASMUSSON">[37]</a>
    </td>
    <td>
      <p align="justify">
A. Rasmusson, T.S. Sørensen, G. Ziegler, "Connected Components Labeling on the GPU with Generalization to Voronoi Diagrams and Signed Distance Fields", International Symposium on Visual Computing, 2013</p>
    </td>
</tr>
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="STAVA">[38]</a>
    </td>
    <td>
      <p align="justify">
O. Stava, B. Benes, "Connected Components Labeling in CUDA", GPU Computing Gems, 2011</p>
    </td>
</tr>	
<tr>
    <td style="vertical-align: top !important;" align="right">
      <a name="LBUF">[39]</a>
    </td>
    <td>
      <p align="justify">
K. Yonehara, K. Aizawa, "A Line-Based Connected Component Labeling Algorithm Using GPUs", Third International Symposium on Computing and Networking, 2015</p>
    </td>
</tr>	
</table>


================================================
FILE: config.yaml
================================================
%YAML:1.2
---
##########################################
# THIS IS THE YACCLAB CONFIGURATION FILE #
##########################################

# -------------------- #
#   Benchmark Tests    #
# -------------------- #


CPU 2D 8-way connectivity:

  execute: false
  
  # Tests to perform and their number of repetitions
  # ------------------------------------------------
  
  perform: 
    correctness:        true
    average:            true
    average_with_steps: false
    density:            false
    granularity:        true
    memory:             false
    
  correctness_tests: 
    eight_connectivity_standard: true
    eight_connectivity_steps:    true
    eight_connectivity_memory:   false
  
  tests_number: 
    average:             10 
    average_with_steps:  10
    density:             10
    granularity:         10
  
  # List of 2D CPU CCL algorithms to test
  # -------------------------------------
  
  algorithms: 
  #  - SAUF_RemSP
  #  - SAUF_TTA
    - SAUF_UFPC
  #  - SAUF_UF
  #  - BBDT_RemSP
  #  - BBDT_TTA
    - BBDT_UFPC
  #  - BBDT_UF
  #  - CCIT_RemSP
  #  - CCIT_TTA
  #  - CCIT_UFPC
  #  - CCIT_UF
  #  - CTB_RemSP
  #  - CTB_TTA
  #  - CTB_UFPC
  #  - CTB_UF
  #  - PRED_RemSP
  #  - PRED_TTA
    - PRED_UFPC
  #  - PRED_UF
  #  - DRAG_RemSP
  #  - DRAG_TTA
    - DRAG_UFPC
  #  - DRAG_UF
  #  - Spaghetti_RemSP
  #  - Spaghetti_TTA
    - Spaghetti_UFPC
  #  - Spaghetti_UF
  #  - LSL_STD_TTA
  #  - LSL_STD_UF
  #  - LSL_STDZ_TTA
  #  - LSL_STDZ_UF
  #  - LSL_RLE_TTA
  #  - LSL_RLE_UF
  #  - LSL_RLEZ_TTA
  #  - LSL_RLEZ_UF
  #  - DiStefano
  #  - CT
  #  - SBLA
  #  - labeling_NULL
  
  # Algorithms which require to specify a labels solver are: SAUF, BBDT, CCIT, LSL, CTB, PRED, DRAG and Spaghetti
  # Possible labels solvers are: UF, UFPC, RemSP, TTA
  # LSL requires also a version specifier: STD, STDZ, RLE, RLEZ; only UF and TTA solvers can be used with LSL
  # Algorithms which don't require to specify a labels solver are: DiStefano, CT, SBLA, NULL
  
  # Datasets to use for each test
  # -----------------------------
  
  # Note that perform correctness tests on labeling_NULL algorithm does not make sense
  check_datasets: ["check", "3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
    
  # List of datasets on which "Average Runtime Tests" shall be run
  average_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
    
  # List of datasets on which "Average Runtime Tests With Steps" shall be run
  average_datasets_with_steps: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
  
  # List of datasets on which "Memory Tests" shall be run
  memory_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
    
  # Save the results of each run test
  save_middle_tests: {average: false, average_with_steps: false, density: false, granularity: false}
  
GPU 2D 8-way connectivity:
   
  execute: true
  
  #  Tests to perform and their number of repetitions
  # -------------------------------------------------
  
  perform: 
    correctness:        true
    average:            false
    average_with_steps: false
    density:            false
    granularity:        false
    memory:             false
    blocksize:          false
  
  correctness_tests: 
    eight_connectivity_standard:    true
    eight_connectivity_steps:       true
    eight_connectivity_memory:      false
    eight_connectivity_blocksize:   false
   
  tests_number: 
    average:             10
    average_with_steps:  10
    density:             10
    granularity:         10
    blocksize:           10
  
  # List of 2D GPU CCL algorithms to test
  # -------------------------------------
  
  algorithms:
  #  - BUF
  #  - BKE
  #  - BE
  #  - UF
  #  - OLE
  #  - LBUF
  #  - KE
  #  - DLP
    - BRB

  
  # Datasets to use for each test
  # -----------------------------
  
  # Note that perform correctness tests on labeling_NULL algorithm does not make sense
  #check_datasets: ["check", "3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
  check_datasets: ["fingerprints", "hamlet"]
  
  # List of datasets on which "Average Runtime Tests" shall be run
  average_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
  
  # List of datasets on which "Average Runtime Tests With Steps" shall be run
  average_datasets_with_steps: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
   
  # List of datasets on which "Memory Tests" shall be run
  memory_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
  
  # List of datasets on which "Blocksize Tests" shall be run
  blocksize_datasets: ["3dpes", "fingerprints", "hamlet", "medical", "mirflickr", "tobacco800", "xdocs"]
  
  blocksize:
    x: [2, 64, 2]
    y: [2, 64, 2]
    z: [1, 1, 1]
  
  # Save the results of each run test
  save_middle_tests: {average: false, average_with_steps: false, density: false, granularity: false}


# -------------------- #
# Additional utilities #
# -------------------- #

# Directory for input/output paths
paths: {input: "F:/lavoro/dataset/YACCLAB", output: "F:/lavoro/progetti/survey_ccl_gpu/YACCLAB/MSVC2019_CUDA_x64/output"}

# Save the returned number of components in output files
write_n_labels: false

# Save labeled image (TODO: remove this option from tests and add a specific tools for doing that in YACCLAB) 
color_labels: {average: false, density: false} #TODO

os: "Windows 10.0.19041"

##########################################
# This is the YACCLAB configuration file #
##########################################


================================================
FILE: cuda/CMakeLists.txt
================================================
add_subdirectory(include)
add_subdirectory(src)

================================================
FILE: cuda/include/CMakeLists.txt
================================================
target_sources(YACCLAB
    PRIVATE
        cuda_mat3.hpp
        cuda_mat3.inl.hpp
        cuda_types3.hpp
        #labeling_CUDA_BKE_merge_tree.inc.h
        #labeling_CUDA_DRAG.inc.h
        #labeling_CUDA_BKE_init_tree.inc.h
)

================================================
FILE: cuda/include/cuda_mat3.hpp
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef OPENCV_CORE_CUDA_MAT3_HPP
#define OPENCV_CORE_CUDA_MAT3_HPP

#ifndef __cplusplus
#  error cuda.hpp header must be compiled as C++
#endif

#include "opencv2/core.hpp"
#include "cuda_types3.hpp"


namespace cv {
	namespace cuda {

		class CV_EXPORTS GpuMat3 {

		public:

			// GpuMat3(Mat &mat);
			
			GpuMat3();
            ~GpuMat3() { release(); }

			size_t elemSize() const;

			void release();

			void create(int x, int y, int z, int type);

			void upload(Mat &mat);

			void download(Mat &mat) const;

			template <class T>
            operator PtrStepSz3<T>() const {            
                return PtrStepSz3<T>(x, y, z, (T*)data, stepy, stepz);                
            }

			template <class T>
            operator PtrStep3<T>() const {
                return PtrStep3<T>((T*)data, stepy, stepz);
            }

			int type() const;

			bool empty() const;

			/*! includes several bit-fields:
			- the magic signature
			- continuity flag
			- depth
			- number of channels
			*/
			int flags;

			//! the number of rows and columns
			int x, y, z;

			//! a distance between successive rows in bytes; includes the gap if any
			size_t stepy;

			//! a distance between successive planes in bytes
			size_t stepz;

			//! pointer to the data
			uchar* data;

		};

	}
}

#include "cuda_mat3.inl.hpp"

#endif /* OPENCV_CORE_CUDA_MAT3_HPP */


================================================
FILE: cuda/include/cuda_mat3.inl.hpp
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef OPENCV_CORE_CUDA_MAT3_INL_HPP
#define OPENCV_CORE_CUDA_MAT3_INL_HPP

#include "cuda_mat3.hpp"


namespace cv {
	namespace cuda {

		inline GpuMat3::GpuMat3() : flags(0), stepy(0), stepz(0), data(0) {}

		inline
			int GpuMat3::type() const
		{
			return CV_MAT_TYPE(flags);
		}

		inline
			size_t GpuMat3::elemSize() const
		{
			return CV_ELEM_SIZE(flags);
		}

		inline
			bool GpuMat3::empty() const
		{
			return data == 0;
		}


		//template <class T> inline
		//	GpuMat3::operator PtrStepSz3<T>() const
		//{
		//	return PtrStepSz3<T>(x, y, z, (T*)data, stepy, stepz);
		//}

		//template <class T> inline
		//	GpuMat3::operator PtrStep3<T>() const
		//{
		//	return PtrStep3<T>((T*)data, stepy, stepz);
		//}

	}
}


#endif // OPENCV_CORE_CUDAINL_HPP


================================================
FILE: cuda/include/cuda_types3.hpp
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef OPENCV_CORE_CUDA_TYPES3_HPP
#define OPENCV_CORE_CUDA_TYPES3_HPP

#ifndef __cplusplus
#  error cuda_types.hpp header must be compiled as C++
#endif

#if defined(__OPENCV_BUILD) && defined(__clang__)
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
#endif
#if defined(__OPENCV_BUILD) && defined(__GNUC__) && __GNUC__ >= 5
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif

/** @file
 * @deprecated Use @ref cudev instead.
 */

 //! @cond IGNORED

#ifdef __CUDACC__
#define __CV_CUDA_HOST_DEVICE__ __host__ __device__ __forceinline__
#else
#define __CV_CUDA_HOST_DEVICE__
#endif

#include "opencv2/core/cuda_types.hpp"

namespace cv
{
	namespace cuda
	{

		// Simple lightweight structures that encapsulates information about an image on device.
		// It is intended to pass to nvcc-compiled code. GpuMat3 depends on headers that nvcc can't compile

		template <typename T> struct PtrSz3 : public DevPtr<T>
		{
			__CV_CUDA_HOST_DEVICE__ PtrSz3() : size(0) {}
			__CV_CUDA_HOST_DEVICE__ PtrSz3(T* data_, size_t size_) : DevPtr<T>(data_), size(size_) {}

			size_t size;
		};

		template <typename T> struct PtrStep3 : public DevPtr<T>
		{
			__CV_CUDA_HOST_DEVICE__ PtrStep3() : stepy(0), stepz(0) {}
			__CV_CUDA_HOST_DEVICE__ PtrStep3(T* data_, size_t stepy_, size_t stepz_) : DevPtr<T>(data_), stepz(stepz_), stepy(stepy_) {}
			//__CV_CUDA_HOST_DEVICE__ PtrStep3(GpuMat3 &gpu_mat) : DevPtr<T>(reinterpret_cast<T*>(gpu_mat.data)), stepz(gpu_mat.stepz), stepy(gpu_mat.stepy) {}

			size_t stepy;
			size_t stepz;

			__CV_CUDA_HOST_DEVICE__       T* ptr(int z = 0, int y = 0) { return (T*)((char*)DevPtr<T>::data + z * stepz + y * stepy); }
			__CV_CUDA_HOST_DEVICE__ const T* ptr(int z = 0, int y = 0) const { return (const T*)((const char*)DevPtr<T>::data + z * stepz + y * stepy); }

			__CV_CUDA_HOST_DEVICE__       T& operator ()(int x, int y, int z) { return ptr(z, y)[x]; }
			__CV_CUDA_HOST_DEVICE__ const T& operator ()(int x, int y, int z) const { return ptr(z, y)[x]; }
		};

		template <typename T> struct PtrStepSz3 : public PtrStep3<T>
		{
			__CV_CUDA_HOST_DEVICE__ PtrStepSz3() : x(0), y(0), z(0) {}
			__CV_CUDA_HOST_DEVICE__ PtrStepSz3(int x_, int y_, int z_, T* data_, size_t stepy_, size_t stepz_)
				: PtrStep3<T>(data_, stepy_, stepz_), x(x_), y(y_), z(z_) {}

			template <typename U>
			explicit PtrStepSz3(const PtrStepSz3<U>& d) : PtrStep3<T>((T*)d.data, d.stepy, d.stepz), x(d.x), y(d.y), z(d.z) {}

			int x;
			int y;
			int z;
		};

		typedef PtrStepSz3<unsigned char> PtrStepSz3b;
		typedef PtrStepSz3<float> PtrStepSz3f;
		typedef PtrStepSz3<int> PtrStepSz3i;

		typedef PtrStep3<unsigned char> PtrStep3b;
		typedef PtrStep3<float> PtrStep3f;
		typedef PtrStep3<int> PtrStep3i;

	}
}

//! @endcond

#endif /* OPENCV_CORE_CUDA_TYPES3_HPP */


================================================
FILE: cuda/src/CMakeLists.txt
================================================
target_sources(YACCLAB  PRIVATE
    gpu_mat3.cu
    labeling_oliveira_2010.cu
    labeling_kalentev_2011.cu
    labeling_chen_2011.cu
    labeling_chen_2011_512.cu
    labeling_chen_2011_1024.cu
    labeling_chen_2011_2048.cu
    labeling_stava_2011.cu
    labeling_rasmusson_2013.cu
    labeling_paravecino_2014.cu
    labeling_soh_2014_8DLS.cu
    labeling_soh_2014_M8DLS.cu
    labeling_yonehara_2015.cu
    labeling_zavalishin_2016.cu
    labeling_cabaret_2017.cu
    labeling_allegretti_2018.cu
    labeling_hennequin_2018_HA4.cu
    labeling_hennequin_2018_HA8.cu
    labeling_allegretti_2019_BBDT.cu
    labeling_allegretti_2019_BKE.cu
    labeling_allegretti_2019_BUF.cu
    labeling_allegretti_2019_DRAG.cu
    labeling_allegretti_2019_SAUF.cu
    #labeling_BE_light.cu
    #labeling_BE_big_tex.cu
    #labeling_BKE_NoInlineCompression.cu
    #labeling_BUF_2S.cu
    #labeling_BUF_NoInlineCompression.cu
    #labeling_KE4.cu
    #labeling_KE_2S.cu
    #labeling_OLE_tex.cu
    #labeling_RADAR.cu
    #labeling_TUF.cu
    #labeling_UF_InlineCompression.cu
    #labeling_UF_naive.cu

)

if(YACCLAB_ENABLE_3D)
    target_sources(YACCLAB PRIVATE        
        labeling_zavalishin_2016_3D.cu
        labeling_allegretti_2019_BKE_3D.cu
        labeling_allegretti_2019_BUF_3D.cu
        labeling_allegretti_2019_UF_3D.cu
        #labeling_BUF_3D_NoInlineCompression.cu
        #labeling_BE_3D_light.cu
        #labeling_BE_3D_light_shared.cu
    )
endif()

================================================
FILE: cuda/src/gpu_mat3.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "opencv2/opencv_modules.hpp"

#ifndef HAVE_OPENCV_CUDEV

#error "opencv_cudev is required"

#else

#include "cuda_mat3.hpp"
#include "opencv2/cudev.hpp"
#include "opencv2/core/cuda/utility.hpp"

using namespace cv;
using namespace cv::cuda;
using namespace cv::cudev;



void cv::cuda::GpuMat3::release()
{
	cudaFree(data);
	data = 0;
	stepy = stepz = x = y = z = 0;
}

void cv::cuda::GpuMat3::create(int _x, int _y, int _z, int _type)
{
	CV_DbgAssert(_x >= 0 && _y >= 0 && _z >= 0);

	_type &= Mat::TYPE_MASK;

	if (x == _x && y == _y && z == _z && type() == _type && data)
		return;

	if (data)
		release();

	if (_x > 0 && _y > 0 && _z > 0)
	{
		flags = Mat::MAGIC_VAL + _type;
		x = _x;
		y = _y;
		z = _z;

		const size_t esz = elemSize();

		struct cudaPitchedPtr pitchedPtr;
		struct cudaExtent extent;

		extent.width = _x * esz;     
		extent.height = _y;
		extent.depth = _z;

		CV_CUDEV_SAFE_CALL(cudaMalloc3D(&pitchedPtr, extent));

		data = reinterpret_cast<uchar *>(pitchedPtr.ptr);
		stepy = pitchedPtr.pitch;
		stepz = pitchedPtr.pitch * y;

		if (esz * x == pitchedPtr.pitch)
			flags |= Mat::CONTINUOUS_FLAG;
	}
}

void cv::cuda::GpuMat3::upload(Mat &mat)
{
	CV_DbgAssert(!mat.empty());
	CV_DbgAssert(mat.dims == 3);

	create(mat.size[2], mat.size[1], mat.size[0], mat.type());

	cudaPitchedPtr srcPtr, dstPtr;
	srcPtr.pitch = mat.step[1];
	srcPtr.ptr = mat.data;
	srcPtr.xsize = mat.size[2] * mat.elemSize();
	srcPtr.ysize = mat.size[1];
	dstPtr.pitch = stepy;
	dstPtr.ptr = data;
	dstPtr.xsize = mat.size[2] * elemSize();
	dstPtr.ysize = mat.size[1];

	cudaMemcpy3DParms params = { 0 };
	params.srcPtr = srcPtr;
	params.dstPtr = dstPtr;
	params.extent = make_cudaExtent(x * elemSize(), y, z);
	params.kind = cudaMemcpyHostToDevice;

    cudaMemcpy3DParms *params_ptr = &params;

	CV_CUDEV_SAFE_CALL(cudaMemcpy3D(params_ptr));
}

void cv::cuda::GpuMat3::download(Mat &mat) const
{
	CV_DbgAssert(!empty());

	int sz[] = { z, y, x };

	mat.create(3, sz, type());

	cudaPitchedPtr srcPtr, dstPtr;
	dstPtr.pitch = mat.step[1];
	dstPtr.ptr = mat.data;
	dstPtr.xsize = mat.size[2] * elemSize();
	dstPtr.ysize = mat.size[1];
	srcPtr.pitch = stepy;
	srcPtr.ptr = data;
	srcPtr.xsize = mat.size[2] * elemSize();
	srcPtr.ysize = mat.size[1];

	cudaMemcpy3DParms params = { 0 };
	params.srcPtr = srcPtr;
	params.dstPtr = dstPtr;
	params.extent = make_cudaExtent(x * elemSize(), y, z);
	params.kind = cudaMemcpyDeviceToHost;

	CV_CUDEV_SAFE_CALL(cudaMemcpy3D(&params));
}

#endif

================================================
FILE: cuda/src/labeling_BE_3D_light.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <opencv2/cudafeatures2d.hpp>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include "labeling_algorithms.h"
#include "register.h"

#define BLOCK_X 8
#define BLOCK_Y 8
#define BLOCK_Z 4

using namespace cv;

// Algorithm itself has good performances, but memory allocation is a problem.
// I will try to reduce it.
namespace {

    // Only use it with unsigned numeric types
    template <typename T>
    __device__ __forceinline__ unsigned char HasBit(T bitmap, unsigned char pos) {
        return (bitmap >> pos) & 1;
    }

    // Only use it with unsigned numeric types
    template <typename T>
    __device__ __forceinline__ void SetBit(T &bitmap, unsigned char pos) {
        bitmap |= (1 << pos);
    }

    // Returns the root index of the UFTree
    __device__ unsigned Find(const int *s_buf, unsigned n) {
        // Warning: do not call Find on a background pixel

        unsigned label = s_buf[n];

        assert(label > 0);

        while (label - 1 != n) {
            n = label - 1;
            label = s_buf[n];

            assert(label > 0);
        }

        return n;

    }


    // Init phase.
    // Labels start at value 1.
    __global__ void Init(const cuda::PtrStepSz3b img, cuda::PtrStepSz3i labels, unsigned int* last_voxel_conn) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned img_index = z * (img.stepz / img.elem_size) + y * (img.stepy / img.elem_size) + x;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {

#define P0 0x77707770777UL

            unsigned long long P = 0UL;

            if (img[img_index]) {
                P |= P0;
            }

            if (x + 1 < img.x) {

                if (img[img_index + 1]) {
                    P |= (P0 << 1);
                }

                if (y + 1 < img.y && img[img_index + img.stepy / img.elem_size + 1]) {
                    P |= (P0 << 5);
                }

            }

            if (y + 1 < img.y) {

                if (img[img_index + img.stepy / img.elem_size]) {
                    P |= (P0 << 4);
                }

            }

            if (z + 1 < img.z) {
                if (img[img_index + img.stepz / img.elem_size]) {
                    P |= P0 << 16;
                }

                if (x + 1 < img.x) {

                    if (img[img_index + img.stepz / img.elem_size + 1]) {
                        P |= (P0 << 17);
                    }

                    if (y + 1 < img.y && img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size + 1]) {
                        P |= (P0 << 21);
                    }

                }

                if (y + 1 < img.y) {

                    if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size]) {
                        P |= (P0 << 20);
                    }

                }
            }

#undef P0

            // checks on borders

            if (x == 0) {
                P &= 0xEEEEEEEEEEEEEEEE;
            }
            if (x + 1 >= img.x) {
                P &= 0x3333333333333333;
            }
            else if (x + 2 >= img.x) {
                P &= 0x7777777777777777;
            }

            if (y == 0) {
                P &= 0xFFF0FFF0FFF0FFF0;
            }
            if (y + 1 >= img.y) {
                P &= 0x00FF00FF00FF00FF;
            }
            else if (y + 2 >= img.y) {
                P &= 0x0FFF0FFF0FFF0FFF;
            }

            if (z == 0) {
                P &= 0xFFFFFFFFFFFF0000;
            }
            if (z + 1 >= img.z) {
                P &= 0x00000000FFFFFFFF;
            }
            else if (z + 2 >= img.z) {
                P &= 0x0000FFFFFFFFFFFF;
            }

            // P is now ready to be used to find neighbour blocks (or it should be)
            // P value avoids range errors

            unsigned int conn_bitmask = 0;

            if (P > 0) {

                labels[labels_index] = labels_index + 1;

                // Lower plane
                unsigned char * plane_data = img.data + img_index - (img.stepz / img.elem_size);
                        
                if (HasBit(P, 0) && plane_data[0 - img.stepy - 1]) {
                    SetBit(conn_bitmask, 0);
                }

                if ((HasBit(P, 1) && plane_data[0 - img.stepy]) || (HasBit(P, 2) && plane_data[0 - img.stepy + 1])) {
                    SetBit(conn_bitmask, 1);
                }

                if (HasBit(P, 3) && plane_data[0 - img.stepy + 2]) {
                    SetBit(conn_bitmask, 2);
                }

                if ((HasBit(P, 4) && plane_data[- 1]) || (HasBit(P, 8) && plane_data[img.stepy - 1])) {
                    SetBit(conn_bitmask, 3);
                }

                if ((HasBit(P, 5) && plane_data[0]) || (HasBit(P, 6) && plane_data[1]) || (HasBit(P, 9) && plane_data[img.stepy]) || (HasBit(P, 10) && plane_data[img.stepy + 1])) {
                    SetBit(conn_bitmask, 4);
                }

                if ((HasBit(P, 7) && plane_data[2]) || (HasBit(P, 11) && plane_data[img.stepy + 2])) {
                    SetBit(conn_bitmask, 5);
                }

                if (HasBit(P, 12) && plane_data[2 * img.stepy - 1]) {
                    SetBit(conn_bitmask, 6);
                }

                if ((HasBit(P, 13) && plane_data[2 * img.stepy]) || (HasBit(P, 14) && plane_data[2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 7);
                }

                if (HasBit(P, 15) && plane_data[2 * img.stepy + 2]) {
                    SetBit(conn_bitmask, 8);
                }

                // Current planes
                plane_data += img.stepz / img.elem_size;

                if ((HasBit(P, 16) && plane_data[0 - img.stepy - 1]) || (HasBit(P, 32) && plane_data[img.stepz - img.stepy - 1])) {
                    SetBit(conn_bitmask, 9);
                }

                if ((HasBit(P, 17) && plane_data[0 - img.stepy]) || (HasBit(P, 18) && plane_data[0 - img.stepy + 1]) || (HasBit(P, 33) && plane_data[img.stepz - img.stepy]) || (HasBit(P, 34) && plane_data[img.stepz - img.stepy + 1])) {
                    SetBit(conn_bitmask, 10);
                }

                if ((HasBit(P, 19) && plane_data[0 - img.stepy + 2]) || (HasBit(P, 35) && plane_data[img.stepz - img.stepy + 2])) {
                    SetBit(conn_bitmask, 11);
                }

                if ((HasBit(P, 20) && plane_data[-1]) || (HasBit(P, 24) && plane_data[img.stepy - 1]) || (HasBit(P, 36) && plane_data[img.stepz - 1]) || (HasBit(P, 40) && plane_data[img.stepz + img.stepy - 1])) {
                    SetBit(conn_bitmask, 12);
                }

                if ((HasBit(P, 23) && plane_data[2]) || (HasBit(P, 27) && plane_data[img.stepy + 2]) || (HasBit(P, 39) && plane_data[img.stepz + 2]) || (HasBit(P, 43) && plane_data[img.stepz + img.stepy + 2])) {
                    SetBit(conn_bitmask, 14);
                }

                if ((HasBit(P, 28) && plane_data[2 * img.stepy - 1]) || (HasBit(P, 44) && plane_data[img.stepz + 2 * img.stepy - 1])) {
                    SetBit(conn_bitmask, 15);
                }

                if ((HasBit(P, 29) && plane_data[2 * img.stepy]) || (HasBit(P, 30) && plane_data[2 * img.stepy + 1]) || (HasBit(P, 45) && plane_data[img.stepz + 2 * img.stepy]) || (HasBit(P, 46) && plane_data[img.stepz + 2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 16);
                }

                if ((HasBit(P, 31) && plane_data[2 * img.stepy + 2]) || (HasBit(P, 47) && plane_data[img.stepz + 2 * img.stepy + 2])) {
                    SetBit(conn_bitmask, 17);
                }

                // Upper plane
                plane_data += 2 * (img.stepz / img.elem_size);

                if (HasBit(P, 48) && plane_data[0 - img.stepy - 1]) {
                    SetBit(conn_bitmask, 18);
                }

                if ((HasBit(P, 49) && plane_data[0 - img.stepy]) || (HasBit(P, 50) && plane_data[0 - img.stepy + 1])) {
                    SetBit(conn_bitmask, 19);
                }

                if (HasBit(P, 51) && plane_data[0 - img.stepy + 2]) {
                    SetBit(conn_bitmask, 20);
                }

                if ((HasBit(P, 52) && plane_data[-1]) || (HasBit(P, 56) && plane_data[img.stepy - 1])) {
                    SetBit(conn_bitmask, 21);
                }

                if ((HasBit(P, 53) && plane_data[0]) || (HasBit(P, 54) && plane_data[1]) || (HasBit(P, 57) && plane_data[img.stepy]) || (HasBit(P, 58) && plane_data[img.stepy + 1])) {
                    SetBit(conn_bitmask, 22);
                }

                if ((HasBit(P, 55) && plane_data[2]) || (HasBit(P, 59) && plane_data[img.stepy + 2])) {
                    SetBit(conn_bitmask, 23);
                }

                if (HasBit(P, 60) && plane_data[2 * img.stepy - 1]) {
                    SetBit(conn_bitmask, 24);
                }

                if ((HasBit(P, 61) && plane_data[2 * img.stepy]) || (HasBit(P, 62) && plane_data[2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 25);
                }

                if (HasBit(P, 63) && plane_data[2 * img.stepy + 2]) {
                    SetBit(conn_bitmask, 26);
                }
            }

            else {
                labels[labels_index] = 0;
            }

            // Write connections
            if (x + 1 < labels.x) {
                labels[labels_index + 1] = conn_bitmask;
            }
            else if (y + 1 < labels.y) {
                labels[labels_index + labels.stepy / labels.elem_size] = conn_bitmask;
            }
            else if (z + 1 < labels.z) {
                labels[labels_index + labels.stepz / labels.elem_size] = conn_bitmask;
            }
            else {
                *last_voxel_conn = conn_bitmask;
            }
        }
    }


    __device__ unsigned int MinLabel(unsigned l1, unsigned l2) {
        if (l1 && l2)
            return min(l1, l2);
        else
            return l1;
    }


    __device__ unsigned int FindMinLabel(cuda::PtrStepSz3i labels, unsigned int neighbours, unsigned label, unsigned labels_index) {

        unsigned int min = label;

        for (char plane = -2; plane <= 2; plane+=2) {
            int * plane_data = labels.data + labels_index + plane * (labels.stepz / labels.elem_size);

            if (HasBit(neighbours, 0)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size) - 2]);
            }

            if (HasBit(neighbours, 1)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size)]);
            }

            if (HasBit(neighbours, 2)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size) + 2]);
            }

            if (HasBit(neighbours, 3)) {
                min = MinLabel(min, plane_data[-2]);
            }

            if (plane && HasBit(neighbours, 4)) {
                min = MinLabel(min, plane_data[0]);
            }

            if (HasBit(neighbours, 5)) {
                min = MinLabel(min, plane_data[2]);
            }

            if (HasBit(neighbours, 6)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size) - 2]);
            }

            if (HasBit(neighbours, 7)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size)]);
            }

            if (HasBit(neighbours, 8)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size) + 2]);
            }

            neighbours >>= 9;
        }

        return min;
    }


    // Scan phase.
    // The pixel associated with current thread is given the minimum label of the neighbours.
    __global__ void Scan(cuda::PtrStepSz3i labels, unsigned char *changes, const unsigned int* last_voxel_conn) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {

            unsigned int neighbors;

            if (x + 1 < labels.x) {
                neighbors = labels[labels_index + 1];
            }
            else if (y + 1 < labels.y) {
                neighbors = labels[labels_index + labels.stepy / labels.elem_size];
            }
            else if (z + 1 < labels.z) {
                neighbors = labels[labels_index + labels.stepz / labels.elem_size];
            }
            else {
                neighbors = *last_voxel_conn;
            }

            unsigned label = labels[labels_index];

            if (label) {
                unsigned min_label = FindMinLabel(labels, neighbors, label, labels_index);
                if (min_label < label) {
                    labels[label - 1] = min(static_cast<unsigned int>(labels[label - 1]), min_label);
                    *changes = 1;
                }
            }
        }
    }


    __global__ void Analyze(cuda::PtrStepSz3i labels) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {
            unsigned int val = labels[labels_index];
            if (val) {
                labels[labels_index] = Find(labels.data, labels_index) + 1;
            }
        }
    }

    // Final Labeling phase
    // Assigns every pixel of 2x2x2 blocks the block label
    __global__ void FinalLabeling(cuda::PtrStepSz3i labels, const cuda::PtrStepSz3b img) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;
        unsigned img_index = z * (img.stepz / img.elem_size) + y * (img.stepy / img.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {

            unsigned int label = labels[labels_index];

            // Current plane
            if (img[img_index]) {
                labels[labels_index] = label;
            }
            else {
                labels[labels_index] = 0;
            }

            if (x + 1 < labels.x) {
                if (img[img_index + 1])
                    labels[labels_index + 1] = label;
                else {
                    labels[labels_index + 1] = 0;
                }

                if (y + 1 < labels.y) {
                    if (img[img_index + img.stepy + 1])
                        labels[labels_index + (labels.stepy / labels.elem_size) + 1] = label;
                    else {
                        labels[labels_index + (labels.stepy / labels.elem_size) + 1] = 0;
                    }
                }
            }

            if (y + 1 < labels.y) {
                if (img[img_index + img.stepy])
                    labels[labels_index + (labels.stepy / labels.elem_size)] = label;
                else {
                    labels[labels_index + (labels.stepy / labels.elem_size)] = 0;
                }
            }

            // Upper plane
            if (z + 1 < labels.z) {

                if (img[img_index + img.stepz / img.elem_size])
                    labels[labels_index + labels.stepz / labels.elem_size] = label;
                else {
                    labels[labels_index + labels.stepz / labels.elem_size] = 0;
                }

                if (x + 1 < labels.x) {
                    if (img[img_index + img.stepz / img.elem_size + 1])
                        labels[labels_index + labels.stepz / labels.elem_size + 1] = label;
                    else {
                        labels[labels_index + labels.stepz / labels.elem_size + 1] = 0;
                    }

                    if (y + 1 < labels.y) {
                        if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size + 1])
                            labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size) + 1] = label;
                        else {
                            labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size) + 1] = 0;
                        }
                    }
                }

                if (y + 1 < labels.y) {
                    if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size])
                        labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size)] = label;
                    else {
                        labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size)] = 0;
                    }
                }

            }

        }

    }

}


class BE_3D_LIGHT : public GpuLabeling3D<Connectivity3D::CONN_26> {
private:
    dim3 grid_size_;
    dim3 block_size_;
    unsigned char changes_;
    unsigned char *d_changes_;
    unsigned int* last_voxel_conn_;
    bool allocated_last_voxel_conn_;

    cuda::GpuMat3 d_connections_;
    cuda::GpuMat3 d_block_labels_;

public:
    BE_3D_LIGHT() {}

    void PerformLabeling() {

        d_img_labels_.create(d_img_.x, d_img_.y, d_img_.z, CV_32SC1);

        // Extra structures that I would gladly do without
        //d_connections_.create((d_img_.x + 1) / 2, (d_img_.y + 1) / 2, (d_img_.z + 1) / 2, CV_32SC1);
        //d_block_labels_.create((d_img_.x + 1) / 2, (d_img_.y + 1) / 2, (d_img_.z + 1) / 2, CV_32SC1);

        // Decide whether last_voxel_ needs specific allocation or not
        // It only needs it in the case that input volume has 2 or more dimensions equals to 1
        allocated_last_voxel_conn_ = false;
        if ((d_img_.x % 2 == 1) && (d_img_.y % 2 == 1) && (d_img_.z % 2 == 1)) {
            if (d_img_.x > 1 && d_img_.y > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 1) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.x > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 1) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.y > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 1;
            }
            else {
                cudaMalloc(&last_voxel_conn_, sizeof(unsigned int));
                allocated_last_voxel_conn_ = true;
            }
        }

        // Block (0, 0, 0) has information about block label, block connettivity AND changes.
        // Its 4 words in slice 0 appear as this:
        // +---+---+
        // |Lab|Con|
        // +---+---+
        // |Cha|   |
        // +---+---+
        if (d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1) {
            d_changes_ = d_img_labels_.data + d_img_labels_.stepy;
        }
        else {
            // In case of degenerate input, allocate additional byte
            cudaMalloc(&d_changes_, sizeof(char));
        }

        grid_size_ = dim3(((d_img_.x + 1) / 2 + BLOCK_X - 1) / BLOCK_X, ((d_img_.y + 1) / 2 + BLOCK_Y - 1) / BLOCK_Y, ((d_img_.z + 1) / 2 + BLOCK_Z - 1) / BLOCK_Z);
        block_size_ = dim3(BLOCK_X, BLOCK_Y, BLOCK_Z);

        Init << <grid_size_, block_size_ >> > (d_img_, d_img_labels_, last_voxel_conn_);

        //Mat init_labels;
        //d_block_labels_.download(init_labels);
        //::NormalizeLabels(init_labels);
        //Mat img_out;
        //ColorLabels(init_labels, img_out);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\init_labels", img_out);

        while (true) {
            changes_ = 0;
            cudaMemcpy(d_changes_, &changes_, sizeof(char), cudaMemcpyHostToDevice);

            Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_voxel_conn_);

            cudaMemcpy(&changes_, d_changes_, sizeof(char), cudaMemcpyDeviceToHost);

            if (!changes_)
                break;

            Analyze << <grid_size_, block_size_ >> > (d_img_labels_);

        }

        //Mat block_labels;
        //d_block_labels_.download(block_labels);
        //::NormalizeLabels(block_labels);
        //ColorLabels(block_labels, img_out);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\block_labels", img_out);

        FinalLabeling << <grid_size_, block_size_ >> > (d_img_labels_, d_img_);

        //d_img_labels_.download(img_labels_);

        if (!(d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1)) {
            cudaFree(d_changes_);
        }
        //d_connections_.release();
        //d_block_labels_.release();

        if (allocated_last_voxel_conn_)
            cudaFree(last_voxel_conn_);

        cudaDeviceSynchronize();

        //d_img_labels_.download(img_labels_);
        //Mat errors;
        //bool correct = CheckLabeledVolume(img_, img_labels_, errors);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\BE_errors", errors);
    }


private:
    double Alloc() {
        perf_.start();

        d_img_labels_.create(d_img_.x, d_img_.y, d_img_.z, CV_32SC1);

        // Decide whether last_voxel_ needs specific allocation or not
        // It only needs it in the case that input volume has 2 or more dimensions equals to 1
        allocated_last_voxel_conn_ = false;
        if ((d_img_.x % 2 == 1) && (d_img_.y % 2 == 1) && (d_img_.z % 2 == 1)) {
            if (d_img_.x > 1 && d_img_.y > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 1) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.x > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 1) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.y > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 1;
            }
            else {
                cudaMalloc(&last_voxel_conn_, sizeof(unsigned int));
                allocated_last_voxel_conn_ = true;
            }
        }

        if (d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1) {
            d_changes_ = d_img_labels_.data + d_img_labels_.stepy;
        }
        else {
            // In case of degenerate input, allocate additional byte
            cudaMalloc(&d_changes_, sizeof(char));
        }

        perf_.stop();
        return perf_.last();
    }

    double Dealloc() {
        perf_.start();
        if (!(d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1)) {
            cudaFree(d_changes_);
        }
        if (allocated_last_voxel_conn_)
            cudaFree(last_voxel_conn_);
        perf_.stop();
        return perf_.last();
    }

    double MemoryTransferHostToDevice() {
        perf_.start();
        d_img_.upload(img_);
        perf_.stop();
        return perf_.last();
    }

    void MemoryTransferDeviceToHost() {
        d_img_labels_.download(img_labels_);
    }

    void AllScans() {
        grid_size_ = dim3(((d_img_.x + 1) / 2 + BLOCK_X - 1) / BLOCK_X, ((d_img_.y + 1) / 2 + BLOCK_Y - 1) / BLOCK_Y, ((d_img_.z + 1) / 2 + BLOCK_Z - 1) / BLOCK_Z);
        block_size_ = dim3(BLOCK_X, BLOCK_Y, BLOCK_Z);

        Init << <grid_size_, block_size_ >> > (d_img_, d_img_labels_, last_voxel_conn_);

        while (true) {
            changes_ = 0;
            cudaMemcpy(d_changes_, &changes_, sizeof(char), cudaMemcpyHostToDevice);

            Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_voxel_conn_);

            cudaMemcpy(&changes_, d_changes_, sizeof(char), cudaMemcpyDeviceToHost);

            if (!changes_)
                break;

            Analyze << <grid_size_, block_size_ >> > (d_img_labels_);

        }

        FinalLabeling << <grid_size_, block_size_ >> > (d_img_labels_, d_img_);

        cudaDeviceSynchronize();
    }

public:
    void PerformLabelingWithSteps()
    {
        double alloc_timing = Alloc();

        perf_.start();
        AllScans();
        perf_.stop();
        perf_.store(Step(StepType::ALL_SCANS), perf_.last());

        double dealloc_timing = Dealloc();

        perf_.store(Step(StepType::ALLOC_DEALLOC), alloc_timing + dealloc_timing);

    }

};

REGISTER_LABELING(BE_3D_LIGHT);


================================================
FILE: cuda/src/labeling_BE_3D_light_shared.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <opencv2/cudafeatures2d.hpp>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include "labeling_algorithms.h"
#include "register.h"

#define BLOCK_X 8
#define BLOCK_Y 8
#define BLOCK_Z 4

using namespace cv;

// This variant uses a byte allocated in shared memory to keep track of changes during Scan kernel.
// It seems rather useless.

// Algorithm itself has good performances, but memory allocation is a problem.
// I will try to reduce it.
namespace {

    // Only use it with unsigned numeric types
    template <typename T>
    __device__ __forceinline__ unsigned char HasBit(T bitmap, unsigned char pos) {
        return (bitmap >> pos) & 1;
    }

    // Only use it with unsigned numeric types
    template <typename T>
    __device__ __forceinline__ void SetBit(T &bitmap, unsigned char pos) {
        bitmap |= (1 << pos);
    }

    // Returns the root index of the UFTree
    __device__ unsigned Find(const int *s_buf, unsigned n) {
        // Warning: do not call Find on a background pixel

        unsigned label = s_buf[n];

        assert(label > 0);

        while (label - 1 != n) {
            n = label - 1;
            label = s_buf[n];

            assert(label > 0);
        }

        return n;

    }


    // Init phase.
    // Labels start at value 1.
    __global__ void Init(const cuda::PtrStepSz3b img, cuda::PtrStepSz3i labels, unsigned int* last_voxel_conn) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned img_index = z * (img.stepz / img.elem_size) + y * (img.stepy / img.elem_size) + x;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {

#define P0 0x77707770777UL

            unsigned long long P = 0UL;

            if (img[img_index]) {
                P |= P0;
            }

            if (x + 1 < img.x) {

                if (img[img_index + 1]) {
                    P |= (P0 << 1);
                }

                if (y + 1 < img.y && img[img_index + img.stepy / img.elem_size + 1]) {
                    P |= (P0 << 5);
                }

            }

            if (y + 1 < img.y) {

                if (img[img_index + img.stepy / img.elem_size]) {
                    P |= (P0 << 4);
                }

            }

            if (z + 1 < img.z) {
                if (img[img_index + img.stepz / img.elem_size]) {
                    P |= P0 << 16;
                }

                if (x + 1 < img.x) {

                    if (img[img_index + img.stepz / img.elem_size + 1]) {
                        P |= (P0 << 17);
                    }

                    if (y + 1 < img.y && img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size + 1]) {
                        P |= (P0 << 21);
                    }

                }

                if (y + 1 < img.y) {

                    if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size]) {
                        P |= (P0 << 20);
                    }

                }
            }

#undef P0

            // checks on borders

            if (x == 0) {
                P &= 0xEEEEEEEEEEEEEEEE;
            }
            if (x + 1 >= img.x) {
                P &= 0x3333333333333333;
            }
            else if (x + 2 >= img.x) {
                P &= 0x7777777777777777;
            }

            if (y == 0) {
                P &= 0xFFF0FFF0FFF0FFF0;
            }
            if (y + 1 >= img.y) {
                P &= 0x00FF00FF00FF00FF;
            }
            else if (y + 2 >= img.y) {
                P &= 0x0FFF0FFF0FFF0FFF;
            }

            if (z == 0) {
                P &= 0xFFFFFFFFFFFF0000;
            }
            if (z + 1 >= img.z) {
                P &= 0x00000000FFFFFFFF;
            }
            else if (z + 2 >= img.z) {
                P &= 0x0000FFFFFFFFFFFF;
            }

            // P is now ready to be used to find neighbour blocks (or it should be)
            // P value avoids range errors

            unsigned int conn_bitmask = 0;

            if (P > 0) {

                labels[labels_index] = labels_index + 1;

                // Lower plane
                unsigned char * plane_data = img.data + img_index - (img.stepz / img.elem_size);
                        
                if (HasBit(P, 0) && plane_data[0 - img.stepy - 1]) {
                    SetBit(conn_bitmask, 0);
                }

                if ((HasBit(P, 1) && plane_data[0 - img.stepy]) || (HasBit(P, 2) && plane_data[0 - img.stepy + 1])) {
                    SetBit(conn_bitmask, 1);
                }

                if (HasBit(P, 3) && plane_data[0 - img.stepy + 2]) {
                    SetBit(conn_bitmask, 2);
                }

                if ((HasBit(P, 4) && plane_data[- 1]) || (HasBit(P, 8) && plane_data[img.stepy - 1])) {
                    SetBit(conn_bitmask, 3);
                }

                if ((HasBit(P, 5) && plane_data[0]) || (HasBit(P, 6) && plane_data[1]) || (HasBit(P, 9) && plane_data[img.stepy]) || (HasBit(P, 10) && plane_data[img.stepy + 1])) {
                    SetBit(conn_bitmask, 4);
                }

                if ((HasBit(P, 7) && plane_data[2]) || (HasBit(P, 11) && plane_data[img.stepy + 2])) {
                    SetBit(conn_bitmask, 5);
                }

                if (HasBit(P, 12) && plane_data[2 * img.stepy - 1]) {
                    SetBit(conn_bitmask, 6);
                }

                if ((HasBit(P, 13) && plane_data[2 * img.stepy]) || (HasBit(P, 14) && plane_data[2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 7);
                }

                if (HasBit(P, 15) && plane_data[2 * img.stepy + 2]) {
                    SetBit(conn_bitmask, 8);
                }

                // Current planes
                plane_data += img.stepz / img.elem_size;

                if ((HasBit(P, 16) && plane_data[0 - img.stepy - 1]) || (HasBit(P, 32) && plane_data[img.stepz - img.stepy - 1])) {
                    SetBit(conn_bitmask, 9);
                }

                if ((HasBit(P, 17) && plane_data[0 - img.stepy]) || (HasBit(P, 18) && plane_data[0 - img.stepy + 1]) || (HasBit(P, 33) && plane_data[img.stepz - img.stepy]) || (HasBit(P, 34) && plane_data[img.stepz - img.stepy + 1])) {
                    SetBit(conn_bitmask, 10);
                }

                if ((HasBit(P, 19) && plane_data[0 - img.stepy + 2]) || (HasBit(P, 35) && plane_data[img.stepz - img.stepy + 2])) {
                    SetBit(conn_bitmask, 11);
                }

                if ((HasBit(P, 20) && plane_data[-1]) || (HasBit(P, 24) && plane_data[img.stepy - 1]) || (HasBit(P, 36) && plane_data[img.stepz - 1]) || (HasBit(P, 40) && plane_data[img.stepz + img.stepy - 1])) {
                    SetBit(conn_bitmask, 12);
                }

                if ((HasBit(P, 23) && plane_data[2]) || (HasBit(P, 27) && plane_data[img.stepy + 2]) || (HasBit(P, 39) && plane_data[img.stepz + 2]) || (HasBit(P, 43) && plane_data[img.stepz + img.stepy + 2])) {
                    SetBit(conn_bitmask, 14);
                }

                if ((HasBit(P, 28) && plane_data[2 * img.stepy - 1]) || (HasBit(P, 44) && plane_data[img.stepz + 2 * img.stepy - 1])) {
                    SetBit(conn_bitmask, 15);
                }

                if ((HasBit(P, 29) && plane_data[2 * img.stepy]) || (HasBit(P, 30) && plane_data[2 * img.stepy + 1]) || (HasBit(P, 45) && plane_data[img.stepz + 2 * img.stepy]) || (HasBit(P, 46) && plane_data[img.stepz + 2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 16);
                }

                if ((HasBit(P, 31) && plane_data[2 * img.stepy + 2]) || (HasBit(P, 47) && plane_data[img.stepz + 2 * img.stepy + 2])) {
                    SetBit(conn_bitmask, 17);
                }

                // Upper plane
                plane_data += 2 * (img.stepz / img.elem_size);

                if (HasBit(P, 48) && plane_data[0 - img.stepy - 1]) {
                    SetBit(conn_bitmask, 18);
                }

                if ((HasBit(P, 49) && plane_data[0 - img.stepy]) || (HasBit(P, 50) && plane_data[0 - img.stepy + 1])) {
                    SetBit(conn_bitmask, 19);
                }

                if (HasBit(P, 51) && plane_data[0 - img.stepy + 2]) {
                    SetBit(conn_bitmask, 20);
                }

                if ((HasBit(P, 52) && plane_data[-1]) || (HasBit(P, 56) && plane_data[img.stepy - 1])) {
                    SetBit(conn_bitmask, 21);
                }

                if ((HasBit(P, 53) && plane_data[0]) || (HasBit(P, 54) && plane_data[1]) || (HasBit(P, 57) && plane_data[img.stepy]) || (HasBit(P, 58) && plane_data[img.stepy + 1])) {
                    SetBit(conn_bitmask, 22);
                }

                if ((HasBit(P, 55) && plane_data[2]) || (HasBit(P, 59) && plane_data[img.stepy + 2])) {
                    SetBit(conn_bitmask, 23);
                }

                if (HasBit(P, 60) && plane_data[2 * img.stepy - 1]) {
                    SetBit(conn_bitmask, 24);
                }

                if ((HasBit(P, 61) && plane_data[2 * img.stepy]) || (HasBit(P, 62) && plane_data[2 * img.stepy + 1])) {
                    SetBit(conn_bitmask, 25);
                }

                if (HasBit(P, 63) && plane_data[2 * img.stepy + 2]) {
                    SetBit(conn_bitmask, 26);
                }
            }

            else {
                labels[labels_index] = 0;
            }

            // Write connections
            if (x + 1 < labels.x) {
                labels[labels_index + 1] = conn_bitmask;
            }
            else if (y + 1 < labels.y) {
                labels[labels_index + labels.stepy / labels.elem_size] = conn_bitmask;
            }
            else if (z + 1 < labels.z) {
                labels[labels_index + labels.stepz / labels.elem_size] = conn_bitmask;
            }
            else {
                *last_voxel_conn = conn_bitmask;
            }
        }
    }


    __device__ unsigned int MinLabel(unsigned l1, unsigned l2) {
        if (l1 && l2)
            return min(l1, l2);
        else
            return l1;
    }


    __device__ unsigned int FindMinLabel(cuda::PtrStepSz3i labels, unsigned int neighbours, unsigned label, unsigned labels_index) {

        unsigned int min = label;

        for (char plane = -2; plane <= 2; plane+=2) {
            int * plane_data = labels.data + labels_index + plane * (labels.stepz / labels.elem_size);

            if (HasBit(neighbours, 0)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size) - 2]);
            }

            if (HasBit(neighbours, 1)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size)]);
            }

            if (HasBit(neighbours, 2)) {
                min = MinLabel(min, plane_data[0 - 2 * (labels.stepy / labels.elem_size) + 2]);
            }

            if (HasBit(neighbours, 3)) {
                min = MinLabel(min, plane_data[-2]);
            }

            if (plane && HasBit(neighbours, 4)) {
                min = MinLabel(min, plane_data[0]);
            }

            if (HasBit(neighbours, 5)) {
                min = MinLabel(min, plane_data[2]);
            }

            if (HasBit(neighbours, 6)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size) - 2]);
            }

            if (HasBit(neighbours, 7)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size)]);
            }

            if (HasBit(neighbours, 8)) {
                min = MinLabel(min, plane_data[2 * (labels.stepy / labels.elem_size) + 2]);
            }

            neighbours >>= 9;
        }

        return min;
    }


    // Scan phase.
    // The pixel associated with current thread is given the minimum label of the neighbours.
    __global__ void Scan(cuda::PtrStepSz3i labels, unsigned char *global_changes, const unsigned int* last_voxel_conn) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        __shared__ unsigned char shared_changes;

        if (threadIdx.x == 0 && threadIdx.y == 0 && threadIdx.z == 0) {
            shared_changes = 0;
        }

        __syncthreads();

        if (x < labels.x && y < labels.y && z < labels.z) {

            unsigned int neighbors;

            if (x + 1 < labels.x) {
                neighbors = labels[labels_index + 1];
            }
            else if (y + 1 < labels.y) {
                neighbors = labels[labels_index + labels.stepy / labels.elem_size];
            }
            else if (z + 1 < labels.z) {
                neighbors = labels[labels_index + labels.stepz / labels.elem_size];
            }
            else {
                neighbors = *last_voxel_conn;
            }

            unsigned label = labels[labels_index];

            if (label) {
                unsigned min_label = FindMinLabel(labels, neighbors, label, labels_index);
                if (min_label < label) {
                    labels[label - 1] = min(static_cast<unsigned int>(labels[label - 1]), min_label);
                    shared_changes = 1;
                }
            }

            __syncthreads();

            if (threadIdx.x == 0 && threadIdx.y == 0 && threadIdx.z == 0 && shared_changes) {
                *global_changes = 1;
            }

        }
    }


    __global__ void Analyze(cuda::PtrStepSz3i labels) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {
            unsigned int val = labels[labels_index];
            if (val) {
                labels[labels_index] = Find(labels.data, labels_index) + 1;
            }
        }
    }

    // Final Labeling phase
    // Assigns every pixel of 2x2x2 blocks the block label
    __global__ void FinalLabeling(cuda::PtrStepSz3i labels, const cuda::PtrStepSz3b img) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
        unsigned z = (blockIdx.z * BLOCK_Z + threadIdx.z) * 2;
        unsigned labels_index = z * (labels.stepz / labels.elem_size) + y * (labels.stepy / labels.elem_size) + x;
        unsigned img_index = z * (img.stepz / img.elem_size) + y * (img.stepy / img.elem_size) + x;

        if (x < labels.x && y < labels.y && z < labels.z) {

            unsigned int label = labels[labels_index];

            // Current plane
            if (img[img_index]) {
                labels[labels_index] = label;
            }
            else {
                labels[labels_index] = 0;
            }

            if (x + 1 < labels.x) {
                if (img[img_index + 1])
                    labels[labels_index + 1] = label;
                else {
                    labels[labels_index + 1] = 0;
                }

                if (y + 1 < labels.y) {
                    if (img[img_index + img.stepy + 1])
                        labels[labels_index + (labels.stepy / labels.elem_size) + 1] = label;
                    else {
                        labels[labels_index + (labels.stepy / labels.elem_size) + 1] = 0;
                    }
                }
            }

            if (y + 1 < labels.y) {
                if (img[img_index + img.stepy])
                    labels[labels_index + (labels.stepy / labels.elem_size)] = label;
                else {
                    labels[labels_index + (labels.stepy / labels.elem_size)] = 0;
                }
            }

            // Upper plane
            if (z + 1 < labels.z) {

                if (img[img_index + img.stepz / img.elem_size])
                    labels[labels_index + labels.stepz / labels.elem_size] = label;
                else {
                    labels[labels_index + labels.stepz / labels.elem_size] = 0;
                }

                if (x + 1 < labels.x) {
                    if (img[img_index + img.stepz / img.elem_size + 1])
                        labels[labels_index + labels.stepz / labels.elem_size + 1] = label;
                    else {
                        labels[labels_index + labels.stepz / labels.elem_size + 1] = 0;
                    }

                    if (y + 1 < labels.y) {
                        if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size + 1])
                            labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size) + 1] = label;
                        else {
                            labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size) + 1] = 0;
                        }
                    }
                }

                if (y + 1 < labels.y) {
                    if (img[img_index + img.stepz / img.elem_size + img.stepy / img.elem_size])
                        labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size)] = label;
                    else {
                        labels[labels_index + labels.stepz / labels.elem_size + (labels.stepy / labels.elem_size)] = 0;
                    }
                }

            }

        }

    }

}


class BE_3D_LIGHT_SHARED : public GpuLabeling3D<Connectivity3D::CONN_26> {
private:
    dim3 grid_size_;
    dim3 block_size_;
    unsigned char changes_;
    unsigned char *d_changes_;
    unsigned int* last_voxel_conn_;
    bool allocated_last_voxel_conn_;

    cuda::GpuMat3 d_connections_;
    cuda::GpuMat3 d_block_labels_;

public:
    BE_3D_LIGHT_SHARED() {}

    void PerformLabeling() {

        d_img_labels_.create(d_img_.x, d_img_.y, d_img_.z, CV_32SC1);

        // Extra structures that I would gladly do without
        //d_connections_.create((d_img_.x + 1) / 2, (d_img_.y + 1) / 2, (d_img_.z + 1) / 2, CV_32SC1);
        //d_block_labels_.create((d_img_.x + 1) / 2, (d_img_.y + 1) / 2, (d_img_.z + 1) / 2, CV_32SC1);

        // Decide whether last_voxel_ needs specific allocation or not
        // It only needs it in the case that input volume has 2 or more dimensions equals to 1
        allocated_last_voxel_conn_ = false;
        if ((d_img_.x % 2 == 1) && (d_img_.y % 2 == 1) && (d_img_.z % 2 == 1)) {
            if (d_img_.x > 1 && d_img_.y > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 1) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.x > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 1) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.y > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 1;
            }
            else {
                cudaMalloc(&last_voxel_conn_, sizeof(unsigned int));
                allocated_last_voxel_conn_ = true;
            }
        }

        // Block (0, 0, 0) has information about block label, block connettivity AND changes.
        // Its 4 words in slice 0 appear as this:
        // +---+---+
        // |Lab|Con|
        // +---+---+
        // |Cha|   |
        // +---+---+
        if (d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1) {
            d_changes_ = d_img_labels_.data + d_img_labels_.stepy;
        }
        else {
            // In case of degenerate input, allocate additional byte
            cudaMalloc(&d_changes_, sizeof(char));
        }

        grid_size_ = dim3(((d_img_.x + 1) / 2 + BLOCK_X - 1) / BLOCK_X, ((d_img_.y + 1) / 2 + BLOCK_Y - 1) / BLOCK_Y, ((d_img_.z + 1) / 2 + BLOCK_Z - 1) / BLOCK_Z);
        block_size_ = dim3(BLOCK_X, BLOCK_Y, BLOCK_Z);

        Init << <grid_size_, block_size_ >> > (d_img_, d_img_labels_, last_voxel_conn_);

        //Mat init_labels;
        //d_block_labels_.download(init_labels);
        //::NormalizeLabels(init_labels);
        //Mat img_out;
        //ColorLabels(init_labels, img_out);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\init_labels", img_out);

        while (true) {
            changes_ = 0;
            cudaMemcpy(d_changes_, &changes_, sizeof(char), cudaMemcpyHostToDevice);

            Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_voxel_conn_);

            cudaMemcpy(&changes_, d_changes_, sizeof(char), cudaMemcpyDeviceToHost);

            if (!changes_)
                break;

            Analyze << <grid_size_, block_size_ >> > (d_img_labels_);

        }

        //Mat block_labels;
        //d_block_labels_.download(block_labels);
        //::NormalizeLabels(block_labels);
        //ColorLabels(block_labels, img_out);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\block_labels", img_out);

        FinalLabeling << <grid_size_, block_size_ >> > (d_img_labels_, d_img_);

        //d_img_labels_.download(img_labels_);

        if (!(d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1)) {
            cudaFree(d_changes_);
        }
        //d_connections_.release();
        //d_block_labels_.release();

        if (allocated_last_voxel_conn_)
            cudaFree(last_voxel_conn_);

        cudaDeviceSynchronize();

        //d_img_labels_.download(img_labels_);
        //Mat errors;
        //bool correct = CheckLabeledVolume(img_, img_labels_, errors);
        //volwrite("C:\\Users\\Stefano\\Desktop\\debug\\BE_errors", errors);
    }


private:
    double Alloc() {
        perf_.start();

        d_img_labels_.create(d_img_.x, d_img_.y, d_img_.z, CV_32SC1);

        // Decide whether last_voxel_ needs specific allocation or not
        // It only needs it in the case that input volume has 2 or more dimensions equals to 1
        allocated_last_voxel_conn_ = false;
        if ((d_img_.x % 2 == 1) && (d_img_.y % 2 == 1) && (d_img_.z % 2 == 1)) {
            if (d_img_.x > 1 && d_img_.y > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 1) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.x > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 1) * d_img_labels_.stepy) + d_img_labels_.x - 2;
            }
            else if (d_img_.y > 1 && d_img_.z > 1) {
                last_voxel_conn_ = reinterpret_cast<unsigned int*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 1;
            }
            else {
                cudaMalloc(&last_voxel_conn_, sizeof(unsigned int));
                allocated_last_voxel_conn_ = true;
            }
        }

        if (d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1) {
            d_changes_ = d_img_labels_.data + d_img_labels_.stepy;
        }
        else {
            // In case of degenerate input, allocate additional byte
            cudaMalloc(&d_changes_, sizeof(char));
        }

        perf_.stop();
        return perf_.last();
    }

    double Dealloc() {
        perf_.start();
        if (!(d_img_.x > 1 && d_img_.y > 1 && d_img_.z > 1)) {
            cudaFree(d_changes_);
        }
        if (allocated_last_voxel_conn_)
            cudaFree(last_voxel_conn_);
        perf_.stop();
        return perf_.last();
    }

    double MemoryTransferHostToDevice() {
        perf_.start();
        d_img_.upload(img_);
        perf_.stop();
        return perf_.last();
    }

    void MemoryTransferDeviceToHost() {
        d_img_labels_.download(img_labels_);
    }

    void AllScans() {
        grid_size_ = dim3(((d_img_.x + 1) / 2 + BLOCK_X - 1) / BLOCK_X, ((d_img_.y + 1) / 2 + BLOCK_Y - 1) / BLOCK_Y, ((d_img_.z + 1) / 2 + BLOCK_Z - 1) / BLOCK_Z);
        block_size_ = dim3(BLOCK_X, BLOCK_Y, BLOCK_Z);

        Init << <grid_size_, block_size_ >> > (d_img_, d_img_labels_, last_voxel_conn_);

        while (true) {
            changes_ = 0;
            cudaMemcpy(d_changes_, &changes_, sizeof(char), cudaMemcpyHostToDevice);

            Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_voxel_conn_);

            cudaMemcpy(&changes_, d_changes_, sizeof(char), cudaMemcpyDeviceToHost);

            if (!changes_)
                break;

            Analyze << <grid_size_, block_size_ >> > (d_img_labels_);

        }

        FinalLabeling << <grid_size_, block_size_ >> > (d_img_labels_, d_img_);

        cudaDeviceSynchronize();
    }

public:
    void PerformLabelingWithSteps()
    {
        double alloc_timing = Alloc();

        perf_.start();
        AllScans();
        perf_.stop();
        perf_.store(Step(StepType::ALL_SCANS), perf_.last());

        double dealloc_timing = Dealloc();

        perf_.store(Step(StepType::ALLOC_DEALLOC), alloc_timing + dealloc_timing);

    }

};

REGISTER_LABELING(BE_3D_LIGHT_SHARED);


================================================
FILE: cuda/src/labeling_BE_big_tex.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <opencv2/cudafeatures2d.hpp>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include "labeling_algorithms.h"
#include "register.h"

#define BLOCK_ROWS 16
#define BLOCK_COLS 16

using namespace cv;

namespace {

	// Only use it with unsigned numeric types
	template <typename T>
	__device__ __forceinline__ unsigned char HasBit(T bitmap, unsigned char pos) {
		return (bitmap >> pos) & 1;
	}

	__device__ __forceinline__ void SetBit(unsigned char &bitmap, unsigned char pos) {
		bitmap |= (1 << pos);
	}

	// Init phase.
	// Labels start at value 1.
	__global__ void Init(const cuda::PtrStepSzb img, cuda::PtrStepSzb block_conn, cuda::PtrStepSzi block_labels) {

		unsigned row = blockIdx.y * BLOCK_ROWS + threadIdx.y;
		unsigned col = blockIdx.x * BLOCK_COLS + threadIdx.x;
		unsigned img_index = 2 * row * img.step + 2 * col;
		unsigned conn_index = row * (block_conn.step / block_conn.elem_size) + col;
		unsigned labels_index = row * (block_labels.step / block_labels.elem_size) + col;

		if (row < block_conn.rows && col < block_conn.cols) {

			unsigned P0 = 0x777;
			unsigned P = 0;

			if (img[img_index]) {
				P |= P0;
			}

			if (2 * col + 1 < img.cols) {

				if (img[img_index + 1]) {
					P |= (P0 << 1);
				}

				if (2 * row + 1 < img.rows && img[img_index + img.step + 1]) {
					P |= (P0 << 5);
				}

			}

			if (2 * row + 1 < img.rows) {

				if (img[img_index + img.step]) {
					P |= (P0 << 4);
				}

			}

			if (col == 0) {
				P &= 0xEEEE;
			}
			if (2 * col + 1 >= img.cols) {
				P &= 0x3333;
			}
			else if (2 * col + 2 >= img.cols) {
				P &= 0x7777;
			}

			if (row == 0) {
				P &= 0xFFF0;
			}
			if (2 * row + 1 >= img.rows) {
				P &= 0xFF;
			}
			else if (2 * row + 2 >= img.rows) {
				P &= 0xFFF;
			}
			
			// P is now ready to be used to find neighbour blocks (or it should be)
			// P value avoids range errors

			unsigned char conn_bitmask = 0;

			if (P > 0) {

				block_labels[labels_index] = labels_index + 1;

				if (HasBit(P, 0) && img[img_index - img.step - 1]) {
					SetBit(conn_bitmask, 0);
				}

				if ((HasBit(P, 1) && img[img_index - img.step]) || (HasBit(P, 2) && img[img_index + 1 - img.step])) {
					SetBit(conn_bitmask, 1);
				}

				if (HasBit(P, 3) && img[img_index + 2 - img.step]) {
					SetBit(conn_bitmask, 2);
				}

				if ((HasBit(P, 4) && img[img_index - 1]) || (HasBit(P, 8) && img[img_index + img.step - 1])) {
					SetBit(conn_bitmask, 3);
				}

				if ((HasBit(P, 7) && img[img_index + 2]) || (HasBit(P, 11) && img[img_index + img.step + 2])) {
					SetBit(conn_bitmask, 4);
				}

				if (HasBit(P, 12) && img[img_index + 2 * img.step - 1]) {
					SetBit(conn_bitmask, 5);
				}

				if ((HasBit(P, 13) && img[img_index + 2 * img.step]) || (HasBit(P, 14) && img[img_index + 2 * img.step + 1])) {
					SetBit(conn_bitmask, 6);
				}

				if (HasBit(P, 15) && img[img_index + 2 * img.step + 2]) {
					SetBit(conn_bitmask, 7);
				}
 			}

			else {
				block_labels[labels_index] = 0;
			}

			block_conn[conn_index] = conn_bitmask;

		}
	}


	/*__global__ void ExpandConnections(const cuda::PtrStepSzb connections, cuda::PtrStepSzb expansion) {

		unsigned row = blockIdx.y * BLOCK_ROWS + threadIdx.y;
		unsigned col = blockIdx.x * BLOCK_COLS + threadIdx.x;
		unsigned conn_index = row * (connections.step / connections.elem_size) + col;
		unsigned exp_index = 3 * row * (expansion.step / expansion.elem_size) + 3 * col;

		if (row < connections.rows && col < connections.cols) {

			expansion[exp_index + (expansion.step / expansion.elem_size) + 1] = 2;

			unsigned char neighbours = connections[conn_index];

			if (HasBit(neighbours, 0)) {
				expansion[exp_index] = 1;
			}
			else {
				expansion[exp_index] = 0;
			}

			if (HasBit(neighbours, 1)) {
				expansion[exp_index + 1] = 1;
			}
			else {
				expansion[exp_index + 1] = 0;
			}

			if (HasBit(neighbours, 2)) {
				expansion[exp_index + 2] = 1;
			}
			else {
				expansion[exp_index + 2] = 0;
			}

			if (HasBit(neighbours, 3)) {
				expansion[exp_index + (expansion.step / expansion.elem_size)] = 1;
			}
			else {
				expansion[exp_index + (expansion.step / expansion.elem_size)] = 0;
			}

			if (HasBit(neighbours, 4)) {
				expansion[exp_index + (expansion.step / expansion.elem_size) + 2] = 1;
			}
			else {
				expansion[exp_index + (expansion.step / expansion.elem_size) + 2] = 0;
			}

			if (HasBit(neighbours, 5)) {
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size)] = 1;
			}
			else {
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size)] = 0;
			}

			if (HasBit(neighbours, 6)) {
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size) + 1] = 1;
			}																 
			else {															 
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size) + 1] = 0;
			}

			if (HasBit(neighbours, 7)) {
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size) + 2] = 1;
			}
			else {
				expansion[exp_index + 2 * (expansion.step / expansion.elem_size) + 2] = 0;
			}
		}
	}*/


	__device__ unsigned int MinLabel(unsigned l1, unsigned l2) {
		if (l1 && l2)
			return min(l1, l2);
		else
			return l1;
	}


	__device__ unsigned int FindMinLabel(cuda::PtrStepSzi labels, unsigned char neighbours, unsigned label, unsigned labels_index) {

		unsigned int min = label;

		if (HasBit(neighbours, 0)) {
			min = MinLabel(min, labels.data[labels_index - (labels.step / labels.elem_size) - 1]);
		}

		if (HasBit(neighbours, 1)) {
			min = MinLabel(min, labels.data[labels_index - (labels.step / labels.elem_size)]);
		}

		if (HasBit(neighbours, 2)) {
			min = MinLabel(min, labels.data[labels_index - (labels.step / labels.elem_size) + 1]);
		}

		if (HasBit(neighbours, 3)) {
			min = MinLabel(min, labels.data[labels_index - 1]);
		}

		if (HasBit(neighbours, 4)) {
			min = MinLabel(min, labels.data[labels_index + 1]);
		}

		if (HasBit(neighbours, 5)) {
			min = MinLabel(min, labels.data[labels_index + (labels.step / labels.elem_size) - 1]);
		}

		if (HasBit(neighbours, 6)) {
			min = MinLabel(min, labels.data[labels_index + (labels.step / labels.elem_size)]);
		}

		if (HasBit(neighbours, 7)) {
			min = MinLabel(min, labels.data[labels_index + (labels.step / labels.elem_size) + 1]);
		}

		return min;
	}


	// Scan phase.
	// The pixel associated with current thread is given the minimum label of the neighbours.
	__global__ void Scan(cuda::PtrStepSzi labels, cuda::PtrStepSzb connections, char *changes) {

		unsigned row = blockIdx.y * BLOCK_ROWS + threadIdx.y;
		unsigned col = blockIdx.x * BLOCK_COLS + threadIdx.x;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;
		unsigned connections_index = row * (connections.step / connections.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {
			
			unsigned char neighbours = connections[connections_index];

			unsigned label = labels[labels_index];

			if (label) {
				unsigned min_label = FindMinLabel(labels, neighbours, label, labels_index);
				if (min_label < label) {
					labels[label - 1] = min(static_cast<unsigned int>(labels[label - 1]), min_label);
					*changes = 1;
				}
			}
		}
	}


	// Analysis phase.
	// The pixel associated with current thread is given the minimum label of the neighbours.
	__global__ void Analyze(cuda::PtrStepSzi labels) {

		unsigned row = blockIdx.y * BLOCK_ROWS + threadIdx.y;
		unsigned col = blockIdx.x * BLOCK_COLS + threadIdx.x;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {

			unsigned label = labels[labels_index];

			if (label) {								// Performances are the same as the paper variant

				unsigned index = labels_index;

				while (label - 1 != index) {
					index = label - 1;
					label = labels[index];
				}

				labels[labels_index] = label;
			}
		}
	}

	// Final Labeling phase
	// Assigns every pixel of 2x2 blocks the block label
	__global__ void FinalLabeling(cuda::PtrStepSzi block_labels, cuda::PtrStepSzi labels, const cuda::PtrStepSzb img) {

		unsigned row = blockIdx.y * BLOCK_ROWS + threadIdx.y;
		unsigned col = blockIdx.x * BLOCK_COLS + threadIdx.x;
		unsigned blocks_index = row * (block_labels.step / block_labels.elem_size) + col;
		unsigned labels_index = 2 * row * (labels.step / labels.elem_size) + 2 * col;
		unsigned img_index = 2 * row * (img.step / img.elem_size) + 2 * col;

		if (row < block_labels.rows && col < block_labels.cols) {

			unsigned int label = block_labels[blocks_index];

			if (img[img_index])
				labels[labels_index] = label;
			else {
				labels[labels_index] = 0;
			}

			if (2 * col + 1 < labels.cols) {
				if (img[img_index + 1])
					labels[labels_index + 1] = label;
				else {
					labels[labels_index + 1] = 0;
				}

				if (2 * row + 1 < labels.rows) {
					if (img[img_index + img.step + 1]) 
						labels[labels_index + (labels.step / labels.elem_size) + 1] = label;
					else {
						labels[labels_index + (labels.step / labels.elem_size) + 1] = 0;
					}
				}
			}

			if (2 * row + 1 < labels.rows) {
				if (img[img_index + img.step])
					labels[labels_index + (labels.step / labels.elem_size)] = label;
				else {
					labels[labels_index + (labels.step / labels.elem_size)] = 0;
				}
			}

		}

	}

}

class BE_TEX : public GpuLabeling2D<Connectivity2D::CONN_8> {
private:
	dim3 grid_size_;
	dim3 block_size_;
	char changes;
	char *d_changes;

	cuda::GpuMat d_connections_;
	cuda::GpuMat d_block_labels_;

public:
	BE_TEX() {}

	void PerformLabeling() {

		d_img_labels_.create(d_img_.size(), CV_32SC1);
		
		// Extra structures that I would gladly do without
		d_connections_.create((d_img_.rows + 1) / 2, (d_img_.cols + 1) / 2, CV_8UC1);
		d_block_labels_.create((d_img_.rows + 1) / 2, (d_img_.cols + 1) / 2, CV_32SC1);

		cudaMalloc(&d_changes, sizeof(char));

		grid_size_ = dim3((d_connections_.cols + BLOCK_COLS - 1) / BLOCK_COLS, (d_connections_.rows + BLOCK_ROWS - 1) / BLOCK_ROWS, 1);
		block_size_ = dim3(BLOCK_COLS, BLOCK_ROWS, 1);

		Init << <grid_size_, block_size_ >> >(d_img_, d_connections_, d_block_labels_);

		//cuda::GpuMat d_expanded_connections;
		//d_expanded_connections.create(d_connections_.rows * 3, d_connections_.cols * 3, CV_8UC1);
		//ExpandConnections << <grid_size_, block_size_ >> > (d_connections_, d_expanded_connections);
		//Mat1b expanded_connections;
		//d_expanded_connections.download(expanded_connections);
		//d_expanded_connections.release();

		//Mat1i init_labels;
		//d_block_labels_.download(init_labels);
		
		while (true) {
			changes = 0;
			cudaMemcpy(d_changes, &changes, sizeof(char), cudaMemcpyHostToDevice);

			Scan << <grid_size_, block_size_ >> > (d_block_labels_, d_connections_, d_changes);

			cudaMemcpy(&changes, d_changes, sizeof(char), cudaMemcpyDeviceToHost);

			if (!changes)
				break;

			Analyze << <grid_size_, block_size_ >> > (d_block_labels_);
		}

		//Mat1i block_labels;
		//d_block_labels_.download(block_labels);

		FinalLabeling << <grid_size_, block_size_ >> >(d_block_labels_, d_img_labels_, d_img_);

		//d_img_labels_.download(img_labels_);

        cudaDeviceSynchronize();

		cudaFree(d_changes);
		d_connections_.release();
		d_block_labels_.release();
	}


private:
	double Alloc() {
		perf_.start();
		d_img_labels_.create(d_img_.size(), CV_32SC1);
		d_connections_.create((d_img_.rows + 1) / 2, (d_img_.cols + 1) / 2, CV_8UC1);
		d_block_labels_.create((d_img_.rows + 1) / 2, (d_img_.cols + 1) / 2, CV_32SC1);
		cudaMalloc(&d_changes, sizeof(char));
		perf_.stop();
		return perf_.last();
	}

	double Dealloc() {
		perf_.start();
		cudaFree(d_changes);
		d_connections_.release();
		d_block_labels_.release();
		perf_.stop();
		return perf_.last();
	}

	double MemoryTransferHostToDevice() {
		perf_.start();
		d_img_.upload(img_);
		perf_.stop();
		return perf_.last();
	}

	void MemoryTransferDeviceToHost() {
		d_img_labels_.download(img_labels_);
	}

	void AllScans() {
		grid_size_ = dim3((d_connections_.cols + BLOCK_COLS - 1) / BLOCK_COLS, (d_connections_.rows + BLOCK_ROWS - 1) / BLOCK_ROWS, 1);
		block_size_ = dim3(BLOCK_COLS, BLOCK_ROWS, 1);

		Init << <grid_size_, block_size_ >> >(d_img_, d_connections_, d_block_labels_);
		// La Init esplode
		// Controlla che cosa contiene connections
		//cuda::GpuMat d_expanded_connections;
		//d_expanded_connections.create(d_connections_.rows * 3, d_connections_.cols * 3, CV_8UC1);
		//ExpandConnections << <grid_size_, block_size_ >> > (d_connections_, d_expanded_connections);
		//Mat1b expanded_connections;
		//d_expanded_connections.download(expanded_connections);
		//d_expanded_connections.release();

		//assert(cudaDeviceSynchronize() == cudaSuccess);

		//Immagine di debug della inizializzazione
		//Mat1i init_labels;
		//d_block_labels_.download(init_labels);

		while (true) {
			changes = 0;
			cudaMemcpy(d_changes, &changes, sizeof(char), cudaMemcpyHostToDevice);

			Scan << <grid_size_, block_size_ >> > (d_block_labels_, d_connections_, d_changes);

			cudaMemcpy(&changes, d_changes, sizeof(char), cudaMemcpyDeviceToHost);

			if (!changes)
				break;

			Analyze << <grid_size_, block_size_ >> > (d_block_labels_);
		}

		// Immagine di debug delle label dei blocchi
		//Mat1i block_labels;
		//d_block_labels_.download(block_labels);

		FinalLabeling << <grid_size_, block_size_ >> >(d_block_labels_, d_img_labels_, d_img_);

        cudaDeviceSynchronize();
	}

public:
	void PerformLabelingWithSteps()
	{
		double alloc_timing = Alloc();

		perf_.start();
		AllScans();
		perf_.stop();
		perf_.store(Step(StepType::ALL_SCANS), perf_.last());

		double dealloc_timing = Dealloc();

		perf_.store(Step(StepType::ALLOC_DEALLOC), alloc_timing + dealloc_timing);

	}

};

REGISTER_LABELING(BE_TEX);



================================================
FILE: cuda/src/labeling_BE_light.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <opencv2/cudafeatures2d.hpp>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include "labeling_algorithms.h"
#include "register.h"


#define BLOCK_ROWS 16
#define BLOCK_COLS 16

using namespace cv;


// Algorithm itself has good performances, but memory allocation is a problem.
// I will try to reduce it.
namespace {

	// Only use it with unsigned numeric types
	template <typename T>
	__device__ __forceinline__ unsigned char HasBit(T bitmap, unsigned char pos) {
		return (bitmap >> pos) & 1;
	}

	__device__ __forceinline__ void SetBit(unsigned char &bitmap, unsigned char pos) {
		bitmap |= (1 << pos);
	}

	__global__ void Init(const cuda::PtrStepSzb img, cuda::PtrStepSzi labels, unsigned char *last_pixel) {

		unsigned row = (blockIdx.y * BLOCK_ROWS + threadIdx.y) * 2;
		unsigned col = (blockIdx.x * BLOCK_COLS + threadIdx.x) * 2;
		unsigned img_index = row * img.step + col;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {

			unsigned P0 = 0x777;
			unsigned P = 0;

			if (img[img_index]) {
				P |= P0;
			}

			if (col + 1 < img.cols) {

				if (img[img_index + 1]) {
					P |= (P0 << 1);
				}

				if (row + 1 < img.rows && img[img_index + img.step + 1]) {
					P |= (P0 << 5);
				}

			}

			if (row + 1 < img.rows) {

				if (img[img_index + img.step]) {
					P |= (P0 << 4);
				}

			}

			if (col == 0) {
				P &= 0xEEEE;
			}
			if (col + 1 >= img.cols) {
				P &= 0x3333;
			}
			else if (col + 2 >= img.cols) {
				P &= 0x7777;
			}

			if (row == 0) {
				P &= 0xFFF0;
			}
			if (row + 1 >= img.rows) {
				P &= 0xFF;
			}
			else if (row + 2 >= img.rows) {
				P &= 0xFFF;
			}

			// P is now ready to be used to find neighbour blocks (or it should be)
			// P value avoids range errors

			unsigned char conn_bitmask = 0;

			if (P > 0) {

				labels[labels_index] = labels_index + 1;

				if (HasBit(P, 0) && img[img_index - img.step - 1]) {
					SetBit(conn_bitmask, 0);
				}

				if ((HasBit(P, 1) && img[img_index - img.step]) || (HasBit(P, 2) && img[img_index + 1 - img.step])) {
					SetBit(conn_bitmask, 1);
				}

				if (HasBit(P, 3) && img[img_index + 2 - img.step]) {
					SetBit(conn_bitmask, 2);
				}

				if ((HasBit(P, 4) && img[img_index - 1]) || (HasBit(P, 8) && img[img_index + img.step - 1])) {
					SetBit(conn_bitmask, 3);
				}

				if ((HasBit(P, 7) && img[img_index + 2]) || (HasBit(P, 11) && img[img_index + img.step + 2])) {
					SetBit(conn_bitmask, 4);
				}

				if (HasBit(P, 12) && img[img_index + 2 * img.step - 1]) {
					SetBit(conn_bitmask, 5);
				}

				if ((HasBit(P, 13) && img[img_index + 2 * img.step]) || (HasBit(P, 14) && img[img_index + 2 * img.step + 1])) {
					SetBit(conn_bitmask, 6);
				}

				if (HasBit(P, 15) && img[img_index + 2 * img.step + 2]) {
					SetBit(conn_bitmask, 7);
				}
			}
			else {
				labels[labels_index] = 0;
			}

			// Connection bitmask is stored in the north-east int of every block
			// If columns are odd, in the last column, it's stored in the south-west of every block instead
			// If columns are odd and rows are odd, it's stored in *last_pixel
			if (col + 1 < labels.cols)
				labels[labels_index + 1] = conn_bitmask;
			else if (row + 1 < labels.rows)
				labels[labels_index + (labels.step / labels.elem_size)] = conn_bitmask;
			else
				*last_pixel = conn_bitmask;

		}
	}


	__device__ unsigned int MinLabel(unsigned l1, unsigned l2) {
		if (l1 && l2)
			return min(l1, l2);
		else
			return l1;
	}


	__device__ unsigned int FindMinLabel(cuda::PtrStepSzi labels, unsigned char neighbours, unsigned label, unsigned labels_index) {

		unsigned int min = label;

		if (HasBit(neighbours, 0)) {
			min = MinLabel(min, labels.data[labels_index - 2 * (labels.step / labels.elem_size) - 2]);
		}

		if (HasBit(neighbours, 1)) {
			min = MinLabel(min, labels.data[labels_index - 2 * (labels.step / labels.elem_size)]);
		}

		if (HasBit(neighbours, 2)) {
			min = MinLabel(min, labels.data[labels_index - 2 * (labels.step / labels.elem_size) + 2]);
		}

		if (HasBit(neighbours, 3)) {
			min = MinLabel(min, labels.data[labels_index - 2]);
		}

		if (HasBit(neighbours, 4)) {
			min = MinLabel(min, labels.data[labels_index + 2]);
		}

		if (HasBit(neighbours, 5)) {
			min = MinLabel(min, labels.data[labels_index + 2 * (labels.step / labels.elem_size) - 2]);
		}

		if (HasBit(neighbours, 6)) {
			min = MinLabel(min, labels.data[labels_index + 2 * (labels.step / labels.elem_size)]);
		}

		if (HasBit(neighbours, 7)) {
			min = MinLabel(min, labels.data[labels_index + 2 * (labels.step / labels.elem_size) + 2]);
		}

		return min;
	}


	__global__ void Scan(cuda::PtrStepSzi labels, unsigned char *changes, unsigned char *last_pixel) {

		unsigned row = (blockIdx.y * BLOCK_ROWS + threadIdx.y) * 2;
		unsigned col = (blockIdx.x * BLOCK_COLS + threadIdx.x) * 2;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {

			unsigned char neighbours;

			if (col + 1 < labels.cols)
				neighbours = labels[labels_index + 1];
			else if (row + 1 < labels.rows)
				neighbours = labels[labels_index + (labels.step / labels.elem_size)];
			else
				neighbours = *last_pixel;

			unsigned label = labels[labels_index];

			if (label) {
				unsigned min_label = FindMinLabel(labels, neighbours, label, labels_index);
				if (min_label < label) {
					labels[label - 1] = min(static_cast<unsigned int>(labels[label - 1]), min_label);
					*changes = 1;
				}
			}
		}
	}


	__global__ void Analyze(cuda::PtrStepSzi labels) {

		unsigned row = (blockIdx.y * BLOCK_ROWS + threadIdx.y) * 2;
		unsigned col = (blockIdx.x * BLOCK_COLS + threadIdx.x) * 2;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {

			unsigned label = labels[labels_index];

			if (label) {								// Performances are the same as the paper variant

				unsigned index = labels_index;

				while (label - 1 != index) {
					index = label - 1;
					label = labels[index];
				}

				labels[labels_index] = label;
			}
		}
	}


	__global__ void FinalLabeling(cuda::PtrStepSzi labels, const cuda::PtrStepSzb img) {

		unsigned row = (blockIdx.y * BLOCK_ROWS + threadIdx.y) * 2;
		unsigned col = (blockIdx.x * BLOCK_COLS + threadIdx.x) * 2;
		unsigned labels_index = row * (labels.step / labels.elem_size) + col;
		unsigned img_index = row * (img.step / img.elem_size) + col;

		if (row < labels.rows && col < labels.cols) {

			unsigned int label = labels[labels_index];

			if (img[img_index]) {}
			// labels[labels_index] = label;
			else {
				labels[labels_index] = 0;
			}

			if (col + 1 < labels.cols) {
				if (img[img_index + 1])
					labels[labels_index + 1] = label;
				else {
					labels[labels_index + 1] = 0;
				}

				if (row + 1 < labels.rows) {
					if (img[img_index + img.step + 1])
						labels[labels_index + (labels.step / labels.elem_size) + 1] = label;
					else {
						labels[labels_index + (labels.step / labels.elem_size) + 1] = 0;
					}
				}
			}

			if (row + 1 < labels.rows) {
				if (img[img_index + img.step])
					labels[labels_index + (labels.step / labels.elem_size)] = label;
				else {
					labels[labels_index + (labels.step / labels.elem_size)] = 0;
				}
			}

		}

	}

}

class BE_LIGHT : public GpuLabeling2D<Connectivity2D::CONN_8> {
private:
	dim3 grid_size_;
	dim3 block_size_;
	char changes_;
	unsigned char *d_changes_;
	bool d_changed_alloc_ = false;
	unsigned char *last_pixel_;

public:
	BE_LIGHT() {}

	void PerformLabeling() {

		d_img_labels_.create(d_img_.size(), CV_32SC1);

		if (d_img_.rows == 1) {
			if (d_img_.cols == 1) {
				d_img_.convertTo(d_img_labels_, CV_32SC1);
				return;
			}
			else if (d_img_.cols % 2) {
				cudaMalloc(&d_changes_, sizeof(unsigned char) * 2);
				d_changed_alloc_ = true;
				last_pixel_ = d_changes_ + 1;
			}
			else {
				cudaMalloc(&d_changes_, sizeof(unsigned char));
				d_changed_alloc_ = true;
			}
		}
		else if (d_img_.cols == 1) {
			if (d_img_.rows % 2) {
				cudaMalloc(&d_changes_, sizeof(unsigned char) * 2);
				d_changed_alloc_ = true;
				last_pixel_ = d_changes_ + 1;
			}
			else {
				cudaMalloc(&d_changes_, sizeof(unsigned char));
				d_changed_alloc_ = true;
			}
		}
		else {
			d_changes_ = d_img_labels_.data + d_img_labels_.step;
			last_pixel_ = d_img_labels_.data + d_img_labels_.step + sizeof(unsigned int);
		}

		grid_size_ = dim3((((d_img_.cols + 1) / 2) + BLOCK_COLS - 1) / BLOCK_COLS, (((d_img_.rows + 1) / 2) + BLOCK_ROWS - 1) / BLOCK_ROWS, 1);
		block_size_ = dim3(BLOCK_COLS, BLOCK_ROWS, 1);

		Init << <grid_size_, block_size_ >> >(d_img_, d_img_labels_, last_pixel_);

		//cuda::GpuMat d_expanded_connections;
		//d_expanded_connections.create(d_connections_.rows * 3, d_connections_.cols * 3, CV_8UC1);
		//ExpandConnections << <grid_size_, block_size_ >> > (d_connections_, d_expanded_connections);
		//Mat1b expanded_connections;
		//d_expanded_connections.download(expanded_connections);
		//d_expanded_connections.release();

		//Mat1i init_labels;
		//d_block_labels_.download(init_labels);

		while (true) {
			changes_ = 0;
			cudaMemcpy(d_changes_, &changes_, sizeof(unsigned char), cudaMemcpyHostToDevice);

			Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_pixel_);

			cudaMemcpy(&changes_, d_changes_, sizeof(unsigned char), cudaMemcpyDeviceToHost);

			if (!changes_)
				break;

			Analyze << <grid_size_, block_size_ >> > (d_img_labels_);
		}

		//Mat1i block_info_final;
		//d_img_labels_.download(block_info_final);		

		/*if ((img_.rows % 2) && (img_.cols % 2))
		LastPixel << <1, 1 >> > (d_img_labels_, last_pixel_);
		*/
		FinalLabeling << <grid_size_, block_size_ >> >(d_img_labels_, d_img_);

		// d_img_labels_.download(img_labels_);

		if (d_changed_alloc_)
			cudaFree(d_changes_);
	}


private:
	bool Alloc() {
		d_img_labels_.create(d_img_.size(), CV_32SC1);
		if (d_img_.rows == 1) {
			if (d_img_.cols == 1) {
				d_img_.convertTo(d_img_labels_, CV_32SC1);
				return true;
			}
			else if (d_img_.cols % 2) {
				cudaMalloc(&d_changes_, sizeof(unsigned char) * 2);
				last_pixel_ = d_changes_ + 1;
			}
			else {
				cudaMalloc(&d_changes_, sizeof(unsigned char));
			}
		}
		else if (d_img_.cols == 1) {
			if (d_img_.rows % 2) {
				cudaMalloc(&d_changes_, sizeof(unsigned char) * 2);
				last_pixel_ = d_changes_ + 1;
			}
			else {
				cudaMalloc(&d_changes_, sizeof(unsigned char));
			}
		}
		else {
			d_changes_ = d_img_labels_.data + d_img_labels_.step;
			last_pixel_ = d_img_labels_.data + d_img_labels_.step + sizeof(unsigned int);
		}
		return false;
	}

	void Dealloc() {
		if (d_changed_alloc_)
			cudaFree(d_changes_);
	}

	double MemoryTransferHostToDevice() {
		perf_.start();
		d_img_.upload(img_);
		perf_.stop();
		return perf_.last();
	}

	void MemoryTransferDeviceToHost() {
		d_img_labels_.download(img_labels_);
	}

	void AllScans() {
		last_pixel_ = d_changes_ + 1;

		grid_size_ = dim3((((d_img_.cols + 1) / 2) + BLOCK_COLS - 1) / BLOCK_COLS, (((d_img_.rows + 1) / 2) + BLOCK_ROWS - 1) / BLOCK_ROWS, 1);
		block_size_ = dim3(BLOCK_COLS, BLOCK_ROWS, 1);

		Init << <grid_size_, block_size_ >> >(d_img_, d_img_labels_, last_pixel_);

		//cuda::GpuMat d_expanded_connections;
		//d_expanded_connections.create(d_connections_.rows * 3, d_connections_.cols * 3, CV_8UC1);
		//ExpandConnections << <grid_size_, block_size_ >> > (d_connections_, d_expanded_connections);
		//Mat1b expanded_connections;
		//d_expanded_connections.download(expanded_connections);
		//d_expanded_connections.release();

		//Mat1i init_labels;
		//d_block_labels_.download(init_labels);

		while (true) {
			changes_ = 0;

			cudaMemcpy(d_changes_, &changes_, sizeof(unsigned char), cudaMemcpyHostToDevice);

			Scan << <grid_size_, block_size_ >> > (d_img_labels_, d_changes_, last_pixel_);

			cudaMemcpy(&changes_, d_changes_, sizeof(unsigned char), cudaMemcpyDeviceToHost);

			if (!changes_)
				break;

			Analyze << <grid_size_, block_size_ >> > (d_img_labels_);
		}

		//Mat1i block_labels;
		//d_block_labels_.download(block_labels);

		FinalLabeling << <grid_size_, block_size_ >> >(d_img_labels_, d_img_);

		cudaDeviceSynchronize();
	}

public:
	void PerformLabelingWithSteps()
	{
		perf_.start();
		bool done = Alloc();
		perf_.stop();
		double alloc_timing = perf_.last();

		if (!done) {
			perf_.start();
			AllScans();
			perf_.stop();
			perf_.store(Step(StepType::ALL_SCANS), perf_.last());
		}

		perf_.start();
		Dealloc();
		perf_.stop();
		double dealloc_timing = perf_.last();

		perf_.store(Step(StepType::ALLOC_DEALLOC), alloc_timing + dealloc_timing);
	}

};

REGISTER_LABELING(BE_LIGHT);


================================================
FILE: cuda/src/labeling_BKE_NoInlineCompression.cu
================================================
// Copyright (c) 2020, the YACCLAB contributors, as 
// shown by the AUTHORS file. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include <opencv2/cudafeatures2d.hpp>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include "labeling_algorithms.h"
#include "register.h"


#define BLOCK_ROWS 16
#define BLOCK_COLS 16

using namespace cv;

namespace {

//
//         This is a block-based algorithm.
// Blocks are 2x2 sized, with internal pixels named as:
//                       +---+
//                       |a b|
//                       |c d|
//                       +---+   
// 
//       Neighbour blocks of block X are named as:
//                      +-+-+-+
//                      |P|Q|R|                
//                      +-+-+-+
//                      |S|X|
//                      +-+-+
//

enum class Info : unsigned char { a = 0, b = 1, c = 2, d = 3, P = 4, Q = 5, R = 6, S = 7 };

// Only use it with unsigned numeric types
template <typename T>
__device__ __forceinline__ unsigned char HasBit(T bitmap, Info pos) {
    return (bitmap >> static_cast<unsigned char>(pos)) & 1;
}

template <typename T>
__device__ __forceinline__ unsigned char HasBit(T bitmap, unsigned char pos) {
    return (bitmap >> pos) & 1;
}

// Only use it with unsigned numeric types
__device__ __forceinline__ void SetBit(unsigned char& bitmap, Info pos) {
    bitmap |= (1 << static_cast<unsigned char>(pos));
}

// Returns the root index of the UFTree
__device__ unsigned Find(const int* s_buf, unsigned n) {
    while (s_buf[n] != n) {
        n = s_buf[n];
    }
    return n;
}


// Merges the UFTrees of a and b, linking one root to the other
__device__ void Union(int* s_buf, unsigned a, unsigned b) {

    bool done;

    do {

        a = Find(s_buf, a);
        b = Find(s_buf, b);

        if (a < b) {
            int old = atomicMin(s_buf + b, a);
            done = (old == b);
            b = old;
        }
        else if (b < a) {
            int old = atomicMin(s_buf + a, b);
            done = (old == a);
            a = old;
        }
        else {
            done = true;
        }

    } while (!done);

}


__global__ void InitLabeling(const cuda::PtrStepSzb img, cuda::PtrStepSzi labels, unsigned char* last_pixel) {
    unsigned row = (blockIdx.y * blockDim.y + threadIdx.y) * 2;
    unsigned col = (blockIdx.x * blockDim.x + threadIdx.x) * 2;
    unsigned img_index = row * img.step + col;
    unsigned labels_index = row * (labels.step / labels.elem_size) + col;

    if (row < labels.rows && col < labels.cols) {

        unsigned P = 0;

        // Bitmask representing two kinds of information
        // Bits 0, 1, 2, 3 are set if pixel a, b, c, d are foreground, respectively
        // Bits 4, 5, 6, 7 are set if block P, Q, R, S need to be merged to X in Merge phase
        unsigned char info = 0;

        uint32_t buffer_int = 0;
        uint8_t* const buffer = reinterpret_cast<uint8_t*>(&buffer_int);

        // Read pairs of consecutive values in memory at once
        if (col + 1 < img.cols) {
            // This does not depend on endianness
            *(reinterpret_cast<int16_t*>(buffer)) = *(reinterpret_cast<int16_t*>(img.data + img_index));
        
            if (row + 1 < img.rows) {
                *(reinterpret_cast<int16_t*>(buffer + 2)) = *(reinterpret_cast<int16_t*>(img.data + img_inde
Download .txt
gitextract_j1r0m0pd/

├── .all-contributorsrc
├── .github/
│   └── workflows/
│       ├── linux64.yml
│       └── macos.yml
├── .gitignore
├── AUTHORS
├── CMakeLists.txt
├── Jenkinsfile
├── LICENSE
├── README.md
├── config.yaml
├── cuda/
│   ├── CMakeLists.txt
│   ├── include/
│   │   ├── CMakeLists.txt
│   │   ├── cuda_mat3.hpp
│   │   ├── cuda_mat3.inl.hpp
│   │   └── cuda_types3.hpp
│   └── src/
│       ├── CMakeLists.txt
│       ├── gpu_mat3.cu
│       ├── labeling_BE_3D_light.cu
│       ├── labeling_BE_3D_light_shared.cu
│       ├── labeling_BE_big_tex.cu
│       ├── labeling_BE_light.cu
│       ├── labeling_BKE_NoInlineCompression.cu
│       ├── labeling_BUF_2S.cu
│       ├── labeling_BUF_3D_NoInlineCompression.cu
│       ├── labeling_BUF_NoInlineCompression.cu
│       ├── labeling_KE4.cu
│       ├── labeling_KE_2S.cu
│       ├── labeling_OLE_tex.cu
│       ├── labeling_RADAR.cu
│       ├── labeling_TUF.cu
│       ├── labeling_UF_InlineCompression.cu
│       ├── labeling_UF_naive.cu
│       ├── labeling_allegretti_2018.cu
│       ├── labeling_allegretti_2019_BBDT.cu
│       ├── labeling_allegretti_2019_BKE.cu
│       ├── labeling_allegretti_2019_BKE_3D.cu
│       ├── labeling_allegretti_2019_BUF.cu
│       ├── labeling_allegretti_2019_BUF_3D.cu
│       ├── labeling_allegretti_2019_DRAG.cu
│       ├── labeling_allegretti_2019_SAUF.cu
│       ├── labeling_allegretti_2019_UF_3D.cu
│       ├── labeling_cabaret_2017.cu
│       ├── labeling_chen_2011.cu
│       ├── labeling_chen_2011_1024.cu
│       ├── labeling_chen_2011_2048.cu
│       ├── labeling_chen_2011_512.cu
│       ├── labeling_hennequin_2018_HA4.cu
│       ├── labeling_hennequin_2018_HA8.cu
│       ├── labeling_kalentev_2011.cu
│       ├── labeling_oliveira_2010.cu
│       ├── labeling_paravecino_2014.cu
│       ├── labeling_rasmusson_2013.cu
│       ├── labeling_soh_2014_8DLS.cu
│       ├── labeling_soh_2014_M8DLS.cu
│       ├── labeling_stava_2011.cu
│       ├── labeling_yonehara_2015.cu
│       ├── labeling_zavalishin_2016.cu
│       ├── labeling_zavalishin_2016_3D.cu
│       └── next_to_trash/
│           ├── labeling_CUDA_BKE_InlineCompression.cu
│           ├── labeling_CUDA_BUF_2S.cu
│           ├── labeling_CUDA_KE_2S.cu
│           └── labeling_CUDA_UF_InlineCompression.cu
├── doc/
│   ├── EPDT/
│   │   └── README.md
│   ├── README.txt
│   ├── config_2d.yaml
│   ├── config_3d.yaml
│   ├── config_base.yaml
│   ├── config_ci_cpu.yaml
│   ├── config_ci_cpu2d.yaml
│   ├── config_cuda_2d.yaml
│   ├── config_cuda_3d.yaml
│   ├── config_epdt_19c.yaml
│   ├── config_epdt_22c.yaml
│   ├── config_epdt_26c.yaml
│   └── config_jenkins.yaml
├── include/
│   ├── CMakeLists.txt
│   ├── bit_scan_forward.h
│   ├── check_labeling.h
│   ├── config_data.h
│   ├── file_manager.h
│   ├── labeling3D_EPDT_19c.h
│   ├── labeling3D_EPDT_19c_211b.h
│   ├── labeling3D_EPDT_19c_action_def.inc.h
│   ├── labeling3D_EPDT_19c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_19c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_19c_tree.inc.h
│   ├── labeling3D_EPDT_22c.h
│   ├── labeling3D_EPDT_22c_211b.h
│   ├── labeling3D_EPDT_22c_action_def.inc.h
│   ├── labeling3D_EPDT_22c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_22c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_22c_tree.inc.h
│   ├── labeling3D_EPDT_26c.h
│   ├── labeling3D_EPDT_26c_action_def.inc.h
│   ├── labeling3D_EPDT_26c_action_def_mem.inc.h
│   ├── labeling3D_EPDT_26c_action_def_memory.inc.h
│   ├── labeling3D_EPDT_26c_tree.inc.h
│   ├── labeling3D_EPDT_2829_action_undef.inc.h
│   ├── labeling3D_PRED_2021.h
│   ├── labeling3D_PRED_2021_cl_forest.inc.h
│   ├── labeling3D_PRED_2021_fl_forest.inc.h
│   ├── labeling3D_PRED_2021_ll_forest.inc.h
│   ├── labeling3D_PRED_2021_sl_forest.inc.h
│   ├── labeling3D_PREDpp_2021.h
│   ├── labeling3D_PREDpp_2021_cl_forest.inc.h
│   ├── labeling3D_PREDpp_2021_fl_forest.inc.h
│   ├── labeling3D_PREDpp_2021_ll_forest.inc.h
│   ├── labeling3D_PREDpp_2021_sl_forest.inc.h
│   ├── labeling3D_SAUF_2021.h
│   ├── labeling3D_SAUF_2021_tree.inc.h
│   ├── labeling3D_SAUFpp_2021.h
│   ├── labeling3D_SAUFpp_2021_tree.inc.h
│   ├── labeling3D_he_2011.h
│   ├── labeling3D_he_2011_run.h
│   ├── labeling3D_he_2011_tree.inc.h
│   ├── labeling3D_naive.h
│   ├── labeling_HT_CCL_Diaz2019_v1_2_0.h
│   ├── labeling_PREDpp_2021.h
│   ├── labeling_PREDpp_2021_cl_forest.inc.h
│   ├── labeling_PREDpp_2021_fl_forest.inc.h
│   ├── labeling_algorithms.h
│   ├── labeling_bolelli_2018.h
│   ├── labeling_bolelli_2018_drag.inc.h
│   ├── labeling_bolelli_2019.h
│   ├── labeling_bolelli_2019_forest.inc.h
│   ├── labeling_bolelli_2019_forest_fl.inc.h
│   ├── labeling_bolelli_2019_forest_ll.inc.h
│   ├── labeling_bolelli_2019_forest_sl.inc.h
│   ├── labeling_distefano_1999.h
│   ├── labeling_fchang_2003.h
│   ├── labeling_grana_2010.h
│   ├── labeling_grana_2010_tree.inc.h
│   ├── labeling_grana_2016.h
│   ├── labeling_grana_2016_forest.inc.h
│   ├── labeling_grana_2016_forest_0.inc.h
│   ├── labeling_he_2008.h
│   ├── labeling_he_2014.h
│   ├── labeling_he_2014_graph.inc.h
│   ├── labeling_lacassagne_2016.h
│   ├── labeling_lacassagne_2016_code.inc.h
│   ├── labeling_lee_2021_bmrs.h
│   ├── labeling_lee_2021_bmrs_no_zeroinit.h
│   ├── labeling_lee_2021_brts.h
│   ├── labeling_lee_2021_brts_no_zeroinit.h
│   ├── labeling_null.h
│   ├── labeling_sauf_4c.h
│   ├── labeling_sauf_4c_tree.inc.h
│   ├── labeling_sauf_background.h
│   ├── labeling_sauf_bg_tree.inc.h
│   ├── labeling_tagliatelle_2021.h
│   ├── labeling_tagliatelle_2021_cl_forest.inc.h
│   ├── labeling_tagliatelle_2021_fl_forest.inc.h
│   ├── labeling_tagliatelle_2021_ll_forest.inc.h
│   ├── labeling_tagliatelle_2021_sl_forest.inc.h
│   ├── labeling_wu_2009.h
│   ├── labeling_wu_2009_tree.inc.h
│   ├── labeling_wychang_2015.h
│   ├── labeling_wychang_2015_tree.inc.h
│   ├── labeling_wychang_2015_tree_0.inc.h
│   ├── labeling_zhao_2010.h
│   ├── labels_solver.h
│   ├── memory_tester.h
│   ├── performance_evaluator.h
│   ├── progress_bar.h
│   ├── register.h
│   ├── stream_demultiplexer.h
│   ├── system_info.h
│   ├── utilities.h
│   ├── volume_util.h
│   ├── yacclab_tensor.h
│   └── yacclab_tests.h
├── old/
│   ├── .travis.yml
│   ├── configurationReader.h
│   └── equivalenceSolverSuzuki.h
├── spike/
│   └── performanceEvaluator.h.chrono
├── src/
│   ├── CMakeLists.txt
│   ├── check_labeling.cc
│   ├── config_data.cc
│   ├── file_manager.cc
│   ├── labeling3D_EPDT_19c.cc
│   ├── labeling3D_EPDT_22c.cc
│   ├── labeling3D_EPDT_26c.cc
│   ├── labeling3D_PRED_2021.cc
│   ├── labeling3D_PREDpp_2021.cc
│   ├── labeling3D_SAUF_2021.cc
│   ├── labeling3D_SAUFpp_2021.cc
│   ├── labeling3D_he_2011.cc
│   ├── labeling3D_he_2011_run.cc
│   ├── labeling3D_naive.cc
│   ├── labeling_HT_CCL_Diaz2019_v1_2_0.cc
│   ├── labeling_PREDpp_2021.cc
│   ├── labeling_algorithms.cc
│   ├── labeling_bolelli_2018.cc
│   ├── labeling_bolelli_2019.cc
│   ├── labeling_distefano_1999.cc
│   ├── labeling_fchang_2003.cc
│   ├── labeling_grana_2010.cc
│   ├── labeling_grana_2016.cc
│   ├── labeling_he_2008.cc
│   ├── labeling_he_2014.cc
│   ├── labeling_lacassagne_2016.cc
│   ├── labeling_lee_2021_bmrs.cc
│   ├── labeling_lee_2021_brts.cc
│   ├── labeling_null.cc
│   ├── labeling_sauf_4c.cc
│   ├── labeling_sauf_background.cc
│   ├── labeling_tagliatelle_2021.cc
│   ├── labeling_wu_2009.cc
│   ├── labeling_wychang_2015.cc
│   ├── labeling_zhao_2010.cc
│   ├── labels_solver.cc
│   ├── main.cc
│   ├── system_info.cc
│   ├── utilities.cc
│   ├── volume_util.cc
│   ├── yacclab_tensor.cc
│   └── yacclab_tests.cc
└── tools/
    ├── actions-scripts/
    │   └── macos-before-install.sh
    ├── embed_pdf/
    │   └── embed.php
    ├── jenkins-scripts/
    │   └── run-script.sh
    └── travis-scripts/
        ├── before-install.sh
        └── run-script.sh
Download .txt
SYMBOL INDEX (415 symbols across 65 files)

FILE: cuda/include/cuda_mat3.hpp
  type cv (line 18) | namespace cv {
    type cuda (line 19) | namespace cuda {
      function GpuMat3 (line 21) | class CV_EXPORTS GpuMat3 {

FILE: cuda/include/cuda_mat3.inl.hpp
  type cv (line 13) | namespace cv {
    type cuda (line 14) | namespace cuda {

FILE: cuda/include/cuda_types3.hpp
  type cv (line 35) | namespace cv
    type cuda (line 37) | namespace cuda
      type PtrSz3 (line 43) | struct PtrSz3 : public DevPtr<T>
        method __CV_CUDA_HOST_DEVICE__ (line 45) | __CV_CUDA_HOST_DEVICE__ PtrSz3() : size(0) {}
      type PtrStep3 (line 51) | struct PtrStep3 : public DevPtr<T>
        method __CV_CUDA_HOST_DEVICE__ (line 60) | __CV_CUDA_HOST_DEVICE__       T* ptr(int z = 0, int y = 0) { retur...
        method __CV_CUDA_HOST_DEVICE__ (line 61) | __CV_CUDA_HOST_DEVICE__ const T* ptr(int z = 0, int y = 0) const {...
        method __CV_CUDA_HOST_DEVICE__ (line 63) | __CV_CUDA_HOST_DEVICE__       T& operator ()(int x, int y, int z) ...
        method __CV_CUDA_HOST_DEVICE__ (line 64) | __CV_CUDA_HOST_DEVICE__ const T& operator ()(int x, int y, int z) ...
      type PtrStepSz3 (line 67) | struct PtrStepSz3 : public PtrStep3<T>
        method PtrStepSz3 (line 74) | explicit PtrStepSz3(const PtrStepSz3<U>& d) : PtrStep3<T>((T*)d.da...

FILE: include/bit_scan_forward.h
  function YacclabBitScanForward64 (line 24) | inline unsigned char YacclabBitScanForward64(unsigned long* Index, uint6...
  function YacclabBitScanForward64 (line 33) | inline unsigned char YacclabBitScanForward64(unsigned long* Index, uint6...
  function YacclabBitScanForward64 (line 43) | inline unsigned char YacclabBitScanForward64(unsigned long* Index, uint6...
  function YacclabBitScanForward64 (line 53) | inline unsigned char YacclabBitScanForward64(unsigned long* Index, uint6...

FILE: include/check_labeling.h
  type class (line 13) | enum class
  type class (line 18) | enum class
  function class (line 24) | class LabelingCheckSingleton2D {
  function class (line 38) | class LabelingCheckSingleton3D {

FILE: include/config_data.h
  type ModeConfig (line 21) | struct ModeConfig {
  type GlobalConfig (line 78) | struct GlobalConfig {
  type ConfigData (line 113) | struct ConfigData {

FILE: include/file_manager.h
  function namespace (line 14) | namespace filesystem {

FILE: include/labeling3D_EPDT_19c.h
  function PerformLabeling (line 197) | void PerformLabeling()
  function PerformLabelingWithSteps (line 444) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 463) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Dealloc (line 660) | void Dealloc() {
  function FirstScan (line 664) | void FirstScan() {
  function SecondScan (line 705) | void SecondScan() {

FILE: include/labeling3D_EPDT_19c_211b.h
  function PerformLabeling (line 197) | void PerformLabeling()
  function PerformLabelingWithSteps (line 444) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 463) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Dealloc (line 660) | void Dealloc() {
  function FirstScan (line 664) | void FirstScan() {
  function SecondScan (line 705) | void SecondScan() {

FILE: include/labeling3D_EPDT_22c.h
  function PerformLabeling (line 54) | void PerformLabeling()
  function PerformLabelingWithSteps (line 188) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 207) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Dealloc (line 416) | void Dealloc() {
  function FirstScan (line 420) | void FirstScan() {
  function SecondScan (line 461) | void SecondScan() {

FILE: include/labeling3D_EPDT_22c_211b.h
  function PerformLabeling (line 54) | void PerformLabeling()
  function PerformLabelingWithSteps (line 188) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 207) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Dealloc (line 416) | void Dealloc() {
  function FirstScan (line 420) | void FirstScan() {
  function SecondScan (line 461) | void SecondScan() {

FILE: include/labeling3D_EPDT_26c.h
  function PerformLabeling (line 205) | void PerformLabeling()
  function PerformLabelingWithSteps (line 520) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 539) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Dealloc (line 818) | void Dealloc() {
  function FirstScan (line 822) | void FirstScan() {
  function SecondScan (line 863) | void SecondScan() {

FILE: include/labeling3D_PRED_2021.h
  function FirstSlice (line 180) | void FirstSlice(int d, int w, int h) {
  function PerformLabeling (line 264) | void PerformLabeling()
  function PerformLabelingWithSteps (line 407) | void PerformLabelingWithSteps() {
  function Dealloc (line 444) | void Dealloc() {
  function FirstScan (line 448) | void FirstScan() {
  function SecondScan (line 549) | void SecondScan() {

FILE: include/labeling3D_PREDpp_2021.h
  function FirstSlice (line 180) | void FirstSlice(int d, int w, int h) {
  function PerformLabeling (line 265) | void PerformLabeling()
  function PerformLabelingWithSteps (line 408) | void PerformLabelingWithSteps() {
  function Dealloc (line 445) | void Dealloc() {
  function FirstScan (line 449) | void FirstScan() {
  function SecondScan (line 568) | void SecondScan() {

FILE: include/labeling3D_SAUF_2021.h
  function FirstSlice (line 177) | void FirstSlice(unsigned int d, unsigned int w, unsigned int h) {
  function PerformLabeling (line 239) | void PerformLabeling()
  function PerformLabelingWithSteps (line 345) | void PerformLabelingWithSteps() {
  function Dealloc (line 382) | void Dealloc() {
  function FirstScan (line 386) | void FirstScan() {
  function SecondScan (line 442) | void SecondScan() {

FILE: include/labeling3D_SAUFpp_2021.h
  function FirstSlice (line 177) | void FirstSlice(unsigned int d, unsigned int w, unsigned int h) {
  function PerformLabeling (line 239) | void PerformLabeling()
  function PerformLabelingWithSteps (line 345) | void PerformLabelingWithSteps() {
  function Dealloc (line 382) | void Dealloc() {
  function FirstScan (line 386) | void FirstScan() {
  function SecondScan (line 457) | void SecondScan() {

FILE: include/labeling3D_he_2011.h
  function PerformLabeling (line 138) | void PerformLabeling()
  function PerformLabelingWithSteps (line 212) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 231) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 664) | void Dealloc() {
  function FirstScan (line 668) | void FirstScan() {
  function SecondScan (line 707) | void SecondScan() {

FILE: include/labeling3D_he_2011_run.h
  type Run (line 16) | struct Run
  function class (line 23) | class Table3D
  function ProcessRun (line 77) | static inline int ProcessRun(uint16_t row_index, uint16_t row_nruns, Run...
  function PerformLabeling (line 116) | void PerformLabeling()
  function PerformLabelingWithSteps (line 240) | void PerformLabelingWithSteps()
  function Dealloc (line 281) | void Dealloc()
  function FirstScan (line 287) | void FirstScan()
  function SecondScan (line 383) | void SecondScan()

FILE: include/labeling3D_he_2011_tree.inc.h
  function ACTION_3 (line 13) | ACTION_3
  function ACTION_7 (line 27) | ACTION_7
  function ACTION_8 (line 41) | ACTION_8
  function ACTION_13 (line 59) | ACTION_13
  function ACTION_14 (line 76) | ACTION_14
  function ACTION_18 (line 89) | ACTION_18
  function ACTION_30 (line 109) | ACTION_30
  function ACTION_36 (line 129) | ACTION_36
  function ACTION_39 (line 139) | ACTION_39
  function ACTION_42 (line 149) | ACTION_42
  function ACTION_45 (line 158) | ACTION_45

FILE: include/labeling3D_naive.h
  function PerformLabeling (line 21) | void PerformLabeling()
  function PerformLabelingWithSteps (line 141) | void PerformLabelingWithSteps()	{
  function Dealloc (line 178) | void Dealloc() {
  function FirstScan (line 182) | void FirstScan() {
  function SecondScan (line 281) | void SecondScan() {

FILE: include/labeling_HT_CCL_Diaz2019_v1_2_0.h
  type Bool (line 56) | typedef unsigned char Bool;
  type ImageType (line 59) | typedef unsigned char ImageType;
  type JumpType (line 60) | typedef int JumpType;
  type RowColType (line 63) | typedef int RowColType;
  type listaPadres (line 84) | struct listaPadres
  type listaPadres (line 86) | struct listaPadres
  type listaPadres (line 89) | struct listaPadres
  type listaPadres (line 92) | struct listaPadres
  type listaPadres (line 94) | struct listaPadres
  type listaPadres (line 96) | struct listaPadres {
  type listaPadres (line 102) | struct listaPadres
  function PerformLabelingWithSteps (line 183) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 198) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 232) | void Dealloc()
  function AllScans (line 236) | void AllScans()
  function init_2LookUpTables_and_infection_process (line 261) | void init_2LookUpTables_and_infection_process(const cv::Mat1b &I, cv::Ma...
  function J_init (line 351) | void J_init(const cv::Mat1b &I, cv::Mat1i &J, struct listaPadres* lista,...
  function J_computation (line 397) | void J_computation(cv::Mat1i &J, struct listaPadres* lista, int id, int ...
  function Jonly_infection_process_original (line 461) | void Jonly_infection_process_original(cv::Mat1i &J, struct listaPadres* ...
  type listaPadres (line 530) | struct listaPadres
  function Transports_only (line 535) | void Transports_only(const cv::Mat1b &Itemp, cv::Mat1i &Jtemp, struct li...
  function Labelling_only (line 626) | unsigned Labelling_only(const cv::Mat1b* I, cv::Mat1i* J, cv::Mat1i* L, ...
  function init_borders (line 711) | void init_borders(const cv::Mat1b &I, cv::Mat1i &J, struct listaPadres *...
  function RowColType (line 987) | RowColType FG_lookup_table_3neighb(RowColType Right, RowColType RiDo, Ro...
  function RowColType (line 994) | RowColType BG_lookup_table_2neighb(RowColType Left, RowColType Up) { // ...
  function Jonly_transports_lots_of_searches (line 1002) | int Jonly_transports_lots_of_searches(int R_SHIFT_SEARCH, int C_SHIFT_SE...
  function JumpType (line 1168) | JumpType * travel_inside_J(JumpType *porigin, JumpType jump, JumpType *p...

FILE: include/labeling_PREDpp_2021.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 124) | void PerformLabelingWithSteps()
  function Dealloc (line 165) | void Dealloc()
  function FirstScan (line 170) | void FirstScan()
  function SecondScan (line 246) | void SecondScan()

FILE: include/labeling_algorithms.h
  function class (line 42) | class Labeling {
  function virtual (line 88) | virtual std::string CheckAlg() const { return LabelingCheckSingleton2D::...
  function virtual (line 109) | virtual std::string CheckAlg() const { return LabelingCheckSingleton3D::...
  function class (line 160) | class LabelingMapSingleton {
  function class (line 181) | class KernelMapSingleton {
  type StepType (line 198) | enum StepType {

FILE: include/labeling_bolelli_2018.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 271) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 292) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 386) | void Dealloc()
  function FirstScan (line 391) | void FirstScan()
  function SecondScan (line 528) | void SecondScan()

FILE: include/labeling_bolelli_2019.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 317) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 337) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Alloc (line 566) | double Alloc()
  function Dealloc (line 584) | void Dealloc()
  function FirstScan (line 590) | void FirstScan()
  function SecondScan (line 778) | void SecondScan()

FILE: include/labeling_fchang_2003.h
  function PerformLabeling (line 22) | void PerformLabeling()
  function PerformLabelingWithSteps (line 70) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 85) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function ContourTracing (line 177) | void ContourTracing(int x, int y, int i_label, bool b_external) {
  function Alloc (line 261) | double Alloc()
  function Dealloc (line 276) | void Dealloc()
  function AllScans (line 280) | void AllScans()

FILE: include/labeling_grana_2010.h
  function PerformLabeling (line 21) | void PerformLabeling()
  function PerformLabelingWithSteps (line 269) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 289) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 504) | void Dealloc()
  function FirstScan (line 509) | void FirstScan()
  function SecondScan (line 646) | void SecondScan()

FILE: include/labeling_grana_2016.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 105) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 126) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 221) | void Dealloc()
  function FirstScan (line 226) | void FirstScan()
  function SecondScan (line 285) | void SecondScan()

FILE: include/labeling_he_2008.h
  function buffer_ (line 31) | CircularBuffer(size_t capacity) : buffer_{ new T[capacity] }, capacity_{...
  function Create (line 39) | void Create(size_t capacity) {
  function T (line 53) | T Enqueue(T item)
  function T (line 67) | T Front()
  function T (line 78) | T Dequeue()
  function T (line 87) | T DequeueAndFront()
  function IsFull (line 93) | bool IsFull() { return size_ == capacity_; }
  function IsEmpty (line 94) | bool IsEmpty() { return !size_; }
  function PerformLabeling (line 104) | void PerformLabeling()
  function PerformLabelingWithSteps (line 264) | void PerformLabelingWithSteps()
  function Dealloc (line 320) | void Dealloc()
  function FirstScan (line 325) | void FirstScan()
  function SecondScan (line 464) | void SecondScan()

FILE: include/labeling_he_2014.h
  function PerformLabeling (line 35) | void PerformLabeling()
  function PerformLabelingWithSteps (line 136) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 156) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 276) | void Dealloc()
  function FirstScan (line 281) | void FirstScan()
  function SecondScan (line 366) | void SecondScan()

FILE: include/labeling_he_2014_graph.inc.h
  function ACTION_6 (line 64) | ACTION_6 // a <- n4
  function ACTION_6 (line 92) | ACTION_6
  function ACTION_5 (line 139) | ACTION_5
  function ACTION_7 (line 150) | ACTION_7
  function ACTION_6 (line 185) | ACTION_6
  function ACTION_6 (line 214) | ACTION_6
  function ACTION_6 (line 252) | ACTION_6
  function ACTION_6 (line 302) | ACTION_6
  function ACTION_5 (line 348) | ACTION_5
  function ACTION_7 (line 359) | ACTION_7
  function ACTION_6 (line 394) | ACTION_6
  function ACTION_6 (line 423) | ACTION_6
  function ACTION_5 (line 470) | ACTION_5
  function ACTION_7 (line 481) | ACTION_7

FILE: include/labeling_lacassagne_2016.h
  function Table2D (line 21) | struct Table2D {
  function Reserve (line 30) | void Reserve(size_t rows, size_t cols) {
  function Release (line 40) | void Release() {
  function class (line 62) | class LSL_STD : public Labeling2D<Connectivity2D::CONN_8> {
  function class (line 109) | class LSL_RLE : public Labeling2D<Connectivity2D::CONN_8> {

FILE: include/labeling_lacassagne_2016_code.inc.h
  function PerformLabelingWithSteps (line 141) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 161) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function Alloc (line 282) | double Alloc()
  function Dealloc (line 326) | void Dealloc() {
  function FirstScan (line 336) | void FirstScan()
  function SecondScan (line 427) | void SecondScan()

FILE: include/labeling_lee_2021_bmrs.h
  function Alloc (line 28) | struct Data_Compressed {
  function Dealloc (line 41) | void Dealloc() {
  type Run (line 45) | struct Run {
  function Dealloc (line 50) | struct Runs {
  function PerformLabeling (line 69) | void PerformLabeling()
  function PerformLabelingWithSteps (line 167) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 187) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function InitCompressedDataMem (line 380) | void InitCompressedDataMem(Data_Compressed& data_compressed, MemMat<unsi...
  function FindRuns (line 464) | void FindRuns(const uint64_t* bits_start, const uint64_t* bits_flag, int...
  function FindRunsMem (line 587) | void FindRunsMem(const uint64_t* bits_start, const uint64_t* bits_flag, ...
  function is_connected (line 710) | uint64_t is_connected(const uint64_t* flag_bits, unsigned start, unsigne...
  function Get_RunAllocTime (line 768) | double Get_RunAllocTime() {
  function Dealloc (line 791) | void Dealloc() {
  function FirstScan (line 799) | void FirstScan() {
  function SecondScan (line 841) | void SecondScan() {

FILE: include/labeling_lee_2021_bmrs_no_zeroinit.h
  function Alloc (line 28) | struct Data_Compressed {
  function Dealloc (line 41) | void Dealloc() {
  type Run (line 45) | struct Run {
  function Dealloc (line 50) | struct Runs {
  function PerformLabeling (line 69) | void PerformLabeling()
  function PerformLabelingWithSteps (line 169) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 189) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function InitCompressedDataMem (line 382) | void InitCompressedDataMem(Data_Compressed& data_compressed, MemMat<unsi...
  function FindRuns (line 466) | void FindRuns(const uint64_t* bits_start, const uint64_t* bits_flag, int...
  function FindRunsMem (line 589) | void FindRunsMem(const uint64_t* bits_start, const uint64_t* bits_flag, ...
  function is_connected (line 712) | uint64_t is_connected(const uint64_t* flag_bits, unsigned start, unsigne...
  function Get_RunAllocTime (line 770) | double Get_RunAllocTime() {
  function Dealloc (line 793) | void Dealloc() {
  function FirstScan (line 801) | void FirstScan() {
  function SecondScan (line 843) | void SecondScan() {

FILE: include/labeling_lee_2021_brts.h
  function Alloc (line 28) | struct Data_Compressed {
  function Dealloc (line 41) | void Dealloc() {
  type Run (line 45) | struct Run {
  function Dealloc (line 50) | struct Runs {
  function PerformLabeling (line 67) | void PerformLabeling()
  function PerformLabelingWithSteps (line 103) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 123) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function InitCompressedDataMem (line 255) | void InitCompressedDataMem(Data_Compressed& data_compressed, MemMat<unsi...
  function FindRuns (line 339) | void FindRuns(const uint64_t* bits_start, int height, int data_width, Ru...
  function FindRunsMem (line 442) | void FindRunsMem(const uint64_t* bits_start, int height, int data_width,...
  function Get_RunAllocTime (line 571) | double Get_RunAllocTime() {
  function Dealloc (line 594) | void Dealloc() {
  function FirstScan (line 600) | void FirstScan() {
  function SecondScan (line 604) | void SecondScan() {

FILE: include/labeling_lee_2021_brts_no_zeroinit.h
  function Alloc (line 28) | struct Data_Compressed {
  function Dealloc (line 41) | void Dealloc() {
  type Run (line 45) | struct Run {
  function Dealloc (line 50) | struct Runs {
  function PerformLabeling (line 67) | void PerformLabeling()
  function PerformLabelingWithSteps (line 103) | void PerformLabelingWithSteps() {
  function PerformLabelingMem (line 123) | void PerformLabelingMem(std::vector<uint64_t>& accesses) {
  function InitCompressedDataMem (line 255) | void InitCompressedDataMem(Data_Compressed& data_compressed, MemMat<unsi...
  function FindRuns (line 339) | void FindRuns(const uint64_t* bits_start, int height, int data_width, Ru...
  function FindRunsMem (line 442) | void FindRunsMem(const uint64_t* bits_start, int height, int data_width,...
  function Get_RunAllocTime (line 571) | double Get_RunAllocTime() {
  function Dealloc (line 594) | void Dealloc() {
  function FirstScan (line 600) | void FirstScan() {
  function SecondScan (line 604) | void SecondScan() {

FILE: include/labeling_null.h
  function class (line 16) | class labeling_NULL : public Labeling2D<Connectivity2D::CONN_8> {

FILE: include/labeling_sauf_4c.h
  function PerformLabeling (line 21) | void PerformLabeling()
  function PerformLabelingWithSteps (line 90) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 110) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 204) | void Dealloc() {
  function FirstScan (line 208) | void FirstScan() {
  function SecondScan (line 262) | void SecondScan()

FILE: include/labeling_sauf_background.h
  function PerformLabeling (line 21) | void PerformLabeling()
  function PerformLabelingWithSteps (line 101) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 121) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 226) | void Dealloc() {
  function FirstScan (line 230) | void FirstScan() {
  function SecondScan (line 295) | void SecondScan()

FILE: include/labeling_tagliatelle_2021.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 317) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 337) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Alloc (line 586) | double Alloc()
  function Dealloc (line 604) | void Dealloc()
  function FirstScan (line 610) | void FirstScan()
  function SecondScan (line 798) | void SecondScan()

FILE: include/labeling_wu_2009.h
  function PerformLabeling (line 21) | void PerformLabeling()
  function PerformLabelingWithSteps (line 95) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 115) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 212) | void Dealloc() {
  function FirstScan (line 216) | void FirstScan() {
  function SecondScan (line 275) | void SecondScan()

FILE: include/labeling_wychang_2015.h
  function PerformLabeling (line 45) | void PerformLabeling()
  function PerformLabelingWithSteps (line 242) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 262) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function Dealloc (line 427) | void Dealloc()
  function FirstScan (line 432) | void FirstScan()
  function SecondScan (line 521) | void SecondScan()

FILE: include/labeling_zhao_2010.h
  function PerformLabeling (line 23) | void PerformLabeling()
  function PerformLabelingWithSteps (line 251) | void PerformLabelingWithSteps()
  function PerformLabelingMem (line 272) | void PerformLabelingMem(std::vector<uint64_t>& accesses)
  function FindRootAndCompress (line 514) | inline void FindRootAndCompress(int *img_labels, int pos, int newroot)
  function FindRootMem (line 527) | inline int FindRootMem(MemMat<int>& img_labels, int pos)
  function FindRootAndCompressMem (line 538) | inline void FindRootAndCompressMem(MemMat<int>& img_labels, int pos, int...
  function Alloc (line 555) | double Alloc()
  function Dealloc (line 570) | void Dealloc()
  function FirstScan (line 573) | void FirstScan()
  function SecondScan (line 763) | void SecondScan()

FILE: include/labels_solver.h
  function class (line 15) | class UF {
  function class (line 169) | class UFPC {
  function class (line 328) | class RemSP {
  function class (line 472) | class TTA {

FILE: include/memory_tester.h
  type memorydatatype (line 12) | enum memorydatatype {
  function GetTotalAccesses (line 84) | double GetTotalAccesses() const
  function GetTotalAccesses (line 135) | double GetTotalAccesses() const
  function T (line 146) | T* GetDataPointer()
  function size (line 151) | size_t size()
  function Memiota (line 156) | void Memiota(size_t begin, size_t end, const T value)

FILE: include/performance_evaluator.h
  function class (line 14) | class PerformanceEvaluator {

FILE: include/progress_bar.h
  function class (line 34) | class ProgressBar {
  function Start (line 56) | void Start()
  function Display (line 69) | void Display(const unsigned progress)
  function End (line 91) | void End()
  function StartRepeated (line 125) | void StartRepeated()
  function DisplayRepeated (line 139) | void DisplayRepeated(const unsigned progress)
  function EndRepeated (line 162) | bool EndRepeated()
  function class (line 200) | class OutputBox {
  function StartUnitaryBox (line 227) | void StartUnitaryBox(const std::string &dataset_name, const size_t n_thi...
  function UpdateUnitaryBox (line 235) | void UpdateUnitaryBox(const unsigned progress)
  function StopUnitaryBox (line 240) | void StopUnitaryBox()
  function StartRepeatedBox (line 246) | void StartRepeatedBox(const std::string &dataset_name, const unsigned n_...
  function UpdateRepeatedBox (line 254) | void UpdateRepeatedBox(const unsigned progress)
  function DisplayReport (line 266) | void DisplayReport(const std::string &title, const std::vector<std::stri...
  function Cmessage (line 333) | void Cmessage(const std::string& msg)
  function CloseBox (line 347) | void CloseBox() {
  function PrintRawData (line 356) | void PrintRawData(const std::string &data)
  function PrintData (line 360) | void PrintData(const std::string &data)

FILE: include/stream_demultiplexer.h
  function class (line 13) | class StreamDemultiplexer

FILE: include/system_info.h
  function class (line 50) | class SystemInfo {
  function cuda_capability (line 98) | struct CudaInfo {
  function std (line 104) | static std::string runtime_version() { return GetInstance().runtime_vers...
  function std (line 105) | static std::string driver_version() { return GetInstance().driver_versio...

FILE: include/utilities.h
  function namespace (line 21) | namespace dmux {

FILE: include/yacclab_tensor.h
  function class (line 21) | class YacclabTensor {
  function class (line 30) | class YacclabTensorInput : public YacclabTensor {
  function class (line 37) | class YacclabTensorInput2D : public YacclabTensorInput {
  function class (line 49) | class YacclabTensorInput3D : public YacclabTensorInput {
  function virtual (line 54) | virtual void Release() override {  mat_.release(); }
  function virtual (line 56) | virtual cv::Mat& GetMat() { return mat_;  }
  function virtual (line 57) | virtual cv::Mat& Raw() {  return mat_;  }
  function Dims (line 58) | virtual unsigned int Dims() override { return 3; }
  function class (line 63) | class YacclabTensorInput2DCuda : public YacclabTensorInput2D {
  function class (line 74) | class YacclabTensorInput3DCuda : public YacclabTensorInput3D {
  function class (line 87) | class YacclabTensorOutput : public YacclabTensor {
  function class (line 99) | class YacclabTensorOutput2D : public YacclabTensorOutput {
  function class (line 132) | class YacclabTensorOutput2DCuda : public YacclabTensorOutput2D {
  function class (line 142) | class YacclabTensorOutput3DCuda : public YacclabTensorOutput3D {

FILE: include/yacclab_tests.h
  function class (line 26) | class YacclabTests {

FILE: old/configurationReader.h
  function exitWithError (line 18) | void exitWithError(const std::string &error)
  function class (line 27) | class Convert
  function class (line 63) | class ConfigFile

FILE: old/equivalenceSolverSuzuki.h
  function setRoot (line 30) | void setRoot(LabelT *P, LabelT i, LabelT root)

FILE: src/check_labeling.cc
  function LabelingCheckSingleton2D (line 5) | LabelingCheckSingleton2D& LabelingCheckSingleton2D::GetInstance() {
  function LabelingCheckSingleton3D (line 14) | LabelingCheckSingleton3D& LabelingCheckSingleton3D::GetInstance() {
  class LabelingCheckAlgorithmsSet (line 24) | class LabelingCheckAlgorithmsSet {
    method LabelingCheckAlgorithmsSet (line 26) | LabelingCheckAlgorithmsSet() {

FILE: src/config_data.cc
  function ReadBool (line 7) | bool ReadBool(const FileNode& node_list)

FILE: src/file_manager.cc
  type stat (line 29) | struct stat
  type stat (line 47) | struct stat

FILE: src/labeling_algorithms.cc
  function LabelingMapSingleton (line 91) | LabelingMapSingleton& LabelingMapSingleton::GetInstance()
  function Labeling (line 98) | Labeling* LabelingMapSingleton::GetLabeling(const std::string& s)
  function KernelMapSingleton (line 110) | KernelMapSingleton& KernelMapSingleton::GetInstance()
  function Step (line 143) | std::string Step(StepType n_step)

FILE: src/main.cc
  function main (line 34) | int main()

FILE: src/system_info.cc
  function SystemInfo (line 18) | SystemInfo& SystemInfo::GetInstance()
  type utsname (line 133) | struct utsname
  function CudaInfo (line 231) | CudaInfo& CudaInfo::GetInstance()

FILE: src/utilities.cc
  function CompareLengthCvString (line 42) | bool CompareLengthCvString(String const& lhs, String const& rhs)
  function RemoveCharacter (line 47) | void RemoveCharacter(string& s, const char c)
  function ctoi (line 52) | unsigned ctoi(const char& c)
  function string (line 57) | string GetDatetime()
  function string (line 85) | string GetDatetimeWithoutSpecialChars()
  function CheckLabeledImage (line 271) | bool CheckLabeledImage(const Mat1b& img, const Mat1i& labels, Mat1i& err...
  function CheckLabeledVolume (line 302) | bool CheckLabeledVolume(const Mat& img, const Mat& labels, Mat& errors) {
  function HideConsoleCursor (line 345) | void HideConsoleCursor()
  function RedirectCvError (line 363) | int RedirectCvError(int status, const char* func_name, const char* err_m...
  function GetGnuplotTitle (line 397) | std::string GetGnuplotTitle() {
  function GetGnuplotTitleGpu (line 404) | std::string GetGnuplotTitleGpu() {
  function string (line 411) | string EscapeUnderscore(const string& s)
  function string (line 426) | string DoubleEscapeUnderscore(const string& s)

FILE: src/volume_util.cc
  function volread (line 13) | cv::Mat volread(const cv::String &filename, int flags) {
  function volwrite (line 68) | bool volwrite(const cv::String& filename, const cv::Mat& volume) {

FILE: src/yacclab_tests.cc
  class CheckDatasetsExistence (line 177) | class CheckDatasetsExistence {
    method CheckDatasetsExistence (line 186) | CheckDatasetsExistence(const path& input_path, const std::string& inpu...

FILE: tools/embed_pdf/embed.php
  function dirtysuds_embed_pdf_enable_embeds (line 34) | function dirtysuds_embed_pdf_enable_embeds() {
  function dirtysuds_embed_pdf (line 38) | function dirtysuds_embed_pdf( $matches, $atts, $url, $rawattr=null ) {
  function dirtysuds_embed_pdf_rate (line 103) | function dirtysuds_embed_pdf_rate($links,$file) {
Copy disabled (too large) Download .json
Condensed preview — 222 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (13,099K chars).
[
  {
    "path": ".all-contributorsrc",
    "chars": 2750,
    "preview": "{\n  \"projectName\": \"YACCLAB\",\n  \"projectOwner\": \"prittt\",\n  \"files\": [\n    \"README.md\"\n  ],\n  \"commit\": false,\n  \"repoTy"
  },
  {
    "path": ".github/workflows/linux64.yml",
    "chars": 499,
    "preview": "name: linux64\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-18.04\n    container:\n        image: docker://aimagelab/yac"
  },
  {
    "path": ".github/workflows/macos.yml",
    "chars": 1201,
    "preview": "name: macos\n\non: [push]\n\njobs:\n  build:\n    runs-on: macos-10.15\n    steps:\n    - uses: actions/checkout@v2\n    \n    - n"
  },
  {
    "path": ".gitignore",
    "chars": 181,
    "preview": "**/*.vcxproj\n**/*.filters\n**/*.sln\n**/*.opensdf\n**/*.suo\n**/*.sdf\n**/*.user\n\n/Release\n/Debug\n/[Bb]in*\n/[Bb]uild*\n\n/CMake"
  },
  {
    "path": "AUTHORS",
    "chars": 533,
    "preview": "Copyright (c) 2020, Federico Bolelli, Costantino Grana, Michele Cancilla, Stefano Allegretti, Lorenzo Baraldi, Roberto V"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 16917,
    "preview": "# Copyright (c) 2021, the YACCLAB contributors, as \n# shown by the AUTHORS file. All rights reserved.\n#\n# Use of this so"
  },
  {
    "path": "Jenkinsfile",
    "chars": 3563,
    "preview": "pipeline {\n    agent none\n    stages {\n        stage('Parallel Stages') {\n            parallel {\n               stage('u"
  },
  {
    "path": "LICENSE",
    "chars": 1566,
    "preview": "BSD 3-Clause License\n\nCopyright (c) 2020, the respective contributors, as shown by the AUTHORS file.\nAll rights reserved"
  },
  {
    "path": "README.md",
    "chars": 71983,
    "preview": "# Yet Another Connected Components Labeling Benchmark\n[![release](https://img.shields.io/github/v/release/prittt/YACCLAB"
  },
  {
    "path": "config.yaml",
    "chars": 5759,
    "preview": "%YAML:1.2\n---\n##########################################\n# THIS IS THE YACCLAB CONFIGURATION FILE #\n####################"
  },
  {
    "path": "cuda/CMakeLists.txt",
    "chars": 47,
    "preview": "add_subdirectory(include)\nadd_subdirectory(src)"
  },
  {
    "path": "cuda/include/CMakeLists.txt",
    "chars": 229,
    "preview": "target_sources(YACCLAB\n    PRIVATE\n        cuda_mat3.hpp\n        cuda_mat3.inl.hpp\n        cuda_types3.hpp\n        #labe"
  },
  {
    "path": "cuda/include/cuda_mat3.hpp",
    "chars": 1581,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/include/cuda_mat3.inl.hpp",
    "chars": 979,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/include/cuda_types3.hpp",
    "chars": 3018,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/CMakeLists.txt",
    "chars": 1460,
    "preview": "target_sources(YACCLAB  PRIVATE\n    gpu_mat3.cu\n    labeling_oliveira_2010.cu\n    labeling_kalentev_2011.cu\n    labeling"
  },
  {
    "path": "cuda/src/gpu_mat3.cu",
    "chars": 2707,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BE_3D_light.cu",
    "chars": 25655,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BE_3D_light_shared.cu",
    "chars": 26186,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BE_big_tex.cu",
    "chars": 13951,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BE_light.cu",
    "chars": 12939,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BKE_NoInlineCompression.cu",
    "chars": 16325,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BUF_2S.cu",
    "chars": 13785,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BUF_3D_NoInlineCompression.cu",
    "chars": 24537,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_BUF_NoInlineCompression.cu",
    "chars": 9258,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_KE4.cu",
    "chars": 5837,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_KE_2S.cu",
    "chars": 14076,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_OLE_tex.cu",
    "chars": 10609,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_RADAR.cu",
    "chars": 6040,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_TUF.cu",
    "chars": 8780,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_UF_InlineCompression.cu",
    "chars": 10573,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_UF_naive.cu",
    "chars": 5812,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2018.cu",
    "chars": 9229,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_BBDT.cu",
    "chars": 13193,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_BKE.cu",
    "chars": 16969,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_BKE_3D.cu",
    "chars": 21912,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_BUF.cu",
    "chars": 11502,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_BUF_3D.cu",
    "chars": 23158,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_DRAG.cu",
    "chars": 13435,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_SAUF.cu",
    "chars": 7881,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_allegretti_2019_UF_3D.cu",
    "chars": 10673,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_cabaret_2017.cu",
    "chars": 11401,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_chen_2011.cu",
    "chars": 10786,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_chen_2011_1024.cu",
    "chars": 17881,
    "preview": "#define WP 32\n\n\n#define BM (WP-1)\n#define dt unsigned short\n#define dts 2\n\n#define TGTG  1\n#define TGNTG 0\n\n#define LBMA"
  },
  {
    "path": "cuda/src/labeling_chen_2011_2048.cu",
    "chars": 17883,
    "preview": "#define WP 32\n\n\n#define BM (WP-1)\n#define dt unsigned short\n#define dts 2\n\n#define TGTG  1\n#define TGNTG 0\n\n#define LBMA"
  },
  {
    "path": "cuda/src/labeling_chen_2011_512.cu",
    "chars": 17928,
    "preview": "#define WP 32\n\n\n#define BM (WP-1)\n#define dt unsigned short\n#define dts 2\n\n#define TGTG  1\n#define TGNTG 0\n\n#define LBMA"
  },
  {
    "path": "cuda/src/labeling_hennequin_2018_HA4.cu",
    "chars": 9795,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_hennequin_2018_HA8.cu",
    "chars": 13306,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_kalentev_2011.cu",
    "chars": 7978,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_oliveira_2010.cu",
    "chars": 12425,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_paravecino_2014.cu",
    "chars": 12464,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_rasmusson_2013.cu",
    "chars": 22126,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_soh_2014_8DLS.cu",
    "chars": 7229,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_soh_2014_M8DLS.cu",
    "chars": 8101,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_stava_2011.cu",
    "chars": 14412,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_yonehara_2015.cu",
    "chars": 8770,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_zavalishin_2016.cu",
    "chars": 18056,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/labeling_zavalishin_2016_3D.cu",
    "chars": 25945,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/next_to_trash/labeling_CUDA_BKE_InlineCompression.cu",
    "chars": 14981,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/next_to_trash/labeling_CUDA_BUF_2S.cu",
    "chars": 14077,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/next_to_trash/labeling_CUDA_KE_2S.cu",
    "chars": 14459,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "cuda/src/next_to_trash/labeling_CUDA_UF_InlineCompression.cu",
    "chars": 10669,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "doc/EPDT/README.md",
    "chars": 4126,
    "preview": "## [RLPR - Reproducible Label in Pattern Recognition](https://github.com/RLPR)\n<img style=\"float: right;\" src=\"RRLPR.png"
  },
  {
    "path": "doc/README.txt",
    "chars": 315,
    "preview": "\"config_base.yaml\": It is the standard configuration file of YACCLAB automatically filled by CMake. \n\tIf you want to cha"
  },
  {
    "path": "doc/config_2d.yaml",
    "chars": 3101,
    "preview": "\nCPU 2D 8-way connectivity:\n\n  execute: true\n  \n  # Tests to perform and their number of repetitions\n  # ---------------"
  },
  {
    "path": "doc/config_3d.yaml",
    "chars": 2066,
    "preview": "\nCPU 3D 26-way connectivity:\n  \n  execute: true\n  \n  # Tests to perform and their number of repetitions\n  # ------------"
  },
  {
    "path": "doc/config_base.yaml",
    "chars": 909,
    "preview": "%YAML:1.2\n---\n##########################################\n# THIS IS THE YACCLAB CONFIGURATION FILE #\n####################"
  },
  {
    "path": "doc/config_ci_cpu.yaml",
    "chars": 4915,
    "preview": "%YAML:1.2\n---\n##########################################\n# This is the YACCLAB configuration file #\n####################"
  },
  {
    "path": "doc/config_ci_cpu2d.yaml",
    "chars": 3225,
    "preview": "%YAML:1.2\n---\n##########################################\n# This is the YACCLAB configuration file #\n####################"
  },
  {
    "path": "doc/config_cuda_2d.yaml",
    "chars": 2223,
    "preview": "  \nGPU 2D 8-way connectivity:\n   \n  execute: true\n  \n  #  Tests to perform and their number of repetitions\n  # ---------"
  },
  {
    "path": "doc/config_cuda_3d.yaml",
    "chars": 1827,
    "preview": "\nGPU 3D 26-way connectivity:\n\n  execute: true\n  \n  # Tests to perform and their number of repetitions\n  # --------------"
  },
  {
    "path": "doc/config_epdt_19c.yaml",
    "chars": 93,
    "preview": "  #  - EPDT_3D_19c_UF\n  #  - EPDT_3D_19c_UFPC\n  #  - EPDT_3D_19c_TTA\n    - EPDT_3D_19c_RemSP\n"
  },
  {
    "path": "doc/config_epdt_22c.yaml",
    "chars": 93,
    "preview": "  #  - EPDT_3D_22c_UF\n  #  - EPDT_3D_22c_UFPC\n  #  - EPDT_3D_22c_TTA\n    - EPDT_3D_22c_RemSP\n"
  },
  {
    "path": "doc/config_epdt_26c.yaml",
    "chars": 93,
    "preview": "  #  - EPDT_3D_26c_UF\n  #  - EPDT_3D_26c_UFPC\n  #  - EPDT_3D_26c_TTA\n    - EPDT_3D_26c_RemSP\n"
  },
  {
    "path": "doc/config_jenkins.yaml",
    "chars": 8059,
    "preview": "%YAML:1.2\n---\n##########################################\n# THIS IS THE YACCLAB CONFIGURATION FILE #\n####################"
  },
  {
    "path": "include/CMakeLists.txt",
    "chars": 3864,
    "preview": "target_sources(YACCLAB\n    PRIVATE\n        check_labeling.h\n        config_data.h\n        file_manager.h\n        labelin"
  },
  {
    "path": "include/bit_scan_forward.h",
    "chars": 1823,
    "preview": "// Copyright (c) 2021, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/check_labeling.h",
    "chars": 1424,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/config_data.h",
    "chars": 6802,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/file_manager.h",
    "chars": 3240,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_EPDT_19c.h",
    "chars": 34749,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_19c_211b.h",
    "chars": 34747,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_19c_action_def.inc.h",
    "chars": 917411,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_19c_action_def_mem.inc.h",
    "chars": 950416,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_19c_action_def_memory.inc.h",
    "chars": 950416,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_19c_tree.inc.h",
    "chars": 74431,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c.h",
    "chars": 20491,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c_211b.h",
    "chars": 20491,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c_action_def.inc.h",
    "chars": 917410,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c_action_def_mem.inc.h",
    "chars": 950416,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c_action_def_memory.inc.h",
    "chars": 950416,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_22c_tree.inc.h",
    "chars": 165827,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_26c.h",
    "chars": 49084,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_26c_action_def.inc.h",
    "chars": 917422,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_26c_action_def_mem.inc.h",
    "chars": 890348,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_26c_action_def_memory.inc.h",
    "chars": 890348,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_26c_tree.inc.h",
    "chars": 1086913,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_EPDT_2829_action_undef.inc.h",
    "chars": 53006,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling3D_PRED_2021.h",
    "chars": 33166,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_PRED_2021_cl_forest.inc.h",
    "chars": 30478,
    "preview": "cl_tree_0: if ((c+=1) >= w - 1) goto cl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto cl_t"
  },
  {
    "path": "include/labeling3D_PRED_2021_fl_forest.inc.h",
    "chars": 4996,
    "preview": "fl_tree_0: if ((c+=1) >= w - 1) goto fl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto fl_t"
  },
  {
    "path": "include/labeling3D_PRED_2021_ll_forest.inc.h",
    "chars": 7298,
    "preview": "ll_tree_0: if ((c+=1) >= w - 1) goto ll_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto ll_t"
  },
  {
    "path": "include/labeling3D_PRED_2021_sl_forest.inc.h",
    "chars": 2174,
    "preview": "sl_tree_0: if ((c+=1) >= w - 1) goto sl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto sl_t"
  },
  {
    "path": "include/labeling3D_PREDpp_2021.h",
    "chars": 33197,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_PREDpp_2021_cl_forest.inc.h",
    "chars": 19795,
    "preview": "cl_tree_0: if ((c+=1) >= w - 1) goto cl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto cl_t"
  },
  {
    "path": "include/labeling3D_PREDpp_2021_fl_forest.inc.h",
    "chars": 3710,
    "preview": "fl_tree_0: if ((c+=1) >= w - 1) goto fl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto fl_t"
  },
  {
    "path": "include/labeling3D_PREDpp_2021_ll_forest.inc.h",
    "chars": 5980,
    "preview": "ll_tree_0: if ((c+=1) >= w - 1) goto ll_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto ll_t"
  },
  {
    "path": "include/labeling3D_PREDpp_2021_sl_forest.inc.h",
    "chars": 2086,
    "preview": "sl_tree_0: if ((c+=1) >= w - 1) goto sl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t\tgoto sl_t"
  },
  {
    "path": "include/labeling3D_SAUF_2021.h",
    "chars": 27808,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_SAUF_2021_tree.inc.h",
    "chars": 10272,
    "preview": "\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (CONDITION_M) {\n\t\t\t\t\tif (CONDITION_K) {\n\t\t"
  },
  {
    "path": "include/labeling3D_SAUFpp_2021.h",
    "chars": 27998,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_SAUFpp_2021_tree.inc.h",
    "chars": 9345,
    "preview": "\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_E) {\n\t\t\t\tACTION_9\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (CONDITION_M) {\n\t\t\t\t\tif (CONDITION_K) {\n\t\t"
  },
  {
    "path": "include/labeling3D_he_2011.h",
    "chars": 30720,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_he_2011_run.h",
    "chars": 16099,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_he_2011_tree.inc.h",
    "chars": 7301,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling3D_naive.h",
    "chars": 9525,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_HT_CCL_Diaz2019_v1_2_0.h",
    "chars": 42837,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling_PREDpp_2021.h",
    "chars": 7672,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_PREDpp_2021_cl_forest.inc.h",
    "chars": 2071,
    "preview": "cl_tree_0: if ((c+=1) >= w - 1) goto cl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tif (CONDITION_Q) {\n\t\t\t\tACTION_4\n\t\t\t\tgoto cl_t"
  },
  {
    "path": "include/labeling_PREDpp_2021_fl_forest.inc.h",
    "chars": 484,
    "preview": "fl_tree_0: if ((c+=1) >= w - 1) goto fl_break_0_0;\n\t\tif (CONDITION_X) {\n\t\t\tACTION_2\n\t\t\tgoto fl_tree_1;\n\t\t}\n\t\telse {\n\t\t\tA"
  },
  {
    "path": "include/labeling_algorithms.h",
    "chars": 6952,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2018.h",
    "chars": 25188,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2018_drag.inc.h",
    "chars": 6257,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2019.h",
    "chars": 27692,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2019_forest.inc.h",
    "chars": 25010,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2019_forest_fl.inc.h",
    "chars": 3060,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2019_forest_ll.inc.h",
    "chars": 10805,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_bolelli_2019_forest_sl.inc.h",
    "chars": 1403,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_distefano_1999.h",
    "chars": 17423,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_fchang_2003.h",
    "chars": 12074,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_grana_2010.h",
    "chars": 29507,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_grana_2010_tree.inc.h",
    "chars": 25477,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_grana_2016.h",
    "chars": 9226,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_grana_2016_forest.inc.h",
    "chars": 3475,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_grana_2016_forest_0.inc.h",
    "chars": 652,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_he_2008.h",
    "chars": 19627,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \r\n// shown by the AUTHORS file. All rights reserved.\r\n//\r\n// Use of "
  },
  {
    "path": "include/labeling_he_2014.h",
    "chars": 13337,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_he_2014_graph.inc.h",
    "chars": 14755,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_lacassagne_2016.h",
    "chars": 3235,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_lacassagne_2016_code.inc.h",
    "chars": 15862,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_lee_2021_bmrs.h",
    "chars": 37737,
    "preview": "// Copyright (c) 2021, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling_lee_2021_bmrs_no_zeroinit.h",
    "chars": 38239,
    "preview": "// Copyright (c) 2021, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling_lee_2021_brts.h",
    "chars": 25880,
    "preview": "// Copyright (c) 2021, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling_lee_2021_brts_no_zeroinit.h",
    "chars": 25980,
    "preview": "// Copyright (c) 2021, the YACCLAB contributors, as \n// shown by the AUTHORS file, plus additional authors\n// listed bel"
  },
  {
    "path": "include/labeling_null.h",
    "chars": 2928,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_sauf_4c.h",
    "chars": 8383,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_sauf_4c_tree.inc.h",
    "chars": 547,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_sauf_background.h",
    "chars": 10673,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_sauf_bg_tree.inc.h",
    "chars": 1484,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_tagliatelle_2021.h",
    "chars": 36054,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_tagliatelle_2021_cl_forest.inc.h",
    "chars": 64619,
    "preview": "cl_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto cl_break_0_0; } else { goto cl_break_1_0; } } \n\t\tif (CONDITION_O"
  },
  {
    "path": "include/labeling_tagliatelle_2021_fl_forest.inc.h",
    "chars": 4153,
    "preview": "fl_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto fl_break_0_0; } else { goto fl_break_1_0; } } \n\t\tif (CONDITION_O"
  },
  {
    "path": "include/labeling_tagliatelle_2021_ll_forest.inc.h",
    "chars": 16180,
    "preview": "ll_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto ll_break_0_0; } else { goto ll_break_1_0; } } \n\t\tif (CONDITION_O"
  },
  {
    "path": "include/labeling_tagliatelle_2021_sl_forest.inc.h",
    "chars": 1296,
    "preview": "sl_tree_0: if ((c+=2) >= w - 2) { if (c > w - 2) { goto sl_break_0_0; } else { goto sl_break_1_0; } } \n\t\tif (CONDITION_O"
  },
  {
    "path": "include/labeling_wu_2009.h",
    "chars": 9612,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_wu_2009_tree.inc.h",
    "chars": 1276,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_wychang_2015.h",
    "chars": 23707,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_wychang_2015_tree.inc.h",
    "chars": 11414,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_wychang_2015_tree_0.inc.h",
    "chars": 3290,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labeling_zhao_2010.h",
    "chars": 25295,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/labels_solver.h",
    "chars": 19931,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/memory_tester.h",
    "chars": 5505,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/performance_evaluator.h",
    "chars": 1829,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/progress_bar.h",
    "chars": 10960,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/register.h",
    "chars": 2453,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/stream_demultiplexer.h",
    "chars": 2158,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/system_info.h",
    "chars": 3217,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/utilities.h",
    "chars": 3329,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/volume_util.h",
    "chars": 733,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/yacclab_tensor.h",
    "chars": 5540,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "include/yacclab_tests.h",
    "chars": 8755,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "old/.travis.yml",
    "chars": 2434,
    "preview": "# Copyright(c) 2016 - 2017 Federico Bolelli\n# All rights reserved.\n# \n# Redistribution and use in source and binary form"
  },
  {
    "path": "old/configurationReader.h",
    "chars": 5861,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "old/equivalenceSolverSuzuki.h",
    "chars": 4701,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "spike/performanceEvaluator.h.chrono",
    "chars": 1715,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/CMakeLists.txt",
    "chars": 1710,
    "preview": "target_sources(YACCLAB\n    PRIVATE\n        check_labeling.cc\n        config_data.cc\n        file_manager.cc\n        labe"
  },
  {
    "path": "src/check_labeling.cc",
    "chars": 1537,
    "preview": "#include \"check_labeling.h\"\n\nusing namespace std;\n\nLabelingCheckSingleton2D& LabelingCheckSingleton2D::GetInstance() {\n "
  },
  {
    "path": "src/config_data.cc",
    "chars": 4463,
    "preview": "#include \"config_data.h\"\n\nusing namespace cv;\nusing namespace std;\nusing namespace ::filesystem;\n\nbool ReadBool(const Fi"
  },
  {
    "path": "src/file_manager.cc",
    "chars": 3133,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \r\n// shown by the AUTHORS file. All rights reserved.\r\n//\r\n// Use of "
  },
  {
    "path": "src/labeling3D_EPDT_19c.cc",
    "chars": 304,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_EPDT_22c.cc",
    "chars": 304,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_EPDT_26c.cc",
    "chars": 304,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_PRED_2021.cc",
    "chars": 301,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_PREDpp_2021.cc",
    "chars": 305,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_SAUF_2021.cc",
    "chars": 301,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_SAUFpp_2021.cc",
    "chars": 305,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_he_2011.cc",
    "chars": 298,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_he_2011_run.cc",
    "chars": 303,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling3D_naive.cc",
    "chars": 296,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_HT_CCL_Diaz2019_v1_2_0.cc",
    "chars": 1765,
    "preview": "// Copyright(c) 2018 Fernando Diaz del Rio and Pedro Real Jurado\n// Dpto ATC: www.atc.us.es and Dpto MA1 www.ma1.us.es\n/"
  },
  {
    "path": "src/labeling_PREDpp_2021.cc",
    "chars": 299,
    "preview": "// Copyright (c) 2022, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_algorithms.cc",
    "chars": 5334,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_bolelli_2018.cc",
    "chars": 298,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_bolelli_2019.cc",
    "chars": 354,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_distefano_1999.cc",
    "chars": 279,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_fchang_2003.cc",
    "chars": 269,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_grana_2010.cc",
    "chars": 297,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_grana_2016.cc",
    "chars": 296,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  },
  {
    "path": "src/labeling_he_2008.cc",
    "chars": 301,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \r\n// shown by the AUTHORS file. All rights reserved.\r\n//\r\n// Use of "
  },
  {
    "path": "src/labeling_he_2014.cc",
    "chars": 292,
    "preview": "// Copyright (c) 2020, the YACCLAB contributors, as \n// shown by the AUTHORS file. All rights reserved.\n//\n// Use of thi"
  }
]

// ... and 22 more files (download for full content)

About this extraction

This page contains the full source code of the prittt/YACCLAB GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 222 files (11.4 MB), approximately 3.0M tokens, and a symbol index with 415 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!