OpenCV 4.13.0 配置、构建与使用指南
本文给出从 Linux 源码构建到 C++/Python 使用、测试、调试和部署的完整流程。内容依据 OpenCV 4.13.0 的根 CMakeLists.txt、模块配置和公开头文件核验。所有命令使用 /path/to 占位,不依赖本文之外的说明。
1. 构建前的版本与目录约定
建议准备三个彼此分离的目录:
1 | /path/to/opencv-4.13.0/ # 只读源码 |
源码外构建便于:
- 同时维护 Debug、Release、静态和交叉构建;删除构建目录后干净重配;
- 避免生成文件污染源码;明确部署内容来自哪个安装前缀。
记录源码标签、提交、编译器和 CMake 版本。若使用opencv_contrib,主仓库与 contrib 应来自相同版本标签。不要把不同小版本的头文件、库和 Python 扩展混在一起。
2. Linux 构建环境
2.1 基础工具
最低实用工具集包括:
- 支持 C++11 及项目要求的 GCC 或 Clang;CMake;
- Ninja 或 Make;pkg-config;
- Python 3 和开发文件;Git、下载工具与证书包;
- 目标功能对应的开发包。
Debian/Ubuntu 类系统的常见准备命令:
1 | sudo apt-get update |
这只是常见组合,不是强制清单。服务器可省略 GTK。不用视频时可省略 FFmpeg。发行版包名和版本可能不同,应以 CMake Summary 的探测结果为准。
2.2 首次 Release 构建
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-opencv -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-opencv |
单配置生成器使用 CMAKE_BUILD_TYPE。Visual Studio、Xcode 等多配置生成器通常在构建和安装时用 --config Release。不要假设环境变量中的编译器会覆盖已有 CMake 缓存。切换编译器、架构或静态/动态策略时应使用新的构建目录。
2.3 配置结果验收
配置末尾的 Summary 至少检查:
- OpenCV version;C/C++ compiler;
- CPU/HW baseline 与 dispatched code;To be built / Disabled / Unavailable modules;
- GUI 与 Video I/O;Media I/O;
- Parallel framework;OpenCL、IPP、Eigen 等;
- Python 3 interpreter、libraries、numpy 和 install path;Install to。
WITH_X=ON表示请求能力。HAVE_X或 Summary 中的 YES 才表示探测成功。某个模块未进入 “To be built” 时,安装后不会凭空可用。
3. CMake 选项语义
3.1 模块选择
| 选项 | 语义 |
|---|---|
BUILD_LIST |
构建列出的模块及其必要依赖,接受逗号、空格、冒号等分隔 |
BUILD_opencv_<name> |
单独控制某模块 |
OPENCV_EXTRA_MODULES_PATH |
一个或多个额外模块目录,通常指向 contrib 的 modules |
BUILD_opencv_world |
构建聚合库 opencv_world |
BUILD_SHARED_LIBS |
ON 生成共享库,OFF 生成静态库 |
BUILD_TESTS |
构建正确性和回归测试 |
BUILD_PERF_TESTS |
构建性能测试 |
BUILD_EXAMPLES |
构建示例 |
BUILD_LIST=core,imgproc 会自动加入必要依赖。它不会加入“业务上可能需要”的可选模块。例如 imread 需要 imgcodecs,窗口需要 highgui,摄像头需要 videoio。 |
|
BUILD_opencv_world=ON 方便简单链接。它不减少内部模块依赖,也不保证第三方静态依赖自动适合所有消费方式。需要最小部署、插件隔离或清晰依赖时,按组件链接通常更稳妥。 |
3.2 第三方能力
| 选项 | 主要作用 |
|---|---|
WITH_IPP |
x86/x86_64 上的 Intel IPP 优化 |
WITH_OPENCL |
OpenCL 与 Transparent API |
WITH_TBB |
TBB 并行后端 |
WITH_OPENMP |
OpenMP 并行支持 |
WITH_FFMPEG |
FFmpeg 视频 I/O |
WITH_GSTREAMER |
GStreamer 视频 I/O |
WITH_GTK / WITH_QT / WITH_WAYLAND |
Linux GUI 后端 |
WITH_CUDA |
CUDA runtime 与相关能力 |
WITH_CUDNN |
DNN CUDA 路径使用 cuDNN |
WITH_OPENVINO |
OpenVINO DNN 后端 |
OPENCV_ENABLE_NONFREE |
启用受额外许可约束的算法,默认关闭 |
选项默认值受平台条件影响。OpenCV 4.13.0 根配置对 WITH_CUDA、WITH_OPENVX、WITH_FASTCV 等默认关闭。打开选项后仍需匹配开发头、库、工具链和版本。 |
3.3 CPU 与构建质量
| 选项 | 语义 |
|---|---|
CPU_BASELINE |
运行二进制所要求的最低 CPU 指令集 |
CPU_DISPATCH |
额外编译并在运行时选择的指令集 |
CV_DISABLE_OPTIMIZATION |
关闭多类优化,主要用于诊断 |
ENABLE_LTO |
请求链接时优化 |
ENABLE_FAST_MATH |
允许影响严格浮点语义的优化 |
CMAKE_BUILD_TYPE |
单配置生成器的 Release/Debug/RelWithDebInfo |
提高 baseline 会牺牲旧 CPU 兼容性。通用发布包更适合保守 baseline 加 runtime dispatch。ENABLE_FAST_MATH 可能改变 NaN、舍入和可重复性,不应只因“更快”而默认打开。 |
3.4 Python 相关
常用变量包括:
1 | BUILD_opencv_python3 |
优先指定目标虚拟环境中的 PYTHON3_EXECUTABLE。其余变量只有在自动探测错误时再显式设置。配置 Summary 必须显示预期解释器、NumPy 和安装路径。
3.5 缓存与重配置
查看缓存:
1 | cmake -L -N /path/to/build-opencv |
更改单个普通选项可重新运行 cmake -S ... -B ...。更改编译器、sysroot、生成器、目标架构或主要依赖版本时新建构建目录。不要手工编辑 CMakeCache.txt 作为常规配置方式。
4. 常见构建配方
4.1 最小图像处理
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-min -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-min -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D WITH_FFMPEG=OFF -D WITH_GSTREAMER=OFF -D WITH_GTK=OFF |
此配方适合无 GUI 的离线图像处理。PNG/JPEG 等能力仍取决于 Media I/O 探测。
4.2 完整桌面构建
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-full -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-full -D WITH_GTK=ON -D WITH_FFMPEG=ON -D WITH_GSTREAMER=ON -D WITH_TBB=ON -D WITH_OPENCL=ON -D BUILD_EXAMPLES=ON -D BUILD_TESTS=ON -D BUILD_PERF_TESTS=ON |
“完整”不是开启所有实验后端。只启用目标机器安装、测试和部署得了的能力。
4.3 contrib 构建
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-contrib -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-contrib -D OPENCV_EXTRA_MODULES_PATH=/path/to/opencv_contrib-4.13.0/modules |
变量应指向 modules 目录,不是 contrib 仓库根目录。若只需少数模块,可同时使用:
1 | -D BUILD_LIST=core,imgproc,imgcodecs,features2d,xfeatures2d |
启用 OPENCV_ENABLE_NONFREE=ON 前先审查算法和部署地区的许可要求。
4.4 静态构建
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-static -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/install-static -D BUILD_SHARED_LIBS=OFF -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF |
静态 OpenCV 不等于最终应用完全静态。编解码器、线程库、系统库和 C++ 运行库仍可能需要显式链接。优先使用安装导出的 CMake 配置传播依赖,不要手写一串 .a。
4.5 Debug 和 RelWithDebInfo
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-debug -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -D CMAKE_INSTALL_PREFIX=/path/to/install-debug -D BUILD_TESTS=ON |
Debug 最便于断言和逐步调试,但性能不能代表发布构建。RelWithDebInfo 常用于接近 Release 的采样和崩溃符号化。
4.6 Linux 交叉构建
OpenCV 源码提供多种工具链文件,例如:
1 | platforms/linux/aarch64-gnu.toolchain.cmake |
示例:
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-aarch64 -G Ninja -D CMAKE_TOOLCHAIN_FILE=/path/to/opencv-4.13.0/platforms/linux/aarch64-gnu.toolchain.cmake -D CMAKE_INSTALL_PREFIX=/usr -D CMAKE_STAGING_PREFIX=/path/to/stage-aarch64 -D ARM_LINUX_SYSROOT=/path/to/sysroot -D BUILD_LIST=core,imgproc,imgcodecs -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF |
CMAKE_INSTALL_PREFIX=/usr 表示目标机路径。CMAKE_STAGING_PREFIX 是主机侧暂存位置。还可按部署流程使用 DESTDIR,但不要同时混淆两套根目录语义。
交叉构建验收:
- 编译器目标三元组正确;sysroot 中头和库属于目标架构;
file或readelf显示正确 ELF 架构;CMake 没有误用主机/usr/lib;- Python 绑定没有把主机解释器库误当目标库;在真实设备或模拟环境运行最小测试。
5. 安装与卸载边界
安装后常见布局:
1 | /path/to/install-opencv/include/opencv4/ |
精确布局受平台和 GNUInstallDirs 影响。消费工程应通过 OpenCVConfig.cmake 查找,不应依赖固定相对层数。
安装到系统前缀:
1 | sudo cmake --install /path/to/build-opencv |
更推荐先安装到项目管理的独立前缀。源码构建通常没有可靠的通用 uninstall 目标。使用独立前缀可通过删除整个前缀干净移除。不要覆盖发行版管理器拥有的同名文件。
6. C++ 工程消费
6.1 推荐 CMake 写法
CMakeLists.txt:
1 | cmake_minimum_required(VERSION 3.16) |
配置消费工程:
1 | cmake -S /path/to/app -B /path/to/build-app -G Ninja -D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4 |
某些安装还提供导出的具体 target。可用名称应以该安装的 OpenCVConfig.cmake 为准。${OpenCV_LIBS} 是跨不同 OpenCV 包布局更常见的兼容写法。
6.2 pkg-config
根配置中的 OPENCV_GENERATE_PKGCONFIG 默认关闭且标为 deprecated。新工程优先使用 CMake package config。必须兼容旧构建系统时,可显式请求生成并验证:
1 | pkg-config --cflags --libs opencv4 |
静态链接时还要检查:
1 | pkg-config --static --libs opencv4 |
6.3 最小图像程序
1 |
|
检查 imread()、VideoCapture::isOpened() 和模型读取结果。不要让空矩阵继续进入算法后才处理异常。
7. Python 构建与使用
7.1 在虚拟环境中构建
1 | python3 -m venv /path/to/venv |
把 python3.x 替换为实际版本目录。安装后验证实际加载文件:
1 | /path/to/venv/bin/python - <<'PY' |
7.2 Python API 示例
1 | from pathlib import Path |
Python 的 NumPy 数组常与 cv::Mat 共享或包装内存。注意 dtype、shape、stride、连续性和生命周期。避免在热点循环中无意义调用 np.ascontiguousarray() 或复制。
7.3 常见 Python 混装
系统包、pip wheel 和源码构建的 cv2 可能同时存在。表现包括:
cv2.__version__不是 4.13.0;getBuildInformation()缺少刚启用的后端;- 导入时报未定义符号;NumPy ABI 不匹配;
- IDE 与终端使用不同解释器。
总是先打印:
1 | import cv2, sys |
8. 视频读取与写入
C++ 示例:
1 | cv::VideoCapture cap("/path/to/input.mp4", cv::CAP_ANY); |
后端、容器和 codec 是三层概念。文件扩展名不能保证编码器存在。用 cap.getBackendName() 或调试日志确认实际后端。相机可显式传 cv::CAP_V4L2、cv::CAP_GSTREAMER 等偏好,但必须由构建支持。
在 Python 中:
1 | cap = cv2.VideoCapture("/path/to/input.mp4", cv2.CAP_ANY) |
生产服务应限制网络流的连接、读取和重连策略。不要无限阻塞或无限缓存来自不可信源的视频。
9. DNN 推理
9.1 ONNX 基本流程
1 | cv::dnn::Net net = cv::dnn::readNetFromONNX("/path/to/model.onnx"); |
预处理参数必须来自模型契约:
- 输入尺寸;NCHW 或其他布局;
- BGR/RGB 顺序;scale;
- mean;crop 或 letterbox;
- 输入精度;输出节点和后处理。
“能运行”不代表预处理正确。应使用已知样本与参考框架对齐输出。
9.2 查询并选择后端
1 | for (const auto& p : cv::dnn::getAvailableBackends()) |
公开后端包括 OpenCV、OpenVINO、CUDA、Halide、VkCom、WebNN、TIM-VX 和 CANN 等。实际可用组合由构建与运行时依赖决定。先查询,再设置 backend/target。首次推理通常包含初始化或编译,性能测试要预热。
9.3 DNN 诊断
可先提高日志等级:
1 | OPENCV_LOG_LEVEL=DEBUG /path/to/dnn-app |
进一步排查可使用:
1 | OPENCV_DNN_CHECK_NAN_INF=1 OPENCV_DNN_CHECK_NAN_INF_RAISE_ERROR=1 /path/to/dnn-app |
这些检查会影响性能,仅用于诊断。对不支持的 ONNX 算子,先最小化模型并记录导出器版本、opset 和错误层。
10. samples、tests 与 perf
源码中的主要样例目录:
1 | samples/cpp/ |
启用示例:
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-samples -D CMAKE_BUILD_TYPE=Release -D BUILD_EXAMPLES=ON |
正确性与性能测试分别位于各模块的 test/ 和 perf/。常见目标名:
1 | opencv_test_core |
运行单个测试:
1 | /path/to/build-opencv/bin/opencv_test_core --gtest_filter='Core_Mat.*' |
通过 CTest:
1 | ctest --test-dir /path/to/build-opencv --output-on-failure |
性能测试:
1 | /path/to/build-opencv/bin/opencv_perf_imgproc --gtest_filter='*GaussianBlur*' |
先运行可执行文件的 --help 确认当前参数。测试数据可能要求额外数据仓库或环境变量。跨机器比较 perf 前固定构建类型、线程数、温度、频率和输入。
11. 调试与日志
11.1 运行时构建信息
1 | std::cout << cv::getVersionString() << '\n'; |
Python 对应:
1 | print(cv2.__version__); print(cv2.getBuildInformation()); print(cv2.getCPUFeaturesLine()); print(cv2.getNumThreads()) |
11.2 日志级别
环境变量方式:
1 | OPENCV_LOG_LEVEL=DEBUG /path/to/app |
C++ API:
1 |
|
详细日志可能包含设备、后端和文件信息。生产环境应控制等级并避免把敏感路径直接发送到外部日志。
11.3 GDB 与 sanitizer
1 | gdb --args /path/to/app /path/to/input.jpg |
应用和 OpenCV 都有符号时回溯最有价值。如需 sanitizer,建议建立独立构建并统一编译、链接选项。
1 | cmake -S /path/to/opencv-4.13.0 -B /path/to/build-asan -G Ninja -D CMAKE_BUILD_TYPE=Debug -D CMAKE_C_FLAGS='-fsanitize=address -fno-omit-frame-pointer' -D CMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer' -D CMAKE_EXE_LINKER_FLAGS='-fsanitize=address' -D CMAKE_SHARED_LINKER_FLAGS='-fsanitize=address' |
常规定位顺序:
- 确认实际加载的 OpenCV;
- 保存原始输入和最小复现;
- 打印尺寸、类型、步长和连续性;
- 单线程复现;
- 关闭特定加速后端做对照;
- 使用 Debug、断言和 sanitizer;
- 修复后增加回归测试。
12. 部署
12.1 共享库部署
查看 ELF 依赖:
1 | ldd /path/to/app |
部署时包含:
- 应用直接依赖的 OpenCV
.so;OpenCV 所需第三方运行库; - 视频、GUI 或 DNN 插件;模型、级联文件和配置;
- 与目标系统兼容的 C++ 运行库。
使用 RPATH/RUNPATH 或系统动态链接器配置管理查找路径。不要依赖开发机的LD_LIBRARY_PATH作为正式部署方案。
12.2 容器部署
多阶段构建可将编译环境与运行环境分开。运行镜像只复制安装前缀、应用和必要运行库。还要考虑:
- 摄像头设备映射;GPU 驱动与容器 runtime;
- GUI socket;codec 和字体;
- 非 root 用户权限;只读文件系统下的缓存目录。
12.3 静态部署
静态链接降低部分运行时查找问题,但会:
- 增大文件;增加第三方依赖传播复杂度;
- 影响插件能力;加重许可证合规工作;
- 使安全更新需要重新链接和发布。
无论共享或静态,都应生成软件物料清单并保留构建配置。
13. ABI 与版本共存
不要假设所有 OpenCV 4.x 二进制 ABI 永久兼容。风险来源包括:
- 编译器和 libstdc++ ABI;Debug 与 Release 混用;
_GLIBCXX_USE_CXX11_ABI;静态与共享库组合;- contrib 与主库版本不一致;第三方库 ABI;
- DNN 插件与核心库版本;Python 与 NumPy ABI。
最佳实践: - 应用与 OpenCV 使用兼容工具链;编译时和运行时加载同一安装前缀;
- 通过
OpenCV_DIR固定消费版本;不混合多个前缀的头和库; - 插件与主库一起构建、测试和部署;升级小版本也执行 ABI 与回归验证;
- 对公共接口避免暴露
cv::Mat跨不受控插件边界,除非双方 ABI 被锁定。
并行安装可使用不同前缀。运行时通过 RUNPATH 或隔离容器选择版本。不要用覆盖系统库的方式实现升级。
14. 迁移到 4.13.0
迁移检查清单:
- 移除旧 C API 和废弃常量;核对模块是否移动到 contrib;
- 检查返回值、默认参数和 Python tuple 形态;重新导出并验证 DNN 模型;
- 核对 ONNX opset 和后端覆盖;重新验证视频后端、codec 和设备索引;
- 检查序列化文件、标定参数和模型兼容性;更新 CMake 的组件列表;
- 重跑正确性、性能和资源泄漏测试;检查许可证与部署依赖变化。
迁移时先固定旧版输出样本。对浮点算法定义绝对或相对误差,而不是要求逐位一致。同时比较性能分布,避免因后端改变出现隐性回退。
15. 安全与资源管理
OpenCV 处理的是复杂二进制格式、视频流和模型。不可信输入应视为攻击面。
15.1 输入控制
- 在解码前限制文件大小;解码后限制宽、高、通道和总像素;
- 对视频限制帧率、分辨率、时长和重连次数;对模型限制来源、大小和允许格式;
- 拒绝路径穿越和意外覆盖输出;设置任务超时和内存上限;
- 将解析服务放入低权限进程或容器;跟踪 OpenCV 与 codec 库安全更新。
像素内存约为:
1 | rows * step |
不能只用压缩文件大小估算解码内存。超高压缩比图片和畸形尺寸可能导致资源耗尽。
15.2 C++ 生命周期
cv::Mat 使用引用计数并支持浅拷贝。返回引用、ROI 或包装外部缓冲区时,必须保证底层内存仍存活。跨线程共享只读矩阵通常可行,但并发写入需要应用自行同步。
资源对象使用 RAII:
1 | { |
不要把 Mat::data 保存到超过矩阵生命周期的异步任务。包装外部内存时,OpenCV 不一定拥有或释放该内存。
15.3 Python 生命周期
使用 try/finally 释放摄像头和 writer。长服务中不要无界保存帧列表。NumPy 视图与 cv2 返回数组共享数据时,保留拥有者引用。捕获 cv2.error 时记录操作和输入元数据,但避免记录敏感图像本身。
16. FAQ
16.1 找不到 OpenCVConfig.cmake
显式指定:
1 | -D OpenCV_DIR=/path/to/install-opencv/lib/cmake/opencv4 |
确认该文件确实由 cmake --install 生成。不要把 OpenCV_DIR 指向源码根目录。
16.2 头文件找到但链接失败
常见原因:
- 头来自一个版本,库来自另一个版本;忘记请求对应组件;
- 静态第三方依赖未传播;Debug/Release 或 C++ ABI 不一致;
- 链接顺序不适合手写静态库列表。
删除手写-lopencv_*,先用安装导出的 CMake 配置复现。
16.3 运行时找不到 .so
先查看:
1 | ldd /path/to/app |
为部署配置 RUNPATH,或将库安装到受管理的系统路径。不要复制单个 OpenCV 库后忽略其第三方依赖。
16.4 imread() 返回空
检查:
- 路径与当前工作目录;文件读取权限;
- 文件是否完整;对应 codec 是否在 Summary 中启用;
- 输入是否超出资源限制;
cv::haveImageReader()是否识别该文件。
内存输入使用imdecode(),并验证字节缓冲区完整。
16.5 VideoCapture 打不开
检查:
WITH_FFMPEG/WITH_GSTREAMER的最终探测;摄像头设备权限;- 容器设备映射;backend preference;
- URL、认证、网络与超时;codec 和像素格式。
用OPENCV_LOG_LEVEL=DEBUG查看后端尝试。
16.6 imshow() 在服务器失败
无桌面环境通常没有可用显示后端或 display server。改为 imwrite()、Web 输出或无头测试。不要为了 imshow() 给生产容器引入整套 GUI,除非确有需求。
16.7 Python 导入了错误版本
打印:
1 | import cv2, sys |
清理冲突的 pip、系统包或 PYTHONPATH。重新配置时确认 Summary 指向目标虚拟环境。
16.8 打开 CUDA 但算法仍在 CPU
WITH_CUDA=ON 不会让普通 cv::Mat 算法自动迁移到 GPU。CUDA 模块通常使用专用 cv::cuda API,并可能来自 contrib。DNN 还需要选择 CUDA backend/target,并满足对应构建依赖。
16.9 Release 仍然很慢
按顺序确认:
- 实际加载的是 Release 库;
- 输入没有重复复制和转换;
- CPU dispatch 与并行后端存在;
- 线程没有过度订阅;
- GPU/OpenCL 计时包含同步;
- DNN 已预热且未回退;
- 热点确实位于 OpenCV 调用内部。
16.10 CMake 选项显示 ON,但功能不可用
选项表达请求,不表达探测成功。检查 Summary、CMakeCache.txt、getBuildInformation() 和日志。依赖版本、头、库、目标架构或工具链任一不匹配都可能使能力不可用。
17. 发布前验收清单
- 使用干净构建目录完成配置;保存完整 CMake 命令和 Summary;
- 构建类型是预期的 Release 或 RelWithDebInfo;安装到独立前缀;
- 消费工程只使用该前缀;C++ 最小程序可编译和运行;
- Python 时确认
cv2.__file__;图片、视频和 DNN 各跑一个真实样本; - 执行目标模块 tests;在目标设备运行 perf 或业务基准;
- 检查共享库和插件依赖;核对模型、codec、contrib 和 nonfree 许可;
- 对不可信输入设置尺寸、时间和内存限制;记录 ABI、编译器和第三方版本;
- 保留回滚所需的旧安装前缀和构建清单。
完成这些步骤后,构建结果才不仅是“编译通过”,而是可定位、可复现、可部署和可维护的 OpenCV 4.13.0 工程。
正在加载留言…