Ubuntu虚拟机的安装过程可以查看另一篇文章:VMware安装Ubuntu虚拟机实现C++OpenCV代码在虚拟机下运行教程-CSDN博客
目前我们已经下载好了OpenCV,这里以OpenCV4.5.2为例。
在内存要求尽可能小的情况下,可以尝试只编译安装代码中使用到的OpenCV模块,以压缩OpenCV占用的内存容量,但是由于OpenCV库中很多函数是具备依赖关系的,可能出现编译后缺少某些模块的情况,这里给出一个编译安装部分模块的实现方法。
这是编译安装部分模块之后OpenCV占用情况,可以看到共占用内存317.9MB,相比整个编译安装小了一倍多。
具体方法如下:
1. 梳理出代码中使用到的OpenCV函数
在我的图像处理三维解算代码中使用到了如下函数:
const cv::Mat& frame1, const cv::Mat& frame2、cv::split(img, channels)、cv::subtract(img1, img2, diff)、cv::threshold(src, dst, threshold, 255, cv::THRESH_BINARY)、cv::morphologyEx(img, img, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)))、
cv::erode(img, img, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3)))、cv::dilate(img, img, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)))、cv::resize(img, img, cv::Size(), scale, scale)、cv::findContours(binImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE)、cv::Point2f bestCenter(0, 0)、cv::contourArea(contour)、cv::arcLength(contour, true)、cv::RotatedRect ellipse = cv::fitEllipse(contour)、cv::moments(contour)、cv::cvtColor(binImg, gray, cv::COLOR_BGR2GRAY)、cv::cornerSubPix(gray, refinedPts, cv::Size(5, 5), cv::Size(-1, -1), criteria)、cv::triangulatePoints(T1, T2, pts1, pts2, pts4d)、cv::Mat::eye(4, 4, CV_64F)、cv::Mat::copyTo、cv::Mat::at、cv::Mat、cv::Point2f、cv::Point3f
注意,需要将使用到的OpenCV数据类型一并摘出,这些数据结构涉及到OpenCV的核心模块core。一般情况下,核心模块是必不可少的,总是会或多或少使用到OpenCV中定义的数据结构。
2. 划分调用的OpenCV函数涉及的OpenCV模块
(1)核心模块 (core)
- 数据结构和基本类型:cv::Mat、cv::Point、cv::Point2f、cv::Point3f 等基础数据结构,这些都是由 core 模块 提供的。
- 基本数学运算与矩阵操作:点与矩阵的乘法、旋转矩阵的构建及复制等都归功于 core 模块。
(2)图像处理模块 (imgproc)
- 通道分离与阈值处理:cv::split、cv::threshold、cv::subtract 等函数对图像进行预处理,归属于 imgproc 模块。
- 形态学处理:代码中的 cv::morphologyEx、cv::erode、cv::dilate 用于图像的噪点去除、形态学开运算等操作,也属于 imgproc。
- 几何变换与轮廓处理:图像的缩放(cv::resize)、轮廓检测(cv::findContours)、轮廓的面积、周长计算(cv::contourArea、cv::arcLength)、拟合椭圆(cv::fitEllipse)、矩计算(cv::moments)、亚像素级的角点检测(cv::cornerSubPix)等均由 imgproc 模块提供。
- 颜色空间转换:在检测亚像素位置时,使用cv::cvtColor,这是 imgproc 模块的另一常用功能。
(3)相机标定与三角测量模块 (calib3d)
- 三角测量:函数 cv::triangulatePoints 归属于 calib3d 模块,用于将二维像素点转换成三维点云,这部分功能归入 OpenCV 的相机标定与三维重建领域。
需要注意的是,calib3d模块对 opencv_flann 是存在依赖关系的,因此在后续的操作中不能禁用 opencv_flann。
3. 编译安装
想要尽可能降低内存占用,可以禁用不使用的模块。
① 解压OpenCV4.5.2
在OpenCV所在路径下打开终端输入:
unzip opencv-4.5.2.zip
② 创建build文件夹
cd到刚才解压之后的OpenCV文件夹下:
cd opencv-4.5.2
然后创建build文件夹并cd到build
mkdir build && cd build
③ cmake
设置要编译的模块和禁用模块。
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D BUILD_SHARED_LIBS=ON \
-D BUILD_opencv_core=ON \
-D BUILD_opencv_imgproc=ON \
-D BUILD_opencv_features2d=ON \
-D BUILD_opencv_calib3d=ON \
-D BUILD_opencv_imgcodecs=ON \
-D WITH_JPEG=OFF \
-D WITH_PNG=OFF \
-D BUILD_opencv_highgui=OFF \
-D BUILD_opencv_videoio=OFF \
-D BUILD_opencv_photo=OFF \
-D BUILD_opencv_video=OFF \
-D BUILD_opencv_ml=OFF \
-D BUILD_opencv_python=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D WITH_TIFF=OFF \
-D WITH_WEBP=OFF \
-D WITH_OPENCL=OFF \
-D WITH_CUDA=OFF \
-D WITH_GTK=OFF \
..
左边部分:设置各种构建选项(比如启用/禁用模块、选择编译类型、关闭不需要的依赖库等)。
右边部分:指定源码目录的路径,这里使用的是 .. 表示上级目录(即源码目录)。
编译后的库文件的内存占用与实际运行时加载占用通常会比全部模块编译时少很多。通过只编译必需模块,能够有效降低内存峰值。
④ 编译安装
Make -j$(nproc)
sudo make install
这样就编译安装成功了。
4. 编译运行程序代码
在你的代码所在文件夹下打开终端,并依次键入如下命令,即可编译运行:
mkdir build && cd build
cmake ..
make
./imgProc
注: ./imgProc 是我的代码工程的名字,需要修改成你的工程名。
运行成功的界面如上图所示。
代码对应CMakeLists.txt格式如下:
cmake_minimum_required(VERSION 3.10)
project(imgProc)
# 强制使用 C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找 OpenCV 并指定版本和模块
find_package(OpenCV 4.5.2 REQUIRED)
# 包含头文件目录
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include # 使用绝对路径指定头文件目录
${OpenCV_INCLUDE_DIRS}
)
# 添加可执行文件
add_executable(imgProc src/Host.cpp src/imgProc.cpp)
# 链接 OpenCV 库
# target_link_libraries(imgProc PRIVATE ${OpenCV_LIBS})
target_link_libraries(imgProc PRIVATE ${OpenCV_LIBS} opencv_calib3d opencv_imgcodecs)
5. 遇到的问题
在编译运行代码的过程中可能会遇到报错,下面是我在编译运行中遇到的问题:
zhouzhou@ubuntu:~/imgProc/build$ cmake .. -- The C compiler identification is GNU 9.4.0 -- The CXX compiler identification is GNU 9.4.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done CMake Error at /usr/share/cmake-4.0/Modules/FindPackageHandleStandardArgs.cmake:227 (message): Could NOT find OpenCV (missing: calib3d imgcodecs) (found suitable version "4.5.2", minimum required is "4.5.2") Call Stack (most recent call first): /usr/share/cmake-4.0/Modules/FindPackageHandleStandardArgs.cmake:591 (_FPHSA_FAILURE_MESSAGE) /usr/local/lib/cmake/opencv4/OpenCVConfig.cmake:354 (find_package_handle_standard_args) CMakeLists.txt:9 (find_package) -- Configuring incomplete, errors occurred!
这个报错的原因是 CMake 和 OpenCV 升级了,但错误日志显示 CMake 仍在调用旧版本路径 /usr/share/cmake-4.0/Modules,表明 系统未正确切换到新安装的 CMake。同时,OpenCVConfig.cmake 可能未正确导出 calib3d 和 imgcodecs 模块的依赖。
# 卸载旧版 CMake
sudo apt remove cmake # 移除系统包管理器安装的旧版本
sudo rm -rf /usr/share/cmake* # 清理残留文件 :ml-citation{ref="4,6" data="citationList"}
# 下载 CMake 3.28
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh
# 安装 CMake 3.28
chmod +x cmake-3.28.3-linux-x86_64.sh # 赋予执行权限
sudo ./cmake-3.28.3-linux-x86_64.sh --prefix=/usr/local --exclude-subdir # 安装到系统路径 :ml-citation{ref="2,6" data="citationList"}
# 更新环境变量
echo 'export PATH=/usr/local/bin:$PATH' >> ~/.bashrc # 将 CMake 路径加入环境变量
source ~/.bashrc # 立即生效 :ml-citation{ref="4" data="citationList"}
# 验证版本
cmake --version # 应输出 3.28.3
如果 wget 下载失败(一般是网络问题),可改用 curl 或浏览器手动下载后上传到服务器:
curl -O https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh
检查 OpenCV 是否包含 calib3d 和 imgcodecs:
# 检查头文件
ls /usr/local/include/opencv4/opencv2/calib3d.hpp
ls /usr/local/include/opencv4/opencv2/imgcodecs.hpp
# 检查库文件
ls /usr/local/lib/libopencv_calib3d*
ls /usr/local/lib/libopencv_imgcodecs*
如果经过上述安装cmake命令之后还是报错,应该是因为g++ gcc的版本太高了导致的不适配,应该降低g++ gcc的版本,之前是因为代码使用的C++ 23标准,升级了g++ gcc版本为13.1.0,目前不能适用,需要手动降低其版本来解决。
由于我之前设置了g++ gcc 13.1.0版本的优先级是60,重新安装9.4.0版本默认使用的还是13.1.0版本,需要将9.4.0版本的优先级设置的更大,这里设置为80:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 80
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 80
# 配置 gcc
sudo update-alternatives --config gcc
# 配置 g++
sudo update-alternatives --config g++
安装成功之后输入:
gcc --version # 应输出 9.4.0
g++ --version # 应输出 9.4.0
这样再重新编译运行即可成功。