Open-source project
theICTlab/3DUNDERWORLD-SLS-GPU_CPU avatar
theICTlab/3DUNDERWORLD-SLS-GPU_CPU

3DUNDERWORLD-SLS-GPU_CPU: a structured light scanner you compile yourself

A structured light scanner

311 stars120 forksC++LGPL-3.0

At a glance

What is it?
The ICT Lab's C++ structured light scanner turns two folders of pattern-lit photos into a point cloud, with CPU and CUDA reconstructors behind one CMake build. It is a research codebase, not a product, and the README is honest about the parts that are missing.
Who is it for?
Adopt 3DUNDERWORLD-SLS-GPU_CPU if you already own a calibrated stereo rig, can produce OpenCV XML calibration files, and are willing to write the camera capture layer yourself; the reconstructor and the point cloud output are the parts it actually delivers. Do not adopt it if you expect a working acquisition pipeline, a maintained release cadence, or CUDA support on a machine without an NVIDIA GPU, since the build silently falls back to CPU.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 95 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What 3DUNDERWORLD-SLS-GPU_CPU reconstructs, and for whom

Structured light scanning works by projecting a grid of patterns onto an object and photographing the result from two viewpoints. Each cell in the projected grid carries a unique sequence, and decoding those sequences in both images gives the correspondences needed to triangulate depth. The README describes the project in exactly those terms: patterns are projected onto the object in a grid manner, each cell has a unique sequence, and corresponding points are extracted by decoding the sequences from both images.

The repository is the C++ implementation of that pipeline, released under LGPL-3.0, with the reconstruction step written twice: once for the CPU and once for the GPU. The intended user is a computer vision researcher or graduate student who has a physical scanner rig (a projector and two cameras), can calibrate it with OpenCV, and needs the software half of the system rather than a finished product. A second audience is developers who want the reconstruction library embedded in their own application, since the README points to App.cpp and App_CUDA.cu as integration examples.

It is not a consumer tool. There is no installer, no GUI, and no camera driver. The README states plainly that camera acquisition is not implemented because there is no good API for cameras, and that interfaces are provided for others to fill in. That single sentence defines the project's boundary: everything downstream of image capture is here, everything upstream is your problem.

ImageProcessor, Reconstructor and the Bucket data flow

The architecture has two building blocks. ImageProcessor takes images, projector parameters and camera calibration parameters, and produces Buckets. Reconstructor consumes all the Buckets and produces the point cloud. The README includes a diagram at doc/how-it-works.svg for the full flow.

That split is the design decision worth noticing. Decoding is per-view and can be parallelised across images, which is where the GPU version earns its place; triangulation is a separate stage that only sees decoded correspondences. Because Buckets are the interface between the two, the CPU and GPU implementations can share the reconstructor and differ only in how decoding runs. The README says both versions accelerate reconstruction time and that the GPU one does so especially, though it gives no numbers, and neither the README nor the release notes provide a benchmark table.

Calibration enters as OpenCV XML files containing intrinsic and extrinsic parameters, generated by OpenCV's calibration tool. There is no calibration workflow inside this repository, so a rig that has not been calibrated elsewhere cannot be used. The projector's resolution is passed separately on the command line as width and height, which means the pattern geometry is a runtime parameter rather than something baked into the build.

Building the scanner from source with CMake

The dependencies are listed as OpenCV2, CUDA 6.0 or newer, and glm. The repository is cloned recursively because submodules are involved, and the build is a standard out-of-tree CMake build. The README gives these commands:

bash
git clone --recursive https://github.com/theICTlab/3DUNDERWORLD-SLS-GPU_CPU.git
cd 3DUNDERWORLD-SLS-GPU_CPU
mkdir build
cd build
cmake ..
make

After make finishes, binaries land in the bin folder. If CUDA is detected, the cmake flag ENABLE_CUDA is set to on by default and both CPU and GPU constructors are created; otherwise only the CPU constructor is generated. That automatic detection is convenient but also a silent failure mode: if CUDA is installed but not visible to CMake, you get a CPU build without an error. Passing -DENABLE_CUDA=off disables CUDA explicitly when you do not want the GPU binary.

There is also an optional test target using Google Test, enabled with -DGTEST=ON at configuration time, which downloads and compiles Google Test during the build; make test runs it. Documentation is built with -DBUILD_DOC=on followed by make doc, and coverage reporting uses lcov when both -DGTEST=on and -DCOVERAGE=on are set, with make coverage writing into a coverage directory. Those extra flags are the fastest way to check that your toolchain can build the project before you invest in a rig.

A first run against the bundled alexander dataset

The repository includes demo data and demo binaries, so the first real use does not require a scanner. The README's library walkthrough copies the alexander dataset into a working directory and runs the SLS binary against it:

bash
cd 3DUNDERWORLD-SLS-GPU_CPU
mkdir test
cd test
mkdir Output
cp -R ../data/alexander/leftCam ./
cp -R ../data/alexander/rightCam ./
cmake ..
make
./bin/SLS --leftcam=./leftCam/dataset1 --rightcam=./rightCam/dataset1 --leftconfig=./leftCam/calib/output/calib.xml --rightconfig=./rightCam/calib/output/calib.xml --output=./Output/output.ply --format=jpg --width=1024 --height=768

The binary's usage string lists the flags it accepts: -l/--leftcam and -r/--rightcam for the two image folders, -L/--leftconfig and -R/--rightconfig for the calibration XML files, -o/--output for the output path, -f/--format for the image suffix such as jpg, -w/--width and -h/--height for projector dimensions, and -?/--help. Note that --output is the name and location of the output file itself, either a ply or an obj, not a directory, despite the name. The example writes ./Output/output.ply.

Progress is logged rather than printed to the terminal. Most outputs go to a file named SLS.log, and the README suggests running tail -f sls.log in another terminal in the same directory to follow along. If you run the binary and see nothing on stdout, that is expected; check the log before assuming the run failed.

No camera acquisition, and a 300MB clone

The most consequential limitation is stated in the Known issues section: camera acquisition is not implemented, because there is no good API for cameras. Interfaces are provided, and the README invites contributors to implement a camera class and open a pull request. In practice this means the project cannot capture anything on its own. You supply two folders of already-captured, synchronised images and the calibration XML files, and the scanner does the rest. If your workflow depends on triggering a projector and cameras in sequence, that logic lives outside this repository.

The second limitation is repository size. The README notes that the example data files are included, making the repository 300MB and the clone slow. That is a real cost for anyone who only wants the library, and it is not something a shallow clone solves cleanly when the demo data sits in the history.

A third constraint is the CUDA dependency itself. The GPU path requires CUDA 6.0 or newer and an NVIDIA GPU. On a machine without one, the build produces only the CPU constructor, which the README says is slower. There is no OpenCL or other accelerator path documented. Finally, the release history is thin: v4.0, described as the CPU and GPU implementation of the reconstructor, is dated 2016-06-01. The dev branch has seen pushes since then, the most recent on 2026-06-26, but anyone expecting tagged releases with changelogs will not find them.

How it compares to OpenCV's own structured light module

The obvious alternative is the structured light module inside OpenCV, which also handles Gray code and phase-shift decoding and is already present in the OpenCV2 dependency this project requires. The difference in approach is where the work happens. OpenCV's module is a set of algorithms you call from your own program, with your own capture, calibration and storage code around it. 3DUNDERWORLD-SLS-GPU_CPU is an application-shaped pipeline: it expects folders of images and calibration XML files, and it writes a ply or obj file, with the CPU and CUDA reconstructors behind a shared Bucket interface.

That makes the choice mostly about whether you want a program or a library. If you need to integrate decoding into an existing C++ application and you are already linking OpenCV, calling the OpenCV module avoids a second build system and a 300MB clone. If you want a command line that takes two image directories and produces a point cloud, and you want the option of a GPU reconstructor, this project gives you that with one cmake invocation. The trade-off is that you inherit its calibration format expectations and its missing capture layer either way.

A second alternative is writing the reconstruction yourself on top of OpenCV's calibration and triangulation primitives. That is more work, but it is the path the README implicitly assumes for anyone whose camera setup does not fit the two-folder input model.

Licence, citation and the cost of upgrading

The repository is licensed LGPL-3.0. For a library you link into another application, that licence carries obligations around relinking and source availability that differ from permissive licences; if you plan to ship a closed product that links these libraries, have your own counsel read the LICENSE file rather than relying on a summary. The README adds a separate requirement that is not a licence term but is enforced socially: to use the software you must cite the two papers listed, one by Gu, Herakleous and Poullis (2016) and one by Herakleous and Poullis (2014, arXiv 1406.6595). For academic users that is a normal condition; for commercial users it is a reminder that this is research output.

Upgrade cost is low in one sense and high in another. There is a single tagged release, v4.0 from 2016-06-01, so there is no release train to track and no changelog to read between versions. Development happens on the dev branch, and the last push there was on 2026-06-26. Anyone building from dev is effectively tracking a moving branch, and the CMake flags (ENABLE_CUDA, GTEST, COVERAGE, BUILD_DOC) are the stable surface you can rely on. Because the demo data is committed to the repository, a fresh clone after a long gap will pull 300MB again rather than a small diff.

Editorial conclusion

Adopt 3DUNDERWORLD-SLS-GPU_CPU if you already own a calibrated stereo rig, can produce OpenCV XML calibration files, and are willing to write the camera capture layer yourself; the reconstructor and the point cloud output are the parts it actually delivers. Do not adopt it if you expect a working acquisition pipeline, a maintained release cadence, or CUDA support on a machine without an NVIDIA GPU, since the build silently falls back to CPU. Before committing, clone with --recursive, confirm that cmake reports ENABLE_CUDA=on for your toolchain, and run the included alexander dataset through ./bin/SLS to check that the ply file matches the geometry you expect.

Frequently asked questions

What is 3DUNDERWORLD-SLS-GPU_CPU?

It is a C++ structured light scanner that reconstructs a point cloud from series of images lit by patterned light, released under LGPL-3.0. The reconstruction step is implemented twice, for the CPU and for the GPU via CUDA.

How do I install 3DUNDERWORLD-SLS-GPU_CPU?

Clone the repository recursively, create a build directory, then run cmake and make. It depends on OpenCV2, CUDA 6.0 or newer, and glm, and the README says the example data makes the clone about 300MB.

Does 3DUNDERWORLD-SLS-GPU_CPU capture images from my camera?

No. The README's Known issues section states that camera acquisition is not implemented because there is no good API for cameras, though interfaces are provided for you to implement a camera class.

Official sources

  1. License: LGPL-3.0
  2. Project website
  3. README
  4. Releases
  5. theICTlab/3DUNDERWORLD-SLS-GPU_CPU on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/theictlab-3dunderworld-sls-gpu-cpu.svg)](https://hysenlabs.com/projects/theictlab-3dunderworld-sls-gpu-cpu)