ScanNet ScannerApp 实战指南:用 Structure Sensor 采集 RGB-D 数据、五种数据格式与上传机制详解
数据集计算机视觉3D视觉【免费下载链接】ScanNet项目地址https://gitcode.com/gh_mirrors/sc/ScanNet点击查看免费下载本文基于 ScanNet 仓库中的 ScannerApp/README.md 展开系统讲解 ScanNet iOS 扫描采集 App 的编译构建流程、五种扫描数据文件*.txt、*.depth、*.h264、*.cam、*.imu的格式细节并结合仓库源码深入剖析深度帧压缩编码、H.264 硬件编码、IMU 二进制布局以及“上传 校验”的数据回传链路帮助读者完整理解 ScanNet 数据集从 iPad 端采集到数据服务器落盘的整条采集链路。一、ScannerApp 的定位ScanNet 数据采集链路的起点ScanNet 是一套包含超过 1500 个场景、250 万帧视图的 RGB-D 视频数据集见仓库根 README.md。其原始数据并非凭空产生而是由配套 iPad 应用 ScanNet Scanner App 采集而来The scanner app acquires RGB-D scans using a structure.io sensor, stores color, depth and IMU data on local memory and then uploads to the data staging server for processing.也就是说ScannerApp 承担三件事采集通过 Structure.io 传感器获取深度帧、通过 iPad 摄像头获取彩色帧、通过 CoreMotion 获取 IMU 数据、本地存储把数据写入 iPad Documents 目录、回传PUT 上传至数据暂存服务器由 Server 目录下的上传服务接收并触发后续处理。仓库根 README 也明确了这一分工ScannerApp负责用 iPad Structure.io 传感器采集 RGB-D 序列Server负责接收这些序列。从源码结构看App 的核心状态机定义在 ViewController.h 的ScannerState枚举中依次为ScannerStateSceneLabelling填写场景标签→ScannerStateCubePlacement放置立方体初始化位姿→ScannerStateScanning正式扫描→ScannerStateViewing查看本地已有扫描。扫描开始前用户必须填写 userName、sceneLabel 并选择场景类型否则 ViewController.mm 中的scanButtonPressed:会弹出 “Incomplete metadata” 提示并阻止进入扫描状态——这保证了每个序列的元数据完整性。二、编译与构建2.1 环境前提README 给出的编译前提Prerequisites如下iPad Air 2其他 iPad 或 iPhone 也可以运行但官方未做测试源码 ViewController.mm 中通过sysctlbyname(hw.machine)识别iPad5,3Wi-Fi/iPad5,4LTE机型并对 iPad Air 2 默认开启 30 FPS 高分辨率深度流其他设备默认关闭以避免帧率过低Xcode 7.2可通过 App Store 或 Apple 开发者下载页获取更新版本可用但可能需要修改工程文件仓库内置的外部依赖Structure.io 传感器 SDK与GPUImage图像滤波库分别位于 ScannerApp/Frameworks/Structure.framework 和 ScannerApp/Frameworks/GPUImage。2.2 构建步骤README 给出的构建流程共 5 步用 Xcode 打开 Scanner.xcodeproj在 Scanner/Config.h 顶部设置数据上传服务器 URL连接 iOS 设备并授权开发机向其安装在顶部工具栏选择 “Scanner” 目标和所连设备点击 “play” 图标构建到设备断开开发机、把 Structure 传感器接到 iPad 上运行 Scanner App。2.3 上传服务器配置Config.hConfig.h 是整个 App 唯一的网络配置入口全部为宏定义// Upload server configuration #define SERVER http://dovahkiin.stanford.edu #define UPLOAD :8000/upload #define VERIFY :8000/verify // Upload stream checksum chunking size in bytes #define READ_CHUNK_SIZE 4096 #define DEBUG_MODESERVER/UPLOAD/VERIFY拼接出上传端点SERVERUPLOADPUT 接收文件与校验端点SERVERVERIFYGET 确认文件完整性READ_CHUNK_SIZE为 4096 字节是本地计算 MD5 校验和时的分块读取大小见 ViewController.mm 的calculateChecksum按块调用CC_MD5_UpdateDEBUG_MODE控制调试期 UI 行为例如仅在 DEBUG 模式下才在扫描列表行上显示 “Upload”/“Delete” 操作按钮。对应服务端实现在 Server/upload.py提供PUT/POST /upload与GET /verify?filenamenamechecksummd5两个路由文件写入 staging 目录扫描全部到齐scan_done_uploading后触发后续处理。upload.py头部注释还给出了模拟 iPad 上传的 curl 命令可用于自行联调curl -v -X PUT -H FILE_NAME: test.h264 --data-binary path_to_some_file \ -H Content-Type: application/ipad_scanner_data http://localhost:8000/upload三、一次扫描产生的文件组织当用户按下 Scan 按钮进入扫描状态后ViewControllerSensor.mm 的startScanningAndOpen会先确认已收到相机内参和deviceId否则拒绝启动并提示No intrinsics received然后以时间戳加设备 ID 作为文件前缀[dateFormatter setDateFormat:yyyy-MM-dd_hh-mm-ss]; std::string dateString [[dateFormatter stringFromDate:[NSDate date]] UTF8String]; ... [self openFile:(dateString __ _options.deviceId)];随后openFile:一次性打开五个输出文件全部位于 iPad 的 Documents 目录文件内容prefix.h264iPad 彩色相机 H.264 码流prefix.depthStructure 传感器压缩深度帧流prefix.txt元数据分辨率、内外参、场景标签等prefix.imuIMU 原始二进制数据prefix.camera每帧相机曝光参数此外第一帧还会额外导出一张prefix.jpg缩略图ViewControllerSensor.mm 中g_frameCount 1时写入供后续 “查看历史扫描” 列表使用。扫描结束时closeFile补齐元数据帧数并把彩色/深度时间戳数组追加写入.depth文件末尾再逐一把五个文件关闭。四、五种数据格式详解README 核心内容4.1 元数据文件*.txtREADME 给出的元数据文件完整样例colorWidth 1296 colorHeight 968 depthWidth 640 depthHeight 480 fx_color 1170.187988 fy_color 1170.187988 mx_color 647.750000 my_color 483.750000 fx_depth 571.623718 fy_depth 571.623718 mx_depth 319.500000 my_depth 239.500000 colorToDepthExtrinsics 0.999977 0.004401 0.005230 -0.037931 -0.004314 0.999852 -0.016630 -0.003321 -0.005303 0.016607 0.999848 -0.021860 -0.000000 0.000000 -0.000000 1.000000 deviceId AA408AE6-80BB-4E45-B6BA-5ECC8C17FB2F deviceName iPad One sceneLabel 0001 sceneType Bedroom / Hotel numDepthFrames 1912 numColorFrames 1912 numIMUmeasurements 4185各字段含义可从 ViewControllerSensor.mm 的writeIntrinsics逐一对应colorWidth/colorHeight、depthWidth/depthHeight彩色/深度帧分辨率。注意若启用半分辨率彩色useHalfResColor写入的彩色分辨率会减半样例中 1296×968 说明该场景采集时未减半iPad 后置相机原分辨率fx_color/fy_color/mx_color/my_color与fx_depth/...两组相机内参焦距与主点在扫描前的前几帧由 SDK 的glProjectionMatrix反解得到getIntrinsicsFromGlProjcolorToDepthExtrinsics4×4 彩色相机到深度相机坐标系的刚体变换行主序展开为 16 个值。从源码看若使用硬件配准深度useHardwareRegisteredDepth则写单位阵否则调用 SDK 的colorCameraPoseInSensorCoordinateFrame:获取真实外参deviceId/deviceNameiPad 设备 UUID 与名称用于服务端区分采集设备sceneLabel/sceneType用户填写的场景编号与类别类别候选列表硬编码在 ViewController.mm包括 Dining Room、Office、Classroom、Bedroom / Hotel、Living room / Lounge、Kitchen、Bookstore / Library、Bathroom、Conference Room、Misc. 共 9 类numDepthFrames/numColorFrames/numIMUmeasurements扫描结束时由closeFile统计写入的三流帧数是下游校验三流时间戳对齐的基础。源码中还额外写入了 README 样例未列出的userName、appVersionId形如Scanner.v1.build以及closeFile追加的scanSavedAtISO 风格时间戳字段实际文件以当前 App 代码输出为准。4.2 深度数据*.depthREADME 描述*.depth是 Structure.io 传感器的压缩深度帧流并指明参考 depth2pgm 代码解析。结合 depth2pgm.cpp 的实现其文件结构可以完整还原逐帧组织每帧前是一个 4 字节小端uint32_t的压缩数据长度byteSize紧随其后是byteSize字节的压缩负载压缩算法采用 Occipital 的 uplinksimple 图像编解码器uplinksimple_image-codecs.h基于 DCT 的位流压缩。采集端在 ViewControllerSensor.mm 中用uplinksimple::encode压缩压缩缓冲上限按每像素 2 字节分配(2*width1)*height即压缩后体积通常不高于原始数据的 2 倍shift → depth 查表传感器输出的是 16 位 “shift” 值经 uplinksimple_shift2depth.h 中的 1024 项查找表换算为毫米深度表值从 0/264mm 起单调递增至 9729mm0xffff为无效值哨兵解析时凡大于等于该换算结果的像素一律置 0时间戳尾巴所有深度帧之后先写入numDepthFrames个 double深度帧时间戳秒再写入numColorFrames个 double彩色帧时间戳depth2pgm的process函数会读出深度时间戳并换算为微秒。解析示例程序的使用方式见 depth2pgm/README.md# 在 ScannerApp/depth2pgm 目录下编译 make # 用法 depth2pgm input.depth output_basename numDepthFramesToExtract输出为二进制 PGM 格式P516 位深度单位 mm。depth2pgm.cpp 的saveAsPGM注意了一个关键细节写出前对每个 16 位像素做字节交换std::swap把小端数据转成 PGM 规范要求的网络字节序并注释 “data values are 16-bit each”。默认按 640×480 解析与 App 中使用的STStreamConfigDepth640x480流配置一致。4.3 彩色数据*.h264README 描述*.h264是 iPad 相机的 H.264 编码彩色帧流可用 ffmpeg 转成图片序列ffmpeg -i id.h264 %6d.color.png从 Encoder.mm 与 EncoderConfig.h 看编码链路的实现事实包括编码器基于 VideoToolbox 的VTCompressionSession源像素格式为kCVPixelFormatType_420YpCbCr8BiPlanarFullRange与 ViewControllerCamera.mm 中AVCaptureVideoDataOutput的采样格式一致格式类型在 JPEG 与 H.264 间由EncoderConfig::MediaFormat选择扫描时固定走 H.264编码参数在 ViewControllerSensor.mm 组装EncoderConfig(colorWidth, colorHeight, EncoderConfig::H264, 30, _options.colorEncodeBitrate)即30 fps、码率默认 5000 kbpsOptions::colorEncodeBitrate的默认值见 ViewController.h彩色帧在进入编码器前会取colorFrame.halfResolutionColorFrame半分辨率版本因此元数据里的彩色分辨率与传感器原始分辨率存在 2 倍关系时需注意useHalfResColor的实际状态输出为Annex B格式writeToFile会遍历 AVCC 长度前缀的 NALU逐个加上 4 字节起始码{0,0,0,1}写出关键帧时先从CMFormatDescription中取出 SPS/PPS 各加起始码写入保证文件可独立解码。深度帧与彩色帧的同步由 SDK 的帧同步机制完成相机回调captureOutput:didOutputSampleBuffer:把彩色 buffer 直接喂给[_sensorController frameSyncNewColorBuffer:]SDK 随后回调sensorDidOutputSynchronizedDepthFrame:andColorFrame:产出配对的深度/彩色帧见 ViewControllerCamera.mm 与 ViewControllerSensor.mm。startStructureSensorStreaming会根据是否使用彩色相机选择STFrameSyncDepthAndRgb或STFrameSyncOff。4.4 相机数据*.camREADME 说明*.cam是 iPad 相机设置流包含曝光信息README 中格式细节标注为 TODO但源码给出了确切布局文件头先写入 3 字节版本字符串v1ViewControllerSensor.mm之后每帧彩色数据写 5 个 32 位 float白平衡红增益redGain、绿增益greenGain、蓝增益blueGain、曝光时长exposureDuration秒、ISO 值ViewControllerSensor.mm。这些参数用于后续重建与标注时的曝光校正参考。App 还提供 UI 支持扫描前可通过 AWB 开关在自动/锁定曝光白平衡间切换或在曝光表auto (low light)、2/5/10/15/20 ms中手动指定曝光档位ViewController.mm。4.5 IMU 数据*.imuREADME 给出*.imu的原始二进制布局约每秒 53 个采样每个采样为 15 个 8 字节 double小端、IEEE 754--- Repeats approx. 53 times per second --- [8-byte capture device up-time sec. represented in double precision IEEE 754 little-endian] [8-byte x rotation rate (Radians/s, double, RHR)] [8-byte y rotation rate (Radians/s, double, RHR)] [8-byte z rotation rate (Radians/s, double, RHR)] [8-byte x user-caused acceleration vector (G, double, devices reference frame)] [8-byte y user-caused acceleration vector (G, double, devices reference frame)] [8-byte z user-caused acceleration vector (G, double, devices reference frame)] [8-byte x magnetic field (microtesla, double)] [8-byte y magnetic field (microtesla, double)] [8-byte z magnetic field (microtesla, double)] [8-byte roll (Radians, double)] [8-byte pitch (Radians, double)] [8-byte yaw (Radians, double)] [8-byte x gravity vector (G, double, devices reference frame)] [8-byte y gravity vector (G, double, devices reference frame)] [8-byte z gravity vector (G, double, devices reference frame)] ----- REPEAT ------源码侧与该布局完全吻合ViewController.mm 的setupIMU通过CMMotionManager以 60 FPS 请求 device motion 事件代码注释说明实际回调约为 53 FPSprocessDeviceMotion:withError:按 “systemUptime → rotationRate ×3 → userAcceleration ×3 → magneticField ×3 → roll/pitch/yaw → gravity ×3” 的顺序逐字段fwrite8 字节并立即fflush字段顺序与 README 描述一一对应时间戳字段使用的是系统运行时间NSProcessInfo.systemUptime源码注释也坦诚说明这依赖主机小端浮点表示。README 同时提示 IMU 数据语义可参考 Apple CMDeviceMotion API 文档。元数据中的numIMUmeasurements即该回调中维护的计数器g_numIMUmeasurements样例值 4185 除以 53 Hz 可反推出约 79 秒的扫描时长与numDepthFrames 1912约 30 fps × 64 秒量级吻合。五、上传与校验从 iPad 到数据服务器README 开篇提到的 “uploads to the data staging server” 在源码中是一条完整的两段式链路上传PUTuploadButtonPressed:扫描 Documents 目录排除.jpg缩略图为每个文件构造 PUT 请求——FILE_NAME头携带文件名、Content-Type: application/ipad_scanner_data、Content-Length为文件字节数正文为文件输入流ViewController.mm。uploadQueue的并发被限制为 1即串行上传进度通过didSendBodyData回调按已传字节/总字节驱动进度条校验GET verify单个文件返回 HTTP 200 后App 本地按 4096 字节块READ_CHUNK_SIZE计算 MD5请求VERIFY?filenamenamechecksummd5服务端比对暂存文件的校验和若返回 200App 才删除本地副本ViewController.mm。verifyQueue并发为 3允许校验与下一轮上传并行。服务端对应实现在 Server/upload.py/upload路由接收 PUT/POST 并把文件写入 staging 目录判断该扫描的全部文件到齐scan_done_uploading后触发处理流程/verify路由执行校验和比对。这套 “上传成功但校验失败则保留本地文件重试” 的设计是采集数据在弱网环境下仍能最终一致落盘的关键。此外App 会检测 WiFi 连通性isConnectedToWIFI实际以能否通过 WiFi 到达服务器主机判断未连网时隐藏上传按钮——即上传能力与网络状态直接联动。六、适用前提与注意事项硬件强依赖采集必须使用 Structure.ioOccipital传感器 iPadSDK 以闭源 framework 形式内置在 ScannerApp/Frameworks/Structure.framework传感器断连或低电量时 App 会中止扫描并复位状态sensorDidDisconnect、sensorBatteryNeedsCharging。工具链年代README 明确以 Xcode 7.2 为基准工程文件为旧版格式新版 Xcode 编译前可能需要修改工程设置。数据解析起点拿到*.depth数据后推荐从 ScannerApp/depth2pgm 的示例程序入手理解帧组织与 shift→mm 换算ScanNet 正式数据发布使用的是统一的*.sens容器格式见 SensReader 与根 README 的 Data Organization 一节其字段语义与本文所述的元数据、深度、IMU 布局一脉相承。服务器端若要自行搭建接收端可参考 Server/upload.py 及 Server/start_upload_server.sh 的启动方式并用文件头部注释中的 curl 命令模拟 iPad 端上传做端到端验证。读完本文读者应能独立复现 ScannerApp 的构建配置Config.h服务器端点、按二进制布局解析*.depth/*.imu/*.cam五类文件、用 ffmpeg 或 depth2pgm 转换彩色与深度数据并理解 PUT 上传 MD5 verify 的可靠回传机制——这正是 ScanNet 数据集采集链路的完整技术全貌。赞分享数据集计算机视觉3D视觉【免费下载链接】ScanNet项目地址https://gitcode.com/gh_mirrors/sc/ScanNet点击查看免费下载相关推荐ScanNet 数据集详解RGB-D 室内场景数据组织、.sens/.segs.json 数据格式与配套工具链ScanNet 数据集详解RGB D 室内场景数据组织、 .sens / .segs.json 数据格式与配套工具链 ScanNet 是一个包含 250 万帧数据集计算机视觉3D视觉ScanNet Converter 详解将 ScannerApp 原始采集数据转换为 .sens 传感器流的完整流程ScanNet Converter 详解将 ScannerApp 原始采集数据转换为 .sens 传感器流的完整流程 本文以 ScanNet 仓库中的 Con数据集计算机视觉3D视觉WeiboSpider终极指南7种微博数据采集模式详解与实战WeiboSpider终极指南7种微博数据采集模式详解与实战 WeiboSpider是一款持续维护的新浪微博采集工具能够帮助用户轻松获取各类微博数据。无论是网页爬虫数据采集创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考