sdxxl编译与使用指南:以一个遥感大图像分割任务为例
这是中国地质大学武汉面向对象程序设计的一项期末作业。作为大一生我记录下我的经验供后人参考。作业要求选段……二、教师提供的程序与数据的说明1stxxl-1.4.1.tar.gz文件是基于外存的标准模板库源代码能处理大于内存的大数据……三、实习内容(1) 设计一个类似于STXXL中VECTOR 的动态数组的模板类HugeVector能处理大于内存的数据。算法能利用内存和硬盘的容量为动态数组分配空间。2设计一个类似于STXXL中MAP 的模板类能处理大于内存的数据。算法能利用内存和硬盘的容量为HugeMap分配空间。3应用自己设计的HugeVector类替换测试程序BigImageSeg.cpp的STXXL中VECTOR实现大遥感图像的分割。……零、 初始状态与目录准备在开始一切之前请在你的电脑上任意位置创建一个纯英文路径的文件夹作为项目根目录例如C:\RemoteSensingProject\。请将你拿到的初始材料放入该目录保持如下最简结构ProjectRoot/ ├── BigImageSeg.cpp ← 老师提供的原始算法测试代码 ├── stxxl-1.4.1.tar.gz ← STXXL 外存库源码压缩包 └── input.tif ← 测试用的遥感图像 (例如 WashintongDC_fus_NC_8.tif)警告整个ProjectRoot的完整路径中绝对不能包含任何中文字符或空格例如不要放在“桌面”或“新建文件夹”中。后续使用的 CMake 编译工具对中文路径极度敏感一旦包含中文必定引发乱码报错与编译失败。一、 核心依赖安装 (MinGW GDAL CMake)在 Windows 下开发 C 遥感程序最痛苦的莫过于配置 GDAL 图像库。我们采用工业界最稳妥的方案MSYS2。下载安装 MSYS2前往 msys2.org 下载并安装。打开MSYS2 MinGW x64终端注意不是 UCRT64 或 MSYS 终端输入以下命令一键安装编译器、CMake 以及 GDAL 库pacman-Smingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-make mingw-w64-x86_64-gdal配置系统环境变量将C:\msys64\mingw64\bin添加到 Windows 系统的Path环境变量中。(此步骤至关重要它确保了后续编译时能找到g且运行时能找到libgdal-39.dll等几十个底层动态库。)二、 解压与编译 STXXL 底层库老师提供的 STXXL 只是源代码它无法直接被调用。我们必须先把它编译成可以链接的静态库.a文件。1. 解压源码在你的项目根目录下打开命令行PowerShell 或 CMD或者打开命令行后使用cd进入你选定的根目录。解压文件tar-xzfstxxl-1.4.1.tar.gz此时根目录下会多出一个stxxl-1.4.1/文件夹。2. 生成构建脚本 (CMake)STXXL 1.4.1 是十几年前的代码它的CMakeLists.txt语法非常老旧。使用现代 CMake 编译时必须强制指定兼容策略否则会直接报错。依次执行以下命令cdstxxl-1.4.1mkdirbuildcdbuild# 执行 CMake强制兼容老版本语法并关闭动态库构建cmake..-GMinGW Makefiles-DCMAKE_CXX_COMPILERg-DCMAKE_C_COMPILERgcc-DBUILD_SHARED_LIBSOFF-DCMAKE_BUILD_TYPERelease-DCMAKE_POLICY_VERSION_MINIMUM3.53. 开始编译继续在build目录下执行mingw32-make-j8(-j8表示开启 8 个线程并发编译可根据你的 CPU 核心数调整一般与你电脑的 CPU 核心数相等最佳 )验证编译结果编译完成后你会在stxxl-1.4.1/build/lib/目录下得到关键的预制菜libstxxl.a。同时在stxxl-1.4.1/build/include/stxxl/bits/下生成了平台适配文件config.h。三、 修改原始算法代码的硬伤BigImageSeg.cpp中大概率将输入文件和输出文件写死在G盘的绝对路径我们必须将其泛化改为相对路径。用任何文本编辑器打开BigImageSeg.cpp修改图像读取路径按下ctrlF输入pathName进行全文搜索。找到类似pathName G:\\WxGis5000.tif;的地方将其改为根目录下的相对路径pathNameinput.tif;修改结果输出路径按下ctrlF输入pFile进行全文搜索。找到类似FILE *pFile fopen(G:\\1_seg.txt, wb);的地方改为FILE*pFilefopen(output_seg.txt,wb);为什么终端会疯狂输出几千万个数字你成功执行整个流程正常运行的时候控制台会被几十万个数字刷屏——这是完全正常的现象。这不是底层容器HugeVector 或 STXXL的锅而是BigImageSeg.cpp的算法逻辑导致的。在其Segmentation()函数内部每当完成一次局部区域合并代码中就有一句std::cout num_segments endl;。初始有 2000 万个独立像素区域最终合并到几万个。这就意味着这段代码会执行近 2000 万次cout如果你觉得太慢或刷屏可以将其注释掉或者改为if (num_segments % 10000 0) cout ...批量打印。四、 终极链接与编译现在退回到项目的根目录。此时你的目录结构应该是这样的ProjectRoot/ ├── BigImageSeg.cpp ├── input.tif └── stxxl-1.4.1/ ├── include/ ← STXXL 的通用头文件 └── build/ ├── include/ ← CMake 生成的 config.h └── lib/libstxxl.a ← 刚才编译出的静态库在根目录下打开命令行执行这串极其严谨的编译指令g-stdc17-O2 BigImageSeg.cpp-I./stxxl-1.4.1/include-I./stxxl-1.4.1/build/include-L./stxxl-1.4.1/build/lib-lstxxl-lgdal-static-libstdc-static-libgcc-lpthread-o BigImageSeg.exe编译参数解析知其然必知其所以然-I(Include): 告诉编译器去哪里找头文件。我们指向了 STXXL 源码的 include 和 build 下的 include为了找config.h。GDAL 的头文件由于安装在 MSYS2 默认路径g会自动找到。-L(Library Path): 告诉链接器去哪里找编译好的库。我们指向了./stxxl-1.4.1/build/lib。-lstxxl -lgdal -lpthread: 链接 STXXL 库、GDAL 图像库和 POSIX 线程库。致命细节在 MinGWGCC中库的链接顺序是严格的从左向右依赖。-lstxxl等库文件必须放在源文件BigImageSeg.cpp的后面如果放在前面链接器扫过库时发现还没人调用它们就会将其丢弃导致最终报出undefined reference错误。-static-libstdc -static-libgcc: 这是在 Windows 下避免灾难的关键。强制将 C 基础运行时静态打包进exe里。如果不加程序在运行时可能会因为 GDAL DLL 调用的 C 库与你系统环境变量里的 C 库版本冲突而发生诡异的静默崩溃。-o BigImageSeg.exe: 在当前根目录下生成可执行文件。五、 运行与验证只要上述编译命令没有报错你的根目录下就会出现BigImageSeg.exe。直接在命令行运行./BigImageSeg.exe预期行为程序通过 GDAL 瞬间打开并读取input.tif。STXXL 会在底层接管内存由于 STXXL 默认只使用约 64MB 的缓冲池如果你用的是 2.45GB 的大图你会明显听到机械硬盘的狂转或看到固态硬盘的 I/O 飙升程序会耗时较长。运行结束后根目录下会生成一个巨大的output_seg.txt二进制的分割映射表这标志着整条包含复杂算法和外存调度的流水线彻底贯通