This Python library is part of the ROMI European project. It provides tools to reconstruct digital twins of plants from a set of RGB images acquired with the "Plant Imager". It also provides tools to quantify some traits of the plant's aerial architecture like angles between successive organs and inter-nodes length.
A more comprehensive documentation about the "Plant Imager" project can be found here.
WARNING: this is an ongoing development and changes will arise unannounced!
Table of Contents
You will need to install:
- the Docker Engine (except if you plan to install COLMAP from sources, good luck with that!)
- the appropriate NVIDIA driver
- and the NVIDIA Container Toolkit to benefit from GPU accelerated algorithms inside the docker container.
To install the Docker Engine, you can follow the official instructions or use the convenience script:
curl https://get.docker.com | sh \
&& sudo systemctl --now enable dockerYou also have to follow the Post-installation steps for Linux.
On Ubuntu, you can install the latest compatible NVIDIA drivers with:
sudo ubuntu-drivers autoinstallTo install the NVIDIA Container Toolkit, follow the official Installation Guide from NVIDIA.
To avoid making a big mess while installing source code, it may be easier to build a Docker image and use it to performs reconstruction and analysis tasks.
To build a Docker image you have to:
- clone the
plant-3d-visiongit repository - initialize & clone the submodules (
plantdb,romitask,romiseg,romicgal&dtw) - use the convenience build scripts
This can be done as follows:
# Clone the plant-3d-vision repository from GitHub
git clone https://github.com/romi/plant-3d-vision.git
# Change directory to the cloned repository
cd plant-3d-vision/
# Initialize and update git submodules (containing additional dependencies)
git submodule init
git submodule update
# Build a Docker image for COLMAP version 3.8 using a convenience script in the docker/colmap3.8 directory
./docker/colmap3.8/build.sh -t colmap3.8
# Build the main Docker image with all dependencies, specifying the previously built COLMAP image to use
./docker/build.sh --colmap 3.8This will create two Docker images:
roboticsmicrofarms/colmap:3.8-cuda_ccXX.roboticsmicrofarms/plant-3d-vision:colmap3.8-cuda_ccXX.
If you want to tag your image with a specific one, here named mytag, use the docker tag command:
docker tag roboticsmicrofarms/plant-3d-vision:colmap3.8-cuda_ccXX roboticsmicrofarms/plant-3d-vision:mytagTo show more options, use the help option -h with the convenience build scripts.
Important:
You must run the convenience build scripts from the root of the plant-3d-vision repository as it will copy the files to the filesystem of the container.
In the docker folder, you will find a convenience script named run.sh.
You may want to test the built image by running a container and performing some tests.
Every test assumes you are in the plant-3d-vision root directory of the repository.
Do NOT forget to specify your tag with the -t option if you changed it (i.e. not latest)
To test if you have access to your GPU(s) can easily be done as follows:
./docker/run.sh --test-gpuTo test if you can run the geometric pipeline:
./docker/run.sh --test-geom-pipelineTo test if you can run the machine learning pipeline:
./docker/run.sh --test-ml-pipelineAssuming you want to put your local plantdb database under /Data/ROMI/DB.
Let's start by setting an environment variable named $ROMI_DB to the end of our .bashrc file:
cat << EOF >> /home/$USER/.bashrc
# ROMI plant-3d-vision - Set the local plantdb database location:
export ROMI_DB='/data/ROMI/DB'
EOFThen create the directories and the required romidb marker file with:
source ~/.bashrc # to 'activate' the $ROMI_DB environment variable
mkdir -p $ROMI_DB
touch $ROMI_DB/romidbIn any case, please avoid doing horrendous things like chmod -R 777 $ROMI_DB!
- Create the
romigroupsudo addgroup romi --gid 2020
- Add the current user to the
romigroupsudo usermod -a -G romi $USER - Change the group of the local DB
sudo chown -R :romi $ROMI_DB - Check the rights with:
This should yield something like:
ls -al $ROMI_DBWheredrwxrwxr-x 2 myuser romi 4096 nov. 21 12:00 . drwxrwxrwx 31 myuser myuser 4096 nov. 21 12:00 .. -rw-rw-r-- 1 myuser romi 0 nov. 21 12:00 romidbmyuseris your username.
To avoid running the container app as root user, we created a non-root user named romi with an uid of 2020.
In turn, when you bind mount a local plantdb database, you will not be able to write if:
- the owner does not have an uid of
2020 - the group is not set to
romior the
In the ./docker/run.sh convenience script, we added a few lines to automatically get the group id of the bind mounted host directory acting as the database location.
To be a bit cleaner and go further in sharing the database with other users, we suggest to:
- create a group named
romi, - add all potential users of the docker image to this group
- change the group of the local
plantdbdatabase to theromigroup - start the docker container with the
--user romi:$romi_gidoption, where$romi_gidis the group id (gid) of theromigroup
This will also allow all users from the romi group to access the files within the database, effectively making this a shared database.
A directory that has ‘setgid’ on it will cause all files that are created in that directory to be owned by the group of the directory as opposed to the group of the owner. This proves useful when sharing a database between multiple users belonging to the same group.
chmod -R g+s /data/ROMI/Let's create a systemd service file that will run your Docker command at system startup.
sudo nano /etc/systemd/system/romi-plant-3d.serviceAdd the following content:
[Unit]
Description=ROMI Plant 3D Vision Service
After=docker.service network.target
Requires=docker.service
[Service]
Type=simple
ExecStartPre=-docker stop %n
ExecStartPre=-docker rm %n
ExecStart=docker run --name %n --gpus all -v /data/ROMI/test_v2/:/myapp/db -v /data/ROMI/configs/:/myapp/cfg --user romi:1003 -p 8080:8080 -d roboticsmicrofarms/plant-3d-vision:latest-cuda_cc50 "gunicorn --worker-class eventlet -w 1 --bind 0.0.0.0:8080 plant3dvision.webterm.wsgi:application"
ExecStop=docker stop %n
ExecStopPost=docker rm %n
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl restart romi-plant-3d.servicesudo systemctl status romi-plant-3d.service
docker ps | grep romi-plant-3dYou can have a look at the logs with:
sudo journalctl -u romi-plant-3d.servicesudo systemctl enable romi-plant-3d.serviceUnitSection: Defines dependencies - this service will start after Docker service is runningServiceSection:ExecStartPre: Removes any existing container with the same nameExecStart: Runs your Docker containerExecStop: Stop the Docker containerExecStopPost: Removes any existing container with the same nameRestart: Automatically restarts the service if it fails
InstallSection: Makes the service start at boot time
You can manage the service using these commands:
- Check status:
sudo systemctl status romi-plant-3d.service - View logs:
sudo journalctl -u romi-plant-3d.service - Stop service:
sudo systemctl stop romi-plant-3d.service - Restart service:
sudo systemctl restart romi-plant-3d.service
Let's first install some useful tools like git, curl, wget & nano:
sudo apt update
sudo apt install -y git curl wget nanoFor romicgal you will need several system dependencies:
sudo apt update
sudo apt install -y build-essential gcc libcgal-dev libeigen3-dev libgmp-dev libmpfr-devIn the following instructions, we use conda, have a look at the official installation instructions here or use this convenience script:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.shFollow the instructions and proceed to remove the convenience script:
rm Miniconda3-latest-Linux-x86_64.shCOLMAP is required to run the reconstruction tasks.
You have two options:
- use the
roboticsmicrofarms/colmap:3.8available from our docker hub [recommended] - follow the official install instructions to install COLMAP for linux here.
To use the CUDA implementation of the backprojection algorithm, you will need nvidia-cuda-toolkit:
On Debian and Ubuntu, you can install it with:
sudo apt update
sudo apt install -y nvidia-cuda-toolkitTo use the OpenCL implementation of the backprojection algorithm, you will need ocl-icd-libopencl1 & opencl-headers.
On Debian and Ubuntu, you can install these dependencies with:
sudo apt-get update && sudo apt-get install -y ocl-icd-libopencl1 opencl-headersThen we add the PYOPENCL_CTX environment variable to the end of our .bashrc file:
cat << EOF >> /home/$USER/.bashrc
# ROMI plant-3d-vision - Select the first available device for PyOpenCL:
export PYOPENCL_CTX='0'
EOF- Clone the
plant-3d-visionsources:git clone https://github.com/romi/plant-3d-vision.git cd plant-3d-vision git submodule init git submodule update - Create a conda environment named
plant3dvisionwith Python3.8 for example:conda create --name plant3dvision "python=3.9" - Install the submodules (
plantdb,romitask,romiseg,romicgal&dtw) andplant3dvisionin activated environment:conda activate plant3dvision python3 -m pip install -e ./plantdb/src/commons/. python3 -m pip install -e ./plantdb/src/client/. python3 -m pip install -e ./romitask/. python3 -m pip install -e ./skeleton_refinement/. python3 -m pip install -e ./romiseg/. conda install -c conda-forge libstdcxx-ng # required to use `open3d.visualization.draw` python3 -m pip install -e ./romicgal/. python3 -m pip install -r ./dtw/requirements.txt python3 -m pip install -e ./dtw/. python3 -m pip install -e .
- Test import of
plant3dvisionlibrary:conda activate plant3dvision python3 -c 'import plant3dvision' - Longer tests using shipped "test dataset":
bash check_pipe.sh rm testdata/models/models/Resnet_896_896_epoch50.pt
This package is built around luigi and adopt a similar pipeline oriented philosophy with Tasks and Parameters.
To reconstruct and analyse the RGB images acquired with the Plant Imager you will have to define a pipeline as a series of task and set their parameters. To make things simpler, we provide two TOML configuration files defining the two main type of pipeline we use:
- the geometric pipeline in
plant-3d-vision/config/geom_pipe_real.toml - the machine learning pipeline in
plant-3d-vision/config/ml_pipe_real.toml.toml
This configuration files should be used on "real plant" dataset, i.e. on RGB images acquired with the Plant Imager.
To start a task defined in this configuration files, use the romi_run_task CLI.
You will have to specify which task you want to perform, on which dataset and pass the path to the configuration file using the --config option.
You will find examples of this using either the Docker container or the sources installed in a conda environment.
For more details about the task and their parameters, have a look at the "Plant Imager" documentation here.
There is now two options to use the previously built Docker image:
- you have experience with the Docker CLI and are willing to use it
- you prefer to use a convenience script with fewer but safer options
You can use the Docker CLI to start a container using the previously built roboticsmicrofarms/plant-3d-vision image.
In the following example, we will use the real_plant dataset from the test database and the geometric pipeline configuration file shipped in this repository.
Assuming you are in the plant-3d-vision root directory of the repository:
CWD=$(pwd) # get the absolute path to the `plant-3d-vision` directory
docker run -it --rm --gpus all \
-v $CWD/tests/testdata/:/myapp/db \
-v $CWD/configs/:/myapp/configs \
roboticsmicrofarms/plant-3d-vision:latest \
bash -c "romi_run_task AnglesAndInternodes /myapp/db/real_plant/ --config /myapp/config/geom_pipe_real.toml"In details, the previous command:
- get the current working directory and assign it to
CWDvariable as docker needs absolute path when performing bind mount - starts a pseudo-TTY interactive shell with
-it - will automatically remove the container when it exits with
--rm - add all available GPUs to the container
- bind mount
$CWD/tests/testdata/from the host to/myapp/dbin the container (created if non-existent) with the-voption - bind mount
$CWD/config/from the host to/myapp/configin the container (created if non-existent) with the-voption - use the
roboticsmicrofarms/plant-3d-visionimage with the taglatestto create the container - call a
bashcommand withbash -c "..." - performs the
AnglesAndInternodestask (reconstruction and analysis) of thereal_planttest dataset using thegeom_pipe_real.tomlconfiguration
There is a convenience bash script, named run.sh in the docker/ directory, that start a docker container using the roboticsmicrofarms/plant-3d-vision image.
It aims at making thing a bit simpler than with the Docker CLI.
In the following example, we will use the real_plant dataset from the test database and the geometric pipeline configuration file shipped in this repository.
Assuming you are in the plant-3d-vision root directory of the repository:
CWD=$(pwd) # get the absolute path to the `plant-3d-vision` directory
./docker/run.sh \
-db $CWD/tests/testdata/ \
-v $CWD/configs/:/myapp/configs \
-c "romi_run_task AnglesAndInternodes /myapp/db/real_plant/ --config /myapp/config/geom_pipe_real.toml"In details, the previous command does (the same thing as the CLI example):
- get the current working directory and assign it to
CWDvariable as docker needs absolute path when performing bind mount - bind mount
$CWD/tests/testdata/from the host to/myapp/dbin the container (created if non-existent) with the-dboption - bind mount
$CWD/config/from the host to/myapp/configin the container (created if non-existent) with the-voption - call a
bashcommand with-c "..." - performs the
AnglesAndInternodestask (reconstruction and analysis) of thereal_planttest dataset using thegeom_pipe_real.tomlconfiguration
Note that:
- with the
-dboption you do not have to specify the destination in the container - you do not have to specify the
bashbefore the-coption
In the plant3dvision conda environment, things are a bit simpler to starts as there is no Docker options to specify.
To execute the same series of tasks on the real_plant dataset from the test database and the geometric pipeline configuration file shipped in this repository we only have to call the romi_run_task CLI.
Assuming you are in the plant-3d-vision root directory of the repository:
cp -R tests/testdata /tmp/. # copy the test DB to the temporary directory
conda activate plant3dvision # activate the conda environment
romi_run_task AnglesAndInternodes /tmp/testdata/real_plant/ --config configs/test_geom_pipe_real.tomlThis will perform the AnglesAndInternodes task (reconstruction and analysis) of the real_plant test dataset using the geom_pipe_real.toml configuration.
To monitor the CPU resource usage, you can use the htop tool.
To install it from Ubuntu PPA repositories:
sudo apt install htopTo install it from the snap store:
snap install htopTo monitor the GPU resource usage, you can use the following command:
watch -n1 nvidia-smiwhere the -n option is the time interval in seconds.
ImportError: libGL.so.1: cannot open shared object file: No such file or directorycan be fixed with:apt-get install libgl1-mesa-glx
ImportError: libSM.so.6: cannot open shared object file: No such file or directorycan be fixed with:apt-get install libsm6 libxext6 libxrender-dev
If you have an NVIDIA GPU, you may solve some issues with:
mkdir -p /etc/OpenCL/vendors
echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icdTo avoid troubles during pyopencl install, check /usr/lib/libOpenCL.so exists, if not add it with:
ln -s /usr/lib/x86_64-linux-gnu/libOpenCL.so.1 /usr/lib/libOpenCL.so