GLIBCXX_3.4.x not found 解决方案

这个问题通常和 libstdc++ 版本有关。我的情况最开始出现在 Python 版 OpenCV 上,因此可以先尝试重新安装 Python 版 OpenCV:

pip install opencv-python

需要注意,pip install opencv-python 主要解决的是 Python OpenCV 包缺失、版本冲突或 wheel 依赖问题,不一定能解决系统 libstdc++ 缺少 GLIBCXX_3.4.x 符号的问题。

如果上面的方法不能解决,可以尝试更新系统的 libstdc++6:

sudo apt-get install libstdc++6

如果系统源里的版本仍然不够新,就需要进一步检查当前程序加载的是哪个 libstdc++.so.6,以及它是否来自系统路径、conda 环境或其他手动安装路径。

ARM 架构的 Jetson 设备找不到 v4l2_xxxx

平台:天准 Jetson AGX Orin。

编译时报错:

/usr/local/lib/libavcodec.so: undefined reference to `v4l2_open'

根据 NVIDIA 论坛中关于 libavcodec.so: undefined reference to v4l2_openJetson TX2 and FFmpeg - Can't initialize nvrm channel 的讨论,这类问题看起来和 FFmpeg 的安装或链接有关。但实际检查时,系统中 FFmpeg 是已经安装的。

通过 jtop 命令可以看到,当前系统中的 OpenCV 不支持 CUDA。这里需要注意,CUDA 支持和 FFmpeg / GStreamer 支持是 OpenCV 的不同编译选项,不能只根据 CUDA 支持情况直接判断 FFmpeg 是否启用。更准确的办法,是查看 OpenCV 编译日志,或者在代码中打印:

std::cout << cv::getBuildInformation() << std::endl;

很多 Jetson 设备出厂环境中的 OpenCV 不一定会开启 CUDA、FFmpeg 或 GStreamer 支持。如果 C++ 工程需要使用自己编译的 OpenCV,可以在 CMakeLists.txt 中指定 OpenCV 路径。知乎文章 Jetson Xavier NX OpenCV 安装 中提到的办法是卸载 OpenCV 并重装,这个方法没问题,但不一定必须这样做。

对于 C++ 工程,通常只需要修改 CMakeLists.txt 中的OpenCV_DIR,让它指向自己编译的 OpenCV 的 build 或安装后的 CMake 配置目录。至于 Python 版本的 OpenCV,可以后续在 conda 虚拟环境中单独配置。

于是我直接下载了 OpenCV 4.5.4 的 source 和 contrib 源码,并重新编译。这里选择 OpenCV 4.5.4 主要是为了兼容当前 JetPack / CUDA / 项目环境,而不是说 Jetson Orin 的 CUDA 11.x 一定不支持 OpenCV 4.7.0+。编译完成后,将 CMakeLists.txt 中的OpenCV_DIR 改为新编译 OpenCV 对应的路径。

修改后,不再报错。

GStreamer 警告:module avidemux0 reported: Internal data stream error

这个问题发生在使用 OpenCV 读取视频或者相机图像时,症状就是打不开图像。

一开始我以为是 OpenCV 缺少 GStreamer 相关支持,因此认为在 build 的时候设置下面这个选项应该能够解决:

-D WITH_GSTREAMER=ON

但是事实证明,添加 GStreamer 以后依旧不能打开图像。于是我开始怀疑问题出在 FFmpeg 支持上,需要确认 FFmpeg 是否被 OpenCV 正确识别。这个可以从 OpenCV 编译结果中看到。起初我的 OpenCV 编译结果是这个样子的:

--   Video I/O:
--     DC1394:                      NO
--     FFMPEG:                      NO
--       avcodec:                   YES (58.18.100)
--       avformat:                  YES (58.12.100)
--       avutil:                    YES (56.14.100)
--       swscale:                   YES (5.1.100)
--       avresample:                NO
--     v4l/v4l2:                    YES (linux/videodev2.h)

可以看到,FFMPEG 的选项为NO。导致这种情况的原因比较多,可能是 pkg-config 没有找到 FFmpeg,也可能是版本不匹配、头文件路径不完整、库路径不完整,或者 CMake 的链接测试没有通过。

虽然在 terminal 中输入 ffmpeg 能够正确显示版本,但这只能说明命令行工具可用,不代表 OpenCV 编译时一定能正确找到 FFmpeg 的开发文件和依赖链。因此,我决定卸载并重新安装 FFmpeg。

jocover/jetson-ffmpeg 仓库中,有手动编译 FFmpeg 的方法。

patch ffmpeg and build 这个步骤中,git apply ffmpeg_nvmpi.patch 命令只需要运行一次。多次运行会报错,报错可以忽略。

随后,./configure --enable-nvmpi 也可能报错:

nvmpi not found

如果当前项目不需要通过 nvmpi 使用显卡解码视频,可以先去掉后面的--enable-nvmpi

nvmpi 的作用是让 FFmpeg 能够通过 GPU 做视频解码,但我们的 GPU 更多用于推理,所以这里先不处理它。

针对编译时出现的报错,像是编译过程中某些静态库出现了问题,可以在编译 FFmpeg 的时候增加下面两个选项:

--disable-static
--enable-shared

注意,这里的参数前缀必须是真正的两个英文短横线 --,不要写成排版后的破折号。

另外,在原本 GitHub 仓库中的 README.MD 指南基础上,编译完 FFmpeg 后,还要执行安装:

sudo make install

参考文章

[1] GLIBCXX_3.4.20 not found, how to fix this error?

[2] Libavcodec.so: undefined reference to v4l2_open

[3] Jetson TX2 and FFmpeg - Can't initialize nvrm channel

[4] Jetson Xavier NX OpenCV 安装

[5] jocover/jetson-ffmpeg