From 20ef609513109b22122bf33f1a9737c546fa4eef Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 17 Jun 2025 08:26:02 +0800 Subject: [PATCH 01/31] update cmakelist --- .github/workflows/build_wheels.yml | 42 +++++ .gitignore | 7 + CMakeLists.txt | 66 ++++++- MANIFEST.in | 2 + README.md | 4 + README_zh.md | 2 + bindings/CMakeLists.txt | 63 +++++++ bindings/README.md | 129 +++++++++++++ bindings/spatialmp4.cpp | 213 ++++++++++++++++++++++ cmake/eigen.cmake | 3 +- cmake/pybind11.cmake | 29 +++ docs/install_faq.md | 58 ++++++ pyproject.toml | 39 ++++ python/TODO | 0 bindings/TODO => python/tests/__init__.py | 0 python/tests/test_reader.py | 49 +++++ scripts/build_ffmpeg.sh | 13 +- scripts/cmake.rb | 6 +- src/spatialmp4/reader.h | 12 +- src/spatialmp4/utils.h | 15 +- src/spatialmp4/version.h.in | 47 +++++ 21 files changed, 785 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/build_wheels.yml create mode 100644 MANIFEST.in create mode 100644 bindings/CMakeLists.txt create mode 100644 bindings/README.md create mode 100644 bindings/spatialmp4.cpp create mode 100644 cmake/pybind11.cmake create mode 100644 docs/install_faq.md create mode 100644 pyproject.toml delete mode 100644 python/TODO rename bindings/TODO => python/tests/__init__.py (100%) create mode 100644 python/tests/test_reader.py create mode 100644 src/spatialmp4/version.h.in diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml new file mode 100644 index 0000000..e4f50be --- /dev/null +++ b/.github/workflows/build_wheels.yml @@ -0,0 +1,42 @@ +name: Build Wheels + +on: + push: + tags: + - 'v*' + pull_request: + branches: [ main ] + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install cmeel[build] + + - name: Build wheels + env: + CIBW_BEFORE_BUILD: | + bash scripts/build_ffmpeg.sh + bash scripts/install_deps.sh + CIBW_BUILD: "cp3*-*" + CIBW_SKIP: "pp* *-win32 *-win_amd64" + run: | + python -m cibuildwheel --output-dir wheelhouse \ No newline at end of file diff --git a/.gitignore b/.gitignore index 98a2134..8308949 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,13 @@ tmp* build/* +build-editable/* # ffmpeg build scripts/build_ffmpeg + +# python venv +.venv + +# cibuildwheel +wheelhouse diff --git a/CMakeLists.txt b/CMakeLists.txt index 27a2808..12f4957 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,13 @@ -cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.24.1 FATAL_ERROR) -project(spatialmp4) +project(spatialmp4 VERSION 0.1.0) + +# Configure version header +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/spatialmp4/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/spatialmp4/version.h + @ONLY +) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -9,6 +16,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) option(BUILD_ANDROID "whether build for android" OFF) option(BUILD_TESTING "whether build unit test" ON) +option(BUILD_PYTHON_BINDINGS "whether build python bindings" OFF) + if(BUILD_ANDROID) message(FATAL_ERROR "Don't support android building.") endif() @@ -22,6 +31,10 @@ include(cmake/spdlog.cmake) include(cmake/fmt.cmake) include(cmake/eigen.cmake) include(cmake/sophus.cmake) + +if(BUILD_PYTHON_BINDINGS) + include(cmake/pybind11.cmake) +endif() set(SRC ./src/spatialmp4/utilities/OpencvUtils.cc @@ -29,11 +42,13 @@ set(SRC ./src/spatialmp4/reader.cc ) -add_library(${CMAKE_PROJECT_NAME}_static STATIC ${SRC}) -target_include_directories(${CMAKE_PROJECT_NAME}_static PUBLIC +add_library(${CMAKE_PROJECT_NAME}_lib SHARED ${SRC}) +target_include_directories(${CMAKE_PROJECT_NAME}_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}/include ) -target_link_libraries(${CMAKE_PROJECT_NAME}_static PUBLIC + +target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC PkgConfig::LIBAV lib_opencv spdlog @@ -42,6 +57,34 @@ target_link_libraries(${CMAKE_PROJECT_NAME}_static PUBLIC sophus ) +# Add macOS framework linking +if(APPLE) + set_target_properties(${CMAKE_PROJECT_NAME}_lib PROPERTIES + INSTALL_RPATH "@loader_path" + BUILD_WITH_INSTALL_RPATH TRUE + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python + ) + target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC + "-framework Foundation" + "-framework AudioToolbox" + "-framework CoreAudio" + "-framework AVFoundation" + "-framework CoreVideo" + "-framework CoreMedia" + "-framework CoreGraphics" + "-framework OpenGL" + "-framework ApplicationServices" + "-framework CoreFoundation" + "-framework AppKit" + "-framework Carbon" + "-framework Metal" + "-framework VideoToolbox" + "-framework CoreImage" + "-framework CoreServices" + "-framework Security" + ) +endif() + if(BUILD_TESTING) include(cmake/gtest.cmake) add_executable(test_reader @@ -51,7 +94,7 @@ if(BUILD_TESTING) ./src/spatialmp4/reader_test.cc ) target_link_libraries(test_reader PRIVATE - ${CMAKE_PROJECT_NAME}_static + ${CMAKE_PROJECT_NAME}_lib gtest gtest_main ) @@ -62,3 +105,14 @@ if(BUILD_TESTING) target_link_libraries(test_reader PRIVATE stdc++fs) endif() endif() + +if(BUILD_PYTHON_BINDINGS) + add_subdirectory(bindings) +endif() + +if (APPLE) + set_target_properties(${CMAKE_PROJECT_NAME}_lib PROPERTIES INSTALL_RPATH "@loader_path") +else() + set_target_properties(${CMAKE_PROJECT_NAME}_lib PROPERTIES INSTALL_RPATH "\$ORIGIN") +endif() +install(TARGETS ${CMAKE_PROJECT_NAME}_lib DESTINATION lib) diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..8fcf336 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +recursive-include spatialmp4 *.so *.dylib +include pyproject.toml diff --git a/README.md b/README.md index cc410df..1e8ecac 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,10 @@ make -j$(nproc) # On Linux make -j$(sysctl -n hw.ncpu) # On macOS ``` +Sometime it can be difficult to build a c++ source project. [FAQ for installation](docs/install_faq.md) +may help you. If still not working, welcome [submit a issue](https://github.com/Pico-Developer/SpatialMP4/issues). + + ### 5. Run Tests (Optional) ```bash diff --git a/README_zh.md b/README_zh.md index 493db91..afee056 100644 --- a/README_zh.md +++ b/README_zh.md @@ -71,6 +71,8 @@ cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) # Linux系统 make -j$(sysctl -n hw.ncpu) # macOS系统 ``` +如果编译报错,请参考[FAQ for installation](docs/install_faq.md)。如果还是解决不了, +欢迎[提issue](https://github.com/Pico-Developer/SpatialMP4/issues),我们会及时帮助你。 ### 5. 运行测试 (可选) diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt new file mode 100644 index 0000000..c729b7b --- /dev/null +++ b/bindings/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 3.14) + +if (NOT PYTHON_SITELIB) +set(PYTHON_SITELIB "lib") +endif() + +if ("${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" STREQUAL "") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +endif() + +set(CMAKE_SHARED_MODULE_PREFIX "") + +# Find Python +find_package(Python3 COMPONENTS Interpreter Development REQUIRED) + +# Add Python bindings library +pybind11_add_module(spatialmp4 spatialmp4.cpp) + +# Link against main library and dependencies +target_link_libraries(spatialmp4 PRIVATE + spatialmp4_lib + ${OpenCV_LIBS} + Sophus::Sophus + Eigen3::Eigen + ${FFMPEG_LIBRARIES} +) + +# Include directories +target_include_directories(spatialmp4 PRIVATE + ${CMAKE_SOURCE_DIR}/src + ${OpenCV_INCLUDE_DIRS} + ${EIGEN3_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIRS} +) + +if (APPLE) +set_target_properties(spatialmp4 PROPERTIES INSTALL_RPATH "@loader_path/../..") +else() +set_target_properties(spatialmp4 PROPERTIES INSTALL_RPATH "\$ORIGIN/../..") +endif() + +# Set output directory +set_target_properties(spatialmp4 PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python +) + +# Install rules +install(TARGETS spatialmp4 + LIBRARY DESTINATION ${PYTHON_SITELIB} + RUNTIME DESTINATION ${PYTHON_SITELIB} +) + +# add_custom_command( +# TARGET spatialmp4 POST_BUILD +# COMMAND doxystub +# --module spatialmp4 +# --doxygen_directory "${CMAKE_CURRENT_SOURCE_DIR}" +# --output "${CMAKE_BINARY_DIR}/${PYTHON_SITELIB}/spatialmp4.pyi" +# WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/${PYTHON_SITELIB}" +# COMMENT "Generating stubs..." +# ) + +# install(FILES ${CMAKE_BINARY_DIR}/${PYTHON_SITELIB}/spatialmp4.pyi DESTINATION ${PYTHON_SITELIB}) \ No newline at end of file diff --git a/bindings/README.md b/bindings/README.md new file mode 100644 index 0000000..ef986b9 --- /dev/null +++ b/bindings/README.md @@ -0,0 +1,129 @@ +# SpatialMP4 Python Bindings + +This directory contains Python bindings for the SpatialMP4 library using pybind11. + +## Requirements + +- Python 3.6 or later +- CMake 3.24 or later +- pybind11 +- OpenCV Python +- NumPy + +## Building the Bindings + +1. Make sure you have all the dependencies installed: + +```bash +# Install Python dependencies +pip install numpy opencv-python + +# Install pybind11 (Ubuntu/Debian) +sudo apt-get install pybind11-dev + +# Install pybind11 (macOS) +brew install pybind11 +``` + +2. Build the project with Python bindings enabled: + +```bash +mkdir build && cd build +cmake .. -DBUILD_PYTHON_BINDINGS=ON +make -j +``` + +The Python module will be built in the `build/python` directory. + +## Installation + +After building, you can install the Python module system-wide: + +```bash +sudo make install +``` + +Or for development, you can add the build directory to your PYTHONPATH: + +```bash +export PYTHONPATH=/path/to/build/python:$PYTHONPATH +``` + +## Usage + +See `example.py` for a complete example of how to use the Python bindings. Here's a basic example: + +```python +import spatialmp4 + +# Create a reader +reader = spatialmp4.Reader("path/to/your/video.mp4") + +# Check available streams +print(f"Has RGB: {reader.has_rgb()}") +print(f"Has Depth: {reader.has_depth()}") +print(f"Has Pose: {reader.has_pose()}") + +# Set read mode +reader.set_read_mode(spatialmp4.ReadMode.RGB_ONLY) + +# Read frames +while reader.has_next(): + rgb_frame = reader.load_rgb() + left_rgb = rgb_frame.left_rgb # NumPy array + right_rgb = rgb_frame.right_rgb # NumPy array + pose = rgb_frame.pose +``` + +## API Reference + +### Classes + +#### Reader +- Main class for reading SpatialMP4 files +- Methods: + - `has_rgb()`: Check if RGB stream is available + - `has_depth()`: Check if depth stream is available + - `has_pose()`: Check if pose data is available + - `get_duration()`: Get video duration in seconds + - `get_rgb_fps()`: Get RGB stream FPS + - `get_depth_fps()`: Get depth stream FPS + - And more... + +#### RGBFrame +- Contains RGB frame data and associated pose +- Properties: + - `timestamp`: Frame timestamp + - `left_rgb`: Left RGB image as NumPy array + - `right_rgb`: Right RGB image as NumPy array + - `pose`: Associated pose data + +#### DepthFrame +- Contains depth frame data and associated pose +- Properties: + - `timestamp`: Frame timestamp + - `depth`: Depth image as NumPy array + - `pose`: Associated pose data + +#### PoseFrame +- Contains pose data +- Properties: + - `timestamp`: Pose timestamp + - `x`, `y`, `z`: Position + - `qw`, `qx`, `qy`, `qz`: Quaternion orientation + +### Enums + +#### ReadMode +- `RGB_ONLY`: Only read RGB frames +- `DEPTH_ONLY`: Only read depth frames +- `DEPTH_FIRST`: Read both RGB and depth frames, depth frame as reference + +#### StreamType +- `UNKNOWN`: Unknown stream type +- `AUDIO`: Audio stream +- `AUDIO_2`: Secondary audio stream +- `RGB`: RGB video stream +- `DISPARITY`: Disparity stream +- `POSE`: Pose data stream +- `DEPTH`: Depth stream diff --git a/bindings/spatialmp4.cpp b/bindings/spatialmp4.cpp new file mode 100644 index 0000000..260aaee --- /dev/null +++ b/bindings/spatialmp4.cpp @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include "spatialmp4/reader.h" +#include "spatialmp4/data_types.h" +#include "spatialmp4/utils.h" +#include "spatialmp4/version.h" + +namespace py = pybind11; + +// Helper function to convert cv::Mat to numpy array +py::array_t mat_to_numpy(const cv::Mat& mat) { + if (mat.empty()) { + return py::array_t(); + } + + py::array_t array({mat.rows, mat.cols, mat.channels()}); + std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); + return array; +} + +// Helper function to convert depth cv::Mat to numpy array +py::array_t depth_mat_to_numpy(const cv::Mat& mat) { + if (mat.empty()) { + return py::array_t(); + } + + py::array_t array({mat.rows, mat.cols}); + std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); + return array; +} + +PYBIND11_MODULE(spatialmp4, m) { + m.doc() = "SpatialMP4 Python Bindings"; + + // 添加版本信息 + m.attr("__version__") = SpatialML::GetVersion(); + m.def("get_version", &SpatialML::GetVersion, "Get the version string"); + m.def("get_major_version", &SpatialML::GetMajorVersion, "Get the major version number"); + m.def("get_minor_version", &SpatialML::GetMinorVersion, "Get the minor version number"); + m.def("get_patch_version", &SpatialML::GetPatchVersion, "Get the patch version number"); + + // Bind StreamType enum + py::enum_(m, "StreamType") + .value("UNKNOWN", SpatialML::MEDIA_TYPE_UNKNOWN) + .value("AUDIO", SpatialML::MEDIA_TYPE_AUDIO) + .value("AUDIO_2", SpatialML::MEDIA_TYPE_AUDIO_2) + .value("RGB", SpatialML::MEDIA_TYPE_RGB) + .value("DISPARITY", SpatialML::MEDIA_TYPE_DISPARITY) + .value("POSE", SpatialML::MEDIA_TYPE_POSE) + .value("DEPTH", SpatialML::MEDIA_TYPE_DEPTH) + .export_values(); + + // Bind pose_frame struct + py::class_(m, "PoseFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::pose_frame::timestamp) + .def_readwrite("x", &SpatialML::pose_frame::x) + .def_readwrite("y", &SpatialML::pose_frame::y) + .def_readwrite("z", &SpatialML::pose_frame::z) + .def_readwrite("qw", &SpatialML::pose_frame::qw) + .def_readwrite("qx", &SpatialML::pose_frame::qx) + .def_readwrite("qy", &SpatialML::pose_frame::qy) + .def_readwrite("qz", &SpatialML::pose_frame::qz) + .def("as_se3", &SpatialML::pose_frame::as_se3) + .def("__repr__", [](const SpatialML::pose_frame &p) { + std::ostringstream ss; + ss << p; + return ss.str(); + }); + + // Bind rgb_frame struct + py::class_(m, "RGBFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::rgb_frame::timestamp) + .def_property("left_rgb", + [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.left_rgb); }, + [](SpatialML::rgb_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property("right_rgb", + [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.right_rgb); }, + [](SpatialML::rgb_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_readwrite("pose", &SpatialML::rgb_frame::pose) + .def("__repr__", [](const SpatialML::rgb_frame &f) { + std::ostringstream ss; + ss << f; + return ss.str(); + }); + + // Bind depth_frame struct + py::class_(m, "DepthFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::depth_frame::timestamp) + .def_property("depth", + [](const SpatialML::depth_frame &f) { return depth_mat_to_numpy(f.depth); }, + [](SpatialML::depth_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_readwrite("pose", &SpatialML::depth_frame::pose) + .def("__repr__", [](const SpatialML::depth_frame &f) { + std::ostringstream ss; + ss << f; + return ss.str(); + }); + + // Bind camera_intrinsics struct + py::class_(m, "CameraIntrinsics") + .def(py::init<>()) + .def_readwrite("fx", &SpatialML::camera_intrinsics::fx) + .def_readwrite("fy", &SpatialML::camera_intrinsics::fy) + .def_readwrite("cx", &SpatialML::camera_intrinsics::cx) + .def_readwrite("cy", &SpatialML::camera_intrinsics::cy) + .def("as_cvmat", &SpatialML::camera_intrinsics::as_cvmat) + .def("__repr__", [](const SpatialML::camera_intrinsics &i) { + std::ostringstream ss; + ss << i; + return ss.str(); + }); + + // Bind camera_extrinsics struct + py::class_(m, "CameraExtrinsics") + .def(py::init<>()) + .def_readwrite("extrinsics", &SpatialML::camera_extrinsics::extrinsics) + .def("as_cvmat", &SpatialML::camera_extrinsics::as_cvmat) + .def("as_se3", &SpatialML::camera_extrinsics::as_se3) + .def("__repr__", [](const SpatialML::camera_extrinsics &e) { + std::ostringstream ss; + ss << e; + return ss.str(); + }); + + // Bind Reader class + py::class_(m, "Reader") + .def(py::init()) + .def("has_rgb", &SpatialML::Reader::HasRGB) + .def("has_depth", &SpatialML::Reader::HasDepth) + .def("has_pose", &SpatialML::Reader::HasPose) + .def("has_audio", &SpatialML::Reader::HasAudio) + .def("has_disparity", &SpatialML::Reader::HasDisparity) + .def("get_start_timestamp", &SpatialML::Reader::GetStartTimestamp) + .def("get_duration", &SpatialML::Reader::GetDuration) + .def("get_rgb_fps", &SpatialML::Reader::GetRgbFPS) + .def("get_rgb_width", &SpatialML::Reader::GetRgbWidth) + .def("get_rgb_height", &SpatialML::Reader::GetRgbHeight) + .def("get_rgb_intrinsics_left", &SpatialML::Reader::GetRgbIntrinsicsLeft) + .def("get_rgb_extrinsics_left", &SpatialML::Reader::GetRgbExtrinsicsLeft) + .def("get_rgb_intrinsics_right", &SpatialML::Reader::GetRgbIntrinsicsRight) + .def("get_rgb_extrinsics_right", &SpatialML::Reader::GetRgbExtrinsicsRight) + .def("get_depth_fps", &SpatialML::Reader::GetDepthFPS) + .def("get_depth_width", &SpatialML::Reader::GetDepthWidth) + .def("get_depth_height", &SpatialML::Reader::GetDepthHeight) + .def("get_depth_intrinsics", &SpatialML::Reader::GetDepthIntrinsics) + .def("get_depth_extrinsics", &SpatialML::Reader::GetDepthExtrinsics) + .def("get_pose_frames", &SpatialML::Reader::GetPoseFrames) + .def("get_rgb_keyframe_index", &SpatialML::Reader::GetRgbKeyframeIndex) + .def("get_depth_keyframe_index", &SpatialML::Reader::GetDepthKeyframeIndex) + .def("is_rgb_distorted", &SpatialML::Reader::IsRgbDistorted) + .def("get_rgb_distortion_model", &SpatialML::Reader::GetRgbDistortionModel) + .def("get_rgb_distortion_params_left", &SpatialML::Reader::GetRgbDistortionParamsLeft) + .def("get_rgb_distortion_params_right", &SpatialML::Reader::GetRgbDistortionParamsRight) + .def("get_depth_distortion_model", &SpatialML::Reader::GetDepthDistortionModel) + .def("get_depth_distortion_params", &SpatialML::Reader::GetDepthDistortionParams) + .def("get_rgb_timebase", &SpatialML::Reader::GetRgbTimebase) + .def("get_depth_timebase", &SpatialML::Reader::GetDepthTimebase) + .def("set_read_mode", &SpatialML::Reader::SetReadMode) + .def("has_next", &SpatialML::Reader::HasNext) + .def("load_rgb", [](SpatialML::Reader& self) { + SpatialML::rgb_frame frame; + self.Load(frame); + return frame; + }) + .def("load_depth", [](SpatialML::Reader& self) { + SpatialML::depth_frame frame; + self.Load(frame); + return frame; + }) + .def("load_both", [](SpatialML::Reader& self) { + SpatialML::rgb_frame rgb_frame; + SpatialML::depth_frame depth_frame; + self.Load(rgb_frame, depth_frame); + return py::make_tuple(rgb_frame, depth_frame); + }) + .def("reset", &SpatialML::Reader::Reset) + .def("get_index", &SpatialML::Reader::GetIndex); + + // Bind ReadMode enum + py::enum_(m, "ReadMode") + .value("RGB_ONLY", SpatialML::Reader::RGB_ONLY) + .value("DEPTH_ONLY", SpatialML::Reader::DEPTH_ONLY) + .value("DEPTH_FIRST", SpatialML::Reader::DEPTH_FIRST) + .export_values(); + + // Bind RandomAccessVideoReader class + py::class_(m, "RandomAccessVideoReader") + .def(py::init<>()) + .def("open", &SpatialML::RandomAccessVideoReader::Open) + .def("get_frame", [](SpatialML::RandomAccessVideoReader& self, int64_t frame_number) -> py::object { + AVFrame* frame = self.GetFrame(frame_number); + if (!frame) { + return py::none(); + } + std::pair rgb_mats; + SpatialML::FrameToBGR24(frame, rgb_mats); + return py::make_tuple(mat_to_numpy(rgb_mats.first), mat_to_numpy(rgb_mats.second)); + }) + .def("get_frame_count", &SpatialML::RandomAccessVideoReader::GetFrameCount) + .def("debug", &SpatialML::RandomAccessVideoReader::Debug); +} \ No newline at end of file diff --git a/cmake/eigen.cmake b/cmake/eigen.cmake index 33eaa52..3e27fcd 100644 --- a/cmake/eigen.cmake +++ b/cmake/eigen.cmake @@ -2,6 +2,7 @@ include(FetchContent) FetchContent_Declare( eigen URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz + # URL /Users/bytedance/Downloads/eigen-3.3.7.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP true ) @@ -19,4 +20,4 @@ if(NOT TARGET Eigen3::Eigen) INTERFACE_INCLUDE_DIRECTORIES "${eigen_SOURCE_DIR}") endif() -message(STATUS "EIGEN_INCLUDE_DIR: ${eigen_SOURCE_DIR}") \ No newline at end of file +message(STATUS "EIGEN_INCLUDE_DIR: ${eigen_SOURCE_DIR}") diff --git a/cmake/pybind11.cmake b/cmake/pybind11.cmake new file mode 100644 index 0000000..58c6fab --- /dev/null +++ b/cmake/pybind11.cmake @@ -0,0 +1,29 @@ +include(FetchContent) + +# 首先查找 Python +find_package(Python3 COMPONENTS Interpreter Development REQUIRED) + +# 设置 Python 相关变量 +set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) +set(PYTHON_INCLUDE_DIR ${Python3_INCLUDE_DIRS}) +set(PYTHON_LIBRARY ${Python3_LIBRARIES}) + +# 配置 pybind11 +FetchContent_Declare( + pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11.git + GIT_TAG v2.11.1 # 使用最新的稳定版本 +) + +# 设置 pybind11 选项 +set(PYBIND11_PYTHON_VERSION ${Python3_VERSION}) +set(PYBIND11_FINDPYTHON ON) +set(PYBIND11_NOPYTHON OFF) + +# 获取并配置 pybind11 +FetchContent_MakeAvailable(pybind11) + +# 确保 pybind11 被正确配置 +if(NOT TARGET pybind11::module) + message(FATAL_ERROR "pybind11::module target not found") +endif() \ No newline at end of file diff --git a/docs/install_faq.md b/docs/install_faq.md new file mode 100644 index 0000000..cb7b735 --- /dev/null +++ b/docs/install_faq.md @@ -0,0 +1,58 @@ +# FAQ for build and install + +Source build a project sometimes can be not easy. This document helps you out of +the trouble. + +## Question 1 +``` +CMake Error at eigen-subbuild/eigen-populate-prefix/src/eigen-populate-stamp/download-eigen-populate.cmake:162 (message): + Each download failed! + + error: downloading 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz' failed + status_code: 35 + status_string: "SSL connect error" + log: + --- LOG BEGIN --- + Trying 172.65.251.78:443... +``` +`eigen-3.3.7.tar.gz` is not accessable in your computer. You can check by open this link in the browser. +If so, please fix network issue and continue building. + +Another solution is to download `eigen-3.3.7.tar.gz` to local path, and set path in [cmake/eigen.cmake](../cmake/eigen.cmake#L4). + +## Question 2 +``` +Compiling the C compiler identification source file "CMakeCCompilerId.c" failed. +Compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc +Build flags: +Id flags: + +The output was: +1 +ld: library 'System' not found +cc: error: linker command failed with exit code 1 (use -v to see invocation) + + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" failed. +Compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ +Build flags: +Id flags: + +The output was: +1 +ld: library 'c++' not found +c++: error: linker command failed with exit code 1 (use -v to see invocation) +``` + +Make sure you have installed xcode and Command Line Tools. Try below commands: +```bash +xcode-select --install +sudo xcode-select --reset +sudo xcode-select -s /Applications/Xcode.app/Contents/Developer + +# Then rebuild +rm -rf build +mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j$(sysctl -n hw.ncpu) +``` diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e8ef3b1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,39 @@ +[build-system] +build-backend = "cmeel" +requires = [ + "cmeel[build]", + "cmake<4", + "doxystub >= 0.0.13" +] + +[project] +name = "spatialmp4" +version = "0.1.0" +description = "SpatialMP4 Python Package" +authors = [{ email = "bingwen.ai@bytedance.com", name = "Bingwen Wang" }] +license = "MIT" +requires-python = ">=3.8" +classifiers = [ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [ + "numpy", + "opencv-python" +] + +[project.urls] +repository = "https://github.com/Pico-Developer/SpatialMP4" + +[tool.cmeel] +run-tests = false + +[tool.cibuildwheel] +before-all = "bash scripts/build_ffmpeg.sh && bash scripts/install_deps.sh" +build = "cp3*-*" +skip = "pp* *-win32 *-win_amd64" diff --git a/python/TODO b/python/TODO deleted file mode 100644 index e69de29..0000000 diff --git a/bindings/TODO b/python/tests/__init__.py similarity index 100% rename from bindings/TODO rename to python/tests/__init__.py diff --git a/python/tests/test_reader.py b/python/tests/test_reader.py new file mode 100644 index 0000000..d85b6ca --- /dev/null +++ b/python/tests/test_reader.py @@ -0,0 +1,49 @@ +import spatialmp4 + + +def test_version(): + print(spatialmp4.__version__) + +def test_reader(): + reader = spatialmp4.Reader("video/test.mp4") + + # Print basic information + print(f"Has RGB: {reader.has_rgb()}") + print(f"Has Depth: {reader.has_depth()}") + print(f"Has Pose: {reader.has_pose()}") + print(f"Duration: {reader.get_duration()} seconds") + print(f"RGB FPS: {reader.get_rgb_fps()}") + print(f"Depth FPS: {reader.get_depth_fps()}") + + # Get camera parameters + rgb_intrinsics = reader.get_rgb_intrinsics_left() + print(f"RGB Intrinsics: fx={rgb_intrinsics.fx}, fy={rgb_intrinsics.fy}, cx={rgb_intrinsics.cx}, cy={rgb_intrinsics.cy}") + + # Set read mode + reader.set_read_mode(spatialmp4.ReadMode.RGB_ONLY) + + # Read frames + while reader.has_next(): + # Load RGB frame + rgb_frame = reader.load_rgb() + + # Access the frame data (returns numpy arrays) + left_rgb = rgb_frame.left_rgb # Shape: (height, width, 3) + right_rgb = rgb_frame.right_rgb # Shape: (height, width, 3) + + # Get pose data + pose = rgb_frame.pose + print(f"Frame timestamp: {rgb_frame.timestamp}") + print(f"Pose: x={pose.x}, y={pose.y}, z={pose.z}, qw={pose.qw}, qx={pose.qx}, qy={pose.qy}, qz={pose.qz}") + + # Example of loading both RGB and depth + reader.reset() + reader.set_read_mode(spatialmp4.ReadMode.DEPTH_FIRST) + + if reader.has_next(): + # Load both RGB and depth frames + rgb_frame, depth_frame = reader.load_both() + + # Access depth data (returns numpy array) + depth = depth_frame.depth # Shape: (height, width) + print(f"Depth: {depth.shape}") \ No newline at end of file diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh index 2759cc2..677cf7d 100755 --- a/scripts/build_ffmpeg.sh +++ b/scripts/build_ffmpeg.sh @@ -59,17 +59,26 @@ build_install_ffmpeg() { cd ffmpeg git reset --hard b6f84cd7 git apply $cur/ffmpeg_b6f84cd7.patch + + # Clean previous build + make distclean || true + + # Configure with enhanced PIC support ./configure \ --disable-doc \ --prefix=$INSTALL_PREFIX \ --pkg-config-flags="--static" \ - --extra-cflags="-I/usr/local/include" \ - --extra-ldflags="-L/usr/local/lib" \ + --enable-pic \ + --enable-static \ + --extra-cflags="-I/usr/local/include -fPIC -fPIE" \ + --extra-cxxflags="-fPIC -fPIE" \ + --extra-ldflags="-L/usr/local/lib -fPIC" \ --enable-libass \ --enable-libfreetype \ --enable-libvorbis \ --enable-version3 + # --enable-shared \ # --enable-libmp3lame \ make -j$(nproc) diff --git a/scripts/cmake.rb b/scripts/cmake.rb index dec34d4..46b5a63 100644 --- a/scripts/cmake.rb +++ b/scripts/cmake.rb @@ -1,8 +1,10 @@ class Cmake < Formula desc "Cross-platform make" homepage "https://www.cmake.org/" - url "https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1.tar.gz" - sha256 "0e998229549d7b3f368703d20e248e7ee1f853910d42704aa87918c213ea82c0" + # url "https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1.tar.gz" + # sha256 "0e998229549d7b3f368703d20e248e7ee1f853910d42704aa87918c213ea82c0" + url "https://github.com/Kitware/CMake/releases/download/v3.24.1/cmake-3.24.1.tar.gz" + sha256 "4931e277a4db1a805f13baa7013a7757a0cbfe5b7932882925c7061d9d1fa82b" license "BSD-3-Clause" head "https://gitlab.kitware.com/cmake/cmake.git" diff --git a/src/spatialmp4/reader.h b/src/spatialmp4/reader.h index 6aa05ce..79c71f2 100644 --- a/src/spatialmp4/reader.h +++ b/src/spatialmp4/reader.h @@ -15,6 +15,14 @@ */ #pragma once + +// 导出宏定义 +#if defined(_WIN32) +# define SPATIALMP4_EXPORT __declspec(dllexport) +#else +# define SPATIALMP4_EXPORT __attribute__((visibility("default"))) +#endif + #include #include #include @@ -37,7 +45,7 @@ namespace SpatialML { * Random access video reader. * This class is used to read a video file in random access mode. */ -class RandomAccessVideoReader { +class SPATIALMP4_EXPORT RandomAccessVideoReader { public: RandomAccessVideoReader() = default; ~RandomAccessVideoReader(); @@ -65,7 +73,7 @@ class RandomAccessVideoReader { * This class is used to read a SpatialMP4 file. * The file format is described in the SpatialMP4 format specification. */ -class Reader { +class SPATIALMP4_EXPORT Reader { public: enum ReadMode { RGB_ONLY, diff --git a/src/spatialmp4/utils.h b/src/spatialmp4/utils.h index 5dd3c40..c3c919d 100644 --- a/src/spatialmp4/utils.h +++ b/src/spatialmp4/utils.h @@ -32,6 +32,13 @@ extern "C" { namespace SpatialML { +// 导出宏定义 +#if defined(_WIN32) +# define SPATIALMP4_EXPORT __declspec(dllexport) +#else +# define SPATIALMP4_EXPORT __attribute__((visibility("default"))) +#endif + std::vector String2DoubleVector(const std::string& str); std::string StreamTypeToString(StreamType type); @@ -40,7 +47,13 @@ void PrintStreamInfo(AVFormatContext* pFormatCtx); std::unordered_map GetStreamTypeInfo(AVFormatContext* pFormatCtx); -bool FrameToBGR24(AVFrame* rgb_frame, std::pair& rgb_pair); +/** + * Convert AVFrame to BGR24 format. + * @param rgb_frame Input AVFrame + * @param rgb_pair Output pair of cv::Mat for left and right images + * @return true if successful, false otherwise + */ +SPATIALMP4_EXPORT bool FrameToBGR24(AVFrame* rgb_frame, std::pair& rgb_pair); std::string FFmpegErrorString(int errnum); diff --git a/src/spatialmp4/version.h.in b/src/spatialmp4/version.h.in new file mode 100644 index 0000000..7c903c6 --- /dev/null +++ b/src/spatialmp4/version.h.in @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace SpatialML { + +// Version number definitions +#define SPATIALMP4_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define SPATIALMP4_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define SPATIALMP4_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define SPATIALMP4_VERSION "@PROJECT_VERSION@" + +// Version string +inline const char* GetVersion() { + return SPATIALMP4_VERSION; +} + +// Get major version number +inline int GetMajorVersion() { + return @PROJECT_VERSION_MAJOR@; +} + +// Get minor version number +inline int GetMinorVersion() { + return @PROJECT_VERSION_MINOR@; +} + +// Get patch version number +inline int GetPatchVersion() { + return @PROJECT_VERSION_PATCH@; +} + +} // namespace SpatialML \ No newline at end of file From 76d2f506bd4b202400c2f256434114997cc0dd69 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 17 Jun 2025 08:36:39 +0800 Subject: [PATCH 02/31] recover cmake version --- CMakeLists.txt | 2 +- scripts/cmake.rb | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12f4957..608742b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR) project(spatialmp4 VERSION 0.1.0) diff --git a/scripts/cmake.rb b/scripts/cmake.rb index 46b5a63..dec34d4 100644 --- a/scripts/cmake.rb +++ b/scripts/cmake.rb @@ -1,10 +1,8 @@ class Cmake < Formula desc "Cross-platform make" homepage "https://www.cmake.org/" - # url "https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1.tar.gz" - # sha256 "0e998229549d7b3f368703d20e248e7ee1f853910d42704aa87918c213ea82c0" - url "https://github.com/Kitware/CMake/releases/download/v3.24.1/cmake-3.24.1.tar.gz" - sha256 "4931e277a4db1a805f13baa7013a7757a0cbfe5b7932882925c7061d9d1fa82b" + url "https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1.tar.gz" + sha256 "0e998229549d7b3f368703d20e248e7ee1f853910d42704aa87918c213ea82c0" license "BSD-3-Clause" head "https://gitlab.kitware.com/cmake/cmake.git" From e12a2c266cf7de80b35066568231c286c6868ce4 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 1 Jul 2025 09:26:04 +0800 Subject: [PATCH 03/31] turn BUILD_PYTHON ON --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc68c71..40adcfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) option(BUILD_ANDROID "whether build for android" OFF) option(BUILD_TESTING "whether build unit test" ON) -option(BUILD_PYTHON_BINDINGS "whether build python bindings" OFF) +option(BUILD_PYTHON_BINDINGS "whether build python bindings" ON) if(BUILD_ANDROID) message(FATAL_ERROR "Don't support android building.") From 073a7b7a05d62a29cb5ca118a275c7f65bedf4fe Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 1 Jul 2025 09:35:52 +0800 Subject: [PATCH 04/31] add spatialmp4_to_colmap script --- CMakeLists.txt | 54 +++++++++++++------ examples/python/spatialmp4_to_colmap.py | 72 +++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 examples/python/spatialmp4_to_colmap.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 40adcfa..4caca80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,24 +70,44 @@ if(APPLE) BUILD_WITH_INSTALL_RPATH TRUE LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python ) + + # Find macOS frameworks + find_library(FOUNDATION_FRAMEWORK Foundation) + find_library(AUDIOTOOLBOX_FRAMEWORK AudioToolbox) + find_library(COREAUDIO_FRAMEWORK CoreAudio) + find_library(AVFOUNDATION_FRAMEWORK AVFoundation) + find_library(COREVIDEO_FRAMEWORK CoreVideo) + find_library(COREMEDIA_FRAMEWORK CoreMedia) + find_library(COREGRAPHICS_FRAMEWORK CoreGraphics) + find_library(OPENGL_FRAMEWORK OpenGL) + find_library(APPLICATIONSERVICES_FRAMEWORK ApplicationServices) + find_library(COREFOUNDATION_FRAMEWORK CoreFoundation) + find_library(APPKIT_FRAMEWORK AppKit) + find_library(CARBON_FRAMEWORK Carbon) + find_library(METAL_FRAMEWORK Metal) + find_library(VIDEOTOOLBOX_FRAMEWORK VideoToolbox) + find_library(COREIMAGE_FRAMEWORK CoreImage) + find_library(CORESERVICES_FRAMEWORK CoreServices) + find_library(SECURITY_FRAMEWORK Security) + target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC - "-framework Foundation" - "-framework AudioToolbox" - "-framework CoreAudio" - "-framework AVFoundation" - "-framework CoreVideo" - "-framework CoreMedia" - "-framework CoreGraphics" - "-framework OpenGL" - "-framework ApplicationServices" - "-framework CoreFoundation" - "-framework AppKit" - "-framework Carbon" - "-framework Metal" - "-framework VideoToolbox" - "-framework CoreImage" - "-framework CoreServices" - "-framework Security" + ${FOUNDATION_FRAMEWORK} + ${AUDIOTOOLBOX_FRAMEWORK} + ${COREAUDIO_FRAMEWORK} + ${AVFOUNDATION_FRAMEWORK} + ${COREVIDEO_FRAMEWORK} + ${COREMEDIA_FRAMEWORK} + ${COREGRAPHICS_FRAMEWORK} + ${OPENGL_FRAMEWORK} + ${APPLICATIONSERVICES_FRAMEWORK} + ${COREFOUNDATION_FRAMEWORK} + ${APPKIT_FRAMEWORK} + ${CARBON_FRAMEWORK} + ${METAL_FRAMEWORK} + ${VIDEOTOOLBOX_FRAMEWORK} + ${COREIMAGE_FRAMEWORK} + ${CORESERVICES_FRAMEWORK} + ${SECURITY_FRAMEWORK} ) endif() diff --git a/examples/python/spatialmp4_to_colmap.py b/examples/python/spatialmp4_to_colmap.py new file mode 100644 index 0000000..a61c88d --- /dev/null +++ b/examples/python/spatialmp4_to_colmap.py @@ -0,0 +1,72 @@ +import spatialmp4 as sm +import os +import cv2 +import numpy as np + +def write_cameras_txt(path, width, height, fx, fy, cx, cy): + with open(path, 'w') as f: + # SIMPLE_PINHOLE model: + # params: fx, cx, cy + f.write(f"1 PINHOLE {width} {height} {fx} {cx} {cy}\n") + +def write_images_txt(path, poses, img_names, camera_id=1): + with open(path, 'w') as f: + for i, (pose, name) in enumerate(zip(poses, img_names)): + # + f.write(f"{i+1} {pose['qw']} {pose['qx']} {pose['qy']} {pose['qz']} {pose['tx']} {pose['ty']} {pose['tz']} {camera_id} {name}\n\n") + +def main(input_file, output_dir): + reader = sm.Reader(input_file) + imgdir = os.path.join(output_dir, "images") + colmapdir = os.path.join(output_dir, "sparse/0/") + os.makedirs(imgdir, exist_ok=True) + os.makedirs(colmapdir, exist_ok=True) + + # 获取相机内参 + width = reader.get_rgb_width() + height = reader.get_rgb_height() + intr = reader.get_rgb_intrinsics_left() + fx = intr.fx + fy = intr.fy + cx = intr.cx + cy = intr.cy + + reader.set_read_mode(sm.ReadMode.RGB_ONLY) + + img_names = [] + poses = [] + + while reader.has_next(): + # Load RGB frame + rgb_frame = reader.load_rgb() + img = rgb_frame.left_rgb + pose = rgb_frame.pose + i = len(img_names) + img_name = f"{i+1:08d}.png" + cv2.imwrite(os.path.join(imgdir, img_name), img) + img_names.append(img_name) + poses.append({ + "qw": pose.qw, + "qx": pose.qx, + "qy": pose.qy, + "qz": pose.qz, + "tx": pose.x, + "ty": pose.y, + "tz": pose.z, + }) + + # 写 cameras.txt + write_cameras_txt(os.path.join(colmapdir, "cameras.txt"), width, height, fx, fy, cx, cy) + # 写 images.txt + write_images_txt(os.path.join(colmapdir, "images.txt"), poses, img_names) + # 空的 points3D.txt + open(os.path.join(colmapdir, "points3D.txt"), 'w').close() + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--input-file", type=str, required=True) + parser.add_argument("--output-dir", type=str, required=True) + args = parser.parse_args() + main(args.input_file, args.output_dir) From bf526265a30f0d52ba4afba408cf3a5bb3e8aee0 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 13:45:42 +0800 Subject: [PATCH 05/31] add pixi, fix building bug --- CMakeLists.txt | 24 +- cmake/eigen.cmake | 3 +- cmake/ffmpeg_local.cmake | 6 + cmake/opencv_host.cmake | 31 +- pixi.lock | 1487 +++++++++++++++++++++++++ pixi.toml | 42 + scripts/build_ffmpeg.sh | 119 +- scripts/ffmpeg_b6f84cd7.patch | 8 +- src/spatialmp4/reader_test.cc | 24 +- src/spatialmp4/utilities/RgbdUtils.cc | 1 + src/spatialmp4/utils.cc | 30 +- src/spatialmp4/utils.h | 6 +- 12 files changed, 1728 insertions(+), 53 deletions(-) create mode 100644 pixi.lock create mode 100644 pixi.toml diff --git a/CMakeLists.txt b/CMakeLists.txt index 4caca80..014a228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,12 @@ configure_file( set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic-functions") set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) option(BUILD_ANDROID "whether build for android" OFF) option(BUILD_TESTING "whether build unit test" ON) -option(BUILD_PYTHON_BINDINGS "whether build python bindings" ON) +option(BUILD_PYTHON "whether build python bindings" ON) if(BUILD_ANDROID) message(FATAL_ERROR "Don't support android building.") @@ -32,7 +33,7 @@ include(cmake/fmt.cmake) include(cmake/eigen.cmake) include(cmake/sophus.cmake) -if(BUILD_PYTHON_BINDINGS) +if(BUILD_PYTHON) include(cmake/pybind11.cmake) endif() @@ -42,15 +43,26 @@ set(SRC ./src/spatialmp4/reader.cc ) -add_library(${CMAKE_PROJECT_NAME}_lib SHARED ${SRC}) +add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SRC}) +# if(APPLE) +# add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SRC}) +# else() +# add_library(${CMAKE_PROJECT_NAME}_lib SHARED ${SRC}) +# endif() + target_include_directories(${CMAKE_PROJECT_NAME}_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/include ) + +if(EXISTS $ENV{CONDA_PREFIX}/lib) + link_directories($ENV{CONDA_PREFIX}/lib) +endif() + target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC PkgConfig::LIBAV - lib_opencv + PkgConfig::OpenCV spdlog fmt::fmt Eigen3::Eigen @@ -59,7 +71,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC # On newer versions of macOS (>=10.15) and with newer compilers, # filesystem is part of the standard library and doesn't need explicit linking if(UNIX AND NOT APPLE) - target_link_libraries(${CMAKE_PROJECT_NAME}_static PRIVATE stdc++fs) + target_link_libraries(${CMAKE_PROJECT_NAME}_lib PRIVATE stdc++fs) endif() @@ -132,7 +144,7 @@ if(BUILD_TESTING) endif() endif() -if(BUILD_PYTHON_BINDINGS) +if(BUILD_PYTHON) add_subdirectory(bindings) endif() diff --git a/cmake/eigen.cmake b/cmake/eigen.cmake index 3e27fcd..8c66996 100644 --- a/cmake/eigen.cmake +++ b/cmake/eigen.cmake @@ -1,7 +1,8 @@ include(FetchContent) FetchContent_Declare( eigen - URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz + # URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz + URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz # URL /Users/bytedance/Downloads/eigen-3.3.7.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP true ) diff --git a/cmake/ffmpeg_local.cmake b/cmake/ffmpeg_local.cmake index 871dff5..1167fda 100644 --- a/cmake/ffmpeg_local.cmake +++ b/cmake/ffmpeg_local.cmake @@ -6,7 +6,13 @@ # 设置 PKG_CONFIG_PATH 环境变量 set(ffmpeg_HOME ${CMAKE_CURRENT_SOURCE_DIR}/scripts/build_ffmpeg/ffmpeg_install) +set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) +if(EXISTS "${PIXI_ROOT}") + set(ffmpeg_HOME "${PIXI_ROOT}") +endif() + set(ENV{PKG_CONFIG_PATH} "${ffmpeg_HOME}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") +set(ENV{PKG_CONFIG} "pkg-config --static") find_package(PkgConfig REQUIRED) pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET diff --git a/cmake/opencv_host.cmake b/cmake/opencv_host.cmake index c8bac1f..7fd4ff9 100644 --- a/cmake/opencv_host.cmake +++ b/cmake/opencv_host.cmake @@ -2,18 +2,29 @@ # >> include(cmake/opencv_host.cmake) # >> "Then you can add `lib_opencv` as link library name to your target." -find_package( OpenCV REQUIRED ) -add_compile_options(-std=c++11) -# find_package(PkgConfig) -# pkg_check_modules(OpenCV REQUIRED opencv>=2.4.9) -# set(OpenCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIRS} /usr/local/opencv_itseez/include/opencv2) +# set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) +# if(EXISTS "${PIXI_ROOT}") +# set(OpenCV_DIR ${CONDA_PREFIX}/share/opencv4) +# endif() +# set(OpenCV_STATIC ON) +# find_package( OpenCV REQUIRED ) +# add_compile_options(-std=c++11) +# include_directories(${OpenCV_INCLUDE_DIRS}) +# add_library(lib_opencv INTERFACE) +# target_link_libraries(lib_opencv INTERFACE ${OpenCV_LIBS}) +# set(OpenCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIRS}) # set(OpenCV_LIBS ${OpenCV_LIBRARIES}) -# LINK_DIRECTORIES(${OpenCV_LIBDIR}) +# LINK_DIRECTORIES(${OpenCV_LIBDIR}) -include_directories(${OpenCV_INCLUDE_DIRS}) -add_library(lib_opencv INTERFACE) -target_link_libraries(lib_opencv INTERFACE ${OpenCV_LIBS}) +set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) +if(EXISTS "${PIXI_ROOT}") + set(ENV{PKG_CONFIG_PATH} "${PIXI_ROOT}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") +endif() +set(ENV{PKG_CONFIG} "pkg-config --static") + +find_package(PkgConfig) +pkg_check_modules(OpenCV REQUIRED IMPORTED_TARGET opencv4) message(STATUS "OpenCV_INCLUDE_DIRS=${OpenCV_INCLUDE_DIRS}") -message(STATUS "OpenCV_LIBS=${OpenCV_LIBS}") +message(STATUS "OpenCV_LIBRARIES=${OpenCV_LIBRARIES}") \ No newline at end of file diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..1c4cdd7 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,1487 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.8-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.43-h4bf12b8_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.1.0-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.1.0-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.5-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.16.0-ha61ee94_1014.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.26.4-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.1.0-hc55bae6_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.14.2-h14ed4e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.12.1-h267a509_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.10-h36c2ea0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.1.0-h33e79ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.1.0-h4393ad2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.80.2-hf974151_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.80.2-hb6ce0ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.1.0-h33e79ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.1.0-h6a1bac1_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-4.4.1-hf9f4e7c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-70.1-h27087fc_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/jpeg-9e-h166bdaf_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.20.1-h81ceb04_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.14.0-hc2a3f6d_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-32_h59b9bed_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb9d3cd8_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-32_he106b2a_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.1.2-h409715c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.1.0-h4c094af_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h4ce23a2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-32_h7ac8fdf_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.5-hd0c01bc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.43-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.1.0-h97b714f_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.1.0-h4c094af_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.18.0-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h9c3ff4c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.13-h7f98852_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.0-h7aa8ee6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.1-h7b32b05_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.2-h29eaf8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.3-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h0157908_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.14.0-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-fixesproto-5.0-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.4-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-5.0.3-h7f98852_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.10-h7f98852_1003.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-renderproto-0.11.1-hb9d3cd8_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-hb9d3cd8_1004.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-hb9d3cd8_1008.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.8.1-hbcc6ac9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-gpl-tools-5.8.1-hbcc6ac9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + size: 2562 + timestamp: 1578324546067 +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + build_number: 16 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.8-h166bdaf_0.tar.bz2 + sha256: 2c0a618d0fa695e4e01a30e7ff31094be540c52e9085cbd724edb132c65cf9cd + md5: be733e69048951df1e4b4b7bb8c7666f + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + license_family: GPL + size: 592320 + timestamp: 1666699031168 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.43-h4bf12b8_5.conda + sha256: 27ae158d415ff2942214b32ac7952e642f0f4c2a45ab683691e2a9a9159f868c + md5: 18852d82df8e5737e320a8731ace51b9 + depends: + - ld_impl_linux-64 2.43 h712a8e2_5 + - sysroot_linux-64 + license: GPL-3.0-only + license_family: GPL + size: 6376971 + timestamp: 1749852878015 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.1.0-hb9d3cd8_3.conda + sha256: c969baaa5d7a21afb5ed4b8dd830f82b78e425caaa13d717766ed07a61630bec + md5: 5d08a0ac29e6a5a984817584775d4131 + depends: + - __glibc >=2.17,<3.0.a0 + - brotli-bin 1.1.0 hb9d3cd8_3 + - libbrotlidec 1.1.0 hb9d3cd8_3 + - libbrotlienc 1.1.0 hb9d3cd8_3 + - libgcc >=13 + license: MIT + license_family: MIT + size: 19810 + timestamp: 1749230148642 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.1.0-hb9d3cd8_3.conda + sha256: ab74fa8c3d1ca0a055226be89e99d6798c65053e2d2d3c6cb380c574972cd4a7 + md5: 58178ef8ba927229fba6d84abf62c108 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlidec 1.1.0 hb9d3cd8_3 + - libbrotlienc 1.1.0 hb9d3cd8_3 + - libgcc >=13 + license: MIT + license_family: MIT + size: 19390 + timestamp: 1749230137037 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda + sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d + md5: 62ee74e96c5ebb0af99386de58cf9553 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + license: bzip2-1.0.6 + license_family: BSD + size: 252783 + timestamp: 1720974456583 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.5-hb9d3cd8_0.conda + sha256: f8003bef369f57396593ccd03d08a8e21966157269426f71e943f96e4b579aeb + md5: f7f0d6cc2dc986d42ac2689ec88192be + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 206884 + timestamp: 1744127994291 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda + sha256: 7cfec9804c84844ea544d98bda1d9121672b66ff7149141b8415ca42dfcd44f6 + md5: 72525f07d72806e3b639ad4504c30ce5 + depends: + - __unix + license: ISC + size: 151069 + timestamp: 1749990087500 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.16.0-ha61ee94_1014.tar.bz2 + sha256: f062cf56e6e50d3ad4b425ebb3765ca9138c6ebc52e6a42d1377de8bc8d954f6 + md5: d1a88f3ed5b52e1024b80d4bcd26a7a0 + depends: + - fontconfig >=2.13.96,<3.0a0 + - fonts-conda-ecosystem + - freetype >=2.12.1,<3.0a0 + - icu >=70.1,<71.0a0 + - libgcc-ng >=12 + - libglib >=2.72.1,<3.0a0 + - libpng >=1.6.38,<1.7.0a0 + - libxcb >=1.13,<1.14.0a0 + - libzlib >=1.2.12,<2.0.0a0 + - pixman >=0.40.0,<1.0a0 + - xorg-libice + - xorg-libsm + - xorg-libx11 + - xorg-libxext + - xorg-libxrender + - zlib >=1.2.12,<1.3.0a0 + license: LGPL-2.1-only or MPL-1.1 + size: 1576122 + timestamp: 1663568213559 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.26.4-hcfe8598_0.conda + sha256: 37533b572a676017704c989c392998c344e889010786d6555dccdfc524a8e238 + md5: 1714cf0f0facaeb609a0846e4270aff2 + depends: + - bzip2 >=1.0.8,<2.0a0 + - expat + - libcurl >=8.1.0,<9.0a0 + - libexpat >=2.5.0,<3.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.3,<7.0a0 + - rhash <=1.4.3 + - xz >=5.2.6,<6.0a0 + - zlib + - zstd >=1.5.2,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 16343060 + timestamp: 1684460894541 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-15.1.0-hc55bae6_3.conda + sha256: d3206e920c44e1637c6b60366670cebd7872812812fba834dfadcc02aa76dad5 + md5: 907e04c7ccdecba6ff583022ade324d4 + depends: + - gcc_impl_linux-64 >=15.1.0,<15.1.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 33184 + timestamp: 1750808533112 +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda + sha256: ce61f4f99401a4bd455b89909153b40b9c823276aefcbb06f2044618696009ca + md5: 72e42d28960d875c7654614f8b50939a + depends: + - python >=3.9 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + size: 21284 + timestamp: 1746947398083 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.0-h5888daf_0.conda + sha256: dd5530ddddca93b17318838b97a2c9d7694fa4d57fc676cf0d06da649085e57a + md5: d6845ae4dea52a2f90178bf1829a21f8 + depends: + - __glibc >=2.17,<3.0.a0 + - libexpat 2.7.0 h5888daf_0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 140050 + timestamp: 1743431809745 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b + md5: 0c96522c6bdaed4b1566d11387caaf45 + license: BSD-3-Clause + license_family: BSD + size: 397370 + timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c + md5: 34893075a5c9e55cdafac56607368fc6 + license: OFL-1.1 + license_family: Other + size: 96530 + timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 + md5: 4d59c254e01d9cde7957100457e2d5fb + license: OFL-1.1 + license_family: Other + size: 700814 + timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 + md5: 49023d73832ef61042f6a237cb2687e7 + license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 + license_family: Other + size: 1620504 + timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.14.2-h14ed4e7_0.conda + sha256: 155d534c9037347ea7439a2c6da7c24ffec8e5dd278889b4c57274a1d91e0a83 + md5: 0f69b688f52ff6da70bccb7ff7001d1d + depends: + - expat >=2.5.0,<3.0a0 + - freetype >=2.12.1,<3.0a0 + - libgcc-ng >=12 + - libuuid >=2.32.1,<3.0a0 + - libzlib >=1.2.13,<2.0.0a0 + license: MIT + license_family: MIT + size: 272010 + timestamp: 1674828850194 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 + md5: fee5683a3f04bd15cbd8318b096a27ab + depends: + - fonts-conda-forge + license: BSD-3-Clause + license_family: BSD + size: 3667 + timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + sha256: 53f23a3319466053818540bcdf2091f253cbdbab1e0e9ae7b9e509dcaa2a5e38 + md5: f766549260d6815b0c52253f1fb1bb29 + depends: + - font-ttf-dejavu-sans-mono + - font-ttf-inconsolata + - font-ttf-source-code-pro + - font-ttf-ubuntu + license: BSD-3-Clause + license_family: BSD + size: 4102 + timestamp: 1566932280397 +- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.12.1-h267a509_2.conda + sha256: b2e3c449ec9d907dd4656cb0dc93e140f447175b125a3824b31368b06c666bb6 + md5: 9ae35c3d96db2c94ce0cef86efdfa2cb + depends: + - libgcc-ng >=12 + - libpng >=1.6.39,<1.7.0a0 + - libzlib >=1.2.13,<2.0.0a0 + license: GPL-2.0-only OR FTL + size: 634972 + timestamp: 1694615932610 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.10-h36c2ea0_0.tar.bz2 + sha256: 5d7b6c0ee7743ba41399e9e05a58ccc1cfc903942e49ff6f677f6e423ea7a627 + md5: ac7bc6a654f8f41b352b38f4051135f8 + depends: + - libgcc-ng >=7.5.0 + license: LGPL-2.1 + size: 114383 + timestamp: 1604416621168 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.1.0-h33e79ad_3.conda + sha256: 69cc03e5b20e064ad5a9ac88ac3b792a1b089c838fa4ab5eb56990a9c166ce5a + md5: 45ddc7242fed76e1b4ff5ee062e6d926 + depends: + - conda-gcc-specs + - gcc_impl_linux-64 15.1.0.* + license: BSD-3-Clause + license_family: BSD + size: 30820 + timestamp: 1750808688614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-15.1.0-h4393ad2_3.conda + sha256: fed91c71f8e7b3f0970f883c589d7dd74a3503b7020d0be273cea301a64ee3af + md5: f39f96280dd8b1ec8cbd395a3d3fdd1e + depends: + - binutils_impl_linux-64 >=2.40 + - libgcc >=15.1.0 + - libgcc-devel_linux-64 15.1.0 h4c094af_103 + - libgomp >=15.1.0 + - libsanitizer 15.1.0 h97b714f_3 + - libstdcxx >=15.1.0 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 76098052 + timestamp: 1750808341511 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.80.2-hf974151_0.conda + sha256: d10a0f194d2c125617352a81a4ff43a17cf5835e88e8f151da9f9710e2db176d + md5: d427988dc3dbd0a4c136f52db356cc6a + depends: + - glib-tools 2.80.2 hb6ce0ca_0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libglib 2.80.2 hf974151_0 + - python * + license: LGPL-2.1-or-later + size: 600389 + timestamp: 1715252749399 +- conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.80.2-hb6ce0ca_0.conda + sha256: 221cd047f998301b96b1517d9f7d3fb0e459e8ee18778a1211f302496f6e110d + md5: a965aeaf060289528a3fbe09326edae2 + depends: + - libgcc-ng >=12 + - libglib 2.80.2 hf974151_0 + license: LGPL-2.1-or-later + size: 114359 + timestamp: 1715252713902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-h5888daf_0.conda + sha256: cac69f3ff7756912bbed4c28363de94f545856b35033c0b86193366b95f5317d + md5: 951ff8d9e5536896408e89d63230b8d5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: LGPL-2.0-or-later + license_family: LGPL + size: 98419 + timestamp: 1750079957535 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.1.0-h33e79ad_3.conda + sha256: b071ff43b64e9c8366411f1d2a8030fb9769c0c588ffa6e16a498957dba96f45 + md5: 5917fb5bed3e2fa4fce4fbbe1b541946 + depends: + - gcc 15.1.0.* + - gxx_impl_linux-64 15.1.0.* + license: BSD-3-Clause + license_family: BSD + size: 30268 + timestamp: 1750808715356 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-15.1.0-h6a1bac1_3.conda + sha256: 8208b77f3d97f2ce5722f1c5623b829caabe5859e30c2a49417a26405bcbc12a + md5: d71cc504fcfdbee8dd7925ebb9c2bf85 + depends: + - gcc_impl_linux-64 15.1.0 h4393ad2_3 + - libstdcxx-devel_linux-64 15.1.0 h4c094af_103 + - sysroot_linux-64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 15489397 + timestamp: 1750808654357 +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-4.4.1-hf9f4e7c_0.tar.bz2 + sha256: d9ca0d32a771554a06406bbf6ab8f41b5d5899e1de46a54c23fe575753f80223 + md5: ac83998fdc71721da8c8f0846a25a503 + depends: + - cairo >=1.16.0,<2.0.0a0 + - freetype >=2.10.4,<3.0a0 + - graphite2 + - icu >=70.1,<71.0a0 + - libgcc-ng >=12 + - libglib >=2.70.2,<3.0a0 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + size: 2096772 + timestamp: 1656503454174 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-70.1-h27087fc_0.tar.bz2 + sha256: 1d7950f3be4637ab915d886304e57731d39a41ab705ffc95c4681655c459374a + md5: 87473a15119779e021c314249d4b4aed + depends: + - libgcc-ng >=10.3.0 + - libstdcxx-ng >=10.3.0 + license: MIT + license_family: MIT + size: 14191488 + timestamp: 1648050221778 +- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + sha256: 0ec8f4d02053cd03b0f3e63168316530949484f80e16f5e2fb199a1d117a89ca + md5: 6837f3eff7dcea42ecd714ce1ac2b108 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 11474 + timestamp: 1733223232820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/jpeg-9e-h166bdaf_2.tar.bz2 + sha256: 0110ee167e8fe386f9019f98757e299a0c42dc6ccdcce161c9bb552b79e459a3 + md5: ee8b844357a0946870901c7c6f418268 + depends: + - libgcc-ng >=12 + license: IJG + size: 275125 + timestamp: 1656500806614 +- conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda + sha256: a922841ad80bd7b222502e65c07ecb67e4176c4fa5b03678a005f39fcc98be4b + md5: ad8527bf134a90e1c9ed35fa0b64318c + constrains: + - sysroot_linux-64 ==2.17 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 943486 + timestamp: 1729794504440 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + sha256: 150c05a6e538610ca7c43beb3a40d65c90537497a4f6a5f4d15ec0451b6f5ebb + md5: 30186d27e2c9fa62b45fb1476b7200e3 + depends: + - libgcc-ng >=10.3.0 + license: LGPL-2.1-or-later + size: 117831 + timestamp: 1646151697040 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.20.1-h81ceb04_0.conda + sha256: 51a346807ce981e1450eb04c3566415b05eed705bc9e6c98c198ec62367b7c62 + md5: 89a41adce7106749573d883b2f657d78 + depends: + - keyutils >=1.6.1,<2.0a0 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - openssl >=3.0.7,<4.0a0 + license: MIT + license_family: MIT + size: 1329877 + timestamp: 1671091750695 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_5.conda + sha256: de097284f497b391fe9d000c75b684583c30aad172d9508ed05df23ce39d75cb + md5: acd9213a63cb62521290e581ef82de80 + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - binutils_impl_linux-64 2.43 + license: GPL-3.0-only + license_family: GPL + size: 670525 + timestamp: 1749852860076 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.14.0-hc2a3f6d_3.tar.bz2 + sha256: dc20ef020b864cc034e117aba344cb9893084b776bcec89599b820dde18abedc + md5: 78e21631f18d404594bf51c2a8cfede7 + depends: + - expat >=2.4.7,<3.0a0 + - fontconfig >=2.13.96,<3.0a0 + - fonts-conda-ecosystem + - freetype >=2.10.4,<3.0a0 + - fribidi >=1.0.10,<2.0a0 + - harfbuzz >=4.0.1,<5.0a0 + - libgcc-ng >=10.3.0 + - libzlib >=1.2.11,<2.0.0a0 + license: ISC + license_family: OTHER + size: 122389 + timestamp: 1647824984482 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-32_h59b9bed_openblas.conda + build_number: 32 + sha256: 1540bf739feb446ff71163923e7f044e867d163c50b605c8b421c55ff39aa338 + md5: 2af9f3d5c2e39f417ce040f5a35c40c6 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - libcblas 3.9.0 32*_openblas + - mkl <2025 + - liblapacke 3.9.0 32*_openblas + - blas 2.132 openblas + - liblapack 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17330 + timestamp: 1750388798074 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hb9d3cd8_3.conda + sha256: 462a8ed6a7bb9c5af829ec4b90aab322f8bcd9d8987f793e6986ea873bbd05cf + md5: cb98af5db26e3f482bebb80ce9d947d3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 69233 + timestamp: 1749230099545 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hb9d3cd8_3.conda + sha256: 3eb27c1a589cbfd83731be7c3f19d6d679c7a444c3ba19db6ad8bf49172f3d83 + md5: 1c6eecffad553bde44c5238770cfb7da + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.1.0 hb9d3cd8_3 + - libgcc >=13 + license: MIT + license_family: MIT + size: 33148 + timestamp: 1749230111397 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb9d3cd8_3.conda + sha256: 76e8492b0b0a0d222bfd6081cae30612aa9915e4309396fdca936528ccf314b7 + md5: 3facafe58f3858eb95527c7d3a3fc578 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.1.0 hb9d3cd8_3 + - libgcc >=13 + license: MIT + license_family: MIT + size: 282657 + timestamp: 1749230124839 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-32_he106b2a_openblas.conda + build_number: 32 + sha256: 92a001fc181e6abe4f4a672b81d9413ca2f22609f8a95327dfcc6eee593ffeb9 + md5: 3d3f9355e52f269cd8bc2c440d8a5263 + depends: + - libblas 3.9.0 32_h59b9bed_openblas + constrains: + - blas 2.132 openblas + - liblapack 3.9.0 32*_openblas + - liblapacke 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17308 + timestamp: 1750388809353 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.1.2-h409715c_0.conda + sha256: d572c31ff48d2db6ca5bab476bf325811cfc82577480b3791487c3fe7bff2ffa + md5: 50c873c9660ed116707ae15b663928d8 + depends: + - krb5 >=1.20.1,<1.21.0a0 + - libgcc-ng >=12 + - libnghttp2 >=1.52.0,<2.0a0 + - libssh2 >=1.10.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.0,<4.0a0 + - zstd >=1.5.2,<1.6.0a0 + license: curl + license_family: MIT + size: 372833 + timestamp: 1685447685782 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb9d3cd8_0.conda + sha256: f53458db897b93b4a81a6dbfd7915ed8fa4a54951f97c698dde6faa028aadfd2 + md5: 4c0ab57463117fbb8df85268415082f5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libpciaccess >=0.18,<0.19.0a0 + license: MIT + license_family: MIT + size: 246161 + timestamp: 1749904704373 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + size: 112766 + timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.0-h5888daf_0.conda + sha256: 33ab03438aee65d6aa667cf7d90c91e5e7d734c19a67aa4c7040742c0a13d505 + md5: db0bfbe7dd197b68ad5f30333bae6ce0 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + constrains: + - expat 2.7.0.* + license: MIT + license_family: MIT + size: 74427 + timestamp: 1743431794976 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda + sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab + md5: ede4673863426c0883c0063d853bbd85 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 57433 + timestamp: 1743434498161 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda + sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 + md5: 9e60c55e725c20d23125a5f0dd69af5d + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.1.0=*_3 + - libgomp 15.1.0 h767d61c_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 824921 + timestamp: 1750808216066 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-15.1.0-h4c094af_103.conda + sha256: 770a59a79f83dbd8ada4565b08633b429c0c54040b2b1f78c4db4648c7c7a805 + md5: ea67e87d658d31dc33818f9574563269 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 2728790 + timestamp: 1750808123770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_3.conda + sha256: b0b0a5ee6ce645a09578fc1cb70c180723346f8a45fdb6d23b3520591c6d6996 + md5: e66f2b8ad787e7beb0f846e4bd7e8493 + depends: + - libgcc 15.1.0 h767d61c_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29033 + timestamp: 1750808224854 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_3.conda + sha256: 77dd1f1efd327e6991e87f09c7c97c4ae1cfbe59d9485c41d339d6391ac9c183 + md5: bfbca721fd33188ef923dfe9ba172f29 + depends: + - libgfortran5 15.1.0 hcea5267_3 + constrains: + - libgfortran-ng ==15.1.0=*_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29057 + timestamp: 1750808257258 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda + sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a + md5: 530566b68c3b8ce7eec4cd047eae19fe + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.1.0 + constrains: + - libgfortran 15.1.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 1565627 + timestamp: 1750808236464 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda + sha256: 93e03b6cf4765bc06d64fa3dac65f22c53ae4a30247bb0e2dea0bd9c47a3fb26 + md5: 72724f6a78ecb15559396966226d5838 + depends: + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - pcre2 >=10.43,<10.44.0a0 + constrains: + - glib 2.80.2 *_0 + license: LGPL-2.1-or-later + size: 3912673 + timestamp: 1715252654366 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_3.conda + sha256: 43710ab4de0cd7ff8467abff8d11e7bb0e36569df04ce1c099d48601818f11d1 + md5: 3cd1a7238a0dd3d0860fdefc496cc854 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 447068 + timestamp: 1750808138400 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h4ce23a2_1.conda + sha256: 18a4afe14f731bfb9cf388659994263904d20111e42f841e9eea1bb6f91f4ab4 + md5: e796ff8ddc598affdf7c173d6145f087 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + size: 713084 + timestamp: 1740128065462 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 + sha256: 0d8b666ca4deabf948a76654df0fa1277145bed1c9e8a58e18a649c22c5f1c3e + md5: b4f717df2d377410b462328bf0e8fb7d + depends: + - libgcc-ng >=12 + license: IJG, modified 3-clause BSD and zlib + size: 1011471 + timestamp: 1664781971968 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-32_h7ac8fdf_openblas.conda + build_number: 32 + sha256: 5b55a30ed1b3f8195dad9020fe1c6d0f514829bfaaf0cf5e393e93682af009f2 + md5: 6c3f04ccb6c578138e9f9899da0bd714 + depends: + - libblas 3.9.0 32_h59b9bed_openblas + constrains: + - libcblas 3.9.0 32*_openblas + - blas 2.132 openblas + - liblapacke 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17316 + timestamp: 1750388820745 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda + sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8 + md5: 1a580f7796c7bf6393fddb8bbbde58dc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + constrains: + - xz 5.8.1.* + license: 0BSD + size: 112894 + timestamp: 1749230047870 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda + sha256: 329e66330a8f9cbb6a8d5995005478188eb4ba8a6b6391affa849744f4968492 + md5: f61edadbb301530bd65a32646bd81552 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - liblzma 5.8.1 hb9d3cd8_2 + license: 0BSD + size: 439868 + timestamp: 1749230061968 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_0.conda + sha256: 151b18e4f92dcca263a6d23e4beb0c4e2287aa1c7d0587ff71ef50035ed34aca + md5: 9b13d5ee90fc9f09d54fd403247342b4 + depends: + - c-ares >=1.21.0,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.4,<4.0a0 + license: MIT + license_family: MIT + size: 631397 + timestamp: 1699440427647 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.5-hd0c01bc_1.conda + sha256: ffb066ddf2e76953f92e06677021c73c85536098f1c21fcd15360dbc859e22e4 + md5: 68e52064ed3897463c0e958ab5c8f91b + depends: + - libgcc >=13 + - __glibc >=2.17,<3.0.a0 + license: BSD-3-Clause + license_family: BSD + size: 218500 + timestamp: 1745825989535 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_0.conda + sha256: 225f4cfdb06b3b73f870ad86f00f49a9ca0a8a2d2afe59440521fafe2b6c23d9 + md5: 323dc8f259224d13078aaf7ce96c3efe + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + size: 5916819 + timestamp: 1750379877844 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda + sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2 + md5: 70e3400cbbfa03e96dcde7fc13e38c7b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 28424 + timestamp: 1749901812541 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.43-h2797004_0.conda + sha256: 502f6ff148ac2777cc55ae4ade01a8fc3543b4ffab25c4e0eaa15f94e90dd997 + md5: 009981dd9cfcaa4dbfa25ffaed86bcae + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: zlib-acknowledgement + size: 288221 + timestamp: 1708780443939 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.1.0-h97b714f_3.conda + sha256: 75fa45d8ea2344bfe96667b478fd00f1d038026f399cb680eceec836c90e67bc + md5: bbcff9bf972a0437bea8e431e4b327bb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.1.0 + - libstdcxx >=15.1.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 5224736 + timestamp: 1750808272292 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + sha256: daee3f68786231dad457d0dfde3f7f1f9a7f2018adabdbb864226775101341a8 + md5: 18aa975d2094c34aef978060ae7da7d8 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0a0 + license: Unlicense + size: 865346 + timestamp: 1718050628718 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + sha256: 50e47fd9c4f7bf841a11647ae7486f65220cfc988ec422a4475fe8d5a823824d + md5: 1f5a58e686b13bcfde88b93f547d23fe + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 271133 + timestamp: 1685837707056 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda + sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 + md5: 6d11a5edae89fe413c0569f16d308f5a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.1.0 h767d61c_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3896407 + timestamp: 1750808251302 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-15.1.0-h4c094af_103.conda + sha256: 3b68242567a104738d6902629e7485a9636e262c66a681e93c0a058656f1b8a3 + md5: 83bbc814f0aeccccb5ea10267bea0d2e + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 14743289 + timestamp: 1750808154361 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_3.conda + sha256: bbaea1ecf973a7836f92b8ebecc94d3c758414f4de39d2cc6818a3d10cb3216b + md5: 57541755b5a51691955012b8e197c06c + depends: + - libstdcxx 15.1.0 h8f9b012_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 29093 + timestamp: 1750808292700 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18 + md5: 40b61aab5c7ba9ff276c41cfffe6b80b + depends: + - libgcc-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 33601 + timestamp: 1680112270483 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb9d3cd8_0.conda + sha256: 770ca175d64323976c9fe4303042126b2b01c1bd54c8c96cafeaba81bdb481b8 + md5: 1349c022c92c5efd3fd705a79a5804d8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 890145 + timestamp: 1748304699136 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.18.0-h0b41bf4_0.conda + sha256: e7254d0111a403ffe707e2ad39b6ce49a2be733e751d14a7255b0cb20da2a16b + md5: 56e049224de34bbe0478aad422227942 + depends: + - libdrm >=2.4.114,<2.5.0a0 + - libgcc-ng >=12 + - xorg-libx11 >=1.8.4,<2.0a0 + - xorg-libxext >=1.3.4,<2.0a0 + - xorg-libxfixes + license: MIT + license_family: MIT + size: 186715 + timestamp: 1679400122269 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h9c3ff4c_0.tar.bz2 + sha256: 53080d72388a57b3c31ad5805c93a7328e46ff22fab7c44ad2a86d712740af33 + md5: 309dec04b70a3cc0f1e84a4013683bc0 + depends: + - libgcc-ng >=9.3.0 + - libogg >=1.3.4,<1.4.0a0 + - libstdcxx-ng >=9.3.0 + license: BSD-3-Clause + license_family: BSD + size: 286280 + timestamp: 1610609811627 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.13-h7f98852_1004.tar.bz2 + sha256: 8d5d24cbeda9282dd707edd3156e5fde2e3f3fe86c802fa7ce08c8f1e803bfd9 + md5: b3653fdc58d03face9724f602218a904 + depends: + - libgcc-ng >=9.4.0 + - pthread-stubs + - xorg-libxau + - xorg-libxdmcp + license: MIT + license_family: MIT + size: 399895 + timestamp: 1636658924671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + size: 100393 + timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda + sha256: 8ced4afed6322172182af503f21725d072a589a6eb918f8a58135c1e00d35980 + md5: 27329162c0dc732bcf67a4e0cd488125 + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.2.13 *_6 + license: Zlib + license_family: Other + size: 61571 + timestamp: 1716874066944 +- conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda + sha256: d652c7bd4d3b6f82b0f6d063b0d8df6f54cc47531092d7ff008e780f3261bdda + md5: 33405d2a66b1411db9f7242c8b97c9e7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: GPL-3.0-or-later + license_family: GPL + size: 513088 + timestamp: 1727801714848 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: X11 AND BSD-3-Clause + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.0-h7aa8ee6_0.conda + sha256: 8cf09470430b5aba5165c7aefed070d2c8f998f69fede01197ef838bf17fa81a + md5: 2f67cb5c5ec172faeba94348ae8af444 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=13 + - libgcc >=13 + license: Apache-2.0 + license_family: APACHE + size: 180917 + timestamp: 1750273173789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 + md5: d8285bea2a350f63fab23bf460221f3f + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + size: 7484186 + timestamp: 1707225809722 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.1-h7b32b05_0.conda + sha256: 942347492164190559e995930adcdf84e2fea05307ec8012c02a505f5be87462 + md5: c87df2ab1448ba69169652ab9547082d + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=13 + license: Apache-2.0 + license_family: Apache + size: 3131002 + timestamp: 1751390382076 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 + md5: 58335b26c38bf4a20f399384c33cbcf9 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + size: 62477 + timestamp: 1745345660407 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 + sha256: 8f35c244b1631a4f31fb1d66ab6e1d9bfac0ca9b679deced1112c7225b3ad138 + md5: c05d1820a6d34ff07aaaab7a9b7eddaa + depends: + - libgcc-ng >=9.3.0 + - libstdcxx-ng >=9.3.0 + license: BSD-3-Clause + license_family: BSD + size: 259377 + timestamp: 1623788789327 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda + sha256: 766dd986a7ed6197676c14699000bba2625fd26c8a890fcb7a810e5cf56155bc + md5: 8292dea9e022d9610a11fce5e0896ed8 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 950847 + timestamp: 1708118050286 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.2-h29eaf8c_0.conda + sha256: 6cb261595b5f0ae7306599f2bb55ef6863534b6d4d1bc0dcfdfa5825b0e4e53d + md5: 39b4228a867772d610c02e06f939a5b8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: MIT + license_family: MIT + size: 402222 + timestamp: 1749552884791 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda + sha256: c9601efb1af5391317e04eca77c6fe4d716bf1ca1ad8da2a05d15cb7c28d7d4e + md5: 1bee70681f504ea424fb07cdb090c001 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + license: GPL-2.0-or-later + license_family: GPL + size: 115175 + timestamp: 1720805894943 +- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda + sha256: a8eb555eef5063bbb7ba06a379fa7ea714f57d9741fe0efdb9442dbbc2cccbcc + md5: 7da7ccd349dbf6487a7778579d2bb971 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 24246 + timestamp: 1747339794916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda + sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 + md5: b3c17d95b5a10c6e64a21fa17573e70e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 8252 + timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a + md5: 6b6ece66ebcae2d5f326c77ef2c5a066 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + size: 889287 + timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda + sha256: 93e267e4ec35353e81df707938a6527d5eb55c97bf54c3b87229b69523afb59d + md5: a49c2283f24696a7b30367b7346a0144 + depends: + - colorama >=0.4 + - exceptiongroup >=1 + - iniconfig >=1 + - packaging >=20 + - pluggy >=1.5,<2 + - pygments >=2.7.2 + - python >=3.9 + - tomli >=1 + constrains: + - pytest-faulthandler >=2 + license: MIT + license_family: MIT + size: 276562 + timestamp: 1750239526127 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + sha256: f9865bcbff69f15fd89a33a2da12ad616e98d65ce7c83c644b92e66e5016b227 + md5: 2540b74d304f71d3e89c81209db4db84 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 31991381 + timestamp: 1713208036041 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda + build_number: 7 + sha256: a1bbced35e0df66cc713105344263570e835625c28d1bdee8f748f482b2d7793 + md5: 0dfcdc155cf23812a0c9deada86fb723 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6971 + timestamp: 1745258861359 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda + sha256: 2d6d0c026902561ed77cd646b5021aef2d4db22e57a5b0178dfc669231e06d2c + md5: 283b96675859b20a825f8fa30f311446 + depends: + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 282480 + timestamp: 1740379431762 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.3-hd590300_2.conda + sha256: 475f68cac8981ff2b10c56e53c2f376fc3c805fbc7ec30d22f870cd88f1479ba + md5: 4cabe3858a856bff08d9a0992e413084 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 184509 + timestamp: 1693427593121 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 + md5: 4de79c071274a53dcaf2a8c749d1499e + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 748788 + timestamp: 1748804951958 +- conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h0157908_18.conda + sha256: 69ab5804bdd2e8e493d5709eebff382a72fab3e9af6adf93a237ccf8f7dbd624 + md5: 460eba7851277ec1fd80a1a24080787a + depends: + - kernel-headers_linux-64 3.10.0 he073ed8_18 + - tzdata + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 15166921 + timestamp: 1735290488259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e + md5: d453b98d9c83e71da0741bb0ff4d76bc + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + size: 3318875 + timestamp: 1699202167581 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda + sha256: 18636339a79656962723077df9a56c0ac7b8a864329eb8f847ee3d38495b863e + md5: ac944244f1fed2eb49bae07193ae8215 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 19167 + timestamp: 1733256819729 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.14.0-pyhe01879c_0.conda + sha256: 8561db52f278c5716b436da6d4ee5521712a49e8f3c70fcae5350f5ebb4be41c + md5: 2adcd9bb86f656d3d43bf84af59a1faf + depends: + - python >=3.9 + - python + license: PSF-2.0 + license_family: PSF + size: 50978 + timestamp: 1748959427551 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + sha256: 5aaa366385d716557e365f0a4e9c3fca43ba196872abbbe3d56bb610d131e192 + md5: 4222072737ccff51314b5ece9c7d6f5a + license: LicenseRef-Public-Domain + size: 122968 + timestamp: 1742727099393 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-fixesproto-5.0-hb9d3cd8_1003.conda + sha256: 07268980b659a84a4bac64b475329348e9cf5fa4aee255fa94aa0407ae5b804c + md5: 19fe37721037acc0a1ed76b8cf937359 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - xorg-xextproto >=7.3.0,<8.0a0 + license: MIT + license_family: MIT + size: 11311 + timestamp: 1727033761080 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-hb9d3cd8_1003.conda + sha256: 849555ddf7fee334a5a6be9f159d2931c9d076ffb310a9e75b9124f789049d3e + md5: e87bfacb110d85e1eb6099c9ed8e7236 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 30242 + timestamp: 1726846706299 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda + sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b + md5: fb901ff28063514abb6046c9ec2c4a45 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 58628 + timestamp: 1734227592886 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda + sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 + md5: 1c74ff8c35dcadf952a16f752ca5aa49 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libuuid >=2.38.1,<3.0a0 + - xorg-libice >=1.1.2,<2.0a0 + license: MIT + license_family: MIT + size: 27590 + timestamp: 1741896361728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.4-h0b41bf4_0.conda + sha256: 3c6862a01a39cdea3870b132706ad7256824299947a3a94ae361d863d402d704 + md5: ea8fbfeb976ac49cbeb594e985393514 + depends: + - libgcc-ng >=12 + - libxcb 1.* + - libxcb >=1.13,<1.14.0a0 + - xorg-kbproto + - xorg-xextproto >=7.3.0,<8.0a0 + - xorg-xproto + license: MIT + license_family: MIT + size: 829872 + timestamp: 1677611125385 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda + sha256: ed10c9283974d311855ae08a16dfd7e56241fac632aec3b92e3cfe73cff31038 + md5: f6ebe2cb3f82ba6c057dde5d9debe4f7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 14780 + timestamp: 1734229004433 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda + sha256: 6b250f3e59db07c2514057944a3ea2044d6a8cdde8a47b6497c254520fade1ee + md5: 8035c64cb77ed555e3f150b7b3972480 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 19901 + timestamp: 1727794976192 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda + sha256: 73e5cfbdff41ef8a844441f884412aa5a585a0f0632ec901da035a03e1fe1249 + md5: 82b6df12252e6f32402b96dacc656fec + depends: + - libgcc-ng >=12 + - xorg-libx11 >=1.7.2,<2.0a0 + - xorg-xextproto + license: MIT + license_family: MIT + size: 50143 + timestamp: 1677036907815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-5.0.3-h7f98852_1004.tar.bz2 + sha256: 1e426a1abb774ef1dcf741945ed5c42ad12ea2dc7aeed7682d293879c3e1e4c3 + md5: e9a21aa4d5e3e5f1aed71e8cefd46b6a + depends: + - libgcc-ng >=9.3.0 + - xorg-fixesproto + - xorg-libx11 >=1.7.0,<2.0a0 + license: MIT + license_family: MIT + size: 18145 + timestamp: 1617717802636 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.10-h7f98852_1003.tar.bz2 + sha256: 7d907ed9e2ec5af5d7498fb3ab744accc298914ae31497ab6dcc6ef8bd134d00 + md5: f59c1242cc1dd93e72c2ee2b360979eb + depends: + - libgcc-ng >=9.3.0 + - xorg-libx11 >=1.7.0,<2.0a0 + - xorg-renderproto + license: MIT + license_family: MIT + size: 32906 + timestamp: 1614866792944 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-renderproto-0.11.1-hb9d3cd8_1003.conda + sha256: 54dd934b0e1c942e54759eb13672fd59b7e523fabea6e69a32d5bf483e45b329 + md5: bf90782559bce8447609933a7d45995a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 11867 + timestamp: 1726802820431 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-hb9d3cd8_1004.conda + sha256: f302a3f6284ee9ad3b39e45251d7ed15167896564dc33e006077a896fd3458a6 + md5: bc4cd53a083b6720d61a1519a1900878 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 30549 + timestamp: 1726846235301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-hb9d3cd8_1008.conda + sha256: ea02425c898d6694167952794e9a865e02e14e9c844efb067374f90b9ce8ce33 + md5: a63f5b66876bb1ec734ab4bdc4d11e86 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + size: 73315 + timestamp: 1726845753874 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.8.1-hbcc6ac9_2.conda + sha256: 802725371682ea06053971db5b4fb7fbbcaee9cb1804ec688f55e51d74660617 + md5: 68eae977d7d1196d32b636a026dc015d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - liblzma 5.8.1 hb9d3cd8_2 + - liblzma-devel 5.8.1 hb9d3cd8_2 + - xz-gpl-tools 5.8.1 hbcc6ac9_2 + - xz-tools 5.8.1 hb9d3cd8_2 + license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later + size: 23987 + timestamp: 1749230104359 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-gpl-tools-5.8.1-hbcc6ac9_2.conda + sha256: 840838dca829ec53f1160f3fca6dbfc43f2388b85f15d3e867e69109b168b87b + md5: bf627c16aa26231720af037a2709ab09 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - liblzma 5.8.1 hb9d3cd8_2 + constrains: + - xz 5.8.1.* + license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later + size: 33911 + timestamp: 1749230090353 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.1-hb9d3cd8_2.conda + sha256: 58034f3fca491075c14e61568ad8b25de00cb3ae479de3e69be6d7ee5d3ace28 + md5: 1bad2995c8f1c8075c6c331bf96e46fb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - liblzma 5.8.1 hb9d3cd8_2 + constrains: + - xz 5.8.1.* + license: 0BSD AND LGPL-2.1-or-later + size: 96433 + timestamp: 1749230076687 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda + sha256: 534824ea44939f3e59ca8ebb95e3ece6f50f9d2a0e69999fbc692311252ed6ac + md5: 559d338a4234c2ad6e676f460a093e67 + depends: + - libgcc-ng >=12 + - libzlib 1.2.13 h4ab18f5_6 + license: Zlib + license_family: Other + size: 92883 + timestamp: 1716874088980 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + sha256: c558b9cc01d9c1444031bd1ce4b9cff86f9085765f17627a6cd85fc623c8a02b + md5: 4d056880988120e29d75bfff282e0f45 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + size: 554846 + timestamp: 1714722996770 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..c53510a --- /dev/null +++ b/pixi.toml @@ -0,0 +1,42 @@ +[project] +name = "spatialmp4" +channels = ["conda-forge"] +platforms = ["linux-64"] + +[tasks] +build-ffmpeg = "bash scripts/build_ffmpeg.sh" +build = "cmake -G Ninja -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -B build -S . && cmake --build build" +rebuild = "rm -rf build; cmake -B build -S . && cmake --build build" +test = "cd build && VIDEO=../video/test.mp4 ./test_reader" +test-python = "pytest -s python/tests" + +[dependencies] +cmake = ">=3.24.1,<4.0" +ninja = ">=1.13.0,<2" +make = "*" +pkg-config = "*" +gcc = "*" +gxx = "*" +zlib = "*" +libpng = ">=1.6.43,<2" +libjpeg-turbo = "*" +freetype = "*" +harfbuzz = "*" +libuuid = "*" +libdrm = "*" +libxcb = "*" +libva = "*" +libass = "*" +fontconfig = "*" +expat = "*" +glib = "*" +pcre = "*" +graphite2 = "*" +fribidi = "*" +brotli = "*" +alsa-lib = "*" +pytest = ">=8.4.1,<9" +setuptools = ">=80.9.0,<81" +jpeg = ">=9e,<10a" +libvorbis = ">=1.3.7,<2" +numpy = "<2.0" diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh index 677cf7d..cb113a1 100755 --- a/scripts/build_ffmpeg.sh +++ b/scripts/build_ffmpeg.sh @@ -7,10 +7,27 @@ cur=$(dirname $_curfile) opt=$cur/build_ffmpeg INSTALL_PREFIX=$opt/ffmpeg_install +PIXI_ROOT=$cur/../.pixi/envs/default +CMAKE_EXTRA_CONFIG="" +if [ -d $PIXI_ROOT ];then + INSTALL_PREFIX=$PIXI_ROOT + CMAKE_EXTRA_CONFIG="-DCMAKE_INCLUDE_PATH=${PIXI_ROOT}/include" +fi +echo "INSTALL_PREFIX: $INSTALL_PREFIX" + if [ ! -d $opt ];then mkdir -p $opt fi +if [[ "$(uname)" == "Darwin" ]];then + make_args="-j$(sysctl -n hw.ncpu)" +elif [[ "$(uname)" == "Linux" ]]; then + make_args="-j$(nproc)" +else + echo "Not supported windows." + exit 1 +fi + install_deps() { if [[ "$(uname)" == "Darwin" ]];then # https://trac.ffmpeg.org/wiki/CompilationGuide/macOS @@ -62,28 +79,110 @@ build_install_ffmpeg() { # Clean previous build make distclean || true + + # EXTRA_CONFIG="--enable-shared --disable-static" + EXTRA_CONFIG="--enable-static --disable-shared --enable-pic --disable-x86asm --disable-asm" + + # if [[ "$(uname)" == "Darwin" ]];then + # EXTRA_CONFIG="--enable-shared --disable-static" + # else + # EXTRA_CONFIG="--enable-static --disable-shared --pkg-config-flags='--static'" + # fi # Configure with enhanced PIC support + + export CFLAGS="-fPIC" + export CXXFLAGS="-fPIC" + export ASFLAGS="-DPIC" ./configure \ - --disable-doc \ --prefix=$INSTALL_PREFIX \ - --pkg-config-flags="--static" \ - --enable-pic \ - --enable-static \ - --extra-cflags="-I/usr/local/include -fPIC -fPIE" \ - --extra-cxxflags="-fPIC -fPIE" \ + --extra-cflags="-I/usr/local/include -fPIC" \ + --extra-cxxflags="-fPIC" \ --extra-ldflags="-L/usr/local/lib -fPIC" \ --enable-libass \ --enable-libfreetype \ --enable-libvorbis \ - --enable-version3 + --enable-version3 \ + --disable-ffplay \ + --disable-doc \ + ${EXTRA_CONFIG} - # --enable-shared \ # --enable-libmp3lame \ - make -j$(nproc) + make $make_args V=1 + make install +} + +build_install_opencv() { + if [[ "$(uname)" == "Darwin" ]];then + # Darwin don't need to install opencv from source + return + fi + opencv_version="4.5.0" + cd $opt + if [ ! -d opencv ];then + git clone https://github.com/opencv/opencv.git -b ${opencv_version} + fi + + BUILD_FLAGS=" + -D CMAKE_BUILD_TYPE=RELEASE + -D BUILD_LIST=core,imgproc,imgcodecs + -D WITH_TBB=ON + -D WITH_OPENEXR=ON + -D WITH_EIGEN=ON + -D WITH_GSTREAMER=OFF + -D WITH_OPENCL=OFF + -D WITH_CUDA=OFF + -D WITH_QT=OFF + -D OPENCV_GENERATE_PKGCONFIG=ON + -D BUILD_DOCS=OFF + -D BUILD_TESTS=OFF + -D BUILD_PERF_TESTS=OFF + -D BUILD_EXAMPLES=OFF + -D BUILD_opencv_world=ON + -D BUILD_opencv_imgcodecs=ON + -D BUILD_opencv_apps=OFF + -D BUILD_opencv_calib3d=OFF + -D BUILD_opencv_dnn=OFF + -D BUILD_opencv_features2d=OFF + -D BUILD_opencv_flann=OFF + -D BUILD_opencv_gapi=OFF + -D BUILD_opencv_ml=OFF + -D BUILD_opencv_photo=OFF + -D BUILD_opencv_shape=OFF + -D BUILD_opencv_videoio=OFF + -D BUILD_opencv_videostab=OFF + -D BUILD_opencv_highgui=OFF + -D BUILD_opencv_superres=OFF + -D BUILD_opencv_stitching=OFF + -D BUILD_opencv_java=OFF + -D BUILD_opencv_java_bindings_generator=OFF + -D BUILD_opencv_js=OFF + -D BUILD_opencv_gpu=OFF + -D BUILD_opencv_gpuarithm=OFF + -D BUILD_opencv_gpubgsegm=OFF + -D BUILD_opencv_python2=OFF + -D BUILD_opencv_python3=ON + -D OPENCV_PYTHON3_INSTALL_PATH=$(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") + -D PYTHON_EXECUTABLE=$(which python3) + -D BUILD_SHARED_LIBS=OFF + -D OPENCV_GENERATE_PKGCONFIG=ON + ${CMAKE_EXTRA_CONFIG} + " + + cd $opt/opencv + if [ -d release ];then + rm -rf release + fi + if [ -d modules/gapi ];then + rm -rf modules/gapi + fi + mkdir release && cd release + cmake $BUILD_FLAGS -D CMAKE_INSTALL_PREFIX=$INSTALL_PREFIX .. + make $make_args # V=1 make install } -install_deps +# install_deps build_install_ffmpeg +# build_install_opencv \ No newline at end of file diff --git a/scripts/ffmpeg_b6f84cd7.patch b/scripts/ffmpeg_b6f84cd7.patch index afdb314..1673a45 100644 --- a/scripts/ffmpeg_b6f84cd7.patch +++ b/scripts/ffmpeg_b6f84cd7.patch @@ -289,9 +289,9 @@ index 8a094b1ea0..6fec10583f 100644 + value_str_right[strlen(value_str_right) - 1] = '\0'; + } + av_log(c->fc, AV_LOG_DEBUG, "DSTR box: %s, %s\n", value_str_left, value_str_right); -+ ++ + AVStream *st = c->fc->streams[c->fc->nb_streams-1]; -+ ++ + // Store individual components in metadata + av_dict_set(&st->metadata, "camera_model", camera_model, 0); + av_dict_set(&st->metadata, "distortion_model", distortion_model, 0); @@ -299,7 +299,7 @@ index 8a094b1ea0..6fec10583f 100644 + if (st->codecpar->codec_id != 0) { // 0 is for depth track + av_dict_set(&st->metadata, "distortion_params_1", value_str_right, 0); + } -+ ++ + av_freep(&value_str_left); + av_freep(&value_str_right); + av_freep(&additional_data); @@ -307,7 +307,7 @@ index 8a094b1ea0..6fec10583f 100644 +} + +static int mov_read_tbtm(MOVContext *c, AVIOContext *pb, MOVAtom atom) -+{ ++{ + if (!c || !c->fc) { + av_log(NULL, AV_LOG_ERROR, "Invalid context for TBTM box\n"); + return AVERROR_INVALIDDATA; diff --git a/src/spatialmp4/reader_test.cc b/src/spatialmp4/reader_test.cc index 9900441..10d8f70 100644 --- a/src/spatialmp4/reader_test.cc +++ b/src/spatialmp4/reader_test.cc @@ -23,19 +23,33 @@ #include "utilities/PointcloudUtils.h" #include "spdlog/spdlog.h" #include +#include const std::string kTestFile = "video/test.mp4"; const std::string kVisRgbDir = "./tmp_vis_rgb"; const std::string kVisRgbDir2 = "./tmp_vis_rgb_random"; const std::string kVisDepthDir = "./tmp_vis_depth"; +std::string GetVideoPath() { + const char* env = std::getenv("VIDEO"); + if (env) { + return std::string(env); + } + std::ifstream file(kTestFile); + if (!file.good()) { + throw std::runtime_error("Please set VIDEO environment variable!"); + } + file.close(); + return kTestFile; +} + TEST(SpatialMP4Test, FilenameCheck_ReaderTest) { EXPECT_THROW(SpatialML::Reader(std::string("video/3DVideo_30min Stationary.mp4")), std::runtime_error); EXPECT_THROW(SpatialML::Reader(std::string("video/dont_exists.mp4")), std::runtime_error); } TEST(SpatialMP4Test, Basic_ReaderTest) { - SpatialML::Reader reader(kTestFile); + SpatialML::Reader reader(GetVideoPath()); ASSERT_TRUE(reader.HasRGB()); ASSERT_TRUE(reader.HasDepth()); ASSERT_TRUE(reader.HasPose()); @@ -112,7 +126,7 @@ TEST(SpatialMP4Test, DepthFirst_ReaderTest) { } fs::create_directory(kVisDepthDir); - SpatialML::Reader reader(kTestFile); + SpatialML::Reader reader(GetVideoPath()); reader.SetReadMode(SpatialML::Reader::ReadMode::DEPTH_FIRST); reader.Reset(); while (reader.HasNext()) { @@ -207,7 +221,7 @@ TEST(SpatialMP4Test, RgbOnly_ReaderTest) { } fs::create_directory(kVisRgbDir); - SpatialML::Reader reader(kTestFile); + SpatialML::Reader reader(GetVideoPath()); ASSERT_TRUE(reader.HasRGB()); reader.Reset(); reader.SetReadMode(SpatialML::Reader::ReadMode::RGB_ONLY); @@ -222,7 +236,7 @@ TEST(SpatialMP4Test, RgbOnly_ReaderTest) { } TEST(SpatialMP4Test, DepthOnly_ReaderTest) { - SpatialML::Reader reader(kTestFile); + SpatialML::Reader reader(GetVideoPath()); ASSERT_TRUE(reader.HasDepth()); reader.Reset(); reader.SetReadMode(SpatialML::Reader::ReadMode::DEPTH_ONLY); @@ -243,7 +257,7 @@ TEST(SpatialMP4Test, RandomAccess_ReaderTest) { fs::create_directory(kVisRgbDir2); SpatialML::RandomAccessVideoReader reader; - if (!reader.Open(kTestFile, true)) { + if (!reader.Open(GetVideoPath(), true)) { std::cerr << "Failed to open video" << std::endl; return; } diff --git a/src/spatialmp4/utilities/RgbdUtils.cc b/src/spatialmp4/utilities/RgbdUtils.cc index 6808321..55e8ab2 100644 --- a/src/spatialmp4/utilities/RgbdUtils.cc +++ b/src/spatialmp4/utilities/RgbdUtils.cc @@ -15,6 +15,7 @@ */ #include "RgbdUtils.h" +#include #include #include diff --git a/src/spatialmp4/utils.cc b/src/spatialmp4/utils.cc index 412f4b5..b79fa6e 100644 --- a/src/spatialmp4/utils.cc +++ b/src/spatialmp4/utils.cc @@ -17,6 +17,7 @@ #include "spatialmp4/utils.h" #include #include +#include namespace SpatialML { @@ -172,21 +173,20 @@ std::string FFmpegErrorString(int errnum) { } std::string microsecondsToDateTime(int64_t timestamp_microseconds) { - // split seconds and microseconds - int64_t timestamp_seconds = timestamp_microseconds / 1000000; - int64_t microseconds = timestamp_microseconds % 1000000; - - // convert to time structure - std::time_t time = timestamp_seconds; - std::tm* tm = std::localtime(&time); - - // format output - std::ostringstream oss; - oss << std::put_time(tm, "%Y-%m-%d %H:%M:%S"); - oss << "." << std::setfill('0') << std::setw(6) << microseconds; - - return oss.str(); -} + // split seconds and microseconds + int64_t timestamp_seconds = timestamp_microseconds / 1000000; + int64_t microseconds = timestamp_microseconds % 1000000; + + // convert to time structure + std::time_t time = timestamp_seconds; + std::tm* tm = std::localtime(&time); + // format output + std::ostringstream oss; + oss << std::put_time(tm, "%Y-%m-%d %H:%M:%S"); + oss << "." << std::setfill('0') << std::setw(6) << microseconds; + + return oss.str(); +} } // namespace SpatialML diff --git a/src/spatialmp4/utils.h b/src/spatialmp4/utils.h index c3c919d..698be31 100644 --- a/src/spatialmp4/utils.h +++ b/src/spatialmp4/utils.h @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include "utilities/SyncPose.hpp" #include "spatialmp4/data_types.h" @@ -34,9 +36,9 @@ namespace SpatialML { // 导出宏定义 #if defined(_WIN32) -# define SPATIALMP4_EXPORT __declspec(dllexport) +#define SPATIALMP4_EXPORT __declspec(dllexport) #else -# define SPATIALMP4_EXPORT __attribute__((visibility("default"))) +#define SPATIALMP4_EXPORT __attribute__((visibility("default"))) #endif std::vector String2DoubleVector(const std::string& str); From 2781e287fe607171d7698a59ed3a801c0674d2c0 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 15:26:42 +0800 Subject: [PATCH 06/31] fix bug in macos --- CMakeLists.txt | 80 ++- cmake/ffmpeg_local.cmake | 8 +- cmake/opencv_host.cmake | 23 +- pixi.lock | 902 ++++++++++++++++++++++++++++++ pixi.toml | 19 +- pyproject.toml | 4 +- scripts/build_ffmpeg.sh | 26 +- scripts/opencv_460_on_macos.patch | 28 + 8 files changed, 1005 insertions(+), 85 deletions(-) create mode 100644 scripts/opencv_460_on_macos.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 014a228..f0ee433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fPIC -DEIGEN_MPL2_ONLY") +set(WITH_OPENGL OFF CACHE BOOL "disable opengl" FORCE) include(cmake/ffmpeg_local.cmake) include(cmake/opencv_host.cmake) @@ -44,11 +45,6 @@ set(SRC ) add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SRC}) -# if(APPLE) -# add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SRC}) -# else() -# add_library(${CMAKE_PROJECT_NAME}_lib SHARED ${SRC}) -# endif() target_include_directories(${CMAKE_PROJECT_NAME}_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -83,44 +79,44 @@ if(APPLE) LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python ) - # Find macOS frameworks - find_library(FOUNDATION_FRAMEWORK Foundation) - find_library(AUDIOTOOLBOX_FRAMEWORK AudioToolbox) - find_library(COREAUDIO_FRAMEWORK CoreAudio) - find_library(AVFOUNDATION_FRAMEWORK AVFoundation) - find_library(COREVIDEO_FRAMEWORK CoreVideo) - find_library(COREMEDIA_FRAMEWORK CoreMedia) - find_library(COREGRAPHICS_FRAMEWORK CoreGraphics) - find_library(OPENGL_FRAMEWORK OpenGL) - find_library(APPLICATIONSERVICES_FRAMEWORK ApplicationServices) - find_library(COREFOUNDATION_FRAMEWORK CoreFoundation) - find_library(APPKIT_FRAMEWORK AppKit) - find_library(CARBON_FRAMEWORK Carbon) - find_library(METAL_FRAMEWORK Metal) - find_library(VIDEOTOOLBOX_FRAMEWORK VideoToolbox) - find_library(COREIMAGE_FRAMEWORK CoreImage) - find_library(CORESERVICES_FRAMEWORK CoreServices) - find_library(SECURITY_FRAMEWORK Security) + # # Find macOS frameworks + # find_library(FOUNDATION_FRAMEWORK Foundation) + # find_library(AUDIOTOOLBOX_FRAMEWORK AudioToolbox) + # find_library(COREAUDIO_FRAMEWORK CoreAudio) + # find_library(AVFOUNDATION_FRAMEWORK AVFoundation) + # find_library(COREVIDEO_FRAMEWORK CoreVideo) + # find_library(COREMEDIA_FRAMEWORK CoreMedia) + # find_library(COREGRAPHICS_FRAMEWORK CoreGraphics) + # find_library(OPENGL_FRAMEWORK OpenGL) + # find_library(APPLICATIONSERVICES_FRAMEWORK ApplicationServices) + # find_library(COREFOUNDATION_FRAMEWORK CoreFoundation) + # find_library(APPKIT_FRAMEWORK AppKit) + # find_library(CARBON_FRAMEWORK Carbon) + # find_library(METAL_FRAMEWORK Metal) + # find_library(VIDEOTOOLBOX_FRAMEWORK VideoToolbox) + # find_library(COREIMAGE_FRAMEWORK CoreImage) + # find_library(CORESERVICES_FRAMEWORK CoreServices) + # find_library(SECURITY_FRAMEWORK Security) - target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC - ${FOUNDATION_FRAMEWORK} - ${AUDIOTOOLBOX_FRAMEWORK} - ${COREAUDIO_FRAMEWORK} - ${AVFOUNDATION_FRAMEWORK} - ${COREVIDEO_FRAMEWORK} - ${COREMEDIA_FRAMEWORK} - ${COREGRAPHICS_FRAMEWORK} - ${OPENGL_FRAMEWORK} - ${APPLICATIONSERVICES_FRAMEWORK} - ${COREFOUNDATION_FRAMEWORK} - ${APPKIT_FRAMEWORK} - ${CARBON_FRAMEWORK} - ${METAL_FRAMEWORK} - ${VIDEOTOOLBOX_FRAMEWORK} - ${COREIMAGE_FRAMEWORK} - ${CORESERVICES_FRAMEWORK} - ${SECURITY_FRAMEWORK} - ) + # target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC + # ${FOUNDATION_FRAMEWORK} + # ${AUDIOTOOLBOX_FRAMEWORK} + # ${COREAUDIO_FRAMEWORK} + # ${AVFOUNDATION_FRAMEWORK} + # ${COREVIDEO_FRAMEWORK} + # ${COREMEDIA_FRAMEWORK} + # ${COREGRAPHICS_FRAMEWORK} + # ${OPENGL_FRAMEWORK} + # ${APPLICATIONSERVICES_FRAMEWORK} + # ${COREFOUNDATION_FRAMEWORK} + # ${APPKIT_FRAMEWORK} + # ${CARBON_FRAMEWORK} + # ${METAL_FRAMEWORK} + # ${VIDEOTOOLBOX_FRAMEWORK} + # ${COREIMAGE_FRAMEWORK} + # ${CORESERVICES_FRAMEWORK} + # ${SECURITY_FRAMEWORK} + # ) endif() if(BUILD_TESTING) diff --git a/cmake/ffmpeg_local.cmake b/cmake/ffmpeg_local.cmake index 1167fda..fe61292 100644 --- a/cmake/ffmpeg_local.cmake +++ b/cmake/ffmpeg_local.cmake @@ -5,10 +5,10 @@ # Install library by `scripts/install/install_ffmpeg.sh` # 设置 PKG_CONFIG_PATH 环境变量 -set(ffmpeg_HOME ${CMAKE_CURRENT_SOURCE_DIR}/scripts/build_ffmpeg/ffmpeg_install) -set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) -if(EXISTS "${PIXI_ROOT}") - set(ffmpeg_HOME "${PIXI_ROOT}") +if(DEFINED ENV{CONDA_PREFIX}) + set(ffmpeg_HOME $ENV{CONDA_PREFIX}) +else() + set(ffmpeg_HOME ${CMAKE_CURRENT_SOURCE_DIR}/scripts/build_ffmpeg/ffmpeg_install) endif() set(ENV{PKG_CONFIG_PATH} "${ffmpeg_HOME}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") diff --git a/cmake/opencv_host.cmake b/cmake/opencv_host.cmake index 7fd4ff9..6aff4b5 100644 --- a/cmake/opencv_host.cmake +++ b/cmake/opencv_host.cmake @@ -1,26 +1,11 @@ # Usage: # >> include(cmake/opencv_host.cmake) -# >> "Then you can add `lib_opencv` as link library name to your target." +# >> "Then you can add `PkgConfig::OpenCV` as link library name to your target." - -# set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) -# if(EXISTS "${PIXI_ROOT}") -# set(OpenCV_DIR ${CONDA_PREFIX}/share/opencv4) -# endif() -# set(OpenCV_STATIC ON) -# find_package( OpenCV REQUIRED ) -# add_compile_options(-std=c++11) -# include_directories(${OpenCV_INCLUDE_DIRS}) -# add_library(lib_opencv INTERFACE) -# target_link_libraries(lib_opencv INTERFACE ${OpenCV_LIBS}) -# set(OpenCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIRS}) -# set(OpenCV_LIBS ${OpenCV_LIBRARIES}) -# LINK_DIRECTORIES(${OpenCV_LIBDIR}) - -set(PIXI_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.pixi/envs/default) -if(EXISTS "${PIXI_ROOT}") - set(ENV{PKG_CONFIG_PATH} "${PIXI_ROOT}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") +if(DEFINED ENV{CONDA_PREFIX}) + set(ENV{PKG_CONFIG_PATH} "${CONDA_PREFIX}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") endif() + set(ENV{PKG_CONFIG} "pkg-config --static") find_package(PkgConfig) diff --git a/pixi.lock b/pixi.lock index 1c4cdd7..c3cd983 100644 --- a/pixi.lock +++ b/pixi.lock @@ -63,6 +63,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.9.1-hd6dc26d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h4ce23a2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-32_h7ac8fdf_openblas.conda @@ -86,6 +87,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libvorbis-1.3.7-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.13-h7f98852_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.10.3-hca2bb57_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda @@ -95,6 +97,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.1.1-pyh8b19718_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.2-h29eaf8c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda @@ -107,10 +110,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.3-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h0157908_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2021.9.0-hf52228f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.14.0-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-fixesproto-5.0-hb9d3cd8_1003.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-hb9d3cd8_1003.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda @@ -129,6 +134,96 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.1.0-h5505292_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.1.0-h5505292_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.5-h5505292_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-h6a3b0d2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.31.6-ha25475f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.0-h286801f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.15.0-h1383a14_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.13.3-hce30654_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.10-h27ca646_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-2.84.2-h85e5b2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.84.2-h1dc7a0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-h286801f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-11.2.1-hab40de2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jpeg-9e-he4db4b2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libass-0.17.4-hcbd7ca7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-32_h10e41b3_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-h5505292_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-h5505292_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-h5505292_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-32_hb3479ef_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.14.1-h73640d1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-20.1.7-ha82da77_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.0-h286801f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.13.3-hce30654_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.13.3-h1d14073_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-14_2_0_h6c33f7e_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-14.2.0-h6c33f7e_103.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.84.2-hbec27ea_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwloc-2.11.2-default_hbce5d74_1001.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-hfe07756_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.24.2-h493aca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-devel-0.24.2-h493aca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-2.1.4-h1a8c8d9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-32_hc9a63f6_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.64.0-h6d7220d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libogg-1.3.5-h48c0fde_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_hf332438_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.49-h3783ad8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.2-h6fb428d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h5505292_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libvorbis-1.3.7-h9f76cd9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.13.8-h52572c6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-20.1.7-hdb05f8b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/make-4.4.1-hc9fafa5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.0-ha024513_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.1-h81ee809_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre-8.45-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.45-ha881caa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.1.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.2-h2f9eb0b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pkg-config-0.29.2-hde07d2e_1009.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.11-hc22306f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.5-h7ab814d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.1.0-h9541205_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.14.0-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-h6491c7d_2.conda packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 @@ -181,6 +276,18 @@ packages: license_family: MIT size: 19810 timestamp: 1749230148642 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.1.0-h5505292_3.conda + sha256: 97e2a90342869cc122921fdff0e6be2f5c38268555c08ba5d14e1615e4637e35 + md5: 03c7865dd4dbf87b7b7d363e24c632f1 + depends: + - __osx >=11.0 + - brotli-bin 1.1.0 h5505292_3 + - libbrotlidec 1.1.0 h5505292_3 + - libbrotlienc 1.1.0 h5505292_3 + license: MIT + license_family: MIT + size: 20094 + timestamp: 1749230390021 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.1.0-hb9d3cd8_3.conda sha256: ab74fa8c3d1ca0a055226be89e99d6798c65053e2d2d3c6cb380c574972cd4a7 md5: 58178ef8ba927229fba6d84abf62c108 @@ -193,6 +300,17 @@ packages: license_family: MIT size: 19390 timestamp: 1749230137037 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.1.0-h5505292_3.conda + sha256: 5c6a808326c3bbb6f015a57c9eb463d65f259f67154f4f06783d8829ce9239b4 + md5: cc435eb5160035fd8503e9a58036c5b5 + depends: + - __osx >=11.0 + - libbrotlidec 1.1.0 h5505292_3 + - libbrotlienc 1.1.0 h5505292_3 + license: MIT + license_family: MIT + size: 17185 + timestamp: 1749230373519 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d md5: 62ee74e96c5ebb0af99386de58cf9553 @@ -203,6 +321,15 @@ packages: license_family: BSD size: 252783 timestamp: 1720974456583 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda + sha256: adfa71f158cbd872a36394c56c3568e6034aa55c623634b37a4836bd036e6b91 + md5: fc6948412dbbbe9a4c9ddbbcfe0a79ab + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + size: 122909 + timestamp: 1720974522888 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.5-hb9d3cd8_0.conda sha256: f8003bef369f57396593ccd03d08a8e21966157269426f71e943f96e4b579aeb md5: f7f0d6cc2dc986d42ac2689ec88192be @@ -213,6 +340,15 @@ packages: license_family: MIT size: 206884 timestamp: 1744127994291 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.5-h5505292_0.conda + sha256: b4bb55d0806e41ffef94d0e3f3c97531f322b3cb0ca1f7cdf8e47f62538b7a2b + md5: f8cd1beb98240c7edb1a95883360ccfa + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 179696 + timestamp: 1744128058734 - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda sha256: 7cfec9804c84844ea544d98bda1d9121672b66ff7149141b8415ca42dfcd44f6 md5: 72525f07d72806e3b639ad4504c30ce5 @@ -244,6 +380,24 @@ packages: license: LGPL-2.1-only or MPL-1.1 size: 1576122 timestamp: 1663568213559 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-h6a3b0d2_0.conda + sha256: 00439d69bdd94eaf51656fdf479e0c853278439d22ae151cabf40eb17399d95f + md5: 38f6df8bc8c668417b904369a01ba2e2 + depends: + - __osx >=11.0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - freetype >=2.12.1,<3.0a0 + - icu >=75.1,<76.0a0 + - libcxx >=18 + - libexpat >=2.6.4,<3.0a0 + - libglib >=2.82.2,<3.0a0 + - libpng >=1.6.47,<1.7.0a0 + - libzlib >=1.3.1,<2.0a0 + - pixman >=0.44.2,<1.0a0 + license: LGPL-2.1-only or MPL-1.1 + size: 896173 + timestamp: 1741554795915 - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.26.4-hcfe8598_0.conda sha256: 37533b572a676017704c989c392998c344e889010786d6555dccdfc524a8e238 md5: 1714cf0f0facaeb609a0846e4270aff2 @@ -265,6 +419,25 @@ packages: license_family: BSD size: 16343060 timestamp: 1684460894541 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.31.6-ha25475f_0.conda + sha256: d71e84b6b7000323d2a394c3e01cfd35df3421741e8b4af7852e8400c2604574 + md5: 3a3bbf1de0a6d99658f4c1b63ad40d21 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.12.1,<9.0a0 + - libcxx >=18 + - libexpat >=2.6.4,<3.0a0 + - liblzma >=5.6.4,<6.0a0 + - libuv >=1.50.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.5,<1.4.6a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 16507414 + timestamp: 1740467905288 - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 md5: 962b9857ee8e7018c22f2776ffa0b2d7 @@ -303,6 +476,16 @@ packages: license_family: MIT size: 140050 timestamp: 1743431809745 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.0-h286801f_0.conda + sha256: df45bc695f88f252e6fee20faac11621d294b9d22d92972fab7def23d4613501 + md5: 6f54d1a312ca354072b7d79aa0d31eb9 + depends: + - __osx >=11.0 + - libexpat 2.7.0 h286801f_0 + license: MIT + license_family: MIT + size: 127135 + timestamp: 1743431804373 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 @@ -344,6 +527,18 @@ packages: license_family: MIT size: 272010 timestamp: 1674828850194 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.15.0-h1383a14_1.conda + sha256: f79d3d816fafbd6a2b0f75ebc3251a30d3294b08af9bb747194121f5efa364bc + md5: 7b29f48742cea5d1ccb5edd839cb5621 + depends: + - __osx >=11.0 + - freetype >=2.12.1,<3.0a0 + - libexpat >=2.6.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 234227 + timestamp: 1730284037572 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 md5: fee5683a3f04bd15cbd8318b096a27ab @@ -375,6 +570,15 @@ packages: license: GPL-2.0-only OR FTL size: 634972 timestamp: 1694615932610 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.13.3-hce30654_1.conda + sha256: 6b63c72ea51a41d41964841404564c0729fdddd3e952e2715839fd759b7cfdfc + md5: e684de4644067f1956a580097502bf03 + depends: + - libfreetype 2.13.3 hce30654_1 + - libfreetype6 2.13.3 h1d14073_1 + license: GPL-2.0-only OR FTL + size: 172220 + timestamp: 1745370149658 - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.10-h36c2ea0_0.tar.bz2 sha256: 5d7b6c0ee7743ba41399e9e05a58ccc1cfc903942e49ff6f677f6e423ea7a627 md5: ac7bc6a654f8f41b352b38f4051135f8 @@ -383,6 +587,12 @@ packages: license: LGPL-2.1 size: 114383 timestamp: 1604416621168 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.10-h27ca646_0.tar.bz2 + sha256: 4b37ea851a2cf85edf0a63d2a63266847ec3dcbba4a31156d430cdd6aa811303 + md5: c64443234ff91d70cb9c7dc926c58834 + license: LGPL-2.1 + size: 60255 + timestamp: 1604417405528 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.1.0-h33e79ad_3.conda sha256: 69cc03e5b20e064ad5a9ac88ac3b792a1b089c838fa4ab5eb56990a9c166ce5a md5: 45ddc7242fed76e1b4ff5ee062e6d926 @@ -420,6 +630,20 @@ packages: license: LGPL-2.1-or-later size: 600389 timestamp: 1715252749399 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-2.84.2-h85e5b2e_0.conda + sha256: 43ea91eee25abe882f34a1b709ddb2bc51dcb18e4c16d0484f9003cd67347d8e + md5: 01fbc39f2524b2788b81b8044a780dba + depends: + - glib-tools 2.84.2 h1dc7a0c_0 + - libffi >=3.4.6,<3.5.0a0 + - libglib 2.84.2 hbec27ea_0 + - libintl >=0.24.1,<1.0a0 + - libintl-devel + - packaging + - python * + license: LGPL-2.1-or-later + size: 591283 + timestamp: 1747837135361 - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.80.2-hb6ce0ca_0.conda sha256: 221cd047f998301b96b1517d9f7d3fb0e459e8ee18778a1211f302496f6e110d md5: a965aeaf060289528a3fbe09326edae2 @@ -429,6 +653,16 @@ packages: license: LGPL-2.1-or-later size: 114359 timestamp: 1715252713902 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.84.2-h1dc7a0c_0.conda + sha256: 809cb62fe75ca0bcf0eecd223d100b4b4aa4555eee4c3e335ab7f453506bbb78 + md5: c6dd3b852d7287ee3bf1d392f107f1ac + depends: + - __osx >=11.0 + - libglib 2.84.2 hbec27ea_0 + - libintl >=0.24.1,<1.0a0 + license: LGPL-2.1-or-later + size: 101786 + timestamp: 1747837093760 - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-h5888daf_0.conda sha256: cac69f3ff7756912bbed4c28363de94f545856b35033c0b86193366b95f5317d md5: 951ff8d9e5536896408e89d63230b8d5 @@ -440,6 +674,16 @@ packages: license_family: LGPL size: 98419 timestamp: 1750079957535 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-h286801f_0.conda + sha256: e1c431b66b0a632e8fcc2b886cccde4eb5ec5eb8a3d84e89b7639d603c174646 + md5: 64d15e1dfe86fa13cf0d519d1074dcd9 + depends: + - __osx >=11.0 + - libcxx >=18 + license: LGPL-2.0-or-later + license_family: LGPL + size: 81566 + timestamp: 1750080158744 - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.1.0-h33e79ad_3.conda sha256: b071ff43b64e9c8366411f1d2a8030fb9769c0c588ffa6e16a498957dba96f45 md5: 5917fb5bed3e2fa4fce4fbbe1b541946 @@ -477,6 +721,25 @@ packages: license_family: MIT size: 2096772 timestamp: 1656503454174 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-11.2.1-hab40de2_0.conda + sha256: 244e4071229aa3b824dd2a9814c0e8b4c2b40dfb28914ec2247bf27c5c681584 + md5: 12f4520f618ff6e398a2c8e0bed1e580 + depends: + - __osx >=11.0 + - cairo >=1.18.4,<2.0a0 + - freetype + - graphite2 + - icu >=75.1,<76.0a0 + - libcxx >=18 + - libexpat >=2.7.0,<3.0a0 + - libfreetype >=2.13.3 + - libfreetype6 >=2.13.3 + - libglib >=2.84.1,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 1395282 + timestamp: 1747091793921 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-70.1-h27087fc_0.tar.bz2 sha256: 1d7950f3be4637ab915d886304e57731d39a41ab705ffc95c4681655c459374a md5: 87473a15119779e021c314249d4b4aed @@ -487,6 +750,15 @@ packages: license_family: MIT size: 14191488 timestamp: 1648050221778 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda + sha256: 9ba12c93406f3df5ab0a43db8a4b4ef67a5871dfd401010fbe29b218b2cbe620 + md5: 5eb22c1d7b3fc4abb50d92d621583137 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 11857802 + timestamp: 1720853997952 - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda sha256: 0ec8f4d02053cd03b0f3e63168316530949484f80e16f5e2fb199a1d117a89ca md5: 6837f3eff7dcea42ecd714ce1ac2b108 @@ -504,6 +776,12 @@ packages: license: IJG size: 275125 timestamp: 1656500806614 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/jpeg-9e-he4db4b2_2.tar.bz2 + sha256: 1175af9e55cb8a8bf24102c9aa9233f2a8d83845f2c01773c2a364a4c889464b + md5: ad1e3584bfef678a4ca6f9daa6695159 + license: IJG + size: 265558 + timestamp: 1656501164015 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda sha256: a922841ad80bd7b222502e65c07ecb67e4176c4fa5b03678a005f39fcc98be4b md5: ad8527bf134a90e1c9ed35fa0b64318c @@ -535,6 +813,19 @@ packages: license_family: MIT size: 1329877 timestamp: 1671091750695 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda + sha256: 4442f957c3c77d69d9da3521268cad5d54c9033f1a73f99cde0a3658937b159b + md5: c6dc8a0fdec13a0565936655c33069a1 + depends: + - __osx >=11.0 + - libcxx >=16 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.3.1,<4.0a0 + license: MIT + license_family: MIT + size: 1155530 + timestamp: 1719463474401 - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_5.conda sha256: de097284f497b391fe9d000c75b684583c30aad172d9508ed05df23ce39d75cb md5: acd9213a63cb62521290e581ef82de80 @@ -562,6 +853,22 @@ packages: license_family: OTHER size: 122389 timestamp: 1647824984482 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libass-0.17.4-hcbd7ca7_0.conda + sha256: 079f5fdf7aace970a0db91cd2cc493c754dfdc4520d422ecec43d2561021167a + md5: 0977f4a79496437ff3a2c97d13c4c223 + depends: + - __osx >=11.0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - libzlib >=1.3.1,<2.0a0 + - fribidi >=1.0.10,<2.0a0 + - libiconv >=1.18,<2.0a0 + - harfbuzz >=11.0.1 + - libfreetype >=2.13.3 + - libfreetype6 >=2.13.3 + license: ISC + size: 138339 + timestamp: 1749328988096 - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-32_h59b9bed_openblas.conda build_number: 32 sha256: 1540bf739feb446ff71163923e7f044e867d163c50b605c8b421c55ff39aa338 @@ -579,6 +886,23 @@ packages: license_family: BSD size: 17330 timestamp: 1750388798074 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-32_h10e41b3_openblas.conda + build_number: 32 + sha256: 2775472dd81d43dc20804b484028560bfecd5ab4779e39f1fb95684da3ff2029 + md5: d4a1732d2b330c9d5d4be16438a0ac78 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - blas 2.132 openblas + - liblapack 3.9.0 32*_openblas + - mkl <2025 + - libcblas 3.9.0 32*_openblas + - liblapacke 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17520 + timestamp: 1750388963178 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hb9d3cd8_3.conda sha256: 462a8ed6a7bb9c5af829ec4b90aab322f8bcd9d8987f793e6986ea873bbd05cf md5: cb98af5db26e3f482bebb80ce9d947d3 @@ -589,6 +913,15 @@ packages: license_family: MIT size: 69233 timestamp: 1749230099545 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-h5505292_3.conda + sha256: 0e9c196ad8569ca199ea05103707cde0ae3c7e97d0cdf0417d873148ea9ad640 + md5: fbc4d83775515e433ef22c058768b84d + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 68972 + timestamp: 1749230317752 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hb9d3cd8_3.conda sha256: 3eb27c1a589cbfd83731be7c3f19d6d679c7a444c3ba19db6ad8bf49172f3d83 md5: 1c6eecffad553bde44c5238770cfb7da @@ -600,6 +933,16 @@ packages: license_family: MIT size: 33148 timestamp: 1749230111397 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-h5505292_3.conda + sha256: d888c228e7d4f0f2303538f6a9705498c81d56fedaab7811e1186cb6e24d689b + md5: 01c4b35a1c4b94b60801f189f1ac6ee3 + depends: + - __osx >=11.0 + - libbrotlicommon 1.1.0 h5505292_3 + license: MIT + license_family: MIT + size: 29249 + timestamp: 1749230338861 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb9d3cd8_3.conda sha256: 76e8492b0b0a0d222bfd6081cae30612aa9915e4309396fdca936528ccf314b7 md5: 3facafe58f3858eb95527c7d3a3fc578 @@ -611,6 +954,16 @@ packages: license_family: MIT size: 282657 timestamp: 1749230124839 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-h5505292_3.conda + sha256: 0734a54db818ddfdfbf388fa53c5036a06bbe17de14005f33215d865d51d8a5e + md5: 1ce5e315293309b5bf6778037375fb08 + depends: + - __osx >=11.0 + - libbrotlicommon 1.1.0 h5505292_3 + license: MIT + license_family: MIT + size: 274404 + timestamp: 1749230355483 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-32_he106b2a_openblas.conda build_number: 32 sha256: 92a001fc181e6abe4f4a672b81d9413ca2f22609f8a95327dfcc6eee593ffeb9 @@ -625,6 +978,20 @@ packages: license_family: BSD size: 17308 timestamp: 1750388809353 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-32_hb3479ef_openblas.conda + build_number: 32 + sha256: 25d46ace14c3ac45d4aa18b5f7a0d3d30cec422297e900f8b97a66334232061c + md5: d8e8ba717ae863b13a7495221f2b5a71 + depends: + - libblas 3.9.0 32_h10e41b3_openblas + constrains: + - blas 2.132 openblas + - liblapack 3.9.0 32*_openblas + - liblapacke 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17485 + timestamp: 1750388970626 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.1.2-h409715c_0.conda sha256: d572c31ff48d2db6ca5bab476bf325811cfc82577480b3791487c3fe7bff2ffa md5: 50c873c9660ed116707ae15b663928d8 @@ -640,6 +1007,30 @@ packages: license_family: MIT size: 372833 timestamp: 1685447685782 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.14.1-h73640d1_0.conda + sha256: 0055b68137309db41ec34c938d95aec71d1f81bd9d998d5be18f32320c3ccba0 + md5: 1af57c823803941dfc97305248a56d57 + depends: + - __osx >=11.0 + - krb5 >=1.21.3,<1.22.0a0 + - libnghttp2 >=1.64.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + size: 403456 + timestamp: 1749033320430 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-20.1.7-ha82da77_0.conda + sha256: a3fd34773f1252a4f089e74a075ff5f0f6b878aede097e83a405f35687c36f24 + md5: 881de227abdddbe596239fa9e82eb3ab + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 567189 + timestamp: 1749847129529 - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb9d3cd8_0.conda sha256: f53458db897b93b4a81a6dbfd7915ed8fa4a54951f97c698dde6faa028aadfd2 md5: 4c0ab57463117fbb8df85268415082f5 @@ -663,6 +1054,17 @@ packages: license_family: BSD size: 134676 timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 + md5: 44083d2d2c2025afca315c7a172eab2b + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + size: 107691 + timestamp: 1738479560845 - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 md5: 172bf1cd1ff8629f2b1179945ed45055 @@ -672,6 +1074,13 @@ packages: license_family: BSD size: 112766 timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + size: 107458 + timestamp: 1702146414478 - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.0-h5888daf_0.conda sha256: 33ab03438aee65d6aa667cf7d90c91e5e7d734c19a67aa4c7040742c0a13d505 md5: db0bfbe7dd197b68ad5f30333bae6ce0 @@ -684,6 +1093,17 @@ packages: license_family: MIT size: 74427 timestamp: 1743431794976 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.0-h286801f_0.conda + sha256: ee550e44765a7bbcb2a0216c063dcd53ac914a7be5386dd0554bd06e6be61840 + md5: 6934bbb74380e045741eb8637641a65b + depends: + - __osx >=11.0 + constrains: + - expat 2.7.0.* + license: MIT + license_family: MIT + size: 65714 + timestamp: 1743431789879 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab md5: ede4673863426c0883c0063d853bbd85 @@ -694,6 +1114,35 @@ packages: license_family: MIT size: 57433 timestamp: 1743434498161 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda + sha256: c6a530924a9b14e193ea9adfe92843de2a806d1b7dbfd341546ece9653129e60 + md5: c215a60c2935b517dcda8cad4705734d + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 39839 + timestamp: 1743434670405 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.13.3-hce30654_1.conda + sha256: 1f8c16703fe333cdc2639f7cdaf677ac2120843453222944a7c6c85ec342903c + md5: d06282e08e55b752627a707d58779b8f + depends: + - libfreetype6 >=2.13.3 + license: GPL-2.0-only OR FTL + size: 7813 + timestamp: 1745370144506 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.13.3-h1d14073_1.conda + sha256: c278df049b1a071841aa0aca140a338d087ea594e07dcf8a871d2cfe0e330e75 + md5: b163d446c55872ef60530231879908b9 + depends: + - __osx >=11.0 + - libpng >=1.6.47,<1.7.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - freetype >=2.13.3 + license: GPL-2.0-only OR FTL + size: 333529 + timestamp: 1745370142848 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 md5: 9e60c55e725c20d23125a5f0dd69af5d @@ -736,6 +1185,15 @@ packages: license_family: GPL size: 29057 timestamp: 1750808257258 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-14_2_0_h6c33f7e_103.conda + sha256: 8628746a8ecd311f1c0d14bb4f527c18686251538f7164982ccbe3b772de58b5 + md5: 044a210bc1d5b8367857755665157413 + depends: + - libgfortran5 14.2.0 h6c33f7e_103 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 156291 + timestamp: 1743863532821 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a md5: 530566b68c3b8ce7eec4cd047eae19fe @@ -748,6 +1206,17 @@ packages: license_family: GPL size: 1565627 timestamp: 1750808236464 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-14.2.0-h6c33f7e_103.conda + sha256: 8599453990bd3a449013f5fa3d72302f1c68f0680622d419c3f751ff49f01f17 + md5: 69806c1e957069f1d515830dcc9f6cbb + depends: + - llvm-openmp >=8.0.0 + constrains: + - libgfortran 5.0.0 14_2_0_*_103 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 806566 + timestamp: 1743863491726 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda sha256: 93e03b6cf4765bc06d64fa3dac65f22c53ae4a30247bb0e2dea0bd9c47a3fb26 md5: 72724f6a78ecb15559396966226d5838 @@ -762,6 +1231,21 @@ packages: license: LGPL-2.1-or-later size: 3912673 timestamp: 1715252654366 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.84.2-hbec27ea_0.conda + sha256: 5fcc5e948706cc64e45e2454267f664ed5a1e84f15345aae04a41d852a879c0e + md5: 7bbb8961dca1b4b9f2b01b6e722111a7 + depends: + - __osx >=11.0 + - libffi >=3.4.6,<3.5.0a0 + - libiconv >=1.18,<2.0a0 + - libintl >=0.24.1,<1.0a0 + - libzlib >=1.3.1,<2.0a0 + - pcre2 >=10.45,<10.46.0a0 + constrains: + - glib 2.84.2 *_0 + license: LGPL-2.1-or-later + size: 3666180 + timestamp: 1747837044507 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_3.conda sha256: 43710ab4de0cd7ff8467abff8d11e7bb0e36569df04ce1c099d48601818f11d1 md5: 3cd1a7238a0dd3d0860fdefc496cc854 @@ -771,6 +1255,28 @@ packages: license_family: GPL size: 447068 timestamp: 1750808138400 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.9.1-hd6dc26d_0.conda + sha256: 39bb53aa6ae0cab734568a58ad31ffe82ea244a82f575cd5c67abba785e442ee + md5: a3ede1b8e47f993ff1fe3908b23bb307 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.10.3,<2.14.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2569104 + timestamp: 1680713440274 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwloc-2.11.2-default_hbce5d74_1001.conda + sha256: dcac7144ad93cf3f276ec14c5553aa34de07443a9b1db6b3cd8d2e117b173c40 + md5: ff6438cf47cff4899ae9900bf9253c41 + depends: + - __osx >=11.0 + - libcxx >=18 + - libxml2 >=2.13.4,<2.14.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2332319 + timestamp: 1731375088576 - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h4ce23a2_1.conda sha256: 18a4afe14f731bfb9cf388659994263904d20111e42f841e9eea1bb6f91f4ab4 md5: e796ff8ddc598affdf7c173d6145f087 @@ -780,6 +1286,33 @@ packages: license: LGPL-2.1-only size: 713084 timestamp: 1740128065462 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-hfe07756_1.conda + sha256: d30780d24bf3a30b4f116fca74dedb4199b34d500fe6c52cced5f8cc1e926f03 + md5: 450e6bdc0c7d986acf7b8443dce87111 + depends: + - __osx >=11.0 + license: LGPL-2.1-only + size: 681804 + timestamp: 1740128227484 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.24.2-h493aca8_0.conda + sha256: aebb3357d4b6e00996b15917d9a4061c3c17e1ee191b7226d2c1317ac049a62a + md5: 2dc5359f33b7038d3a35a2d2defeb608 + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + license: LGPL-2.1-or-later + size: 90769 + timestamp: 1751465374263 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-devel-0.24.2-h493aca8_0.conda + sha256: 1e5f0f5ba34ac085fdb7453dd73404e10706c3d44949c2d237014362cceca72e + md5: f8bfc03eb84a19b82d9f056125d63b0c + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + - libintl 0.24.2 h493aca8_0 + license: LGPL-2.1-or-later + size: 40105 + timestamp: 1751465417290 - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 sha256: 0d8b666ca4deabf948a76654df0fa1277145bed1c9e8a58e18a649c22c5f1c3e md5: b4f717df2d377410b462328bf0e8fb7d @@ -788,6 +1321,12 @@ packages: license: IJG, modified 3-clause BSD and zlib size: 1011471 timestamp: 1664781971968 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-2.1.4-h1a8c8d9_0.tar.bz2 + sha256: 34dc289e85fbfabbf763edf6ad83dba25d11934749580ef1d4080fbacf3530f3 + md5: bd550dd10ccf96d75a16a0d7194aacf7 + license: IJG, modified 3-clause BSD and zlib + size: 854754 + timestamp: 1664782154413 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-32_h7ac8fdf_openblas.conda build_number: 32 sha256: 5b55a30ed1b3f8195dad9020fe1c6d0f514829bfaaf0cf5e393e93682af009f2 @@ -802,6 +1341,20 @@ packages: license_family: BSD size: 17316 timestamp: 1750388820745 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-32_hc9a63f6_openblas.conda + build_number: 32 + sha256: 5e1cfa3581d1dec6b07a75084ff6cfa4b4465c646c6884a71c78a28543f83b61 + md5: bf9ead3fa92fd75ad473c6a1d255ffcb + depends: + - libblas 3.9.0 32_h10e41b3_openblas + constrains: + - blas 2.132 openblas + - libcblas 3.9.0 32*_openblas + - liblapacke 3.9.0 32*_openblas + license: BSD-3-Clause + license_family: BSD + size: 17507 + timestamp: 1750388977861 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8 md5: 1a580f7796c7bf6393fddb8bbbde58dc @@ -813,6 +1366,16 @@ packages: license: 0BSD size: 112894 timestamp: 1749230047870 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda + sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285 + md5: d6df911d4564d77c4374b02552cb17d1 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.1.* + license: 0BSD + size: 92286 + timestamp: 1749230283517 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda sha256: 329e66330a8f9cbb6a8d5995005478188eb4ba8a6b6391affa849744f4968492 md5: f61edadbb301530bd65a32646bd81552 @@ -837,6 +1400,21 @@ packages: license_family: MIT size: 631397 timestamp: 1699440427647 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.64.0-h6d7220d_0.conda + sha256: 00cc685824f39f51be5233b54e19f45abd60de5d8847f1a56906f8936648b72f + md5: 3408c02539cee5f1141f9f11450b6a51 + depends: + - __osx >=11.0 + - c-ares >=1.34.2,<2.0a0 + - libcxx >=17 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.3.2,<4.0a0 + license: MIT + license_family: MIT + size: 566719 + timestamp: 1729572385640 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 @@ -857,6 +1435,15 @@ packages: license_family: BSD size: 218500 timestamp: 1745825989535 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libogg-1.3.5-h48c0fde_1.conda + sha256: 28bd1fe20fe43da105da41b95ac201e95a1616126f287985df8e86ddebd1c3d8 + md5: 29b8b11f6d7e6bd0e76c029dcf9dd024 + depends: + - __osx >=11.0 + license: BSD-3-Clause + license_family: BSD + size: 216719 + timestamp: 1745826006052 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_0.conda sha256: 225f4cfdb06b3b73f870ad86f00f49a9ca0a8a2d2afe59440521fafe2b6c23d9 md5: 323dc8f259224d13078aaf7ce96c3efe @@ -871,6 +1458,20 @@ packages: license_family: BSD size: 5916819 timestamp: 1750379877844 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_hf332438_0.conda + sha256: 501c8c64f1a6e6b671e49835e6c483bc25f0e7147f3eb4bbb19a4c3673dcaf28 + md5: 5d7dbaa423b4c253c476c24784286e4b + depends: + - __osx >=11.0 + - libgfortran 5.* + - libgfortran5 >=13.3.0 + - llvm-openmp >=18.1.8 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + size: 4163399 + timestamp: 1750378829050 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2 md5: 70e3400cbbfa03e96dcde7fc13e38c7b @@ -890,6 +1491,15 @@ packages: license: zlib-acknowledgement size: 288221 timestamp: 1708780443939 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.49-h3783ad8_0.conda + sha256: b1050f6da51de507eec6902367cc2a3f381dd548eaaccb85673784543dcdee1a + md5: 90be56ffd1a6b1950268f88c12e17c69 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: zlib-acknowledgement + size: 259291 + timestamp: 1750095759683 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.1.0-h97b714f_3.conda sha256: 75fa45d8ea2344bfe96667b478fd00f1d038026f399cb680eceec836c90e67bc md5: bbcff9bf972a0437bea8e431e4b327bb @@ -910,6 +1520,15 @@ packages: license: Unlicense size: 865346 timestamp: 1718050628718 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.2-h6fb428d_0.conda + sha256: 6b51a9e7366d6cd26e50d1d0646331d457999ebb88af258f06a74f075e95bf68 + md5: b2dc1707166040e738df2d514f8a1d22 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: Unlicense + size: 901519 + timestamp: 1751135765345 - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda sha256: 50e47fd9c4f7bf841a11647ae7486f65220cfc988ec422a4475fe8d5a823824d md5: 1f5a58e686b13bcfde88b93f547d23fe @@ -921,6 +1540,16 @@ packages: license_family: BSD size: 271133 timestamp: 1685837707056 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a + md5: b68e8f66b94b44aaa8de4583d3d4cc40 + depends: + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 279193 + timestamp: 1745608793272 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 md5: 6d11a5edae89fe413c0569f16d308f5a @@ -968,6 +1597,15 @@ packages: license_family: MIT size: 890145 timestamp: 1748304699136 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h5505292_0.conda + sha256: 41c1230a3f4e0d265e5053c671f112a16be4405b9047d3da5581e03e9d53de65 + md5: 230a885fe67a3e945a4586b944b6020a + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 420654 + timestamp: 1748304893204 - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.18.0-h0b41bf4_0.conda sha256: e7254d0111a403ffe707e2ad39b6ce49a2be733e751d14a7255b0cb20da2a16b md5: 56e049224de34bbe0478aad422227942 @@ -992,6 +1630,16 @@ packages: license_family: BSD size: 286280 timestamp: 1610609811627 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libvorbis-1.3.7-h9f76cd9_0.tar.bz2 + sha256: 60457217e20d8b24a8390c81338a8fa69c8656b440c067cd82f802a09da93cb9 + md5: 92a1a88d1a1d468c19d9e1659ac8d3df + depends: + - libcxx >=11.0.0 + - libogg >=1.3.4,<1.4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 254839 + timestamp: 1610609991029 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.13-h7f98852_1004.tar.bz2 sha256: 8d5d24cbeda9282dd707edd3156e5fde2e3f3fe86c802fa7ce08c8f1e803bfd9 md5: b3653fdc58d03face9724f602218a904 @@ -1012,6 +1660,32 @@ packages: license: LGPL-2.1-or-later size: 100393 timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.10.3-hca2bb57_4.conda + sha256: d4170f1fe356768758b13a51db123f990bff81b0eae0d5a0ba11c7ca6b9536f4 + md5: bb808b654bdc3c783deaf107a2ffb503 + depends: + - icu >=70.1,<71.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 713891 + timestamp: 1679341466192 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.13.8-h52572c6_0.conda + sha256: 13eb825eddce93761d965da3edaf3a42d868c61ece7d9cf21f7e2a13087c2abe + md5: d7884c7af8af5a729353374c189aede8 + depends: + - __osx >=11.0 + - icu >=75.1,<76.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 583068 + timestamp: 1746634531197 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda sha256: 8ced4afed6322172182af503f21725d072a589a6eb918f8a58135c1e00d35980 md5: 27329162c0dc732bcf67a4e0cd488125 @@ -1023,6 +1697,28 @@ packages: license_family: Other size: 61571 timestamp: 1716874066944 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b + md5: 369964e85dc26bfe78f41399b366c435 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + size: 46438 + timestamp: 1727963202283 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-20.1.7-hdb05f8b_0.conda + sha256: e7d95b50a90cdc9e0fc38bc37f493a61b9d08164114b562bbd9ff0034f45eca2 + md5: 741e1da0a0798d32e13e3724f2ca2dcf + depends: + - __osx >=11.0 + constrains: + - openmp 20.1.7|20.1.7.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 281996 + timestamp: 1749892286735 - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda sha256: d652c7bd4d3b6f82b0f6d063b0d8df6f54cc47531092d7ff008e780f3261bdda md5: 33405d2a66b1411db9f7242c8b97c9e7 @@ -1033,6 +1729,15 @@ packages: license_family: GPL size: 513088 timestamp: 1727801714848 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/make-4.4.1-hc9fafa5_2.conda + sha256: 90ca65e788406d9029ae23ad4bd944a8b5353ad5f59bd6ce326f980cde46f37e + md5: 9f44ef1fea0a25d6a3491c58f3af8460 + depends: + - __osx >=11.0 + license: GPL-3.0-or-later + license_family: GPL + size: 274048 + timestamp: 1727801725384 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 @@ -1042,6 +1747,14 @@ packages: license: X11 AND BSD-3-Clause size: 891641 timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + size: 797030 + timestamp: 1738196177597 - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.0-h7aa8ee6_0.conda sha256: 8cf09470430b5aba5165c7aefed070d2c8f998f69fede01197ef838bf17fa81a md5: 2f67cb5c5ec172faeba94348ae8af444 @@ -1053,6 +1766,16 @@ packages: license_family: APACHE size: 180917 timestamp: 1750273173789 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.0-ha024513_0.conda + sha256: 2715f956c17f4c4240972567f710dea93f0ffe3073fb9bd0d636eba15c3ab2e6 + md5: 91f96a6daf4c14e45b3bbc71e3b8e1f8 + depends: + - libcxx >=18 + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + size: 165419 + timestamp: 1750273167832 - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 md5: d8285bea2a350f63fab23bf460221f3f @@ -1070,6 +1793,23 @@ packages: license_family: BSD size: 7484186 timestamp: 1707225809722 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + sha256: c8841d6d6f61fd70ca80682efbab6bdb8606dc77c68d8acabfbd7c222054f518 + md5: d83fc83d589e2625a3451c9a7e21047c + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + size: 6073136 + timestamp: 1707226249608 - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.1-h7b32b05_0.conda sha256: 942347492164190559e995930adcdf84e2fea05307ec8012c02a505f5be87462 md5: c87df2ab1448ba69169652ab9547082d @@ -1081,6 +1821,16 @@ packages: license_family: Apache size: 3131002 timestamp: 1751390382076 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.1-h81ee809_0.conda + sha256: f94fde0f096fa79794c8aa0a2665630bbf9026cc6438e8253f6555fc7281e5a8 + md5: a8ac77e7c7e58d43fa34d60bd4361062 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + size: 3071649 + timestamp: 1751390309393 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 md5: 58335b26c38bf4a20f399384c33cbcf9 @@ -1101,6 +1851,15 @@ packages: license_family: BSD size: 259377 timestamp: 1623788789327 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre-8.45-hbdafb3b_0.tar.bz2 + sha256: f2e0c4ae3306f94851eea2318c6d26d24f8e191e329ddd256a612cd1184c5737 + md5: 500758f2515ae07c640d255c11afc19f + depends: + - libcxx >=11.1.0 + license: BSD-3-Clause + license_family: BSD + size: 235554 + timestamp: 1623788902053 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda sha256: 766dd986a7ed6197676c14699000bba2625fd26c8a890fcb7a810e5cf56155bc md5: 8292dea9e022d9610a11fce5e0896ed8 @@ -1112,6 +1871,28 @@ packages: license_family: BSD size: 950847 timestamp: 1708118050286 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.45-ha881caa_0.conda + sha256: e9ecb706b58b5a2047c077b3a1470e8554f3aad02e9c3c00cfa35d537420fea3 + md5: a52385b93558d8e6bbaeec5d61a21cd7 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 837826 + timestamp: 1745955207242 +- conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.1.1-pyh8b19718_0.conda + sha256: ebfa591d39092b111b9ebb3210eb42251be6da89e26c823ee03e5e838655a43e + md5: 32d0781ace05105cc99af55d36cbec7c + depends: + - python >=3.9,<3.13.0a0 + - setuptools + - wheel + license: MIT + license_family: MIT + size: 1242995 + timestamp: 1746249983238 - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.2-h29eaf8c_0.conda sha256: 6cb261595b5f0ae7306599f2bb55ef6863534b6d4d1bc0dcfdfa5825b0e4e53d md5: 39b4228a867772d610c02e06f939a5b8 @@ -1123,6 +1904,16 @@ packages: license_family: MIT size: 402222 timestamp: 1749552884791 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.2-h2f9eb0b_0.conda + sha256: 68d1eef12946d779ce4b4b9de88bc295d07adce5dd825a0baf0e1d7cf69bc5a6 + md5: 0587a57e200568a71982173c07684423 + depends: + - __osx >=11.0 + - libcxx >=18 + license: MIT + license_family: MIT + size: 214660 + timestamp: 1749553221709 - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda sha256: c9601efb1af5391317e04eca77c6fe4d716bf1ca1ad8da2a05d15cb7c28d7d4e md5: 1bee70681f504ea424fb07cdb090c001 @@ -1133,6 +1924,17 @@ packages: license_family: GPL size: 115175 timestamp: 1720805894943 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pkg-config-0.29.2-hde07d2e_1009.conda + sha256: d82f4655b2d67fe12eefe1a3eea4cd27d33fa41dbc5e9aeab5fd6d3d2c26f18a + md5: b4f41e19a8c20184eec3aaf0f0953293 + depends: + - __osx >=11.0 + - libglib >=2.80.3,<3.0a0 + - libiconv >=1.17,<2.0a0 + license: GPL-2.0-or-later + license_family: GPL + size: 49724 + timestamp: 1720806128118 - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda sha256: a8eb555eef5063bbb7ba06a379fa7ea714f57d9741fe0efdb9442dbbc2cccbcc md5: 7da7ccd349dbf6487a7778579d2bb971 @@ -1204,6 +2006,27 @@ packages: license: Python-2.0 size: 31991381 timestamp: 1713208036041 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.11-hc22306f_0_cpython.conda + sha256: cde8b944c2dc378a5afbc48028d0843583fd215493d5885a80f1b41de085552f + md5: 9207ebad7cfbe2a4af0702c92fd031c4 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.0,<3.0a0 + - libffi >=3.4.6,<3.5.0a0 + - liblzma >=5.8.1,<6.0a0 + - libsqlite >=3.50.0,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.0,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + size: 13009234 + timestamp: 1749048134449 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda build_number: 7 sha256: a1bbced35e0df66cc713105344263570e835625c28d1bdee8f748f482b2d7793 @@ -1224,6 +2047,15 @@ packages: license_family: GPL size: 282480 timestamp: 1740379431762 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + sha256: 7db04684d3904f6151eff8673270922d31da1eea7fa73254d01c437f49702e34 + md5: 63ef3f6e6d6d5c589e64f11263dc5676 + depends: + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 252359 + timestamp: 1740379663071 - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.3-hd590300_2.conda sha256: 475f68cac8981ff2b10c56e53c2f376fc3c805fbc7ec30d22f870cd88f1479ba md5: 4cabe3858a856bff08d9a0992e413084 @@ -1233,6 +2065,15 @@ packages: license_family: MIT size: 184509 timestamp: 1693427593121 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.5-h7ab814d_0.conda + sha256: e6a3e9dbfcb5ad5d69a20c8ac237d37a282a95983314a28912fc54208c5db391 + md5: 352b210f81798ae1e2f25a98ef4b3b54 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 177240 + timestamp: 1728886815751 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 md5: 4de79c071274a53dcaf2a8c749d1499e @@ -1252,6 +2093,28 @@ packages: license_family: GPL size: 15166921 timestamp: 1735290488259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2021.9.0-hf52228f_0.conda + sha256: 86352f4361e8dc2374a95d9d1dfee742beecaa59dcb0e76ca36ca06a4efe1df2 + md5: f495e42d3d2020b025705625edf35490 + depends: + - libgcc-ng >=12 + - libhwloc >=2.9.1,<2.9.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 1527865 + timestamp: 1681486787952 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.1.0-h9541205_0.conda + sha256: 3a7442e806f36b2b7efeaad88c330cdc5f24ceea8eb1ccdb7b428e4797d54733 + md5: fba14047c046475a82806c17885ba7fa + depends: + - __osx >=11.0 + - libcxx >=18 + - libhwloc >=2.11.2,<2.11.3.0a0 + license: Apache-2.0 + license_family: APACHE + size: 119289 + timestamp: 1743578923826 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e md5: d453b98d9c83e71da0741bb0ff4d76bc @@ -1262,6 +2125,16 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda + sha256: cb86c522576fa95c6db4c878849af0bccfd3264daf0cc40dd18e7f4a7bfced0e + md5: 7362396c170252e7b7b0c8fb37fe9c78 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + size: 3125538 + timestamp: 1748388189063 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda sha256: 18636339a79656962723077df9a56c0ac7b8a864329eb8f847ee3d38495b863e md5: ac944244f1fed2eb49bae07193ae8215 @@ -1287,6 +2160,15 @@ packages: license: LicenseRef-Public-Domain size: 122968 timestamp: 1742727099393 +- conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda + sha256: 1b34021e815ff89a4d902d879c3bd2040bc1bd6169b32e9427497fa05c55f1ce + md5: 75cb7132eb58d97896e173ef12ac9986 + depends: + - python >=3.9 + license: MIT + license_family: MIT + size: 62931 + timestamp: 1733130309598 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-fixesproto-5.0-hb9d3cd8_1003.conda sha256: 07268980b659a84a4bac64b475329348e9cf5fa4aee255fa94aa0407ae5b804c md5: 19fe37721037acc0a1ed76b8cf937359 @@ -1474,6 +2356,16 @@ packages: license_family: Other size: 92883 timestamp: 1716874088980 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda + sha256: 58f8860756680a4831c1bf4f294e2354d187f2e999791d53b1941834c4b37430 + md5: e3170d898ca6cb48f1bb567afb92f775 + depends: + - __osx >=11.0 + - libzlib 1.3.1 h8359307_2 + license: Zlib + license_family: Other + size: 77606 + timestamp: 1727963209370 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda sha256: c558b9cc01d9c1444031bd1ce4b9cff86f9085765f17627a6cd85fc623c8a02b md5: 4d056880988120e29d75bfff282e0f45 @@ -1485,3 +2377,13 @@ packages: license_family: BSD size: 554846 timestamp: 1714722996770 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-h6491c7d_2.conda + sha256: 0d02046f57f7a1a3feae3e9d1aa2113788311f3cf37a3244c71e61a93177ba67 + md5: e6f69c7bcccdefa417f056fa593b40f0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 399979 + timestamp: 1742433432699 diff --git a/pixi.toml b/pixi.toml index c53510a..3067927 100644 --- a/pixi.toml +++ b/pixi.toml @@ -15,17 +15,11 @@ cmake = ">=3.24.1,<4.0" ninja = ">=1.13.0,<2" make = "*" pkg-config = "*" -gcc = "*" -gxx = "*" zlib = "*" libpng = ">=1.6.43,<2" libjpeg-turbo = "*" freetype = "*" harfbuzz = "*" -libuuid = "*" -libdrm = "*" -libxcb = "*" -libva = "*" libass = "*" fontconfig = "*" expat = "*" @@ -34,9 +28,20 @@ pcre = "*" graphite2 = "*" fribidi = "*" brotli = "*" -alsa-lib = "*" +tbb = ">=2021.9.0,<2023" pytest = ">=8.4.1,<9" setuptools = ">=80.9.0,<81" jpeg = ">=9e,<10a" libvorbis = ">=1.3.7,<2" numpy = "<2.0" +pip = ">=25.1.1,<26" + + +[target.linux-64.dependencies] +gcc = "*" +gxx = "*" +libdrm = "*" +libxcb = "*" +libva = "*" +alsa-lib = "*" +libuuid = "*" \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e8ef3b1..062e41b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,6 @@ repository = "https://github.com/Pico-Developer/SpatialMP4" run-tests = false [tool.cibuildwheel] -before-all = "bash scripts/build_ffmpeg.sh && bash scripts/install_deps.sh" +before-all = "bash scripts/install_deps.sh && bash scripts/build_ffmpeg.sh" build = "cp3*-*" -skip = "pp* *-win32 *-win_amd64" +skip = "pp* *-win32 *-win_amd64" \ No newline at end of file diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh index cb113a1..97f7c38 100755 --- a/scripts/build_ffmpeg.sh +++ b/scripts/build_ffmpeg.sh @@ -7,11 +7,10 @@ cur=$(dirname $_curfile) opt=$cur/build_ffmpeg INSTALL_PREFIX=$opt/ffmpeg_install -PIXI_ROOT=$cur/../.pixi/envs/default CMAKE_EXTRA_CONFIG="" -if [ -d $PIXI_ROOT ];then - INSTALL_PREFIX=$PIXI_ROOT - CMAKE_EXTRA_CONFIG="-DCMAKE_INCLUDE_PATH=${PIXI_ROOT}/include" +if [ -n "$CONDA_PREFIX" ];then + INSTALL_PREFIX=$CONDA_PREFIX + CMAKE_EXTRA_CONFIG="-DCMAKE_INCLUDE_PATH=${CONDA_PREFIX}/include" fi echo "INSTALL_PREFIX: $INSTALL_PREFIX" @@ -106,19 +105,19 @@ build_install_ffmpeg() { --disable-ffplay \ --disable-doc \ ${EXTRA_CONFIG} - # --enable-libmp3lame \ - make $make_args V=1 + make $make_args # V=1 make install } + build_install_opencv() { - if [[ "$(uname)" == "Darwin" ]];then - # Darwin don't need to install opencv from source + if [[ "$(uname)" == "Darwin" && -z "$CONDA_PREFIX" ]];then + # Darwin without pixi don't need to install opencv from source return fi - opencv_version="4.5.0" + opencv_version="4.6.0" cd $opt if [ ! -d opencv ];then git clone https://github.com/opencv/opencv.git -b ${opencv_version} @@ -171,6 +170,9 @@ build_install_opencv() { " cd $opt/opencv + git reset --hard $opencv_version + git apply $cur/opencv_460_on_macos.patch + if [ -d release ];then rm -rf release fi @@ -183,6 +185,8 @@ build_install_opencv() { make install } -# install_deps +if [ -z "$CONDA_PREFIX" ];then + install_deps +fi build_install_ffmpeg -# build_install_opencv \ No newline at end of file +build_install_opencv \ No newline at end of file diff --git a/scripts/opencv_460_on_macos.patch b/scripts/opencv_460_on_macos.patch new file mode 100644 index 0000000..1d9c828 --- /dev/null +++ b/scripts/opencv_460_on_macos.patch @@ -0,0 +1,28 @@ +diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h +index 583c26f9bd..ca7bd6ffaf 100644 +--- a/3rdparty/libpng/pngpriv.h ++++ b/3rdparty/libpng/pngpriv.h +@@ -524,7 +524,7 @@ + * if possible. + */ + # if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +-# include ++# include + # endif + # else + # include +diff --git a/3rdparty/zlib/zutil.h b/3rdparty/zlib/zutil.h +index d9a20ae1bf..f9b0694163 100644 +--- a/3rdparty/zlib/zutil.h ++++ b/3rdparty/zlib/zutil.h +@@ -142,10 +142,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + # ifndef Z_SOLO + # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os + # include /* for fdopen */ +-# else +-# ifndef fdopen +-# define fdopen(fd,mode) NULL /* No fdopen() */ +-# endif + # endif + # endif + #endif From de6700fb77c127b22e805595f60baa5da2a52150 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 15:33:47 +0800 Subject: [PATCH 07/31] update pyproject.toml --- .gitignore | 3 +++ pyproject.toml | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index 1870030..2615167 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,6 @@ wheelhouse # mac .DS_Store + +# python build +dist/* diff --git a/pyproject.toml b/pyproject.toml index 062e41b..8995a95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,16 @@ dependencies = [ "numpy", "opencv-python" ] +dependencies-dev = [ + "pytest", + "setuptools", + "pip", + "wheel", + "twine", + "cmeel", + "cmake", + "build", +] [project.urls] repository = "https://github.com/Pico-Developer/SpatialMP4" From 89579483e7ac523d806c7ef3f0c95dc42ef565a9 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 15:57:05 +0800 Subject: [PATCH 08/31] fix bug --- .github/workflows/build_wheels.yml | 5 +- pixi.lock | 842 ----------------------------- pixi.toml | 1 - scripts/install_deps.sh | 10 +- 4 files changed, 12 insertions(+), 846 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index e4f50be..96bc9db 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -30,13 +30,14 @@ jobs: run: | python -m pip install --upgrade pip pip install cmeel[build] + pip install build - name: Build wheels env: CIBW_BEFORE_BUILD: | - bash scripts/build_ffmpeg.sh bash scripts/install_deps.sh + bash scripts/build_ffmpeg.sh CIBW_BUILD: "cp3*-*" CIBW_SKIP: "pp* *-win32 *-win_amd64" run: | - python -m cibuildwheel --output-dir wheelhouse \ No newline at end of file + python -m build --wheel \ No newline at end of file diff --git a/pixi.lock b/pixi.lock index c3cd983..33ba5c8 100644 --- a/pixi.lock +++ b/pixi.lock @@ -134,96 +134,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.1.0-h5505292_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.1.0-h5505292_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.5-h5505292_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-h6a3b0d2_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.31.6-ha25475f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.0-h286801f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.15.0-h1383a14_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.13.3-hce30654_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.10-h27ca646_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-2.84.2-h85e5b2e_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.84.2-h1dc7a0c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-h286801f_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-11.2.1-hab40de2_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jpeg-9e-he4db4b2_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libass-0.17.4-hcbd7ca7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-32_h10e41b3_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-h5505292_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-h5505292_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-h5505292_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-32_hb3479ef_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.14.1-h73640d1_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-20.1.7-ha82da77_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.0-h286801f_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.13.3-hce30654_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.13.3-h1d14073_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-14_2_0_h6c33f7e_103.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-14.2.0-h6c33f7e_103.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.84.2-hbec27ea_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwloc-2.11.2-default_hbce5d74_1001.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-hfe07756_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.24.2-h493aca8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-devel-0.24.2-h493aca8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-2.1.4-h1a8c8d9_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-32_hc9a63f6_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.64.0-h6d7220d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libogg-1.3.5-h48c0fde_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_hf332438_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.49-h3783ad8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.2-h6fb428d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h5505292_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libvorbis-1.3.7-h9f76cd9_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.13.8-h52572c6_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-20.1.7-hdb05f8b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/make-4.4.1-hc9fafa5_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.0-ha024513_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.1-h81ee809_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre-8.45-hbdafb3b_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.45-ha881caa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.1.1-pyh8b19718_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.2-h2f9eb0b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pkg-config-0.29.2-hde07d2e_1009.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.11-hc22306f_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.5-h7ab814d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.1.0-h9541205_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.14.0-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-h6491c7d_2.conda packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 @@ -276,18 +186,6 @@ packages: license_family: MIT size: 19810 timestamp: 1749230148642 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.1.0-h5505292_3.conda - sha256: 97e2a90342869cc122921fdff0e6be2f5c38268555c08ba5d14e1615e4637e35 - md5: 03c7865dd4dbf87b7b7d363e24c632f1 - depends: - - __osx >=11.0 - - brotli-bin 1.1.0 h5505292_3 - - libbrotlidec 1.1.0 h5505292_3 - - libbrotlienc 1.1.0 h5505292_3 - license: MIT - license_family: MIT - size: 20094 - timestamp: 1749230390021 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.1.0-hb9d3cd8_3.conda sha256: ab74fa8c3d1ca0a055226be89e99d6798c65053e2d2d3c6cb380c574972cd4a7 md5: 58178ef8ba927229fba6d84abf62c108 @@ -300,17 +198,6 @@ packages: license_family: MIT size: 19390 timestamp: 1749230137037 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.1.0-h5505292_3.conda - sha256: 5c6a808326c3bbb6f015a57c9eb463d65f259f67154f4f06783d8829ce9239b4 - md5: cc435eb5160035fd8503e9a58036c5b5 - depends: - - __osx >=11.0 - - libbrotlidec 1.1.0 h5505292_3 - - libbrotlienc 1.1.0 h5505292_3 - license: MIT - license_family: MIT - size: 17185 - timestamp: 1749230373519 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d md5: 62ee74e96c5ebb0af99386de58cf9553 @@ -321,15 +208,6 @@ packages: license_family: BSD size: 252783 timestamp: 1720974456583 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda - sha256: adfa71f158cbd872a36394c56c3568e6034aa55c623634b37a4836bd036e6b91 - md5: fc6948412dbbbe9a4c9ddbbcfe0a79ab - depends: - - __osx >=11.0 - license: bzip2-1.0.6 - license_family: BSD - size: 122909 - timestamp: 1720974522888 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.5-hb9d3cd8_0.conda sha256: f8003bef369f57396593ccd03d08a8e21966157269426f71e943f96e4b579aeb md5: f7f0d6cc2dc986d42ac2689ec88192be @@ -340,15 +218,6 @@ packages: license_family: MIT size: 206884 timestamp: 1744127994291 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.5-h5505292_0.conda - sha256: b4bb55d0806e41ffef94d0e3f3c97531f322b3cb0ca1f7cdf8e47f62538b7a2b - md5: f8cd1beb98240c7edb1a95883360ccfa - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 179696 - timestamp: 1744128058734 - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.6.15-hbd8a1cb_0.conda sha256: 7cfec9804c84844ea544d98bda1d9121672b66ff7149141b8415ca42dfcd44f6 md5: 72525f07d72806e3b639ad4504c30ce5 @@ -380,24 +249,6 @@ packages: license: LGPL-2.1-only or MPL-1.1 size: 1576122 timestamp: 1663568213559 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-h6a3b0d2_0.conda - sha256: 00439d69bdd94eaf51656fdf479e0c853278439d22ae151cabf40eb17399d95f - md5: 38f6df8bc8c668417b904369a01ba2e2 - depends: - - __osx >=11.0 - - fontconfig >=2.15.0,<3.0a0 - - fonts-conda-ecosystem - - freetype >=2.12.1,<3.0a0 - - icu >=75.1,<76.0a0 - - libcxx >=18 - - libexpat >=2.6.4,<3.0a0 - - libglib >=2.82.2,<3.0a0 - - libpng >=1.6.47,<1.7.0a0 - - libzlib >=1.3.1,<2.0a0 - - pixman >=0.44.2,<1.0a0 - license: LGPL-2.1-only or MPL-1.1 - size: 896173 - timestamp: 1741554795915 - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.26.4-hcfe8598_0.conda sha256: 37533b572a676017704c989c392998c344e889010786d6555dccdfc524a8e238 md5: 1714cf0f0facaeb609a0846e4270aff2 @@ -419,25 +270,6 @@ packages: license_family: BSD size: 16343060 timestamp: 1684460894541 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.31.6-ha25475f_0.conda - sha256: d71e84b6b7000323d2a394c3e01cfd35df3421741e8b4af7852e8400c2604574 - md5: 3a3bbf1de0a6d99658f4c1b63ad40d21 - depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libcurl >=8.12.1,<9.0a0 - - libcxx >=18 - - libexpat >=2.6.4,<3.0a0 - - liblzma >=5.6.4,<6.0a0 - - libuv >=1.50.0,<2.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - rhash >=1.4.5,<1.4.6a0 - - zstd >=1.5.7,<1.6.0a0 - license: BSD-3-Clause - license_family: BSD - size: 16507414 - timestamp: 1740467905288 - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 md5: 962b9857ee8e7018c22f2776ffa0b2d7 @@ -476,16 +308,6 @@ packages: license_family: MIT size: 140050 timestamp: 1743431809745 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.0-h286801f_0.conda - sha256: df45bc695f88f252e6fee20faac11621d294b9d22d92972fab7def23d4613501 - md5: 6f54d1a312ca354072b7d79aa0d31eb9 - depends: - - __osx >=11.0 - - libexpat 2.7.0 h286801f_0 - license: MIT - license_family: MIT - size: 127135 - timestamp: 1743431804373 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 @@ -527,18 +349,6 @@ packages: license_family: MIT size: 272010 timestamp: 1674828850194 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.15.0-h1383a14_1.conda - sha256: f79d3d816fafbd6a2b0f75ebc3251a30d3294b08af9bb747194121f5efa364bc - md5: 7b29f48742cea5d1ccb5edd839cb5621 - depends: - - __osx >=11.0 - - freetype >=2.12.1,<3.0a0 - - libexpat >=2.6.3,<3.0a0 - - libzlib >=1.3.1,<2.0a0 - license: MIT - license_family: MIT - size: 234227 - timestamp: 1730284037572 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 md5: fee5683a3f04bd15cbd8318b096a27ab @@ -570,15 +380,6 @@ packages: license: GPL-2.0-only OR FTL size: 634972 timestamp: 1694615932610 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.13.3-hce30654_1.conda - sha256: 6b63c72ea51a41d41964841404564c0729fdddd3e952e2715839fd759b7cfdfc - md5: e684de4644067f1956a580097502bf03 - depends: - - libfreetype 2.13.3 hce30654_1 - - libfreetype6 2.13.3 h1d14073_1 - license: GPL-2.0-only OR FTL - size: 172220 - timestamp: 1745370149658 - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.10-h36c2ea0_0.tar.bz2 sha256: 5d7b6c0ee7743ba41399e9e05a58ccc1cfc903942e49ff6f677f6e423ea7a627 md5: ac7bc6a654f8f41b352b38f4051135f8 @@ -587,12 +388,6 @@ packages: license: LGPL-2.1 size: 114383 timestamp: 1604416621168 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.10-h27ca646_0.tar.bz2 - sha256: 4b37ea851a2cf85edf0a63d2a63266847ec3dcbba4a31156d430cdd6aa811303 - md5: c64443234ff91d70cb9c7dc926c58834 - license: LGPL-2.1 - size: 60255 - timestamp: 1604417405528 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-15.1.0-h33e79ad_3.conda sha256: 69cc03e5b20e064ad5a9ac88ac3b792a1b089c838fa4ab5eb56990a9c166ce5a md5: 45ddc7242fed76e1b4ff5ee062e6d926 @@ -630,20 +425,6 @@ packages: license: LGPL-2.1-or-later size: 600389 timestamp: 1715252749399 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-2.84.2-h85e5b2e_0.conda - sha256: 43ea91eee25abe882f34a1b709ddb2bc51dcb18e4c16d0484f9003cd67347d8e - md5: 01fbc39f2524b2788b81b8044a780dba - depends: - - glib-tools 2.84.2 h1dc7a0c_0 - - libffi >=3.4.6,<3.5.0a0 - - libglib 2.84.2 hbec27ea_0 - - libintl >=0.24.1,<1.0a0 - - libintl-devel - - packaging - - python * - license: LGPL-2.1-or-later - size: 591283 - timestamp: 1747837135361 - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.80.2-hb6ce0ca_0.conda sha256: 221cd047f998301b96b1517d9f7d3fb0e459e8ee18778a1211f302496f6e110d md5: a965aeaf060289528a3fbe09326edae2 @@ -653,16 +434,6 @@ packages: license: LGPL-2.1-or-later size: 114359 timestamp: 1715252713902 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/glib-tools-2.84.2-h1dc7a0c_0.conda - sha256: 809cb62fe75ca0bcf0eecd223d100b4b4aa4555eee4c3e335ab7f453506bbb78 - md5: c6dd3b852d7287ee3bf1d392f107f1ac - depends: - - __osx >=11.0 - - libglib 2.84.2 hbec27ea_0 - - libintl >=0.24.1,<1.0a0 - license: LGPL-2.1-or-later - size: 101786 - timestamp: 1747837093760 - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-h5888daf_0.conda sha256: cac69f3ff7756912bbed4c28363de94f545856b35033c0b86193366b95f5317d md5: 951ff8d9e5536896408e89d63230b8d5 @@ -674,16 +445,6 @@ packages: license_family: LGPL size: 98419 timestamp: 1750079957535 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.14-h286801f_0.conda - sha256: e1c431b66b0a632e8fcc2b886cccde4eb5ec5eb8a3d84e89b7639d603c174646 - md5: 64d15e1dfe86fa13cf0d519d1074dcd9 - depends: - - __osx >=11.0 - - libcxx >=18 - license: LGPL-2.0-or-later - license_family: LGPL - size: 81566 - timestamp: 1750080158744 - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-15.1.0-h33e79ad_3.conda sha256: b071ff43b64e9c8366411f1d2a8030fb9769c0c588ffa6e16a498957dba96f45 md5: 5917fb5bed3e2fa4fce4fbbe1b541946 @@ -721,25 +482,6 @@ packages: license_family: MIT size: 2096772 timestamp: 1656503454174 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/harfbuzz-11.2.1-hab40de2_0.conda - sha256: 244e4071229aa3b824dd2a9814c0e8b4c2b40dfb28914ec2247bf27c5c681584 - md5: 12f4520f618ff6e398a2c8e0bed1e580 - depends: - - __osx >=11.0 - - cairo >=1.18.4,<2.0a0 - - freetype - - graphite2 - - icu >=75.1,<76.0a0 - - libcxx >=18 - - libexpat >=2.7.0,<3.0a0 - - libfreetype >=2.13.3 - - libfreetype6 >=2.13.3 - - libglib >=2.84.1,<3.0a0 - - libzlib >=1.3.1,<2.0a0 - license: MIT - license_family: MIT - size: 1395282 - timestamp: 1747091793921 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-70.1-h27087fc_0.tar.bz2 sha256: 1d7950f3be4637ab915d886304e57731d39a41ab705ffc95c4681655c459374a md5: 87473a15119779e021c314249d4b4aed @@ -750,15 +492,6 @@ packages: license_family: MIT size: 14191488 timestamp: 1648050221778 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - sha256: 9ba12c93406f3df5ab0a43db8a4b4ef67a5871dfd401010fbe29b218b2cbe620 - md5: 5eb22c1d7b3fc4abb50d92d621583137 - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 11857802 - timestamp: 1720853997952 - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda sha256: 0ec8f4d02053cd03b0f3e63168316530949484f80e16f5e2fb199a1d117a89ca md5: 6837f3eff7dcea42ecd714ce1ac2b108 @@ -776,12 +509,6 @@ packages: license: IJG size: 275125 timestamp: 1656500806614 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/jpeg-9e-he4db4b2_2.tar.bz2 - sha256: 1175af9e55cb8a8bf24102c9aa9233f2a8d83845f2c01773c2a364a4c889464b - md5: ad1e3584bfef678a4ca6f9daa6695159 - license: IJG - size: 265558 - timestamp: 1656501164015 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda sha256: a922841ad80bd7b222502e65c07ecb67e4176c4fa5b03678a005f39fcc98be4b md5: ad8527bf134a90e1c9ed35fa0b64318c @@ -813,19 +540,6 @@ packages: license_family: MIT size: 1329877 timestamp: 1671091750695 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - sha256: 4442f957c3c77d69d9da3521268cad5d54c9033f1a73f99cde0a3658937b159b - md5: c6dc8a0fdec13a0565936655c33069a1 - depends: - - __osx >=11.0 - - libcxx >=16 - - libedit >=3.1.20191231,<3.2.0a0 - - libedit >=3.1.20191231,<4.0a0 - - openssl >=3.3.1,<4.0a0 - license: MIT - license_family: MIT - size: 1155530 - timestamp: 1719463474401 - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_5.conda sha256: de097284f497b391fe9d000c75b684583c30aad172d9508ed05df23ce39d75cb md5: acd9213a63cb62521290e581ef82de80 @@ -853,22 +567,6 @@ packages: license_family: OTHER size: 122389 timestamp: 1647824984482 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libass-0.17.4-hcbd7ca7_0.conda - sha256: 079f5fdf7aace970a0db91cd2cc493c754dfdc4520d422ecec43d2561021167a - md5: 0977f4a79496437ff3a2c97d13c4c223 - depends: - - __osx >=11.0 - - fontconfig >=2.15.0,<3.0a0 - - fonts-conda-ecosystem - - libzlib >=1.3.1,<2.0a0 - - fribidi >=1.0.10,<2.0a0 - - libiconv >=1.18,<2.0a0 - - harfbuzz >=11.0.1 - - libfreetype >=2.13.3 - - libfreetype6 >=2.13.3 - license: ISC - size: 138339 - timestamp: 1749328988096 - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-32_h59b9bed_openblas.conda build_number: 32 sha256: 1540bf739feb446ff71163923e7f044e867d163c50b605c8b421c55ff39aa338 @@ -886,23 +584,6 @@ packages: license_family: BSD size: 17330 timestamp: 1750388798074 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-32_h10e41b3_openblas.conda - build_number: 32 - sha256: 2775472dd81d43dc20804b484028560bfecd5ab4779e39f1fb95684da3ff2029 - md5: d4a1732d2b330c9d5d4be16438a0ac78 - depends: - - libopenblas >=0.3.30,<0.3.31.0a0 - - libopenblas >=0.3.30,<1.0a0 - constrains: - - blas 2.132 openblas - - liblapack 3.9.0 32*_openblas - - mkl <2025 - - libcblas 3.9.0 32*_openblas - - liblapacke 3.9.0 32*_openblas - license: BSD-3-Clause - license_family: BSD - size: 17520 - timestamp: 1750388963178 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hb9d3cd8_3.conda sha256: 462a8ed6a7bb9c5af829ec4b90aab322f8bcd9d8987f793e6986ea873bbd05cf md5: cb98af5db26e3f482bebb80ce9d947d3 @@ -913,15 +594,6 @@ packages: license_family: MIT size: 69233 timestamp: 1749230099545 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-h5505292_3.conda - sha256: 0e9c196ad8569ca199ea05103707cde0ae3c7e97d0cdf0417d873148ea9ad640 - md5: fbc4d83775515e433ef22c058768b84d - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 68972 - timestamp: 1749230317752 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hb9d3cd8_3.conda sha256: 3eb27c1a589cbfd83731be7c3f19d6d679c7a444c3ba19db6ad8bf49172f3d83 md5: 1c6eecffad553bde44c5238770cfb7da @@ -933,16 +605,6 @@ packages: license_family: MIT size: 33148 timestamp: 1749230111397 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-h5505292_3.conda - sha256: d888c228e7d4f0f2303538f6a9705498c81d56fedaab7811e1186cb6e24d689b - md5: 01c4b35a1c4b94b60801f189f1ac6ee3 - depends: - - __osx >=11.0 - - libbrotlicommon 1.1.0 h5505292_3 - license: MIT - license_family: MIT - size: 29249 - timestamp: 1749230338861 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb9d3cd8_3.conda sha256: 76e8492b0b0a0d222bfd6081cae30612aa9915e4309396fdca936528ccf314b7 md5: 3facafe58f3858eb95527c7d3a3fc578 @@ -954,16 +616,6 @@ packages: license_family: MIT size: 282657 timestamp: 1749230124839 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-h5505292_3.conda - sha256: 0734a54db818ddfdfbf388fa53c5036a06bbe17de14005f33215d865d51d8a5e - md5: 1ce5e315293309b5bf6778037375fb08 - depends: - - __osx >=11.0 - - libbrotlicommon 1.1.0 h5505292_3 - license: MIT - license_family: MIT - size: 274404 - timestamp: 1749230355483 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-32_he106b2a_openblas.conda build_number: 32 sha256: 92a001fc181e6abe4f4a672b81d9413ca2f22609f8a95327dfcc6eee593ffeb9 @@ -978,20 +630,6 @@ packages: license_family: BSD size: 17308 timestamp: 1750388809353 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-32_hb3479ef_openblas.conda - build_number: 32 - sha256: 25d46ace14c3ac45d4aa18b5f7a0d3d30cec422297e900f8b97a66334232061c - md5: d8e8ba717ae863b13a7495221f2b5a71 - depends: - - libblas 3.9.0 32_h10e41b3_openblas - constrains: - - blas 2.132 openblas - - liblapack 3.9.0 32*_openblas - - liblapacke 3.9.0 32*_openblas - license: BSD-3-Clause - license_family: BSD - size: 17485 - timestamp: 1750388970626 - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.1.2-h409715c_0.conda sha256: d572c31ff48d2db6ca5bab476bf325811cfc82577480b3791487c3fe7bff2ffa md5: 50c873c9660ed116707ae15b663928d8 @@ -1007,30 +645,6 @@ packages: license_family: MIT size: 372833 timestamp: 1685447685782 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.14.1-h73640d1_0.conda - sha256: 0055b68137309db41ec34c938d95aec71d1f81bd9d998d5be18f32320c3ccba0 - md5: 1af57c823803941dfc97305248a56d57 - depends: - - __osx >=11.0 - - krb5 >=1.21.3,<1.22.0a0 - - libnghttp2 >=1.64.0,<2.0a0 - - libssh2 >=1.11.1,<2.0a0 - - libzlib >=1.3.1,<2.0a0 - - openssl >=3.5.0,<4.0a0 - - zstd >=1.5.7,<1.6.0a0 - license: curl - license_family: MIT - size: 403456 - timestamp: 1749033320430 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-20.1.7-ha82da77_0.conda - sha256: a3fd34773f1252a4f089e74a075ff5f0f6b878aede097e83a405f35687c36f24 - md5: 881de227abdddbe596239fa9e82eb3ab - depends: - - __osx >=11.0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 567189 - timestamp: 1749847129529 - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb9d3cd8_0.conda sha256: f53458db897b93b4a81a6dbfd7915ed8fa4a54951f97c698dde6faa028aadfd2 md5: 4c0ab57463117fbb8df85268415082f5 @@ -1054,17 +668,6 @@ packages: license_family: BSD size: 134676 timestamp: 1738479519902 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 - md5: 44083d2d2c2025afca315c7a172eab2b - depends: - - ncurses - - __osx >=11.0 - - ncurses >=6.5,<7.0a0 - license: BSD-2-Clause - license_family: BSD - size: 107691 - timestamp: 1738479560845 - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 md5: 172bf1cd1ff8629f2b1179945ed45055 @@ -1074,13 +677,6 @@ packages: license_family: BSD size: 112766 timestamp: 1702146165126 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f - md5: 36d33e440c31857372a72137f78bacf5 - license: BSD-2-Clause - license_family: BSD - size: 107458 - timestamp: 1702146414478 - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.0-h5888daf_0.conda sha256: 33ab03438aee65d6aa667cf7d90c91e5e7d734c19a67aa4c7040742c0a13d505 md5: db0bfbe7dd197b68ad5f30333bae6ce0 @@ -1093,17 +689,6 @@ packages: license_family: MIT size: 74427 timestamp: 1743431794976 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.0-h286801f_0.conda - sha256: ee550e44765a7bbcb2a0216c063dcd53ac914a7be5386dd0554bd06e6be61840 - md5: 6934bbb74380e045741eb8637641a65b - depends: - - __osx >=11.0 - constrains: - - expat 2.7.0.* - license: MIT - license_family: MIT - size: 65714 - timestamp: 1743431789879 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab md5: ede4673863426c0883c0063d853bbd85 @@ -1114,35 +699,6 @@ packages: license_family: MIT size: 57433 timestamp: 1743434498161 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda - sha256: c6a530924a9b14e193ea9adfe92843de2a806d1b7dbfd341546ece9653129e60 - md5: c215a60c2935b517dcda8cad4705734d - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 39839 - timestamp: 1743434670405 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.13.3-hce30654_1.conda - sha256: 1f8c16703fe333cdc2639f7cdaf677ac2120843453222944a7c6c85ec342903c - md5: d06282e08e55b752627a707d58779b8f - depends: - - libfreetype6 >=2.13.3 - license: GPL-2.0-only OR FTL - size: 7813 - timestamp: 1745370144506 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.13.3-h1d14073_1.conda - sha256: c278df049b1a071841aa0aca140a338d087ea594e07dcf8a871d2cfe0e330e75 - md5: b163d446c55872ef60530231879908b9 - depends: - - __osx >=11.0 - - libpng >=1.6.47,<1.7.0a0 - - libzlib >=1.3.1,<2.0a0 - constrains: - - freetype >=2.13.3 - license: GPL-2.0-only OR FTL - size: 333529 - timestamp: 1745370142848 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 md5: 9e60c55e725c20d23125a5f0dd69af5d @@ -1185,15 +741,6 @@ packages: license_family: GPL size: 29057 timestamp: 1750808257258 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-14_2_0_h6c33f7e_103.conda - sha256: 8628746a8ecd311f1c0d14bb4f527c18686251538f7164982ccbe3b772de58b5 - md5: 044a210bc1d5b8367857755665157413 - depends: - - libgfortran5 14.2.0 h6c33f7e_103 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - size: 156291 - timestamp: 1743863532821 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a md5: 530566b68c3b8ce7eec4cd047eae19fe @@ -1206,17 +753,6 @@ packages: license_family: GPL size: 1565627 timestamp: 1750808236464 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-14.2.0-h6c33f7e_103.conda - sha256: 8599453990bd3a449013f5fa3d72302f1c68f0680622d419c3f751ff49f01f17 - md5: 69806c1e957069f1d515830dcc9f6cbb - depends: - - llvm-openmp >=8.0.0 - constrains: - - libgfortran 5.0.0 14_2_0_*_103 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - size: 806566 - timestamp: 1743863491726 - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda sha256: 93e03b6cf4765bc06d64fa3dac65f22c53ae4a30247bb0e2dea0bd9c47a3fb26 md5: 72724f6a78ecb15559396966226d5838 @@ -1231,21 +767,6 @@ packages: license: LGPL-2.1-or-later size: 3912673 timestamp: 1715252654366 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.84.2-hbec27ea_0.conda - sha256: 5fcc5e948706cc64e45e2454267f664ed5a1e84f15345aae04a41d852a879c0e - md5: 7bbb8961dca1b4b9f2b01b6e722111a7 - depends: - - __osx >=11.0 - - libffi >=3.4.6,<3.5.0a0 - - libiconv >=1.18,<2.0a0 - - libintl >=0.24.1,<1.0a0 - - libzlib >=1.3.1,<2.0a0 - - pcre2 >=10.45,<10.46.0a0 - constrains: - - glib 2.84.2 *_0 - license: LGPL-2.1-or-later - size: 3666180 - timestamp: 1747837044507 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_3.conda sha256: 43710ab4de0cd7ff8467abff8d11e7bb0e36569df04ce1c099d48601818f11d1 md5: 3cd1a7238a0dd3d0860fdefc496cc854 @@ -1266,17 +787,6 @@ packages: license_family: BSD size: 2569104 timestamp: 1680713440274 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwloc-2.11.2-default_hbce5d74_1001.conda - sha256: dcac7144ad93cf3f276ec14c5553aa34de07443a9b1db6b3cd8d2e117b173c40 - md5: ff6438cf47cff4899ae9900bf9253c41 - depends: - - __osx >=11.0 - - libcxx >=18 - - libxml2 >=2.13.4,<2.14.0a0 - license: BSD-3-Clause - license_family: BSD - size: 2332319 - timestamp: 1731375088576 - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h4ce23a2_1.conda sha256: 18a4afe14f731bfb9cf388659994263904d20111e42f841e9eea1bb6f91f4ab4 md5: e796ff8ddc598affdf7c173d6145f087 @@ -1286,33 +796,6 @@ packages: license: LGPL-2.1-only size: 713084 timestamp: 1740128065462 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-hfe07756_1.conda - sha256: d30780d24bf3a30b4f116fca74dedb4199b34d500fe6c52cced5f8cc1e926f03 - md5: 450e6bdc0c7d986acf7b8443dce87111 - depends: - - __osx >=11.0 - license: LGPL-2.1-only - size: 681804 - timestamp: 1740128227484 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.24.2-h493aca8_0.conda - sha256: aebb3357d4b6e00996b15917d9a4061c3c17e1ee191b7226d2c1317ac049a62a - md5: 2dc5359f33b7038d3a35a2d2defeb608 - depends: - - __osx >=11.0 - - libiconv >=1.18,<2.0a0 - license: LGPL-2.1-or-later - size: 90769 - timestamp: 1751465374263 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-devel-0.24.2-h493aca8_0.conda - sha256: 1e5f0f5ba34ac085fdb7453dd73404e10706c3d44949c2d237014362cceca72e - md5: f8bfc03eb84a19b82d9f056125d63b0c - depends: - - __osx >=11.0 - - libiconv >=1.18,<2.0a0 - - libintl 0.24.2 h493aca8_0 - license: LGPL-2.1-or-later - size: 40105 - timestamp: 1751465417290 - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 sha256: 0d8b666ca4deabf948a76654df0fa1277145bed1c9e8a58e18a649c22c5f1c3e md5: b4f717df2d377410b462328bf0e8fb7d @@ -1321,12 +804,6 @@ packages: license: IJG, modified 3-clause BSD and zlib size: 1011471 timestamp: 1664781971968 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-2.1.4-h1a8c8d9_0.tar.bz2 - sha256: 34dc289e85fbfabbf763edf6ad83dba25d11934749580ef1d4080fbacf3530f3 - md5: bd550dd10ccf96d75a16a0d7194aacf7 - license: IJG, modified 3-clause BSD and zlib - size: 854754 - timestamp: 1664782154413 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-32_h7ac8fdf_openblas.conda build_number: 32 sha256: 5b55a30ed1b3f8195dad9020fe1c6d0f514829bfaaf0cf5e393e93682af009f2 @@ -1341,20 +818,6 @@ packages: license_family: BSD size: 17316 timestamp: 1750388820745 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-32_hc9a63f6_openblas.conda - build_number: 32 - sha256: 5e1cfa3581d1dec6b07a75084ff6cfa4b4465c646c6884a71c78a28543f83b61 - md5: bf9ead3fa92fd75ad473c6a1d255ffcb - depends: - - libblas 3.9.0 32_h10e41b3_openblas - constrains: - - blas 2.132 openblas - - libcblas 3.9.0 32*_openblas - - liblapacke 3.9.0 32*_openblas - license: BSD-3-Clause - license_family: BSD - size: 17507 - timestamp: 1750388977861 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8 md5: 1a580f7796c7bf6393fddb8bbbde58dc @@ -1366,16 +829,6 @@ packages: license: 0BSD size: 112894 timestamp: 1749230047870 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285 - md5: d6df911d4564d77c4374b02552cb17d1 - depends: - - __osx >=11.0 - constrains: - - xz 5.8.1.* - license: 0BSD - size: 92286 - timestamp: 1749230283517 - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.1-hb9d3cd8_2.conda sha256: 329e66330a8f9cbb6a8d5995005478188eb4ba8a6b6391affa849744f4968492 md5: f61edadbb301530bd65a32646bd81552 @@ -1400,21 +853,6 @@ packages: license_family: MIT size: 631397 timestamp: 1699440427647 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.64.0-h6d7220d_0.conda - sha256: 00cc685824f39f51be5233b54e19f45abd60de5d8847f1a56906f8936648b72f - md5: 3408c02539cee5f1141f9f11450b6a51 - depends: - - __osx >=11.0 - - c-ares >=1.34.2,<2.0a0 - - libcxx >=17 - - libev >=4.33,<4.34.0a0 - - libev >=4.33,<5.0a0 - - libzlib >=1.3.1,<2.0a0 - - openssl >=3.3.2,<4.0a0 - license: MIT - license_family: MIT - size: 566719 - timestamp: 1729572385640 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 @@ -1435,15 +873,6 @@ packages: license_family: BSD size: 218500 timestamp: 1745825989535 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libogg-1.3.5-h48c0fde_1.conda - sha256: 28bd1fe20fe43da105da41b95ac201e95a1616126f287985df8e86ddebd1c3d8 - md5: 29b8b11f6d7e6bd0e76c029dcf9dd024 - depends: - - __osx >=11.0 - license: BSD-3-Clause - license_family: BSD - size: 216719 - timestamp: 1745826006052 - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_0.conda sha256: 225f4cfdb06b3b73f870ad86f00f49a9ca0a8a2d2afe59440521fafe2b6c23d9 md5: 323dc8f259224d13078aaf7ce96c3efe @@ -1458,20 +887,6 @@ packages: license_family: BSD size: 5916819 timestamp: 1750379877844 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_hf332438_0.conda - sha256: 501c8c64f1a6e6b671e49835e6c483bc25f0e7147f3eb4bbb19a4c3673dcaf28 - md5: 5d7dbaa423b4c253c476c24784286e4b - depends: - - __osx >=11.0 - - libgfortran 5.* - - libgfortran5 >=13.3.0 - - llvm-openmp >=18.1.8 - constrains: - - openblas >=0.3.30,<0.3.31.0a0 - license: BSD-3-Clause - license_family: BSD - size: 4163399 - timestamp: 1750378829050 - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2 md5: 70e3400cbbfa03e96dcde7fc13e38c7b @@ -1491,15 +906,6 @@ packages: license: zlib-acknowledgement size: 288221 timestamp: 1708780443939 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.49-h3783ad8_0.conda - sha256: b1050f6da51de507eec6902367cc2a3f381dd548eaaccb85673784543dcdee1a - md5: 90be56ffd1a6b1950268f88c12e17c69 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: zlib-acknowledgement - size: 259291 - timestamp: 1750095759683 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-15.1.0-h97b714f_3.conda sha256: 75fa45d8ea2344bfe96667b478fd00f1d038026f399cb680eceec836c90e67bc md5: bbcff9bf972a0437bea8e431e4b327bb @@ -1520,15 +926,6 @@ packages: license: Unlicense size: 865346 timestamp: 1718050628718 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.2-h6fb428d_0.conda - sha256: 6b51a9e7366d6cd26e50d1d0646331d457999ebb88af258f06a74f075e95bf68 - md5: b2dc1707166040e738df2d514f8a1d22 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: Unlicense - size: 901519 - timestamp: 1751135765345 - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda sha256: 50e47fd9c4f7bf841a11647ae7486f65220cfc988ec422a4475fe8d5a823824d md5: 1f5a58e686b13bcfde88b93f547d23fe @@ -1540,16 +937,6 @@ packages: license_family: BSD size: 271133 timestamp: 1685837707056 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a - md5: b68e8f66b94b44aaa8de4583d3d4cc40 - depends: - - libzlib >=1.3.1,<2.0a0 - - openssl >=3.5.0,<4.0a0 - license: BSD-3-Clause - license_family: BSD - size: 279193 - timestamp: 1745608793272 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 md5: 6d11a5edae89fe413c0569f16d308f5a @@ -1597,15 +984,6 @@ packages: license_family: MIT size: 890145 timestamp: 1748304699136 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h5505292_0.conda - sha256: 41c1230a3f4e0d265e5053c671f112a16be4405b9047d3da5581e03e9d53de65 - md5: 230a885fe67a3e945a4586b944b6020a - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 420654 - timestamp: 1748304893204 - conda: https://conda.anaconda.org/conda-forge/linux-64/libva-2.18.0-h0b41bf4_0.conda sha256: e7254d0111a403ffe707e2ad39b6ce49a2be733e751d14a7255b0cb20da2a16b md5: 56e049224de34bbe0478aad422227942 @@ -1630,16 +1008,6 @@ packages: license_family: BSD size: 286280 timestamp: 1610609811627 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libvorbis-1.3.7-h9f76cd9_0.tar.bz2 - sha256: 60457217e20d8b24a8390c81338a8fa69c8656b440c067cd82f802a09da93cb9 - md5: 92a1a88d1a1d468c19d9e1659ac8d3df - depends: - - libcxx >=11.0.0 - - libogg >=1.3.4,<1.4.0a0 - license: BSD-3-Clause - license_family: BSD - size: 254839 - timestamp: 1610609991029 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.13-h7f98852_1004.tar.bz2 sha256: 8d5d24cbeda9282dd707edd3156e5fde2e3f3fe86c802fa7ce08c8f1e803bfd9 md5: b3653fdc58d03face9724f602218a904 @@ -1673,19 +1041,6 @@ packages: license_family: MIT size: 713891 timestamp: 1679341466192 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.13.8-h52572c6_0.conda - sha256: 13eb825eddce93761d965da3edaf3a42d868c61ece7d9cf21f7e2a13087c2abe - md5: d7884c7af8af5a729353374c189aede8 - depends: - - __osx >=11.0 - - icu >=75.1,<76.0a0 - - libiconv >=1.18,<2.0a0 - - liblzma >=5.8.1,<6.0a0 - - libzlib >=1.3.1,<2.0a0 - license: MIT - license_family: MIT - size: 583068 - timestamp: 1746634531197 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda sha256: 8ced4afed6322172182af503f21725d072a589a6eb918f8a58135c1e00d35980 md5: 27329162c0dc732bcf67a4e0cd488125 @@ -1697,28 +1052,6 @@ packages: license_family: Other size: 61571 timestamp: 1716874066944 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b - md5: 369964e85dc26bfe78f41399b366c435 - depends: - - __osx >=11.0 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - size: 46438 - timestamp: 1727963202283 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-20.1.7-hdb05f8b_0.conda - sha256: e7d95b50a90cdc9e0fc38bc37f493a61b9d08164114b562bbd9ff0034f45eca2 - md5: 741e1da0a0798d32e13e3724f2ca2dcf - depends: - - __osx >=11.0 - constrains: - - openmp 20.1.7|20.1.7.* - license: Apache-2.0 WITH LLVM-exception - license_family: APACHE - size: 281996 - timestamp: 1749892286735 - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda sha256: d652c7bd4d3b6f82b0f6d063b0d8df6f54cc47531092d7ff008e780f3261bdda md5: 33405d2a66b1411db9f7242c8b97c9e7 @@ -1729,15 +1062,6 @@ packages: license_family: GPL size: 513088 timestamp: 1727801714848 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/make-4.4.1-hc9fafa5_2.conda - sha256: 90ca65e788406d9029ae23ad4bd944a8b5353ad5f59bd6ce326f980cde46f37e - md5: 9f44ef1fea0a25d6a3491c58f3af8460 - depends: - - __osx >=11.0 - license: GPL-3.0-or-later - license_family: GPL - size: 274048 - timestamp: 1727801725384 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 @@ -1747,14 +1071,6 @@ packages: license: X11 AND BSD-3-Clause size: 891641 timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 - md5: 068d497125e4bf8a66bf707254fff5ae - depends: - - __osx >=11.0 - license: X11 AND BSD-3-Clause - size: 797030 - timestamp: 1738196177597 - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.0-h7aa8ee6_0.conda sha256: 8cf09470430b5aba5165c7aefed070d2c8f998f69fede01197ef838bf17fa81a md5: 2f67cb5c5ec172faeba94348ae8af444 @@ -1766,16 +1082,6 @@ packages: license_family: APACHE size: 180917 timestamp: 1750273173789 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.0-ha024513_0.conda - sha256: 2715f956c17f4c4240972567f710dea93f0ffe3073fb9bd0d636eba15c3ab2e6 - md5: 91f96a6daf4c14e45b3bbc71e3b8e1f8 - depends: - - libcxx >=18 - - __osx >=11.0 - license: Apache-2.0 - license_family: APACHE - size: 165419 - timestamp: 1750273167832 - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 md5: d8285bea2a350f63fab23bf460221f3f @@ -1793,23 +1099,6 @@ packages: license_family: BSD size: 7484186 timestamp: 1707225809722 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda - sha256: c8841d6d6f61fd70ca80682efbab6bdb8606dc77c68d8acabfbd7c222054f518 - md5: d83fc83d589e2625a3451c9a7e21047c - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libcxx >=16 - - liblapack >=3.9.0,<4.0a0 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - - python_abi 3.12.* *_cp312 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - size: 6073136 - timestamp: 1707226249608 - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.1-h7b32b05_0.conda sha256: 942347492164190559e995930adcdf84e2fea05307ec8012c02a505f5be87462 md5: c87df2ab1448ba69169652ab9547082d @@ -1821,16 +1110,6 @@ packages: license_family: Apache size: 3131002 timestamp: 1751390382076 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.1-h81ee809_0.conda - sha256: f94fde0f096fa79794c8aa0a2665630bbf9026cc6438e8253f6555fc7281e5a8 - md5: a8ac77e7c7e58d43fa34d60bd4361062 - depends: - - __osx >=11.0 - - ca-certificates - license: Apache-2.0 - license_family: Apache - size: 3071649 - timestamp: 1751390309393 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 md5: 58335b26c38bf4a20f399384c33cbcf9 @@ -1851,15 +1130,6 @@ packages: license_family: BSD size: 259377 timestamp: 1623788789327 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre-8.45-hbdafb3b_0.tar.bz2 - sha256: f2e0c4ae3306f94851eea2318c6d26d24f8e191e329ddd256a612cd1184c5737 - md5: 500758f2515ae07c640d255c11afc19f - depends: - - libcxx >=11.1.0 - license: BSD-3-Clause - license_family: BSD - size: 235554 - timestamp: 1623788902053 - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda sha256: 766dd986a7ed6197676c14699000bba2625fd26c8a890fcb7a810e5cf56155bc md5: 8292dea9e022d9610a11fce5e0896ed8 @@ -1871,17 +1141,6 @@ packages: license_family: BSD size: 950847 timestamp: 1708118050286 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.45-ha881caa_0.conda - sha256: e9ecb706b58b5a2047c077b3a1470e8554f3aad02e9c3c00cfa35d537420fea3 - md5: a52385b93558d8e6bbaeec5d61a21cd7 - depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - size: 837826 - timestamp: 1745955207242 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.1.1-pyh8b19718_0.conda sha256: ebfa591d39092b111b9ebb3210eb42251be6da89e26c823ee03e5e838655a43e md5: 32d0781ace05105cc99af55d36cbec7c @@ -1904,16 +1163,6 @@ packages: license_family: MIT size: 402222 timestamp: 1749552884791 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.2-h2f9eb0b_0.conda - sha256: 68d1eef12946d779ce4b4b9de88bc295d07adce5dd825a0baf0e1d7cf69bc5a6 - md5: 0587a57e200568a71982173c07684423 - depends: - - __osx >=11.0 - - libcxx >=18 - license: MIT - license_family: MIT - size: 214660 - timestamp: 1749553221709 - conda: https://conda.anaconda.org/conda-forge/linux-64/pkg-config-0.29.2-h4bc722e_1009.conda sha256: c9601efb1af5391317e04eca77c6fe4d716bf1ca1ad8da2a05d15cb7c28d7d4e md5: 1bee70681f504ea424fb07cdb090c001 @@ -1924,17 +1173,6 @@ packages: license_family: GPL size: 115175 timestamp: 1720805894943 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pkg-config-0.29.2-hde07d2e_1009.conda - sha256: d82f4655b2d67fe12eefe1a3eea4cd27d33fa41dbc5e9aeab5fd6d3d2c26f18a - md5: b4f41e19a8c20184eec3aaf0f0953293 - depends: - - __osx >=11.0 - - libglib >=2.80.3,<3.0a0 - - libiconv >=1.17,<2.0a0 - license: GPL-2.0-or-later - license_family: GPL - size: 49724 - timestamp: 1720806128118 - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda sha256: a8eb555eef5063bbb7ba06a379fa7ea714f57d9741fe0efdb9442dbbc2cccbcc md5: 7da7ccd349dbf6487a7778579d2bb971 @@ -2006,27 +1244,6 @@ packages: license: Python-2.0 size: 31991381 timestamp: 1713208036041 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.11-hc22306f_0_cpython.conda - sha256: cde8b944c2dc378a5afbc48028d0843583fd215493d5885a80f1b41de085552f - md5: 9207ebad7cfbe2a4af0702c92fd031c4 - depends: - - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.0,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 - - liblzma >=5.8.1,<6.0a0 - - libsqlite >=3.50.0,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.0,<4.0a0 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - constrains: - - python_abi 3.12.* *_cp312 - license: Python-2.0 - size: 13009234 - timestamp: 1749048134449 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-7_cp312.conda build_number: 7 sha256: a1bbced35e0df66cc713105344263570e835625c28d1bdee8f748f482b2d7793 @@ -2047,15 +1264,6 @@ packages: license_family: GPL size: 282480 timestamp: 1740379431762 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - sha256: 7db04684d3904f6151eff8673270922d31da1eea7fa73254d01c437f49702e34 - md5: 63ef3f6e6d6d5c589e64f11263dc5676 - depends: - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - size: 252359 - timestamp: 1740379663071 - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.3-hd590300_2.conda sha256: 475f68cac8981ff2b10c56e53c2f376fc3c805fbc7ec30d22f870cd88f1479ba md5: 4cabe3858a856bff08d9a0992e413084 @@ -2065,15 +1273,6 @@ packages: license_family: MIT size: 184509 timestamp: 1693427593121 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.5-h7ab814d_0.conda - sha256: e6a3e9dbfcb5ad5d69a20c8ac237d37a282a95983314a28912fc54208c5db391 - md5: 352b210f81798ae1e2f25a98ef4b3b54 - depends: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 177240 - timestamp: 1728886815751 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 md5: 4de79c071274a53dcaf2a8c749d1499e @@ -2104,17 +1303,6 @@ packages: license_family: APACHE size: 1527865 timestamp: 1681486787952 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.1.0-h9541205_0.conda - sha256: 3a7442e806f36b2b7efeaad88c330cdc5f24ceea8eb1ccdb7b428e4797d54733 - md5: fba14047c046475a82806c17885ba7fa - depends: - - __osx >=11.0 - - libcxx >=18 - - libhwloc >=2.11.2,<2.11.3.0a0 - license: Apache-2.0 - license_family: APACHE - size: 119289 - timestamp: 1743578923826 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e md5: d453b98d9c83e71da0741bb0ff4d76bc @@ -2125,16 +1313,6 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - sha256: cb86c522576fa95c6db4c878849af0bccfd3264daf0cc40dd18e7f4a7bfced0e - md5: 7362396c170252e7b7b0c8fb37fe9c78 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: TCL - license_family: BSD - size: 3125538 - timestamp: 1748388189063 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhd8ed1ab_1.conda sha256: 18636339a79656962723077df9a56c0ac7b8a864329eb8f847ee3d38495b863e md5: ac944244f1fed2eb49bae07193ae8215 @@ -2356,16 +1534,6 @@ packages: license_family: Other size: 92883 timestamp: 1716874088980 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.1-h8359307_2.conda - sha256: 58f8860756680a4831c1bf4f294e2354d187f2e999791d53b1941834c4b37430 - md5: e3170d898ca6cb48f1bb567afb92f775 - depends: - - __osx >=11.0 - - libzlib 1.3.1 h8359307_2 - license: Zlib - license_family: Other - size: 77606 - timestamp: 1727963209370 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda sha256: c558b9cc01d9c1444031bd1ce4b9cff86f9085765f17627a6cd85fc623c8a02b md5: 4d056880988120e29d75bfff282e0f45 @@ -2377,13 +1545,3 @@ packages: license_family: BSD size: 554846 timestamp: 1714722996770 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-h6491c7d_2.conda - sha256: 0d02046f57f7a1a3feae3e9d1aa2113788311f3cf37a3244c71e61a93177ba67 - md5: e6f69c7bcccdefa417f056fa593b40f0 - depends: - - __osx >=11.0 - - libzlib >=1.3.1,<2.0a0 - license: BSD-3-Clause - license_family: BSD - size: 399979 - timestamp: 1742433432699 diff --git a/pixi.toml b/pixi.toml index 3067927..e9bb343 100644 --- a/pixi.toml +++ b/pixi.toml @@ -36,7 +36,6 @@ libvorbis = ">=1.3.7,<2" numpy = "<2.0" pip = ">=25.1.1,<26" - [target.linux-64.dependencies] gcc = "*" gxx = "*" diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 05728c8..c85acd8 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -7,7 +7,15 @@ if [[ "$(uname)" == "Darwin" ]];then brew install --formula $cur/cmake.rb brew install opencv elif [[ "$(uname)" == "Linux" ]]; then - sudo apt update && sudo apt install -y libopencv-dev cmake + SUDO="sudo" + if [ $(id -u) -eq 0 ];then + SUDO="" + fi + APT="apt" + if hash yum 2>/dev/null;then + APT="yum" + fi + ${SUDO} ${APT} update && ${SUDO} ${APT} install -y libopencv-dev cmake elif [[ "$(uname)" == *"_NT"* ]]; then echo "Not supported windows now." fi From 7e2402a1a837841b7d0d272f034d2b5df81bcfe4 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 15:59:48 +0800 Subject: [PATCH 09/31] update --- .github/workflows/build_wheels.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 96bc9db..e65be1d 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -31,6 +31,7 @@ jobs: python -m pip install --upgrade pip pip install cmeel[build] pip install build + pip install cibuildwheel - name: Build wheels env: From dadba5d7811d5e036ce02577e63f4e8b26574c15 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 16:02:25 +0800 Subject: [PATCH 10/31] update --- .github/workflows/build_wheels.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index e4f50be..9e3677f 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -34,9 +34,11 @@ jobs: - name: Build wheels env: CIBW_BEFORE_BUILD: | - bash scripts/build_ffmpeg.sh bash scripts/install_deps.sh + bash scripts/build_ffmpeg.sh CIBW_BUILD: "cp3*-*" CIBW_SKIP: "pp* *-win32 *-win_amd64" run: | + bash scripts/install_deps.sh + bash scripts/build_ffmpeg.sh python -m cibuildwheel --output-dir wheelhouse \ No newline at end of file From 8805286b1366f98dc13ff2d10428395eb0e2c435 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 16:18:58 +0800 Subject: [PATCH 11/31] update github workflow --- .github/workflows/build_wheels.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 9e3677f..91050a8 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -31,6 +31,11 @@ jobs: python -m pip install --upgrade pip pip install cmeel[build] + - name: Install CMake + uses: ssrobins/install-cmake@v1 + with: + version: 3.26.4 + - name: Build wheels env: CIBW_BEFORE_BUILD: | From 1313e224ccb691480c90d2ddd1bae3ae687f801c Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 16:22:10 +0800 Subject: [PATCH 12/31] update github workflow --- .github/workflows/build_wheels.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 91050a8..4528a0d 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -21,6 +21,11 @@ jobs: with: submodules: true + - name: Install CMake + uses: actions/setup-cmake@v4 + with: + version: 3.26.4 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -31,11 +36,6 @@ jobs: python -m pip install --upgrade pip pip install cmeel[build] - - name: Install CMake - uses: ssrobins/install-cmake@v1 - with: - version: 3.26.4 - - name: Build wheels env: CIBW_BEFORE_BUILD: | From df8606feab76b93fedc61032239de85a83d2f666 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 16:38:42 +0800 Subject: [PATCH 13/31] update github workflow --- .github/workflows/build_wheels.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 4528a0d..8d31a70 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -1,5 +1,8 @@ name: Build Wheels +- name: actions-setup-cmake + uses: jwlawson/actions-setup-cmake@v2.0.2 + on: push: tags: @@ -21,10 +24,9 @@ jobs: with: submodules: true - - name: Install CMake - uses: actions/setup-cmake@v4 + - uses: prefix-dev/setup-pixi@v0.8.8 with: - version: 3.26.4 + pixi-version: v0.41.4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 @@ -44,6 +46,7 @@ jobs: CIBW_BUILD: "cp3*-*" CIBW_SKIP: "pp* *-win32 *-win_amd64" run: | + cmake --version bash scripts/install_deps.sh bash scripts/build_ffmpeg.sh python -m cibuildwheel --output-dir wheelhouse \ No newline at end of file From ac8e732f9803cb73cbf494668e8688429ea47dab Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 16:44:53 +0800 Subject: [PATCH 14/31] update github workflow --- .github/workflows/build_wheels.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 8d31a70..2eea2bb 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -1,8 +1,5 @@ name: Build Wheels -- name: actions-setup-cmake - uses: jwlawson/actions-setup-cmake@v2.0.2 - on: push: tags: From b7b3bbfe8f6699f44601281112806b859205f345 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 17:17:54 +0800 Subject: [PATCH 15/31] update github workflow --- .github/workflows/build_wheels.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 2eea2bb..a86abb2 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -21,10 +21,6 @@ jobs: with: submodules: true - - uses: prefix-dev/setup-pixi@v0.8.8 - with: - pixi-version: v0.41.4 - - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: From 769a2500e4cb89b6b891a27a041c336587f4e1b7 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 17:30:48 +0800 Subject: [PATCH 16/31] update github workflow --- scripts/build_ffmpeg.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh index 97f7c38..da89f8d 100755 --- a/scripts/build_ffmpeg.sh +++ b/scripts/build_ffmpeg.sh @@ -166,6 +166,7 @@ build_install_opencv() { -D PYTHON_EXECUTABLE=$(which python3) -D BUILD_SHARED_LIBS=OFF -D OPENCV_GENERATE_PKGCONFIG=ON + -D CMAKE_POLICY_VERSION_MINIMUM=3.5 ${CMAKE_EXTRA_CONFIG} " From 9bc3817c961a8f7a64c70bce4a9e1dde56871154 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 18:00:54 +0800 Subject: [PATCH 17/31] update github workflow --- .github/workflows/build_wheels.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index a86abb2..8c51227 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -30,6 +30,7 @@ jobs: run: | python -m pip install --upgrade pip pip install cmeel[build] + pip install build - name: Build wheels env: @@ -42,4 +43,4 @@ jobs: cmake --version bash scripts/install_deps.sh bash scripts/build_ffmpeg.sh - python -m cibuildwheel --output-dir wheelhouse \ No newline at end of file + python -m build --wheel \ No newline at end of file From 42e8d51f3684ff195ac2814fc44b2d2a3175336d Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 18:14:56 +0800 Subject: [PATCH 18/31] update github workflow --- scripts/build_ffmpeg.sh | 3 ++- scripts/opencv_for_new_cmake.patch | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 scripts/opencv_for_new_cmake.patch diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh index da89f8d..b7ca258 100755 --- a/scripts/build_ffmpeg.sh +++ b/scripts/build_ffmpeg.sh @@ -173,6 +173,7 @@ build_install_opencv() { cd $opt/opencv git reset --hard $opencv_version git apply $cur/opencv_460_on_macos.patch + git apply $cur/opencv_for_new_cmake.patch if [ -d release ];then rm -rf release @@ -190,4 +191,4 @@ if [ -z "$CONDA_PREFIX" ];then install_deps fi build_install_ffmpeg -build_install_opencv \ No newline at end of file +build_install_opencv diff --git a/scripts/opencv_for_new_cmake.patch b/scripts/opencv_for_new_cmake.patch new file mode 100644 index 0000000..f749a21 --- /dev/null +++ b/scripts/opencv_for_new_cmake.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/OpenCVGenPkgconfig.cmake b/cmake/OpenCVGenPkgconfig.cmake +index 43d6a87e74..6da10dce55 100644 +--- a/cmake/OpenCVGenPkgconfig.cmake ++++ b/cmake/OpenCVGenPkgconfig.cmake +@@ -110,7 +110,7 @@ endif() + # ============================================================================= + else() # DEFINED CMAKE_HELPER_SCRIPT + +-cmake_minimum_required(VERSION 2.8.12.2) ++cmake_minimum_required(VERSION 3.5) + cmake_policy(SET CMP0012 NEW) + include("${CMAKE_HELPER_SCRIPT}") + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake") From 44be82108ec642c20acc6599b15a45b076171cb6 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 20:30:50 +0800 Subject: [PATCH 19/31] update github workflow --- .github/workflows/build_wheels.yml | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 8c51227..2f14e54 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -43,4 +43,45 @@ jobs: cmake --version bash scripts/install_deps.sh bash scripts/build_ffmpeg.sh - python -m build --wheel \ No newline at end of file + python -m build --wheel + + release: + needs: build_wheels + runs-on: ubuntu-latest + steps: + + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + body: | + Changes in this Release + - First release + draft: true + prerelease: false + + - name: Upload release asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./dist/spatialmp4-*.whl + asset_name: spatialmp4-*.whl + asset_content_type: application/zip + + - name: Publish release + uses: StuYarrow/publish-release@v1.1.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + id: ${{ steps.create_release.outputs.id }} + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 9dd1cd6a23c202a92d6555d39f3fe095372a99e6 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 20:37:26 +0800 Subject: [PATCH 20/31] update github workflow --- .github/workflows/build_wheels.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 2f14e54..202f02c 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -63,7 +63,6 @@ jobs: - First release draft: true prerelease: false - - name: Upload release asset uses: actions/upload-release-asset@v1 env: @@ -73,15 +72,9 @@ jobs: asset_path: ./dist/spatialmp4-*.whl asset_name: spatialmp4-*.whl asset_content_type: application/zip - - name: Publish release uses: StuYarrow/publish-release@v1.1.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - id: ${{ steps.create_release.outputs.id }} - - name: Create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + id: ${{ steps.create_release.outputs.id }} \ No newline at end of file From 276a678f2a366e01ecccfb2744f31c4b18950a20 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Thu, 3 Jul 2025 20:44:23 +0800 Subject: [PATCH 21/31] update github workflow --- .github/workflows/build_wheels.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 202f02c..b4bbd32 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -49,7 +49,6 @@ jobs: needs: build_wheels runs-on: ubuntu-latest steps: - - name: Create release id: create_release uses: actions/create-release@v1 @@ -71,10 +70,4 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./dist/spatialmp4-*.whl asset_name: spatialmp4-*.whl - asset_content_type: application/zip - - name: Publish release - uses: StuYarrow/publish-release@v1.1.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - id: ${{ steps.create_release.outputs.id }} \ No newline at end of file + asset_content_type: application/zip \ No newline at end of file From cec2261f141de4743360f158d9810dc27f9393de Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Fri, 4 Jul 2025 08:55:12 +0800 Subject: [PATCH 22/31] update workflows --- .github/workflows/build_wheels.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index b4bbd32..3bb4778 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -1,5 +1,9 @@ name: Build Wheels +permissions: + contents: "read" + id-token: "write" + on: push: tags: @@ -70,4 +74,4 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./dist/spatialmp4-*.whl asset_name: spatialmp4-*.whl - asset_content_type: application/zip \ No newline at end of file + asset_content_type: application/zip From c6168198ada027bd56fc2a55071a289f656eb67d Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Fri, 4 Jul 2025 11:02:54 +0800 Subject: [PATCH 23/31] update github workflow --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 3bb4778..15838da 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -1,7 +1,7 @@ name: Build Wheels permissions: - contents: "read" + contents: "write" id-token: "write" on: From 055676899c363e891e0c1e02d9c2c1f3f9018b59 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Fri, 4 Jul 2025 20:55:18 +0800 Subject: [PATCH 24/31] add 01_generate_pcd.py --- .gitignore | 6 + CMakeLists.txt | 75 +++--- bindings/spatialmp4.cpp | 37 ++- examples/python/01_generate_pcd.py | 248 ++++++++++++++++++ ...colmap.py => 02_generate_colmap_format.py} | 0 src/spatialmp4/reader.cc | 75 +++++- src/spatialmp4/reader.h | 3 + src/spatialmp4/reader_test.cc | 41 +++ src/spatialmp4/utilities/RgbdUtils.h | 15 ++ 9 files changed, 459 insertions(+), 41 deletions(-) create mode 100644 examples/python/01_generate_pcd.py rename examples/python/{spatialmp4_to_colmap.py => 02_generate_colmap_format.py} (100%) diff --git a/.gitignore b/.gitignore index 2615167..93472ad 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,9 @@ wheelhouse # python build dist/* + +# cache files +*.png +*.pkl +*.ply +*.json diff --git a/CMakeLists.txt b/CMakeLists.txt index f0ee433..1bcf9fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ if(BUILD_PYTHON) endif() set(SRC + ./src/spatialmp4/utilities/RgbdUtils.cc ./src/spatialmp4/utilities/OpencvUtils.cc ./src/spatialmp4/utils.cc ./src/spatialmp4/reader.cc @@ -79,44 +80,44 @@ if(APPLE) LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python ) - # # Find macOS frameworks - # find_library(FOUNDATION_FRAMEWORK Foundation) - # find_library(AUDIOTOOLBOX_FRAMEWORK AudioToolbox) - # find_library(COREAUDIO_FRAMEWORK CoreAudio) - # find_library(AVFOUNDATION_FRAMEWORK AVFoundation) - # find_library(COREVIDEO_FRAMEWORK CoreVideo) - # find_library(COREMEDIA_FRAMEWORK CoreMedia) - # find_library(COREGRAPHICS_FRAMEWORK CoreGraphics) - # find_library(OPENGL_FRAMEWORK OpenGL) - # find_library(APPLICATIONSERVICES_FRAMEWORK ApplicationServices) - # find_library(COREFOUNDATION_FRAMEWORK CoreFoundation) - # find_library(APPKIT_FRAMEWORK AppKit) - # find_library(CARBON_FRAMEWORK Carbon) - # find_library(METAL_FRAMEWORK Metal) - # find_library(VIDEOTOOLBOX_FRAMEWORK VideoToolbox) - # find_library(COREIMAGE_FRAMEWORK CoreImage) - # find_library(CORESERVICES_FRAMEWORK CoreServices) - # find_library(SECURITY_FRAMEWORK Security) + # Find macOS frameworks + find_library(FOUNDATION_FRAMEWORK Foundation) + find_library(AUDIOTOOLBOX_FRAMEWORK AudioToolbox) + find_library(COREAUDIO_FRAMEWORK CoreAudio) + find_library(AVFOUNDATION_FRAMEWORK AVFoundation) + find_library(COREVIDEO_FRAMEWORK CoreVideo) + find_library(COREMEDIA_FRAMEWORK CoreMedia) + find_library(COREGRAPHICS_FRAMEWORK CoreGraphics) + find_library(OPENGL_FRAMEWORK OpenGL) + find_library(APPLICATIONSERVICES_FRAMEWORK ApplicationServices) + find_library(COREFOUNDATION_FRAMEWORK CoreFoundation) + find_library(APPKIT_FRAMEWORK AppKit) + find_library(CARBON_FRAMEWORK Carbon) + find_library(METAL_FRAMEWORK Metal) + find_library(VIDEOTOOLBOX_FRAMEWORK VideoToolbox) + find_library(COREIMAGE_FRAMEWORK CoreImage) + find_library(CORESERVICES_FRAMEWORK CoreServices) + find_library(SECURITY_FRAMEWORK Security) - # target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC - # ${FOUNDATION_FRAMEWORK} - # ${AUDIOTOOLBOX_FRAMEWORK} - # ${COREAUDIO_FRAMEWORK} - # ${AVFOUNDATION_FRAMEWORK} - # ${COREVIDEO_FRAMEWORK} - # ${COREMEDIA_FRAMEWORK} - # ${COREGRAPHICS_FRAMEWORK} - # ${OPENGL_FRAMEWORK} - # ${APPLICATIONSERVICES_FRAMEWORK} - # ${COREFOUNDATION_FRAMEWORK} - # ${APPKIT_FRAMEWORK} - # ${CARBON_FRAMEWORK} - # ${METAL_FRAMEWORK} - # ${VIDEOTOOLBOX_FRAMEWORK} - # ${COREIMAGE_FRAMEWORK} - # ${CORESERVICES_FRAMEWORK} - # ${SECURITY_FRAMEWORK} - # ) + target_link_libraries(${CMAKE_PROJECT_NAME}_lib PUBLIC + ${FOUNDATION_FRAMEWORK} + ${AUDIOTOOLBOX_FRAMEWORK} + ${COREAUDIO_FRAMEWORK} + ${AVFOUNDATION_FRAMEWORK} + ${COREVIDEO_FRAMEWORK} + ${COREMEDIA_FRAMEWORK} + ${COREGRAPHICS_FRAMEWORK} + ${OPENGL_FRAMEWORK} + ${APPLICATIONSERVICES_FRAMEWORK} + ${COREFOUNDATION_FRAMEWORK} + ${APPKIT_FRAMEWORK} + ${CARBON_FRAMEWORK} + ${METAL_FRAMEWORK} + ${VIDEOTOOLBOX_FRAMEWORK} + ${COREIMAGE_FRAMEWORK} + ${CORESERVICES_FRAMEWORK} + ${SECURITY_FRAMEWORK} + ) endif() if(BUILD_TESTING) diff --git a/bindings/spatialmp4.cpp b/bindings/spatialmp4.cpp index 260aaee..9857290 100644 --- a/bindings/spatialmp4.cpp +++ b/bindings/spatialmp4.cpp @@ -7,6 +7,7 @@ #include "spatialmp4/data_types.h" #include "spatialmp4/utils.h" #include "spatialmp4/version.h" +#include "spatialmp4/utilities/RgbdUtils.h" namespace py = pybind11; @@ -185,8 +186,14 @@ PYBIND11_MODULE(spatialmp4, m) { self.Load(rgb_frame, depth_frame); return py::make_tuple(rgb_frame, depth_frame); }) + .def("load_rgbd", [](SpatialML::Reader& self, bool densify = false) { + Utilities::Rgbd rgbd; + self.Load(rgbd, densify); + return rgbd; + }) .def("reset", &SpatialML::Reader::Reset) - .def("get_index", &SpatialML::Reader::GetIndex); + .def("get_index", &SpatialML::Reader::GetIndex) + .def("get_frame_count", &SpatialML::Reader::GetFrameCount); // Bind ReadMode enum py::enum_(m, "ReadMode") @@ -210,4 +217,32 @@ PYBIND11_MODULE(spatialmp4, m) { }) .def("get_frame_count", &SpatialML::RandomAccessVideoReader::GetFrameCount) .def("debug", &SpatialML::RandomAccessVideoReader::Debug); + + // Bind Utilities::Rgbd struct + py::class_(m, "Rgbd") + .def(py::init<>()) + .def_readwrite("timestamp", &Utilities::Rgbd::timestamp) + .def_property("rgb", + [](const Utilities::Rgbd &f) { return mat_to_numpy(f.rgb); }, + [](Utilities::Rgbd &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property("depth", + [](const Utilities::Rgbd &f) { return depth_mat_to_numpy(f.depth); }, + [](Utilities::Rgbd &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property_readonly("T_W_S", + [](const Utilities::Rgbd &f) { + // Expose as Eigen::Matrix4d for now + Eigen::Matrix4d T = f.T_W_S.matrix(); + return T; + }) + .def("__repr__", [](const Utilities::Rgbd &f) { + std::ostringstream ss; + ss << "Rgbd(timestamp=" << f.timestamp << ", rgb shape=[" << f.rgb.rows << "," << f.rgb.cols << "," << f.rgb.channels() << "]"; + ss << ", depth shape=[" << f.depth.rows << "," << f.depth.cols << "]"; + ss << ")"; + return ss.str(); + }); } \ No newline at end of file diff --git a/examples/python/01_generate_pcd.py b/examples/python/01_generate_pcd.py new file mode 100644 index 0000000..eb414bf --- /dev/null +++ b/examples/python/01_generate_pcd.py @@ -0,0 +1,248 @@ +from ast import dump +from re import I +from socket import IP_DEFAULT_MULTICAST_LOOP, IP_DROP_MEMBERSHIP +from typing import Optional +import typer +import spatialmp4 as sm +import open3d as o3d +import numpy as np +import cv2 +import rerun as rr +import rerun.blueprint as rrb +from scipy.spatial.transform import Rotation +import os +import pickle + +''' +Rerun for different data source: + + colmap: + rr.ViewCoordinates.RIGHT_HAND_Y_DOWN + rr.log("camera", rr.ViewCoordinates.RDF, static=True) + +''' + +def pico_pose_to_open3d(extrinsic): + convert = np.eye(4) + return convert @ extrinsic + +def generate_pcd( + video_file: str, + skip_last_frame: bool = typer.Option(True, help="skip last frame"), + output: Optional[str] = typer.Option(None, help="output name"), +): + """Generate pcd file from spatialmp4, using TSDF in open3d. + """ + if not output: + output = video_file.replace(".mp4", "_pcd.ply") + + reader = sm.Reader(video_file) + reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) + + if not reader.has_depth(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + if not reader.has_pose(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + + voxel_length = 0.01 + sdf_trunc = 0.04 + down_voxel_size = 0.02 + volume = o3d.pipelines.integration.ScalableTSDFVolume( + voxel_length=voxel_length, + sdf_trunc=sdf_trunc, + color_type=o3d.pipelines.integration.TSDFVolumeColorType.NoColor + ) + + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.TextDocumentView(name="Description", origin="/description"), + row_shares=[7, 3], + ), + rrb.Vertical( + rrb.Spatial2DView( + name="RGB & Depth", + origin="world/camera/image", + overrides={"world/camera/image/rgb": rr.Image.from_fields(opacity=0.5)}, + ), + rrb.Tabs( + rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + rrb.Spatial2DView(name="Depth", origin="world/camera/image", contents="world/camera/image/depth"), + ), + name="2D", + row_shares=[3, 3, 2], + ), + column_shares=[2, 1], + ) + rr.init(f"spatialmp4_{os.path.basename(video_file)}", spawn=True) + rr.send_blueprint(blueprint) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_X_UP, static=True) # same as open3d + + positions = [] + frames = [] + + intrinsic = o3d.camera.PinholeCameraIntrinsic() + width = reader.get_rgb_width() + height = reader.get_rgb_height() + intrinsic.set_intrinsics( + width=width, + height=height, + fx=float(reader.get_rgb_intrinsics_left().fx), + fy=float(reader.get_rgb_intrinsics_left().fy), + cx=float(reader.get_rgb_intrinsics_left().cx), + cy=float(reader.get_rgb_intrinsics_left().cy) + ) + intrinsic_o3d = o3d.camera.PinholeCameraIntrinsic( + width=height, + height=width, + fx=float(reader.get_rgb_intrinsics_left().fy), + fy=float(reader.get_rgb_intrinsics_left().fx), + cx=float(reader.get_rgb_intrinsics_left().cy), + cy=width - 1 - float(reader.get_rgb_intrinsics_left().cx) + ) + + while reader.has_next(): + rgbd = reader.load_rgbd(True) + if skip_last_frame and reader.get_index() == reader.get_frame_count() - 1: + continue + print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") + + if reader.get_index() > 20: + break + + # preprocess on depthmap + depth_np = rgbd.depth + depth_uint16 = (depth_np * 1000).astype(np.uint16) + sobelx = cv2.Sobel(depth_uint16, cv2.CV_32F, 1, 0, ksize=3) + sobely = cv2.Sobel(depth_uint16, cv2.CV_32F, 0, 1, ksize=3) + grad_mag = np.sqrt(sobelx**2 + sobely**2) + depth_np[grad_mag > 500] = 0 + depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 + + extrinsic = rgbd.T_W_S + extrinsic_o3d = pico_pose_to_open3d(extrinsic) + + # rorate + rgb_rotated = cv2.rotate(rgbd.rgb, cv2.ROTATE_90_CLOCKWISE) + depth_rotated = cv2.rotate(depth_np, cv2.ROTATE_90_CLOCKWISE) + rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( + o3d.geometry.Image(rgb_rotated), + o3d.geometry.Image(depth_rotated), + depth_scale=1.0, + depth_trunc=5.0, + convert_rgb_to_intensity=True + ) + volume.integrate(rgbd_image, intrinsic_o3d, extrinsic_o3d) + + pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic_o3d) + pcd_i.transform(extrinsic_o3d) + pcd_i.paint_uniform_color([0, 0, 1]) + frames.append(pcd_i) + + rr.set_time_seconds("time", rgbd.timestamp) + rr.log("world/xyz", rr.Arrows3D(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]])) + rr.log("world/camera/image", rr.Pinhole( + resolution=[width, height], + focal_length=[intrinsic.intrinsic_matrix[0, 0], intrinsic.intrinsic_matrix[1, 1]], + principal_point=[intrinsic.intrinsic_matrix[0, 2], intrinsic.intrinsic_matrix[1, 2]], + camera_xyz=rr.ViewCoordinates.URF, + )) + position = extrinsic[:3, 3] + rotation = Rotation.from_matrix(extrinsic[:3, :3]).as_quat() + rr.log("world/camera", rr.Transform3D(translation=position, rotation=rr.Quaternion(xyzw=rotation))) + rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) + rr.log("world/camera/image/depth", rr.DepthImage(depth_np, meter=1.0)) + + pcd = volume.extract_point_cloud() + pcd.paint_uniform_color([1, 1, 0]) + + origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1.0, origin=[0, 0, 0]) + + vis=o3d.visualization.VisualizerWithKeyCallback() + vis.create_window() + idx=0 + vis.add_geometry(origin) + vis.add_geometry(frames[idx]) + #vis.update_renderer() + + def save_view_control(vis): + vc = vis.get_view_control() + params = vc.convert_to_pinhole_camera_parameters() + data = { + "extrinsic": params.extrinsic, + "intrinsic_matrix": params.intrinsic.intrinsic_matrix, + "width": params.intrinsic.width, + "height": params.intrinsic.height, + } + with open("view_control.pkl", "wb") as f: + pickle.dump(data, f) + print("Saved view control") + + def click_next(vis): + nonlocal idx + print('a_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(pcd) + vis.add_geometry(frames[idx]) + idx = (idx+1) % len(frames) + + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + + def click_prev(vis): + nonlocal idx + print('b_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(pcd) + vis.add_geometry(frames[idx]) + idx = (idx-1) % len(frames) + idx = max(idx, 0) + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + def exit_key(vis): + vis.destroy_window() + import glfw + vis.register_key_callback(glfw.KEY_A,click_next) + vis.register_key_callback(glfw.KEY_B,click_prev) + vis.register_key_callback(glfw.KEY_S,save_view_control) + vis.register_key_callback(glfw.KEY_ESCAPE,exit_key) + vis.poll_events() + vis.run() + #vis.destroy_window() + + + # print("[Info] Removing non-finite points...") + # pcd = pcd.remove_non_finite_points() + # print("[Info] Downsampling point cloud using voxel grid...") + # pcd = pcd.voxel_down_sample(voxel_size=args.down_voxel_size) + # print("[Info] Removing statistical outliers...") + # _, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2) + # print(f"[Info] Valid points: {len(ind)} / {len(pcd.points)} ({len(ind) / len(pcd.points) * 100:.2f} %)") + # pcd = pcd.select_by_index(ind) + + o3d.io.write_point_cloud(output, pcd) + print(f"[Info] Saved {len(pcd.points)} total points to {output}") + + +if __name__ == "__main__":# + typer.run(generate_pcd) \ No newline at end of file diff --git a/examples/python/spatialmp4_to_colmap.py b/examples/python/02_generate_colmap_format.py similarity index 100% rename from examples/python/spatialmp4_to_colmap.py rename to examples/python/02_generate_colmap_format.py diff --git a/src/spatialmp4/reader.cc b/src/spatialmp4/reader.cc index c43ef1d..85a84fa 100644 --- a/src/spatialmp4/reader.cc +++ b/src/spatialmp4/reader.cc @@ -310,7 +310,7 @@ Reader::Reader(const std::string& filename) if (has_rgb_) { rgb_fps_ = pFormatCtx_->streams[rgb_frame_id_]->r_frame_rate.num / pFormatCtx_->streams[rgb_frame_id_]->r_frame_rate.den; - rgb_width_ = pFormatCtx_->streams[rgb_frame_id_]->codecpar->width; + rgb_width_ = pFormatCtx_->streams[rgb_frame_id_]->codecpar->width / 2; // side-by-side stereo rgb_height_ = pFormatCtx_->streams[rgb_frame_id_]->codecpar->height; AVDictionaryEntry* tag = NULL; @@ -332,13 +332,15 @@ Reader::Reader(const std::string& filename) rgb_extrinsics_left_.extrinsics = cv::Matx44d(extrinsics_data[0], extrinsics_data[1], extrinsics_data[2], extrinsics_data[3], extrinsics_data[4], extrinsics_data[5], extrinsics_data[6], extrinsics_data[7], - extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], 0, 0, 0, 1); + extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], + 0, 0, 0, 1); } else if (std::string(tag->key).find("ecam_1") != std::string::npos) { std::vector extrinsics_data = SpatialML::String2DoubleVector(tag->value); rgb_extrinsics_right_.extrinsics = cv::Matx44d(extrinsics_data[0], extrinsics_data[1], extrinsics_data[2], extrinsics_data[3], extrinsics_data[4], extrinsics_data[5], extrinsics_data[6], extrinsics_data[7], - extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], 0, 0, 0, 1); + extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], + 0, 0, 0, 1); } else if (std::string(tag->key).find("distortion_model") != std::string::npos) { is_rgb_distorted_ = true; rgb_distortion_model_ = tag->value; @@ -499,6 +501,18 @@ int Reader::GetIndex() const { } } +int Reader::GetFrameCount() const { + switch (read_mode_) { + case ReadMode::DEPTH_FIRST: + case ReadMode::DEPTH_ONLY: + return keyframes_depth.size(); + case ReadMode::RGB_ONLY: + return allframes_rgb.size(); + default: + return -1; + } +} + void Reader::Load(rgb_frame& frame_rgb, depth_frame& frame_depth) { if (pFormatCtx_ == NULL) { std::cerr << "pFormatCtx_ is NULL" << std::endl; @@ -631,6 +645,61 @@ void Reader::Load(depth_frame& frame_depth) { } } +void Reader::Load(Utilities::Rgbd& rgbd, bool densify) { + if (read_mode_ != ReadMode::DEPTH_FIRST) { + std::cerr << "Read mode should be DEPTH_FIRST, but got " << ReadMode2String(read_mode_) << std::endl; + return; + } + if (!has_depth_ || !has_rgb_) { + std::cerr << "depth frame or rgb frame is not found" << std::endl; + return; + } + + rgb_frame frame_rgb; + depth_frame frame_depth; + Load(frame_rgb, frame_depth); + + // project depth to rgb + cv::Mat projected_depth; + auto T_I_Srgb = GetRgbExtrinsicsLeft().as_se3(); + auto T_I_Stof = GetDepthExtrinsics().as_se3(); + + // Read head_model_offset from /system/etc/pvr/config/config_head.txt#line_1 + auto head_model_offset = Eigen::Vector3d(-0.05057, -0.01874, 0.04309); + + // Note: + // W: World + // H: Head + // S: Sensor, rgb sensor or depth sensor + // I: IMU + auto T_W_Hrgb = frame_rgb.pose.as_se3(); + auto T_W_Htof = frame_depth.pose.as_se3(); + Sophus::SE3d T_W_Irgb, T_W_Itof; + Utilities::HeadToImu(T_W_Hrgb, head_model_offset, T_W_Irgb); + Utilities::HeadToImu(T_W_Htof, head_model_offset, T_W_Itof); + auto T_W_Srgb = T_W_Irgb * T_I_Srgb; + auto T_W_Stof = T_W_Itof * T_I_Stof; + auto T_Srgb_Stof = T_W_Srgb.inverse() * T_W_Stof; + + cv::Matx33d K_tof = GetDepthIntrinsics().as_cvmat(); + if (densify) { + // densify depth by nearest neighbor interpolation + float scale = frame_rgb.left_rgb.cols / frame_depth.depth.cols; + cv::resize(frame_depth.depth, frame_depth.depth, + cv::Size(frame_rgb.left_rgb.cols, frame_rgb.left_rgb.rows), cv::INTER_NEAREST); + K_tof = GetDepthIntrinsics().as_cvmat(); + K_tof(0, 0) *= scale; + K_tof(1, 1) *= scale; + K_tof(0, 2) *= scale; + K_tof(1, 2) *= scale; + } + + Utilities::ProjectDepthToRgb(frame_depth.depth, frame_rgb.left_rgb, GetRgbIntrinsicsLeft().as_cvmat(), + K_tof, T_Srgb_Stof, projected_depth, true); + + rgbd = Utilities::Rgbd(frame_rgb.left_rgb, projected_depth, frame_depth.timestamp, T_W_Stof); +} + void Reader::LoadAllPoseData(int frame_id) { const AVStream* pose_stream = pFormatCtx_->streams[frame_id]; AVPacket pkt; diff --git a/src/spatialmp4/reader.h b/src/spatialmp4/reader.h index 0b48f22..304f2f4 100644 --- a/src/spatialmp4/reader.h +++ b/src/spatialmp4/reader.h @@ -29,6 +29,7 @@ #include #include #include "utilities/SyncPose.hpp" +#include "utilities/RgbdUtils.h" #include "spatialmp4/data_types.h" extern "C" { @@ -141,8 +142,10 @@ class SPATIALMP4_EXPORT Reader { void Load(rgb_frame& rgb_frame); void Load(depth_frame& depth_frame); void Load(rgb_frame& rgb_frame, depth_frame& depth_frame); + void Load(Utilities::Rgbd& rgbd, bool densify = false); void Reset(); int GetIndex() const; + int GetFrameCount() const; protected: void LoadAllPoseData(int frame_id); diff --git a/src/spatialmp4/reader_test.cc b/src/spatialmp4/reader_test.cc index 10d8f70..3ea03aa 100644 --- a/src/spatialmp4/reader_test.cc +++ b/src/spatialmp4/reader_test.cc @@ -29,6 +29,7 @@ const std::string kTestFile = "video/test.mp4"; const std::string kVisRgbDir = "./tmp_vis_rgb"; const std::string kVisRgbDir2 = "./tmp_vis_rgb_random"; const std::string kVisDepthDir = "./tmp_vis_depth"; +const std::string kVisRgbdDir = "./tmp_vis_rgbd"; std::string GetVideoPath() { const char* env = std::getenv("VIDEO"); @@ -198,6 +199,8 @@ TEST(SpatialMP4Test, DepthFirst_ReaderTest) { } } + + TEST(SpatialMP4Test, HeadModel_ReaderTest) { // test data auto head_model_offset = Eigen::Vector3d(-0.05057, -0.01874, 0.04309); @@ -283,3 +286,41 @@ TEST(SpatialMP4Test, RandomAccess_ReaderTest) { } } } + +TEST(SpatialMP4Test, DepthFirst_ReaderTest_Rgbd) { + // spdlog::set_level(spdlog::level::debug); // debug mode + + if (fs::exists(kVisRgbdDir)) { + fs::remove_all(kVisRgbdDir); + } + fs::create_directory(kVisRgbdDir); + + SpatialML::Reader reader(GetVideoPath()); + reader.SetReadMode(SpatialML::Reader::ReadMode::DEPTH_FIRST); + reader.Reset(); + while (reader.HasNext()) { + Utilities::Rgbd rgbd; + reader.Load(rgbd); + + std::cout << "rgbd frame: \t" << rgbd.timestamp << std::endl; + std::stringstream ss; + ss << std::setw(4) << std::setfill('0') << reader.GetIndex(); + + cv::Mat vis_projected_depth; + Utilities::VisualizeMat(rgbd.depth, vis_projected_depth, "projected_depth", &rgbd.rgb, 0, 5, true); + + std::string filename = kVisRgbdDir + "/depth_" + ss.str() + ".png"; + cv::putText(vis_projected_depth, "depth_" + std::to_string(rgbd.timestamp), cv::Point(100, 150), + cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2); + cv::imwrite(filename, vis_projected_depth); + + // projection depth to pointcloud + Utilities::Pointcloud pcd; + Utilities::RgbdToPointcloud(rgbd.rgb, rgbd.depth, reader.GetRgbIntrinsicsLeft().as_cvmat(), pcd, 10); + std::string pcd_filename = kVisRgbdDir + "/pcd_" + ss.str() + ".obj"; + Utilities::SavePointcloudToFile(pcd_filename, pcd); + + EXPECT_TRUE(rgbd.depth.data != nullptr); + EXPECT_TRUE(rgbd.rgb.data != nullptr); + } +} \ No newline at end of file diff --git a/src/spatialmp4/utilities/RgbdUtils.h b/src/spatialmp4/utilities/RgbdUtils.h index 9aa3942..6513e2f 100644 --- a/src/spatialmp4/utilities/RgbdUtils.h +++ b/src/spatialmp4/utilities/RgbdUtils.h @@ -33,4 +33,19 @@ void ImuToHead(const Sophus::SE3d& in, const Eigen::Vector3d& head_model_offset, void HeadToImu(const Sophus::SE3d& in, const Eigen::Vector3d& head_model_offset, Sophus::SE3d& out); +struct Rgbd { + Rgbd(const cv::Mat& rgb, const cv::Mat& depth, double timestamp, const Sophus::SE3d& T_W_S) + : rgb(rgb), depth(depth), timestamp(timestamp), T_W_S(T_W_S) {} + Rgbd() = default; + Rgbd(const Rgbd& other) = default; + Rgbd& operator=(const Rgbd& other) = default; + Rgbd(Rgbd&& other) = default; + Rgbd& operator=(Rgbd&& other) = default; + + cv::Mat rgb; + cv::Mat depth; + double timestamp; + Sophus::SE3d T_W_S; +}; + } // namespace Utilities \ No newline at end of file From 1e4d3080aed48e6c47964790b266a1eafc227b0e Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Fri, 4 Jul 2025 20:56:39 +0800 Subject: [PATCH 25/31] TODO: visualize by rerun and open3d --- examples/python/visualize_open3d.py | 0 examples/python/visualize_rerun.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/python/visualize_open3d.py create mode 100644 examples/python/visualize_rerun.py diff --git a/examples/python/visualize_open3d.py b/examples/python/visualize_open3d.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/python/visualize_rerun.py b/examples/python/visualize_rerun.py new file mode 100644 index 0000000..e69de29 From fab72d9a5cee3274252a8f8568b783d2543b7806 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Mon, 7 Jul 2025 19:55:07 +0800 Subject: [PATCH 26/31] add open3d and rerun visualize script --- .gitignore | 3 + examples/python/01_generate_pcd.py | 301 +++++++++++++------------- examples/python/visualize_open3d.py | 169 +++++++++++++++ examples/python/visualize_rerun.py | 100 +++++++++ src/spatialmp4/reader.cc | 28 ++- src/spatialmp4/utilities/SyncPose.hpp | 20 +- 6 files changed, 453 insertions(+), 168 deletions(-) diff --git a/.gitignore b/.gitignore index 93472ad..acb8253 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ dist/* *.pkl *.ply *.json + +# examples +examples/python/view_control.pkl diff --git a/examples/python/01_generate_pcd.py b/examples/python/01_generate_pcd.py index eb414bf..eed7ebf 100644 --- a/examples/python/01_generate_pcd.py +++ b/examples/python/01_generate_pcd.py @@ -1,38 +1,35 @@ -from ast import dump -from re import I -from socket import IP_DEFAULT_MULTICAST_LOOP, IP_DROP_MEMBERSHIP from typing import Optional import typer -import spatialmp4 as sm -import open3d as o3d -import numpy as np -import cv2 -import rerun as rr -import rerun.blueprint as rrb -from scipy.spatial.transform import Rotation import os import pickle +import cv2 +import numpy as np +import open3d as o3d +import spatialmp4 as sm -''' -Rerun for different data source: - - colmap: - rr.ViewCoordinates.RIGHT_HAND_Y_DOWN - rr.log("camera", rr.ViewCoordinates.RDF, static=True) +from scipy.spatial.transform import Rotation -''' def pico_pose_to_open3d(extrinsic): - convert = np.eye(4) - return convert @ extrinsic + convert = np.array([ + [0, 0, 1, 0], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) + output = convert @ extrinsic + return output + def generate_pcd( video_file: str, - skip_last_frame: bool = typer.Option(True, help="skip last frame"), + topk: Optional[int] = typer.Option(None, help="topk frames"), + skip_last_frame: Optional[bool] = typer.Option(True, help="skip last frame"), output: Optional[str] = typer.Option(None, help="output name"), + vis_rerun: Optional[bool] = typer.Option(False, help="visualize using rerun"), + vis_open3d: Optional[bool] = typer.Option(False, help="visualize using open3d"), ): - """Generate pcd file from spatialmp4, using TSDF in open3d. - """ + """Generate pcd file from spatialmp4, using TSDF in open3d.""" if not output: output = video_file.replace(".mp4", "_pcd.ply") @@ -52,31 +49,35 @@ def generate_pcd( sdf_trunc=sdf_trunc, color_type=o3d.pipelines.integration.TSDFVolumeColorType.NoColor ) - - blueprint=rrb.Horizontal( - rrb.Vertical( - rrb.Spatial3DView(name="3D", origin="world"), - rrb.TextDocumentView(name="Description", origin="/description"), - row_shares=[7, 3], - ), - rrb.Vertical( - rrb.Spatial2DView( - name="RGB & Depth", - origin="world/camera/image", - overrides={"world/camera/image/rgb": rr.Image.from_fields(opacity=0.5)}, + + if vis_rerun: + import rerun as rr + import rerun.blueprint as rrb + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.TextDocumentView(name="Description", origin="/description"), + row_shares=[7, 3], ), - rrb.Tabs( - rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), - rrb.Spatial2DView(name="Depth", origin="world/camera/image", contents="world/camera/image/depth"), + rrb.Vertical( + rrb.Spatial2DView( + name="RGB & Depth", + origin="world/camera/image", + overrides={"world/camera/image/rgb": rr.Image.from_fields(opacity=0.5)}, + ), + rrb.Tabs( + rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + rrb.Spatial2DView(name="Depth", origin="world/camera/image", contents="world/camera/image/depth"), + ), + name="2D", + row_shares=[3, 3, 2], ), - name="2D", - row_shares=[3, 3, 2], - ), - column_shares=[2, 1], - ) - rr.init(f"spatialmp4_{os.path.basename(video_file)}", spawn=True) - rr.send_blueprint(blueprint) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_X_UP, static=True) # same as open3d + column_shares=[2, 1], + ) + rr.init(f"spatialmp4_{os.path.basename(video_file)}", spawn=True) + rr.send_blueprint(blueprint) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) # same as open3d + view_coord = rr.ViewCoordinates.UBR positions = [] frames = [] @@ -103,13 +104,12 @@ def generate_pcd( while reader.has_next(): rgbd = reader.load_rgbd(True) + if topk is not None and reader.get_index() >= topk: + break if skip_last_frame and reader.get_index() == reader.get_frame_count() - 1: continue print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") - if reader.get_index() > 20: - break - # preprocess on depthmap depth_np = rgbd.depth depth_uint16 = (depth_np * 1000).astype(np.uint16) @@ -120,129 +120,120 @@ def generate_pcd( depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 extrinsic = rgbd.T_W_S - extrinsic_o3d = pico_pose_to_open3d(extrinsic) + extrinsic = pico_pose_to_open3d(extrinsic) - # rorate - rgb_rotated = cv2.rotate(rgbd.rgb, cv2.ROTATE_90_CLOCKWISE) - depth_rotated = cv2.rotate(depth_np, cv2.ROTATE_90_CLOCKWISE) rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( - o3d.geometry.Image(rgb_rotated), - o3d.geometry.Image(depth_rotated), + o3d.geometry.Image(rgbd.rgb), + o3d.geometry.Image(depth_np), depth_scale=1.0, depth_trunc=5.0, - convert_rgb_to_intensity=True + convert_rgb_to_intensity=False ) - volume.integrate(rgbd_image, intrinsic_o3d, extrinsic_o3d) + volume.integrate(rgbd_image, intrinsic, extrinsic) - pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic_o3d) - pcd_i.transform(extrinsic_o3d) + pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic) + pcd_i.transform(np.linalg.inv(extrinsic)) pcd_i.paint_uniform_color([0, 0, 1]) frames.append(pcd_i) - - rr.set_time_seconds("time", rgbd.timestamp) - rr.log("world/xyz", rr.Arrows3D(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]])) - rr.log("world/camera/image", rr.Pinhole( - resolution=[width, height], - focal_length=[intrinsic.intrinsic_matrix[0, 0], intrinsic.intrinsic_matrix[1, 1]], - principal_point=[intrinsic.intrinsic_matrix[0, 2], intrinsic.intrinsic_matrix[1, 2]], - camera_xyz=rr.ViewCoordinates.URF, - )) - position = extrinsic[:3, 3] - rotation = Rotation.from_matrix(extrinsic[:3, :3]).as_quat() - rr.log("world/camera", rr.Transform3D(translation=position, rotation=rr.Quaternion(xyzw=rotation))) - rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) - rr.log("world/camera/image/depth", rr.DepthImage(depth_np, meter=1.0)) + + if vis_rerun: + rr.set_time_seconds("time", rgbd.timestamp) + rr.log("world/xyz", rr.Arrows3D(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]])) + rr.log("world/camera/image", rr.Pinhole( + resolution=[width, height], + focal_length=[intrinsic.intrinsic_matrix[0, 0], intrinsic.intrinsic_matrix[1, 1]], + principal_point=[intrinsic.intrinsic_matrix[0, 2], intrinsic.intrinsic_matrix[1, 2]], + camera_xyz=view_coord, + )) + position = extrinsic[:3, 3] + rotation = Rotation.from_matrix(extrinsic[:3, :3]).as_quat() + rr.log("world/camera", rr.Transform3D(translation=position, rotation=rr.Quaternion(xyzw=rotation))) + rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) + rr.log("world/camera/image/depth", rr.DepthImage(depth_np, meter=1.0)) pcd = volume.extract_point_cloud() pcd.paint_uniform_color([1, 1, 0]) - origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1.0, origin=[0, 0, 0]) - - vis=o3d.visualization.VisualizerWithKeyCallback() - vis.create_window() - idx=0 - vis.add_geometry(origin) - vis.add_geometry(frames[idx]) - #vis.update_renderer() - - def save_view_control(vis): - vc = vis.get_view_control() - params = vc.convert_to_pinhole_camera_parameters() - data = { - "extrinsic": params.extrinsic, - "intrinsic_matrix": params.intrinsic.intrinsic_matrix, - "width": params.intrinsic.width, - "height": params.intrinsic.height, - } - with open("view_control.pkl", "wb") as f: - pickle.dump(data, f) - print("Saved view control") - - def click_next(vis): - nonlocal idx - print('a_click') - vis.clear_geometries() - vis.add_geometry(origin) - vis.add_geometry(pcd) - vis.add_geometry(frames[idx]) - idx = (idx+1) % len(frames) + print("Pointcloud post processing...") + pcd = pcd.remove_non_finite_points() + pcd = pcd.voxel_down_sample(voxel_size=down_voxel_size) + _, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2) + print(f"Valid points: {len(ind)} / {len(pcd.points)} ({len(ind) / len(pcd.points) * 100:.2f} %)") + pcd = pcd.select_by_index(ind) + o3d.io.write_point_cloud(output, pcd) + print(f"Saved {len(pcd.points)} total points to {output}") - if os.path.exists("view_control.pkl"): - vc = vis.get_view_control() - with open("view_control.pkl", "rb") as f: - data = pickle.load(f) - params = o3d.camera.PinholeCameraParameters() - params.extrinsic = data["extrinsic"] - params.intrinsic = o3d.camera.PinholeCameraIntrinsic( - data["width"], data["height"], data["intrinsic_matrix"] - ) - vc.convert_from_pinhole_camera_parameters(params) - - - def click_prev(vis): - nonlocal idx - print('b_click') - vis.clear_geometries() + if vis_open3d: + origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1.0, origin=[0, 0, 0]) + vis=o3d.visualization.VisualizerWithKeyCallback() + vis.create_window() + idx = 0 vis.add_geometry(origin) - vis.add_geometry(pcd) vis.add_geometry(frames[idx]) - idx = (idx-1) % len(frames) - idx = max(idx, 0) - if os.path.exists("view_control.pkl"): - vc = vis.get_view_control() - with open("view_control.pkl", "rb") as f: - data = pickle.load(f) - params = o3d.camera.PinholeCameraParameters() - params.extrinsic = data["extrinsic"] - params.intrinsic = o3d.camera.PinholeCameraIntrinsic( - data["width"], data["height"], data["intrinsic_matrix"] - ) - vc.convert_from_pinhole_camera_parameters(params) - - def exit_key(vis): - vis.destroy_window() - import glfw - vis.register_key_callback(glfw.KEY_A,click_next) - vis.register_key_callback(glfw.KEY_B,click_prev) - vis.register_key_callback(glfw.KEY_S,save_view_control) - vis.register_key_callback(glfw.KEY_ESCAPE,exit_key) - vis.poll_events() - vis.run() - #vis.destroy_window() - - - # print("[Info] Removing non-finite points...") - # pcd = pcd.remove_non_finite_points() - # print("[Info] Downsampling point cloud using voxel grid...") - # pcd = pcd.voxel_down_sample(voxel_size=args.down_voxel_size) - # print("[Info] Removing statistical outliers...") - # _, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2) - # print(f"[Info] Valid points: {len(ind)} / {len(pcd.points)} ({len(ind) / len(pcd.points) * 100:.2f} %)") - # pcd = pcd.select_by_index(ind) - o3d.io.write_point_cloud(output, pcd) - print(f"[Info] Saved {len(pcd.points)} total points to {output}") + def save_view_control(vis): + vc = vis.get_view_control() + params = vc.convert_to_pinhole_camera_parameters() + data = { + "extrinsic": params.extrinsic, + "intrinsic_matrix": params.intrinsic.intrinsic_matrix, + "width": params.intrinsic.width, + "height": params.intrinsic.height, + } + with open("view_control.pkl", "wb") as f: + pickle.dump(data, f) + print("Saved view control") + + def click_next(vis): + nonlocal idx + print('a_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(pcd) + vis.add_geometry(frames[idx]) + idx = (idx+1) % len(frames) + + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + def click_prev(vis): + nonlocal idx + print('b_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(pcd) + vis.add_geometry(frames[idx]) + idx = (idx-1) % len(frames) + idx = max(idx, 0) + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + def exit_key(vis): + vis.destroy_window() + + vis.register_key_callback(65, click_next) # glfw.KEY_A + vis.register_key_callback(66, click_prev) # glfw.KEY_B + vis.register_key_callback(83, save_view_control) # glfw.KEY_S + vis.register_key_callback(256, exit_key) # glfw.KEY_ESCAPE + vis.poll_events() + vis.run() if __name__ == "__main__":# - typer.run(generate_pcd) \ No newline at end of file + typer.run(generate_pcd) diff --git a/examples/python/visualize_open3d.py b/examples/python/visualize_open3d.py index e69de29..9fa5c78 100644 --- a/examples/python/visualize_open3d.py +++ b/examples/python/visualize_open3d.py @@ -0,0 +1,169 @@ +import typer +import os +import pickle +import cv2 +import numpy as np +import open3d as o3d +import spatialmp4 as sm + +''' +Rerun for different data source: + + colmap: + rr.ViewCoordinates.RIGHT_HAND_Y_DOWN + rr.log("camera", rr.ViewCoordinates.RDF, static=True) + +''' + +def pico_pose_to_open3d(extrinsic): + convert = np.array([ + [0, 0, 1, 0], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) + output = convert @ extrinsic + return output + + +def main( + video_file: str, + topk: int = None, +): + """Generate pcd file from spatialmp4, using TSDF in open3d. + """ + reader = sm.Reader(video_file) + reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) + + if not reader.has_depth(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + return + if not reader.has_pose(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + return + + positions = [] + frames = [] + + intrinsic = o3d.camera.PinholeCameraIntrinsic() + width = reader.get_rgb_width() + height = reader.get_rgb_height() + intrinsic.set_intrinsics( + width=width, + height=height, + fx=float(reader.get_rgb_intrinsics_left().fx), + fy=float(reader.get_rgb_intrinsics_left().fy), + cx=float(reader.get_rgb_intrinsics_left().cx), + cy=float(reader.get_rgb_intrinsics_left().cy) + ) + intrinsic_o3d = o3d.camera.PinholeCameraIntrinsic( + width=height, + height=width, + fx=float(reader.get_rgb_intrinsics_left().fy), + fy=float(reader.get_rgb_intrinsics_left().fx), + cx=float(reader.get_rgb_intrinsics_left().cy), + cy=width - 1 - float(reader.get_rgb_intrinsics_left().cx) + ) + + while reader.has_next(): + rgbd = reader.load_rgbd(True) + if topk is not None and reader.get_index() >= topk: + break + print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") + + # preprocess on depthmap + depth_np = rgbd.depth + depth_uint16 = (depth_np * 1000).astype(np.uint16) + sobelx = cv2.Sobel(depth_uint16, cv2.CV_32F, 1, 0, ksize=3) + sobely = cv2.Sobel(depth_uint16, cv2.CV_32F, 0, 1, ksize=3) + grad_mag = np.sqrt(sobelx**2 + sobely**2) + depth_np[grad_mag > 500] = 0 + depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 + + extrinsic = rgbd.T_W_S + extrinsic = pico_pose_to_open3d(extrinsic) + + rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( + o3d.geometry.Image(rgbd.rgb), + o3d.geometry.Image(depth_np), + depth_scale=1.0, + depth_trunc=5.0, + convert_rgb_to_intensity=True + ) + + pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic) + pcd_i.transform(np.linalg.inv(extrinsic)) + pcd_i.paint_uniform_color([0, 0, 1]) + frames.append(pcd_i) + + origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1.0, origin=[0, 0, 0]) + vis=o3d.visualization.VisualizerWithKeyCallback() + vis.create_window() + idx=0 + vis.add_geometry(origin) + vis.add_geometry(frames[idx]) + + def save_view_control(vis): + vc = vis.get_view_control() + params = vc.convert_to_pinhole_camera_parameters() + data = { + "extrinsic": params.extrinsic, + "intrinsic_matrix": params.intrinsic.intrinsic_matrix, + "width": params.intrinsic.width, + "height": params.intrinsic.height, + } + with open("view_control.pkl", "wb") as f: + pickle.dump(data, f) + print("Saved view control") + + def click_next(vis): + nonlocal idx + print('a_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(frames[idx]) + idx = (idx+1) % len(frames) + + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + def click_prev(vis): + nonlocal idx + print('b_click') + vis.clear_geometries() + vis.add_geometry(origin) + vis.add_geometry(frames[idx]) + idx = (idx-1) % len(frames) + idx = max(idx, 0) + if os.path.exists("view_control.pkl"): + vc = vis.get_view_control() + with open("view_control.pkl", "rb") as f: + data = pickle.load(f) + params = o3d.camera.PinholeCameraParameters() + params.extrinsic = data["extrinsic"] + params.intrinsic = o3d.camera.PinholeCameraIntrinsic( + data["width"], data["height"], data["intrinsic_matrix"] + ) + vc.convert_from_pinhole_camera_parameters(params) + + def exit_key(vis): + vis.destroy_window() + + vis.register_key_callback(65, click_next) # glfw.KEY_A + vis.register_key_callback(66, click_prev) # glfw.KEY_B + vis.register_key_callback(83, save_view_control) # glfw.KEY_S + vis.register_key_callback(256, exit_key) # glfw.KEY_ESCAPE + vis.poll_events() + vis.run() + + +if __name__ == "__main__":# + typer.run(main) diff --git a/examples/python/visualize_rerun.py b/examples/python/visualize_rerun.py index e69de29..7dd56fd 100644 --- a/examples/python/visualize_rerun.py +++ b/examples/python/visualize_rerun.py @@ -0,0 +1,100 @@ +import typer +import os +import cv2 +import numpy as np +from scipy.spatial.transform import Rotation +import spatialmp4 as sm +import rerun as rr +import rerun.blueprint as rrb + + +def pico_pose_to_open3d(extrinsic): + convert = np.array([ + [0, 0, 1, 0], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) + output = convert @ extrinsic + return output + + +def main( + video_file: str, +): + """Visualize spatialmp4 using rerun.""" + reader = sm.Reader(video_file) + reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) + + if not reader.has_depth(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + return + if not reader.has_pose(): + typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) + return + + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.TextDocumentView(name="Description", origin="/description"), + row_shares=[7, 3], + ), + rrb.Vertical( + rrb.Spatial2DView( + name="RGB & Depth", + origin="world/camera/image", + overrides={"world/camera/image/rgb": rr.Image.from_fields(opacity=0.5)}, + ), + rrb.Tabs( + rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + rrb.Spatial2DView(name="Depth", origin="world/camera/image", contents="world/camera/image/depth"), + ), + name="2D", + row_shares=[3, 3, 2], + ), + column_shares=[2, 1], + ) + rr.init(f"spatialmp4_{os.path.basename(video_file)}", spawn=True) + rr.send_blueprint(blueprint) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) # same as open3d + view_coord = rr.ViewCoordinates.UBR + + width = reader.get_rgb_width() + height = reader.get_rgb_height() + fx = float(reader.get_rgb_intrinsics_left().fx) + fy = float(reader.get_rgb_intrinsics_left().fy) + cx = float(reader.get_rgb_intrinsics_left().cx) + cy = float(reader.get_rgb_intrinsics_left().cy) + while reader.has_next(): + rgbd = reader.load_rgbd(True) + print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") + + # preprocess on depthmap + depth_np = rgbd.depth + depth_uint16 = (depth_np * 1000).astype(np.uint16) + sobelx = cv2.Sobel(depth_uint16, cv2.CV_32F, 1, 0, ksize=3) + sobely = cv2.Sobel(depth_uint16, cv2.CV_32F, 0, 1, ksize=3) + grad_mag = np.sqrt(sobelx**2 + sobely**2) + depth_np[grad_mag > 500] = 0 + depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 + + extrinsic = rgbd.T_W_S + extrinsic = pico_pose_to_open3d(extrinsic) + + rr.set_time_seconds("time", rgbd.timestamp) + rr.log("world/xyz", rr.Arrows3D(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]])) + rr.log("world/camera/image", rr.Pinhole( + resolution=[width, height], + focal_length=[fx, fy], + principal_point=[cx, cy], + camera_xyz=view_coord, + )) + position = extrinsic[:3, 3] + rotation = Rotation.from_matrix(extrinsic[:3, :3]).as_quat() + rr.log("world/camera", rr.Transform3D(translation=position, rotation=rr.Quaternion(xyzw=rotation))) + rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) + rr.log("world/camera/image/depth", rr.DepthImage(depth_np, meter=1.0)) + + +if __name__ == "__main__":# + typer.run(main) diff --git a/src/spatialmp4/reader.cc b/src/spatialmp4/reader.cc index 85a84fa..c159e9e 100644 --- a/src/spatialmp4/reader.cc +++ b/src/spatialmp4/reader.cc @@ -332,15 +332,13 @@ Reader::Reader(const std::string& filename) rgb_extrinsics_left_.extrinsics = cv::Matx44d(extrinsics_data[0], extrinsics_data[1], extrinsics_data[2], extrinsics_data[3], extrinsics_data[4], extrinsics_data[5], extrinsics_data[6], extrinsics_data[7], - extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], - 0, 0, 0, 1); + extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], 0, 0, 0, 1); } else if (std::string(tag->key).find("ecam_1") != std::string::npos) { std::vector extrinsics_data = SpatialML::String2DoubleVector(tag->value); rgb_extrinsics_right_.extrinsics = cv::Matx44d(extrinsics_data[0], extrinsics_data[1], extrinsics_data[2], extrinsics_data[3], extrinsics_data[4], extrinsics_data[5], extrinsics_data[6], extrinsics_data[7], - extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], - 0, 0, 0, 1); + extrinsics_data[8], extrinsics_data[9], extrinsics_data[10], extrinsics_data[11], 0, 0, 0, 1); } else if (std::string(tag->key).find("distortion_model") != std::string::npos) { is_rgb_distorted_ = true; rgb_distortion_model_ = tag->value; @@ -531,6 +529,7 @@ void Reader::Load(rgb_frame& frame_rgb, depth_frame& frame_depth) { rgb_frame_pts_queue_.addPose(rgb_timestamp, rgb_frame_pts); } } + // rgb_frame_pts_queue_.print(); av_seek_frame(pFormatCtx_, depth_frame_id_, keyframes_depth[keyframe_depth_idx_], AVSEEK_FLAG_BACKWARD); while (av_read_frame(pFormatCtx_, ¤t_packet_) >= 0) { @@ -552,7 +551,13 @@ void Reader::Load(rgb_frame& frame_rgb, depth_frame& frame_depth) { int64_t target_rgb_pts; double time_diff; double depth_timestamp = frame_depth.timestamp; - rgb_frame_pts_queue_.findNearestPose(depth_timestamp, target_rgb_pts, time_diff); + if (!rgb_frame_pts_queue_.findNearestPose(depth_timestamp, target_rgb_pts, time_diff)) { + std::cerr << "findNearestPose failed" << std::endl; + return; + } + if (time_diff > 0.1) { + spdlog::warn("time_diff is too large: {:.4f}", time_diff); + } // 2. get nearest rgb packet auto compare = [](int64_t a, int64_t b) { return a < b; }; @@ -685,8 +690,11 @@ void Reader::Load(Utilities::Rgbd& rgbd, bool densify) { if (densify) { // densify depth by nearest neighbor interpolation float scale = frame_rgb.left_rgb.cols / frame_depth.depth.cols; - cv::resize(frame_depth.depth, frame_depth.depth, - cv::Size(frame_rgb.left_rgb.cols, frame_rgb.left_rgb.rows), cv::INTER_NEAREST); + std::cout << "frame_rgb.left_rgb.cols: " << frame_rgb.left_rgb.cols << std::endl; + std::cout << "frame_depth.depth.cols: " << frame_depth.depth.cols << std::endl; + std::cout << "scale: " << scale << std::endl; + cv::resize(frame_depth.depth, frame_depth.depth, cv::Size(frame_rgb.left_rgb.cols, frame_rgb.left_rgb.rows), + cv::INTER_NEAREST); K_tof = GetDepthIntrinsics().as_cvmat(); K_tof(0, 0) *= scale; K_tof(1, 1) *= scale; @@ -694,9 +702,9 @@ void Reader::Load(Utilities::Rgbd& rgbd, bool densify) { K_tof(1, 2) *= scale; } - Utilities::ProjectDepthToRgb(frame_depth.depth, frame_rgb.left_rgb, GetRgbIntrinsicsLeft().as_cvmat(), - K_tof, T_Srgb_Stof, projected_depth, true); - + Utilities::ProjectDepthToRgb(frame_depth.depth, frame_rgb.left_rgb, GetRgbIntrinsicsLeft().as_cvmat(), K_tof, + T_Srgb_Stof, projected_depth, true); + rgbd = Utilities::Rgbd(frame_rgb.left_rgb, projected_depth, frame_depth.timestamp, T_W_Stof); } diff --git a/src/spatialmp4/utilities/SyncPose.hpp b/src/spatialmp4/utilities/SyncPose.hpp index 3aded75..59ea281 100644 --- a/src/spatialmp4/utilities/SyncPose.hpp +++ b/src/spatialmp4/utilities/SyncPose.hpp @@ -78,14 +78,28 @@ class SynchronizedQueue { } } + void print() const { + std::unique_lock lock(mtx); + // print top3 and tail 3 + for (int i = 0; i < 3; i++) { + std::cout << "timestamp: " << pose_queue[i].timestamp << ", data: " << pose_queue[i].data << std::endl; + } + std::cout << "..." << std::endl; + for (int i = pose_queue.size() - 3; i < pose_queue.size(); i++) { + std::cout << "timestamp: " << pose_queue[i].timestamp << ", data: " << pose_queue[i].data << std::endl; + } + } + bool findNearestPose(double rgb_timestamp, PoseType& pose, double& time_diff) { std::unique_lock lock(mtx); if (pose_queue.empty()) { + std::cerr << "pose_queue is empty" << std::endl; return false; } - if (rgb_timestamp < pose_queue.front().timestamp || rgb_timestamp > pose_queue.back().timestamp) { - return false; - } + // if (rgb_timestamp < pose_queue.front().timestamp || rgb_timestamp > pose_queue.back().timestamp) { + // std::cerr << "rgb_timestamp is out of range" << std::endl; + // return false; + // } auto it = std::lower_bound(pose_queue.begin(), pose_queue.end(), rgb_timestamp, [](const TimestampedData& data, double ts) { return data.timestamp < ts; }); From b2f679c96669d8d4912666457ac37c4fdc5602d6 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 15 Jul 2025 19:30:51 +0800 Subject: [PATCH 27/31] update docs --- README.md | 164 +++++- bindings/spatialmp4.cpp | 476 +++++++++--------- ...ap_format.py => generate_colmap_format.py} | 0 .../{01_generate_pcd.py => generate_pcd.py} | 8 +- examples/python/visualize_open3d.py | 92 +++- examples/python/visualize_rerun.py | 54 +- python/tests/test_reader.py | 3 +- src/spatialmp4/reader.cc | 57 ++- src/spatialmp4/reader.h | 9 +- 9 files changed, 570 insertions(+), 293 deletions(-) rename examples/python/{02_generate_colmap_format.py => generate_colmap_format.py} (100%) rename examples/python/{01_generate_pcd.py => generate_pcd.py} (97%) diff --git a/README.md b/README.md index 773083c..d3b25a3 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ The project depends on the following third-party libraries: - [**fmt**](https://github.com/fmtlib/fmt): Modern C++ formatting library - [**Google Test**](https://github.com/google/googletest): Unit testing framework (optional) -## 🛠️ Build and Installation +## 🛠️ Build and Installation (cpp) ### 1. Clone Repository @@ -89,7 +89,36 @@ cd .. ./build/test_reader ``` -## 📖 Usage Guide +## 🛠️ Build and Installation (python) + +### 1. Clone Repository + +```bash +git clone https://github.com/Pico-Developer/SpatialMP4 +cd SpatialMP4 +``` + +### 2. Build FFmpeg + +Build `ffmpeg` first: + +```bash +bash scripts/build_ffmpeg.sh +``` + +### 3. Install Dependencies + +```bash +bash scripts/install_deps.sh +``` + +### 4. Build and Install + +```bash +pip3 instsall . +``` + +## 📖 Usage Guide (cpp) ### Basic Usage @@ -211,7 +240,7 @@ Utilities::RgbdToPointcloud(rgb_frame.left_rgb, projected_depth, Utilities::SavePointcloudToFile("output.obj", pcd); ``` -## 📚 API Reference +## 📚 API Reference (cpp) ### SpatialML::Reader @@ -288,20 +317,125 @@ struct pose_frame { }; ``` -## 🔍 Utility Functions +## 📖 Usage Guide (cpp) + + +### Basic Usage Example + +```python +import spatialmp4 -### Image Processing (OpencvUtils) -- `VisualizeMat()`: Visualize matrix data -- `DumpMat()` / `LoadMat()`: Save/load matrices -- `ConcatenateMat()`: Concatenate multiple images +# Create a reader +reader = spatialmp4.Reader("your_video.mp4") + +# Check available streams +print("Has RGB:", reader.has_rgb()) +print("Has Depth:", reader.has_depth()) +print("Has Pose:", reader.has_pose()) + +# Set reading mode +reader.set_read_mode(spatialmp4.ReadMode.DEPTH_FIRST) + +# Read frames +while reader.has_next(): + rgb_frame, depth_frame = reader.load_both() + left_rgb = rgb_frame.left_rgb # numpy array (H, W, 3) + depth = depth_frame.depth # numpy array (H, W) + pose = rgb_frame.pose + print("RGB timestamp:", rgb_frame.timestamp, "Pose:", pose.x, pose.y, pose.z) +``` -### RGBD Processing (RgbdUtils) -- `ProjectDepthToRgb()`: Project depth to RGB -- `RgbdToPointcloud()`: Convert RGBD to point cloud +## 📚 API Reference (python) + +### Main Classes and Methods + +#### `spatialmp4.Reader` +Main class for reading SpatialMP4 files. + +- `Reader(filename: str)` — Create a new reader for the given file. +- `has_rgb() -> bool` — Whether the file contains RGB data. +- `has_depth() -> bool` — Whether the file contains depth data. +- `has_pose() -> bool` — Whether the file contains pose data. +- `has_audio() -> bool` — Whether the file contains audio data. +- `has_disparity() -> bool` — Whether the file contains disparity data. +- `get_duration() -> float` — Get video duration in seconds. +- `get_rgb_fps() -> float` — Get RGB stream FPS. +- `get_depth_fps() -> float` — Get depth stream FPS. +- `get_rgb_width() -> int` — Get RGB frame width. +- `get_rgb_height() -> int` — Get RGB frame height. +- `get_depth_width() -> int` — Get depth frame width. +- `get_depth_height() -> int` — Get depth frame height. +- `get_rgb_intrinsics_left() -> CameraIntrinsics` — Get left RGB camera intrinsics. +- `get_rgb_intrinsics_right() -> CameraIntrinsics` — Get right RGB camera intrinsics. +- `get_rgb_extrinsics_left() -> CameraExtrinsics` — Get left RGB camera extrinsics. +- `get_rgb_extrinsics_right() -> CameraExtrinsics` — Get right RGB camera extrinsics. +- `get_depth_intrinsics() -> CameraIntrinsics` — Get depth camera intrinsics. +- `get_depth_extrinsics() -> CameraExtrinsics` — Get depth camera extrinsics. +- `get_pose_frames() -> List[PoseFrame]` — Get all pose frames. +- `set_read_mode(mode: ReadMode)` — Set reading mode (see enums below). +- `has_next() -> bool` — Whether there is a next frame. +- `reset()` — Reset to the beginning of the file. +- `get_index() -> int` — Get current frame index. +- `get_frame_count() -> int` — Get total number of frames. +- `load_rgb() -> RGBFrame` — Load the next RGB frame. +- `load_depth(raw_head_pose: bool = False) -> DepthFrame` — Load the next depth frame. +- `load_both() -> (RGBFrame, DepthFrame)` — Load the next RGB and depth frames simultaneously. +- `load_rgbd(densify: bool = False) -> Rgbd` — Load RGBD data (for advanced use). + +#### `spatialmp4.RGBFrame` +- `timestamp: float` — Frame timestamp. +- `left_rgb: np.ndarray` — Left RGB image (H, W, 3, uint8). +- `right_rgb: np.ndarray` — Right RGB image (H, W, 3, uint8). +- `pose: PoseFrame` — Associated pose data. + +#### `spatialmp4.DepthFrame` +- `timestamp: float` — Frame timestamp. +- `depth: np.ndarray` — Depth image (H, W, float32, meters). +- `pose: PoseFrame` — Associated pose data. + +#### `spatialmp4.PoseFrame` +- `timestamp: float` — Pose timestamp. +- `x, y, z: float` — Position. +- `qw, qx, qy, qz: float` — Quaternion orientation. +- `as_se3()` — Convert to SE(3) representation (requires Sophus/Eigen, advanced use). + +#### `spatialmp4.CameraIntrinsics` +- `fx, fy, cx, cy: float` — Camera intrinsic parameters. +- `as_cvmat()` — Return as OpenCV matrix. + +#### `spatialmp4.CameraExtrinsics` +- `extrinsics: np.ndarray` — 4x4 extrinsic matrix. +- `as_cvmat()` — Return as OpenCV matrix. +- `as_se3()` — Return as SE(3) (advanced use). + +--- + +### Enums + +#### `spatialmp4.ReadMode` +- `RGB_ONLY` — Only read RGB frames. +- `DEPTH_ONLY` — Only read depth frames. +- `DEPTH_FIRST` — Read both RGB and depth frames, depth as reference. + +#### `spatialmp4.StreamType` +- `UNKNOWN` — Unknown stream type +- `AUDIO` — Audio stream +- `AUDIO_2` — Secondary audio stream +- `RGB` — RGB video stream +- `DISPARITY` — Disparity stream +- `POSE` — Pose data stream +- `DEPTH` — Depth stream + +--- + +### Advanced Usage + +- See `examples/python/visualize_rerun.py` and `examples/python/generate_pcd.py` for advanced usage, including point cloud generation and visualization with Open3D or Rerun. +- All image and depth data are returned as NumPy arrays for easy integration with OpenCV, Open3D, PyTorch, etc. +- Camera parameters and pose data can be used for 3D reconstruction and SLAM applications. + +--- -### Point Cloud Processing (PointcloudUtils) -- `SavePointcloudToFile()`: Save point cloud files -- Support for OBJ format output ## 🐛 Debugging and Logging @@ -326,4 +460,4 @@ Issues and Pull Requests are welcome to improve this project! ## 📞 Contact -For questions or suggestions, please contact us through GitHub Issues. +For questions or suggestions, please contact us through GitHub Issues. \ No newline at end of file diff --git a/bindings/spatialmp4.cpp b/bindings/spatialmp4.cpp index 9857290..21739d8 100644 --- a/bindings/spatialmp4.cpp +++ b/bindings/spatialmp4.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include @@ -12,237 +28,245 @@ namespace py = pybind11; // Helper function to convert cv::Mat to numpy array -py::array_t mat_to_numpy(const cv::Mat& mat) { - if (mat.empty()) { - return py::array_t(); - } - - py::array_t array({mat.rows, mat.cols, mat.channels()}); - std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); - return array; +py::array_t mat_to_numpy(const cv::Mat &mat) { + if (mat.empty()) { + return py::array_t(); + } + + py::array_t array({mat.rows, mat.cols, mat.channels()}); + std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); + return array; } // Helper function to convert depth cv::Mat to numpy array -py::array_t depth_mat_to_numpy(const cv::Mat& mat) { - if (mat.empty()) { - return py::array_t(); - } - - py::array_t array({mat.rows, mat.cols}); - std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); - return array; +py::array_t depth_mat_to_numpy(const cv::Mat &mat) { + if (mat.empty()) { + return py::array_t(); + } + + py::array_t array({mat.rows, mat.cols}); + std::memcpy(array.mutable_data(), mat.data, mat.total() * mat.elemSize()); + return array; } PYBIND11_MODULE(spatialmp4, m) { - m.doc() = "SpatialMP4 Python Bindings"; - - // 添加版本信息 - m.attr("__version__") = SpatialML::GetVersion(); - m.def("get_version", &SpatialML::GetVersion, "Get the version string"); - m.def("get_major_version", &SpatialML::GetMajorVersion, "Get the major version number"); - m.def("get_minor_version", &SpatialML::GetMinorVersion, "Get the minor version number"); - m.def("get_patch_version", &SpatialML::GetPatchVersion, "Get the patch version number"); - - // Bind StreamType enum - py::enum_(m, "StreamType") - .value("UNKNOWN", SpatialML::MEDIA_TYPE_UNKNOWN) - .value("AUDIO", SpatialML::MEDIA_TYPE_AUDIO) - .value("AUDIO_2", SpatialML::MEDIA_TYPE_AUDIO_2) - .value("RGB", SpatialML::MEDIA_TYPE_RGB) - .value("DISPARITY", SpatialML::MEDIA_TYPE_DISPARITY) - .value("POSE", SpatialML::MEDIA_TYPE_POSE) - .value("DEPTH", SpatialML::MEDIA_TYPE_DEPTH) - .export_values(); - - // Bind pose_frame struct - py::class_(m, "PoseFrame") - .def(py::init<>()) - .def_readwrite("timestamp", &SpatialML::pose_frame::timestamp) - .def_readwrite("x", &SpatialML::pose_frame::x) - .def_readwrite("y", &SpatialML::pose_frame::y) - .def_readwrite("z", &SpatialML::pose_frame::z) - .def_readwrite("qw", &SpatialML::pose_frame::qw) - .def_readwrite("qx", &SpatialML::pose_frame::qx) - .def_readwrite("qy", &SpatialML::pose_frame::qy) - .def_readwrite("qz", &SpatialML::pose_frame::qz) - .def("as_se3", &SpatialML::pose_frame::as_se3) - .def("__repr__", [](const SpatialML::pose_frame &p) { - std::ostringstream ss; - ss << p; - return ss.str(); - }); - - // Bind rgb_frame struct - py::class_(m, "RGBFrame") - .def(py::init<>()) - .def_readwrite("timestamp", &SpatialML::rgb_frame::timestamp) - .def_property("left_rgb", - [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.left_rgb); }, - [](SpatialML::rgb_frame &f, py::array_t arr) { - // TODO: implement setter if needed - }) - .def_property("right_rgb", - [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.right_rgb); }, - [](SpatialML::rgb_frame &f, py::array_t arr) { - // TODO: implement setter if needed - }) - .def_readwrite("pose", &SpatialML::rgb_frame::pose) - .def("__repr__", [](const SpatialML::rgb_frame &f) { - std::ostringstream ss; - ss << f; - return ss.str(); - }); - - // Bind depth_frame struct - py::class_(m, "DepthFrame") - .def(py::init<>()) - .def_readwrite("timestamp", &SpatialML::depth_frame::timestamp) - .def_property("depth", - [](const SpatialML::depth_frame &f) { return depth_mat_to_numpy(f.depth); }, - [](SpatialML::depth_frame &f, py::array_t arr) { - // TODO: implement setter if needed - }) - .def_readwrite("pose", &SpatialML::depth_frame::pose) - .def("__repr__", [](const SpatialML::depth_frame &f) { - std::ostringstream ss; - ss << f; - return ss.str(); - }); - - // Bind camera_intrinsics struct - py::class_(m, "CameraIntrinsics") - .def(py::init<>()) - .def_readwrite("fx", &SpatialML::camera_intrinsics::fx) - .def_readwrite("fy", &SpatialML::camera_intrinsics::fy) - .def_readwrite("cx", &SpatialML::camera_intrinsics::cx) - .def_readwrite("cy", &SpatialML::camera_intrinsics::cy) - .def("as_cvmat", &SpatialML::camera_intrinsics::as_cvmat) - .def("__repr__", [](const SpatialML::camera_intrinsics &i) { - std::ostringstream ss; - ss << i; - return ss.str(); - }); - - // Bind camera_extrinsics struct - py::class_(m, "CameraExtrinsics") - .def(py::init<>()) - .def_readwrite("extrinsics", &SpatialML::camera_extrinsics::extrinsics) - .def("as_cvmat", &SpatialML::camera_extrinsics::as_cvmat) - .def("as_se3", &SpatialML::camera_extrinsics::as_se3) - .def("__repr__", [](const SpatialML::camera_extrinsics &e) { - std::ostringstream ss; - ss << e; - return ss.str(); - }); - - // Bind Reader class - py::class_(m, "Reader") - .def(py::init()) - .def("has_rgb", &SpatialML::Reader::HasRGB) - .def("has_depth", &SpatialML::Reader::HasDepth) - .def("has_pose", &SpatialML::Reader::HasPose) - .def("has_audio", &SpatialML::Reader::HasAudio) - .def("has_disparity", &SpatialML::Reader::HasDisparity) - .def("get_start_timestamp", &SpatialML::Reader::GetStartTimestamp) - .def("get_duration", &SpatialML::Reader::GetDuration) - .def("get_rgb_fps", &SpatialML::Reader::GetRgbFPS) - .def("get_rgb_width", &SpatialML::Reader::GetRgbWidth) - .def("get_rgb_height", &SpatialML::Reader::GetRgbHeight) - .def("get_rgb_intrinsics_left", &SpatialML::Reader::GetRgbIntrinsicsLeft) - .def("get_rgb_extrinsics_left", &SpatialML::Reader::GetRgbExtrinsicsLeft) - .def("get_rgb_intrinsics_right", &SpatialML::Reader::GetRgbIntrinsicsRight) - .def("get_rgb_extrinsics_right", &SpatialML::Reader::GetRgbExtrinsicsRight) - .def("get_depth_fps", &SpatialML::Reader::GetDepthFPS) - .def("get_depth_width", &SpatialML::Reader::GetDepthWidth) - .def("get_depth_height", &SpatialML::Reader::GetDepthHeight) - .def("get_depth_intrinsics", &SpatialML::Reader::GetDepthIntrinsics) - .def("get_depth_extrinsics", &SpatialML::Reader::GetDepthExtrinsics) - .def("get_pose_frames", &SpatialML::Reader::GetPoseFrames) - .def("get_rgb_keyframe_index", &SpatialML::Reader::GetRgbKeyframeIndex) - .def("get_depth_keyframe_index", &SpatialML::Reader::GetDepthKeyframeIndex) - .def("is_rgb_distorted", &SpatialML::Reader::IsRgbDistorted) - .def("get_rgb_distortion_model", &SpatialML::Reader::GetRgbDistortionModel) - .def("get_rgb_distortion_params_left", &SpatialML::Reader::GetRgbDistortionParamsLeft) - .def("get_rgb_distortion_params_right", &SpatialML::Reader::GetRgbDistortionParamsRight) - .def("get_depth_distortion_model", &SpatialML::Reader::GetDepthDistortionModel) - .def("get_depth_distortion_params", &SpatialML::Reader::GetDepthDistortionParams) - .def("get_rgb_timebase", &SpatialML::Reader::GetRgbTimebase) - .def("get_depth_timebase", &SpatialML::Reader::GetDepthTimebase) - .def("set_read_mode", &SpatialML::Reader::SetReadMode) - .def("has_next", &SpatialML::Reader::HasNext) - .def("load_rgb", [](SpatialML::Reader& self) { - SpatialML::rgb_frame frame; - self.Load(frame); - return frame; - }) - .def("load_depth", [](SpatialML::Reader& self) { + m.doc() = "SpatialMP4 Python Bindings"; + + // 添加版本信息 + m.attr("__version__") = SpatialML::GetVersion(); + m.def("get_version", &SpatialML::GetVersion, "Get the version string"); + m.def("get_major_version", &SpatialML::GetMajorVersion, "Get the major version number"); + m.def("get_minor_version", &SpatialML::GetMinorVersion, "Get the minor version number"); + m.def("get_patch_version", &SpatialML::GetPatchVersion, "Get the patch version number"); + + // Bind StreamType enum + py::enum_(m, "StreamType") + .value("UNKNOWN", SpatialML::MEDIA_TYPE_UNKNOWN) + .value("AUDIO", SpatialML::MEDIA_TYPE_AUDIO) + .value("AUDIO_2", SpatialML::MEDIA_TYPE_AUDIO_2) + .value("RGB", SpatialML::MEDIA_TYPE_RGB) + .value("DISPARITY", SpatialML::MEDIA_TYPE_DISPARITY) + .value("POSE", SpatialML::MEDIA_TYPE_POSE) + .value("DEPTH", SpatialML::MEDIA_TYPE_DEPTH) + .export_values(); + + // Bind pose_frame struct + py::class_(m, "PoseFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::pose_frame::timestamp) + .def_readwrite("x", &SpatialML::pose_frame::x) + .def_readwrite("y", &SpatialML::pose_frame::y) + .def_readwrite("z", &SpatialML::pose_frame::z) + .def_readwrite("qw", &SpatialML::pose_frame::qw) + .def_readwrite("qx", &SpatialML::pose_frame::qx) + .def_readwrite("qy", &SpatialML::pose_frame::qy) + .def_readwrite("qz", &SpatialML::pose_frame::qz) + .def("as_se3", &SpatialML::pose_frame::as_se3) + .def("__repr__", [](const SpatialML::pose_frame &p) { + std::ostringstream ss; + ss << p; + return ss.str(); + }); + + // Bind rgb_frame struct + py::class_(m, "RGBFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::rgb_frame::timestamp) + .def_property( + "left_rgb", [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.left_rgb); }, + [](SpatialML::rgb_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property( + "right_rgb", [](const SpatialML::rgb_frame &f) { return mat_to_numpy(f.right_rgb); }, + [](SpatialML::rgb_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_readwrite("pose", &SpatialML::rgb_frame::pose) + .def("__repr__", [](const SpatialML::rgb_frame &f) { + std::ostringstream ss; + ss << f; + return ss.str(); + }); + + // Bind depth_frame struct + py::class_(m, "DepthFrame") + .def(py::init<>()) + .def_readwrite("timestamp", &SpatialML::depth_frame::timestamp) + .def_property( + "depth", [](const SpatialML::depth_frame &f) { return depth_mat_to_numpy(f.depth); }, + [](SpatialML::depth_frame &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_readwrite("pose", &SpatialML::depth_frame::pose) + .def("__repr__", [](const SpatialML::depth_frame &f) { + std::ostringstream ss; + ss << f; + return ss.str(); + }); + + // Bind camera_intrinsics struct + py::class_(m, "CameraIntrinsics") + .def(py::init<>()) + .def_readwrite("fx", &SpatialML::camera_intrinsics::fx) + .def_readwrite("fy", &SpatialML::camera_intrinsics::fy) + .def_readwrite("cx", &SpatialML::camera_intrinsics::cx) + .def_readwrite("cy", &SpatialML::camera_intrinsics::cy) + .def("as_cvmat", &SpatialML::camera_intrinsics::as_cvmat) + .def("__repr__", [](const SpatialML::camera_intrinsics &i) { + std::ostringstream ss; + ss << i; + return ss.str(); + }); + + // Bind camera_extrinsics struct + py::class_(m, "CameraExtrinsics") + .def(py::init<>()) + .def_readwrite("extrinsics", &SpatialML::camera_extrinsics::extrinsics) + .def("as_cvmat", &SpatialML::camera_extrinsics::as_cvmat) + .def("as_se3", &SpatialML::camera_extrinsics::as_se3) + .def("__repr__", [](const SpatialML::camera_extrinsics &e) { + std::ostringstream ss; + ss << e; + return ss.str(); + }); + + // Bind Reader class + py::class_(m, "Reader") + .def(py::init()) + .def("has_rgb", &SpatialML::Reader::HasRGB) + .def("has_depth", &SpatialML::Reader::HasDepth) + .def("has_pose", &SpatialML::Reader::HasPose) + .def("has_audio", &SpatialML::Reader::HasAudio) + .def("has_disparity", &SpatialML::Reader::HasDisparity) + .def("get_start_timestamp", &SpatialML::Reader::GetStartTimestamp) + .def("get_duration", &SpatialML::Reader::GetDuration) + .def("get_rgb_fps", &SpatialML::Reader::GetRgbFPS) + .def("get_rgb_width", &SpatialML::Reader::GetRgbWidth) + .def("get_rgb_height", &SpatialML::Reader::GetRgbHeight) + .def("get_rgb_intrinsics_left", &SpatialML::Reader::GetRgbIntrinsicsLeft) + .def("get_rgb_extrinsics_left", &SpatialML::Reader::GetRgbExtrinsicsLeft) + .def("get_rgb_intrinsics_right", &SpatialML::Reader::GetRgbIntrinsicsRight) + .def("get_rgb_extrinsics_right", &SpatialML::Reader::GetRgbExtrinsicsRight) + .def("get_depth_fps", &SpatialML::Reader::GetDepthFPS) + .def("get_depth_width", &SpatialML::Reader::GetDepthWidth) + .def("get_depth_height", &SpatialML::Reader::GetDepthHeight) + .def("get_depth_intrinsics", &SpatialML::Reader::GetDepthIntrinsics) + .def("get_depth_extrinsics", &SpatialML::Reader::GetDepthExtrinsics) + .def("get_pose_frames", &SpatialML::Reader::GetPoseFrames) + .def("get_rgb_keyframe_index", &SpatialML::Reader::GetRgbKeyframeIndex) + .def("get_depth_keyframe_index", &SpatialML::Reader::GetDepthKeyframeIndex) + .def("is_rgb_distorted", &SpatialML::Reader::IsRgbDistorted) + .def("get_rgb_distortion_model", &SpatialML::Reader::GetRgbDistortionModel) + .def("get_rgb_distortion_params_left", &SpatialML::Reader::GetRgbDistortionParamsLeft) + .def("get_rgb_distortion_params_right", &SpatialML::Reader::GetRgbDistortionParamsRight) + .def("get_depth_distortion_model", &SpatialML::Reader::GetDepthDistortionModel) + .def("get_depth_distortion_params", &SpatialML::Reader::GetDepthDistortionParams) + .def("get_rgb_timebase", &SpatialML::Reader::GetRgbTimebase) + .def("get_depth_timebase", &SpatialML::Reader::GetDepthTimebase) + .def("set_read_mode", &SpatialML::Reader::SetReadMode) + .def("has_next", &SpatialML::Reader::HasNext) + .def("load_rgb", + [](SpatialML::Reader &self) { + SpatialML::rgb_frame frame; + self.Load(frame); + return frame; + }) + .def( + "load_depth", + [](SpatialML::Reader &self, bool raw_head_pose) { SpatialML::depth_frame frame; - self.Load(frame); + self.Load(frame, raw_head_pose); return frame; - }) - .def("load_both", [](SpatialML::Reader& self) { - SpatialML::rgb_frame rgb_frame; - SpatialML::depth_frame depth_frame; - self.Load(rgb_frame, depth_frame); - return py::make_tuple(rgb_frame, depth_frame); - }) - .def("load_rgbd", [](SpatialML::Reader& self, bool densify = false) { - Utilities::Rgbd rgbd; - self.Load(rgbd, densify); - return rgbd; - }) - .def("reset", &SpatialML::Reader::Reset) - .def("get_index", &SpatialML::Reader::GetIndex) - .def("get_frame_count", &SpatialML::Reader::GetFrameCount); - - // Bind ReadMode enum - py::enum_(m, "ReadMode") - .value("RGB_ONLY", SpatialML::Reader::RGB_ONLY) - .value("DEPTH_ONLY", SpatialML::Reader::DEPTH_ONLY) - .value("DEPTH_FIRST", SpatialML::Reader::DEPTH_FIRST) - .export_values(); - - // Bind RandomAccessVideoReader class - py::class_(m, "RandomAccessVideoReader") - .def(py::init<>()) - .def("open", &SpatialML::RandomAccessVideoReader::Open) - .def("get_frame", [](SpatialML::RandomAccessVideoReader& self, int64_t frame_number) -> py::object { - AVFrame* frame = self.GetFrame(frame_number); - if (!frame) { - return py::none(); - } - std::pair rgb_mats; - SpatialML::FrameToBGR24(frame, rgb_mats); - return py::make_tuple(mat_to_numpy(rgb_mats.first), mat_to_numpy(rgb_mats.second)); - }) - .def("get_frame_count", &SpatialML::RandomAccessVideoReader::GetFrameCount) - .def("debug", &SpatialML::RandomAccessVideoReader::Debug); - - // Bind Utilities::Rgbd struct - py::class_(m, "Rgbd") - .def(py::init<>()) - .def_readwrite("timestamp", &Utilities::Rgbd::timestamp) - .def_property("rgb", - [](const Utilities::Rgbd &f) { return mat_to_numpy(f.rgb); }, - [](Utilities::Rgbd &f, py::array_t arr) { - // TODO: implement setter if needed - }) - .def_property("depth", - [](const Utilities::Rgbd &f) { return depth_mat_to_numpy(f.depth); }, - [](Utilities::Rgbd &f, py::array_t arr) { - // TODO: implement setter if needed - }) - .def_property_readonly("T_W_S", - [](const Utilities::Rgbd &f) { - // Expose as Eigen::Matrix4d for now - Eigen::Matrix4d T = f.T_W_S.matrix(); - return T; - }) - .def("__repr__", [](const Utilities::Rgbd &f) { - std::ostringstream ss; - ss << "Rgbd(timestamp=" << f.timestamp << ", rgb shape=[" << f.rgb.rows << "," << f.rgb.cols << "," << f.rgb.channels() << "]"; - ss << ", depth shape=[" << f.depth.rows << "," << f.depth.cols << "]"; - ss << ")"; - return ss.str(); - }); -} \ No newline at end of file + }, + py::arg("raw_head_pose") = false) + .def("load_both", + [](SpatialML::Reader &self) { + SpatialML::rgb_frame rgb_frame; + SpatialML::depth_frame depth_frame; + self.Load(rgb_frame, depth_frame); + return py::make_tuple(rgb_frame, depth_frame); + }) + .def("load_rgbd", + [](SpatialML::Reader &self, bool densify = false) { + Utilities::Rgbd rgbd; + self.Load(rgbd, densify); + return rgbd; + }) + .def("reset", &SpatialML::Reader::Reset) + .def("get_index", &SpatialML::Reader::GetIndex) + .def("get_frame_count", &SpatialML::Reader::GetFrameCount); + + // Bind ReadMode enum + py::enum_(m, "ReadMode") + .value("RGB_ONLY", SpatialML::Reader::RGB_ONLY) + .value("DEPTH_ONLY", SpatialML::Reader::DEPTH_ONLY) + .value("DEPTH_FIRST", SpatialML::Reader::DEPTH_FIRST) + .export_values(); + + // Bind RandomAccessVideoReader class + py::class_(m, "RandomAccessVideoReader") + .def(py::init<>()) + .def("open", &SpatialML::RandomAccessVideoReader::Open) + .def("get_frame", + [](SpatialML::RandomAccessVideoReader &self, int64_t frame_number) -> py::object { + AVFrame *frame = self.GetFrame(frame_number); + if (!frame) { + return py::none(); + } + std::pair rgb_mats; + SpatialML::FrameToBGR24(frame, rgb_mats); + return py::make_tuple(mat_to_numpy(rgb_mats.first), mat_to_numpy(rgb_mats.second)); + }) + .def("get_frame_count", &SpatialML::RandomAccessVideoReader::GetFrameCount) + .def("debug", &SpatialML::RandomAccessVideoReader::Debug); + + // Bind Utilities::Rgbd struct + py::class_(m, "Rgbd") + .def(py::init<>()) + .def_readwrite("timestamp", &Utilities::Rgbd::timestamp) + .def_property( + "rgb", [](const Utilities::Rgbd &f) { return mat_to_numpy(f.rgb); }, + [](Utilities::Rgbd &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property( + "depth", [](const Utilities::Rgbd &f) { return depth_mat_to_numpy(f.depth); }, + [](Utilities::Rgbd &f, py::array_t arr) { + // TODO: implement setter if needed + }) + .def_property_readonly("T_W_S", + [](const Utilities::Rgbd &f) { + // Expose as Eigen::Matrix4d for now + Eigen::Matrix4d T = f.T_W_S.matrix(); + return T; + }) + .def("__repr__", [](const Utilities::Rgbd &f) { + std::ostringstream ss; + ss << "Rgbd(timestamp=" << f.timestamp << ", rgb shape=[" << f.rgb.rows << "," << f.rgb.cols << "," + << f.rgb.channels() << "]"; + ss << ", depth shape=[" << f.depth.rows << "," << f.depth.cols << "]"; + ss << ")"; + return ss.str(); + }); +} diff --git a/examples/python/02_generate_colmap_format.py b/examples/python/generate_colmap_format.py similarity index 100% rename from examples/python/02_generate_colmap_format.py rename to examples/python/generate_colmap_format.py diff --git a/examples/python/01_generate_pcd.py b/examples/python/generate_pcd.py similarity index 97% rename from examples/python/01_generate_pcd.py rename to examples/python/generate_pcd.py index eed7ebf..a97e933 100644 --- a/examples/python/01_generate_pcd.py +++ b/examples/python/generate_pcd.py @@ -103,7 +103,10 @@ def generate_pcd( ) while reader.has_next(): - rgbd = reader.load_rgbd(True) + # rgbd = reader.load_rgbd(True) + rgb_frame, depth_frame = reader.load_both() + import ipdb; ipdb.set_trace() + if topk is not None and reader.get_index() >= topk: break if skip_last_frame and reader.get_index() == reader.get_frame_count() - 1: @@ -133,6 +136,9 @@ def generate_pcd( pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic) pcd_i.transform(np.linalg.inv(extrinsic)) + + o3d.io.write_point_cloud(output+f"_{reader.get_index()}.ply", pcd_i) + pcd_i.paint_uniform_color([0, 0, 1]) frames.append(pcd_i) diff --git a/examples/python/visualize_open3d.py b/examples/python/visualize_open3d.py index 9fa5c78..7cdc9d6 100644 --- a/examples/python/visualize_open3d.py +++ b/examples/python/visualize_open3d.py @@ -4,6 +4,7 @@ import cv2 import numpy as np import open3d as o3d +from scipy.spatial.transform import Rotation import spatialmp4 as sm ''' @@ -15,25 +16,38 @@ ''' -def pico_pose_to_open3d(extrinsic): - convert = np.array([ - [0, 0, 1, 0], - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 0, 1] - ]) +def pico_pose_to_open3d(extrinsic, depth_only=False): + if depth_only: + convert = np.array([ + [1, 0, 0, 0], + [0, 0, -1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) + else: + convert = np.array([ + [0, 0, 1, 0], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) output = convert @ extrinsic return output def main( video_file: str, + depth_only: bool = False, topk: int = None, + save_pcd: str = None, ): """Generate pcd file from spatialmp4, using TSDF in open3d. """ reader = sm.Reader(video_file) - reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) + if depth_only: + reader.set_read_mode(sm.ReadMode.DEPTH_ONLY) + else: + reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) if not reader.has_depth(): typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) @@ -45,16 +59,29 @@ def main( positions = [] frames = [] + if depth_only: + width = reader.get_depth_width() + height = reader.get_depth_height() + fx = float(reader.get_depth_intrinsics().fx) + fy = float(reader.get_depth_intrinsics().fy) + cx = float(reader.get_depth_intrinsics().cx) + cy = float(reader.get_depth_intrinsics().cy) + else: + width = reader.get_rgb_width() + height = reader.get_rgb_height() + fx = float(reader.get_rgb_intrinsics_left().fx) + fy = float(reader.get_rgb_intrinsics_left().fy) + cx = float(reader.get_rgb_intrinsics_left().cx) + cy = float(reader.get_rgb_intrinsics_left().cy) + intrinsic = o3d.camera.PinholeCameraIntrinsic() - width = reader.get_rgb_width() - height = reader.get_rgb_height() intrinsic.set_intrinsics( width=width, height=height, - fx=float(reader.get_rgb_intrinsics_left().fx), - fy=float(reader.get_rgb_intrinsics_left().fy), - cx=float(reader.get_rgb_intrinsics_left().cx), - cy=float(reader.get_rgb_intrinsics_left().cy) + fx=fx, + fy=fy, + cx=cx, + cy=cy ) intrinsic_o3d = o3d.camera.PinholeCameraIntrinsic( width=height, @@ -66,13 +93,27 @@ def main( ) while reader.has_next(): - rgbd = reader.load_rgbd(True) + if depth_only: + depth_frame = reader.load_depth() + timestamp = depth_frame.timestamp + depth_np = depth_frame.depth + TWH = depth_frame.pose # T_W_H + if TWH.timestamp == 0: + continue # invalid pose data + extrinsic = np.eye(4) + extrinsic[:3, 3] = [TWH.x, TWH.y, TWH.z] + extrinsic[:3, :3] = Rotation.from_quat((TWH.qx, TWH.qy, TWH.qz, TWH.qw)).as_matrix() + fake_rgb = np.zeros((height, width, 3), dtype=np.uint8) + else: + rgbd = reader.load_rgbd(True) + timestamp = rgbd.timestamp + depth_np = rgbd.depth + extrinsic = rgbd.T_W_S if topk is not None and reader.get_index() >= topk: break - print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") + print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {timestamp}") # preprocess on depthmap - depth_np = rgbd.depth depth_uint16 = (depth_np * 1000).astype(np.uint16) sobelx = cv2.Sobel(depth_uint16, cv2.CV_32F, 1, 0, ksize=3) sobely = cv2.Sobel(depth_uint16, cv2.CV_32F, 0, 1, ksize=3) @@ -80,20 +121,20 @@ def main( depth_np[grad_mag > 500] = 0 depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 - extrinsic = rgbd.T_W_S - extrinsic = pico_pose_to_open3d(extrinsic) + extrinsic = pico_pose_to_open3d(extrinsic, depth_only) rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( - o3d.geometry.Image(rgbd.rgb), + o3d.geometry.Image(fake_rgb if depth_only else rgbd.rgb), o3d.geometry.Image(depth_np), depth_scale=1.0, depth_trunc=5.0, - convert_rgb_to_intensity=True + convert_rgb_to_intensity=False ) pcd_i = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic) pcd_i.transform(np.linalg.inv(extrinsic)) - pcd_i.paint_uniform_color([0, 0, 1]) + if depth_only: + pcd_i.paint_uniform_color([1, 0, 0]) frames.append(pcd_i) origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1.0, origin=[0, 0, 0]) @@ -103,6 +144,13 @@ def main( vis.add_geometry(origin) vis.add_geometry(frames[idx]) + if save_pcd: + for i in range(len(frames)): + os.makedirs(save_pcd, exist_ok=True) + savename = os.path.join(save_pcd, f"{i:04d}.ply") + o3d.io.write_point_cloud(savename, frames[i]) + print(f"saved to {save_pcd}") + def save_view_control(vis): vc = vis.get_view_control() params = vc.convert_to_pinhole_camera_parameters() diff --git a/examples/python/visualize_rerun.py b/examples/python/visualize_rerun.py index 7dd56fd..fbae9a0 100644 --- a/examples/python/visualize_rerun.py +++ b/examples/python/visualize_rerun.py @@ -21,10 +21,15 @@ def pico_pose_to_open3d(extrinsic): def main( video_file: str, + depth_only: bool = False, ): """Visualize spatialmp4 using rerun.""" reader = sm.Reader(video_file) - reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) + + if depth_only: + reader.set_read_mode(sm.ReadMode.DEPTH_ONLY) + else: + reader.set_read_mode(sm.ReadMode.DEPTH_FIRST) if not reader.has_depth(): typer.echo(typer.style(f"No depth found in input file", fg=typer.colors.RED)) @@ -59,18 +64,41 @@ def main( rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) # same as open3d view_coord = rr.ViewCoordinates.UBR - width = reader.get_rgb_width() - height = reader.get_rgb_height() - fx = float(reader.get_rgb_intrinsics_left().fx) - fy = float(reader.get_rgb_intrinsics_left().fy) - cx = float(reader.get_rgb_intrinsics_left().cx) - cy = float(reader.get_rgb_intrinsics_left().cy) + + if depth_only: + width = reader.get_depth_width() + height = reader.get_depth_height() + fx = float(reader.get_depth_intrinsics().fx) + fy = float(reader.get_depth_intrinsics().fy) + cx = float(reader.get_depth_intrinsics().cx) + cy = float(reader.get_depth_intrinsics().cy) + else: + width = reader.get_rgb_width() + height = reader.get_rgb_height() + fx = float(reader.get_rgb_intrinsics_left().fx) + fy = float(reader.get_rgb_intrinsics_left().fy) + cx = float(reader.get_rgb_intrinsics_left().cx) + cy = float(reader.get_rgb_intrinsics_left().cy) + while reader.has_next(): - rgbd = reader.load_rgbd(True) - print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {rgbd.timestamp}") + if depth_only: + depth_frame = reader.load_depth() + timestamp = depth_frame.timestamp + depth_np = depth_frame.depth + TWH = depth_frame.pose # T_W_H + if TWH.timestamp == 0: + continue # invalid pose data + extrinsic = np.eye(4) + extrinsic[:3, 3] = [TWH.x, TWH.y, TWH.z] + extrinsic[:3, :3] = Rotation.from_quat((TWH.qx, TWH.qy, TWH.qz, TWH.qw)).as_matrix() + else: + rgbd = reader.load_rgbd(True) + timestamp = rgbd.timestamp + depth_np = rgbd.depth + extrinsic = rgbd.T_W_S + print(f"Loading frame {reader.get_index() + 1} / {reader.get_frame_count()}, timestamp: {timestamp}") # preprocess on depthmap - depth_np = rgbd.depth depth_uint16 = (depth_np * 1000).astype(np.uint16) sobelx = cv2.Sobel(depth_uint16, cv2.CV_32F, 1, 0, ksize=3) sobely = cv2.Sobel(depth_uint16, cv2.CV_32F, 0, 1, ksize=3) @@ -78,10 +106,9 @@ def main( depth_np[grad_mag > 500] = 0 depth_np[(depth_np < 0.2) | (depth_np > 5)] = 0 - extrinsic = rgbd.T_W_S extrinsic = pico_pose_to_open3d(extrinsic) - rr.set_time_seconds("time", rgbd.timestamp) + rr.set_time_seconds("time", timestamp) rr.log("world/xyz", rr.Arrows3D(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]])) rr.log("world/camera/image", rr.Pinhole( resolution=[width, height], @@ -92,8 +119,9 @@ def main( position = extrinsic[:3, 3] rotation = Rotation.from_matrix(extrinsic[:3, :3]).as_quat() rr.log("world/camera", rr.Transform3D(translation=position, rotation=rr.Quaternion(xyzw=rotation))) - rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) rr.log("world/camera/image/depth", rr.DepthImage(depth_np, meter=1.0)) + if not depth_only: + rr.log("world/camera/image/rgb", rr.Image(rgbd.rgb, color_model="BGR").compress(jpeg_quality=95)) if __name__ == "__main__":# diff --git a/python/tests/test_reader.py b/python/tests/test_reader.py index d85b6ca..9cf0921 100644 --- a/python/tests/test_reader.py +++ b/python/tests/test_reader.py @@ -4,6 +4,7 @@ def test_version(): print(spatialmp4.__version__) + def test_reader(): reader = spatialmp4.Reader("video/test.mp4") @@ -46,4 +47,4 @@ def test_reader(): # Access depth data (returns numpy array) depth = depth_frame.depth # Shape: (height, width) - print(f"Depth: {depth.shape}") \ No newline at end of file + print(f"Depth: {depth.shape}") diff --git a/src/spatialmp4/reader.cc b/src/spatialmp4/reader.cc index c159e9e..86b481c 100644 --- a/src/spatialmp4/reader.cc +++ b/src/spatialmp4/reader.cc @@ -538,7 +538,7 @@ void Reader::Load(rgb_frame& frame_rgb, depth_frame& frame_depth) { av_packet_unref(¤t_packet_); continue; } - ParseDepthFrame(current_packet_, frame_depth); + ParseDepthFrame(current_packet_, frame_depth, true); keyframe_depth_idx_++; break; } @@ -627,7 +627,7 @@ void Reader::Load(rgb_frame& frame_rgb) { } } -void Reader::Load(depth_frame& frame_depth) { +void Reader::Load(depth_frame& frame_depth, bool raw_head_pose) { if (pFormatCtx_ == NULL) { std::cerr << "pFormatCtx_ is NULL" << std::endl; return; @@ -642,7 +642,7 @@ void Reader::Load(depth_frame& frame_depth) { } while (av_read_frame(pFormatCtx_, ¤t_packet_) >= 0) { if (current_packet_.stream_index == depth_frame_id_) { - ParseDepthFrame(current_packet_, frame_depth); + ParseDepthFrame(current_packet_, frame_depth, raw_head_pose); keyframe_depth_idx_++; break; } @@ -690,9 +690,6 @@ void Reader::Load(Utilities::Rgbd& rgbd, bool densify) { if (densify) { // densify depth by nearest neighbor interpolation float scale = frame_rgb.left_rgb.cols / frame_depth.depth.cols; - std::cout << "frame_rgb.left_rgb.cols: " << frame_rgb.left_rgb.cols << std::endl; - std::cout << "frame_depth.depth.cols: " << frame_depth.depth.cols << std::endl; - std::cout << "scale: " << scale << std::endl; cv::resize(frame_depth.depth, frame_depth.depth, cv::Size(frame_rgb.left_rgb.cols, frame_rgb.left_rgb.rows), cv::INTER_NEAREST); K_tof = GetDepthIntrinsics().as_cvmat(); @@ -704,8 +701,11 @@ void Reader::Load(Utilities::Rgbd& rgbd, bool densify) { Utilities::ProjectDepthToRgb(frame_depth.depth, frame_rgb.left_rgb, GetRgbIntrinsicsLeft().as_cvmat(), K_tof, T_Srgb_Stof, projected_depth, true); - - rgbd = Utilities::Rgbd(frame_rgb.left_rgb, projected_depth, frame_depth.timestamp, T_W_Stof); + // timestamp is the time of depth frame + // T_W_Srgb is the transform from world to rgb sensor + rgbd = Utilities::Rgbd(frame_rgb.left_rgb, projected_depth, frame_depth.timestamp, T_W_Srgb); + // Why it is bad with T_W_Srgb? + // rgbd = Utilities::Rgbd(frame_rgb.left_rgb, projected_depth, frame_depth.timestamp, T_W_Stof); } void Reader::LoadAllPoseData(int frame_id) { @@ -731,7 +731,7 @@ void Reader::LoadAllPoseData(int frame_id) { av_seek_frame(pFormatCtx_, -1, 0, AVSEEK_FLAG_BACKWARD); } -void Reader::ParseDepthFrame(const AVPacket& pkt, depth_frame& frame_depth) { +void Reader::ParseDepthFrame(const AVPacket& pkt, depth_frame& frame_depth, bool raw_head_pose) { frame_depth.timestamp = pkt.pts * av_q2d(pFormatCtx_->streams[depth_frame_id_]->time_base); frame_depth.depth = cv::Mat(depth_height_, depth_width_, CV_16UC1, pkt.data); frame_depth.depth.convertTo(frame_depth.depth, CV_32FC1, 0.001); // unit: meter @@ -739,10 +739,40 @@ void Reader::ParseDepthFrame(const AVPacket& pkt, depth_frame& frame_depth) { double time_diff; pose_frames_.findNearestPose(frame_depth.timestamp, target_pose, time_diff); frame_depth.pose = target_pose; - if (time_diff <= find_pose_distance_) { + + bool pose_is_valid = false; + if (time_diff <= find_pose_distance_ || IsLastFrame()) { frame_depth.pose = target_pose; + pose_is_valid = true; } else { frame_depth.pose = pose_frame(); + pose_is_valid = false; + } + if (!raw_head_pose && pose_is_valid) { + // Read head_model_offset from /system/etc/pvr/config/config_head.txt#line_1 + auto head_model_offset = Eigen::Vector3d(-0.05057, -0.01874, 0.04309); + // convert T_W_Htof to T_W_Stof + // Note: + // W: World + // H: Head + // S: Sensor, rgb sensor or depth sensor + // I: IMU + auto T_W_Htof = frame_depth.pose.as_se3(); + auto T_I_Stof = GetDepthExtrinsics().as_se3(); + + Sophus::SE3d T_W_Itof; + Utilities::HeadToImu(T_W_Htof, head_model_offset, T_W_Itof); + auto T_W_Stof = T_W_Itof * T_I_Stof; + + Eigen::Vector3d t = T_W_Stof.translation(); + Eigen::Quaterniond q = T_W_Stof.unit_quaternion(); + frame_depth.pose.x = t.x(); + frame_depth.pose.y = t.z(); + frame_depth.pose.z = t.z(); + frame_depth.pose.qx = q.x(); + frame_depth.pose.qy = q.y(); + frame_depth.pose.qz = q.z(); + frame_depth.pose.qw = q.w(); } } @@ -767,7 +797,7 @@ void Reader::ParseRgbFrame(const AVPacket& pkt, rgb_frame& frame_rgb, bool skip) pose_frame target_pose; double time_diff; pose_frames_.findNearestPose(frame_rgb.timestamp, target_pose, time_diff); - if (time_diff <= find_pose_distance_) { + if (time_diff <= find_pose_distance_ || IsLastFrame()) { frame_rgb.pose = target_pose; } else { frame_rgb.pose = pose_frame(); @@ -790,4 +820,9 @@ bool Reader::SeekToRgbKeyframe(int64_t target_pts) { return true; } +bool Reader::IsLastFrame() { + std::cout << "GetIndex: " << GetIndex() << ", GetFrameCount: " << GetFrameCount() << std::endl; + return GetIndex() == GetFrameCount() - 1; +} + } // namespace SpatialML diff --git a/src/spatialmp4/reader.h b/src/spatialmp4/reader.h index 304f2f4..1cdc884 100644 --- a/src/spatialmp4/reader.h +++ b/src/spatialmp4/reader.h @@ -18,9 +18,9 @@ // 导出宏定义 #if defined(_WIN32) -# define SPATIALMP4_EXPORT __declspec(dllexport) +#define SPATIALMP4_EXPORT __declspec(dllexport) #else -# define SPATIALMP4_EXPORT __attribute__((visibility("default"))) +#define SPATIALMP4_EXPORT __attribute__((visibility("default"))) #endif #include @@ -140,7 +140,7 @@ class SPATIALMP4_EXPORT Reader { void SetReadMode(ReadMode mode) { read_mode_ = mode; } bool HasNext() const; void Load(rgb_frame& rgb_frame); - void Load(depth_frame& depth_frame); + void Load(depth_frame& depth_frame, bool raw_head_pose = false); void Load(rgb_frame& rgb_frame, depth_frame& depth_frame); void Load(Utilities::Rgbd& rgbd, bool densify = false); void Reset(); @@ -149,10 +149,11 @@ class SPATIALMP4_EXPORT Reader { protected: void LoadAllPoseData(int frame_id); - void ParseDepthFrame(const AVPacket& pkt, depth_frame& depth_frame); + void ParseDepthFrame(const AVPacket& pkt, depth_frame& depth_frame, bool raw_head_pose = false); void ParseRgbFrame(const AVPacket& pkt, rgb_frame& rgb_frame, bool skip = false); bool SeekToRgbKeyframe(int64_t timestamp); + bool IsLastFrame(); private: std::string filename_; From e67637f5bd6e1a9f30d8bf5516a9a45a66e7ed66 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 15 Jul 2025 19:38:57 +0800 Subject: [PATCH 28/31] update doc --- README.md | 6 +- README_zh.md | 156 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 147 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d3b25a3..5d726b5 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ bash scripts/install_deps.sh ### 4. Build and Install ```bash -pip3 instsall . +pip3 install . ``` ## 📖 Usage Guide (cpp) @@ -317,7 +317,7 @@ struct pose_frame { }; ``` -## 📖 Usage Guide (cpp) +## 📖 Usage Guide (python) ### Basic Usage Example @@ -430,7 +430,7 @@ Main class for reading SpatialMP4 files. ### Advanced Usage -- See `examples/python/visualize_rerun.py` and `examples/python/generate_pcd.py` for advanced usage, including point cloud generation and visualization with Open3D or Rerun. +- See [examples/python/visualize_rerun.py](./examples/python/visualize_rerun.py) and [examples/python/generate_pcd.py](./examples/python/generate_pcd.py) for advanced usage, including point cloud generation and visualization with Open3D or Rerun. - All image and depth data are returned as NumPy arrays for easy integration with OpenCV, Open3D, PyTorch, etc. - Camera parameters and pose data can be used for 3D reconstruction and SLAM applications. diff --git a/README_zh.md b/README_zh.md index c32da7b..3fcbb6a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -36,7 +36,7 @@ - [**fmt**](https://github.com/fmtlib/fmt): 现代C++格式化库 - [**Google Test**](https://github.com/google/googletest): 单元测试框架 (可选) -## 🛠️ 编译安装 +## 🛠️ 编译安装 (cpp) ### 1. 克隆仓库 @@ -87,6 +87,35 @@ cd .. ./build/test_reader ``` +## 🛠️ 编译安装 (python) + +### 1. 克隆代码 + +```bash +git clone https://github.com/Pico-Developer/SpatialMP4 +cd SpatialMP4 +``` + +### 2. 编译FFmpeg + +Build `ffmpeg` first: + +```bash +bash scripts/build_ffmpeg.sh +``` + +### 3. 安装依赖 + +```bash +bash scripts/install_deps.sh +``` + +### 4. 构建安装 + +```bash +pip3 install . +``` + ## 📖 使用指南 ### 基本用法 @@ -286,20 +315,123 @@ struct pose_frame { }; ``` -## 🔍 工具函数 +## 📖 使用指南 (python) + +### 基本用法示例 + +```python +import spatialmp4 + +# 创建读取器 +reader = spatialmp4.Reader("your_video.mp4") -### 图像处理 (OpencvUtils) -- `VisualizeMat()`: 可视化矩阵数据 -- `DumpMat()` / `LoadMat()`: 保存/加载矩阵 -- `ConcatenateMat()`: 拼接多个图像 +# 检查可用流 +print("Has RGB:", reader.has_rgb()) +print("Has Depth:", reader.has_depth()) +print("Has Pose:", reader.has_pose()) + +# 设置读取模式 +reader.set_read_mode(spatialmp4.ReadMode.DEPTH_FIRST) + +# 读取帧 +while reader.has_next(): + rgb_frame, depth_frame = reader.load_both() + left_rgb = rgb_frame.left_rgb # numpy数组 (H, W, 3) + depth = depth_frame.depth # numpy数组 (H, W) + pose = rgb_frame.pose + print("RGB时间戳:", rgb_frame.timestamp, "位姿:", pose.x, pose.y, pose.z) +``` -### RGBD处理 (RgbdUtils) -- `ProjectDepthToRgb()`: 深度投影到RGB -- `RgbdToPointcloud()`: RGBD转点云 +--- + +## 📚 API 参考 (python) + +### 主要类与方法 + +#### `spatialmp4.Reader` +SpatialMP4 文件读取主类。 + +- `Reader(filename: str)` — 创建读取器。 +- `has_rgb() -> bool` — 是否包含RGB数据。 +- `has_depth() -> bool` — 是否包含深度数据。 +- `has_pose() -> bool` — 是否包含位姿数据。 +- `has_audio() -> bool` — 是否包含音频数据。 +- `has_disparity() -> bool` — 是否包含视差数据。 +- `get_duration() -> float` — 获取视频时长(秒)。 +- `get_rgb_fps() -> float` — 获取RGB帧率。 +- `get_depth_fps() -> float` — 获取深度帧率。 +- `get_rgb_width() -> int` — 获取RGB宽度。 +- `get_rgb_height() -> int` — 获取RGB高度。 +- `get_depth_width() -> int` — 获取深度宽度。 +- `get_depth_height() -> int` — 获取深度高度。 +- `get_rgb_intrinsics_left() -> CameraIntrinsics` — 获取左RGB相机内参。 +- `get_rgb_intrinsics_right() -> CameraIntrinsics` — 获取右RGB相机内参。 +- `get_rgb_extrinsics_left() -> CameraExtrinsics` — 获取左RGB相机外参。 +- `get_rgb_extrinsics_right() -> CameraExtrinsics` — 获取右RGB相机外参。 +- `get_depth_intrinsics() -> CameraIntrinsics` — 获取深度相机内参。 +- `get_depth_extrinsics() -> CameraExtrinsics` — 获取深度相机外参。 +- `get_pose_frames() -> List[PoseFrame]` — 获取所有位姿帧。 +- `set_read_mode(mode: ReadMode)` — 设置读取模式(见下方枚举)。 +- `has_next() -> bool` — 是否有下一帧。 +- `reset()` — 重置到文件开头。 +- `get_index() -> int` — 获取当前帧索引。 +- `get_frame_count() -> int` — 获取总帧数。 +- `load_rgb() -> RGBFrame` — 读取下一个RGB帧。 +- `load_depth(raw_head_pose: bool = False) -> DepthFrame` — 读取下一个深度帧。 +- `load_both() -> (RGBFrame, DepthFrame)` — 同时读取下一个RGB和深度帧。 +- `load_rgbd(densify: bool = False) -> Rgbd` — 读取RGBD数据(高级用法)。 + +#### `spatialmp4.RGBFrame` +- `timestamp: float` — 帧时间戳。 +- `left_rgb: np.ndarray` — 左RGB图像 (H, W, 3, uint8)。 +- `right_rgb: np.ndarray` — 右RGB图像 (H, W, 3, uint8)。 +- `pose: PoseFrame` — 对应位姿数据。 + +#### `spatialmp4.DepthFrame` +- `timestamp: float` — 帧时间戳。 +- `depth: np.ndarray` — 深度图像 (H, W, float32, 单位米)。 +- `pose: PoseFrame` — 对应位姿数据。 + +#### `spatialmp4.PoseFrame` +- `timestamp: float` — 位姿时间戳。 +- `x, y, z: float` — 位置。 +- `qw, qx, qy, qz: float` — 四元数旋转。 +- `as_se3()` — 转换为SE(3)表示(需Sophus/Eigen,高级用法)。 + +#### `spatialmp4.CameraIntrinsics` +- `fx, fy, cx, cy: float` — 相机内参。 +- `as_cvmat()` — 以OpenCV矩阵返回。 + +#### `spatialmp4.CameraExtrinsics` +- `extrinsics: np.ndarray` — 4x4外参矩阵。 +- `as_cvmat()` — 以OpenCV矩阵返回。 +- `as_se3()` — 以SE(3)返回(高级用法)。 + +--- + +### 枚举类型 + +#### `spatialmp4.ReadMode` +- `RGB_ONLY` — 仅读取RGB帧。 +- `DEPTH_ONLY` — 仅读取深度帧。 +- `DEPTH_FIRST` — 同时读取RGB和深度帧,以深度为参考。 + +#### `spatialmp4.StreamType` +- `UNKNOWN` — 未知流类型 +- `AUDIO` — 音频流 +- `AUDIO_2` — 第二音频流 +- `RGB` — RGB视频流 +- `DISPARITY` — 视差流 +- `POSE` — 位姿数据流 +- `DEPTH` — 深度流 + + +### 高级用法 + +- 参见 [examples/python/visualize_rerun.py](./examples/python/visualize_rerun.py) 和 [examples/python/generate_pcd.py](./examples/python/generate_pcd.py) 获取点云生成、Open3D/Rerun可视化等高级用法。 +- 所有图像和深度数据均以NumPy数组返回,便于与OpenCV、Open3D、PyTorch等生态集成。 +- 相机参数和位姿数据可用于三维重建和SLAM等应用。 -### 点云处理 (PointcloudUtils) -- `SavePointcloudToFile()`: 保存点云文件 -- 支持OBJ格式输出 ## 🐛 调试和日志 From 8092e8acbaa439e0095c5d579a052fc1bf7f6c7d Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 15 Jul 2025 19:41:57 +0800 Subject: [PATCH 29/31] update doc --- README.md | 4 ---- README_zh.md | 3 --- 2 files changed, 7 deletions(-) diff --git a/README.md b/README.md index 5d726b5..e71671c 100644 --- a/README.md +++ b/README.md @@ -408,7 +408,6 @@ Main class for reading SpatialMP4 files. - `as_cvmat()` — Return as OpenCV matrix. - `as_se3()` — Return as SE(3) (advanced use). ---- ### Enums @@ -426,7 +425,6 @@ Main class for reading SpatialMP4 files. - `POSE` — Pose data stream - `DEPTH` — Depth stream ---- ### Advanced Usage @@ -434,8 +432,6 @@ Main class for reading SpatialMP4 files. - All image and depth data are returned as NumPy arrays for easy integration with OpenCV, Open3D, PyTorch, etc. - Camera parameters and pose data can be used for 3D reconstruction and SLAM applications. ---- - ## 🐛 Debugging and Logging diff --git a/README_zh.md b/README_zh.md index 3fcbb6a..8478461 100644 --- a/README_zh.md +++ b/README_zh.md @@ -342,7 +342,6 @@ while reader.has_next(): print("RGB时间戳:", rgb_frame.timestamp, "位姿:", pose.x, pose.y, pose.z) ``` ---- ## 📚 API 参考 (python) @@ -407,8 +406,6 @@ SpatialMP4 文件读取主类。 - `as_cvmat()` — 以OpenCV矩阵返回。 - `as_se3()` — 以SE(3)返回(高级用法)。 ---- - ### 枚举类型 #### `spatialmp4.ReadMode` From c191bc94c670702e762d6e2adfcf7ba15dbe56d8 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 15 Jul 2025 19:50:31 +0800 Subject: [PATCH 30/31] update doc --- README.md | 4 ++-- README_zh.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e71671c..4a2878f 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ bash scripts/install_deps.sh mkdir build && cd build # Configure project -cmake .. -DCMAKE_BUILD_TYPE=Release +cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON=OFF # Build make -j$(nproc) # On Linux @@ -456,4 +456,4 @@ Issues and Pull Requests are welcome to improve this project! ## 📞 Contact -For questions or suggestions, please contact us through GitHub Issues. \ No newline at end of file +For questions or suggestions, please contact us through GitHub Issues. diff --git a/README_zh.md b/README_zh.md index 8478461..0f6f870 100644 --- a/README_zh.md +++ b/README_zh.md @@ -65,7 +65,7 @@ bash scripts/install_deps.sh mkdir build && cd build # 配置项目 -cmake .. -DCMAKE_BUILD_TYPE=Release +cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON=OFF # 编译 make -j$(nproc) # Linux系统 From 2f10911b145a273741ff53cf1578f5ba4d7f9109 Mon Sep 17 00:00:00 2001 From: duinodu <472365351duino@gmail.com> Date: Tue, 15 Jul 2025 19:55:45 +0800 Subject: [PATCH 31/31] update doc --- cmake/eigen.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/eigen.cmake b/cmake/eigen.cmake index 8c66996..638f242 100644 --- a/cmake/eigen.cmake +++ b/cmake/eigen.cmake @@ -3,7 +3,6 @@ FetchContent_Declare( eigen # URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz - # URL /Users/bytedance/Downloads/eigen-3.3.7.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP true )