Fix: Restore MATLAB Module Compilation for OpenCV 4.x#3898
Fix: Restore MATLAB Module Compilation for OpenCV 4.x#3898asmorkalov merged 2 commits intoopencv:4.xfrom
Conversation
Fixes related to optflow and xphoto, whose namespace have changed since 4.0.0-rc, and therefore deprecated the 'matlab' module
|
@CodeHotel Thanks a lot for the contribution. Could you add your build steps to the PR description. I want to try the patch. |
|
@asmorkalov Thanks for the review. I’ll post the build steps as a comment to keep them separate, as there may be future adjustments. |
|
Additional clarification: This PR is to ensure that the MATLAB module compiles successfully. I forgot to mention I have not yet run tests specifically designed for the matlab module. I have added such clarification to the main PR description |
Added fix in order to address previously unresolved issue when building in environments with python 3.10+. Modified so that this fix does not effect 3.9 or less.
|
@asmorkalov Hardware DetailsThe following hardware was used for testing the OpenCV MATLAB module compilation:
These specifications were used for both Ubuntu 22.04 and RHEL 9.1 testing. Ubuntu 22.04I have fully reinstalled ubuntu 22.04 and tested build 2 times using the below scripts. Package setupI tried to seamlessly include as much modules, features, libraries as possible with testing in mind. [script] Click to expand#!/bin/bash
# This script installs all dependencies and clones repositories necessary for testing
# Run this script in minimal ubuntu installation (was made for and tested in actual installation, not docker)
# It also acts as a dependency package list (full package list of the environment that I used)
# Almost all modules and features, excluding js, julia, ovis(ogre3d), vtk, qt will build
# IMPORTANT : Before running the script, please set below
USE_CUDA=1 # Change to 0 to skip CUDA installation. Modification of below code according to your architecture version may be required
USE_VTK=0 # libtbb2 is known to conflict with libtbb in ubuntu 22.04, therefore non compatible with vtk
# Paths to install NVidia Video Codec SDK
NV_CUVID_ZIP_NAME="Video_Codec_SDK_12.1.14" # Exclude '.zip' + This MUST be manually downloaded to the script's directory
NV_CUVID_INC_PATH=/usr/local/cuda-12.4/include
NV_CUVID_LIB_PATH=/usr/local/cuda-12.4/lib64
set -xe
trap 'echo "Error on line $LINENO"; exit 0' ERR
SHDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# This keeps sudo active for the rest of installation. Remove if needed when root (e.g. Docker)
cat $SHDIR/.sudo_passwd | sudo -S -v
while true; do cat $SHDIR/.sudo_passwd | sudo -S -v; sleep 30; done &
sudo apt update
if [ "$USE_CUDA" -eq 1 ]; then
# If needed, modify this according to your own hardware
echo "Installing CUDA keyring..."
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt update
CUDA_PACKAGES="cuda-drivers cuda-toolkit-12-4 libcudnn8 libcudnn8-dev libcudnn8-samples"
else
CUDA_PACKAGES=""
fi
if [ "$USE_VTK" -eq 1 ]; then
sudo apt remove -y libtbb2
TBB_PACKAGES="libtbb-dev libvtk9-dev"
else
sudo apt remove -y libtbb-dev
TBB_PACKAGES="libtbb2 libtbb2-dev"
fi
# I tried to minimze this list using dependency/suggested/recommended tree
sudo apt full-upgrade -y apt-rdepends btop cmake \
xfce4 $CUDA_PACKAGES \
flake8 git pylint \
openjdk-11-jdk python3-numpy python3.10-dev \
unzip vim \
libavformat-dev libavif-dev libceres-dev libdc1394-dev \
libgstreamer-plugins-base1.0-dev libgtk-3-dev libgtkglext1-dev \
libhdf5-dev liblapacke-dev libopenblas-dev libswscale-dev \
$TBB_PACKAGES libtesseract-dev libva-dev
# Install video codec sdk
if [ "$USE_CUDA" -eq 1 ]; then
unzip $NV_CUVID_ZIP_NAME.zip
sudo cp $NV_CUVID_ZIP_NAME/Interface/nvcuvid.h $NV_CUVID_INC_PATH
sudo cp $NV_CUVID_ZIP_NAME/Interface/nvEncodeAPI.h $NV_CUVID_INC_PATH
sudo cp $NV_CUVID_ZIP_NAME/Interface/cuviddec.h $NV_CUVID_INC_PATH
sudo cp $NV_CUVID_ZIP_NAME/Lib/linux/stubs/x86_64/libnvcuvid.so $NV_CUVID_LIB_PATH
sudo cp $NV_CUVID_ZIP_NAME/Lib/linux/stubs/x86_64/libnvidia-encode.so $NV_CUVID_LIB_PATH
sudo ldconfig
fi
if [ -d "$SHDIR/opencv" ]; then
echo "[ WARNING ] $SHDIR/opencv already exists. Skipping cloning."
else
echo "Cloning OpenCV repository into $SHDIR/opencv."
cd $SHDIR
git clone https://github.com/opencv/opencv.git
cd opencv
git fetch --tags
git checkout 4.11.0
cd ..
fi
if [ -d "$SHDIR/opencv_contrib" ]; then
echo "[ WARNING ] $SHDIR/opencv_contrib already exists. Skipping cloning."
else
echo "Cloning OpenCV contrib repository into $SHDIR/opencv_contrib."
cd "$SHDIR"
git clone https://github.com/CodeHotel/opencv_contrib.git
cd opencv_contrib
git checkout matlab-build-fix-4.11.0
cd $SHDIR
fi
# Restart to load correct nv firmware
if [ "$USE_CUDA" -eq 1 ]; then
sudo reboot now
fiSetup MATLABMatlab has a GUI installer, which is the reason why I included xfce in above script. sudo ./installIn terminal within the xfce wm session. Configure CMake and buildResets configurations, configures, and builds. [script] Click to expand#!/bin/bash
set -x
# This Script sets the build configs for opencv compilation.
# Please set correct variables below :
BUILD_CUDA=1
CUDA_ARCH_NUMBER=8.9
export CXXFLAGS="-O0 -fno-lto -w"
export CFLAGS="-O0 -fno-lto -w"
SHDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTDIR="$SHDIR/pr-build-out" # Build directory
# Resets build output directory
[ -d "$OUTDIR" ] && rm -rf $OUTDIR
mkdir $OUTDIR
cd $OUTDIR
# Set CUDA variables
if [ "$BUILD_CUDA" -eq 1 ]; then
CUDA_FLAGS="
-D WITH_CUDA=ON \
-D CUDA_ARCH_BIN=$CUDA_ARCH_NUMBER \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUFFT=ON"
else
CUDA_FLAGS=""
fi
# Quick fix for ubuntu 22.04 openblas and openblas-lapack header detection
OPENBLAS_INCLUDE=$(find /usr -type f -name "cblas.h" 2>/dev/null | grep "pthread" | head -n 1 | xargs dirname)
OPENBLAS_LIB=$(find /usr -type f -name "libopenblas*.so" 2>/dev/null | grep "pthread" | head -n 1)
BLAS_FLAGS=""
if [ -n "$OPENBLAS_INCLUDE" ]; then
BLAS_FLAGS+=" -DOpenBLAS_INCLUDE_DIR=$OPENBLAS_INCLUDE"
fi
if [ -n "$OPENBLAS_LIB" ]; then
BLAS_FLAGS+=" -DOpenBLAS_LIB=$OPENBLAS_LIB"
fi
LAPACKE_HEADERS=("lapacke.h" "lapacke_config.h" "lapacke_mangling.h" "lapacke_utils.h")
LAPACKE_DIR="/usr/include"
TARGET_DIR="$OPENBLAS_INCLUDE"
if [ -d "$TARGET_DIR" ]; then
for header in "${LAPACKE_HEADERS[@]}"; do
SOURCE_PATH="$LAPACKE_DIR/$header"
TARGET_PATH="$TARGET_DIR/$header"
if [ -f "$SOURCE_PATH" ]; then
if [ ! -L "$TARGET_PATH" ]; then
echo "Creating symlink for $header in $TARGET_DIR"
sudo ln -s "$SOURCE_PATH" "$TARGET_PATH"
fi
fi
done
else
echo "Warning: OpenBLAS include directory not found. Skipping LAPACKE symlink creation."
fi
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-DBUILD_opencv_world=OFF \
-D BUILD_TESTS=ON \
-D BUILD_PERF_TESTS=ON \
-D BUILD_DOCS=OFF \
-D BUILD_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=ON \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_JAVA=ON \
-D WITH_TBB=ON \
-D WITH_IPP=ON \
$BLAS_FLAGS \
$CUDA_FLAGS \
-D ENABLE_FAST_MATH=ON \
-D WITH_OPENGL=ON \
-D WITH_V4L=ON \
-D WITH_FFMPEG=ON \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
-D WITH_QT=ON \
-D WITH_GTK=ON \
-D WITH_IMGCODEC_GIF=ON \
-D BUILD_WITH_DEBUG_INFO=OFF \
-D BUILD_opencv_python3=ON \
-D WITH_MATLAB=ON \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_ENABLE_NONFREE=ON \
-D OPENCV_EXTRA_MODULES_PATH=$SHDIR/opencv_contrib/modules \
$SHDIR/opencv \
2>&1 | tee config.log
echo "Configuration outputs logged to $OUTDIR/config.log"
read -p "Proceed to build? (y/n): " answer
if [[ "${answer,,}" == "y" ]]; then
make -j$(nproc) | tee build.log
else
cd $SHDIR
exit 0
fi
cd $SHDIR
exit 0I will also post the config.log as a reference: [log] Click to expandRHEL 9.1This script was for my own personal use, and therefore is not as organized and tailored as the ubuntu script, and is quite messy. Setup script 1[script] Click to expand#!/bin/bash
set -xe
trap 'echo "Error on line $LINENO"; exit 0' ERR
SHDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# This keeps sudo active for the rest of installation. Remove if needed when root (e.g. Docker)
cat $SHDIR/.sudo_passwd | sudo -S -v
while true; do cat $SHDIR/.sudo_passwd | sudo -S -v; sleep 30; done &
# Use sudo with stored password
sudo subscription-manager release --set=9.1
# Add repositories
sudo subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
sudo dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf -y install https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm
sudo dnf -y install https://mirrors.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-9.noarch.rpm
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo
# Install the latest available kernel
sudo dnf -y install kernel kernel-core kernel-devel kernel-headers
# Stop sudo keep-alive (cleanup)
exit 0Setup Script 2[script] Click to expand#!/bin/bash
set -xe
trap 'echo "Error on line $LINENO"; exit 0' ERR
SHDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# This keeps sudo active for the rest of installation. Remove if needed when root (e.g. Docker)
cat $SHDIR/.sudo_passwd | sudo -S -v
while true; do cat $SHDIR/.sudo_passwd | sudo -S -v; sleep 30; done &
# Prepare docker install
sudo systemctl stop podman
sudo dnf remove -y podman
sudo rm -rf /var/lib/docker /var/lib/containerd /var/lib/podman
sudo systemctl daemon-reload
# Add Docker dependencies and clean DNF cache
sudo dnf -y install dnf-plugins-core
sudo dnf -y clean all
# Install NVIDIA driver
sudo dnf -y module install nvidia-driver:latest-dkms
# Install all required packages
sudo dnf install -y cmake \
gtk2-devel \
gtk3-devel \
gtkglext-devel \
ccache \
ceres-solver-devel \
suitesparse-devel \
xine-lib xine-lib-devel \
metis metis-devel \
mesa-libGL-devel mesa-libEGL-devel \
libcudnn8* \
cuda-toolkit-12-4 \
docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
gstreamer1-devel gstreamer1-plugins-base-devel \
eigen3-devel \
lapack-devel \
java-11-openjdk-devel ant \
nasm \
giflib-devel \
libva-devel \
hdf5-devel \
python3-devel \
python3-numpy \
libavif \
libavif-devel \
libjpeg-turbo-devel \
openblas-devel \
lapack-devel \
alsa-lib-devel SDL2-devel \
ffmpeg-devel ffmpeg \
qt5 qt5-devel \
rpm-build rpmdevtools rpmlint \
doxygen \
python3-pip \
tesseract-devel \
gflags gflags-devel \
glog glog-devel \
tbb tbb-devel \
pybind11-devel python3-pybind11 \
python3-jinja2 \
libedit-devel ncurses-devel swig python3-devel lua-devel perl-core ninja-build texlive-epstopdf texlive-epstopdf \
htop btop nmon
# Setup TensorRT
tar -xzvf TensorRT-8.6.1.6.Linux.x86_64-gnu.cuda-12.0.tar.gz
sudo mv TensorRT-8.6.1.6 /usr/local/TensorRT
echo '/usr/local/TensorRT/lib' | sudo tee /etc/ld.so.conf.d/tensorrt.conf
sudo ldconfig
sudo python3 -m pip install /usr/local/TensorRT/python/tensorrt-*-cp39-none-linux_x86_64.whl
# Setup llvm and bazel
sudo ./install-llvm
sudo ./install-bazel
# Start and enable Docker
sudo systemctl start docker
sudo systemctl enable docker
# Confirm Docker installation
sudo docker run hello-world
sudo docker pull tensorflow/build:2.17-python3.9
echo "Docker and TensorFlow GPU image setup completed successfully."
docker --version
sudo docker images
# Set CUDA vars
sudo tee /etc/profile.d/cuda-env.sh > /dev/null <<EOL
# CUDA
export PATH=/usr/local/cuda-12.4/bin:\$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:\$LD_LIBRARY_PATH
# cuDNN
export LD_LIBRARY_PATH=/usr/lib64:\$LD_LIBRARY_PATH
# TensorRT
export LD_LIBRARY_PATH=/usr/local/TensorRT/lib:\$LD_LIBRARY_PATH
export PYTHONPATH=/usr/local/TensorRT/python:\$PYTHONPATH
# Common NVIDIA Paths
export CUDA_HOME=/usr/local/cuda-12.4
export CUDNN_HOME=/usr/lib64
export TENSORRT_HOME=/usr/local/TensorRT
EOL
sudo chmod +x /etc/profile.d/cuda-env.sh
source /etc/profile.d/cuda-env.sh
echo "/usr/local/cuda-12.4/lib64" | sudo tee /etc/ld.so.conf.d/cuda.conf
echo "/usr/lib64" | sudo tee /etc/ld.so.conf.d/cudnn.conf
echo "/usr/local/TensorRT/lib" | sudo tee /etc/ld.so.conf.d/tensorrt.conf
sudo ldconfig
# Cuda vars for matlab
echo "NVIDIA_CUDNN=/usr" | sudo tee -a /etc/environment
echo "NVIDIA_TENSORRT=/usr/local/TensorRT" | sudo tee -a /etc/environment
# Test CUDA installation
nvcc -V
# Stop sudo keep-alive (cleanup)
exit 0 # Exiting script ensures the `sudo -v` loop stopsPrepare opencv installation[script] Click to expand#!/bin/bash
set -xe
trap 'echo "Error on line $LINENO"; exit 0' ERR
SHDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# This keeps sudo active for the rest of installation. Remove if needed when root (e.g. Docker)
cat $SHDIR/.sudo_passwd | sudo -S -v
while true; do cat $SHDIR/.sudo_passwd | sudo -S -v; sleep 30; done &
# Remove existing mpg123 package
sudo dnf -y remove mpg123
# Extract the source tarball
tar -xvf mpg123-1.32.10.tar.bz2
cd mpg123-1.32.10/
# Configure with optimizations
CFLAGS="-march=native -O3" CXXFLAGS="-march=native -O3" ./configure --prefix=/usr --with-cpu=generic --enable-id3v2 --enable-feature-report --enable-newoldwritesample
# Compile and install
make
sudo make install
# Return to previous directory
cd ..
# Force qt5-qtwebkit deps in order to install vtk
sudo dnf -y remove qt5-qtwebkit
dnf download --nobest qt5-qtwebkit
sudo rpm -ivh --nodeps qt5-qtwebkit-*.rpm
sudo dnf -y install vtk vtk-devel
wget https://developer.nvidia.com/downloads/designworks/video-codec-sdk/secure/12.1/video_codec_sdk_12.1.14.zip
unzip Video_Codec_SDK_12.1.14.zip
VENC_PATH=/usr/local/cuda/include
sudo cp Video_Codec_SDK_12.1.14/Interface/nvcuvid.h /usr/local/cuda/include/
sudo cp Video_Codec_SDK_12.1.14/Interface/nvEncodeAPI.h /usr/local/cuda/include/
sudo cp Video_Codec_SDK_12.1.14/Interface/cuviddec.h /usr/local/cuda/include/
sudo cp Video_Codec_SDK_12.1.14/Lib/linux/stubs/x86_64/libnvcuvid.so /usr/local/cuda/lib64/
sudo cp Video_Codec_SDK_12.1.14/Lib/linux/stubs/x86_64/libnvidia-encode.so /usr/local/cuda/lib64/
sudo ldconfig
sudo pip3 install bs4 pylint flake8
# Define the directory
DIR="cv_cuda"
# Check if the directory exists
if [ -d "$DIR" ]; then
echo "$DIR already exists. Skipping cloning."
else
echo "Creating $DIR and cloning OpenCV repositories."
mkdir $DIR
cd $DIR
git clone https://github.com/opencv/opencv.git
git clone https://github.com/CodeHotel/opencv_contrib.git
# Checkout to rel4.11 in opencv
cd opencv
git fetch --tags
git checkout 4.11.0
cd ..
# Checkout to rel4.11 in opencv_contrib
cd opencv_contrib
git checkout matlab-build-fix-4.11.0
cd ../..
fi
exit 0Configure CMake#!/bin/bash
set -x
cd cv_cuda
[ -d "release_general" ] && rm -rf release_general
mkdir release_general
cd release_general
export CXXFLAGS="-O3 -march=native -mtune=native -fno-lto -w"
export CFLAGS="-O3 -march=native -mtune=native -fno-lto -w"
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-DBUILD_opencv_world=OFF \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \
-D BUILD_JAVA=ON \
-D WITH_LAPACK=ON \
-D WITH_TBB=ON \
-D WITH_IPP=ON \
-D WITH_CUDA=ON \
-D CUDA_ARCH_BIN="8.9" \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D CUDA_FAST_MATH=ON \
-D ENABLE_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUFFT=ON \
-D WITH_OPENGL=ON \
-D WITH_V4L=ON \
-D WITH_FFMPEG=ON \
-D WITH_XINE=ON \
-D BUILD_DOCS=ON \
-D BUILD_EXAMPLES=ON \
-D BUILD_TESTS=ON \
-D BUILD_PERF_TESTS=ON \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
-D INSTALL_C_EXAMPLES=ON \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D WITH_QT=ON \
-D WITH_GTK=ON \
-D OPENCV_ENABLE_NONFREE=ON \
-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \
-D WITH_IMGCODEC_GIF=ON \
-D BUILD_WITH_DEBUG_INFO=OFF \
-D BUILD_opencv_python3=ON \
-D WITH_MATLAB=ON \
../opencv
cd ../.. |
This PR resolves a VERY long-standing issue where the
MATLABmodule in opencv_contrib fails to compile due to namespace changes incv::optflowandcv::xphoto. The MATLAB module has been broken since OpenCV 4.0.0-rc due to these changes, and this fix restores compilation compatibility.Issue Details
Namespace Changes
opencvtoopencv_contrib/optflow, breaking references in the MATLAB module. This was done during4.0.0-betaand4.0.0-rc, but never reflected incv::matlabcv::xphotoalso underwent similar changes, but I am yet to find the exact version such change was made in.collections.Iterablewas changed intocollections.abc.Iterable, which causesparse_tree.pyto break. I added fixes for build to work for both versions.Reported Issues
Fix Implementation
makeandgccRequest to Maintainers
I acknowledge that the MATLAB module has not been actively maintained for nearly 7 years, which, I find, is quite unusual for an active project like opencv.
If the devs do not intend to support the MATLAB module anymore, I request the maintainers to officially mark it as deprecated, or disable its inclusion using CMake scripts rather than leaving it in a permanently broken state.
Even if the PR is to be rejected, I hope at least a deprecation notice of the module will be considered.