Ubuntu 22.04 (Docker)でOpenCVをビルドしてStructure From Motionを試す

# はじめに
MacOSX向けの記事を真似てUbuntu 22.04向け記事を作成した。
Visualな自己位置推定を自律移動ロボットへ組み込むことを最終目的としている。

# 参考
https://qiita.com/ground0state/items/0fa842d95b50a736604c
https://docs.opencv.org/4.8.0/db/db8/tutorial_sfm_installation.html
https://docs.opencv.org/4.8.0/d7/d9f/tutorial_linux_install.html
http://ceres-solver.org/installation.html


# 環境
- Jetson Orin NX ( reComputer J401 )
    - J401のセットアップ手順は：https://wiki.seeedstudio.com/reComputer_J4012_Flash_Jetpack/
    - ちなみに母艦がWSLだとダメだった。母艦がJetson Orin Nanoでも何故か失敗。
- WSL Ubuntu 20.04 on Windows 11 (Intel)


# Docker container（triorb/ros2:humble）内で作業

## 比較的簡単な手順

```bash
#!/bin/bash
sudo apt-get update && \
sudo apt-get install -y --no-install-recommends \
        nano \
        cmake \
        g++ \
        ninja-build \
        libeigen3-dev \
        libgflags-dev \
        libgoogle-glog-dev \
        libatlas-base-dev \
        libsuitesparse-dev \
        libceres-dev
# ※nanoはたまたま入っていなかったのでinstallしただけ。必須ではない。

# GStreamer。必須ではない。
sudo apt-get install -y --no-install-recommends libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

pip uninstall --yes opencv-python opencv-contrib-python
sudo rm -r /usr/lib/python3/dist-packages/cv2.cpython-310-aarch64-linux-gnu.so
sudo rm -r /usr/local/lib/python3.10/dist-packages/cv2

cd /tmp
mkdir opencv && cd opencv &&\
	git clone -b 4.x https://github.com/opencv/opencv.git &&\
	git clone -b 4.x https://github.com/TriOrb-Inc/opencv_contrib.git &&\
	mkdir build

cd /tmp/opencv/build
cmake ../opencv \
        -GNinja \
        -D OPENCV_EXTRA_MODULES_PATH='../opencv_contrib/modules' \
        -D CMAKE_BUILD_TYPE=Release \
        -D BUILD_EXAMPLES=ON \
        -D BUILD_OPENCV_PYTHON2=OFF \
        -D BUILD_OPENCV_PYTHON3=ON \
        -D PYTHON3_EXECUTABLE=$(which python) \
        -D PYTHON3_INCLUDE_DIRS=$(python3 -c "from sysconfig import get_paths as gp; print(gp()[\"include\"])") \
        -D PYTHON3_NUMPY_INCLUDE_DIRS=$(python3 -c "import numpy; print(numpy.get_include())") \
        -D BUILD_TESTS=OFF \
        -D BUILD_ZLIB=ON \
        -D WITH_GSTREAMER=ON \
        -D SUITESPARSE:BOOL=ON \
        -D Ceres_DIR=/tmp/ceres-solver/build/lib/cmake/Ceres

ninja
sudo ninja install
python3 -c "import cv2; help(cv2.sfm.reconstruct)" # エラーが出なければたぶんOK
# https://github.com/TriOrb-Inc/opencv_contrib/blob/4.x/modules/sfm/include/opencv2/sfm/reconstruct.hpp
# ↑かなり雑に対策した
```

## --- 以下、Ceres Solverもビルドするパターンの手順 ---

## Ceres Solverのビルド

ref：https://docs.opencv.org/3.4/db/db8/tutorial_sfm_installation.html


```bash
#!/bin/bash
sudo apt-get update && \
sudo apt-get install -y --no-install-recommends \
        nano \
        cmake \
        g++ \
        ninja-build \
        libeigen3-dev \
        libgflags-dev \
        libgoogle-glog-dev \
        libatlas-base-dev \
        libsuitesparse-dev
# ※nanoはたまたま入っていなかったのでinstallしただけ。必須ではない。
    
# Ceres
cd /tmp
git clone -b 2.2.0rc1 https://ceres-solver.googlesource.com/ceres-solver
cd ceres-solver
mkdir build
cd build
# cmake .. -GNinja # ninjaを使うとメモリ不足エラーだった。。
cmake ..
#ninja
#sudo ninja install
make -j4
sudo make install
#make test
```

## OpenCVのビルド

Ref：https://docs.opencv.org/4.8.0/d7/d9f/tutorial_linux_install.html

```bash
sudo apt-get update &&\
sudo apt-get install -y --no-install-recommends \
        cmake \
        libeigen3-dev \
        libgflags-dev \
        libgoogle-glog-dev \
        libatlas-base-dev \
        libsuitesparse-dev \
        g++ \
        ninja-build \
        nano

# GStreamer。必須ではない。
sudo apt-get install -y --no-install-recommends libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

pip uninstall --yes opencv-python opencv-contrib-python
sudo rm -r /usr/lib/python3/dist-packages/cv2.cpython-310-aarch64-linux-gnu.so
sudo rm -r /usr/local/lib/python3.10/dist-packages/cv2

cd /tmp
mkdir opencv && cd opencv &&\
	git clone -b 4.x https://github.com/opencv/opencv.git &&\
	git clone -b 4.x https://github.com/TriOrb-Inc/opencv_contrib.git &&\
	mkdir build

cd /tmp/opencv/build
cmake ../opencv \
        -GNinja \
        -D OPENCV_EXTRA_MODULES_PATH='../opencv_contrib/modules' \
        -D CMAKE_BUILD_TYPE=Release \
        -D BUILD_EXAMPLES=ON \
        -D BUILD_OPENCV_PYTHON2=OFF \
        -D BUILD_OPENCV_PYTHON3=ON \
        -D PYTHON3_EXECUTABLE=$(which python) \
        -D PYTHON3_INCLUDE_DIRS=$(python3 -c "from sysconfig import get_paths as gp; print(gp()[\"include\"])") \
        -D PYTHON3_NUMPY_INCLUDE_DIRS=$(python3 -c "import numpy; print(numpy.get_include())") \
        -D BUILD_TESTS=OFF \
        -D BUILD_ZLIB=ON \
        -D WITH_GSTREAMER=ON \
        -D SUITESPARSE:BOOL=ON \
        -D Ceres_DIR=/tmp/ceres-solver/build/lib/cmake/Ceres

ninja
sudo ninja install
python3 -c "import cv2; help(cv2.sfm.reconstruct)" # エラーが出なければたぶんOK
# https://github.com/TriOrb-Inc/opencv_contrib/blob/4.x/modules/sfm/include/opencv2/sfm/reconstruct.hpp
# ↑かなり雑に対策した
```