pax_global_header00006660000000000000000000000064146474556650014540gustar00rootroot0000000000000052 comment=0bd66d901c7549051e21e8f648777f802eb20a73 colmap-3.10/000077500000000000000000000000001464745566500127365ustar00rootroot00000000000000colmap-3.10/.clang-format000077500000000000000000000005661464745566500153230ustar00rootroot00000000000000BasedOnStyle: Google BinPackArguments: false BinPackParameters: false DerivePointerAlignment: false IncludeBlocks: Regroup IncludeCategories: - Regex: '^"colmap' Priority: 1 - Regex: '^"pycolmap' Priority: 2 - Regex: '^"thirdparty' Priority: 3 - Regex: '^<[[:alnum:]_]+>' Priority: 4 - Regex: '.*' Priority: 5 SortIncludes: true colmap-3.10/.clang-tidy000066400000000000000000000010501464745566500147660ustar00rootroot00000000000000Checks: > performance-*, concurrency-*, bugprone-*, -bugprone-easily-swappable-parameters, -bugprone-exception-escape, -bugprone-implicit-widening-of-multiplication-result, -bugprone-narrowing-conversions, -bugprone-reserved-identifier, -bugprone-unchecked-optional-access, cppcoreguidelines-virtual-class-destructor, google-explicit-constructor, google-build-using-namespace, readability-avoid-const-params-in-decls, clang-analyzer-core*, clang-analyzer-cplusplus*, WarningsAsErrors: '*' FormatStyle: 'file' User: 'user' colmap-3.10/.github/000077500000000000000000000000001464745566500142765ustar00rootroot00000000000000colmap-3.10/.github/ISSUE_TEMPLATE/000077500000000000000000000000001464745566500164615ustar00rootroot00000000000000colmap-3.10/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000011531464745566500211530ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. Input images and/or output reconstructions are usually helpful. **Environment:** - OS: [e.g. Windows 11] - COLMAP Version [e.g. 3.8 or git commit hash] - Capture Device [e.g. iPhone X] colmap-3.10/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000010601464745566500222030ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. colmap-3.10/.github/workflows/000077500000000000000000000000001464745566500163335ustar00rootroot00000000000000colmap-3.10/.github/workflows/build-docker.yml000066400000000000000000000027221464745566500214250ustar00rootroot00000000000000name: COLMAP (Docker) on: push: branches: - main pull_request: types: [ assigned, opened, synchronize, reopened ] release: types: [ published, edited ] env: IS_RELEASE: ${{ github.event_name == 'release' || startsWith(github.ref, 'refs/tags') }} jobs: build: name: ubuntu-22.04 runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub if: ${{ env.IS_RELEASE == 'true' }} uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push run: | dockertag=$(date +%Y%m%d).${{ github.run_number }} if [[ "${{ env.IS_RELEASE }}" == "true" ]]; then cuda_archs="50;60;70;75;90" else cuda_archs="50" fi docker build . \ --file docker/Dockerfile \ --tag colmap/colmap:$dockertag \ --build-arg COLMAP_GIT_COMMIT="$GITHUB_SHA" \ --build-arg CUDA_ARCHITECTURES="$cuda_archs" if [[ "${{ env.IS_RELEASE }}" == "true" ]]; then docker tag colmap/colmap:$dockertag colmap/colmap:latest docker push colmap/colmap:$dockertag docker push colmap/colmap:latest fi colmap-3.10/.github/workflows/build-mac.yml000066400000000000000000000046771464745566500207310ustar00rootroot00000000000000name: COLMAP (Mac) on: push: branches: - main pull_request: types: [ assigned, opened, synchronize, reopened ] release: types: [ published, edited ] jobs: build: name: ${{ matrix.config.os }} ${{ matrix.config.arch }} ${{ matrix.config.cmakeBuildType }} runs-on: ${{ matrix.config.os }} strategy: matrix: config: [ { os: macos-14, arch: arm64, cmakeBuildType: Release, }, ] env: COMPILER_CACHE_VERSION: 1 COMPILER_CACHE_DIR: ${{ github.workspace }}/compiler-cache CCACHE_DIR: ${{ github.workspace }}/compiler-cache/ccache CCACHE_BASEDIR: ${{ github.workspace }} steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 id: cache-builds with: key: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.arch }}-${{ matrix.config.cmakeBuildType }}-${{ github.run_id }}-${{ github.run_number }} restore-keys: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.arch }}-${{ matrix.config.cmakeBuildType }} path: ${{ env.COMPILER_CACHE_DIR }} - name: Setup Mac run: | # Fix `brew link` error. find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete brew install \ cmake \ ninja \ boost \ eigen \ flann \ freeimage \ metis \ glog \ googletest \ ceres-solver \ qt5 \ glew \ cgal \ sqlite3 \ ccache - name: Configure and build run: | export PATH="/usr/local/opt/qt@5/bin:$PATH" cmake --version mkdir build cd build cmake .. \ -GNinja \ -DCMAKE_BUILD_TYPE=${{ matrix.config.cmakeBuildType }} \ -DTESTS_ENABLED=ON \ -DCMAKE_PREFIX_PATH="/opt/homebrew/opt/flann;/opt/homebrew/opt/metis;/opt/homebrew/opt/suite-sparse;/opt/homebrew/opt/qt@5;/opt/homebrew/opt/freeimage" ninja - name: Run tests run: | cd build set +e ctest --output-on-failure - name: Cleanup compiler cache run: | set -x ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose colmap-3.10/.github/workflows/build-pycolmap.yml000066400000000000000000000175671464745566500220170ustar00rootroot00000000000000name: PyCOLMAP on: push: branches: - main pull_request: types: [ assigned, opened, synchronize, reopened ] release: types: [ published, edited ] jobs: build: name: ${{ matrix.config.os }} ${{ matrix.config.arch }} runs-on: ${{ matrix.config.os }} strategy: matrix: config: [ {os: ubuntu-latest}, {os: macos-14, arch: x86_64}, {os: macos-14, arch: arm64}, {os: windows-latest}, ] env: COMPILER_CACHE_VERSION: 1 COMPILER_CACHE_DIR: ${{ github.workspace }}/compiler-cache CCACHE_DIR: ${{ github.workspace }}/compiler-cache/ccache CCACHE_BASEDIR: ${{ github.workspace }} MACOSX_DEPLOYMENT_TARGET: 10.12 steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 id: cache-builds with: key: pycolmap-v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.arch }}-${{ github.run_id }}-${{ github.run_number }} restore-keys: pycolmap-v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.arch }} path: ${{ env.COMPILER_CACHE_DIR }} - name: Set env (macOS) if: runner.os == 'macOS' run: | if [[ ${{ matrix.config.arch }} == "x86_64" ]]; then VCPKG_TARGET_TRIPLET="x64-osx-release" elif [[ ${{ matrix.config.arch }} == "arm64" ]]; then VCPKG_TARGET_TRIPLET="arm64-osx-release" else exit 1 fi echo "VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" >> "$GITHUB_ENV" VCPKG_INSTALLATION_ROOT="/Users/runner/work/vcpkg" CMAKE_TOOLCHAIN_FILE="${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" CMAKE_OSX_ARCHITECTURES=${{ matrix.config.arch }} echo "VCPKG_INSTALLATION_ROOT=${VCPKG_INSTALLATION_ROOT}" >> "$GITHUB_ENV" echo "CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" >> "$GITHUB_ENV" echo "CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}" >> "$GITHUB_ENV" # Fix: cibuildhweel cannot interpolate env variables. CONFIG_SETTINGS="cmake.define.CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" CONFIG_SETTINGS="${CONFIG_SETTINGS} cmake.define.VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" CONFIG_SETTINGS="${CONFIG_SETTINGS} cmake.define.VCPKG_INSTALLED_DIR=${{ github.workspace }}/build/vcpkg_installed" CONFIG_SETTINGS="${CONFIG_SETTINGS} cmake.define.CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}" echo "CIBW_CONFIG_SETTINGS_MACOS=${CONFIG_SETTINGS}" >> "$GITHUB_ENV" # vcpkg binary caching VCPKG_CACHE_DIR="${COMPILER_CACHE_DIR}/vcpkg" VCPKG_BINARY_SOURCES="clear;files,${VCPKG_CACHE_DIR},readwrite" echo "VCPKG_BINARY_SOURCES=${VCPKG_BINARY_SOURCES}" >> "$GITHUB_ENV" - name: Set env (Windows) if: runner.os == 'Windows' shell: pwsh run: | $VCPKG_INSTALLATION_ROOT = "${{ github.workspace }}/vcpkg" echo "VCPKG_INSTALLATION_ROOT=${VCPKG_INSTALLATION_ROOT}" >> "${env:GITHUB_ENV}" $CMAKE_TOOLCHAIN_FILE = "${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" echo "CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" >> "${env:GITHUB_ENV}" $VCPKG_TARGET_TRIPLET = "x64-windows-release" echo "VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" >> "${env:GITHUB_ENV}" # Fix: cibuildhweel cannot interpolate env variables. $CMAKE_TOOLCHAIN_FILE = $CMAKE_TOOLCHAIN_FILE.replace('\', '/') $VCPKG_INSTALLED_DIR = "${{ github.workspace }}/build/vcpkg_installed" $VCPKG_INSTALLED_DIR = $VCPKG_INSTALLED_DIR.replace('\', '/') $CONFIG_SETTINGS = "cmake.define.CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" $CONFIG_SETTINGS = "${CONFIG_SETTINGS} cmake.define.VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" $CONFIG_SETTINGS = "${CONFIG_SETTINGS} cmake.define.VCPKG_INSTALLED_DIR=${VCPKG_INSTALLED_DIR}" echo "CIBW_CONFIG_SETTINGS_WINDOWS=${CONFIG_SETTINGS}" >> "${env:GITHUB_ENV}" $CIBW_REPAIR_WHEEL_COMMAND = "delvewheel repair -v --add-path ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin -w {dest_dir} {wheel}" echo "CIBW_REPAIR_WHEEL_COMMAND_WINDOWS=${CIBW_REPAIR_WHEEL_COMMAND}" >> "${env:GITHUB_ENV}" # vcpkg binary caching $VCPKG_CACHE_DIR = "${env:COMPILER_CACHE_DIR}/vcpkg" $VCPKG_BINARY_SOURCES = "clear;files,${VCPKG_CACHE_DIR},readwrite" echo "VCPKG_BINARY_SOURCES=${VCPKG_BINARY_SOURCES}" >> "${env:GITHUB_ENV}" - name: Set env (Linux) if: runner.os == 'Linux' run: | VCPKG_TARGET_TRIPLET="x64-linux-release" echo "VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" >> "$GITHUB_ENV" VCPKG_INSTALLATION_ROOT="${{ github.workspace }}/vcpkg" CMAKE_TOOLCHAIN_FILE="${VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" echo "VCPKG_INSTALLATION_ROOT=${VCPKG_INSTALLATION_ROOT}" >> "$GITHUB_ENV" echo "CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" >> "$GITHUB_ENV" # Fix: cibuildhweel cannot interpolate env variables. CONFIG_SETTINGS="cmake.define.CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" CONFIG_SETTINGS="${CONFIG_SETTINGS} cmake.define.VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}" CONFIG_SETTINGS="${CONFIG_SETTINGS} cmake.define.VCPKG_INSTALLED_DIR=/project/build/vcpkg_installed" echo "CIBW_CONFIG_SETTINGS_LINUX=${CONFIG_SETTINGS}" >> "$GITHUB_ENV" # Remap caching paths to the container CONTAINER_COMPILER_CACHE_DIR="/compiler-cache" CIBW_CONTAINER_ENGINE="docker; create_args: -v ${COMPILER_CACHE_DIR}:${CONTAINER_COMPILER_CACHE_DIR}" echo "CIBW_CONTAINER_ENGINE=${CIBW_CONTAINER_ENGINE}" >> "$GITHUB_ENV" echo "CONTAINER_COMPILER_CACHE_DIR=${CONTAINER_COMPILER_CACHE_DIR}" >> "$GITHUB_ENV" echo "CCACHE_DIR=${CONTAINER_COMPILER_CACHE_DIR}/ccache" >> "$GITHUB_ENV" echo "CCACHE_BASEDIR=/project" >> "$GITHUB_ENV" # vcpkg binary caching VCPKG_CACHE_DIR="${CONTAINER_COMPILER_CACHE_DIR}/vcpkg" VCPKG_BINARY_SOURCES="clear;files,${VCPKG_CACHE_DIR},readwrite" echo "VCPKG_BINARY_SOURCES=${VCPKG_BINARY_SOURCES}" >> "$GITHUB_ENV" CIBW_ENVIRONMENT_PASS_LINUX="VCPKG_TARGET_TRIPLET VCPKG_INSTALLATION_ROOT CMAKE_TOOLCHAIN_FILE VCPKG_BINARY_SOURCES CONTAINER_COMPILER_CACHE_DIR CCACHE_DIR CCACHE_BASEDIR" echo "CIBW_ENVIRONMENT_PASS_LINUX=${CIBW_ENVIRONMENT_PASS_LINUX}" >> "$GITHUB_ENV" CIBW_MANYLINUX_X86_64_IMAGE="quay.io/pypa/manylinux_2_28_x86_64" echo "CIBW_MANYLINUX_X86_64_IMAGE=${CIBW_MANYLINUX_X86_64_IMAGE}" >> "$GITHUB_ENV" - name: Build wheels uses: pypa/cibuildwheel@v2.19.2 with: package-dir: ./pycolmap/ env: CIBW_ARCHS_MACOS: ${{ matrix.config.arch }} - name: Archive wheels uses: actions/upload-artifact@v4 with: name: pycolmap-${{ matrix.config.os }}-${{ matrix.config.arch }} path: wheelhouse/pycolmap-*.whl pypi-publish: name: Publish wheels to PyPI needs: build runs-on: ubuntu-latest # We publish the wheel to pypi when a new tag is pushed, # either by creating a new GitHub release or explictly with `git tag` if: ${{ github.event_name == 'release' || startsWith(github.ref, 'refs/tags') }} steps: - name: Download wheels uses: actions/download-artifact@v4 with: path: ./artifacts/ - name: Move wheels run: mkdir ./wheelhouse && mv ./artifacts/**/*.whl ./wheelhouse/ - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 with: skip_existing: true user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} packages_dir: ./wheelhouse/ colmap-3.10/.github/workflows/build-ubuntu.yml000066400000000000000000000223671464745566500215070ustar00rootroot00000000000000name: COLMAP (Ubuntu) on: push: branches: - main pull_request: types: [ assigned, opened, synchronize, reopened ] release: types: [ published, edited ] jobs: build: name: ${{ matrix.config.os }} ${{ matrix.config.cmakeBuildType }} ${{ matrix.config.cudaEnabled && 'CUDA' || '' }} ${{ matrix.config.asanEnabled && 'ASan' || '' }} runs-on: ${{ matrix.config.os }} strategy: matrix: config: [ { os: ubuntu-22.04, cmakeBuildType: Release, asanEnabled: false, guiEnabled: true, cudaEnabled: false, e2eTests: true, checkCodeFormat: true, }, { os: ubuntu-22.04, cmakeBuildType: Release, asanEnabled: false, guiEnabled: false, cudaEnabled: true, e2eTests: false, checkCodeFormat: false, }, { os: ubuntu-22.04, cmakeBuildType: Release, asanEnabled: true, guiEnabled: false, cudaEnabled: false, e2eTests: false, checkCodeFormat: false, }, { os: ubuntu-22.04, cmakeBuildType: ClangTidy, asanEnabled: false, guiEnabled: false, cudaEnabled: false, e2eTests: false, checkCodeFormat: false, }, { os: ubuntu-20.04, cmakeBuildType: Release, asanEnabled: false, guiEnabled: true, cudaEnabled: false, e2eTests: false, checkCodeFormat: false, }, { os: ubuntu-20.04, cmakeBuildType: Release, asanEnabled: false, guiEnabled: false, cudaEnabled: true, e2eTests: false, checkCodeFormat: false, }, ] env: COMPILER_CACHE_VERSION: 1 COMPILER_CACHE_DIR: ${{ github.workspace }}/compiler-cache CCACHE_DIR: ${{ github.workspace }}/compiler-cache/ccache CCACHE_BASEDIR: ${{ github.workspace }} CTCACHE_DIR: ${{ github.workspace }}/compiler-cache/ctcache steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 id: cache-builds with: key: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }}-${{ github.run_id }}-${{ github.run_number }} restore-keys: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }} path: ${{ env.COMPILER_CACHE_DIR }} - name: Install compiler cache run: | mkdir -p "$CCACHE_DIR" "$CTCACHE_DIR" echo "$COMPILER_CACHE_DIR/bin" >> $GITHUB_PATH if [ -f "$COMPILER_CACHE_DIR/bin/ccache" ]; then exit 0 fi set -x wget https://github.com/ccache/ccache/releases/download/v4.8.2/ccache-4.8.2-linux-x86_64.tar.xz echo "0b33f39766fe9db67f40418aed6a5b3d7b2f4f7fab025a8213264b77a2d0e1b1 ccache-4.8.2-linux-x86_64.tar.xz" | sha256sum --check tar xfv ccache-4.8.2-linux-x86_64.tar.xz mkdir -p "$COMPILER_CACHE_DIR/bin" mv ./ccache-4.8.2-linux-x86_64/ccache "$COMPILER_CACHE_DIR/bin" ctcache_commit_id="66c3614175fc650591488519333c411b2eac15a3" wget https://github.com/matus-chochlik/ctcache/archive/${ctcache_commit_id}.zip echo "108b087f156a9fe7da0c796de1ef73f5855d2a33a27983769ea39061359a40fc ${ctcache_commit_id}.zip" | sha256sum --check unzip "${ctcache_commit_id}.zip" mv ctcache-${ctcache_commit_id}/clang-tidy* "$COMPILER_CACHE_DIR/bin" - name: Check code format run: | if [ "${{ matrix.config.checkCodeFormat }}" != "true" ]; then exit 0 fi set +x -euo pipefail sudo apt-get update && sudo apt-get install -y clang-format-14 black ./scripts/format/clang_format.sh ./scripts/format/black.sh git diff --name-only git diff --exit-code || (echo "Code formatting failed" && exit 1) - name: Setup Ubuntu run: | sudo apt-get update && sudo apt-get install -y \ build-essential \ cmake \ ninja-build \ libboost-program-options-dev \ libboost-filesystem-dev \ libboost-graph-dev \ libboost-system-dev \ libeigen3-dev \ libceres-dev \ libflann-dev \ libfreeimage-dev \ libmetis-dev \ libgoogle-glog-dev \ libgtest-dev \ libsqlite3-dev \ libglew-dev \ qtbase5-dev \ libqt5opengl5-dev \ libcgal-dev \ libcgal-qt5-dev \ libgl1-mesa-dri \ libunwind-dev \ xvfb if [ "${{ matrix.config.cudaEnabled }}" == "true" ]; then if [ "${{ matrix.config.os }}" == "ubuntu-20.04" ]; then sudo apt-get install -y \ nvidia-cuda-toolkit \ nvidia-cuda-toolkit-gcc echo "CC=/usr/bin/cuda-gcc" >> $GITHUB_ENV echo "CXX=/usr/bin/cuda-g++" >> $GITHUB_ENV elif [ "${{ matrix.config.os }}" == "ubuntu-22.04" ]; then sudo apt-get install -y \ nvidia-cuda-toolkit \ nvidia-cuda-toolkit-gcc \ gcc-10 g++-10 echo "CC=/usr/bin/gcc-10" >> $GITHUB_ENV echo "CXX=/usr/bin/g++-10" >> $GITHUB_ENV echo "CUDAHOSTCXX=/usr/bin/g++-10" >> $GITHUB_ENV fi fi if [ "${{ matrix.config.asanEnabled }}" == "true" ]; then sudo apt-get install -y clang-15 libomp-15-dev echo "CC=/usr/bin/clang-15" >> $GITHUB_ENV echo "CXX=/usr/bin/clang++-15" >> $GITHUB_ENV fi if [ "${{ matrix.config.cmakeBuildType }}" == "ClangTidy" ]; then sudo apt-get install -y clang-15 clang-tidy-15 libomp-15-dev echo "CC=/usr/bin/clang-15" >> $GITHUB_ENV echo "CXX=/usr/bin/clang++-15" >> $GITHUB_ENV fi - name: Configure and build run: | set -x cmake --version mkdir build cd build cmake .. \ -GNinja \ -DCMAKE_BUILD_TYPE=${{ matrix.config.cmakeBuildType }} \ -DCMAKE_INSTALL_PREFIX=./install \ -DCMAKE_CUDA_ARCHITECTURES=50 \ -DTESTS_ENABLED=ON \ -DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} \ -DGUI_ENABLED=${{ matrix.config.guiEnabled }} \ -DASAN_ENABLED=${{ matrix.config.asanEnabled }} ninja -k 10000 - name: Install and build sample run: | if [ "${{ matrix.config.asanEnabled }}" == "true" ] || [ "${{ matrix.config.cmakeBuildType }}" == "ClangTidy" ]; then exit 0 fi set -x cd build ninja install cd ../doc/sample-project mkdir build cd build export colmap_DIR=${{ github.workspace }}/build/install/share/colmap cmake .. \ -GNinja \ -DCMAKE_CUDA_ARCHITECTURES=50 ninja ./hello_world --message "world" - name: Run tests run: | if [ "${{ matrix.config.cmakeBuildType }}" == "ClangTidy" ]; then exit 0 fi if [ "${{ matrix.config.cudaEnabled }}" == "true" ]; then ctestExclusions="(feature/colmap_feature_sift_test)|(mvs/colmap_mvs_gpu_mat_test)" fi export DISPLAY=":99.0" export QT_QPA_PLATFORM="offscreen" Xvfb :99 & sleep 3 cd build ctest -E "$ctestExclusions" --output-on-failure - name: Run E2E tests run: | if [ "${{ matrix.config.e2eTests }}" != "true" ]; then exit 0 fi export DISPLAY=":99.0" export QT_QPA_PLATFORM="offscreen" Xvfb :99 & sleep 3 sudo apt install 7zip mkdir eth3d_benchmark # Error thresholds in degrees and meters, # as the ETH3D groundtruth has metric scale. GLOG_v=1 python ./scripts/python/benchmark_eth3d.py \ --workspace_path ./eth3d_benchmark \ --colmap_path ./build/src/colmap/exe/colmap \ --dataset_names boulders,door \ --max_rotation_error 1.0 \ --max_proj_center_error 0.05 - name: Cleanup compiler cache run: | set -x ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose echo "Size of ctcache before: $(du -sh $CTCACHE_DIR)" echo "Number of ctcache files before: $(find $CTCACHE_DIR | wc -l)" # Delete cache older than 10 days. find "$CTCACHE_DIR"/*/ -mtime +10 -print0 | xargs -0 rm -rf echo "Size of ctcache after: $(du -sh $CTCACHE_DIR)" echo "Number of ctcache files after: $(find $CTCACHE_DIR | wc -l)" colmap-3.10/.github/workflows/build-windows.yml000066400000000000000000000143531464745566500216530ustar00rootroot00000000000000name: COLMAP (Windows) on: push: branches: - main pull_request: types: [ assigned, opened, synchronize, reopened ] release: types: [ published, edited ] jobs: build: name: ${{ matrix.config.os }} ${{ matrix.config.cmakeBuildType }} ${{ matrix.config.cudaEnabled && 'CUDA' || '' }} runs-on: ${{ matrix.config.os }} strategy: matrix: config: [ { os: windows-2019, cmakeBuildType: Release, cudaEnabled: false, testsEnabled: true, exportPackage: false, }, { os: windows-2022, cmakeBuildType: Release, cudaEnabled: true, testsEnabled: true, exportPackage: true, }, { os: windows-2022, cmakeBuildType: Release, cudaEnabled: false, testsEnabled: true, exportPackage: true, }, ] env: COMPILER_CACHE_VERSION: 1 COMPILER_CACHE_DIR: ${{ github.workspace }}/compiler-cache CCACHE_DIR: ${{ github.workspace }}/compiler-cache/ccache CCACHE_BASEDIR: ${{ github.workspace }} VCPKG_COMMIT_ID: e01906b2ba7e645a76ee021a19de616edc98d29f VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" steps: - uses: actions/checkout@v4 - name: Export GitHub Actions cache env uses: actions/github-script@v7 with: script: | core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - name: Compiler cache uses: actions/cache@v4 id: cache-builds with: key: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }}-${{ github.run_id }}-${{ github.run_number }} restore-keys: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }} path: ${{ env.COMPILER_CACHE_DIR }} - name: Install ccache shell: pwsh run: | New-Item -ItemType Directory -Force -Path "${{ env.CCACHE_DIR }}" echo "${{ env.COMPILER_CACHE_DIR }}/bin" | Out-File -Encoding utf8 -Append -FilePath $env:GITHUB_PATH if (Test-Path -PathType Leaf "${{ env.COMPILER_CACHE_DIR }}/bin/ccache.exe") { exit } .github/workflows/install-ccache.ps1 -Destination "${{ env.COMPILER_CACHE_DIR }}/bin" - name: Install CUDA uses: Jimver/cuda-toolkit@v0.2.16 if: matrix.config.cudaEnabled id: cuda-toolkit with: cuda: '12.5.0' sub-packages: '["nvcc", "nvtx", "cudart", "curand", "curand_dev", "nvrtc_dev"]' method: 'network' - name: Install CMake and Ninja uses: lukka/get-cmake@latest - name: Setup vcpkg shell: pwsh run: | ./scripts/shell/enter_vs_dev_shell.ps1 cd ${{ github.workspace }} git clone https://github.com/microsoft/vcpkg cd vcpkg git reset --hard ${{ env.VCPKG_COMMIT_ID }} ./bootstrap-vcpkg.bat - name: Configure and build shell: pwsh run: | ./scripts/shell/enter_vs_dev_shell.ps1 cd ${{ github.workspace }} ./vcpkg/vcpkg.exe integrate install mkdir build cd build cmake .. ` -GNinja ` -DCMAKE_MAKE_PROGRAM=ninja ` -DCMAKE_BUILD_TYPE=Release ` -DTESTS_ENABLED=${{ matrix.config.testsEnabled }} ` -DGUI_ENABLED=ON ` -DCUDA_ENABLED=${{ matrix.config.cudaEnabled }} ` -DCMAKE_CUDA_ARCHITECTURES=all-major ` -DCUDAToolkit_ROOT="${{ steps.cuda-toolkit.outputs.CUDA_PATH }}" ` -DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake" ` -DVCPKG_TARGET_TRIPLET=x64-windows-release ` -DCMAKE_INSTALL_PREFIX=install ninja - name: Run tests shell: pwsh run: | ./vcpkg/vcpkg.exe integrate install cd build $EXCLUDED_TESTS = "(feature/colmap_feature_sift_test)|(util/colmap_util_opengl_utils_test)|(mvs/colmap_mvs_gpu_mat_test)" ctest -E ${EXCLUDED_TESTS} --output-on-failure - name: Export package if: matrix.config.exportPackage shell: pwsh run: | ./vcpkg/vcpkg.exe integrate install cd build ninja install ../vcpkg/vcpkg.exe install ` --triplet=x64-windows-release ` --x-feature=gui ` --x-feature=cgal ` $(if ($${{ matrix.config.testsEnabled }}) { echo "--x-feature=tests" }) ` $(if ($${{ matrix.config.cudaEnabled }}) { echo "--x-feature=cuda" }) ../vcpkg/vcpkg.exe export --raw --output-dir vcpkg_export --output colmap cp vcpkg_export/colmap/installed/x64-windows/bin/*.dll install/bin cp vcpkg_export/colmap/installed/x64-windows-release/bin/*.dll install/bin cp -r vcpkg_export/colmap/installed/x64-windows/plugins install if ($${{ matrix.config.cudaEnabled }}) { cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/cudart64_*.dll" install/bin cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/curand64_*.dll" install/bin } Remove-Item -Recurse -Force install/include,install/lib,install/share - name: Upload package uses: actions/upload-artifact@v4 if: ${{ matrix.config.exportPackage && matrix.config.cudaEnabled }} with: name: colmap-x64-windows-cuda path: build/install - name: Upload package uses: actions/upload-artifact@v4 if: ${{ matrix.config.exportPackage && !matrix.config.cudaEnabled }} with: name: colmap-x64-windows-nocuda path: build/install - name: Cleanup compiler cache shell: pwsh run: | ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose colmap-3.10/.github/workflows/install-ccache.ps1000066400000000000000000000022531464745566500216340ustar00rootroot00000000000000[CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $Destination ) $version = "4.8" $folder = "ccache-$version-windows-x86_64" $url = "https://github.com/ccache/ccache/releases/download/v$version/$folder.zip" $expectedSha256 = "A2B3BAB4BB8318FFC5B3E4074DC25636258BC7E4B51261F7D9BEF8127FDA8309" $ErrorActionPreference = "Stop" try { New-Item -Path "$Destination" -ItemType Container -ErrorAction SilentlyContinue Write-Host "Download CCache" $zipFilePath = Join-Path "$env:TEMP" "$folder.zip" Invoke-WebRequest -Uri $url -UseBasicParsing -OutFile "$zipFilePath" -MaximumRetryCount 3 $hash = Get-FileHash $zipFilePath -Algorithm "sha256" if ($hash.Hash -ne $expectedSha256) { throw "File $Path hash $hash.Hash did not match expected hash $expectedHash" } Write-Host "Unzip CCache" Expand-Archive -Path "$zipFilePath" -DestinationPath "$env:TEMP" Write-Host "Move CCache" Move-Item -Force "$env:TEMP/$folder/ccache.exe" "$Destination" Remove-Item "$zipFilePath" Remove-Item -Recurse "$env:TEMP/$folder" } catch { Write-Host "Installation failed with an error" $_.Exception | Format-List exit -1 } colmap-3.10/.gitignore000077500000000000000000000006621464745566500147350ustar00rootroot00000000000000# Custom files LocalConfig.cmake src/colmap/util/version.cc # Custom directories .idea/ .vscode .vs .DS_Store build*/ install-debug/ install-release/ data/ doc/_build vcpkg_installed/ # Compiled Object files *.slo *.lo *.o *.obj *.pyc # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app colmap-3.10/.gitmodules000066400000000000000000000001721464745566500151130ustar00rootroot00000000000000[submodule "doc/_build/html"] path = doc/_build/html url = https://github.com/colmap/colmap.github.io.git ignore = all colmap-3.10/CHANGELOG.txt000066400000000000000000001252541464745566500147770ustar00rootroot00000000000000COLMAP 3.9.1 (01/08/2024) ------------------------- * Version 3.9 changelog by @ahojnnes in https://github.com/colmap/colmap/pull/2325 * Fully encapsulate freeimage in bitmap library (#2332) by @ahojnnes in https://github.com/colmap/colmap/pull/2334 COLMAP 3.9 (01/06/2024) ----------------------- * clang format all code and require clang-format-14 by @ahojnnes in https://github.com/colmap/colmap/pull/1785 * Fix compilation for vcpkg windows build by @ahojnnes in https://github.com/colmap/colmap/pull/1791 * Increment version number to 3.9 by @ahojnnes in https://github.com/colmap/colmap/pull/1794 * Remove unnecessary /arch:sse2 flag for MSVC by @ahojnnes in https://github.com/colmap/colmap/pull/1798 * Updated faq.rst by @CGCooke in https://github.com/colmap/colmap/pull/1801 * Fixed mistake in code comment for OpenCV Fisheye camera by @CGCooke in https://github.com/colmap/colmap/pull/1802 * Replace deprecated cudaThreadSynchronize with cudaDeviceSynchronize by @ahojnnes in https://github.com/colmap/colmap/pull/1806 * Replace deprecated Cuda texture references with texture objects by @ahojnnes in https://github.com/colmap/colmap/pull/1809 * Remove unused SIFT GPU cuda texture reference by @ahojnnes in https://github.com/colmap/colmap/pull/1823 * Upgrade SiftGPU to use CUDA texture objects by @ahojnnes in https://github.com/colmap/colmap/pull/1838 * Remove PBA as bundle adjustment backend to support CUDA 12+ by @ahojnnes in https://github.com/colmap/colmap/pull/1840 * Replace deprecated CUDA sature function call by @ahojnnes in https://github.com/colmap/colmap/pull/1841 * Avoid unnecessary mallocs during sampling by @ahojnnes in https://github.com/colmap/colmap/pull/1842 * Cleaned up docker readme and scripts by @ahojnnes in https://github.com/colmap/colmap/pull/1852 * add "Shared intrinsics per sub-folder" checkbox to automatic reconstruction window by @kenshi84 in https://github.com/colmap/colmap/pull/1853 * Update vcpkg by @ahojnnes in https://github.com/colmap/colmap/pull/1925 * Log the name of the file that causes Mat::Read() to checkfail by @SomeAlphabetGuy in https://github.com/colmap/colmap/pull/1923 * check Z_index correctly in ReadPly by @countywest in https://github.com/colmap/colmap/pull/1896 * Don't re-open files when reading and writing matrices by @SomeAlphabetGuy in https://github.com/colmap/colmap/pull/1926 * Update vcpkg to latest commit by @ahojnnes in https://github.com/colmap/colmap/pull/1948 * Remove unnecessary custom Eigen aligned allocator macros by @ahojnnes in https://github.com/colmap/colmap/pull/1947 * Prefix internal sources/includes with colmap by @ahojnnes in https://github.com/colmap/colmap/pull/1949 * Simplify clang-format config and sort includes by @ahojnnes in https://github.com/colmap/colmap/pull/1950 * Handle possible overflow in median function by @ahojnnes in https://github.com/colmap/colmap/pull/1951 * Run ASan pipeline under Ubuntu 22.04 by @ahojnnes in https://github.com/colmap/colmap/pull/1952 * Fix Ceres version test by @drkoller in https://github.com/colmap/colmap/pull/1954 * Fix deprecation warning for Qt font metrics width by @ahojnnes in https://github.com/colmap/colmap/pull/1958 * Setup clang-tidy and enable perf warnings by @ahojnnes in https://github.com/colmap/colmap/pull/1959 * VCPKG binary caching for windows CI by @ahojnnes in https://github.com/colmap/colmap/pull/1957 * Cosmetics for VS dev shell script by @ahojnnes in https://github.com/colmap/colmap/pull/1965 * Enable clang-tidy concurrency checks by @ahojnnes in https://github.com/colmap/colmap/pull/1967 * [Bug] fix finding shared points3D in FindLocalBundle by @wesleyliwei in https://github.com/colmap/colmap/pull/1963 * Enable compiler caching in CI by @ahojnnes in https://github.com/colmap/colmap/pull/1972 * Set number of features for different quality levels by @ahojnnes in https://github.com/colmap/colmap/pull/1975 * Specify parameter name using inline comment by @ahojnnes in https://github.com/colmap/colmap/pull/1976 * Fix Windows CCache by @ahojnnes in https://github.com/colmap/colmap/pull/1977 * Add e2e tests in CI pipeline using ETH3D datasets by @ahojnnes in https://github.com/colmap/colmap/pull/1397 * [feature] print verbose information for model analyzer by @wesleyliwei in https://github.com/colmap/colmap/pull/1978 * Add a missing include to compile with gcc13 by @EstebanDugueperoux2 in https://github.com/colmap/colmap/pull/1984 * Speed up snapshot construct in RigBundleAdjuster by @wesleyliwei in https://github.com/colmap/colmap/pull/1988 * Update outdated docker cuda image tag by @ahojnnes in https://github.com/colmap/colmap/pull/1992 * Add boulders ETH3D dataset to CI E2E tests by @ahojnnes in https://github.com/colmap/colmap/pull/1991 * Update executable paths in documentation by @ahojnnes in https://github.com/colmap/colmap/pull/1993 * Avoid unnecessary copy in ExtractTopScaleFeatures by @ahojnnes in https://github.com/colmap/colmap/pull/1994 * Move related code under new image library folder by @ahojnnes in https://github.com/colmap/colmap/pull/1995 * Move related code under new camera folder by @ahojnnes in https://github.com/colmap/colmap/pull/1996 * Added a virtual destructor to Sampler by @SomeAlphabetGuy in https://github.com/colmap/colmap/pull/2000 * Add a few more clang-tidy checks by @ahojnnes in https://github.com/colmap/colmap/pull/2001 * Move related code to new geometry module by @ahojnnes in https://github.com/colmap/colmap/pull/2006 * Use #pragma once as include guard by @ahojnnes in https://github.com/colmap/colmap/pull/2007 * Add bugprone-* clang-tidy checks by @ahojnnes in https://github.com/colmap/colmap/pull/2010 * Avoid const params in declarations by @ahojnnes in https://github.com/colmap/colmap/pull/2011 * Set and require C++14 by @ahojnnes in https://github.com/colmap/colmap/pull/2012 * Cleanup math functions that are now part of eigen/stdlib by @ahojnnes in https://github.com/colmap/colmap/pull/2013 * Add clang-analyzer checks by @ahojnnes in https://github.com/colmap/colmap/pull/2014 * Replace CMake provided find_package scripts and modern CMake targets by @ahojnnes in https://github.com/colmap/colmap/pull/2016 * Switch from Boost unit tests to Gtest by @ahojnnes in https://github.com/colmap/colmap/pull/2017 * Fix ccache restore keys in pipeline caching by @ahojnnes in https://github.com/colmap/colmap/pull/2018 * Add missing cacheHitVar to fix ccache by @ahojnnes in https://github.com/colmap/colmap/pull/2020 * Add missing Boost::graph import by @sarlinpe in https://github.com/colmap/colmap/pull/2021 * Compressed/flattened correspondence graph for faster triangulation / less memory by @ahojnnes in https://github.com/colmap/colmap/pull/2019 * Fix window ccache key by @ahojnnes in https://github.com/colmap/colmap/pull/2024 * Consistently use shared_ptr for shared pointers for SFM objects by @ahojnnes in https://github.com/colmap/colmap/pull/2023 * Remove check on Qt version by @sarlinpe in https://github.com/colmap/colmap/pull/2022 * Synthetics for E2E incremental mapper tests by @ahojnnes in https://github.com/colmap/colmap/pull/2025 * New math module by @ahojnnes in https://github.com/colmap/colmap/pull/2028 * Simplify similarity transform and more tests by @ahojnnes in https://github.com/colmap/colmap/pull/2030 * Extract reconstruction alignment functions into new file by @ahojnnes in https://github.com/colmap/colmap/pull/2032 * Add E2E hierarchical mapper tests by @ahojnnes in https://github.com/colmap/colmap/pull/2033 * Rename SimilarityTransform3 to Sim3d by @ahojnnes in https://github.com/colmap/colmap/pull/2034 * Add Rigid3d transform class by @ahojnnes in https://github.com/colmap/colmap/pull/2035 * Consolidate and simplify Rigid3d and Sim3d by @ahojnnes in https://github.com/colmap/colmap/pull/2037 * Some small improvements/cleanup for rigid3d/sim3d usage by @ahojnnes in https://github.com/colmap/colmap/pull/2041 * CamFromWorld replaces qvec/tvec by @ahojnnes in https://github.com/colmap/colmap/pull/2039 * Retry download of ETH3D datasets by @ahojnnes in https://github.com/colmap/colmap/pull/2043 * WorldToImage becomes CamToImg by @ahojnnes in https://github.com/colmap/colmap/pull/2044 * Camera models operate on camera rays by @ahojnnes in https://github.com/colmap/colmap/pull/2045 * Ignore directory .vs by @whuaegeanse in https://github.com/colmap/colmap/pull/2046 * Use the reference of Rigid3d to reduce memory consumption by @whuaegeanse in https://github.com/colmap/colmap/pull/2047 * Inline point to image projection by @ahojnnes in https://github.com/colmap/colmap/pull/2050 * Point2D becomes simpler pure data struct by @ahojnnes in https://github.com/colmap/colmap/pull/2051 * Use Eigen math for estimator utils by @ahojnnes in https://github.com/colmap/colmap/pull/2052 * Move cost functions under geometry module and rename by @ahojnnes in https://github.com/colmap/colmap/pull/2053 * Bundle adjuster is an estimator by @ahojnnes in https://github.com/colmap/colmap/pull/2054 * Remaining base targets move to new scene module by @ahojnnes in https://github.com/colmap/colmap/pull/2055 * Vote and verify improvements/speedup by @ahojnnes in https://github.com/colmap/colmap/pull/2056 * Generate version info in .cc file to reduce number of recompilations by @ahojnnes in https://github.com/colmap/colmap/pull/2057 * Option manager moves to controllers to disentangle circular deps by @ahojnnes in https://github.com/colmap/colmap/pull/2058 * Granular CMake modules and build targets by @ahojnnes in https://github.com/colmap/colmap/pull/2059 * Fix docker build by @ahojnnes in https://github.com/colmap/colmap/pull/2069 * Remove warnings about duplicated marco NOMINMAX by @whuaegeanse in https://github.com/colmap/colmap/pull/2067 * lib folder becomes thirdparty folder by @ahojnnes in https://github.com/colmap/colmap/pull/2068 * Remove unnecessary checks in image pair conversion by @ahojnnes in https://github.com/colmap/colmap/pull/2074 * Replace flaky ETH3D terrace with courtyard dataset by @ahojnnes in https://github.com/colmap/colmap/pull/2075 * Synthesize chained match graph for more mapper tests by @ahojnnes in https://github.com/colmap/colmap/pull/2076 * Introduce abstract feature extractor by @ahojnnes in https://github.com/colmap/colmap/pull/2077 * Avoid unnecessary data copies in feature conversion utils by @ahojnnes in https://github.com/colmap/colmap/pull/2078 * Abstract feature matcher by @ahojnnes in https://github.com/colmap/colmap/pull/2082 * Encapsulate feature matching controller/worker implementations by @ahojnnes in https://github.com/colmap/colmap/pull/2085 * Some cosmetics for util/feature types by @ahojnnes in https://github.com/colmap/colmap/pull/2084 * Use std:: when cmath included by @whuaegeanse in https://github.com/colmap/colmap/pull/2081 * Encapsulate feature extraction controller/worker implementations by @ahojnnes in https://github.com/colmap/colmap/pull/2086 * Reenable VS2022 CI pipeline by @ahojnnes in https://github.com/colmap/colmap/pull/1689 * Consistent transform convention for CenterAndNormalizeImagePoints by @ahojnnes in https://github.com/colmap/colmap/pull/2092 * Retire Mac 11 CI build by @ahojnnes in https://github.com/colmap/colmap/pull/2094 * Add ReprojErrorConstantPoint3DCostFunction to speed up the RefineAbsolutePose function by @whuaegeanse in https://github.com/colmap/colmap/pull/2089 * Numeric differentiation of camera model using partial piv LU by @ahojnnes in https://github.com/colmap/colmap/pull/2100 * cmake: add testing.cc to colmap_util only if TESTS_ENABLED=ON by @NeroBurner in https://github.com/colmap/colmap/pull/2102 * Set CUDA_STANDARD to 14 by @ahojnnes in https://github.com/colmap/colmap/pull/2108 * Transform back to existing images positions after mapper processing if set fixed by @ferreram in https://github.com/colmap/colmap/pull/2095 * Update documentation with new branch policy by @ahojnnes in https://github.com/colmap/colmap/pull/2110 * Update CMake find dependencies for vcpkg by @ahojnnes in https://github.com/colmap/colmap/pull/2116 * Decouple SIFT match from two view geometry options by @ahojnnes in https://github.com/colmap/colmap/pull/2118 * Fix docker build by @vnmsklnk in https://github.com/colmap/colmap/pull/2122 * Trigger build pipeline on main branch by @ahojnnes in https://github.com/colmap/colmap/pull/2123 * Update Linux install documentation with new branch policy by @joshuaoreilly in https://github.com/colmap/colmap/pull/2126 * Fix link in camera model documentation by @CFretter in https://github.com/colmap/colmap/pull/2152 * [Bugfix] Fix GUI_ENABLED=OFF and skip SiftGPU if no GUI and no CUDA by @sarlinpe in https://github.com/colmap/colmap/pull/2151 * [Bugfix] Properly handle CGAL_ENABLED by @sarlinpe in https://github.com/colmap/colmap/pull/2149 * Refinement of intrinsics in the point_triangulator by @tsattler in https://github.com/colmap/colmap/pull/2144 * Bugfix in handling COLMAP_GPU_ENABLED by @sarlinpe in https://github.com/colmap/colmap/pull/2163 * Expose exe as libs by @sarlinpe in https://github.com/colmap/colmap/pull/2165 * Add Sim3d::FromMatrix by @sarlinpe in https://github.com/colmap/colmap/pull/2147 * Check code format in CI by @ahojnnes in https://github.com/colmap/colmap/pull/2171 * Clean up dependencies by @sarlinpe in https://github.com/colmap/colmap/pull/2173 * Move tests into anonymous namespaces by @ahojnnes in https://github.com/colmap/colmap/pull/2175 * Fix glew/qopengl conflict warning by @ahojnnes in https://github.com/colmap/colmap/pull/2176 * Update documentation with new link to GitHub discussions by @ahojnnes in https://github.com/colmap/colmap/pull/2177 * Restore GLEW include by @sarlinpe in https://github.com/colmap/colmap/pull/2178 * Align reconstructions via shared 3D points by @sarlinpe in https://github.com/colmap/colmap/pull/2169 * Add clang-tidy-cachein CI by @ahojnnes in https://github.com/colmap/colmap/pull/2182 * Disable GUI build in one CI config by @ahojnnes in https://github.com/colmap/colmap/pull/2181 * Show verbose ccache stats by @ahojnnes in https://github.com/colmap/colmap/pull/2183 * Add EstimateGeneralizedAbsolutePose by @sarlinpe in https://github.com/colmap/colmap/pull/2174 * Fix bug in ReconstructionManagerWidget::Update by @whuaegeanse in https://github.com/colmap/colmap/pull/2186 * Fix missing retrieval dependency by @ahojnnes in https://github.com/colmap/colmap/pull/2189 * Removing clustering_options_ and mapper_options_ in Hierarchical Mapper Controller by @Serenitysmk in https://github.com/colmap/colmap/pull/2193 * Publish docker image to docker hub by @ahojnnes in https://github.com/colmap/colmap/pull/2195 * Fix Cuda architecture in docker build by @ahojnnes in https://github.com/colmap/colmap/pull/2196 * Fix all-major cuda arch missing in CMake < 3.23 by @ahojnnes in https://github.com/colmap/colmap/pull/2197 * Update triangulation.cc by @RayShark0605 in https://github.com/colmap/colmap/pull/2205 * Update author and acknowledgements by @ahojnnes in https://github.com/colmap/colmap/pull/2207 * Code formatting for Python by @ahojnnes in https://github.com/colmap/colmap/pull/2208 * Retire outdated build script by @ahojnnes in https://github.com/colmap/colmap/pull/2217 * Remove mention of deprecated build script by @sarlinpe in https://github.com/colmap/colmap/pull/2220 * Improve word spelling by @zchrissirhcz in https://github.com/colmap/colmap/pull/2235 * Stack allocate camera param idx arrays by @ahojnnes in https://github.com/colmap/colmap/pull/2234 * fix: typo in colmap/src/colmap/ui/project_widget.cc by @varundhand in https://github.com/colmap/colmap/pull/2241 * Update reconstruction.cc by @RayShark0605 in https://github.com/colmap/colmap/pull/2238 * Update to Docker CUDA 12.2.2 by @ahojnnes in https://github.com/colmap/colmap/pull/2244 * Stop setting C++ standard flags manually by @AdrianBunk in https://github.com/colmap/colmap/pull/2251 * Setting clear_points to true per default in point_triangulator by @tsattler in https://github.com/colmap/colmap/pull/2252 * Update cameras.rst to fix link to code by @tsattler in https://github.com/colmap/colmap/pull/2246 * Fix matching of imported features without descriptors by @ahojnnes in https://github.com/colmap/colmap/pull/2269 * Consistent versioning between documentation and code by @ahojnnes in https://github.com/colmap/colmap/pull/2275 * Reduce mallocs for RANSAC estimator models by @ahojnnes in https://github.com/colmap/colmap/pull/2283 * Migrate to glog logging by @ahojnnes in https://github.com/colmap/colmap/pull/2172 * Turn Point3D into simple data struct by @ahojnnes in https://github.com/colmap/colmap/pull/2285 * Camera becomes simple data struct by @ahojnnes in https://github.com/colmap/colmap/pull/2286 * Recover custom Eigen std::vector allocator for Eigen <3.4 support by @ahojnnes in https://github.com/colmap/colmap/pull/2293 * Replace result_of with invoke_result_t by @sarlinpe in https://github.com/colmap/colmap/pull/2300 * Allow getters FocalLength{X,Y} for isotropic models by @sarlinpe in https://github.com/colmap/colmap/pull/2301 * Add missing Boost targets and cleanup includes by @sarlinpe in https://github.com/colmap/colmap/pull/2304 * Expose IncrementalMapperOptions::{mapper,triangulation} by @sarlinpe in https://github.com/colmap/colmap/pull/2308 * Update install instructions for Mac by @Dawars in https://github.com/colmap/colmap/pull/2310 * Remove unused ceres reference in doc by @ahojnnes in https://github.com/colmap/colmap/pull/2315 * Fix typo by @whuaegeanse in https://github.com/colmap/colmap/pull/2317 * Stable version 3.9 release by @ahojnnes in https://github.com/colmap/colmap/pull/2319 COLMAP 3.8 (01/31/2023) ----------------------- * Updating geo-registration doc. by @ferreram in https://github.com/colmap/colmap/pull/1410 * Adding user-specified option for reconstructing purely planar scene. … by @ferreram in https://github.com/colmap/colmap/pull/1408 * Only apply sqlite vacuum command when elements are deleted from the database. by @ferreram in https://github.com/colmap/colmap/pull/1414 * Replace Graclus with Metis dependency by @ahojnnes in https://github.com/colmap/colmap/pull/1422 * Update ceres download URL in build script by @whuaegeanse in https://github.com/colmap/colmap/pull/1430 * Fix type errors when building colmap with build.py in windows by @whuaegeanse in https://github.com/colmap/colmap/pull/1440 * Fix bug in the computation of the statistics Global/Local BA by @whuaegeanse in https://github.com/colmap/colmap/pull/1449 * Add RefineGeneralizedAbsolutePose and covariance estimation by @Skydes in https://github.com/colmap/colmap/pull/1464 * Update docker image definition by @ahojnnes in https://github.com/colmap/colmap/pull/1478 * Upgrade deprecated ceres parameterizations to manifolds by @ahojnnes in https://github.com/colmap/colmap/pull/1477 * Use masks for stereo fusion on automatic reconstruction by @ibrarmalik in https://github.com/colmap/colmap/pull/1488 * fix random seed set failed from external interface by @WZG3661 in https://github.com/colmap/colmap/pull/1498 * Replace deprecated Eigen nonZeros() call for most recent Eigen versions. by @nackjaylor in https://github.com/colmap/colmap/pull/1494 * Fix ceres-solver folder name by @f-fl0 in https://github.com/colmap/colmap/pull/1501 * Improved convergence criterion for XYZ to ELL conversion by @ahojnnes in https://github.com/colmap/colmap/pull/1505 * Fix bug in the function SetPtr of Bitmap by @whuaegeanse in https://github.com/colmap/colmap/pull/1525 * Avoid the calling of copy constructor/assignment by @whuaegeanse in https://github.com/colmap/colmap/pull/1524 * Avoid calling copy constructors of FeatureKeypoints and FeatureDescriptors by @whuaegeanse in https://github.com/colmap/colmap/pull/1540 * Initialize freeimage if statically linked by @ahojnnes in https://github.com/colmap/colmap/pull/1549 * Avoid hard crash if Jacobian matrix is rank deficient by @mihaidusmanu in https://github.com/colmap/colmap/pull/1557 * visualize_model.py: added FULL_OPENCV model by @soeroesg in https://github.com/colmap/colmap/pull/1552 * Update vcpkg version to fix CI pipeline by @ahojnnes in https://github.com/colmap/colmap/pull/1568 * Replace deprecated Mac OS 10.15 with Mac OS 12 build in CI by @ahojnnes in https://github.com/colmap/colmap/pull/1569 * Fix inconsistent between the actual executed image reader option and the saved project.ini file by @XuChengHUST in https://github.com/colmap/colmap/pull/1564 * checkout the expected version of ceres solver by @scott-vsi in https://github.com/colmap/colmap/pull/1576 * use default qt5 brew install directory #1573 by @catapulta in https://github.com/colmap/colmap/pull/1574 * Fix image undistortion with nested image folders by @ahojnnes in https://github.com/colmap/colmap/pull/1606 * Fix source file permissions by @ahojnnes in https://github.com/colmap/colmap/pull/1607 * Fixed the collection of arguments in colmap.bat by @tdegraaff in https://github.com/colmap/colmap/pull/1121 * Add OpenMP to COLMAP_EXTERNAL_LIBRARIES if enabled by @logchan in https://github.com/colmap/colmap/pull/1632 * Fix output tile reconstructions are the same as the input reconstruction in `RunModelSplitter` (#1513) by @Serenitysmk in https://github.com/colmap/colmap/pull/1531 * add `libmetis-dev` to solve `METIS_INCLUDE_DIRS`. by @FavorMylikes in https://github.com/colmap/colmap/pull/1672 * Update install.rst by @tomer-grin in https://github.com/colmap/colmap/pull/1671 * Update freeimage links. by @Yulv-git in https://github.com/colmap/colmap/pull/1675 * fix small typo by @skal65535 in https://github.com/colmap/colmap/pull/1668 * Update build.py with new glew link by @aghand0ur in https://github.com/colmap/colmap/pull/1658 * Add use_cache in fusion options GUI by @hrflr in https://github.com/colmap/colmap/pull/1655 * Add CI pipeline for Ubuntu 22.04 by @ahojnnes in https://github.com/colmap/colmap/pull/1688 * Avoid unnecessary copies of data by @ahojnnes in https://github.com/colmap/colmap/pull/1691 * Reduce memory allocations in correspondence graph search by @ahojnnes in https://github.com/colmap/colmap/pull/1692 * Use FindCUDAToolkit when available. by @hanseuljun in https://github.com/colmap/colmap/pull/1693 * Fixed a crash due to inconsistent undistortion by @SomeAlphabetGuy in https://github.com/colmap/colmap/pull/1698 * Add CUDA Ubuntu 22.04 CI build by @ahojnnes in https://github.com/colmap/colmap/pull/1705 * Delete the redundancy install of libmetis-dev by @thomas-graphopti in https://github.com/colmap/colmap/pull/1721 * Fix broken loading of image masks on macOS by @buesma in https://github.com/colmap/colmap/pull/1639 * Update install instructions with latest hints and known issues by @ahojnnes in https://github.com/colmap/colmap/pull/1736 * Modernize smart pointer initialization, fix alloc/dealloc mismatch by @ahojnnes in https://github.com/colmap/colmap/pull/1737 * Fix typo in cli.rst by @ojhernandez in https://github.com/colmap/colmap/pull/1747 * Fix inconsistent image resizing between CPU/GPU implementations of SIFT by @Yzhbuaa in https://github.com/colmap/colmap/pull/1642 * Reduce number of SIFT test features to make tests run under WSL by @ahojnnes in https://github.com/colmap/colmap/pull/1748 * Tag documentation version with dev by @ahojnnes in https://github.com/colmap/colmap/pull/1749 * Update copyright to 2023 by @ahojnnes in https://github.com/colmap/colmap/pull/1750 * Fix max image dimension for positive first_octave by @ahojnnes in https://github.com/colmap/colmap/pull/1751 * Fix SIFT GPU match creation by @ahojnnes in https://github.com/colmap/colmap/pull/1757 * Fix SIFT tests for OpenGL by @ahojnnes in https://github.com/colmap/colmap/pull/1762 * Suppress CUDA stack size warning for ptxas by @ahojnnes in https://github.com/colmap/colmap/pull/1770 * Simplify CUDA CMake configuration by @ahojnnes in https://github.com/colmap/colmap/pull/1776 * Fixes for CUDA compilation by @ahojnnes in https://github.com/colmap/colmap/pull/1777 * Improvements to dockerfile and build pipeline by @ahojnnes in https://github.com/colmap/colmap/pull/1778 * Explicitly require CMAKE_CUDA_ARCHITECTURES to be defined by @ahojnnes in https://github.com/colmap/colmap/pull/1781 * Depend on system installed FLANN by @ahojnnes in https://github.com/colmap/colmap/pull/1782 * Option to store relative pose between two cameras in database by @yanxke in https://github.com/colmap/colmap/pull/1774 * Depend on system installed SQLite3 by @ahojnnes in https://github.com/colmap/colmap/pull/1783 COLMAP 3.7 (01/26/2022) ----------------------- * Allow to save fused point cloud in colmap format when using command line by @boitumeloruf in https://github.com/colmap/colmap/pull/799 * Fix typos in image.h by @Pascal-So in https://github.com/colmap/colmap/pull/936 * Fix for EPnP estimator by @vlarsson in https://github.com/colmap/colmap/pull/943 * Visualize models using Python in Open3D by @ahojnnes in https://github.com/colmap/colmap/pull/948 * Update tutorial.rst by @ignacio-rocco in https://github.com/colmap/colmap/pull/953 * 8 point algorithm internal contraint fix by @mihaidusmanu in https://github.com/colmap/colmap/pull/982 * Python script for writing depth/normal arrays by @SBCV in https://github.com/colmap/colmap/pull/957 * BuildImageModel: use std::vector instead of numbered arguments by @Pascal-So in https://github.com/colmap/colmap/pull/949 * Fix bugs of sift feature matching by @whuaegeanse in https://github.com/colmap/colmap/pull/985 * script for modifying fused results by @SBCV in https://github.com/colmap/colmap/pull/984 * fix camera model query by @Pascal-So in https://github.com/colmap/colmap/pull/997 * fixed small bug in visualize_model.py by @sniklaus in https://github.com/colmap/colmap/pull/1007 * Update .travis.yml by @srinivas32 in https://github.com/colmap/colmap/pull/989 * Ensure DecomposeHomographyMatrix() always returns rotations by @daithimaco in https://github.com/colmap/colmap/pull/1040 * Remove deprecated qt foreach by @UncleGene in https://github.com/colmap/colmap/pull/1039 * Fix AMD/Windows GUI visualization bug by @drkoller in https://github.com/colmap/colmap/pull/1079 * include colmap_cuda in COLMAP_LIBRARIES when compiled with cuda by @ClementPinard in https://github.com/colmap/colmap/pull/1084 * Fix runtime crash when sparsesuite is missing from ceres by @anmatako in https://github.com/colmap/colmap/pull/1115 * Store relative poses in two_view_geometry table by @Ahmed-Salama in https://github.com/colmap/colmap/pull/1103 * search src images for patch_match from all set, not only referenced subset by @DaniilSNikulin in https://github.com/colmap/colmap/pull/1038 * Replace Travis CI with Azure Pipelines for Linux/Mac builds by @ahojnnes in https://github.com/colmap/colmap/pull/1119 * Allow ReadPly to handle double precision files by @anmatako in https://github.com/colmap/colmap/pull/1131 * Update GPSTransform calculations to improve accuracy by @anmatako in https://github.com/colmap/colmap/pull/1132 * Add scale template flag in SimilarityTransform3::Estimate by @anmatako in https://github.com/colmap/colmap/pull/1133 * Add CopyFile utility that can copy or hard/soft-link files by @anmatako in https://github.com/colmap/colmap/pull/1134 * Expose BA options in IncrementalMapper by @anmatako in https://github.com/colmap/colmap/pull/1139 * Allow configurable paths for mvs::Model by @anmatako in https://github.com/colmap/colmap/pull/1141 * Change ReconstructionMaanger to write larger recons first by @anmatako in https://github.com/colmap/colmap/pull/1137 * Setup Azure pipelines for Windows build by @ahojnnes in https://github.com/colmap/colmap/pull/1150 * Add fixed extrinsics in rig config by @anmatako in https://github.com/colmap/colmap/pull/1144 * Allow custom config and missing dependencies for patch-match by @anmatako in https://github.com/colmap/colmap/pull/1142 * Update print statements for Python 3 compatibility by @UncleGene in https://github.com/colmap/colmap/pull/1126 * Allow cleanup of SQLite tables using new database_cleaner command by @anmatako in https://github.com/colmap/colmap/pull/1136 * Extend SceneClustering to support non-hierarchical (flat) clusters by @anmatako in https://github.com/colmap/colmap/pull/1140 * Support more formats in model_converter by @anmatako in https://github.com/colmap/colmap/pull/1147 * Fix Mac 10.15 build due to changed Qt5 path by @ahojnnes in https://github.com/colmap/colmap/pull/1157 * Fix bug in ReadCameraRigConfig when reading extrinsics by @anmatako in https://github.com/colmap/colmap/pull/1158 * Add utility to compare poses between two sparse models by @ahojnnes in https://github.com/colmap/colmap/pull/1159 * Modularize executable main functions into separate sources by @ahojnnes in https://github.com/colmap/colmap/pull/1160 * Fix unnecessary copies in for range loops by @ahojnnes in https://github.com/colmap/colmap/pull/1162 * Add script to clang-format all source code by @ahojnnes in https://github.com/colmap/colmap/pull/1163 * Add back new options and formats for model_converter by @anmatako in https://github.com/colmap/colmap/pull/1164 * ImageReder new option and bug fix in GPS priors by @anmatako in https://github.com/colmap/colmap/pull/1146 * Parallelize stereo fusion; needs pre-loading of entire workspace by @anmatako in https://github.com/colmap/colmap/pull/1148 * Refactoring and new functionality in Reconstruction class by @anmatako in https://github.com/colmap/colmap/pull/1169 * Add new functionality in image_undistorter by @anmatako in https://github.com/colmap/colmap/pull/1168 * Add new CMake option to disable GUI by @anmatako in https://github.com/colmap/colmap/pull/1165 * Fix the memory leak caused by not releasing the memory of the PRNG at the end of the thread by @whuaegeanse in https://github.com/colmap/colmap/pull/1170 * Fix fusion segfault bug by @anmatako in https://github.com/colmap/colmap/pull/1176 * Update SiftGPU to use floorf for floats by @anmatako in https://github.com/colmap/colmap/pull/1182 * fix typo in extraction.cc by @iuk in https://github.com/colmap/colmap/pull/1191 * Improvements to NVM, Cam, Recon3D, and Bundler exporters by @drkoller in https://github.com/colmap/colmap/pull/1187 * Update model_aligner functionality by @anmatako in https://github.com/colmap/colmap/pull/1177 * Add new model_cropper and model_splitter commands by @anmatako in https://github.com/colmap/colmap/pull/1179 * use type point2D_t instead of image_t by @iuk in https://github.com/colmap/colmap/pull/1199 * Fix radial distortion in Cam format exporter by @drkoller in https://github.com/colmap/colmap/pull/1196 * Add new model_transformer command by @anmatako in https://github.com/colmap/colmap/pull/1178 * Fix error of using urllib to download eigen from gitlab by @whuaegeanse in https://github.com/colmap/colmap/pull/1194 * Multi-line string fix in Python model script by @mihaidusmanu in https://github.com/colmap/colmap/pull/1217 * added visibility_sigma to CLI input options for delaunay_mesher. by @Matstah in https://github.com/colmap/colmap/pull/1236 * Backwards compatibility of model_aligner by @tsattler in https://github.com/colmap/colmap/pull/1240 * [update undistortion] update dumped commands by @hiakru in https://github.com/colmap/colmap/pull/1276 * Compute reprojection error in generalized absolute solver by @Skydes in https://github.com/colmap/colmap/pull/1257 * Modifying scripts/python/flickr_downloader.py to create files with correct extensions by @snavely in https://github.com/colmap/colmap/pull/1275 * revise Dockerfile and readme. by @MasahiroOgawa in https://github.com/colmap/colmap/pull/1281 * Update to latest vcpkg version by @ahojnnes in https://github.com/colmap/colmap/pull/1319 * Fix compiler warnings reported by GCC by @ahojnnes in https://github.com/colmap/colmap/pull/1317 * Auto-rotate JPEG images based on EXIF orientation by @ahojnnes in https://github.com/colmap/colmap/pull/1318 * Upgrade vcpkg to fix CI build issues by @ahojnnes in https://github.com/colmap/colmap/pull/1331 * Added descriptor normalization argument to feature_extractor. by @mihaidusmanu in https://github.com/colmap/colmap/pull/1332 * Fix memory leak in the function of StringAppendV by @whuaegeanse in https://github.com/colmap/colmap/pull/1337 * Add CUDA_SAFE_CALL to cudaGetDeviceCount. by @chpatrick in https://github.com/colmap/colmap/pull/1334 * Add missing include in case CUDA/GUI is not available by @ahojnnes in https://github.com/colmap/colmap/pull/1329 * Fix wrong WGS84 model and test cases in GPSTransform by @Freeverc in https://github.com/colmap/colmap/pull/1333 * Fixes bug in sprt.cc: num_inliers was not set. by @rmbrualla in https://github.com/colmap/colmap/pull/1360 * Prevent a divide by zero corner case. by @rmbrualla in https://github.com/colmap/colmap/pull/1361 * Adds missing header. by @rmbrualla in https://github.com/colmap/colmap/pull/1362 * Require Qt in COLMAPConfig only if GUI is enabled by @Skydes in https://github.com/colmap/colmap/pull/1365 * Keep precision in the process of storing in text. by @whuaegeanse in https://github.com/colmap/colmap/pull/1363 * Expose exe internals by @Skydes in https://github.com/colmap/colmap/pull/1366 * Fix inliers matches extraction in EstimateUncalibrated function. by @ferreram in https://github.com/colmap/colmap/pull/1369 * Expose exe internals - fix by @Skydes in https://github.com/colmap/colmap/pull/1368 * Remove deprecated Mac OSX 10.14 image in ADO pipeline by @ahojnnes in https://github.com/colmap/colmap/pull/1383 * Add Mac OSX 11 ADO pipeline job by @ahojnnes in https://github.com/colmap/colmap/pull/1384 * Fix warnings for latest compiler/libraries by @ahojnnes in https://github.com/colmap/colmap/pull/1382 * Fix clang compiler warnings by @ahojnnes in https://github.com/colmap/colmap/pull/1387 * Add Address Sanitizer options and fix reported issues by @ahojnnes in https://github.com/colmap/colmap/pull/1390 * User/joschonb/asan cleanup by @ahojnnes in https://github.com/colmap/colmap/pull/1391 * Add ADO pipeline for Visual Studio 2022 by @ahojnnes in https://github.com/colmap/colmap/pull/1392 * Add ccache option by @ahojnnes in https://github.com/colmap/colmap/pull/1395 * Update ModelAligner to handle GPS and custom coords. and more by @ferreram in https://github.com/colmap/colmap/pull/1371 COLMAP 3.6 (07/24/2020) ----------------------- - Improved robustness and faster incremental reconstruction process - Add ``image_deleter`` command to remove images from sparse model - Add ``image_filter`` command to filter bad registrations from sparse model - Add ``point_filtering`` command to filter sparse model point clouds - Add ``database_merger`` command to merge two databases, which is useful to parallelize matching across different machines - Add ``image_undistorter_standalone`` to enable undistorting images without a pre-existing full sparse model - Improved undistortion for fisheye cameras and FOV camera model - Support for masking input images in feature extraction stage - Improved HiDPI support in GUI for high-resolution monitors - Import sparse model when launching GUI from CLI - Faster CPU-based matching using approximate NN search - Support for bundle adjustment with fixed extrinsics - Support for fixing existing images when continuing reconstruction - Camera model colors in viewer can be customized - Support for latest GPU architectures in CUDA build - Support for writing sparse models in Python scripts - Scripts for building and running COLMAP in Docker - Many more bug fixes and improvements to code and documentation COLMAP 3.5 (08/22/2018) ----------------------- - COLMAP is now released under the BSD license instead of the GPL - COLMAP is now installed as a library, whose headers can be included and libraries linked against from other C/C++ code - Add hierarchical mapper for parallelized reconstruction or large scenes - Add sparse and dense Delaunay meshing algorithms, which reconstruct a watertight surface using a graph cut on the Delaunay triangulation of the reconstructed sparse or dense point cloud - Improved robustness when merging different models - Improved pre-trained vocabulary trees available for download - Add COLMAP as a software entry under Linux desktop systems - Add support to compile COLMAP on ARM platforms - Add example Python script to read/write COLMAP database - Add region of interest (ROI) cropping in image undistortion - Several import bug fixes for spatial verification in image retrieval - Add more extensive continuous integration across more compilation scenarios - Many more bug fixes and improvements to code and documentation COLMAP 3.4 (01/29/2018) ----------------------- - Unified command-line interface: The functionality of previous executables have been merged into the ``src/exe/colmap.cc`` executable. The GUI can now be started using the command ``colmap gui`` and other commands are available as ``colmap [command]``. For example, the feature extractor is now available as ``colmap feature_extractor [args]`` while all command-line arguments stay the same as before. This should result in much faster project compile times and smaller disk space usage of the program. More details about the new interface are documented at https://colmap.github.io/cli.html - More complete depth and normal maps with larger patch sizes - Faster dense stereo computation by skipping rows/columns in patch match, improved random sampling in patch match, and faster bilateral NCC - Better high DPI screen support for the graphical user interface - Improved model viewer under Windows, which now requires Qt 5.4 - Save computed two-view geometries in database - Images (keypoint/matches visualization, depth and normal maps) can now be saved from the graphical user interface - Support for PMVS format without sparse bundler file - Faster covariant feature detection - Many more bug fixes and improvements COLMAP 3.3 (11/21/2017) ----------------------- - Add DSP (Domain Size Pooling) SIFT implementation. DSP-SIFT outperforms standard SIFT in most cases, as shown in "Comparative Evaluation of Hand-Crafted and Learned Local Features", Schoenberger et al., CVPR 2017 - Improved parameters dense reconstruction of smaller models - Improved compile times due to various code optimizations - Add option to specify camera model in automatic reconstruction - Add new model orientation alignment based on upright image assumption - Improved numerical stability for generalized absolute pose solver - Support for image range specification in PMVS dense reconstruction format - Support for older Python versions in automatic build script - Fix OpenCV Fisheye camera model to exactly match OpenCV specifications COLMAP 3.2 (9/2/2017) ---------------------- - Fully automatic cross-platform build script (Windows, Mac, Linux) - Add multi-GPU feature extraction if multiple CUDA devices are available - Configurable dimension and data type for vocabulary tree implementation - Add new sequential matching mode for image sequences with high frame-rate - Add generalized relative pose solver for multi-camera systems - Add sparse least absolute deviation solver - Add CPU/GPU options to automatic reconstruction tool - Add continuous integration system under Windows, Mac, Linux through Github - Many more bug fixes and improvements COLMAP 3.1 (6/15/2017) ---------------------- - Add fast spatial verification to image retrieval module - Add binary file format for sparse models by default. Old text format still fully compatible and possible conversion in GUI and CLI - Add cross-platform little endian binary file reading and writing - Faster and less memory hungry stereo fusion by computing consistency on demand and possible limitation of image size in fusion - Simpler geometric stereo processing interface. Now geometric stereo output can be computed using a single pass - Faster and multi-architecture CUDA compilation - Add medium quality option in automatic reconstructor - Many more bug fixes and improvements COLMAP 3.0 (5/22/2017) ---------------------- - Add automatic end-to-end reconstruction tool that automatically performs sparse and dense reconstruction on a given set of images - Add multi-GPU dense stereo if multiple CUDA devices are available - Add multi-GPU feature matching if multiple CUDA devices are available - Add Manhattan-world / gravity alignment using line detection - Add CUDA-based feature extraction useful for usage on clusters - Add CPU-based feature matching for machines without GPU - Add new THIN_PRISM_FISHEYE camera model with tangential/radial correction - Add binary to triangulate existing/empty sparse reconstruction - Add binary to print summary statistics about sparse reconstruction - Add transitive feature matching to transitively complete match graph - Improved scalability of dense reconstruction by using caching - More stable GPU-based feature matching with informative warnings - Faster vocabulary tree matching using dynamic scheduling in FLANN - Faster spatial feature matching using linear index instead of kd-tree - More stable camera undistortion using numerical Newton iteration - Improved option parsing with some backwards incompatible option renaming - Faster compile times by optimizing includes and CUDA flags - More stable view selection for small baseline scenario in dense reconstruction - Many more bug fixes and improvements COLMAP 2.1 (12/7/2016) ---------------------- - Support to only index and match specific images in vocabulary tree matching - Support to perform image retrieval using vocabulary tree - Several bug fixes and improvements for multi-view stereo module - Improved Structure-from-Motion initialization strategy - Support to only reconstruct the scene using specific images in the database - Add support to merge two models using overlapping registered images - Add support to geo-register/align models using known camera locations - Support to only extract specific images in feature extraction module - Support for snapshot model export during reconstruction - Skip already undistorted images if they exist in output directory - Support to limit the number of features in image retrieval for improved speed - Miscellaneous bug fixes and improvements COLMAP 2.0 (9/8/2016) --------------------- - Implementation of dense reconstruction pipeline - Improved feature matching performance - New bundle adjuster for rigidly mounted multi-camera systems - New generalized absolute pose solver for multi-camera systems - New executable to extract colors from all images - Boost can now be linked in shared and static mode - Various bug fixes and performance improvements COLMAP 1.1 (5/19/2016) ---------------------- - Implementation of state-of-the-art image retrieval system using Hamming embedding for vocabulary tree matching. This should lead to much improved matching results as compared to the previous implementation. - Guided matching as an optional functionality. - New demo datasets for download. - Automatically switch to PBA if supported by the project. - Implementation of EPNP solver for local pose optimization in RANSAC. - Add option to extract upright SIFT features. - Saving JPEGs in superb quality by default in export. - Add option to clear matches and inlier matches in the project. - New fisheye camera models, including the FOV camera model used by Google Project Tango (Thomas Schoeps). - Extended documentation based on user feedback. - Fixed typo in documentation (Thomas Schoeps). COLMAP 1.0 (4/4/2016) --------------------- - Initial release of COLMAP. colmap-3.10/CMakeLists.txt000066400000000000000000000335171464745566500155070ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. cmake_minimum_required(VERSION 3.10) ################################################################################ # Options ################################################################################ option(SIMD_ENABLED "Whether to enable SIMD optimizations" ON) option(OPENMP_ENABLED "Whether to enable OpenMP parallelization" ON) option(IPO_ENABLED "Whether to enable interprocedural optimization" ON) option(CUDA_ENABLED "Whether to enable CUDA, if available" ON) option(GUI_ENABLED "Whether to enable the graphical UI" ON) option(OPENGL_ENABLED "Whether to enable OpenGL, if available" ON) option(TESTS_ENABLED "Whether to build test binaries" OFF) option(ASAN_ENABLED "Whether to enable AddressSanitizer flags" OFF) option(PROFILING_ENABLED "Whether to enable google-perftools linker flags" OFF) option(CCACHE_ENABLED "Whether to enable compiler caching, if available" ON) option(CGAL_ENABLED "Whether to enable the CGAL library" ON) option(LSD_ENABLED "Whether to enable the LSD library" ON) option(UNINSTALL_ENABLED "Whether to create a target to 'uninstall' colmap" ON) # Propagate options to vcpkg manifest. if(TESTS_ENABLED) enable_testing() list(APPEND VCPKG_MANIFEST_FEATURES "tests") endif() if(CUDA_ENABLED) list(APPEND VCPKG_MANIFEST_FEATURES "cuda") endif() if(GUI_ENABLED) list(APPEND VCPKG_MANIFEST_FEATURES "gui") endif() if(CGAL_ENABLED) list(APPEND VCPKG_MANIFEST_FEATURES "cgal") endif() if(LSD_ENABLED) message(STATUS "Enabling LSD support") add_definitions("-DCOLMAP_LSD_ENABLED") else() message(STATUS "Disabling LSD support") endif() project(COLMAP LANGUAGES C CXX) set(COLMAP_VERSION "3.10-dev") set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CUDA_STANDARD 14) set(CMAKE_CUDA_STANDARD_REQUIRED ON) set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON) ################################################################################ # Include CMake dependencies ################################################################################ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(CheckCXXCompilerFlag) # Include helper macros and commands, and allow the included file to override # the CMake policies in this file include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeHelper.cmake NO_POLICY_SCOPE) # Build position-independent code, so that shared libraries can link against # COLMAP's static libraries. set(CMAKE_POSITION_INDEPENDENT_CODE ON) ################################################################################ # Dependency configuration ################################################################################ set(COLMAP_FIND_QUIETLY FALSE) include(cmake/FindDependencies.cmake) ################################################################################ # Compiler specific configuration ################################################################################ if(CMAKE_BUILD_TYPE) message(STATUS "Build type specified as ${CMAKE_BUILD_TYPE}") else() message(STATUS "Build type not specified, using Release") set(CMAKE_BUILD_TYPE Release) set(IS_DEBUG OFF) endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "ClangTidy") find_program(CLANG_TIDY_EXE NAMES clang-tidy) if(NOT CLANG_TIDY_EXE) message(FATAL_ERROR "Could not find the clang-tidy executable, please set CLANG_TIDY_EXE") endif() else() unset(CLANG_TIDY_EXE) endif() if(IS_MSVC) # Some fixes for the Glog library. add_definitions("-DGLOG_USE_GLOG_EXPORT") add_definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") add_definitions("-DGL_GLEXT_PROTOTYPES") add_definitions("-DNOMINMAX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") # Disable warning: 'initializing': conversion from 'X' to 'Y', possible loss of data set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4267 /wd4305") # Enable object level parallel builds in Visual Studio. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") endif() endif() if(IS_GNU) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) message(FATAL_ERROR "GCC version 4.8 or older not supported") endif() # Hide incorrect warnings for uninitialized Eigen variables under GCC. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-maybe-uninitialized") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-maybe-uninitialized") endif() if(IS_DEBUG) add_definitions("-DEIGEN_INITIALIZE_MATRICES_BY_NAN") endif() if(SIMD_ENABLED) message(STATUS "Enabling SIMD support") else() message(STATUS "Disabling SIMD support") endif() if(IPO_ENABLED AND NOT IS_DEBUG AND NOT IS_GNU) message(STATUS "Enabling interprocedural optimization") set_property(DIRECTORY PROPERTY INTERPROCEDURAL_OPTIMIZATION 1) else() message(STATUS "Disabling interprocedural optimization") endif() if(ASAN_ENABLED) message(STATUS "Enabling ASan support") if(IS_CLANG OR IS_GNU) add_compile_options(-fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope) add_link_options(-fsanitize=address) else() message(FATAL_ERROR "Unsupported compiler for ASan mode") endif() endif() if(CCACHE_ENABLED) find_program(CCACHE ccache) if(CCACHE) message(STATUS "Enabling ccache support") set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE}) set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) else() message(STATUS "Disabling ccache support") endif() else() message(STATUS "Disabling ccache support") endif() if(PROFILING_ENABLED) message(STATUS "Enabling profiling support") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lprofiler -ltcmalloc") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lprofiler -ltcmalloc") else() message(STATUS "Disabling profiling support") endif() ################################################################################ # Add sources ################################################################################ # Generate source file with version definitions. include(GenerateVersionDefinitions) include_directories(src) link_directories(${COLMAP_LINK_DIRS}) add_subdirectory(src/colmap) add_subdirectory(src/thirdparty) ################################################################################ # Generate source groups for Visual Studio, XCode, etc. ################################################################################ COLMAP_ADD_SOURCE_DIR(src/colmap/controllers CONTROLLERS_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/estimators ESTIMATORS_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/exe EXE_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/feature FEATURE_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/geometry GEOMETRY_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/image IMAGE_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/math MATH_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/mvs MVS_SRCS *.h *.cc *.cu) COLMAP_ADD_SOURCE_DIR(src/colmap/optim OPTIM_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/retrieval RETRIEVAL_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/scene SCENE_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/sensor SENSOR_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/sfm SFM_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/tools TOOLS_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/ui UI_SRCS *.h *.cc) COLMAP_ADD_SOURCE_DIR(src/colmap/util UTIL_SRCS *.h *.cc) if(LSD_ENABLED) COLMAP_ADD_SOURCE_DIR(src/thirdparty/LSD THIRDPARTY_LSD_SRCS *.h *.c) endif() COLMAP_ADD_SOURCE_DIR(src/thirdparty/PoissonRecon THIRDPARTY_POISSON_RECON_SRCS *.h *.cpp *.inl) COLMAP_ADD_SOURCE_DIR(src/thirdparty/SiftGPU THIRDPARTY_SIFT_GPU_SRCS *.h *.cpp *.cu) COLMAP_ADD_SOURCE_DIR(src/thirdparty/VLFeat THIRDPARTY_VLFEAT_SRCS *.h *.c *.tc) # Add all of the source files to a regular library target, as using a custom # target does not allow us to set its C++ include directories (and thus # intellisense can't find any of the included files). set(ALL_SRCS ${CONTROLLERS_SRCS} ${ESTIMATORS_SRCS} ${EXE_SRCS} ${FEATURE_SRCS} ${GEOMETRY_SRCS} ${IMAGE_SRCS} ${MATH_SRCS} ${MVS_SRCS} ${OPTIM_SRCS} ${RETRIEVAL_SRCS} ${SCENE_SRCS} ${SENSOR_SRCS} ${SFM_SRCS} ${TOOLS_SRCS} ${UI_SRCS} ${UTIL_SRCS} ${THIRDPARTY_POISSON_RECON_SRCS} ${THIRDPARTY_SIFT_GPU_SRCS} ${THIRDPARTY_VLFEAT_SRCS} ) if(LSD_ENABLED) list(APPEND ALL_SRCS ${THIRDPARTY_LSD_SRCS} ) endif() add_library( ${COLMAP_SRC_ROOT_FOLDER} ${ALL_SRCS} ) # Prevent the library from being compiled automatically. set_target_properties( ${COLMAP_SRC_ROOT_FOLDER} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) ################################################################################ # Install and uninstall scripts ################################################################################ # Install batch scripts under Windows. if(IS_MSVC) install(FILES "scripts/shell/COLMAP.bat" "scripts/shell/RUN_TESTS.bat" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION "/") endif() # Install application meny entry under Linux/Unix. if(UNIX AND NOT APPLE) install(FILES "doc/COLMAP.desktop" DESTINATION "share/applications") endif() # Configure the uninstallation script. if(UNINSTALL_ENABLED) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeUninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake) set_target_properties(uninstall PROPERTIES FOLDER ${CMAKE_TARGETS_ROOT_FOLDER}) endif() set(COLMAP_EXPORT_LIBS # Internal. colmap_controllers colmap_estimators colmap_exe colmap_feature_types colmap_feature colmap_geometry colmap_image colmap_math colmap_mvs colmap_optim colmap_retrieval colmap_scene colmap_sensor colmap_sfm colmap_util # Third-party. colmap_poisson_recon colmap_vlfeat ) if(LSD_ENABLED) list(APPEND COLMAP_EXPORT_LIBS # Third-party. colmap_lsd ) endif() if(GUI_ENABLED) list(APPEND COLMAP_EXPORT_LIBS colmap_ui ) endif() if(CUDA_ENABLED) list(APPEND COLMAP_EXPORT_LIBS colmap_util_cuda colmap_mvs_cuda ) endif() if(GPU_ENABLED) list(APPEND COLMAP_EXPORT_LIBS colmap_sift_gpu ) endif() # Add unified interface library target to export. add_library(colmap INTERFACE) target_link_libraries(colmap INTERFACE ${COLMAP_EXPORT_LIBS}) set(INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") target_include_directories( colmap INTERFACE $ $) install( TARGETS colmap ${COLMAP_EXPORT_LIBS} EXPORT colmap-targets LIBRARY DESTINATION thirdparty/) # Generate config and version. include(CMakePackageConfigHelpers) set(PACKAGE_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/colmap-config.cmake") set(INSTALL_CONFIG_DIR "share/colmap") configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/colmap-config.cmake.in ${PACKAGE_CONFIG_FILE} INSTALL_DESTINATION ${INSTALL_CONFIG_DIR}) install(FILES ${PACKAGE_CONFIG_FILE} DESTINATION ${INSTALL_CONFIG_DIR}) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/colmap-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/colmap-config-version.cmake" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/colmap-config-version.cmake" DESTINATION "share/colmap") # Install targets. install( EXPORT colmap-targets FILE colmap-targets.cmake NAMESPACE colmap:: DESTINATION ${INSTALL_CONFIG_DIR}) # Install header files. install( DIRECTORY src/colmap DESTINATION include FILES_MATCHING PATTERN "*.h") install( DIRECTORY src/thirdparty DESTINATION include/colmap FILES_MATCHING REGEX ".*[.]h|.*[.]hpp|.*[.]inl") # Install find_package scripts for dependencies. install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake DESTINATION share/colmap FILES_MATCHING PATTERN "Find*.cmake") colmap-3.10/CONTRIBUTING.md000066400000000000000000000010721464745566500151670ustar00rootroot00000000000000Contributing ------------ Contributions (bug reports, bug fixes, improvements, etc.) are very welcome and should be submitted in the form of new issues and/or pull requests on GitHub. Please, adhere to the Google coding style guide: https://google.github.io/styleguide/cppguide.html by using the provided ".clang-format" file. Document code, functions, methods, classes, etc. Make sure to add unit tests for all newly added code and make sure that algorithmic "improvements" generalize and actually improve the results of the pipeline on a variety of datasets. colmap-3.10/COPYING.txt000066400000000000000000000035721464745566500146160ustar00rootroot00000000000000The COLMAP library is licensed under the new BSD license. Note that this text refers only to the license for COLMAP itself, independent of its dependencies, which are separately licensed. Building COLMAP with these dependencies may affect the resulting COLMAP license. Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. colmap-3.10/README.md000066400000000000000000000126541464745566500142250ustar00rootroot00000000000000COLMAP ====== About ----- COLMAP is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface. It offers a wide range of features for reconstruction of ordered and unordered image collections. The software is licensed under the new BSD license. If you use this project for your research, please cite: @inproceedings{schoenberger2016sfm, author={Sch\"{o}nberger, Johannes Lutz and Frahm, Jan-Michael}, title={Structure-from-Motion Revisited}, booktitle={Conference on Computer Vision and Pattern Recognition (CVPR)}, year={2016}, } @inproceedings{schoenberger2016mvs, author={Sch\"{o}nberger, Johannes Lutz and Zheng, Enliang and Pollefeys, Marc and Frahm, Jan-Michael}, title={Pixelwise View Selection for Unstructured Multi-View Stereo}, booktitle={European Conference on Computer Vision (ECCV)}, year={2016}, } If you use the image retrieval / vocabulary tree engine, please also cite: @inproceedings{schoenberger2016vote, author={Sch\"{o}nberger, Johannes Lutz and Price, True and Sattler, Torsten and Frahm, Jan-Michael and Pollefeys, Marc}, title={A Vote-and-Verify Strategy for Fast Spatial Verification in Image Retrieval}, booktitle={Asian Conference on Computer Vision (ACCV)}, year={2016}, } The latest source code is available at https://github.com/colmap/colmap. COLMAP builds on top of existing works and when using specific algorithms within COLMAP, please also cite the original authors, as specified in the source code, and consider citing relevant third-party dependencies. Download -------- * Binaries for **Windows** and other resources can be downloaded from https://github.com/colmap/colmap/releases. * Binaries for **Linux/Unix/BSD** are available at https://repology.org/metapackage/colmap/versions. * Pre-built **Docker** images are available at https://hub.docker.com/r/colmap/colmap. * **Python bindings** are available at https://pypi.org/project/pycolmap. * To **build from source**, please see https://colmap.github.io/install.html. Getting Started --------------- 1. Download pre-built binaries or build from source. 2. Download one of the provided datasets at https://demuc.de/colmap/datasets/ or use your own images. 3. Use the **automatic reconstruction** to easily build models with a single click or command. Documentation ------------- The documentation is available at https://colmap.github.io/. Support ------- Please, use GitHub Discussions at https://github.com/colmap/colmap/discussions for questions and the GitHub issue tracker at https://github.com/colmap/colmap for bug reports, feature requests/additions, etc. Acknowledgments --------------- COLMAP was originally written by [Johannes Schönberger](https://demuc.de/) with funding provided by his PhD advisors Jan-Michael Frahm and Marc Pollefeys. The Python bindings in PyCOLMAP were originally added by [Mihai Dusmanu](https://github.com/mihaidusmanu), [Philipp Lindenberger](https://github.com/Phil26AT), and [Paul-Edouard Sarlin](https://github.com/Skydes). The project has also benefitted from countless community contributions, including bug fixes, improvements, new features, third-party tooling, and community support (special credits to [Torsten Sattler](https://tsattler.github.io)). Contribution ------------ Contributions (bug reports, bug fixes, improvements, etc.) are very welcome and should be submitted in the form of new issues and/or pull requests on GitHub. License ------- The COLMAP library is licensed under the new BSD license. Note that this text refers only to the license for COLMAP itself, independent of its thirdparty dependencies, which are separately licensed. Building COLMAP with these dependencies may affect the resulting COLMAP license. Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. colmap-3.10/benchmark/000077500000000000000000000000001464745566500146705ustar00rootroot00000000000000colmap-3.10/benchmark/CMakeLists.txt000066400000000000000000000004301464745566500174250ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.10) project(colmap_benchmarks) find_package(colmap REQUIRED) find_package(benchmark REQUIRED) add_executable(benchmark_cost_functions cost_functions.cc) target_link_libraries(benchmark_cost_functions PRIVATE colmap::colmap benchmark::benchmark) colmap-3.10/benchmark/README.md000066400000000000000000000010211464745566500161410ustar00rootroot00000000000000# Benchmarking ## Installation 1. Install [google/benchmark](https://github.com/google/benchmark). 2. Build the benchmarking executables: ```bash mkdir build && cd build cmake .. -GNinja && ninja ``` To reduce the variance, consider setting up your system appropriately [following these instructions](https://github.com/google/benchmark/blob/main/docs/reducing_variance.md). ## Running the benchmarks Cost functions: ```bash ./benchmark_cost_functions --benchmark_display_aggregates_only=true --benchmark_repetitions=50 ``` colmap-3.10/benchmark/cost_functions.cc000066400000000000000000000070711464745566500202440ustar00rootroot00000000000000#include "colmap/estimators/cost_functions.h" #include "colmap/geometry/rigid3.h" #include "colmap/sensor/models.h" #include "colmap/util/eigen_alignment.h" #include "colmap/util/logging.h" #include #include using namespace colmap; using camera_model = SimpleRadialCameraModel; struct ReprojErrorData { Rigid3d cam_from_world; Eigen::Vector3d point3D; Eigen::Vector2d point2D; std::vector camera_params; }; static ReprojErrorData CreateReprojErrorData() { ReprojErrorData data{ Rigid3d(Eigen::Quaterniond(0.9, 0.1, 0.1, 0.1), Eigen::Vector3d::Zero()), Eigen::Vector3d(1, 2, 10), Eigen::Vector2d(0.1, 0.2), {1, 0, 0, 0.1}, }; CHECK_EQ(data.camera_params.size(), camera_model::num_params); return std::move(data); } class BM_ReprojErrorCostFunction : public benchmark::Fixture { public: void SetUp(::benchmark::State& state) { cost_function.reset( ReprojErrorCostFunction::Create(data.point2D)); } ReprojErrorData data = CreateReprojErrorData(); const double* parameters[4] = {data.cam_from_world.rotation.coeffs().data(), data.cam_from_world.translation.data(), data.point3D.data(), data.camera_params.data()}; double residuals[2]; double jacobian_q[2 * 4]; double jacobian_t[2 * 3]; double jacobian_p[2 * 3]; double jacobian_params[2 * camera_model::num_params]; double* jacobians[4] = {jacobian_q, jacobian_t, jacobian_p, jacobian_params}; std::unique_ptr cost_function; }; BENCHMARK_F(BM_ReprojErrorCostFunction, Run)(benchmark::State& state) { for (auto _ : state) { cost_function->Evaluate(parameters, residuals, jacobians); } } class BM_ReprojErrorConstantPoseCostFunction : public benchmark::Fixture { public: void SetUp(::benchmark::State& state) { cost_function.reset( ReprojErrorConstantPoseCostFunction::Create( data.cam_from_world, data.point2D)); } ReprojErrorData data = CreateReprojErrorData(); const double* parameters[2] = {data.point3D.data(), data.camera_params.data()}; double residuals[2]; double jacobian_p[2 * 3]; double jacobian_params[2 * camera_model::num_params]; double* jacobians[2] = {jacobian_p, jacobian_params}; std::unique_ptr cost_function; }; BENCHMARK_F(BM_ReprojErrorConstantPoseCostFunction, Run) (benchmark::State& state) { for (auto _ : state) { cost_function->Evaluate(parameters, residuals, jacobians); } } class BM_ReprojErrorConstantPoint3DCostFunction : public benchmark::Fixture { public: void SetUp(::benchmark::State& state) { cost_function.reset( ReprojErrorConstantPoint3DCostFunction::Create( data.point2D, data.point3D)); } ReprojErrorData data = CreateReprojErrorData(); const double* parameters[3] = {data.cam_from_world.rotation.coeffs().data(), data.cam_from_world.translation.data(), data.camera_params.data()}; double residuals[2]; double jacobian_q[2 * 4]; double jacobian_t[2 * 3]; double jacobian_params[2 * camera_model::num_params]; double* jacobians[3] = {jacobian_q, jacobian_t, jacobian_params}; std::unique_ptr cost_function; }; BENCHMARK_F(BM_ReprojErrorConstantPoint3DCostFunction, Run) (benchmark::State& state) { for (auto _ : state) { cost_function->Evaluate(parameters, residuals, jacobians); } } BENCHMARK_MAIN(); colmap-3.10/cmake/000077500000000000000000000000001464745566500140165ustar00rootroot00000000000000colmap-3.10/cmake/CMakeHelper.cmake000066400000000000000000000127751464745566500171540ustar00rootroot00000000000000if(POLICY CMP0043) cmake_policy(SET CMP0043 NEW) endif() if(POLICY CMP0054) cmake_policy(SET CMP0054 NEW) endif() # Determine project compiler. if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(IS_MSVC TRUE) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(IS_GNU TRUE) endif() if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") set(IS_CLANG TRUE) endif() # Determine project architecture. if(CMAKE_SYSTEM_PROCESSOR MATCHES "[ix].?86|amd64|AMD64") set(IS_X86 TRUE) endif() # Determine project operating system. string(REGEX MATCH "Linux" IS_LINUX ${CMAKE_SYSTEM_NAME}) string(REGEX MATCH "DragonFly|BSD" IS_BSD ${CMAKE_SYSTEM_NAME}) string(REGEX MATCH "SunOS" IS_SOLARIS ${CMAKE_SYSTEM_NAME}) if(WIN32) set(IS_WINDOWS TRUE BOOL INTERNAL) endif() if(APPLE) set(IS_MACOS TRUE BOOL INTERNAL) endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug" OR CMAKE_BUILD_TYPE_LOWER STREQUAL "relwithdebinfo") set(IS_DEBUG TRUE) endif() # Enable solution folders. set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(CMAKE_TARGETS_ROOT_FOLDER "cmake") set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER ${CMAKE_TARGETS_ROOT_FOLDER}) set(COLMAP_TARGETS_ROOT_FOLDER "colmap_targets") set(COLMAP_SRC_ROOT_FOLDER "colmap_sources") # This macro will search for source files in a given directory, will add them # to a source group (folder within a project), and will then return paths to # each of the found files. The usage of the macro is as follows: # COLMAP_ADD_SOURCE_DIR( # # # ) macro(COLMAP_ADD_SOURCE_DIR SRC_DIR SRC_VAR) # Create the list of expressions to be used in the search. set(GLOB_EXPRESSIONS "") foreach(ARG ${ARGN}) list(APPEND GLOB_EXPRESSIONS ${SRC_DIR}/${ARG}) endforeach() # Perform the search for the source files. file(GLOB ${SRC_VAR} RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOB_EXPRESSIONS}) # Create the source group. string(REPLACE "/" "\\" GROUP_NAME ${SRC_DIR}) source_group(${GROUP_NAME} FILES ${${SRC_VAR}}) # Clean-up. unset(GLOB_EXPRESSIONS) unset(ARG) unset(GROUP_NAME) endmacro(COLMAP_ADD_SOURCE_DIR) # Replacement for the normal add_library() command. The syntax remains the same # in that the first argument is the target name, and the following arguments # are the source files to use when building the target. macro(COLMAP_ADD_LIBRARY) set(options) set(oneValueArgs) set(multiValueArgs NAME SRCS PRIVATE_LINK_LIBS PUBLIC_LINK_LIBS) cmake_parse_arguments(COLMAP_ADD_LIBRARY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) add_library(${COLMAP_ADD_LIBRARY_NAME} STATIC ${COLMAP_ADD_LIBRARY_SRCS}) set_target_properties(${COLMAP_ADD_LIBRARY_NAME} PROPERTIES FOLDER ${COLMAP_TARGETS_ROOT_FOLDER}/${FOLDER_NAME}) if(CLANG_TIDY_EXE) set_target_properties(${COLMAP_ADD_LIBRARY_NAME} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-header-filter=.*") endif() target_link_libraries(${COLMAP_ADD_LIBRARY_NAME} PRIVATE ${COLMAP_ADD_LIBRARY_PRIVATE_LINK_LIBS} PUBLIC ${COLMAP_ADD_LIBRARY_PUBLIC_LINK_LIBS}) endmacro(COLMAP_ADD_LIBRARY) # Replacement for the normal add_executable() command. The syntax remains the # same in that the first argument is the target name, and the following # arguments are the source files to use when building the target. macro(COLMAP_ADD_EXECUTABLE) set(options) set(oneValueArgs) set(multiValueArgs NAME SRCS LINK_LIBS) cmake_parse_arguments(COLMAP_ADD_EXECUTABLE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) add_executable(${COLMAP_ADD_EXECUTABLE_NAME} ${COLMAP_ADD_EXECUTABLE_SRCS}) set_target_properties(${COLMAP_ADD_EXECUTABLE_NAME} PROPERTIES FOLDER ${COLMAP_TARGETS_ROOT_FOLDER}/${FOLDER_NAME}) target_link_libraries(${COLMAP_ADD_EXECUTABLE_NAME} ${COLMAP_ADD_EXECUTABLE_LINK_LIBS}) if(VCPKG_BUILD) install(TARGETS ${COLMAP_ADD_EXECUTABLE_NAME} DESTINATION tools/) else() install(TARGETS ${COLMAP_ADD_EXECUTABLE_NAME} DESTINATION bin/) endif() if(CLANG_TIDY_EXE) set_target_properties(${COLMAP_ADD_EXECUTABLE_NAME} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-header-filter=.*") endif() endmacro(COLMAP_ADD_EXECUTABLE) # Wrapper for test executables. macro(COLMAP_ADD_TEST) set(options) set(oneValueArgs) set(multiValueArgs NAME SRCS LINK_LIBS) cmake_parse_arguments(COLMAP_ADD_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(TESTS_ENABLED) # ${ARGN} will store the list of link libraries. set(COLMAP_ADD_TEST_NAME "colmap_${FOLDER_NAME}_${COLMAP_ADD_TEST_NAME}") add_executable(${COLMAP_ADD_TEST_NAME} ${COLMAP_ADD_TEST_SRCS}) set_target_properties(${COLMAP_ADD_TEST_NAME} PROPERTIES FOLDER ${COLMAP_TARGETS_ROOT_FOLDER}/${FOLDER_NAME}) if(CLANG_TIDY_EXE) set_target_properties(${COLMAP_ADD_TEST_NAME} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-header-filter=.*") endif() target_link_libraries(${COLMAP_ADD_TEST_NAME} ${COLMAP_ADD_TEST_LINK_LIBS} GTest::gtest GTest::gtest_main) add_test("${FOLDER_NAME}/${COLMAP_ADD_TEST_NAME}" ${COLMAP_ADD_TEST_NAME}) if(IS_MSVC) install(TARGETS ${COLMAP_ADD_TEST_NAME} DESTINATION bin/) endif() endif() endmacro(COLMAP_ADD_TEST) colmap-3.10/cmake/CMakeUninstall.cmake.in000066400000000000000000000015331464745566500203010ustar00rootroot00000000000000if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif() file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif() else() message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif() endforeach() colmap-3.10/cmake/FindDependencies.cmake000066400000000000000000000154011464745566500202100ustar00rootroot00000000000000if(COLMAP_FIND_QUIETLY) set(COLMAP_FIND_TYPE QUIET) else() set(COLMAP_FIND_TYPE REQUIRED) endif() find_package(Boost ${COLMAP_FIND_TYPE} COMPONENTS filesystem graph program_options system) find_package(Eigen3 ${COLMAP_FIND_TYPE}) find_package(FreeImage ${COLMAP_FIND_TYPE}) find_package(FLANN ${COLMAP_FIND_TYPE}) find_package(LZ4 ${COLMAP_FIND_TYPE}) find_package(Metis ${COLMAP_FIND_TYPE}) find_package(Glog ${COLMAP_FIND_TYPE}) if(DEFINED glog_VERSION_MAJOR) # Older versions of glog don't export version variables. add_definitions("-DGLOG_VERSION_MAJOR=${glog_VERSION_MAJOR}") add_definitions("-DGLOG_VERSION_MINOR=${glog_VERSION_MINOR}") endif() find_package(SQLite3 ${COLMAP_FIND_TYPE}) set(OpenGL_GL_PREFERENCE GLVND) find_package(OpenGL ${COLMAP_FIND_TYPE}) find_package(Glew ${COLMAP_FIND_TYPE}) find_package(Git) find_package(Ceres ${COLMAP_FIND_TYPE}) if(NOT TARGET Ceres::ceres) # Older Ceres versions don't come with an imported interface target. add_library(Ceres::ceres INTERFACE IMPORTED) target_include_directories( Ceres::ceres INTERFACE ${CERES_INCLUDE_DIRS}) target_link_libraries( Ceres::ceres INTERFACE ${CERES_LIBRARIES}) endif() if(TESTS_ENABLED) find_package(GTest ${COLMAP_FIND_TYPE}) endif() if(OPENMP_ENABLED) find_package(OpenMP QUIET) endif() if(OPENMP_ENABLED AND OPENMP_FOUND) message(STATUS "Enabling OpenMP support") add_definitions("-DCOLMAP_OPENMP_ENABLED") else() message(STATUS "Disabling OpenMP support") endif() if(CGAL_ENABLED) set(CGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE TRUE) # We do not use CGAL data. This prevents an unnecessary warning by CMake. set(CGAL_DATA_DIR "unused") find_package(CGAL ${COLMAP_FIND_TYPE}) endif() if(CGAL_FOUND) add_definitions("-DCOLMAP_CGAL_ENABLED") list(APPEND CGAL_LIBRARY ${CGAL_LIBRARIES}) message(STATUS "Found CGAL") message(STATUS " Includes : ${CGAL_INCLUDE_DIRS}") message(STATUS " Libraries : ${CGAL_LIBRARY}") if(NOT TARGET CGAL) # Older CGAL versions don't come with an imported interface target. add_library(CGAL INTERFACE IMPORTED) target_include_directories( CGAL INTERFACE ${CGAL_INCLUDE_DIRS} ${GMP_INCLUDE_DIR}) target_link_libraries( CGAL INTERFACE ${CGAL_LIBRARY} ${GMP_LIBRARIES}) endif() list(APPEND COLMAP_LINK_DIRS ${CGAL_LIBRARIES_DIR}) endif() set(COLMAP_LINK_DIRS ${Boost_LIBRARY_DIRS}) set(CUDA_MIN_VERSION "7.0") if(CUDA_ENABLED) if(CMAKE_VERSION VERSION_LESS 3.17) find_package(CUDA QUIET) if(CUDA_FOUND) message(STATUS "Found CUDA version ${CUDA_VERSION} installed in " "${CUDA_TOOLKIT_ROOT_DIR} via legacy CMake (<3.17) module. " "Using the legacy CMake module means that any installation of " "COLMAP will require that the CUDA libraries are " "available under LD_LIBRARY_PATH.") message(STATUS "Found CUDA ") message(STATUS " Includes : ${CUDA_INCLUDE_DIRS}") message(STATUS " Libraries : ${CUDA_LIBRARIES}") enable_language(CUDA) macro(declare_imported_cuda_target module) add_library(CUDA::${module} INTERFACE IMPORTED) target_include_directories( CUDA::${module} INTERFACE ${CUDA_INCLUDE_DIRS}) target_link_libraries( CUDA::${module} INTERFACE ${CUDA_${module}_LIBRARY} ${ARGN}) endmacro() declare_imported_cuda_target(cudart ${CUDA_LIBRARIES}) declare_imported_cuda_target(curand ${CUDA_LIBRARIES}) set(CUDAToolkit_VERSION "${CUDA_VERSION_STRING}") set(CUDAToolkit_BIN_DIR "${CUDA_TOOLKIT_ROOT_DIR}/bin") else() message(STATUS "CUDA not found") endif() else() find_package(CUDAToolkit QUIET) if(CUDAToolkit_FOUND) set(CUDA_FOUND ON) enable_language(CUDA) else() message(STATUS "CUDA not found") endif() endif() endif() if(CUDA_ENABLED AND CUDA_FOUND) if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) set(CMAKE_CUDA_ARCHITECTURES "native") endif() add_definitions("-DCOLMAP_CUDA_ENABLED") # Do not show warnings if the architectures are deprecated. set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets") # Explicitly set PIC flags for CUDA targets. if(NOT IS_MSVC) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --compiler-options -fPIC") endif() message(STATUS "Enabling CUDA support (version: ${CUDAToolkit_VERSION}, " "archs: ${CMAKE_CUDA_ARCHITECTURES})") else() set(CUDA_ENABLED OFF) message(STATUS "Disabling CUDA support") endif() if(GUI_ENABLED) find_package(Qt5 5.4 ${COLMAP_FIND_TYPE} COMPONENTS Core OpenGL Widgets) message(STATUS "Found Qt") message(STATUS " Module : ${Qt5Core_DIR}") message(STATUS " Module : ${Qt5OpenGL_DIR}") message(STATUS " Module : ${Qt5Widgets_DIR}") if(Qt5_FOUND) # Qt5 was built with -reduce-relocations. if(Qt5_POSITION_INDEPENDENT_CODE) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Workaround for Qt5 CMake config bug under Ubuntu 20.04: https://gitlab.kitware.com/cmake/cmake/-/issues/16915 if(TARGET Qt5::Core) get_property(core_options TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_OPTIONS) string(REPLACE "-fPIC" "" new_qt5_core_options "${core_options}") set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_OPTIONS ${new_qt5_core_options}) set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE "ON") if(NOT IS_MSVC) set(CMAKE_CXX_COMPILE_OPTIONS_PIE "-fPIC") endif() endif() endif() # Enable automatic compilation of Qt resource files. set(CMAKE_AUTORCC ON) endif() endif() if(GUI_ENABLED AND Qt5_FOUND) add_definitions("-DCOLMAP_GUI_ENABLED") message(STATUS "Enabling GUI support") else() set(GUI_ENABLED OFF) message(STATUS "Disabling GUI support") endif() if(OPENGL_ENABLED) if(NOT GUI_ENABLED) message(STATUS "Disabling GUI also disables OpenGL") set(OPENGL_ENABLED OFF) else() add_definitions("-DCOLMAP_OPENGL_ENABLED") message(STATUS "Enabling OpenGL support") endif() else() message(STATUS "Disabling OpenGL support") endif() set(GPU_ENABLED OFF) if(OPENGL_ENABLED OR CUDA_ENABLED) add_definitions("-DCOLMAP_GPU_ENABLED") message(STATUS "Enabling GPU support (OpenGL: ${OPENGL_ENABLED}, CUDA: ${CUDA_ENABLED})") set(GPU_ENABLED ON) endif() colmap-3.10/cmake/FindFLANN.cmake000066400000000000000000000063671464745566500164730ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for FLANN library. # # The following variables are set by this module: # # FLANN_FOUND: TRUE if FLANN is found. # flann: Imported target to link against. # # The following variables control the behavior of this module: # # FLANN_INCLUDE_DIR_HINTS: List of additional directories in which to # search for FLANN includes. # FLANN_LIBRARY_DIR_HINTS: List of additional directories in which to # search for FLANN libraries. set(FLANN_INCLUDE_DIR_HINTS "" CACHE PATH "FLANN include directory") set(FLANN_LIBRARY_DIR_HINTS "" CACHE PATH "FLANN library directory") unset(FLANN_FOUND) unset(FLANN_INCLUDE_DIRS) unset(FLANN_LIBRARIES) list(APPEND FLANN_CHECK_INCLUDE_DIRS ${FLANN_INCLUDE_DIR_HINTS} /usr/include /usr/local/include /opt/include /opt/local/include ) list(APPEND FLANN_CHECK_LIBRARY_DIRS ${FLANN_LIBRARY_DIR_HINTS} /usr/lib /usr/local/lib /opt/lib /opt/local/lib ) find_path(FLANN_INCLUDE_DIRS NAMES flann/flann.hpp PATHS ${FLANN_CHECK_INCLUDE_DIRS}) find_library(FLANN_LIBRARIES NAMES flann PATHS ${FLANN_CHECK_LIBRARY_DIRS}) if(FLANN_INCLUDE_DIRS AND FLANN_LIBRARIES) set(FLANN_FOUND TRUE) endif() if(FLANN_FOUND) message(STATUS "Found FLANN") message(STATUS " Includes : ${FLANN_INCLUDE_DIRS}") message(STATUS " Libraries : ${FLANN_LIBRARIES}") else() if(FLANN_FIND_REQUIRED) message(FATAL_ERROR "Could not find FLANN") endif() endif() add_library(flann INTERFACE IMPORTED) target_include_directories( flann INTERFACE ${FLANN_INCLUDE_DIRS}) target_link_libraries( flann INTERFACE ${FLANN_LIBRARIES}) colmap-3.10/cmake/FindFreeImage.cmake000066400000000000000000000074261464745566500174560ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for FreeImage library. # # The following variables are set by this module: # # FREEIMAGE_FOUND: TRUE if FreeImage is found. # freeimage::FreeImage: Imported target to link against. # # The following variables control the behavior of this module: # # FREEIMAGE_INCLUDE_DIR_HINTS: List of additional directories in which to # search for FreeImage includes. # FREEIMAGE_LIBRARY_DIR_HINTS: List of additional directories in which to # search for FreeImage libraries. set(FREEIMAGE_INCLUDE_DIR_HINTS "" CACHE PATH "FreeImage include directory") set(FREEIMAGE_LIBRARY_DIR_HINTS "" CACHE PATH "FreeImage library directory") unset(FREEIMAGE_FOUND) find_package(FreeImage CONFIG QUIET) if(FreeImage_FOUND) if(TARGET freeimage::FreeImage) set(FREEIMAGE_FOUND TRUE) message(STATUS "Found FreeImage") message(STATUS " Target : freeimage::FreeImage") endif() else() list(APPEND FREEIMAGE_CHECK_INCLUDE_DIRS ${FREEIMAGE_INCLUDE_DIR_HINTS} /usr/include /usr/local/include /opt/include /opt/local/include ) list(APPEND FREEIMAGE_CHECK_LIBRARY_DIRS ${FREEIMAGE_LIBRARY_DIR_HINTS} /usr/lib /usr/local/lib /opt/lib /opt/local/lib ) find_path(FREEIMAGE_INCLUDE_DIRS NAMES FreeImage.h PATHS ${FREEIMAGE_CHECK_INCLUDE_DIRS}) find_library(FREEIMAGE_LIBRARIES NAMES freeimage PATHS ${FREEIMAGE_CHECK_LIBRARY_DIRS}) if(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES) set(FREEIMAGE_FOUND TRUE) endif() if(FREEIMAGE_FOUND) message(STATUS "Found FreeImage") message(STATUS " Includes : ${FREEIMAGE_INCLUDE_DIRS}") message(STATUS " Libraries : ${FREEIMAGE_LIBRARIES}") endif() add_library(freeimage::FreeImage INTERFACE IMPORTED) target_include_directories( freeimage::FreeImage INTERFACE ${FREEIMAGE_INCLUDE_DIRS}) target_link_libraries( freeimage::FreeImage INTERFACE ${FREEIMAGE_LIBRARIES}) endif() if(NOT FREEIMAGE_FOUND AND FREEIMAGE_FIND_REQUIRED) message(FATAL_ERROR "Could not find FreeImage") endif() colmap-3.10/cmake/FindGlew.cmake000066400000000000000000000067671464745566500165370ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for Glew library. # # The following variables are set by this module: # # GLEW_FOUND: TRUE if Glew is found. # GLEW::GLEW: Imported target to link against. # # The following variables control the behavior of this module: # # GLEW_INCLUDE_DIR_HINTS: List of additional directories in which to # search for Glew includes. # GLEW_LIBRARY_DIR_HINTS: List of additional directories in which to # search for Glew libraries. set(GLEW_INCLUDE_DIR_HINTS "" CACHE PATH "Glew include directory") set(GLEW_LIBRARY_DIR_HINTS "" CACHE PATH "Glew library directory") unset(GLEW_FOUND) unset(GLEW_INCLUDE_DIRS) unset(GLEW_LIBRARIES) find_package(Glew CONFIG QUIET) if(TARGET GLEW::GLEW) set(GLEW_FOUND TRUE) message(STATUS "Found Glew") message(STATUS " Target : GLEW::GLEW") else() find_path(GLEW_INCLUDE_DIRS NAMES GL/glew.h PATHS ${GLEW_INCLUDE_DIR_HINTS} /usr/include /usr/local/include /sw/include /opt/include /opt/local/include) find_library(GLEW_LIBRARIES NAMES GLEW Glew glew glew32 PATHS ${GLEW_LIBRARY_DIR_HINTS} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /sw/lib /opt/lib /opt/local/lib) if(GLEW_INCLUDE_DIRS AND GLEW_LIBRARIES) set(GLEW_FOUND TRUE) message(STATUS "Found Glew") message(STATUS " Includes : ${GLEW_INCLUDE_DIRS}") message(STATUS " Libraries : ${GLEW_LIBRARIES}") else() set(GLEW_FOUND FALSE) endif() add_library(GLEW::GLEW INTERFACE IMPORTED) target_include_directories( GLEW::GLEW INTERFACE ${GLEW_INCLUDE_DIRS}) target_link_libraries( GLEW::GLEW INTERFACE ${GLEW_LIBRARIES}) endif() if(NOT GLEW_FOUND AND GLEW_FIND_REQUIRED) message(FATAL_ERROR "Could not find Glew") endif() colmap-3.10/cmake/FindGlog.cmake000066400000000000000000000101331464745566500165070ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for Glog library. # # The following variables are set by this module: # # GLOG_FOUND: TRUE if Glog is found. # glog::glog: Imported target to link against. # # The following variables control the behavior of this module: # # GLOG_INCLUDE_DIR_HINTS: List of additional directories in which to # search for Glog includes. # GLOG_LIBRARY_DIR_HINTS: List of additional directories in which to # search for Glog libraries. set(GLOG_INCLUDE_DIR_HINTS "" CACHE PATH "Glog include directory") set(GLOG_LIBRARY_DIR_HINTS "" CACHE PATH "Glog library directory") unset(GLOG_FOUND) find_package(glog CONFIG QUIET) if(TARGET glog::glog) set(GLOG_FOUND TRUE) message(STATUS "Found Glog") message(STATUS " Target : glog::glog") else() # Older versions of glog don't come with a find_package config. # Fall back to custom logic to find the library and remap to imported target. include(FindPackageHandleStandardArgs) list(APPEND GLOG_CHECK_INCLUDE_DIRS /usr/local/include /usr/local/homebrew/include /opt/local/var/macports/software /opt/local/include /usr/include) list(APPEND GLOG_CHECK_PATH_SUFFIXES glog/include glog/Include Glog/include Glog/Include src/windows) list(APPEND GLOG_CHECK_LIBRARY_DIRS /usr/local/lib /usr/local/homebrew/lib /opt/local/lib /usr/lib) list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES glog/lib glog/Lib Glog/lib Glog/Lib x64/Release) find_path(GLOG_INCLUDE_DIRS NAMES glog/logging.h PATHS ${GLOG_INCLUDE_DIR_HINTS} ${GLOG_CHECK_INCLUDE_DIRS} PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES}) find_library(GLOG_LIBRARIES NAMES glog libglog PATHS ${GLOG_LIBRARY_DIR_HINTS} ${GLOG_CHECK_LIBRARY_DIRS} PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES}) if(GLOG_INCLUDE_DIRS AND GLOG_LIBRARIES) set(GLOG_FOUND TRUE) message(STATUS "Found Glog") message(STATUS " Includes : ${GLOG_INCLUDE_DIRS}") message(STATUS " Libraries : ${GLOG_LIBRARIES}") endif() add_library(glog::glog INTERFACE IMPORTED) target_include_directories(glog::glog INTERFACE ${GLOG_INCLUDE_DIRS}) target_link_libraries(glog::glog INTERFACE ${GLOG_LIBRARIES}) endif() if(NOT GLOG_FOUND AND GLOG_FIND_REQUIRED) message(FATAL_ERROR "Could not find Glog") endif() colmap-3.10/cmake/FindLZ4.cmake000066400000000000000000000063731464745566500162430ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for LZ4 library. # # The following variables are set by this module: # # LZ4_FOUND: TRUE if LZ4 is found. # LZ4_INCLUDE_DIRS: Include directories for LZ4. # LZ4_LIBRARIES: Libraries required to link LZ4. # # The following variables control the behavior of this module: # # LZ4_INCLUDE_DIR_HINTS: List of additional directories in which to # search for LZ4 includes. # LZ4_LIBRARY_DIR_HINTS: List of additional directories in which to # search for LZ4 libraries. set(LZ4_INCLUDE_DIR_HINTS "" CACHE PATH "LZ4 include directory") set(LZ4_LIBRARY_DIR_HINTS "" CACHE PATH "LZ4 library directory") unset(LZ4_FOUND) unset(LZ4_INCLUDE_DIRS) unset(LZ4_LIBRARIES) list(APPEND LZ4_CHECK_INCLUDE_DIRS ${LZ4_INCLUDE_DIR_HINTS} /usr/include /usr/local/include /opt/include /opt/local/include ) list(APPEND LZ4_CHECK_LIBRARY_DIRS ${LZ4_LIBRARY_DIR_HINTS} /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu /opt/lib /opt/local/lib ) find_path(LZ4_INCLUDE_DIRS NAMES lz4.h PATHS ${LZ4_CHECK_INCLUDE_DIRS}) find_library(LZ4_LIBRARIES NAMES lz4 PATHS ${LZ4_CHECK_LIBRARY_DIRS}) if(LZ4_INCLUDE_DIRS AND LZ4_LIBRARIES) set(LZ4_FOUND TRUE) endif() if(LZ4_FOUND) message(STATUS "Found LZ4") message(STATUS " Includes : ${LZ4_INCLUDE_DIRS}") message(STATUS " Libraries : ${LZ4_LIBRARIES}") else() if(LZ4_FIND_REQUIRED) message(FATAL_ERROR "Could not find LZ4") endif() endif() add_library(lz4 INTERFACE IMPORTED) target_include_directories( lz4 INTERFACE ${LZ4_INCLUDE_DIRS}) target_link_libraries( lz4 INTERFACE ${LZ4_LIBRARIES}) colmap-3.10/cmake/FindMetis.cmake000066400000000000000000000071041464745566500167040ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package module for Metis library. # # The following variables are set by this module: # # METIS_FOUND: TRUE if Metis is found. # metis: Imported target to link against. # # The following variables control the behavior of this module: # # METIS_INCLUDE_DIR_HINTS: List of additional directories in which to # search for Metis includes. # METIS_LIBRARY_DIR_HINTS: List of additional directories in which to # search for Metis libraries. set(METIS_INCLUDE_DIR_HINTS "" CACHE PATH "Metis include directory") set(METIS_LIBRARY_DIR_HINTS "" CACHE PATH "Metis library directory") unset(METIS_FOUND) find_package(metis CONFIG QUIET) if(TARGET metis) set(METIS_FOUND TRUE) message(STATUS "Found Metis") message(STATUS " Target : metis") else() list(APPEND METIS_CHECK_INCLUDE_DIRS ${METIS_INCLUDE_DIR_HINTS} /usr/include /usr/local/include /opt/include /opt/local/include ) list(APPEND METIS_CHECK_LIBRARY_DIRS ${METIS_LIBRARY_DIR_HINTS} /usr/lib /usr/local/lib /opt/lib /opt/local/lib ) find_path(METIS_INCLUDE_DIRS NAMES metis.h PATHS ${METIS_CHECK_INCLUDE_DIRS}) find_library(METIS_LIBRARIES NAMES metis PATHS ${METIS_CHECK_LIBRARY_DIRS}) find_library(GK_LIBRARIES NAMES GKlib PATHS ${METIS_CHECK_LIBRARY_DIRS}) if(METIS_INCLUDE_DIRS AND METIS_LIBRARIES) set(METIS_FOUND TRUE) message(STATUS "Found Metis") message(STATUS " Includes : ${METIS_INCLUDE_DIRS}") message(STATUS " Libraries : ${METIS_LIBRARIES}") endif() add_library(metis INTERFACE IMPORTED) target_include_directories( metis INTERFACE ${METIS_INCLUDE_DIRS}) target_link_libraries( metis INTERFACE ${METIS_LIBRARIES}) endif() if(NOT METIS_FOUND AND METIS_FIND_REQUIRED) message(FATAL_ERROR "Could not find Metis") endif() colmap-3.10/cmake/GenerateVersionDefinitions.cmake000066400000000000000000000052761464745566500223260ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. if (DEFINED GIT_COMMIT_ID OR DEFINED GIT_COMMIT_DATE) message(STATUS "Using custom-defined GIT_COMMIT_ID (${GIT_COMMIT_ID}) " "and GIT_COMMIT_DATE (${GIT_COMMIT_DATE})") elseif(Git_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --short HEAD WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE GIT_COMMIT_ID ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND "${GIT_EXECUTABLE}" log -1 --format=%ad --date=short WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE GIT_COMMIT_DATE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) # Re-generate version.cc if the git index changes. set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/.git/index" ) else() set(GIT_COMMIT_ID "Unknown") set(GIT_COMMIT_DATE "Unknown") endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/colmap/util/version.cc.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/colmap/util/version.cc") colmap-3.10/cmake/colmap-config-version.cmake.in000066400000000000000000000034211464745566500216260ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. set(PACKAGE_VERSION "@COLMAP_VERSION@") if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() colmap-3.10/cmake/colmap-config.cmake.in000066400000000000000000000060031464745566500201420ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Find package config for COLMAP library. # # The following variables are set by this config: # # COLMAP_FOUND: TRUE if COLMAP is found. # COLMAP_VERSION: COLMAP version. # # The colmap::colmap imported interface target is defined. @PACKAGE_INIT@ set(COLMAP_FOUND FALSE) # Set hints for finding dependency packages. set(FLANN_INCLUDE_DIR_HINTS @FLANN_INCLUDE_DIR_HINTS@) set(FLANN_LIBRARY_DIR_HINTS @FLANN_LIBRARY_DIR_HINTS@) set(LZ4_INCLUDE_DIR_HINTS @LZ4_INCLUDE_DIR_HINTS@) set(LZ4_LIBRARY_DIR_HINTS @LZ4_LIBRARY_DIR_HINTS@) set(FREEIMAGE_INCLUDE_DIR_HINTS @FREEIMAGE_INCLUDE_DIR_HINTS@) set(FREEIMAGE_LIBRARY_DIR_HINTS @FREEIMAGE_LIBRARY_DIR_HINTS@) set(METIS_INCLUDE_DIR_HINTS @METIS_INCLUDE_DIR_HINTS@) set(METIS_LIBRARY_DIR_HINTS @METIS_LIBRARY_DIR_HINTS@) set(GLEW_INCLUDE_DIR_HINTS @GLEW_INCLUDE_DIR_HINTS@) set(GLEW_LIBRARY_DIR_HINTS @GLEW_LIBRARY_DIR_HINTS@) # Find dependency packages. set(TEMP_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH ${PACKAGE_PREFIX_DIR}/share/colmap/cmake) # Set the exported variables. set(COLMAP_FOUND TRUE) set(COLMAP_VERSION @COLMAP_VERSION@) set(OPENMP_ENABLED @OPENMP_ENABLED@) set(CUDA_ENABLED @CUDA_ENABLED@) set(CUDA_MIN_VERSION @CUDA_MIN_VERSION@) set(GUI_ENABLED @GUI_ENABLED@) set(CGAL_ENABLED @CGAL_ENABLED@) include(${PACKAGE_PREFIX_DIR}/share/colmap/colmap-targets.cmake) include(${PACKAGE_PREFIX_DIR}/share/colmap/cmake/FindDependencies.cmake) check_required_components(colmap) colmap-3.10/doc/000077500000000000000000000000001464745566500135035ustar00rootroot00000000000000colmap-3.10/doc/COLMAP.desktop000066400000000000000000000003601464745566500160500ustar00rootroot00000000000000[Desktop Entry] Name=COLMAP Comment=Structure-from-Motion and Multi-View Stereo Exec=colmap gui Icon=colmap Terminal=false Categories=Graphics;3DGraphics; Keywords=3d;reconstruction;structure-from-motion;multi-view-stereo; Type=Application colmap-3.10/doc/Makefile000077500000000000000000000151521464745566500151520ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/COLMAP.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/COLMAP.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/COLMAP" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/COLMAP" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." colmap-3.10/doc/_build/000077500000000000000000000000001464745566500147415ustar00rootroot00000000000000colmap-3.10/doc/_build/html/000077500000000000000000000000001464745566500157055ustar00rootroot00000000000000colmap-3.10/doc/bibliography.rst000077500000000000000000000034441464745566500167200ustar00rootroot00000000000000Bibliography ============ .. [schoenberger_thesis] Johannes L. Schönberger. "Robust Methods for Accurate and Efficient 3D Modeling from Unstructured Imagery." ETH Zürich, 2018. .. [furukawa10] Furukawa, Yasutaka, and Jean Ponce. "Accurate, dense, and robust multiview stereopsis." Transactions on Pattern Analysis and Machine Intelligence, 2010. .. [hofer16] Hofer, M., Maurer, M., and Bischof, H. Efficient 3D Scene Abstraction Using Line Segments, Computer Vision and Image Understanding, 2016. .. [jancosek11] Jancosek, Michal, and Tomás Pajdla. "Multi-view reconstruction preserving weakly-supported surfaces." Conference on Computer Vision and Pattern Recognition, 2011. .. [kazhdan2013] Kazhdan, Michael and Hoppe, Hugues "Screened poisson surface reconstruction." ACM Transactions on Graphics (TOG), 2013. .. [schoenberger16sfm] Schönberger, Johannes Lutz and Frahm, Jan-Michael. "Structure-from-Motion Revisited." Conference on Computer Vision and Pattern Recognition, 2016. .. [schoenberger16mvs] Schönberger, Johannes Lutz and Zheng, Enliang and Pollefeys, Marc and Frahm, Jan-Michael. "Pixelwise View Selection for Unstructured Multi-View Stereo." European Conference on Computer Vision, 2016. .. [schoenberger16vote] Schönberger, Johannes Lutz and Price, True and Sattler, Torsten and Frahm, Jan-Michael and Pollefeys, Marc "A Vote­-and­-Verify Strategy for Fast Spatial Verification in Image Retrieval." Asian Conference on Computer Vision, 2016. .. [lowe04] Lowe, David G. "Distinctive image features from scale-invariant keypoints". International journal of computer vision 60.2 (2004): 91-110. .. [wu13] Wu, Changchang. "Towards linear-time incremental structure from motion." International Conference 3D Vision, 2013. colmap-3.10/doc/cameras.rst000066400000000000000000000052251464745566500156540ustar00rootroot00000000000000Camera Models ============= COLMAP implements different camera models of varying complexity. If no intrinsic parameters are known a priori, it is generally best to use the simplest camera model that is complex enough to model the distortion effects: - ``SIMPLE_PINHOLE``, ``PINHOLE``: Use these camera models, if your images are undistorted a priori. These use one and two focal length parameters, respectively. Note that even in the case of undistorted images, COLMAP could try to improve the intrinsics with a more complex camera model. - ``SIMPLE_RADIAL``, ``RADIAL``: This should be the camera model of choice, if the intrinsics are unknown and every image has a different camera calibration, e.g., in the case of Internet photos. Both models are simplified versions of the ``OPENCV`` model only modeling radial distortion effects with one and two parameters, respectively. - ``OPENCV``, ``FULL_OPENCV``: Use these camera models, if you know the calibration parameters a priori. You can also try to let COLMAP estimate the parameters, if you share the intrinsics for multiple images. Note that the automatic estimation of parameters will most likely fail, if every image has a separate set of intrinsic parameters. - ``SIMPLE_RADIAL_FISHEYE``, ``RADIAL_FISHEYE``, ``OPENCV_FISHEYE``, ``FOV``, ``THIN_PRISM_FISHEYE``: Use these camera models for fisheye lenses and note that all other models are not really capable of modeling the distortion effects of fisheye lenses. The ``FOV`` model is used by Google Project Tango (make sure to not initialize `omega` to zero). You can inspect the estimated intrinsic parameters by double-clicking specific images in the model viewer or by exporting the model and opening the `cameras.txt` file. To achieve optimal reconstruction results, you might have to try different camera models for your problem. Generally, when the reconstruction fails and the estimated focal length values / distortion coefficients are grossly wrong, it is a sign of using a too complex camera model. Contrary, if COLMAP uses many iterative local and global bundle adjustments, it is a sign of using a too simple camera model that is not able to fully model the distortion effects. You can also share intrinsics between multiple images to obtain more reliable results (see :ref:`Share intrinsic camera parameters `) or you can fix the intrinsic parameters during the reconstruction (see :ref:`Fix intrinsic camera parameters `). Please, refer to the camera models header file for information on the parameters of the different camera models: https://github.com/colmap/colmap/blob/main/src/colmap/sensor/models.h colmap-3.10/doc/changelog.rst000066400000000000000000000001031464745566500161560ustar00rootroot00000000000000.. _changelog: Changelog ========= .. include:: ../CHANGELOG.txt colmap-3.10/doc/cli.rst000066400000000000000000000273441464745566500150160ustar00rootroot00000000000000.. _cli: Command-line Interface ====================== The command-line interface provides access to all of COLMAP's functionality for automated scripting. Each core functionality is implemented as a command to the ``colmap`` executable. Run ``colmap -h`` to list the available commands (or ``COLMAP.bat -h`` under Windows). Note that if you run COLMAP from the CMake build folder, the executable is located at ``./src/colmap/exe/colmap``. To start the graphical user interface, run ``colmap gui``. Example ------- Assuming you stored the images of your project in the following structure:: /path/to/project/... +── images │   +── image1.jpg │   +── image2.jpg │   +── ... │   +── imageN.jpg The command for the automatic reconstruction tool would be:: # The project folder must contain a folder "images" with all the images. $ DATASET_PATH=/path/to/project $ colmap automatic_reconstructor \ --workspace_path $DATASET_PATH \ --image_path $DATASET_PATH/images Note that any command lists all available options using the ``-h,--help`` command-line argument. In case you need more control over the individual parameters of the reconstruction process, you can execute the following sequence of commands as an alternative to the automatic reconstruction command:: # The project folder must contain a folder "images" with all the images. $ DATASET_PATH=/path/to/dataset $ colmap feature_extractor \ --database_path $DATASET_PATH/database.db \ --image_path $DATASET_PATH/images $ colmap exhaustive_matcher \ --database_path $DATASET_PATH/database.db $ mkdir $DATASET_PATH/sparse $ colmap mapper \ --database_path $DATASET_PATH/database.db \ --image_path $DATASET_PATH/images \ --output_path $DATASET_PATH/sparse $ mkdir $DATASET_PATH/dense $ colmap image_undistorter \ --image_path $DATASET_PATH/images \ --input_path $DATASET_PATH/sparse/0 \ --output_path $DATASET_PATH/dense \ --output_type COLMAP \ --max_image_size 2000 $ colmap patch_match_stereo \ --workspace_path $DATASET_PATH/dense \ --workspace_format COLMAP \ --PatchMatchStereo.geom_consistency true $ colmap stereo_fusion \ --workspace_path $DATASET_PATH/dense \ --workspace_format COLMAP \ --input_type geometric \ --output_path $DATASET_PATH/dense/fused.ply $ colmap poisson_mesher \ --input_path $DATASET_PATH/dense/fused.ply \ --output_path $DATASET_PATH/dense/meshed-poisson.ply $ colmap delaunay_mesher \ --input_path $DATASET_PATH/dense \ --output_path $DATASET_PATH/dense/meshed-delaunay.ply If you want to run COLMAP on a computer without an attached display (e.g., cluster or cloud service), COLMAP automatically switches to use CUDA if supported by your system. If no CUDA enabled device is available, you can manually select to use CPU-based feature extraction and matching by setting the ``--SiftExtraction.use_gpu 0`` and ``--SiftMatching.use_gpu 0`` options. Help ---- The available commands can be listed using the command:: $ colmap help Usage: colmap [command] [options] Documentation: https://colmap.github.io/ Example usage: colmap help [ -h, --help ] colmap gui colmap gui -h [ --help ] colmap automatic_reconstructor -h [ --help ] colmap automatic_reconstructor --image_path IMAGES --workspace_path WORKSPACE colmap feature_extractor --image_path IMAGES --database_path DATABASE colmap exhaustive_matcher --database_path DATABASE colmap mapper --image_path IMAGES --database_path DATABASE --output_path MODEL ... Available commands: help gui automatic_reconstructor bundle_adjuster color_extractor database_creator delaunay_mesher exhaustive_matcher feature_extractor feature_importer image_deleter image_rectifier image_registrator image_undistorter mapper matches_importer model_aligner model_analyzer model_converter model_merger model_orientation_aligner patch_match_stereo point_triangulator poisson_mesher rig_bundle_adjuster sequential_matcher spatial_matcher stereo_fusion transitive_matcher vocab_tree_builder vocab_tree_matcher vocab_tree_retriever And each command has a ``-h,--help`` command-line argument to show the usage and the available options, e.g.:: $ colmap feature_extractor -h Options can either be specified via command-line or by defining them in a .ini project file passed to `--project_path`. -h [ --help ] --project_path arg --database_path arg --image_path arg --image_list_path arg --ImageReader.camera_model arg (=SIMPLE_RADIAL) --ImageReader.single_camera arg (=0) --ImageReader.camera_params arg --ImageReader.default_focal_length_factor arg (=1.2) --SiftExtraction.num_threads arg (=-1) --SiftExtraction.use_gpu arg (=1) --SiftExtraction.gpu_index arg (=-1) --SiftExtraction.max_image_size arg (=3200) --SiftExtraction.max_num_features arg (=8192) --SiftExtraction.first_octave arg (=-1) --SiftExtraction.num_octaves arg (=4) --SiftExtraction.octave_resolution arg (=3) --SiftExtraction.peak_threshold arg (=0.0066666666666666671) --SiftExtraction.edge_threshold arg (=10) --SiftExtraction.estimate_affine_shape arg (=0) --SiftExtraction.max_num_orientations arg (=2) --SiftExtraction.upright arg (=0) --SiftExtraction.domain_size_pooling arg (=0) --SiftExtraction.dsp_min_scale arg (=0.16666666666666666) --SiftExtraction.dsp_max_scale arg (=3) --SiftExtraction.dsp_num_scales arg (=10) The available options can either be provided directly from the command-line or through a `.ini` file provided to ``--project_path``. Commands -------- The following list briefly documents the functionality of each command, that is available as ``colmap [command]``: - ``gui``: The graphical user interface, see :ref:`Graphical User Interface ` for more information. - ``automatic_reconstructor``: Automatically reconstruct sparse and dense model for a set of input images. - ``project_generator``: Generate project files at different quality settings. - ``feature_extractor``, ``feature_importer``: Perform feature extraction or import features for a set of images. - ``exhaustive_matcher``, ``vocab_tree_matcher``, ``sequential_matcher``, ``spatial_matcher``, ``transitive_matcher``, ``matches_importer``: Perform feature matching after performing feature extraction. - ``mapper``: Sparse 3D reconstruction / mapping of the dataset using SfM after performing feature extraction and matching. - ``hierarchical_mapper``: Sparse 3D reconstruction / mapping of the dataset using hierarchical SfM after performing feature extraction and matching. This parallelizes the reconstruction process by partitioning the scene into overlapping submodels and then reconstructing each submodel independently. Finally, the overlapping submodels are merged into a single reconstruction. It is recommended to run a few rounds of point triangulation and bundle adjustment after this step. - ``image_undistorter``: Undistort images and/or export them for MVS or to external dense reconstruction software, such as CMVS/PMVS. - ``image_rectifier``: Stereo rectify cameras and undistort images for stereo disparity estimation. - ``image_filterer``: Filter images from a sparse reconstruction. - ``image_deleter``: Delete specific images from a sparse reconstruction. - ``patch_match_stereo``: Dense 3D reconstruction / mapping using MVS after running the ``image_undistorter`` to initialize the workspace. - ``stereo_fusion``: Fusion of ``patch_match_stereo`` results into to a colored point cloud. - ``poisson_mesher``: Meshing of the fused point cloud using Poisson surface reconstruction. - ``delaunay_mesher``: Meshing of the reconstructed sparse or dense point cloud using a graph cut on the Delaunay triangulation and visibility voting. - ``image_registrator``: Register new images in the database against an existing model, e.g., when extracting features and matching newly added images in a database after running ``mapper``. Note that no bundle adjustment or triangulation is performed. - ``point_triangulator``: Triangulate all observations of registered images in an existing model using the feature matches in a database. - ``point_filtering``: Filter sparse points in model by enforcing criteria, such as minimum track length, maximum reprojection error, etc. - ``bundle_adjuster``: Run global bundle adjustment on a reconstructed scene, e.g., when a refinement of the intrinsics is needed or after running the ``image_registrator``. - ``database_creator``: Create an empty COLMAP SQLite database with the necessary database schema information. - ``database_merger``: Merge two databases into a new database. Note that the cameras will not be merged and that the unique camera and image identifiers might change during the merging process. - ``model_analyzer``: Print statistics about reconstructions. - ``model_aligner``: Align/geo-register model to coordinate system of given camera centers. - ``model_orientation_aligner``: Align the coordinate axis of a model using a Manhattan world assumption. - ``model_converter``: Convert the COLMAP export format to another format, such as PLY or NVM. - ``model_cropper``: Crop model to specific bounding box described in GPS or model coordinate system. - ``model_splitter``: Divide model in rectangular sub-models specified from file containing bounding box coordinates, or max extent of sub-model, or number of subdivisions in each dimension. - ``model_merger``: Attempt to merge two disconnected reconstructions, if they have common registered images. - ``color_extractor``: Extract mean colors for all 3D points of a model. - ``vocab_tree_builder``: Create a vocabulary tree from a database with extracted images. This is an offline procedure and can be run once, while the same vocabulary tree can be reused for other datasets. Note that, as a rule of thumb, you should use at least 10-100 times more features than visual words. Pre-trained trees can be downloaded from https://demuc.de/colmap/. This is useful if you want to build a custom tree with a different trade-off in terms of precision/recall vs. speed. - ``vocab_tree_retriever``: Perform vocabulary tree based image retrieval. Visualization ------------- If you want to quickly visualize the outputs of the sparse or dense reconstruction pipelines, COLMAP offers you the following possibilities: - The sparse point cloud obtained with the ``mapper`` can be visualized via the COLMAP GUI by importing the following files: choose ``File > Import Model`` and select the folder where the three files, ``cameras.txt``, ``images.txt``, and ``points3d.txt`` are located. - The dense point cloud obtained with the ``stereo_fusion`` can be visualized via the COLMAP GUI by importing ``fused.ply``: choose ``File > Import Model from...`` and then select the file ``fused.ply``. - The dense mesh model ``meshed-*.ply`` obtained with the ``poisson_mesher`` or the ``delaunay_mesher`` can currently not be visualized with COLMAP, instead you can use an external viewer, such as Meshlab. colmap-3.10/doc/colmap.1000066400000000000000000000021021464745566500150330ustar00rootroot00000000000000.TH colmap 1 "January 4 2018" .SH NAME colmap \- Structure-from-Motion and Multi-View Stereo .SH SYNOPSIS .B colmap .RI "[command] [options]" .SH DESCRIPTION This manual page documents briefly the .B colmap command. .PP COLMAP is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface. It offers a wide range of features for reconstruction of ordered and unordered image collections. .SH OPTIONS This program offers a graphical and command-line interface. Each command offers summary of all available options. .TP .B help [ \-h, \-\-help ] Show summary of all options. .TP .B gui Start graphical interface. .TP .B gui \-h [ \-\-help ] Show summary of graphical interface options. .TP .B feature_extractor \-h [ \-\-help ] Show summary of feature extractor options. .TP .B feature_extractor \-\-image_path IMAGES \-\-database_path DATABASE Extract features for images in the given folder and store them in the database. .br .TP .B ... .br .SH ONLINE DOCUMENTATION The program is documented at https://colmap.github.io/ colmap-3.10/doc/conf.py000077500000000000000000000203771464745566500150160ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # COLMAP documentation build configuration file, created by # sphinx-quickstart on Wed Jan 28 09:31:25 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.mathjax", ] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. project = u"COLMAP" copyright = u"2023, Johannes L. Schoenberger" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = "3.10-dev" # The full version, including alpha/beta/rc tags. release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ["_themes"] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "COLMAPdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'a4paper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ( "index", "COLMAP.tex", u"COLMAP Documentation", u"Johannes L. Schoenberger", "manual", ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. latex_show_pagerefs = True # If true, show URL addresses after external links. latex_show_urls = "footnote" # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. latex_domain_indices = False # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ( "index", "colmap", u"COLMAP Documentation", [u"Johannes L. Schoenberger"], 1, ) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( "index", "COLMAP", u"COLMAP Documentation", u"Johannes L. Schoenberger", "COLMAP", "Structure-from-Motion and Multi-View Stereo.", "Miscellaneous", ), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False colmap-3.10/doc/contribution.rst000066400000000000000000000016731464745566500167630ustar00rootroot00000000000000Contribution ============ Contributions (bug reports, bug fixes, improvements, etc.) are very welcome and should be submitted in the form of new issues and/or pull requests on GitHub. Please, adhere to the Google coding style guide:: https://google.github.io/styleguide/cppguide.html by using the provided ".clang-format" file. Document functions, methods, classes, etc. with inline documentation strings describing the API, using the following format:: // Short description. // // Longer description with a few sentences and multiple lines. // // @param parameter1 Description for parameter 1. // @param parameter2 Description for parameter 2. // // @return Description of optional return value. Add unit tests for all newly added code and make sure that algorithmic "improvements" generalize and actually improve the results of the pipeline on a variety of datasets. colmap-3.10/doc/database.rst000077500000000000000000000113261464745566500160070ustar00rootroot00000000000000.. _database-format: Database Format =============== COLMAP stores all extracted information in a single SQLite database file. The database can be accessed with the database management toolkit in the COLMAP GUI, the provided C++ database API (see ``src/colmap/scene/database.h``), or with a scripting language of your choice (see ``scripts/python/database.py``). The database contains the following tables: - cameras - images - keypoints - descriptors - matches - two_view_geometries To initialize an empty SQLite database file with the required schema, you can either create a new project in the GUI or execute `src/colmap/exe/database_create.cc`. Cameras and Images ------------------ The relation between cameras and images is 1-to-N. This has important implications for Structure-from-Motion, since one camera shares the same intrinsic parameters (focal length, principal point, distortion, etc.), while every image has separate extrinsic parameters (orientation and location). The intrinsic parameters of cameras are stored as contiguous binary blobs in `float64`, ordered as specified in ``src/colmap/sensor/models.h``. COLMAP only uses cameras that are referenced by images, all other cameras are ignored. The ``name`` column in the images table is the unique relative path in the image folder. As such, the database file and image folder can be moved to different locations, as long as the relative folder structure is preserved. When manually inserting images and cameras into the database, make sure that all identifiers are positive and non-zero, i.e. ``image_id > 0`` and ``camera_id > 0``. Keypoints and Descriptors ------------------------- The detected keypoints are stored as row-major `float32` binary blobs, where the first two columns are the X and Y locations in the image, respectively. COLMAP uses the convention that the upper left image corner has coordinate `(0, 0)` and the center of the upper left most pixel has coordinate `(0.5, 0.5)`. If the keypoints have 4 columns, then the feature geometry is a similarity and the third column is the scale and the fourth column the orientation of the feature (according to SIFT conventions). If the keypoints have 6 columns, then the feature geometry is an affinity and the last 4 columns encode its affine shape (see ``src/feature/types.h`` for details). The extracted descriptors are stored as row-major `uint8` binary blobs, where each row describes the feature appearance of the corresponding entry in the keypoints table. Note that COLMAP only supports 128-D descriptors for now, i.e. the `cols` column must be 128. In both tables, the `rows` table specifies the number of detected features per image, while `rows=0` means that an image has no features. For feature matching and geometric verification, every image must have a corresponding keypoints and descriptors entry. Note that only vocabulary tree matching with fast spatial verification requires meaningful values for the local feature geometry, i.e., only X and Y must be provided and the other keypoint columns can be set to zero. The rest of the reconstruction pipeline only uses the keypoint locations. Matches ------- Feature matching stores its output in the `matches` table and geometric verification in the `two_view_geometries` table. COLMAP only uses the data in `two_view_geometries` for reconstruction. Every entry in the two tables stores the feature matches between two unique images, where the `pair_id` is the row-major, linear index in the upper-triangular match matrix, generated as follows:: def image_ids_to_pair_id(image_id1, image_id2): if image_id1 > image_id2: return 2147483647 * image_id2 + image_id1 else: return 2147483647 * image_id1 + image_id2 and image identifiers can be uniquely determined from the `pair_id` as:: def pair_id_to_image_ids(pair_id): image_id2 = pair_id % 2147483647 image_id1 = (pair_id - image_id2) / 2147483647 return image_id1, image_id2 The `pair_id` enables efficient database queries, as the matches tables may contain several hundred millions of entries. This scheme limits the maximum number of images in a database to 2147483647 (maximum value of signed 32-bit integers), i.e. `image_id` must be smaller than 2147483647. The binary blobs in the matches tables are row-major `uint32` matrices, where the left column are zero-based indices into the features of `image_id1` and the second column into the features of `image_id2`. The column `cols` must be 2 and the `rows` column specifies the number of feature matches. The F, E, H blobs in the `two_view_geometries` table are stored as 3x3 matrices in row-major `float64` format. The meaning of the `config` values are documented in the `src/estimators/two_view_geometry.h` source file. colmap-3.10/doc/datasets.rst000066400000000000000000000021461464745566500160500ustar00rootroot00000000000000.. _datasets: Datasets ======== A number of different datasets are available for download at: https://demuc.de/colmap/datasets/ - **Gerrard Hall**: 100 high-resolution images of the "Gerrard" hall at UNC Chapel Hill, which is the building right next to the "South" building. The images are taken with the same camera but different focus using a wide-angle lens. - **Graham Hall**: 1273 high-resolution images of the interior and exterior of "Graham" memorial hall at UNC Chapel Hill. The images are taken with the same camera but different focus using a wide-angle lens. - **Person Hall**: 330 high-resolution images of the "Person" hall at UNC Chapel Hill. The images are taken with the same camera using a wide-angle lens. - **South Building**: 128 images of the "South" building at UNC Chapel Hill. The images are taken with the same camera, kindly provided by Christopher Zach. A number of sample reconstructions produced by COLMAP can be viewed here: **Sparse reconstructions**: - https://youtu.be/PmXqdfBQxfQ - https://youtu.be/DIv1aGKqSIk **Dense reconstructions**: - https://youtu.be/11awtGWSqQU colmap-3.10/doc/faq.rst000066400000000000000000000663701464745566500150200ustar00rootroot00000000000000Frequently Asked Questions ========================== Adjusting the options for different reconstruction scenarios and output quality ------------------------------------------------------------------------------- COLMAP provides many options that can be tuned for different reconstruction scenarios and to trade off accuracy and completeness versus efficiency. The default options are set to for medium to high quality reconstruction of unstructured input data. There are several presets for different scenarios and quality levels, which can be set in the GUI as ``Extras > Set options for ...``. To use these presets from the command-line, you can save the current set of options as ``File > Save project`` after choosing the presets. The resulting project file can be opened with a text editor to view the different options. Alternatively, you can generate the project file also from the command-line by running ``colmap project_generator``. Extending COLMAP ---------------- If you need to simply analyze the produced sparse or dense reconstructions from COLMAP, you can load the sparse models in Python and Matlab using the provided scripts in ``scripts/python`` and ``scripts/matlab``. If you want to write a C/C++ executable that builds on top of COLMAP, there are two possible approaches. First, the COLMAP headers and library are installed to the ``CMAKE_INSTALL_PREFIX`` by default. Compiling against COLMAP as a library is described :ref:`here `. Alternatively, you can start from the ``src/tools/example.cc`` code template and implement the desired functionality directly as a new binary within COLMAP. .. _faq-share-intrinsics: Share intrinsics ---------------- COLMAP supports shared intrinsics for arbitrary groups of images and camera models. Images share the same intrinsics, if they refer to the same camera, as specified by the `camera_id` property in the database. You can add new cameras and set shared intrinsics in the database management tool. Please, refer to :ref:`Database Management ` for more information. .. _faq-fix-intrinsics: Fix intrinsics -------------- By default, COLMAP tries to refine the intrinsic camera parameters (except principal point) automatically during the reconstruction. Usually, if there are enough images in the dataset and you share the intrinsics between multiple images, the estimated intrinsic camera parameters in SfM should be better than parameters manually obtained with a calibration pattern. However, sometimes COLMAP's self-calibration routine might converge in degenerate parameters, especially in case of the more complex camera models with many distortion parameters. If you know the calibration parameters a priori, you can fix different parameter groups during the reconstruction. Choose ``Reconstruction > Reconstruction options > Bundle Adj. > refine_*`` and check which parameter group to refine or to keep constant. Even if you keep the parameters constant during the reconstruction, you can refine the parameters in a final global bundle adjustment by setting ``Reconstruction > Bundle adj. options > refine_*`` and then running ``Reconstruction > Bundle adjustment``. Principal point refinement -------------------------- By default, COLMAP keeps the principal point constant during the reconstruction, as principal point estimation is an ill-posed problem in general. Once all images are reconstructed, the problem is most often constrained enough that you can try to refine the principal point in global bundle adjustment, especially when sharing intrinsic parameters between multiple images. Please, refer to :ref:`Fix intrinsics ` for more information. Increase number of matches / sparse 3D points --------------------------------------------- To increase the number of matches, you should use the more discriminative DSP-SIFT features instead of plain SIFT and also estimate the affine feature shape using the options: ``--SiftExtraction.estimate_affine_shape=true`` and ``--SiftExtraction.domain_size_pooling=true``. In addition, you should enable guided feature matching using: ``--SiftMatching.guided_matching=true``. By default, COLMAP ignores two-view feature tracks in triangulation, resulting in fewer 3D points than possible. Triangulation of two-view tracks can in rare cases improve the stability of sparse image collections by providing additional constraints in bundle adjustment. To also triangulate two-view tracks, unselect the option ``Reconstruction > Reconstruction options > Triangulation > ignore_two_view_tracks``. If your images are taken from far distance with respect to the scene, you can try to reduce the minimum triangulation angle. Reconstruct sparse/dense model from known camera poses ------------------------------------------------------ If the camera poses are known and you want to reconstruct a sparse or dense model of the scene, you must first manually construct a sparse model by creating a ``cameras.txt``, ``points3D.txt``, and ``images.txt`` under a new folder:: +── path/to/manually/created/sparse/model │   +── cameras.txt │   +── images.txt │   +── points3D.txt The ``points3D.txt`` file should be empty while every other line in the ``images.txt`` should also be empty, since the sparse features are computed, as described below. You can refer to :ref:`this article ` for more information about the structure of a sparse model. Example of images.txt:: 1 0.695104 0.718385 -0.024566 0.012285 -0.046895 0.005253 -0.199664 1 image0001.png # Make sure every other line is left empty 2 0.696445 0.717090 -0.023185 0.014441 -0.041213 0.001928 -0.134851 2 image0002.png 3 0.697457 0.715925 -0.025383 0.018967 -0.054056 0.008579 -0.378221 1 image0003.png 4 0.698777 0.714625 -0.023996 0.021129 -0.048184 0.004529 -0.313427 2 image0004.png Each image above must have the same ``image_id`` (first column) as in the database (next step). This database can be inspected either in the GUI (under ``Database management > Processing``), or, one can create a reconstruction with colmap and later export it as text in order to see the images.txt file it creates. To reconstruct a sparse map, you first have to recompute features from the images of the known camera poses as follows:: colmap feature_extractor \ --database_path $PROJECT_PATH/database.db \ --image_path $PROJECT_PATH/images If your known camera intrinsics have large distortion coefficients, you should now manually copy the parameters from your ``cameras.txt`` to the database, such that the matcher can leverage the intrinsics. Modifying the database is possible in many ways, but an easy option is to use the provided ``scripts/python/database.py`` script. Otherwise, you can skip this step and simply continue as follows:: colmap exhaustive_matcher \ # or alternatively any other matcher --database_path $PROJECT_PATH/database.db colmap point_triangulator \ --database_path $PROJECT_PATH/database.db \ --image_path $PROJECT_PATH/images --input_path path/to/manually/created/sparse/model \ --output_path path/to/triangulated/sparse/model Note that the sparse reconstruction step is not necessary in order to compute a dense model from known camera poses. Assuming you computed a sparse model from the known camera poses, you can compute a dense model as follows:: colmap image_undistorter \ --image_path $PROJECT_PATH/images \ --input_path path/to/triangulated/sparse/model \ --output_path path/to/dense/workspace colmap patch_match_stereo \ --workspace_path path/to/dense/workspace colmap stereo_fusion \ --workspace_path path/to/dense/workspace \ --output_path path/to/dense/workspace/fused.ply Alternatively, you can also produce a dense model without a sparse model as:: colmap image_undistorter \ --image_path $PROJECT_PATH/images \ --input_path path/to/manually/created/sparse/model \ --output_path path/to/dense/workspace Since the sparse point cloud is used to automatically select neighboring images during the dense stereo stage, you have to manually specify the source images, as described :ref:`here `. The dense stereo stage now also requires a manual specification of the depth range:: colmap patch_match_stereo \ --workspace_path path/to/dense/workspace \ --PatchMatchStereo.depth_min $MIN_DEPTH \ --PatchMatchStereo.depth_max $MAX_DEPTH colmap stereo_fusion \ --workspace_path path/to/dense/workspace \ --output_path path/to/dense/workspace/fused.ply .. _faq-merge-models: Merge disconnected models ------------------------- Sometimes COLMAP fails to reconstruct all images into the same model and hence produces multiple sub-models. If those sub-models have common registered images, they can be merged into a single model as post-processing step:: colmap model_merger \ --input_path1 /path/to/sub-model1 \ --input_path2 /path/to/sub-model2 \ --output_path /path/to/merged-model To improve the quality of the alignment between the two sub-models, it is recommended to run another global bundle adjustment after the merge:: colmap bundle_adjuster \ --input_path /path/to/merged-model \ --output_path /path/to/refined-merged-model Geo-registration ---------------- Geo-registration of models is possible by providing the 3D locations for the camera centers of a subset or all registered images. The 3D similarity transformation between the reconstructed model and the target coordinate frame of the geo-registration is determined from these correspondences. The geo-registered 3D coordinates can either be extracted from the database (tvec_prior field) or from a user specified text file. For text-files, the geo-registered 3D coordinates of the camera centers for images must be specified with the following format:: image_name1.jpg X1 Y1 Z1 image_name2.jpg X2 Y2 Z2 image_name3.jpg X3 Y3 Z3 ... The coordinates can be either GPS-based (lat/lon/alt) or cartesian-based (x/y/z). In case of GPS coordinates, a conversion will be performed to turn those into cartesian coordinates. The conversion can be done from GPS to ECEF (Earth-Centered-Earth-Fixed) or to ENU (East-North-Up) coordinates. If ENU coordinates are used, the first image GPS coordinates will define the origin of the ENU frame. It is also possible to use ECEF coordinates for alignment and then rotate the aligned reconstruction into the ENU plane. Note that at least 3 images must be specified to estimate a 3D similarity transformation. Then, the model can be geo-registered using:: colmap model_aligner \ --input_path /path/to/model \ --output_path /path/to/geo-registered-model \ --ref_images_path /path/to/text-file (or --database_path /path/to/database.db) \ --ref_is_gps 1 \ --alignment_type ecef \ --robust_alignment 1 \ --robust_alignment_max_error 3.0 (where 3.0 is the error threshold to be used in RANSAC) By default, the robust_alignment flag is set to 1. If this flag is set, a 3D similarity transformation will be estimated with a RANSAC estimator to be robust to potential outliers in the data. In such case, it is required to provide the error threshold to be used in the RANSAC estimator. Manhattan world alignment ------------------------- COLMAP has functionality to align the coordinate axes of a reconstruction using a Manhattan world assumption, i.e. COLMAP can automatically determine the gravity axis and the major horizontal axis of the Manhattan world through vanishing point detection in the images. Please, refer to the ``model_orientation_aligner`` for more details. Mask image regions ------------------ COLMAP supports masking of keypoints during feature extraction two different ways: 1. Passing ``mask_path`` to a folder with image masks. For a given image, the corresponding mask must have the same sub-path below this root as the image has below ``image_path``. The filename must be equal, aside from the added extension ``.png``. For example, for an image ``image_path/abc/012.jpg``, the mask would be ``mask_path/abc/012.jpg.png``. 2. Passing ``camera_mask_path`` to a single mask image. This single mask is applied to all images. In both cases no features will be extracted in regions, where the mask image is black (pixel intensity value 0 in grayscale). Register/localize new images into an existing reconstruction ------------------------------------------------------------ If you have an existing reconstruction of images and want to register/localize new images within this reconstruction, you can follow these steps:: colmap feature_extractor \ --database_path $PROJECT_PATH/database.db \ --image_path $PROJECT_PATH/images \ --image_list_path /path/to/image-list.txt colmap vocab_tree_matcher \ --database_path $PROJECT_PATH/database.db \ --VocabTreeMatching.vocab_tree_path /path/to/vocab-tree.bin \ --VocabTreeMatching.match_list_path /path/to/image-list.txt colmap image_registrator \ --database_path $PROJECT_PATH/database.db \ --input_path /path/to/existing-model \ --output_path /path/to/model-with-new-images colmap bundle_adjuster \ --input_path /path/to/model-with-new-images \ --output_path /path/to/model-with-new-images Note that this first extracts features for the new images, then matches them to the existing images in the database, and finally registers them into the model. The image list text file contains a list of images to extract and match, specified as one image file name per line. The bundle adjustment is optional. If you need a more accurate image registration with triangulation, then you should restart or continue the reconstruction process rather than just registering the images to the model. Instead of running the ``image_registrator``, you should run the ``mapper`` to continue the reconstruction process from the existing model:: colmap mapper \ --database_path $PROJECT_PATH/database.db \ --image_path $PROJECT_PATH/images \ --input_path /path/to/existing-model \ --output_path /path/to/model-with-new-images Or, alternatively, you can start the reconstruction from scratch:: colmap mapper \ --database_path $PROJECT_PATH/database.db \ --image_path $PROJECT_PATH/images \ --output_path /path/to/model-with-new-images Note that dense reconstruction must be re-run from scratch after running the ``mapper`` or the ``bundle_adjuster``, as the coordinate frame of the model can change during these steps. Available functionality without GPU/CUDA ---------------------------------------- If you do not have a CUDA-enabled GPU but some other GPU, you can use all COLMAP functionality except the dense reconstruction part. However, you can use external dense reconstruction software as an alternative, as described in the :ref:`Tutorial `. If you have a GPU with low compute power or you want to execute COLMAP on a machine without an attached display and without CUDA support, you can run all steps on the CPU by specifying the appropriate options (e.g., ``--SiftExtraction.use_gpu=false`` for the feature extraction step). But note that this might result in a significant slow-down of the reconstruction pipeline. Please, also note that feature extraction on the CPU can consume excessive RAM for large images in the default settings, which might require manually reducing the maximum image size using ``--SiftExtraction.max_image_size`` and/or setting ``--SiftExtraction.first_octave 0`` or by manually limiting the number of threads using ``--SiftExtraction.num_threads``. Multi-GPU support in feature extraction/matching ------------------------------------------------ You can run feature extraction/matching on multiple GPUs by specifying multiple indices for CUDA-enabled GPUs, e.g., ``--SiftExtraction.gpu_index=0,1,2,3`` and ``--SiftMatching.gpu_index=0,1,2,3`` runs the feature extraction/matching on 4 GPUs in parallel. Note that you can only run one thread per GPU and this typically also gives the best performance. By default, COLMAP runs one feature extraction/matching thread per CUDA-enabled GPU and this usually gives the best performance as compared to running multiple threads on the same GPU. Feature matching fails due to illegal memory access --------------------------------------------------- If you encounter the following error message:: MultiplyDescriptor: an illegal memory access was encountered or the following: ERROR: Feature matching failed. This probably caused by insufficient GPU memory. Consider reducing the maximum number of features. during feature matching, your GPU runs out of memory. Try decreasing the option ``--SiftMatching.max_num_matches`` until the error disappears. Note that this might lead to inferior feature matching results, since the lower-scale input features will be clamped in order to fit them into GPU memory. Alternatively, you could change to CPU-based feature matching, but this can become very slow, or better you buy a GPU with more memory. The maximum required GPU memory can be approximately estimated using the following formula: ``4 * num_matches * num_matches + 4 * num_matches * 256``. For example, if you set ``--SiftMatching.max_num_matches 10000``, the maximum required GPU memory will be around 400MB, which are only allocated if one of your images actually has that many features. Trading off completeness and accuracy in dense reconstruction ------------------------------------------------------------- If the dense point cloud contains too many outliers and too much noise, try to increase the value of option ``--StereoFusion.min_num_pixels``. If the reconstructed dense surface mesh model using Poisson reconstruction contains no surface or there are too many outlier surfaces, you should reduce the value of option ``--PoissonMeshing.trim`` to decrease the surface are and vice versa to increase it. Also consider to try the reduce the outliers or increase the completeness in the fusion stage, as described above. If the reconstructed dense surface mesh model using Delaunay reconstruction contains too noisy or incomplete surfaces, you should increase the ``--DenaunayMeshing.quality_regularization`` parameter to obtain a smoother surface. If the resolution of the mesh is too coarse, you should reduce the ``--DelaunayMeshing.max_proj_dist`` option to a lower value. Improving dense reconstruction results for weakly textured surfaces ------------------------------------------------------------------- For scenes with weakly textured surfaces it can help to have a high resolution of the input images (``--PatchMatchStereo.max_image_size``) and a large patch window radius (``--PatchMatchStereo.window_radius``). You may also want to reduce the filtering threshold for the photometric consistency cost (``--PatchMatchStereo.filter_min_ncc``). Surface mesh reconstruction --------------------------- COLMAP supports two types of surface reconstruction algorithms. Poisson surface reconstruction [kazhdan2013]_ and graph-cut based surface extraction from a Delaunay triangulation. Poisson surface reconstruction typically requires an almost outlier-free input point cloud and it often produces bad surfaces in the presence of outliers or large holes in the input data. The Delaunay triangulation based meshing algorithm is more robust to outliers and in general more scalable to large datasets than the Poisson algorithm, but it usually produces less smooth surfaces. Furthermore, the Delaunay based meshing can be applied to sparse and dense reconstruction results. To increase the smoothness of the surface as a post-processing step, you could use Laplacian smoothing, as e.g. implemented in Meshlab. Note that the two algorithms can also be combined by first running the Delaunay meshing to robustly filter outliers from the sparse or dense point cloud and then, in the second step, performing Poisson surface reconstruction to obtain a smooth surface. Speedup dense reconstruction ---------------------------- The dense reconstruction can be speeded up in multiple ways: - Put more GPUs in your system as the dense reconstruction can make use of multiple GPUs during the stereo reconstruction step. Put more RAM into your system and increase the ``--PatchMatchStereo.cache_size``, ``--StereoFusion.cache_size`` to the largest possible value in order to speed up the dense fusion step. - Do not perform geometric dense stereo reconstruction ``--PatchMatchStereo.geom_consistency false``. Make sure to also enable ``--PatchMatchStereo.filter true`` in this case. - Reduce the ``--PatchMatchStereo.max_image_size``, ``--StereoFusion.max_image_size`` values to perform dense reconstruction on a maximum image resolution. - Reduce the number of source images per reference image to be considered, as described :ref:`here `. - Increase the patch windows step ``--PatchMatchStereo.window_step`` to 2. - Reduce the patch window radius ``--PatchMatchStereo.window_radius``. - Reduce the number of patch match iterations ``--PatchMatchStereo.num_iterations``. - Reduce the number of sampled views ``--PatchMatchStereo.num_samples``. - To speedup the dense stereo and fusion step for very large reconstructions, you can use CMVS to partition your scene into multiple clusters and to prune redundant images, as described :ref:`here `. Note that apart from upgrading your hardware, the proposed changes might degrade the quality of the dense reconstruction results. When canceling the stereo reconstruction process and restarting it later, the previous progress is not lost and any already processed views will be skipped. .. _faq-dense-memory: Reduce memory usage during dense reconstruction ----------------------------------------------- If you run out of GPU memory during patch match stereo, you can either reduce the maximum image size by setting the option ``--PatchMatchStereo.max_image_size`` or reduce the number of source images in the ``stereo/patch-match.cfg`` file from e.g. ``__auto__, 30`` to ``__auto__, 10``. Note that enabling the ``geom_consistency`` option increases the required GPU memory. If you run out of CPU memory during stereo or fusion, you can reduce the ``--PatchMatchStereo.cache_size`` or ``--StereoFusion.cache_size`` specified in gigabytes or you can reduce ``--PatchMatchStereo.max_image_size`` or ``--StereoFusion.max_image_size``. Note that a too low value might lead to very slow processing and heavy load on the hard disk. For large-scale reconstructions of several thousands of images, you should consider splitting your sparse reconstruction into more manageable clusters of images using e.g. CMVS [furukawa10]_. In addition, CMVS allows to prune redundant images observing the same scene elements. Note that, for this use case, COLMAP's dense reconstruction pipeline also supports the PMVS/CMVS folder structure when executed from the command-line. Please, refer to the workspace folder for example shell scripts. Note that the example shell scripts for PMVS/CMVS are only generated, if the output type is set to PMVS. Since CMVS produces highly overlapping clusters, it is recommended to increase the default value of 100 images per cluster to as high as possible according to your available system resources and speed requirements. To change the number of images using CMVS, you must modify the shell scripts accordingly. For example, ``cmvs pmvs/ 500`` to limit each cluster to 500 images. If you want to use CMVS to prune redundant images but not to cluster the scene, you can simply set this number to a very large value. .. _faq-dense-manual-source: Manual specification of source images during dense reconstruction ----------------------------------------------------------------- You can change the number of source images in the ``stereo/patch-match.cfg`` file from e.g. ``__auto__, 30`` to ``__auto__, 10``. This selects the images with the most visual overlap automatically as source images. You can also use all other images as source images, by specifying ``__all__``. Alternatively, you can manually specify images with their name, for example:: image1.jpg image2.jpg, image3.jpg image2.jpg image1.jpg, image3.jpg image3.jpg image1.jpg, image2.jpg Here, ``image2.jpg`` and ``image3.jpg`` are used as source images for ``image1.jpg``, etc. Multi-GPU support in dense reconstruction ----------------------------------------- You can run dense reconstruction on multiple GPUs by specifying multiple indices for CUDA-enabled GPUs, e.g., ``--PatchMatchStereo.gpu_index=0,1,2,3`` runs the dense reconstruction on 4 GPUs in parallel. You can also run multiple dense reconstruction threads on the same GPU by specifying the same GPU index twice, e.g., ``--PatchMatchStereo.gpu_index=0,0,1,1,2,3``. By default, COLMAP runs one dense reconstruction thread per CUDA-enabled GPU. .. _faq-dense-timeout: Fix GPU freezes and timeouts during dense reconstruction -------------------------------------------------------- The stereo reconstruction pipeline runs on the GPU using CUDA and puts the GPU under heavy load. You might experience a display freeze or even a program crash during the reconstruction. As a solution to this problem, you could use a secondary GPU in your system, that is not connected to your display by setting the GPU indices explicitly (usually index 0 corresponds to the card that the display is attached to). Alternatively, you can increase the GPU timeouts of your system, as detailed in the following. By default, the Windows operating system detects response problems from the GPU, and recovers to a functional desktop by resetting the card and aborting the stereo reconstruction process. The solution is to increase the so-called "Timeout Detection & Recovery" (TDR) delay to a larger value. Please, refer to the `NVIDIA Nsight documentation `_ or to the `Microsoft documentation `_ on how to increase the delay time under Windows. You can increase the delay using the following Windows Registry entries:: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers] "TdrLevel"=dword:00000001 "TdrDelay"=dword:00000120 To set the registry entries, execute the following commands using administrator privileges (e.g., in ``cmd.exe`` or ``powershell.exe``):: reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers /v TdrLevel /t REG_DWORD /d 00000001 reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers /v TdrDelay /t REG_DWORD /d 00000120 and restart your machine afterwards to make the changes effective. The X window system under Linux/Unix has a similar feature and detects response problems of the GPU. The easiest solution to avoid timeout problems under the X window system is to shut it down and run the stereo reconstruction from the command-line. Under Ubuntu, you could first stop X using:: sudo service lightdm stop And then run the dense reconstruction code from the command-line:: colmap patch_match_stereo ... Finally, you can restart your desktop environment with the following command:: sudo service lightdm start If the dense reconstruction still crashes after these changes, the reason is probably insufficient GPU memory, as discussed in a separate item in this list. colmap-3.10/doc/format.rst000066400000000000000000000225051464745566500155310ustar00rootroot00000000000000.. _output-format: Output Format ============= ================== Binary File Format ================== Note that all binary data is stored using little endian byte ordering. All x86 processors are little endian and thus no special care has to be taken when reading COLMAP binary data on most platforms. ======================= Indices and Identifiers ======================= Any variable name ending with ``*_idx`` should be considered as an ordered, contiguous zero-based index. In general, any variable name ending with ``*_id`` should be considered as an unordered, non-contiguous identifier. For example, the unique identifiers of cameras (`CAMERA_ID`), images (`IMAGE_ID`), and 3D points (`POINT3D_ID`) are unordered and are most likely not contiguous. This also means that the maximum `POINT3D_ID` does not necessarily correspond to the number 3D points, since some `POINT3D_ID`'s are missing due to filtering during the reconstruction, etc. ===================== Sparse Reconstruction ===================== By default, COLMAP uses a binary file format (machine-readable, fast) for storing sparse models. In addition, COLMAP provides the option to store the sparse models as text files (human-readable, slow). In both cases, the information is split into three files for the information about `cameras`, `images`, and `points`. Any directory containing those three files constitutes a sparse model. The binary files have the file extension `.bin` and the text files the file extension `.txt`. Note that when loading a model from a directory which contains both binary and text files, COLMAP prefers the binary format. To export the currently selected model in the GUI, choose ``File > Export model``. To export all reconstructed models in the current dataset, choose ``File > Export all``. The selected folder then contains the three files, and for convenience, the current project configuration for importing the model to COLMAP. To import the exported models, e.g., for visualization or to resume the reconstruction, choose ``File > Import model`` and select the folder containing the `cameras`, `images`, and `points3D` files. To convert between the binary and text format in the GUI, you can load the model using ``File > Import model`` and then export the model in the desired output format using ``File > Export model`` (binary) or ``File > Export model as text`` (text). In addition, you can export sparse models to other formats, such as VisualSfM's NVM, Bundler files, PLY, VRML, etc., using ``File > Export as...``. To convert between various formats from the CLI, use the ``model_converter`` executable. There are two source files to conveniently read the sparse reconstructions using Python (``scripts/python/read_write_model.py`` supporting binary and text) and Matlab (``scripts/matlab/read_model.m`` supporting text). ----------- Text Format ----------- COLMAP exports the following three text files for every reconstructed model: `cameras.txt`, `images.txt`, and `points3D.txt`. Comments start with a leading "#" character and are ignored. The first comment lines briefly describe the format of the text files, as described in more detailed on this page. cameras.txt ----------- This file contains the intrinsic parameters of all reconstructed cameras in the dataset using one line per camera, e.g.:: # Camera list with one line of data per camera: # CAMERA_ID, MODEL, WIDTH, HEIGHT, PARAMS[] # Number of cameras: 3 1 SIMPLE_PINHOLE 3072 2304 2559.81 1536 1152 2 PINHOLE 3072 2304 2560.56 2560.56 1536 1152 3 SIMPLE_RADIAL 3072 2304 2559.69 1536 1152 -0.0218531 Here, the dataset contains 3 cameras based using different distortion models with the same sensor dimensions (width: 3072, height: 2304). The length of parameters is variable and depends on the camera model. For the first camera, there are 3 parameters with a single focal length of 2559.81 pixels and a principal point at pixel location `(1536, 1152)`. The intrinsic parameters of a camera can be shared by multiple images, which refer to cameras using the unique identifier `CAMERA_ID`. images.txt ---------- This file contains the pose and keypoints of all reconstructed images in the dataset using two lines per image, e.g.:: # Image list with two lines of data per image: # IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, NAME # POINTS2D[] as (X, Y, POINT3D_ID) # Number of images: 2, mean observations per image: 2 1 0.851773 0.0165051 0.503764 -0.142941 -0.737434 1.02973 3.74354 1 P1180141.JPG 2362.39 248.498 58396 1784.7 268.254 59027 1784.7 268.254 -1 2 0.851773 0.0165051 0.503764 -0.142941 -0.737434 1.02973 3.74354 1 P1180142.JPG 1190.83 663.957 23056 1258.77 640.354 59070 Here, the first two lines define the information of the first image, and so on. The reconstructed pose of an image is specified as the projection from world to the camera coordinate system of an image using a quaternion `(QW, QX, QY, QZ)` and a translation vector `(TX, TY, TZ)`. The quaternion is defined using the Hamilton convention, which is, for example, also used by the Eigen library. The coordinates of the projection/camera center are given by ``-R^t * T``, where ``R^t`` is the inverse/transpose of the 3x3 rotation matrix composed from the quaternion and ``T`` is the translation vector. The local camera coordinate system of an image is defined in a way that the X axis points to the right, the Y axis to the bottom, and the Z axis to the front as seen from the image. Both images in the example above use the same camera model and share intrinsics (`CAMERA_ID = 1`). The image name is relative to the selected base image folder of the project. The first image has 3 keypoints and the second image has 2 keypoints, while the location of the keypoints is specified in pixel coordinates. Both images observe 2 3D points and note that the last keypoint of the first image does not observe a 3D point in the reconstruction as the 3D point identifier is -1. points3D.txt ------------ This file contains the information of all reconstructed 3D points in the dataset using one line per point, e.g.:: # 3D point list with one line of data per point: # POINT3D_ID, X, Y, Z, R, G, B, ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX) # Number of points: 3, mean track length: 3.3334 63390 1.67241 0.292931 0.609726 115 121 122 1.33927 16 6542 15 7345 6 6714 14 7227 63376 2.01848 0.108877 -0.0260841 102 209 250 1.73449 16 6519 15 7322 14 7212 8 3991 63371 1.71102 0.28566 0.53475 245 251 249 0.612829 118 4140 117 4473 Here, there are three reconstructed 3D points, where `POINT2D_IDX` defines the zero-based index of the keypoint in the `images.txt` file. The error is given in pixels of reprojection error and is only updated after global bundle adjustment. ==================== Dense Reconstruction ==================== COLMAP uses the following workspace folder structure:: +── images │   +── image1.jpg │   +── image2.jpg │   +── ... +── sparse │   +── cameras.txt │   +── images.txt │   +── points3D.txt +── stereo │   +── consistency_graphs │   │   +── image1.jpg.photometric.bin │   │   +── image2.jpg.photometric.bin │   │   +── ... │   +── depth_maps │   │   +── image1.jpg.photometric.bin │   │   +── image2.jpg.photometric.bin │   │   +── ... │   +── normal_maps │   │   +── image1.jpg.photometric.bin │   │   +── image2.jpg.photometric.bin │   │   +── ... │   +── patch-match.cfg │   +── fusion.cfg +── fused.ply +── meshed-poisson.ply +── meshed-delaunay.ply +── run-colmap-geometric.sh +── run-colmap-photometric.sh Here, the `images` folder contains the undistorted images, the `sparse` folder contains the sparse reconstruction with undistorted cameras, the `stereo` folder contains the stereo reconstruction results, `point-cloud.ply` and `mesh.ply` are the results of the fusion and meshing procedure, and `run-colmap-geometric.sh` and `run-colmap-photometric.sh` contain example command-line usage to perform the dense reconstruction. --------------------- Depth and Normal Maps --------------------- The depth maps are stored as mixed text and binary files. The text header defines the dimensions of the image in the format ``with&height&channels&`` followed by row-major `float32` binary data. For depth maps ``channels=1`` and for normal maps ``channels=3``. The depth and normal maps can be conveniently read with Python using the functions in ``scripts/python/read_dense.py`` and with Matlab using the functions in ``scripts/matlab/read_depth_map.m`` and ``scripts/matlab/read_normal_map.m``. ------------------ Consistency Graphs ------------------ The consistency graph defines, for all pixels in an image, the source images a pixel is consistent with. The graph is stored as a mixed text and binary file, while the text part is equivalent to the depth and normal maps and the binary part is a continuous list of `int32` values in the format ``...``. Here, ``(row, col)`` defines the location of the pixel in the image followed by a list of ``N`` image indices. The indices are specified w.r.t. the ordering in the ``images.txt`` file. colmap-3.10/doc/gui.rst000066400000000000000000000060071464745566500150240ustar00rootroot00000000000000.. _gui: Graphical User Interface ======================== The graphical user interface of COLMAP provides access to most of the available functionality and visualizes the reconstruction process in "real-time". To start the GUI, you can run the pre-built packages (Windows: `COLMAP.bat`, Mac: `COLMAP.app`), execute ``colmap gui`` if you installed COLMAP or execute ``./src/colmap/exe/colmap gui`` from the CMake build folder. The GUI application requires an attached display with at least OpenGL 3.2 support. Registered images are visualized in red and reconstructed points in their average point color extracted from the images. The viewer can also visualize dense point clouds produced from Multi-View Stereo. Model Viewer Controls --------------------- - **Rotate model**: Left-click and drag. - **Shift model**: Right-click or -click (-click) and drag. - **Zoom model**: Scroll. - **Change point size**: -scroll (-scroll). - **Change camera size**: -scroll. - **Adjust clipping plane**: -scroll. - **Select point**: Double-left-click point (change point size if too small). The green lines visualize the projections into the images that see the point. The opening window shows the projected locations of the point in all images. - **Select camera**: Double-left-click camera (change camera size if too small). The purple lines visualize images that see at least one common point with the selected image. The opening window shows a few statistics of the image. - **Reset view**: To reset all viewing settings, choose ``Render > Reset view``. Render Options -------------- The model viewer allows you to render the model with different settings, projections, colormaps, etc. Please, choose ``Render > Render options``. Create Screenshots ------------------ To create screenshots of the current viewpoint (without coordinate axes), choose ``Extras > Grab image`` and save the image in the format of your choice. Create Screencast ----------------- To create a video screen capture of the reconstructed model, choose ``Extras > Grab movie``. This dialog allows you to set individual control viewpoints by choosing ``Add``. COLMAP generates a fixed number of frames per second between each control viewpoint by smoothly interpolating the linear trajectory, and to interpolate the configured point and the camera sizes at the time of clicking ``Add``. To change the number of frames between two viewpoints or to reorder individual viewpoints, modify the time of the viewpoint by double-clicking the respective cell in the table. Note that the video capture requires to set the perspective projection model in the render options. You can review the trajectory in the viewer, which is rendered in light blue. Choose ``Assemble movie``, if you are done creating the trajectory. The output directory then contains the individual frames of the video capture, which can be assembled to a movie using `FFMPEG `_ with the following command:: ffmpeg -i frame%06d.png -r 30 -vf scale=1680:1050 movie.mp4 colmap-3.10/doc/images/000077500000000000000000000000001464745566500147505ustar00rootroot00000000000000colmap-3.10/doc/images/dense.png000066400000000000000000034071551464745566500165730ustar00rootroot00000000000000PNG  IHDR#jgAMA a cHRMz&u0`:pQ< pHYs""*YiTXtXML:com.adobe.xmp 1 L'Y@IDATxWu7wP@PPDQjShG/zxx?Ŀ}vնF7Ւ%Cxr9'?ɖ"KUB9;| Z\|@@ \ rhIhD@ @@ @@ eE`>["ˋsѪe'ߵ+HmmcVﵬ<cآƻkhkW+wʒ;xRӮ%b#i7oȲٜE UY̌6gs&i"}hdsZ,Ocx>(nbӹј%i΋plƓ?΍s̊u]΍Yl8hcKsK&hb]ڽdt.-HY۷rbW-OXg0Ngӱe Br mY/ZqKS֘.it:J1o ιwhycGm4Y2pl#pXzƴo 9rf6m>y}3ʌG! ҳD2iiʎ،r)g22 6aVkϐ: 4Ĺ)+ 69}Glk1+ smll X?sۮEvֆ,dlڣ{-OΎ]\٠7Gڪl4؈6E_ԯ\>Msk5Z<>٩ Cmsyjժ5ջw`е/13+S|^bNN,qҬcO*S ;1e&|&ݵ3|b0Z4f7Fq|2漈S>;sdjz}'3vU+.s@X5A4ƌ֑&F>J9|ډXٲno`J6؈s}>1,k;1ssO쯾c;<9L:ae;ni2,_(xZRL3d#sZK^:kl8,<㜛X$7fpgN4?ދӎ(mךԏy\iXjIouZm2Sk"ΚOShԣ@EFsY$i<\gk.@w¯@@ @@ )" ;M_x@@ |"t[%E6ӵٮZpr@)R[ׂC^VK;+Hr 15dmnHk׃T-V!P5*63 =YR4 A q_"WQ!x,IQ(,e2lC>C2$FG"\?"7EF!'>j,jh|HY3!ҙ=rCʗWv_1uX']^eO 9Ne9?ҟYQDDJ=z qGm ,օj\i)qS"Ez'!rA0&cr6:gJ;z.d1 o\VCC{;[bH%Wq9;ER{-CA HEfJKQľ_C12+vẕ'`ץ QJ{ꖭol{mnv8?0:nF 15}<4jˎ%W 9QùC>D#"\!x"sRs4{?sD{8s^։YE  ÈB*U tՎR1!Рp NSIfk8Lsʔ?I)4s)qg2Omk{H߽aZٺ(xY.!48pn.sg?vymKm2xj9r|P3/@"HqкP{SC9H) )D4zKf؄r}cɔN52$&"g\ cC"g՟`G47y1"U@@  nr`Gs1U;?9BJ]NaA=8LD3G)NCD&yL[Tn`a$ռƒpP(nc0frJNrޘz4RRy8F|kmqYaڕB@8{៷P|y;:FlU=Dߒs rj'=@"iPP+džYQ\;Kk}*`15]xo[UiY[D` m':26/-@DuQ'ŵSǩ 'zC{ - 9bͳY祮 Kz!սBA)D2?Q9ppPDpwޗ39yo#7Y8݇! @@ <d額caGGWg;"qE>BHˆQ7;dl֪3ځlBAIaS8kRy",!jbqv յEaaPt_ GꇜҩmVRhu:8iy9> }Z`EȽ}tu>HpU_B2 Գdkqo>.TDlr~+4"d#q`eDI8C9o7-u==+yBM;OB8\rU4uJ]HV{ۀx߾rŎAC>W57f39Ka5\LtxWpL4Wi<\eƆe˱DĬb"#w{Ǝ@ʡC 9/U{["D|y<ؤsfΉ9N"ITϵsg͌*nAw4z["UBG!nͷ>7= 0DO$&SN3xznKY׸YT_ҁKuPTi͛#R!4'ܣi(uz9szD+҄ھX(Uo9ׁ@whï@@ @@ &[< 0d$&+ѫazOH}29!;/Z/\u_|^3ǻ2,Wz@@ <Zʴ{PZ:ۍв6DY |"{CHkϞ Lvp樐(v~Qظ!&rHVr% 2Wnn%*yﲛږBK"Dl)~K{rC*SgP`+nGe/Eߕ$]• =kVO}:Q*ϙ*w(Ҁ)&-" h^#֍By"=abJdaVI`F4?> G֡-b=Mn T|M+ i޻:gGu/e"Ck{헌ٟMr\PQ4v L; `c D`l`sZ ȁFu 3}#ksUZJ)E п0_a@@  9CNBsqKWT u]Φ_%d!HUCIPBDoC%+Qn˂x)C h=CU+*8')x!'z &G{FN:vε []28^tYN4mKh.+z&2?|'S 'Ehbmx9T :> "%A{rFмcs fyڬk]69% ~D+A&7R@@ @@ [" Ń,271Be ٌ>>'DF]w;g*A. u~aeO6z`:\2z]5PĹ4GB6w|Ӎ ,d)liމh3 y^~@@yC`/J*2 2\SD!eu!=:9xl0.<l r< #wV?"~ RŹ]($ud(zB]%96ZVxw){gF#B&0Ӝ)9NygRyW 9S}"ef> Zw"MH$חs$m[1\v|zFFαy? }̊?Cu_=> >9F4k}3?Fu EA{g~g/w'㓎g}oSosgI(!E^i?R[>I{ͬzi=TۉV_X2rd៤:>1u8iH>g\tz5-x2mEۅZuacՕ G! c"x(9 |}pW9{E<4]Ը)2*tUDh19©ˎL$2zK>}H N!TEV4F%-D:8y Qxꓵ5Ǯ@Fh)"C弇 ERYeꑿbyIى@? fldb]Wq~&Q%/MS Un0 ՝q&tU*+PMC"O."TJa HAu ܁ Tv!QCD B/Q*RFsp cd-H2iV@#TcoصW^G6u^cݳMB5/RtTRܕ\a8LM~VRqU-m^4Ug2x0,+~Ϛ PÇ)-_65/NW 58fn/,Qqzf He}Wogp+UˮWd8 X(謕]fWf>XWQpep(2w6WvFtd9̨.ؿʮ@޻g†"ذQs}mK ݽqo8e!!rt#;e+YF&_z08u(9DYK?z͝kW_@:3=5e]+c0p˄@1U `Y!Ç8#0^1 CNoIamh|!GU: zB&c]]{aWvQoz2N1E7..)K/\ju}d}k4Wɯ` 5>YNWluz5h 'v@.~RDt9 M &w@ x.\?hF@@ VX XZ cm?챥crg35꧘\>Wi[y۶BNTPlzE 'x>[.-e)B} =u*6%!!R%nCPeOsU'47 _*UwH ݝ[Aؠvq0]B$y֎p_*Cg~xbޠDI rg}|x A*U-οPWC,*aU*%m%ԦC@'j^Vuť>^JP‰wQ_k$s"-/T-@Ŭ|r(\)mw꼞toBC=KD&Q 5j<@yYr$'! *(tzpun>uyO gK#e:\9q) +sʮnLPnYRNޯA& c)B0 ;9= *Z+붺7XkpquOVskKeRyt.e0xH5/Qf<"D6FV:C+W ˽JꋣsKr>ҷַ+҇C08`Kv+ vpx*[^]C$J*(_ho;,[:g!ʅY{9 C^`@|{BܿcUwC+xa- J8sŗ_~{ J\ Ϟ[;ށ$׶{e6w_@|n]rˑDys镻7ligux燶3}slejkV?ﶱ{5-|ǧUJp4^4DG`S2% azzƲ) C{]kB@my61P2*xawΎ? pywiej@@ ߀nKU H}BèCqAWLjl v' 23BH7ȥ$PCI2^ƤHh飇=ǔ uF.A> ^:kX*[f0Ӿ!XhXC^5G &IC*|]!@@ |q`V=l.F8ŊVex T95s|  '[RRcYpVaUN'b\ ,̩P^uۨP!&!*vնc+:tqpfϦ1[ڶ ۽qRaڢ~R*ooRv:!7~EI 8Dw Bkpqʩ]ݽmCbCO[R#2߼IN6|ᕫ,Y{NHv>F8a3Ex(g'mˢ\nB[}dDŽ>'NwZoޣjbϏ0Ur0*9̓s!1;Ng2 `6IcT>v@AҔ!M УM+:}0Yfxl[WTz5c(3)r==?<<{{5 aAg˶ i6qY9qtȪ8gܽm_![>GzpCBCܦ F7LJ'v}iƣ{kk[6d1(ԑ]h} Ƕcز8* /qb>*gZ0=:dpuQbZ pxFԴ!!ND< UTjq?ʾI(1!s9'z9[ #)ͭ1,dn",R)9LPpHANG8o@w{msg[͍! l{NF`oS+_?yC{w?It|[C,lWZjm0ޝx'Ƶ.c >,'Q>" )u'&\h{7yGȐS룾3&:F//\C@ @@ "6{*DcC6Fڈhb.-O$F6vksbՙY\-z(K Z$(v"l)\4FػT 'd{wzA^U>%dH6N ]*W((n4/qɎE?= <@@ |xz/$D){R> ?M?7=QAOO|j|(J;zsoUnY#6dkq=Ӈ}SH縭FAAzi rEHOZǐtjDx*rw!yIz${kC-olc3{ǯvB'rCB% $@u 0̫yBG6^aM6Wʋ-8[sNRTO:kʉ@fK SD@ +`_60"}ɧ#{6xUژ#ʡ-[q0Ah* uQ-B`=6CDvNJPJw1N]ZF~qQS"$@w D55^߃o]r?E-$Jc]1蓬>Z1o `xɀCިwQ_=d}2@5&w 'yc $ĶhsɽX?`_*; rӓЎŰPo3PߗQ:*gGZr8Q'R1׸&V߼ϯRW@ <Ј@@ gSٍEWv,I&%c 𤝝}n*`?>'ƔO˖nR3Ξ?/ !(匏gq-l燇V-GZVޮ\'\jxv" v߲ pM%Cϲ'?R/j @@ y#9ST1Dģ#kۮJu] Cxl%K){!Q{CV**D,"ĜIj"OuyLKϾDL JpK!8_BR@ETBo':ix2ϙBo_q V'ܳJļ6=tx<5uhpJek_Bi;#Uk0I {Jh \TR@{;T:nCxL ҽcs6vw֭ÚJgхo"b@Da\1a! (_'|f<~ҴrEX[_;#W֦(icht/G=]+C2FzKW1减i!c?_&Z #BzX=VZŹ8()%>j;|0KӶ%H(5:>'3r<)8|/ޖF~6]|<޷S d 9@.远Q(ufuBk`Ii"y@:(M{Ox>6"V8vU۾qC0(6!#:l!p'*q迲˸@U؋7(A1Z͜)IΟ%sFM7# S><@@ )DܽȦ}htB=@=pcפ1MT7Zs~Hq Eu"_ NiH 9ĥULGZFh]mx@r.5wD3$Y ]9u~Em22Q\G (U 蟋LCM ?-0 !ܞ%ɇE_FU|hnٛ7-Ʊ?>':ژcB>#om~I{oQG[!=rSkǧ'r1:$NKЖ(S;Fz(RUŔ'[ğ"omAS)!SSW*cx(*u a )iDFАZۜ z'*Wx.ss:90Ard'Ve_B|rUu4Czė ݫ(֖!QSrDT]D[krzWE1@gʱ]C6 O/i wWi{QrZAy􅥚;Dq1 (1{"eՎ(X.1`Sx%~>G'95#3!8cDX["y&Gܘ2DS $=QZ Ey?KSPcr-(?zs01@s"Qxx=+9ϼp;Lוm)j\SQDBCj'!5+_6s1"2ﰎ66^@ A瘏Z* =DO`1|s"<] Ƙ%q"ȧκ@P_@@@`|%" ~v#+ JX!/V!,,Z»kNDT/e꼶nbP`>W3yG#^RhgD/wѻO#pa7˾Y7ȆV:WB!sC"nqȆ}G"܏}XO@@ Y!wDb xh#|RyZ"DLy"dCO""r'_ 5IgJ| QÁ5qJM BKUne% V|Qr=qIu+WHB/rxg*W($$%Դ@IDAT ڜsF̐CN$9Ex+0bFRX)CxmE'E$fΕm'8j/QiC7^T}|BFαSDJqcǔ`B=k阇Weϋ i>B&U_!s:)G9N'ESE-Z㨐 s>k$ѿ9Qm,JDcUIp3g 2u(/PAwf¯@@ | /MݐG@ 2ƱܰHw1" oل#̡޶5Gs6 x}bc]ޗGzflLĹޒ}g?^:_|rc)W>c?oAgbH+zʉ>g%ݶ{?[B!ذ9-Ez({8C66pO>Hp~d:uF7@@ L_LɠTn r.2ef-aqԆʅ: =cs_g@@!{`G=JԮ"~E)td-Ya'D` EZ@ D`JUIzSsYuL0"e^tsD]BeK-~0VmSZRR*NJ(LA)qu@d|\[C> HeE!ה#Y}+TrzKE?iGO*gǵ"S")IPt8?2zj|&Ji2w2Tf}|J;"=9H,v VAr1YI}oǂRs*GXG_?kT=0ٽ#7j(ZbI:k;װPW=c{<9sŒePԧŗ~[zջ8Pf^^"D:f#:sQa D\iV\؝;wl͝5B_$-fs/oڃ{vyZmU3V$}#m0#ڄ I穞P}>]z-9Lp2֘Ρ#,sT^Y" |k]{x_VAsO6t݄%X+S{DQ? SH*C>K>I@x]s8Y(Ig k~ԇ?g^Wp _ty@@ dMbKPCPDșaC&ZŠ~4)H_/W($ڜ=y':s VV1(X 6S=T率&zM<9Rp6oT tխ(L6#ڬRɋ2yCsY쳉VE7)f JБ4B@@#`m ?kP"=@GECwv՛7w!Ͼƀn>=sER`V$` C =Fy 1>_ݺw亹錔qXϮNU OvL2\qRJ9.UH`DE">OnȮBUD3#PDcEq&[ickJ. 3!S-հSV$l&ẗȳI -k1:=\eLdݲCrӷ"+E[&N(QJ빯i(BVzCNRjP:G6̀:P}֌:̯DCT"imggjKK(y۶QJSl ?|w8llۍk o/<]=}kllKV^~/}=yIt#oP1PK*r9oȆN75@s)إo3)A5L׊%ezCS܆ӚT@e-z\wx[eqA~:?|g9Ux{8UrkQ! |6!gPc` KsDng'!['9u26loѓ>W1=V+le9,+vm] "/B}xLn/ݾ Q_?;!B# @@ >7e:i./rl`ʺbG]6"lÛ͝~:q‡MU9/㟷1*Dlsʗɫ_ 9EvOD{b7lLA##V"i>Cv+:2)TEԍd *mhGnsX~žicX2UgDT|DT:s7S~J/"?N"<Jf$,HV9"ujl*]++lE/M[DKO1nڼSFϹeSa>@ ҫwŻ4=Kr.e߷wՊm. ^{K:8A֛Q (}7HiF4Hneliދ@~/< ˘sMY+S/7JTjCٷ^w^E߳{NZɖ/S{[+ps³=@^P8 ϯ44{i2Q斝-lZ7^kns7"̿vfr*%19Z3ZZ"['L=vctڕC'$5/nay b"h̘}^uLp('PhwUjc6)OP2y(C14(30rT(S=#"H1f^A6B;8|BY6L'_V`p?آR'ZB9%/jF{=n4{D@@ XWB[XIrx4O'y߉HG@ )(>4*T+vQu߇(ױBz=:&7pE++6+F #*}֫ǺclĪ~ݰ"5sߝ kCd_}? Y*ҸIxt]VaU/=4:8yycVsC&4;<=l*h[}ܤW}CcpLc3Oo~ž؝׈fF{,g-K̚۰/!!2!D6"22x}'1E!nXaഹ$8L6?'2bCƶvУb8vK^&&."87U'NM$MqMD@21N\!lߢDfPsKV!1d2f-ާ="\O )T 8?"3ժf/\# Oݷ^1d%!3,UFVGmthMtW|Ws ר׭bCq=Lr2U_ SPȗ{h\zZC+U>"˕D"5e.[F"ȤX"8ݗ Dr.HQb"m]>0ꐜDԍ E>10Ԧ kg!R(g+D!.Ԧr^WVn!͛lv.MO3uڸZWzNF"eXDJe ^oH Vy{D։ V[tn7穖F8 Pm1j3yq!鿜Er k9N6"w)˯P>dɩ$mdBGm/ޡ+77$c'V`})[owUW8W].R{6I4<t\j+х7}Jbϊ4!/`))nBkHg`ܖ,@Uﶡ#υgz}]?u{|s[Y.NOtJ7wn76}}[1Cv^ڠo/:ˡQk>,xT5wcQоWt ).*kBe0cyucZơ8<!y-SAnr3gs(K| \9mFB*v0y0@ad1:rCUT6g2y bm kڤ`sy}Pa0g|Aj mnȠUy.{2f6L02Z|!1tgwˠ_x(lhS_֚pr o'ѩ_דz'<@@ $+FH{{:ZG{UO=DT<Ц1[l~⡝O=vuŎ [WnbI8\# (n"?n"s+=1N¬=x(*FݸC@Ql(\5F QRCm!ؕ"W֝Q}!"{1y*}}OzZʺWOr^rKĢއӷ(m}vA#-\NZsm(Ɖ F9]a-;te1 j0c1לJe* W 7蝢i~cT~:wMLH꧷p\[$&ssWv]=;.xCCivPٹbU EZqX*sV\Z*xTGV} PpvqavWnж~dbͪ+CH3f/rVl6UT7gM<ٝ<ݲX-\ yeOp]`.5t>]w4&)/ڟ񿰛d5YKWw[ok[wnaϭūCXY!=s\v{Vm2~8s+zEb, )>M9W ɈݚiZrg!ZoR_r8\]4/|M{ih_Hi8BHv=a柊\ӼTrHuGNs)ԵW E}+ (qdGեzBXc|UrQza# 'œy0`?`6Iߑ眅ʀ)U>ވ(/^:;\iʧqA+$ĉa)WO[ ǀ2#fѧCSSeДe C+g?h{c7wqW5nΒso (WN9G0Y p|dP]\p @}OoR^[g ڹ '{w-@nr  TRz d@駵._*+L9 <=euͣ؃3~s'Y{ @8vi1,fJr[n$b- 1!CnLm\-HV(- 3Xl*1.=+&VM-_6ǐ%\I!&',%xL0UMd9\[IVFf5ՅLu db +tph b//sJrQd۴WfӋEg^C,_@,qH~I]1]i j*_@ּ(muj2IP6R|aa"%/Ϧ~?D:gtVm@J.-}qx@y-,,23Z||g糿*I',=Q&.),Z>O } Q Ȝ^y!G~IzƕtVWϕ7>~6?fͭW!'X> PmsN80׭2ʵ[[q @1=b^m䴎M#HǣZϼ<9G,0L(K(8߉-g {|B[ǝ?es̜P.#桻iC'wCNlL8mH9x`hsThme^X|or'i3y0m;G<%s|*}z%›5iA4)d9A7EoUYX/S 3A6ީ!Fd[ X{Pkܗ7'̶4[!mK|dЯxYf˲,:J %:>Q! ڬ~] '?ź] {$6MX޿f7Qaa PZK{+3 /)b;-!nJkE朱oknI29$-s>Fڌ1 t2v4x%q1qLrEl9N0tCR]k$SofFk'fsZe$1qLEe'8_.&_[ @nr |,%d~F k X.]GqPQYhPhg=T+&ʷb#ְ*;>gkRlXy YqO\KBF +밎u%͠X7+,!Z|S:ZZ,f`% r% l@>qAAo\+Yv4U#33zu>Z5>9$A=66/ΦNLw܍URE gm @ w u5ItaRf{8->yTTZ ;m% e p<`V1Q&л 6t:E$ŇP(gx޾w/^}d{Mg'PwV:9\s[N͸W i 9m(6AO"AfD{`{O|+$}h1un 6 ›Y5A45(G6Z Wcm0<&FDQW>EclC  =BiN|x7 P10!n$Lϒ} ~8d^nyߣ⃶1Dr $9lb <&  z{Iz*1 Ac'7CN^EK1:&lB~^" <3y7[h|Տ;yA 8}?$%}OkS^+-7JhJ5Gh >oYFh'knZ*uDP NM->}iB^`_QvuQԒmSLN Ema#w&F3+\tɞV*KƹR=OAee(yym3v?mc rFKE3@7Hn ,'-q/q}8spVU:b:Ȱ)x"XOOfX am@P.wZɹpy dcj: }8Ԃcv$>:؅FT8B0t/pg˽瓒wbe~/rkn/r ~gS_jkt0>>ڢߝtDvgӵ "Y\!{՟ulijvsNl7s:̷_:m~pH`P\bڵlUrL:]La6$xD\%˼B&ʛd+2gۄ65#>Yϟ@Bz*Fh9:_%Qe YΨl I5!O b i K`Ų|hWPjoo/?8kt9UjWċ7T=>!ͬVxIR?A~B։Ȅ*{~qb^T7 'j X[?Bؕ=9gds<(22n>tbs--?S2`ޏoD ɹϸ \#]OOBZɡ 1Gɠ0~?! ƚvS57XAR] \јۂ7o |1U/,kĥ).b3];}B&HKm`8zx׶#{m>xkd MLϦ52j8޾}?}5{A iT?:<<8'*ܾ}/p%׆1?9l2!vHdv-|Oi/>^9˟;pXU;g̲^Jจ9&F7`b<2^$!/i+K%*TDA "0v܋6mKU.qGUQ4QmJoEb@{?3CySCC%;%Zf:ۈb{ h,s&9RoU/PyS(c[w_{8#mi~Y-v f4xm56b$t+o$H0S,xkH_"h].&;j3svX]3qTh ~<|YBԬcm3, y"<6ȏ-EYe}f.ͧ|xaꙂh"lUkږbDV%1k&D##b:"j5 WߝlzU׀bYsCilsK1xOX$FtmA2g؋1>7n~F&t[@^Й-h>4G SI&hOhsv "qJ7=TZ,7LV d%Ova |9Je J'-%ӃBzϝ3)@]B6PC=4al5Xz9X#{(pYgnհϓݴ~ }/ȧ6^kvvvhKki3 ksӶ*OP{N;?-@n//Ikf-[ @n+PK=Yd 1 $o%\dJe:6md d}OGM"w Nܽ.>9-8y$%CWFu~F!xdҮ*u.8z}׌[(<[Y1I&dNg1e"$u_ThRG 4|^ pgt~d@6i [\9ե^ wlTx_lAd&m&{ {\(!m*8SV i+gY PHG^NLrnlc|{,t`?P6ݝ}\/!_'wy:5wQ3a:)Ldє1J8+2aMRϵ]N؂<or -[;i QyՅٹt:Q:V } SgCumdx)w9or <lƨa-'W{ےvb&G5X #l'DKSJ8;s<>Sn1ׄc.qoh,؟>gm N=hXM0JE"~9F >3%b 15U:%S9u=~u0 .Hh eͼm4رn><[pzo쳒}`+3`MIbqs$gg|>#ll{^_y g"Ûsg*xWfx&J|x;23]HNkkirn&Uwn6U 1h`s{;>x9ݴ09* b doaCZe1xoPf+g$x}m(Qd/(@,Wz*:0sxV*2YMҹ|:josedt$q?oPz>t;H{{$2P:lmJ Ot^%;$"br[ep'*{B]υei?̸.hA|IpvY{ 9Mnެ/b{zyx=ϱ/_5}:(H[D^%>o{d/#IAIv2̛dL 8o!tPRSzWz|;d2 mSv7C<FKۦ5̓ZSMS8,VVQcSX%H $6+Dm{gMjHA# ponV DyO{)-1q+n2x5d͹Yb kvtamجdߗ6[~IXwwKNwXk(ؠr>?է 6V`YŬ>35/70fW.0؋{m8 fyؐHzJ{fj#۔R5 {ݶx)t; >]z۳`14y?גp 5U@8B^t&'Vd6K;̱f\<࠰mʉnڤ |6^u?.'D3grv8q_d1˖\ZnYq<ܲ6 ]C: M>lNNկ~LdR'OCgۻ~q>mpW>x=a9<[cog1 9:?\}f yhM%@*ǜS_rrr߽{77G}={P܎Ą>j̡shm@=C`"CU`p{hc6{}k6vRf_ hD{vR %s\^LoryJ;q'W1"gtwQ#ԁ09c45``|lk}&_ĞoV$/O sioIe{,,v6yvτcK̏%Bay̔h66蹏ľYA~ goAf,iq9N\KL0 68pژ%>&j;>58g|BIgN:`Vӭqð ,HO-QLJ^"Nv8<$fs2}4Px xr1̰?!ArUB,hk_L3Π+; W9*>HtsV];9$#H_♝?nʜ۶kCkc7wo st|nZ&}+pf ^Lk`>o9 {nl?l3ҹ622%dxQm0l7k,r\s޿Q;Gfq+#Q6#E_K zQ%">̼*1m0;)4CO·%v*g.N cꁶ7 N&{;x_yq޾8#KyLZ!1(9|8;4w-[ Kb[ @nu-f0 V0I눘O+6 Jc Lok fB:^p4f6+~ u3W։bZoisDYnQ6tґA3vA YLGQt 7V"dj?.L!#ff.Rt ¼NtQs9j^BrAJ >J&Vtc*)Ax~n:=z8]Z\H/edG M?G:~rzr)HK >؏~_t 4nܸfd__^#~>n]#`Dt%uE}"k8._YL[SZP_i48x5FluZHGvp]~Etl\ Ņ)@V*? ái`6HwȂW%3]&/sMQJ{ G $vb6K\l6 N~bv ḱCO-Tq)! ffN<(wLUfoq/-[ @nWU:tڵ4*k{nGZkC ?UH7:zk23,]Tx|7K-u,qs|iC_$%sKӋq#J1D3dA-krR'[*b)}m`4Te% kN6VB/碄us&Mmoᮇ]ƃ!!%ZFLۓc'Q* ~SX|4%C-"|hlnAҖt ?OHC.=t=dJBb /9 Y Hg{cO ־ 868WSV7AQ. 4H`lbWۃ49dS*DI@~0TW|?m͝׮>o"8qdj#;~af&'| 9y b: /Iˇ0!o8[s Ɀ ^:nYD;9)IVB!='CCr] ^im^ -6UK8?Ivݥ2w m}U8I0V*ɑtKȀ>]_qKHݯs 1xg>Ƹ/j}>{2 JFw CKto5Ri'8"eې8L#< 9 gmU0It_ϸY lT8m.!^oBY" SxLg"hΛ+Q 2 6:_)t% ͨuDH*6Q\<ڭh:p9ܻ2ʮI+.>5Wo9 \R?c@@H Qʦ׫izz"Wá3` ܠ)v:$afۆ!/9gK6ցJ'itl$"N?=)-B߹G=v#Vħd_H u\"Pν;ick12!?hp-^'x3~]ix`(=y4FmGG8ƬZc!xftt^3bkk3.-Ef[8zq$㥳lhhX\\}MpصNح c2^{b<#g$QA7QdNh90܏ّr -[%@I5i|_.?I?~7]X(׿H0˕HМ}?d=͛- V"C:0\@r|u =6Yqp,pOٰ>>e0g@{k!#n`exifutH#~9=77v?$pr96#Ĉtk I$s#R8:DAYܬrۦC1}Uj/^Z!3~n> !u Zy,^Cd?x0t&lUбs!GSÞp, iM@zcM-y2kH0 შ'?W {E2@0^Z^YJi vkKc? C-;tb6  6p;e?jyv$߸7dl ݸ:}Gwːc`o$'ƆC!.kUap<1¹y/+UG>T%-%F G%؟x/Ey ?Wu (xo2ڨ(K{G[)^\26 pRTgN|%|>eW=Wc&k:>ksKŸcGڌ}[ B 1X'SB_+ePA_>o1Ir -[ @nr hG"j9󆔖_eΨ>r015ՂjfLp;oo{-p,x~ANlf%!iw g53Bi@wd"UFz qTJYolIn `gOgg7I+Ƞ_*G['A<{=o@+J>~'Y8KN‰a"A}8b #84gfpޭ|>` 2:8u;ntbgf[:h{ [="9 KݧLPG^$>@qD]pnꯛ,6Ci^6=M9kkB>}rƍd#3ixq:W㇏3iii9_qcdtH[uޱ>vAp:tuRY>A]㎰sT άcRp(jL'eO0ǵ(#*aLǶѠ㣧nM_0#yA'^ 7c)?m߶u~}w,)nϸC]_ew:JUvccR*$m5bD] Lz`caxbxYo'wįdR %1WxT`1Y h cWCw\N6TY5.O)A[%*(:`_3ו77[mPrdm^8ߩn7m3@UeE#TXG@5dϟI]GHX 1he'O8ۤҗc1$i37{JUƔ%-'bȌ]=};/ku,"m}46w"-:ԋj@K7Zi|X[LGk@Md}fl^q{7 }!ÇbѶ-dm،Z{;Þލ ~p(~~6Gy@k6f8%I^Äzp,]%b!{7s^{^1$3| .6O#P{JaV8;~F~}JՅ4O]B+ B{VS2'G``-ăfh P߾Z:A ;(½xҝ2(VwGlV*1%H 0&(n7eǁ}]P'_2@.UI0?sruMlт>!;ۜ;s( A@\{9cyưJiὴJ}qxIqQ;.R?׷_U"ܧ` |cڤOkR#Ld*cpEHkSrJL9\] 8GJӼ-NfqeRn $7nJmgHnok$l3keM 0 Tq]jY>  Gx!MdH3d9}mj"]Hn1~YjML4UKb{'ej`F2^C=lY ]ksYӾvSx}Cy#`">cO lyc_Ȝ^ ?9;ψ11r%gP44cX9eMOӓSiv zqj8~82GƆ)7G\o lN/1~*Yow`Dro (BK/A(* 6T~$d7m{ j^ho >ƎPV;DAl)g}$ׂ~APp3zoyx]h,- ,wS9n EP1yfl ݼ9E)jZz*a\KoLDr>o-@?׏4YCh!F2M8 CRοyT-[ @nr x,p5$Zb pй"z %IНD"Wڀ0ж]q/f?c1GAG+hԴC`4`ㄈ_?#hJ*b >/qXg:]nvq-. cֈY.9\rF$KZjcgm/B1lé "76:@#uǩ=>6=xfPo` 5wOAIlf#CQHtt`}mYsSN^2g~6;]{p@z?d:$+݃Pn5s>@V8@ .lb'!&5j~p2t1A=Q@=AA3T}!!ϵW3@[cY{H8K+sKBی~,;;O?㫴0Υp{ 7®nt t8HG3h)'OpX,>5'XKS{-ᕀAvBc;gaE6@zN)rd_M}zKt(Ƀ{i>3>kߌq$ͼC7pɇI ZaOFn]zt 9 捎 ?Qdz{39;}c7_9kusk#>kq@e!FaxuGo޲糀~GŜԱ;G}ј>xq=Ζy_'&Ryo'u]MXf> rt܀k@'$d߾Y%ou 7 dGYJ귣.seA,0kxv'8Gr5Yw XrK֜az_BV ~ =׀\bˬ"ckb4S]mBB'V9!+TBB1MeǓF8R"M, .~kk?cFv9:\_:jAwhٷY dH- ^82 %*lZkG%OO ŻS2o%6#Ex lenlG6qFi*x- jo%8. 8=!KS݀>Tc+N;NO!lQz335O $b!PzQH:0cYNm) Y.>F|4ķ;b~ So0r~8=4;'dz'ޣ1ϳfkkqa0S2̝7_L|p7- u!-G@\q~%k\? !ɠ&$֟F-]@` ,Opz?v' ȣ a#E߅lt[Ck[{!ȋ5Z@R>#<>Q9ssn;'NSL~x{s}@ 4??;gR*dsĽKR$ 83}50hKW2TAV[id)J.4i }HYdJz`K3'r -[ @n^Z RGpwBJ,r%u~12%3#Vnͭ42:A4+ =og?| ΢?ۤ#Zf03.P(6/|ʪ)M/>اEVDUâ BA+ I&A?E=%iek@UfY/Isg/dL$uCm8;P"Go$Zܼq>=]`,,mQA[zLx+v#/C␌ &3MyS.-k"WTh@F_֓nF"mG~i 1*d5je}t3m[?QgNԋ!`ͱYF=#8W P m2KZb\'49tJöz&ʷ0{]r܉aq8%SnuYY~Od?Zq1|pS<{MӼTfh.l+C]@YuW{G?In]M߾}b}tP5]t2!g udSq,8ôF\4"t|:19ϳ?;$\{7v}fӹtFfRmn2IwS5GwzG;Ix&}Sm{qVȯ[yzMb{ R _* OB01x ~|=}^ȭ6c8q46D6|~jF -'.q܊i|fEx0~Vl?I[Ry&ÿm(RӦDR Uaʙ`q讆AAxλn"7xn+1%, PVARw9o,l$ Q ͈#JmXSt%!U%I3vqyz #ˇGFrٵ2 O^6 ֖mr~84<ŵjhu,qt bL|}W ms*pQV:u촃q_ 8/;kU:h۬x&8|i V $^1j@QzJ^> N)յ p@|6F% Rc;`}N%#w;Oĵ@DϰS9ΐ>§cPk܏ǀ 9xnN\S=v 2kc^11621nb#TM5ĩ [vg)Uq.&糵%vmo\~|v>XׯͦO8@lKY֍{^E Dc<- =`NG%ψl`+͠`==6 P`\+  /m,Qs[T٭K0 f;7> tlor -[ @n/bYbٚKG­]$m*O.nFu:1h?V[]_M[釯o%9# Mfq{s 840ڶhO=.%gn٭HfN~LwEQ!-4XJ v]>i.kڧv k38 =iJoAbh~ǏRN'қ]KW./upG h%!S6#닋AnY~qa4O}7Y0cEw'OFҁ;K9V"_'$λ}Hcll R#1G넙.1od6 );|{H,29{l*7g=`T':tzʱ1]A?״.^oFV- k;f0ҪA `? pPb>O!}N,>?qqgHodL]!l,OR{ ެKC&}`h8=@?cԭAZ!akO*uq /1d/-0<V=.]ZL|I|iHw%@ɽw+W/,m52ݧ҃ jB`&(6 Ameqk`tJj3ZUKsP=Xjy(dy_0"S~jÑ 4* :,#}: [t"fgg7i/b?:$ے?oIu`s7m*^Ϸߤ>%=>((  kejBC~rry}wy@'O5%&SuHs?1 {(2C\ybޯnon 30v 9+dkoMc `QfߑE[uHuw WN[YKߵ@}G` {YDB1s]Tvm~|iwvތ&xEJS5Զ̸ ZKۑ>wY~ T4H %J{G&:VS3g? ZLs8^8=&:te|w6AA>|N_N:1YRO2/dn}E_|ƹX~o.Ifw*W3siآH`KVq9M B@IDATYi; n+n증13+/DlkWQ2˞ƎQ˞@-ƍ*b>љ`P`e 1˧-0Ա2r1 Spxmhv*gT^G>Y0Ft ۴~t+~FVxm|πgm]KGbxVx }^DBcfV817m:J[*OL@7Ȩ]> Kd1+v?$7thiXk:6O򙫲jv>;(W ߏj.xguG!z#n|`/#p}q$B٢$ٟ-ܱ^=p%}{-o.s郃t9jڇA<1Z 5r -[ @nr tTx5 4p ^LY }*h.:i\ 8 5C9ߦne$~? *Xˍ8˽:W>k<hx+[6CA;Ay Cv d;e֑2_PN !%Kǀ$V b>!9GJxK$XO>J 2|VlpMXHduS[Ea6`[8s%1Rd!_亂oi1d\_@sWY5]gYӕpflomZ"f4_^DSf\g1+369H9cX'ݶH&` P)?K9l} ^Сr G$8 `V:όqc@c o9?S>MM1LKҕKڕK?$m'MC?y"IxB:L,̟Q8Oӛ3T ҏj|PHOR}C2%#RusR]1ajsAu+k|BA5ZWf֌i7_@Q5[f ?NLO v萙AGa IP!!穵Թ5b:n>+|$s+ͳcy+mgJ>A +ȽsCdj_RgGߞB_ӱ<Ξ8xz2'5  [/Zv(slBe8 zpzd!Rي~7TOKd*n}P횟 jÔop,*W`0^qŖU\%,I?hwe>w,v #Zf~  Rcleop.syvF#c3XY`jO:J 4>%UC97`@{-xl=3,TVymVR| Ei.-[yA9ra֒\ӻt9:!}3r *v t4r -[ @n^. m0TX]~6VVKEj,Jr^:l,YnyN6!X`e ɜ_?OCzkLhw$?[1H@+;R^)3·slS`>e$ڼ~rZ-`FwaX0df}zQwf$$Ynf@Z<DtW#,#(m`:8$RሏfI["NF{Mvۦ>Nvrˀ[W 8f ' ]IK+= g!i$_zmU:DUdF|Wۈi:!,GTWBm$֭B0ҢQڃJבө#ifN]䗤HQkJܛMu(EgmH™]'%m:u ѯ%ޭ5yVy|1x)tnfC ]%|D7߇Wv|DoooS|Wҭ7CvX/}~n.}iZ\XH.~Wsz[pܼkʕPS[$0{ާwp @37|L<] C(2a`ysyZ$ جpL' ΰe::tsbj9[s\Ηc'dY~&h\>?}֢nLjI8u$G|Vo>̮xv9.`:~Sj;u/h_'k?I3;fyh1gVCKjW B_mHb($]R$CwYYFs(0Lns?83SnJ7cf.++gH YR 0#o7-}{t%{?Y³jޑ6_c;o^)QۯCh ,i7?}pIgdOݺ{Ag{;im=llhuz/N*(yZ^JLF)w[SEMO9+|WTb\]=p:e;>[caCՄa9h'5!H\@V< +X/w}Kpp:Gly [l`6T j %}KMRF-Q,/OAH-4;f},YW&Li,8,w:zؿھ>$_BV5 vm5{r6q 巕gηU={J*MU3}|txy0X{ɇi[X{mJ}6R+_߼MN3#_WJ- ifz:JTgV rka`:N4W+wֶ ;W;Rdžߣ߰gW~g%}`HXW "i䞫ȸIr6~\rq<Ɔ*/Niv :%JfT1׀)bLonz bheNxN ~nmnƻ`[fNSi4QNv|&ngqjm$x1ykӨ& vKW2k@%?A~v}Eg\tyNשX_UE eUId \Ɛ$ӒC}31}[@!*8>$; ߇4 $0낔iõ} KTs!} ORI hM+[<jΕvQ68=݈pA2]8VWA@ʵ!@q{Ur{(@=PT'끁 S˵;y0տ'{&p.BSEƨ/w8~GkttiuX&&'ҿݟQ:MI=ȃHe]Άzsq^9]q3:ql/:L{:S|o%l*U.:ZRMY۞;]&q08$ >&k[&H.j:bYK{-j%̥ptttt‡%PMF  .==Z"`_ 54H-j>{8`*~ ;2}t[{zcI'!!ɠm"kAY3=lE[1 <` ΰp0u\wdɬVc)5%ZWLyS/P1 H9W'Z"Nt0ut ]PFF` 2R6-s4 @0Ap? f0Ot$/>;mĖ=o6(έpj@)AZ96|8γJJ%{B,{k ZQTwO4c ⏌!8%b1]Cv?3c=cK/by[ ~{a9Xe ?\&⫓v ?۟"gV,F|}ٿ7EWpf<fW xUAk[tA">=3"$:nr%%G6Cp9oJ(NMmݬdAyCd.!} 6@U*{zvgFjxQ~ r~(6L[E.wAnh`R^S+{sda1ײylI|߼HO>0 NMAd @gy}7g>3#3Ӎ zAZb\l`dZKd8OfHV<{ 6 NYkaWbYs2R/ > $j}>0Fش]l%Ek=&wVh (p8;c}irM±3X| M^A@өE*%%{ gjdzfkckrm5tT/G!]kq5SbYfWC*P_6L_19gmohhocMgLϙOv熌`^ %wM5Í `Ź~)n8׭ۈ?PAq*Hdb7n(18?r\ Qdy;.! J:0T0h6s&p;s_}Q[a\9J<¸L /p`f%i Ihi,Pԣ{(<#P[RnA=PonOƤLCc?z^o?${`~ nldptttSfJ@M# [k}uZ:Rt68G' ;TmȄc:`.rql,&* N(-`LN {\2q qk]mllvj~;{= 'lbm 'S*`X[ksHd/Z Ot,oƹL]^GHf9Av a 6Oڎ&;lxDRcʿ;7[>Ln1'C GE;'%g_'\vEKqƝ˺f5!iJs`pPzAp> %s~_NϨ_HƁȸo:ەmn׭ی~k;C/(K<4Wr^`Mdb3s7; ͞!e)}W7=ǹ{&r u2GQ.hE@ib|RDwZ[2:2b=]\QgQlU@wRd tIŋ4h>J[>x&cJ433lkzyo|?ݘHȨW޺_|@"xZ^\०!ז4g\ͦgL`}dFKyXDBdjk yLpy`m$ŜV -2+0. ˙PCzX#=\? n 2 f,} Xr-C 2 Wg|$llYUnܞAN) 2p簩sF:3XsRrk±q qk7סF>#C.dcKh@uZ\W"p^!,2#i/WLKèvl٥;&G{)+u3=6v͛7a,Du2U3CϺCw+BbB | 6Xi}yN ׵ c3\*DDUš_-ɾ6d|ۛF~ HWw-@}%d 3VwS3kb)_C̬s*ꈿ?q:YЯVvb{{8=%bxqQEl%>Ԉ}]Jl qSb'2w8Roj2iR~](8E:y<5#Mtݓ u}{ثy?ρU2{G~*7 V ڍuKڣ`>4@29{Y)Jο(@#=qP~{(/z@'K$L5?}VmikNH8чi~n>ܹEf'qn]XpZKntxt /΃/ o?/ux'g0O[~Nal=cS2uRtܰѩ AFYG5ἊN*PK'tq8|K'"@Yzo8k:X|P2]GUoպr2P)G𫻦=JnVsmp(-ȖC/wINTQ;a0ۺ80_Afk?WP,x \x;=@"YČLZ"+++Q'Ѯ3`dlcWUXp:6+qe(D6["5 (OVnȲIc)暎 X٧d>Wlmz}eB=`Ӈ+.lI\XԹh{uz:Vz ceYlAgu'~.KApyE<Ӄ RG - 5dR-2Y/IɈ8;H=ȱ[\9X%Z4(!)Lo fq.KQ:~_P+fߜgc#d %ܸ9Y y =}!OXqF|faaP8xu!OW/_fu$GSd wFPE180n|OGDNtyJ{Yo޼I?&n+oboH~8mCoXfT!S z B6H(vx`D=>T)r jF!ܬ-q̇sMdf;HJ9c}r/)H1+U`YUG@ub0ǽǽS <׭^tϲB#\ z [`jd;9G0$ 劽0;(KKivvi[/! 0ɴ:n B)/N8 o{J'fu>PNOsiȫ'j5NhP*Wvf 1 $W42QR҆YX1cI?Sc"~7v7 a Lئs_UC]8$?Ht9-3N[ o !nj&lW(Hʹu&1؉˘SȫV7[@6xf\qdF}ȝ*aS0 pGJ6-ys.Qy& /gI6Jp>H1.%i{G5AȀ``6lv@llHfڟ:C`5Ry!02%3o&`z1IM ԾG/O .SϺt8[cbQ{wQ<[$Ej5}'p*īY#x^h+PD|U$_s+O3kdɵ4vg(؞CLP54,bCf3K*5Y妍1bo}J Ǽ|@+BLm.ggJ$O'ߘD\K#E\L'IkVzu:ZNh Aq_?~ӗ9%ҡ һ.::uws2CǸi_/jjG;]O] ā ƪxR=kcpȹ"VpAFu+LKߟ7jk;+"kGU~Vx>ϝNU$sOcWq/_>+WXY>CIa#e= 9BU-$!6gAW~z> GWoV_џnQ[f)-Z{UÇ!<˳=9wD&[g6ͱ,\CR~W}JvV1$`IcMY>GC ItCE% u\{V+X\1O dN-ܟ(U[ҹ+Z|u6q|vgq00 "}-K N1`&L*kK *-&%l6"uG+^7c[f Rcv Y֖\ 1sh̖qdjOcXhYj G,6t56{ɠ ?!`aVll'''*W8w-Jm,!ar|"#px3UP3䫭>1:XTxH_.o%9^ ,h'`u#.hNVGH8f7|6[Zft8f>#D CJ^ՂJrZOkLy-C^XizA)+<@èg#H8Ɯ[Q@ !gJm 7i|r@v'C+Yi||,g^M.䌡k$[7ǟ|X-s5j  otūT}@ u2 Vhtk %w]آ9{kqi~>Z*F'm@Y_+xD,a16HcM^\:%Iz2GϸKkLnӬ{>뫂r'PJ5g.x8nbsH& gׯo8zE>,Mj9mYu[_j^mt`tzgT{wLs}ڟڔMd_=i>˳G@d dF j ~5^5D8_ߍp$TKJdG* hh=5 eL6>eAPU`bEnVU3LXU^b_)5^5j.o4uư~mj`= QJFeT%1T <L؎gI+KMURUL`aQ9/$CwAC{(Ն튏=Fm6q rs J;ůrs|߱˰2yڔ|-_@QCN{DJOkz۟M?mqvB>دTr?dT[Ϳ ^z.4:Бn=WNNP/ϪO; }3bVW^CQn*E|chh Iguhwr8'ԱH @^+MW\{ta2\+ۡDXf7|FHSF=vm_#6+òT-]Brp|.yJҹ佶~!˧EP2j.% >{y-$ڳ. sKN`ԙpցփ۔.O&pkf[إY;i.ZbIt%`_s8 SX9f,5N"V}]^c6s"X CD 12Ĥg4L17/f;?en&~5$߸RW;U!=Pm1fXxb:~\бRB/>OoߩE]W(valn#S8EO' YqH{Uߐ$pB^sCl/熀q13\˯r{(@=Pr|gz@]'#f~f$_] Gogh3>XyI@dutk%m&U2p4:n/0[2<3`.YY>kFl>z+q*pk͂.88UP}Oriia9d\8ʊYo\KGEIt :0f\ ʞ{n0SJi1"Ζ]#hi{A?`<-Yƹ6\ k1TQ5ZuWYS ylAq8^@8; Zp\_ |)홛8~5Ծ^g+pS?ʷE6{%*T0ڹHo_t!KՂv>58K o"l@ !@]<2]g0yti6 ` }8CapzSw 7 ue;FL5,{h3fA1tCI w~lۛz@im4 0֨_fqtȣKhh$hp݀4Mzo% JW6]E뻎@!kk۞ R /@MdoB8(7sݻiph}3hf޼~ms!]'\¿|>|'?~,tL۟~(OG,!2@x%mOM?<-,.qdwwғOm2{!sJd1aРIUeA& ΣQ "m8Z DSEc ϔIb]mjb^4إqoK iZUK./0~M^h 1$kUByd19&XOf__#CBalT]Cku]YCA 53:)aPer"ƪG#/ ~w+*$دx77ˆ.SoI')CR DEumką!^QriA `̕e=zO=PH*=Prþ4s-P:!CtA8fbI5FzZ[Y j >2RFhmp*zu )6n*x[$J@Vc#T>EA;N_~E1QPlλcfi+ 3*a/)#z\`eaSbj\ffM3m{ mkݛ o:կS A> 6:f>88DMt0m@IDATG8CYuqkC\b7"쳒 4|U s16S!kee9dXʮI@$cvyoO`y72xsHo0%:MHw_J޺e__]|&#}h }g+`?.>r+o12_~ @_i Ejz)4K$ 3?yF֥vtkJΝi}nanG#Mߺ>GLMΑ_Nc[y?sc/R$7.IwclpPIADI:l  9w z1{=1/̋ 1٦b */5%M:7ݟ\2þ`;\~~*C҉۰ 2'ԩ<Ci$'̱Z]Z=e=ɩ{]zFW]:~/u!]F S*SW\d#( /(G0Asm$7Ș?d$@ϲL(.i:ޘWƄ&RO'όKl&WEh~^ʭTSH{#0rjxo[s'l:8-Sڤq(qU}6Knf %.Tq;?3e{e~ +k ;>w"{p U2jX =J}55d!X@kG>y0w HLewI̦[_fsI9RϮ_ FwiHLfW{M*1^vsn~)B^P&7hl+B}FJ}y|v&X_jo ~|ޑVҧ~EaOU ;^hU11k 50nsP36\4zm}Pv`wF+P"U89M1pvvhc*hT%Q5ic$ND}}oT?Ԑ.DvOXCmDD 3$mM \Wڇ͸x Wu_;?3)Kf_(@=Pr{{8lٸvt`pܾYE,+MlJ2Q%Em8YrR:L;:05u mVV=4cRuڃ]av`d38l|݇a~vac͹jD$* seK$Zڥ0e8f>}T VgYޯ~AJbARg8En;@'S6Nt 3W9XئV]& 7Rwiig[; v;6[ȳ(im rCdoLOh ֎Rm4gND;i]v16A܆^G0=5ta]X4|!TNV/rs]I0Q6̽ie0^~)mp#r|Vr<xw$6w\i.Vbe;!\iC"[q[A_ηKo@(eX!Χޡ‚dfb.$QxY@ c_ we{ %S@mH@0;ùiF׳) C pNzpgil &:@xH#N?I|L+k#R?zqg>v1~+DLǍ@؞ ѱAMUF! p>` C_X1DwKY賀ssd? 16L}v3/6@ \zޝ4qH&77wc5:|Ȓ1$=|aq/PɉʷzN9/;[woSE*B)g(LMCrW/ q {QxFnjR-N_ϦfjK6O`Ȁd>>C?rUF o)xg'Xq<_kG}|q?%oAӭÒXfUfY>K9"_/plPIY3eo 2;\s"Rc玱ռ'2sST)~g .b{t mEj3.`Mrʉ,.}( OJ<Օ}ه9)7ărPWd~[Or>ʤ4o*}U_G7*O-\Л~H$\mמT͵jB@/ 0I޻`肏uMر %$H ϯ~_о 1aμ2۟f3fucяlH 0#9O_"&B[Ÿ;q?t@-sX@׾Uޞ 7sHh_yf xx.dw`}>#k R54z)-.m[SAw;n;?zn 1nĘ)gģ2s~/BVх!. !ڬ|!r.ԙ1!KuA$lA/evV/!s>uC]e;)IVnz[6K㓓FG&,&Ex,7C 9!SJH+gv*Yꀩ##Y8]ԧ^l!"|@pTWq.=@mHnـIdYWA=@rpJu.YeN3elumL~| 6S*H0)"N'vQޝɉ3L^1W9e|k6K`C`J1N(٥?B4}uikLL~6CqgD6$WWVbun0LNuOLLO>u>KK ;x':ȸϟ}zg/w0pinvDsk&}nFj/B;<$KCG=~hznݙdZ1B˗KSUzw}'=˴~`%$Ѡ}ჟ ȐE&2OMUѱdO;P(8#;Ӆ  A `k| @-TνFt$c\D( W]f04gO͛(~4[c}mdG fvz)n!+_;1 ں xK2oEzn$e{ͪ`5>[";9 \#23!|UU8fd2=4 k5 $~6f<#l{ʯr{ ̀yu}G̨do5$v'G]{<VB9xҹgNwߤ7-NICŌU~}{ 7CvAGnvMZ`we(DdڀTsW[_۵mTZSy gxF bj/ism!obS/<8-yn&1U2x x<_@hoXgԍ穾,5GvX:45vA:B%C~XNlƐW~)ղ!~-]Sa_:R\w`OG:) o P &l&lm#mxT4)`;*=6îr*i 6l>"܌j@قzfx,5?k'*C. g8WM#vAd:Cka8i}/D8Jg>ĽnBAu>~!}}M>LF} [>7l[mlY0:UTYxx  uR [+[ӍS>]n ceT:qo* Bz 0ޓaUU1 KѮCK3^QSK9aY[fR!YzId/z=mg{\Ok7#TC0}=˩%k>Q|;%K#A8{ttLsg5u}=~95w#@lkt<7qaĸwcl}:O_n4:<@GkZ]ۉ1߆c@ >B}_ُ!Cw+]ʌ<. }b+) 6BIQՕC(ňQ\?ֵoiAu >"%Y~i}VߏeU!e9oX{|O*9˃BD-\uȺ\c8ŋWec8R^ = YE5oCC脽i=Pr{>ˎwa$m(@ 6YPL6l5F1`/,ID&sO{>Ys8(Zf|+Utu2KYH!HVְWz]vAU K?ue%cDMK8]:ehRY:42uRq3hY t ,< @*( ,0.p{cWjNAAkn"DGlo*s1-ڼ =AV8j骯?qkj{;~?@~l1`]dn{K] )XhPEoS584RgKkwR73 wr(F?]?0@f3w|6 ҚOVf2t !߈nfXJn*XU2ynk!a`_ |&d dH|hír~Yo['M+eWHȔӇJM<^,ٰ81o!f7$p#kEGN{fe3öQӜsd0|17C%v@5z5úvu~*;ʼg_MdilUYp\atޛo? FKE4$\ywҕ?P7>D }|L=yMَR d/1۹vS2s1x^QU{CA'mHU:JSf~ P`u͇C_~\n65#s=a+.SiK ^KbOM7oͤI(_Od%`u|.Yތ~Ƹ庙<H:L5D B/mpfbcʯr*{ѓһD:F; U7Q`)]4`RdkYc)=fIyB$3Z(~ /s"U;ؐϟ=FY`l=J(E@\hkk#ij(rt؍Dоϡ l@RxuHsA> KSmt!=JH `}!MC^ĆkVM&^KZx+[".Tdg 6.]1>ΐNrϾ5fM!OLՇ!LjRQg&6m?^k2WYyġ+16L$:S5_F~c~5E}3U|N!Cmnc0B9n\(w(4-2{ i9b=V^̥ڣI3!*{mI-`II$T6kQMW%>m5"Üdi`z$pp b1FqXrF?q\`Ud xU6~Cd#ؾюD}aN3x=קk5e|A0M"SŗĀ#39L;SU{g9X(R{뮅{Ur{ߍMєr+=Pr|c=]zɔUι޼y dɶuE`3خ;d{s~ (gK52)u5} b Ѻ2 upq+ T8IY@T;dd TVƫ@10R|/J"-aauFf #y 2ciҙ :mAY+;'S&Ϋ`SA=c)Sf``a tsZER:c4|=&CKm&^D`w=5WV5&Ggn%Pdvqgrihp9zۃ`dTH[C P\d8X/z}l)35oNOEmia`$aFrE|`Z@ nCWgQ7H 8;o9asYk jq0-8l褞KбsJvLL[{3!X1屮q/rD}_` Afq ,tu\#Ω{ ȇ4s: D9AzuJ`mwE4g?kS .nHWr I]U pu%xDMkBLեm;@,Dv?sœ¾100$(e\f`|'0:Y]]^bL!@Ejsz^؞ݫ7 N?{g-@1?zrO ䷦q2>I>ȚejA31dnzSCI2z2}?`g}{i9 x$8*]lŘ<"}5s 81{ɬpjX(Q:~VtD>,%XC fg%7$) [c!=2$e/x=1fPhlhF:l4}[Tc֒"`I]c\[ _{f(gy{;(TݫZJdI.=pI!6A BbyYޞv};ݿ}7i ՑK( "q R~{W:mJl[҇O0Ndb=n8}]8Kyqku , ;0~--F}=ClTOYEHNbAvr|FMUl"UNcj tm= ! V<^1?%"U +eث%bkXPH'w@Vq>hinU G 31c5rV diF&!3ʬ4mC#V1Jw/Ϗ eQ-/k(렢OR@a+6z]53'[O pxrãߕ׷'1$rG ݫ.̉~q+Yr=l q_cܾ1 Ar-@j\%vK@b+lQo os#63%u;ZFXCi~n.G}/X ĵ#X{dzY"s UcXh  rd<..=o d û SINfެ.QĀ)b װm6C{p}:>$Ʉ%=#!xa0Ilf- +챂=pqk$r̵+ NHN9TR,GWmR cǻ=d8ϾIU!}O[((t 0jI gC-Ey^^fPXp \_U3!ǔB\l:Y68Y3.K>II^ygc s&Cr9PO"S,+~ga zMD'P ,(mÆk%g:'& Z> '*vləчihgwsdv25R݈;>y Ng[ 6 6QFM(ǔKC7~3u1VLRg3W3/?Q_nϴCފuZ&V1b5;l#(Uc#񠕸q!:o1C恪)>WTf|O[>uP͒#N\/=kܳς*|+yA a LdD>~nm/6LeIj{}ixdl89=L5GiLj$> |yNm$zY43߹YܷtZ:q.aUUjƷPR\ܯ }|Y>d *+IӃcJb~؉$eH?kE@rn ZYaNpCI>!SZ˘xø#L\MsG'6j3{D$t|~\FKCTևX(@=Pr{ j e3wDHWSI TFK~pxnhh-oxl3Tc=2Xd E/ l e% luAf-PFJ6ue *pxø綔t:$KT53uLwwMע60E]C@y+vtl]iem@s@ f*YOMfcj>i4?8 g-%VV>J[wM33_.Q3]NK'UAKW7^~W_4%{EoEBCt+ҟ~̽z#0{ G$R,l_s]OO^IBc2Yy6#;:M@XӡfFx- aX zxLp(VGm1dA:m_N|`͍q}8m8x+-9K#OԠ$Ltt^E-c 0fz]qD3q2;B싮*krGuU:%|32|Z4==Y #fg`5\{&D 9\͝4{յ(ߠW:^B闿U ߾MX*'lnnzuW߯ĜyMF׿PgNMmuY xK L1?Ov=r뛷K鳟<} 0[p33KD6}NFea̋O^"kx*Ϳ|izn~;o?sj&ӟI2`f@`\߽}N'kk9n<"Qc';2x"aEc<;3@=FX{.Tmbln3`&P"]6S̫MUsUp'GƉk{AO9;={ @1y0Zo'{M6lY= (&VΤ gJuEqQ=ys}Dٛ)^AC!6Cg=F4_`G??S=T%@66j݇ ǰS ?JT5}=ό7K rk X!j,LFa[3$ٻw(ؒسȹ qGΦ~ȁC|>(aח0AilPGA55xƬwoMԪ"(/_ɐX!oxQw@>9]1eNx|8Z # h?=uς_ NśT|>vJ\FЉYEH3O*E0<צb<+H;̌vJ1h{n;3)u<::.7(Ze:~wC`m3[k̍{;$ۙ9H+RG ľmT7\̥lLZ ԚƷ ߭eiGm"|aVaK]3Cre;Uisƺ{`uI」n֯ L h^6q]~eԧ6`C-NnԌ 0[=W[R"v ,!V[lDUrTԏYHOOԥE=/rXbC2CwZ̦RMf*Vˌi|OҀ!Ӵle۩mrBA?@g!r/Kcޯ,mU!rGMz3}y rNPπ8Oޟ %=~= ޼}Ov4%5/s\$ DH(3Y9sxCy6nPVD 1J||5Na16H$dl#4a}Ɣd,:b } ze$d|96M <_؏5 w['mks(֢\qLxm܄4|zWG8>wϻN:Sj@=F4za{ qOP3ѩy]:NVnB)E݆saݧ.K`"3;Tqm}iq;pB4.dtI t8~JiP `=Dvhގlce+ש\g#f5O,lg g`uAq+7q ?Y v60sEy{:?i1i>zɽf+cf}vS3)lրR 2:]<+S%t]I㖧-*Ŧ-=J p:u mcAE/fW]L kp 6f@zӾ[޻#PY€'z[fM@::>gkwb{7k X%Lo3ջ oԁIƁyau=1=ÓeCa.o|GF 11SRR B/qwk2>$;{sO Eދ \zn)OȪB,]jq!I&yJ}vGjV6Ȁ/"[~:s32/Oۻ!]_&X^M15Dfx/U WfoFܿ_v8Gy;{3 4,ޓ?Ak%v"}d&7.$_-2ݭ/713n"5ӗKč@xPQ`5op{~[tFJW. 1㣫륉eh#` ̝<5x8VjG2? 2DDPTyS--d`YfR~$H)xrsI'% ]8*80A1*ƫ@@`ADeOhO,dG؜_EwW"lrHMP氥=%!V_U,wO3|5aB`wimwf* t3&[iD47՝ޞ*I/hf& }ʸߎo5Y:z a%ӑ6q^bokOFlktb[ [:D T>pdKyپ׈s}]W q~'#ne jؖbn ]><{bսۋxg_ a U9!8s7lG1kL a?֞%! SGd3Ɛl࠘0aI6|3sh % ,/T QE{3|_u]^Jm  pTM1\ ӁG=F]s_3alx5zh@=0 ƫIsY1~K nū/I[ڽĐ| ێFt`sڐ-m6@Nm:Ge$Q-d*.He/S7 yF⠕̎yM3IdaϾ\"'R:G/_,-Q*<0Xtlf :w 7 0i5@,f Ykvf:[Q`Q`Y~nMs2' Z͙\ Ȭg .EA^lؼ=d%Gv)x8Yz__wL^|Ceßq$p6aid;!F9fз&keJ }ȼtVnqw%|5]KFYdCL6% 9C1?trunu h|QAݧ#y 8xeY^SG[13!:nv1g ?AX`M=)i3>onSC+HIgqTg,Bve+!CZɧbSGwHsu:frf,r.SR_9;>> `5!Y0 hU \WRBE_cmA`Ȍ6spxl PLpÓSbqCH5/o2Aaڽ,m0s1Fv$_@7طri5M.2OC.=ng/G_mAZ知Y-36X_Ga-}U%21f{D:HCXY]皅 _z>-l_}y޼yr_/{iP6z]e p5˽'T_dOGfhl<8ۗ2I`O|-}2{: Թ#[S.=Q.g% [cݢ[d~ƸJZ9 A rӆ62(c#k ڐ,An|OhnqM)-lQ=JH3X~͚!(l ˍFp.h'7܀q!X E|Yo@)uAs ߥoߥ֎z Tl#CHOHD8; l=,9~J}#3A-_sv?8aV5+jf=FVXkN[Ϭ?wrO`Jn@2 %Om`=b p=K&=/V~]2sH_]~p3X78-C°ADa=C̸%aY=7skΖi6C쁙8Yrff`_Vu qptW`14M]1,|ş)Ϳ|Jp])qov-eA[\Cw$h"QWkbO?i@6Yl3<뀩6RYhg` s %/',IQli 5|~|8}wѬE]{@fV@k> # !~5>3皐~g@?êi#w-ް4nt .)HY:QdOچOBᦂz=\!ds@bJ?Q0F}+GEG@V`\\5ɠRа99,hf{vH l_bF|N17|TU!πJ SϪ$AumПk}<ӿ W[@ejUJzA<mH2bO$s[T`؂)%ܶV|G8sV]=39m`>B$bJ6 [ǹ3!QCh @^"aJV8-+ 7"żm eHc| e@ddlͬ>2Ffз37!x7.k<>syn]K#a>:d҆lݟ%9UzfwxE!%b(x=* v >)~ IuUl$sO/&[*o|_t|鋵 0o-4k 5ϢܘW;Dy У[i@=Fz@C?uün`i5^iX8@ޡ/IZNsԳ}T6y)]LJ872[,jޭȊ圞QpbY twt\@?dTp$7Y\"Zn^.ഄA{g" #~gswvvLd(-(?BswfN(ò?<8Id 8 L=$ݭ8?;q0)ێ6\ ''GWɯǓ֚W&3R`' g7[L_I GiW fH Yw_3ExI::>2G4 rڎWpl=' cffNrm:Ifn=/#͆QPKțEQ"̊!k^'v-ʦ+Q^Zȑ&7$m_p?4r瓵%pWݯ ˘6?2ɹD3;udo 8@~=ÕL&V>!c!}OVB%Qk3 t?ej֘QCI/.il@ odc[2f7sT7d26ftQmXwTw `β-16Ef>1_Tt ױbӻe=4sr[{ -q(906Y;ާY|AcvaT ~_9?3{,Q|=a> Z38T9=gI p1ꬒ^5<~z?[Et9h`S4ڡt[.yHi]k͛ RBoOaWh:%yP{8_%tNVa ?Jmdwwv(Lƛ*5.j&հyJ^`G(L^߰ePY;6k^sqp$~96Yζ5$!g=+]Lxs B;M>o-mRd 5ˇ89F =l1Wl{? I|mreP;/wJ c9q}w2=y⟦yaNf>c}{njF=ApY@Sb`lcNX$]qSl딬-/d$L2/vYU % WksqJ0*CsbwVͨUYZ9fQku-Pڐl¶crL[TgyU(d9|AKI1cYk>JgTz} E[c[bN´5BrO1K{+.bE[rY̖rDܻ"kFwHWG `w&)Ў}ߏtY\qGث)jN<;31x6J}gI.}¸CXm͙nm#As/K->>5YuiT4>4 "Hd2k^ߙ-y#1cch??k3mG>L3gŵAO7^h@=Fz@ClAkj 茴PNjO4^eV@|QOh8`"j#8'g_y Q}}BF۬wʑi}֋u{Z"{z#OkWlfN,qE1َ@ߔ=?`||Hɺ4@ !8@X;Wq0k 64Bݓp> U^* o"s 8?8I_H HAQu<&{vkff㻀 ss Hbۛ/=(l@]'` ١f;Jʐk_^H  Y_@PތR맯ujPd!.v7JgguH *ɮ*o7c]Њ{e0=V"lgIRA`Ax@s2SW*f$ O#%BՂ^Xw:igɥu͝>ei8kL8$D)vs}^ p 0#0qtt,֨IF;Y`NQ ,?+yiUw9oS_ٵ\k!d ѯ&FPp<+3-[ ~w~x(ON[6kg1y ,w#wY+'(E-p@yhd$z% 3Aأij|B<O5ڳ07;a`/T"* FKD\ߠ[ PorU@4ϒlGjn5xZf|3n)֗"Gf~KX~L4Oޯ鐀7c|a?IDZݹcFDR} oyi27o7 P睽j}oQTNwÛk[Q2mY>!lM NBÖֿP;PFml<䕹=iWo m}>?>gY؊UlKxsnw9l4;1=ގ}M6ЮMM=d=p2}ӌ]+z,Bz$^sle@݇8F9{٢c{,\Dg Ifm( dPja^>C&SWUN=T:uœ=@f[6G"q3b͑ڌ< /Ƿc/l;L}bWY \_ P.Rzl!`k6#c{[ ;`38}AfA<@2-g}{,5cp(=+ -R?7:e)c JyYEs5fA.6@@ć;A< 1muxAoI=؀fan>,dѱ?et?>~]c\<l`ka%KX缧B^"H uۙ7'M$kނJʃ 9,R 8=|f/k$w=([[o$S0d|ė+U>pmm$?!6@Ņ{;s#kyˌ@q[=g$1(;-`xX*:Ȁ8=1fuFms̖7@g `[ xZ7wRwԿ1>uT'@A)hiK9Gߧ׽}1Vf&q@|cz1 v(g>Ϻ_DY4?aM4{kܲD( (PL OSy݂,:7lw07s<n3 \@w1o )LŅ yqo ~_βidVjݠJoByP @w;woZE2Y@y!O*UX>'x# ;I 7_BPRֽ r H'S'8{sXbobL/ 3\G璓Fxf$+eҗ}@מ#"g>uݛrMuYqnDǽ=/u?={*t ͼ J|<{Ȗfδ2}3ȹ;㏵1?-͢z b Ax(nv\bm2*+Pe^\a {缗,pm׊Dȵ8k3i;~|M\ H8Ύ&sB{ {;߭M.9ƹj̥bm~'jcxyF=AgG7`1p]%"_t܊\35F4z?n=wDN#Q1a֘Gg6>#pܘǽ8ֽ]մ'˶bc\%y Ä b#b]0LJnQn5"A8wt&qe_& ,"KT=3$qqH*XzT5G CbbG'K-E04OU@P)|vV̔ӁCr.J ALs / Yŋ=Ȗ.ٙ707{hlw7Y;ۻ^ +=733PhkW=޳RH6C~`?mnoo0y R5QpNDse5\{ UfP@ ^{)<\[ ~׏(A(mc xx@9ך֨?`6G=H`feP=".87 %S< ,rSC<@YC?NӬwoAH3s3dʕ dϒQoRa? #ϽWSǧo.+MTPo `s7! -w mWF\  !,~2ŋf}}|!o:R/ΰIg?6v_YOd#M/. ~V'!ҿ|^ddt,d(.*[_jg 6 0QQ8>a^FP^i}%'%*Tܐ!Pݑ9rA05㹂uj'38PLAZ;JoA1FtfUƫ{c ,?+ݴU:A}ag$oCE;^?U뙣5sKP]CF5ǻd\W6S!O.Rϭ*gutcxzz߃`E>*{ÿ-{ [TTmhFӾR)ͬ"vg-e߶m!ѿͬ%V/3Pߋ`^D٤ؼ% {Y{4yc uW9cF0xMWxA ֜ WgglAE,Ɣ ^b3Ϋ҅|s;.j5ڮGg0>vSE=RzBu~J&Ozpo )Ka"@>lf)gg~}|NE_?9d̯x+;&~?S $>?P1=5ԍ-f;=,'f!hUOz'%3<-ޑ7 +Ts8l 7dz{}'/D?~ƾ>qVڧCBq36$g$zph,I:VT^򄞟ރrHPȲv_b }88.$֢kCNJ+9*.SYU+8LV@? mSeϲ<{ܘK6^h@=FDzCŬ@ KnMF{)mؚfӯ⟦W"`_"O~vN)m2V`${cElXeL[3Wrɢ'آptOP0ͫul3hT@6.f|;T1OVw V'K .묍^Yjel%5M SWgΌ 6>,@-mU/ !_|SΚjq0^o3ȉCwe`6,l3$ָΥA& o T:w!f-Б}H|*A#u׍㹆B8+x}j&}3@NMwk+]n@HVݺ+{ ]Jid7 O r"HHK2{+ izゕd÷GY'Ȝa@="  vl#slvnϲ P+|jj:g*!8bw2wenvy9ں6\֫g?Yzɫ >$9\;i11ymu38vG  |Air^8D5 4O`Noޑr]KSdʿ~*H6;[x}D?XtqѕynqyCQ-o{&c$'/  `KʩB1QG.Jn@ .$t(G%C2ц)N )oEBb-~S%8:kLBAÝdv뤖C9(̠J`FŻ7[~F?56k~& P\t= (NVI=G@f@F|#,j,83$=^_cʏBj3Гg[!UٿRc]yb#}EXl7؃fa ( We$B_d8YUvn+ rN*ag`/sǗi.K()En>03ll*׹fH%Z HFE5:*EDJ<|Uzk͘ v{![S[kolz{'',5njzLVw}KN/@50(ǃt? _>L#CiLB_i`$Ѻ Ax=Mk NƃUάmJqB [yS}i$y'h=6hi/K*\^EUk*vv ֜Nbw12UviܽƆ]%Hlk@Ż 0"h[ڬ^uYl4^{. *Tk{>T!G\fP#CBV`^| 16->P~z{=bc|2;=-9|2\_ Z֨W)IM_5+%%AWq)i ;~6{$nkK^|F :#|w):,s:)IGX d~j ;v2=@T+ Ǿ4žyw bZ<_.'#1YL_TW^ǿ%s  fFy -Ayc}|f;xgۏĤDM<(?ΟTxtsՁo!ir ౵WUJuuYl<$rG0Sв@IDAT  U Koۑşϰ6trhm]E|x_Y%sVRS~nVUΗ;&f, :9<װf{bx.db_f;N/[[ܛ/Qw!ZŽB\ W 1㻮/?9b=K"m-&ĩ{Φ K YVrkEή VAO9B)FfO-. Y0Po, Op]i`/dggfpZCiBHe4@z贶*fkA|: pu'fpnjY])TJVsZ` ދ€yf !'o >||?X2sܭ[_xL Tf2Œs$3Mm:UvT%Dmzޚ_fS1;C?n ^ +vNС !$yө7;dBvW t :_Tvԃdv0oz)Jt0n0 EzԌI6@i{^.:^瘌pN֣ .>i(*־6%H.pM qĹ0ے.x!ofR;'=n h:Gz((>u.7SdB6㿳WVWK\wfsa_C},cE Gd OgO-H,fzi`{> k[@LRVߥfG֔Λ&6}Ja%2_F~}ڂ2H69 !m( ě5}y\^cVR'kb@Zlٛ jϤ+̥ۺ!h_|1O_7.q߃巀dFbGF_ncc:dc2GQ{%ϛWU 2 wk+˧%{1>\HnB0@7|p]2^ّmثb"053cuuyRf8V`ium`0^5y q5(G%HĴ;ϨgI,~gvI7θ[ °ۑ{xGRP.dJud;{7ҳc m-Y@{и1T&dgVD_WBvx=r# ) \3sVž'm=4(~܃w9h}kG~ x j0(d"3ݏ}_MaMzVo;ܳKtArLo?asϞ0f:7Ӟ}Hfv{/-s#~s3[#!lK??gPȰOys8~ħ~xraQvgc&gH.T{[{m/(\-$ÑRQx8l p~qP!oro*3z6{$=pI-pܸ%b ).:,bLBEKtRrJN̵c5AA[]C&MaTU3x~^9==?JTD3~!.[E)&xUoSK,6ƫh@~`n=w@ 6Y|}'=w8,a|ct3$h/,Ҽ2[ 403H-ōesQn]uZqXu4[k:fNYtng޿qDu `Xw=>p>csƷ:rdJTn`)oV"qrz:0߾`e@J Ϛ-s Tf~/}@C W/`2*yw/qR9g*e}~,iԏN#V Y Gt>ϫk @AuCF,O9RZYy.%'X9YS뗟+g8Y%nY'H C;C32o^?:Vf0tS½Gi;c14}jeep3LYJ?Lv+X1Ü xx}$KD67-"ϜW:lyc_:d,7^EQh-u|W=ȴ1$NY>`ųGp,\A< k01#PkQ213ZAS~˾"C~楄%,D9Rf][\pY7l(^WC{;\\c [ q3ggW_}$"=' ]]Xd+xov0ReY{]PZsӱɸw=Oeuꬿz@۷TxO붭ym9U@ׯ2@gb/5޽w]S|}}ZfCB, kڒ s9}ELƳ"oOafv6fkc-Ƙӎ6i{uu YSAx?DR^Fci8^qX}zv"֚{! _ѯ'ז 2^24;̣l{BJ" b#[6(au-C=;vm2R{{NlVW׃tr^B!.lj%‹teN~*l`5[ tp l%1B.J3k+# Hʳw";304q;g[<3.3h ח.g$'KuBtQnH(k~_ %2wwWHOaC<'^lނ/IsülM*([A9HܳVw#?{iv/mS=Խm.FRp!7Tn ^-wKGڌ:UH*o1mFkI6.lo5W!eK ZwVQ(Ŷxf_3ZF:>܄P  ##9Woy fI%|y ¾ {cm6 9r%61۟2U9-A Cf!l|=Ą{|H?Q,8/`9?~RLW/ufGG1h}wGΞa 3 gn:lHoAIT~6ekȄ?1GȄl2Y&؃rF|bNW[e-dvzsM <~1vdds[Z)YP8gG }ɌXV<>e$ g%r)C̻V0ʢΔV&ZZ*O6:8<0[To.>> B!)M9;gm2X KyG1F L!a X1$k? ,Y_EmYg0j3};Yy4!|*bY: 'llo8Z 1=/7esNש2~_0y( U2d]D3mo(2 @}Z==ݏ}~H#ڼ#|9uÞfB;o|&Hxf4wOcC5|Rv+C<ߖZ.mkL+i-j>gxS!b5$?fk[{8yji\[g^xA'雯[_͉VwCf<hîY1|rI]ω8 fYq;YIt~5 2!cFG 9E,Sl7}زANd{:>Y_p]dG^lg[Dʘ9}: pf p Vm<Ȑ֩TZk}{ )UԺ66jf6l}gy0جsN֠9yo`Lh+]ԗ$9Gfy2}ݪ 8> ѺWu8w7Wc믾J+K_ k+f,'dv/7oYb ӹ2f~/QN?Uo$ٙX 7e[/=\fuWNj4L+k!n}tޯEEw"02}|ź5>5%_XdMf6#}mԉ}ǜ+ ?PMI3+As Tɨ]7Q:wzߤ&2}k3:S'iͿH=:MdP>?ςUԹZO3@C2Rj~Dʘ,@Zn$wO\_L)0rIJ4hIThf#ۚyrtʏ~B$k ;fL8o? @ܸDk?켲 r5,#;;bkErWZ^AKEʽR >Mf>Ym#n+[( <tObDO_l㕾Y-f57\@gO;$ df9W޻!}nx+dKoc?8G=}c:~O.P)]j68X Nv݃#S:|IeH2}գr ѷ:x97M.EA\e-CQpw$n,g{g{bE3 *<מ۞*H=e#P/0yK0D&%s[H}l7}4.+2^@U^I#;fq#'#q \%@[ Pa}2t^ f*~o@7J ׺xscm4 ֣GM kiU~LԳu x㈑GU$HqEt(:Zn!#0fk^҄`3?~k]KSd&0M 0x/HC/YamT0̙^^2 "6㛄nFܿCA;f tp:llX]CЕy1g.zN+K%\0^dY3D7:6ta? 4FZ^c;9FB`DJ|M<0L 0 Ape`avt:[쳧pˈ)a \Ì?Ǒ =Hptqo uZl&[X?i`]H>R a `f^6n]Ldu11`-FLF2 q֪s6[#gk'e~?^OK;Dsδд>6(Ye 󂨨p:H6{PB6zxq:=xHD.f;sΎ1xk~e+QwV~ak4=(;!Tƅ+RsiZORct¹KA@䴿(7#y|}R#2Ϭ%:a5G&rgWOYrX_-ңg$N3~KXUYRz'ǟw51v8ꕗqz9'N[ 65̴'?e½ދ:j6Eqtj 7 о77=ca]9HeD`6D١>,Jp曞 0TVAXA](}`(gfȵx7*HF XF}HgdZ #}?N+qZdC.̓c&cKׂo>'}9Fwӕ1uJEAFZ(E c 9֩o7}5eǏW8 ˲S}&OQ9Q>[f(Ya&96'|]Ό  ɞu/.k$ΔȘxⰮlt \ΐO"\MҶNBYl8`tN tQʐ_YY˅ 8X,xڦ~wx(Fm"a [gvfgů%O?l9,vm}:MUU5zQG/Iӄ-"t!h_@_ٲޫGDk@~o0 ^BժŢŌ!Ǣ\ Y|u1&B?7ik0(EؚRSHCP6chVǛKߔL*7\bδ+gVPO1Lz^GAZmi(w7*:=ԭ69gY&gYN᙮"+CP0TxրZ2OwPn0"v S~zE*"QQ`5P+o h5qk syiZiMSyϠ8lj6? RKWSV]c@' oԬQzO¡^mPP 8$K)Qs?FֈzZׁ)NUPP5.3I6&0@1zH#X?j(虜/m4&Q_Z O] ^,z_]Q #(*]2`4'z70 `h"#xi@R7׍Q k&34p~T.$k-d~o>,8|F:264d~,SuZNVLĮ t2xRJu]vXD]v93[`}u`i$ ,YPd% KKiaJMufG[͛\ݹ<ǽ+ /{.P*tr6ey쎥ۤN?WpHs֧5ƍV~'"}^LOpbOo&}|*K/q_z)+x=M͗n? G]al7c9C}o=x[Ȍp ӥv2{_<:1~&e:۫[ic2 8I`PcUF#  8AޭFG=1|ѣih|8!ihtv*6:{d}|O? D`g/t;Թ%t8+X'W "o<_#~j*ԓ\)S -"-6a7Ms`eMٷ0_S<5jqϔQΫs.s?Pv%Kp J8f6}b@ԫw8<XM/W$3~#(nw>1| `86SѝvTdϏ\gϰ~2[5`<:Yh r!W5 I Ha \KL./џ<|!@!]umҡҽ铻Dt!"uL #ЀOXHDiAmYKɴ}4bp'Gd(k {Ѐ~gv<2HFQs`>ٶH' 2Qzٛ;H=r wYmAARQyK kflZpqVkqOɜ#̷6u͚(#lq~UxдȜ5G:Zfih?Qse:>YJ=/l.dZ%" *^6Iko'/JHv 7c7ѳ,ETWl޳dV)b.s2-!W8s#s5@tFvQO@].}Qܫi.s&Z5K ?Ë1u\A"@gŁ!|wY MJDjW)]`jD3 u!0Q%#\Ged>o,`uCTrLn{82Q"J`Ѭ]ܧSy[l`FZF> [L: g:5myYcY^`v0ykR L.wt؈lJ[yWOY|gxfC֓W u}YL}J3s?m;7c ̂pYpPgpa|[D`]鴽Sϑ:N֕ot2@C6Dtz&1zl 1&5(}9}b>8{de&`t8(1㞛vp u/Z3XqNA/ssMfG_E5 % ]{frώ MpmPAZӞ3v3HA|C7H'QG%_b IéU?^OV_+>;_ WdCj=_TU~ƙw(||K7Q֞Љs z[mptRhG^ G-2gԇ7z> ?RQSnIL:oQ"0! &&^eHM 0`+2>/ NQ*Q[TobV:0r\Ћ*"YnUbh{ m zCͻ(]x D4ңO=@)Y[!jpKo}k߱PX. 2X#)G2 Kt>)0]pf:*<퍷^Iq/=xL-Iqn''j`g?Vqc!Ԛl|eJs} scē'Qr?ɻiuiԍ'?r2G|wi6ۡ4߹{7|4 aL̽5mǡ^G OF ?>=Fjb(<0x'#{Pfc~CbM=f<B ѵ4Uǀ·Deuñe#MR|?g J<]QyLf}} p;0~ADV?|OV7#g}(gU$8:<~Hqm _%-byHQ+;)=&=$i5ꓤ#*mg:l3@f510CZ\.6xҩ];-E Pv)+%18%nCTG.ƞ{X%)hDZT!tmҷc!mx8G(`vIU a t]$hx:WI{66|VB6wRB f,edrO hDjK|H;z++,_^Le|Rz7! Nfȼek}1=ĹZQ2k ީ_gۉ6CQw~Z~1:hϔ.RyY19bp3<>xgW>Vj~RrcMNI}&ԇ0W4yo(Ml!} /ʖZ2[V`?sRZUUF)QݱnCg d)5qgS+V #=8_D(##Uro()urAKee.=b|qD @Z;o7ƠȚ){{fzm`~,oPGrq `YV҂: uV~j99v @gmoD y"'zrC3uhyy{6]4:X.-!i&H}:;8}FVĸtV.w CἤƵ<|gg=~֗|R3΂0(t uq0ne1m~mDasqv>[(kXS^WtOU}Y k9{zkŠt3޽aAeּ?{{&*t=/tqN8op++`\>rjFײsv=Ӳ#9dӫ +O[RifәPKcs5@c9{ ¢D{UJ:hXdqZ/͝=b 8FPA{zQP@×`Ƨ8elq|zJIޫGDVfŨ d!=a_Wk0# ^H U0x E0ߕ@IDATyڍXɧNU1pzWOQnTGsϱB&ѦB:zwܩtU|rtƹ1҆8qIXmo6g{PT>T;<I**Ce(6'PTUvyǣC*$PqO?QhSغo*=*!HX9#QUM4I=3zTF#`| '+aʷwx6Jv( _}AM/0ye릁tlV TNvFӽ/>H #ͪJ#&PgajΥGҵ۷ӝ?]˗𻼼jqo m.d0o{#H7 l$Q9OCmbDP6g/-C?ίƺ4=xo޸Z9n\=B2iIf=AJ5_Fl [޽{ԫ'H/Rc7ER)@%iw~͕>#7^ƫ'O#uUXiJm 4VtH~ij1JX+eWp0,׳ _9Ž/L:,|t&7K_|EmoS} cߋn:Nӗ{o-?Mo.wx2;_>I}#{5>4x7ݽ|ҕowǏM?Ʃ΃黿mx=}BƼ@a>GqJ#xiYw/>^}Dko>$M(!ed>D{D`>7Lw</'G#$B_'~ WL#(?`mk,cР%.22 F;׌IaqHX]!O$.6"0rihlSRM47ux:!sno:3BDC3FEv$Rgq+EF80*l`_;ӸfG[%FXq㑦j\:>ime*Y';8b| ]W5 g`fjo>6,N`Whfpֶ]1~rdGAȆQH.D'/_% >5Ro[oQz12{wȭy:gfK̳J)B o]My9Qӏ{N 9уt ɬ+qF[K+ts)]{-)}^EN&dMca:F33˄TJ:ۈE:^U DH!/чYmC3 BWF96Rh>#VW{ @k x(e@zZ&ƵkȀ 2^އ|G$~T~oIrhQKuQ0:Ũ^GVU=- ܝHC /!M NTdGr#1ʿkY4͛[}m /f<1r(H+w{ o\y%]|]T#u!j YǔˋdvXNS|GіiW.s 'D +_[,8#`\P)~}bOk?I72 !^z)䉋. _#¢eoTmy=r*:63l"eՎ. Vx.30)>5;/r AvCջ3Om uu蓮q"Y)-?Q' hQ5xF?N<<FRZ brv]y@Ͳazyy5UnAykKr}g嘔qK|-Cg{c̶3cV7=={_ʂdC^֑%Q%g%FmƄK+KG ªgY2e Tg(`NC5k^!߬sD >qok9 ʇ !1J~f,W;tlq_Z#upsp8'\Z!yUF䎿yrw5U% ڬwyMOc.]3tic ,g+5=gM׵a?L%XoՎv)VɊN҂.+Bd> AGA%kXS3рQ~B& >Juݫ9a_> "@gݳxi'#l|yj zt`mSĺaیhͦ\5m_ ]ڵ)"^Y)$1^XO)~j+c./ҖvH:(6-5 L@zmEmp u߱lOGIe3hK?] 5i 'QG2|uRXWD}  _4:Pz# BsH;kjb;ƾ AH 4P @ ? UAxE?Ko]Z|/-Z3C<{|}ҏ6J @M¡eQv-n5VXe8m\%YQ1 k!KUh{pûkY@0׽0ҦJmJ g#$:8caD47{ 03?5<5h8]oeb_ys\y嫰x Tl<-B!R(PשaQ06A/IC#L g_dƇ6i4HPw>&Bv^sli2i)&:㤯̇+2GpkQhkpRh3^/u0Nj_T5'}*l9F)=/R΅W"iGqҒo{} \DjE GdWxv !_?V̶ X'Om~j&)åIfd6Ƈ1R<M q AMa7ij5tZ`Qye-se]*O+BM9ШB451@C~&?eN}=eO'}.cF1j( ]_\ t ϗOQv3.FS׹?}Yȳ#ǽx?Q^\g[܈Gן[&󯽚#5A_U uPe-A͸~ pS1@/~Nv?t )Gh\m_~B(@Q]d+&_ǘzsյEikӵW_0X ڞLCsb\ C{&&eJVH~e08U&b ;Szz{ 80 a|i2,h0铗wVǏ>%cbȊcu" dj%OxTGh*]ga&|u<"ޠ/xfj^5w(Cd:G^BNҩBvI23 4էp{!#O0BX7aɧ!< `VL1〠ǜ߂:V/;"S:|5̡2?Rg;5Jփ!ځ'sB<}9=\y>AQhQ^|Jt!Ne6b= \צ9}1O=L,P跦0G"M,\g)<|WPVyf/u_߼mqdC,g?F'/P6$ugڒOPnsRLFdh/&ki=pBI42w-xZ*"_<㻋icdp}.F160L:\O'ցcu.:#e#xDࣘkZ!b,'=y%,H^ԕ40zrrDʣmAr۷) AfCa]h?t~#[olo{K/o4\>B֧{Z!9?B`4ʛF%L^ lC@uJMW82(İvFb//C"_P5hr4g^ZF|+!!878D]I҄lE"wSztfx$`:1v1#Mz{ɗ񘘃Q-y_U&>'9'nhUOt7͸ k: 6|f0eK?19ש~o?{ꭖ5R\ l#ףu8uKR]g诌szw~&LR^5NG: k+~mxv2CP+se]>Ct. {hQ+ 2甠%9"22^%x8a( 2ço⯢926 Aӳ3<se q SC<#gzeAJ'QO[NG1xW欗dc5лO-OVW|ZF] ^NIQDnpaϛ}&g=Pe&ѤM޴ tm?[`c^= (УPЗXAD%A뽞ҭG$u)|qD.y)КJ!O:<>kE:G ʋJ/y=Uzͷ?$ HlLBzb!88g:Bq~[YodHhQ⌣U#Q|FFeB_[}(g< Kȗ&\70pJQ'96MJ`q\5B ^r= t4Pb.Хqx@YW\F7DRF0ڧbQ )4XJ½SSDQLqܠ3/5 dPӺwvbRK˜ό26U~{ɩ쓵7_ sίhTW<&zV)AA4z΁)xx?"5yF. ԟSSeΙ_OfXҷZwvA7gXix3>rv5׼g3(ٓ uyCf4:1GM"S}4HQw8 a<ч4"5#Vù s0Z0J nh#O]4#WF F#c?OSόvrN ]Sbǹ4r/ҠdQ⼥ g xmeMX4hq$oB'E>O=`[+yhs] M}=w)Wko:N1:i5LTA ֳ0o*߈Pd,*43#d5oߺu^eN1]g_~(Sr{.n5^z-휯;?2l_ ~gqG?;[x3ÔG{[CO_ ]@ @)Rh07]@! 0^8 gF0眏5:~ mJ#wx4Ly+8g p]Q{A>0h$s#;-9W:xgun<òF,CkFN O/2am@~p l48*q=0FL[0q}4}YX*iWo)q3YQ 5C^fkytirhNh< ˈ}k1K.|A:\^l}X>tN7eTGF4gAgzzt?,>HWV4K o&:i‡aڣlХ_Kz<^ ='+s~_!DQ3Ed.,Ϝ/{;8&7Y8ܢm#KDU2Y~8TйLk.4k@tM}wUSd_)L?NnvN^kҏpFfpD02odȪb>thf̀k\5zR [aO"zN\;*Y*'jP3hZxi9@=ls'q%C :Y ]֖$h:rvlǹ/<\qh28b,EFWbFu0V֢9H{Ʋ;ۛaAN&1ByBx(s8gxKml8XR}O y}Nt63ͅP,o2zQMYgY|c_d_B` w*lb4 fE=( , N6֨TSe3G)N8x74)PJM%h+ om% 4 6')lXzU/:=5(ئ}zr(Q(ק6m{>úD՞c HiY;aDq(e°ՐKPVIRHGB)2U&gBhP"cAӰfѺm̺8G[*z \$ ›r9R[Sڻu,%BT18\O_U ٜ 7רf@TOt6BY凇)q}7Jm.Oqʏ>*?{YN$3m׽kA.(Cq\tRP/=ڥ-j5΁#JNgevX+)ٹޚy- Ύ*JJOEѬlOhNF9tX6oSS\YDvF1HBV빋0Rh!9d7F?%L`>t1Z<)\3 g>0iB#@(m#t+R4i3uJs (bmtݦ u g  3q[P7_``p 5q}ӎYzR0$.scU up-[·Tg!iJ\cX5p@Q_%'][[:>=s32/SHR{T%XF4y>F/a `v-VΓ\.6Kv'yugʓ!dϵ':d^q-YPޤߗ_##gZAK}OFMFC^sK @nw!x\#R#+>F ɮ{\s}O0ms7CQرkd˜@1 w9g5gG8uW֗Gq?ŠMdZ_}cI1AW) u)GL,# >Ai:lёGg:Ҟ717qL.PH|q`,-3'A`enJsW8k8i#d>rبwrsZjx٥fF>Rd7-짽 0hLz6]URSZc``T\ ("3GГ[ `T$yr3i5E6;74Ȝ#JE aь 32p6)1AmR>GqX~'ι.5֪?.'߹P~a&q_jrJX|@*ä/Uqȏԗ_Ms҆t'7Dy0Pdc2aei'dW_ׇzN4+:MX ^u.4-usdMdF֌+2@?2! ynw!52170˂Gr:F\Or>w@YxJY~K:mw0 :+cq'"?sz$gd3}{ dFRG>Wtǻ/wpj֤{=AR3Xnpd%] }#YɆpf:<ߐW+6Yn[/̬ܭmBg\oNقY9Xm ]/]uR*;iddn+B3R3c'|2 K mw8'YM #)f:T|qSưf̷59K44:](uF2 H}uCS,62:k;ts32JDUhQUcuآdЖ3K=%38x&O3: m"fxӌhKk33cBaM'ENy]Ci69gpF;ytNԏG܊ 2L{3!H&BN >~n?f(svه%(<ѡp\;FWWtb, ez3>Zε@cǦ.|~ gMi4#gg:|Xsod hr| jc upzx~z! =LhޫGzx^ Ȭ4)0Yrz,߻RCBQ7Q@Y#Fb/""@ )PbR裏s5)xc~&K)-z1ŮnPfLߧiM1LAY%?9\#M5L6M) Z2QlT,ҶhBAy#4.@|2K,U0f%;T?C e>B|AA?u\iR!yn&J3tb rq1e^(߇q%Φ d `_4&]㚘g}Te<7sn ŹwKf.[:O m򝣢:y;|ڍ;.t9:tҀ%noD@k'FKQzQHF-ʹN['B|>;?+I\o3h@,izB˄-Rȏ|>>` NYķs@tЏ2gB@C8-- {/xN;# ײKaSým.ԇC4UOࠡe6t3p =ͳ/J1Rڱ9ʬ :HO&uӏ#'` 4:H+;16S OCZi~&qS^ȡev.gd9 bYVգ@= |I @zD,/ }i)u* [@u ~QO}KK! )^/Rg,oK^J @F[oQ&1^mY*Ʀ!0=pGVkXc e% B_-$3!dP`ܵ>f?`acq1Ǝ7JTbDYQU@R`%;C m h +[q9FgAE_# o6^?q*U9=TLޞL[in|)+|w6*U!!xa"@c^_˼b7L/igDcVΨaY皅tp| _1!BnDϕGH.-/!a4F; a\Q" }Cs#?%>_|i>" :;,Zp+t9>5E?i-lfN49)=?aʀ~FW:AY}ƘgBsmR#G9y>o&}>dkdJh0rnh=-0b{;԰adc38#Yшnh<؞QUz><',F\:KCAι*P&=QD lm$00uMi F*ZnrϾzr% `0r^c bݣ3tp:F:'wlZMI haBF+Fc>_~⺏LN];1Y*pjdgIHj{sm)4ggag_K{K>.>}@FEcF1bQf:[3kbf/9fv}!''/XNyncl҉ OcޫG+ח`~:yDZt Mo;^vt|JX 048x(iC X?c|H87S8牸7U˺ `'KwU+ !87A$0wRP-hDt]_DEy"y0uIM6"@x~ <:gM:ΌϦo٣>dd2 j{WW-(ji|.\zj@BRp1Bebl=Xզ&e|)L^>bw8qΏ7Fyuԫѭ\ mmxnACԚ:A"gv+Ȍ1'dAd3RqCnSHޥ ;x'MviGq0eڽ1^7ʶ9@9 epL,.p N"^GbPPuO8R+_꜒E|q[;%Oy{zdT^!4 2Dl3rKfA CfكflH&NSFӞ7ȘN"c71CCU:s@QC%pnʕ:ƾ9#ȉ:6}d.7"< ~ҙs OR[=`)?32LR L]7`]]s)]u^Z6h)&Tc2%/=#npv tờ˟ ?!&/)Șsg$% "XgvP0~C@2IlETC5s2N&)v+y֥q?T\Z¹4Fy+n_+m%N2kֲb- I]:lY]Jqi5paAcd"}Crp}ꭥ[iR3ռסu* fbQ>yS/Όva]i|g(G+|tc(*vF)?Hg zqvI`ޫlJ ^|Me4Y^lZC(AL4diya@h[pc1Yߦ "q5[C1C@ָLX<i2 pvvON9>I]m#`Ήs'_FnM:a;O_H & A>lrJE@IDAT97sy3sJ;+8hn-[8~}*;"{| 'sơl g m\F]sDqN#Q4 W.hjR. :㳼а`;?/^x}9kz1FqAgAa=j:A}-V#C%oZ#h\&F_VaΉ-I @mZ+"Ix{Bi ]gsq19 ȽS:,#3dgwA,9Ƥ<)*}''qP^ossww-wډc7ku16H;s):kiqO99TN"qM9;ԑ @Q^}f\܏OO@ͨ( p0BH"<R`3|'1cfAm7_~b#c1Seߐ${KF:^= |p,P:Kgi46s9obiǙiC 3ҌNմvܷA X-R_F|<;GC kCݤFGDul;EQ :Btr\'b7pڨ"ˌ Hyϙu}9}:#ib : [)kw&)Ms=>D5N$;cӌ«'¹Z$c7S2Ys$k@RGGt,Q>lR6…l5#_H׌.ƐOɦ]wS=`})3iaPiѵ4pFR_9 d4+X-Y-XȠu/KvQ$X-)ϱ[ȏ܋΂!f>:$K< -}-yqFH?:ьòMFM<0׈@/*ːáۍgז өCEZxuo  hf;`9#xkQ@ :g>-ahյD,i|:vU %P-l5SFwik'!wM7wfe5tb&t`#/edj{X^k nF3|ˋ[|ޯq;oϧ[W,E.s8 FB>Pԩ^'ar2`: gk ީ\#F^Ӷ/exitF[Ag8˰@ug J)1N}lu6gNN֝ʣqsik)|\'dʥNpD u|Q9XZl}A8yB< ;k8$v҃tQ)m}ϻyq<d>YEB >OcJlZs?cˌ<>Cx0t 4jIzi`1FZm"j=7bHOltqU4D!W~\7J(y^ͺ|>0vC8*HrvJđ8ig}KЕczz$hovޜg>#h{,1Ft3h#ss訣F,W ~\s1xb>Hf 0|YG,2 pcᕟ (7OA'k={|ɟ]vuP4B =H}/W.cuymsM}h h߱ؗK kE_?kTq8p+v3/U(e47 4Ȼx>0g8HEqCD[% 3<[hpIΉ5sBɳxO4h :V+, r FGXWyC?ҋy e#3քl!GZF#;":g|'t6(~yF3:k6]]WCi]{vc 5{оl |I##^Q'8̐J}cQ>FE]̉T6{ >oA{9RJ|f\뉮dA~{(۠M@lP)2gzeҴY<oY+^`tNrݑId+ CiH0RuˈSz%y5hDJ`I(寿y^-gn_y39n콬6X 8.%ܛ˔p ,@qh넳'mTWҥx FfxQ?}?`ΥoF}% ҧE!jWlXtlI 6{mwٹH]*х~9y"JqxdD n*|6`9{dL#%j_q+f4=I~^>Ld/]2>f1`:j9 2,I?E~-ΡYӌyiEcM$Y{eef{hl)ġF"Gٳ8Fa}r8b8q8PgqÐI#")A$n^յdVJR v^|߻{g?8 @_c21~x@x5Ԑi_483Ai '$\Ir,QH{S5 5kr&Mϕg(cbFyZJ|_iO6qoy)_扯`87YLo"F:޽'IM$'|&lm[,؎P*ًJc)rc] F.^Tc*PXm$q9JC'Ԁ?pY ix%H ̍eU6Xg[`յyM@EeYa7QOagZ䙇R8@K@Р:$x|1NDpc0g26l#%= gZ2J]2!gD*/."G[z̫G3oȊSj0X4r6u0K +4c#'Y2J:nZcGRSRNBcMV |m# H:}:K8clVc'tV# 薙0{tB:I|+ L8-a0XЕ5BkkΈA"'T:K-nT)=>1|x='J#QʨSa_J;;(9Nr8 Udʜ=Si#>+D.Nwd`mSIA_0bg 8aiAcL]ɱ7@q_G dc7m Ag C: ieFwRu;]&૲o2p{%-]{r-Fp[4:TAa螙̬ 0!j_rgFr{BF!YF^zԘ"Q*^kZ_Jfzt @mT}qyÖ[w~.ݸ4E|@*7o atf;k(_Q'/ G-74VY${ #J_d~k #PlGY*zUzrg4u1UA# BFE/RBL~]^zۚ>4 )&"=UJqA7|%R2`*$'>S7b_!x292z \,/*T'iN NGigTgV*,njɱ @bCXOL9ᅀ$amD7t0u* y',j1Ƶl|B@5z! IeD;51Ol yUgkt|||߶#߲r@pw #rǺgAr~P믾 `=7QPB EiИoqy7)O8xmϳQ@8DnDeʺ9uspp흣ks^FYgTUlPnpiX3Tr3縄Q>nF/Xh7+sXik{^VQpA#cx5`X6GkìmW1_X3Gג&|4< ̎|e;k?*h5טSbc*}AWcY4;;nݸl:(0rRTd `?)&jlbzz셅ŕ I~1*F<UlW:2(j<}  ?wzoyd?C1^rIW$'ʳHeP㌈؈f#8cQPb41:twc9He^K/Qa(:chYLHPY.l5jSZN ܔ4U9ZӁ XKgysSd<:N?v-JI;qCN$YY ѡBˆ)^6oo},c5 5k}8,KAU'疴[<:#4{M"+9s]AGOF!|tEbnz;4{nz$Dg3F*TUtcb,3< 8(.'%:Yz$t1NJgX% Gn|]8ʁ:[ lr&GXtdND,a^Xw)Y5>(F|3K--.əǀ>A3ϱv8t8vDtN?Z|2nʲ:zuvR| #d gϮfvdBs8xxegա="gd9x" ⎂[6%\cuG|& F0MHpsMvч{8X#7(rlS}70SV.2ԁg{1xw5٧)4(`' " }aԩ/@ڡ~GB9g:ۘ}Ub#7J<ۢ %:{!#9K;9j//}+-47q?D62IfV]b\aO.*㙍E}}u5M=yPNf?Wq ?nxpO\;(ƞc.N[8)FPyED!>p]?.vKΎq1Vߍ^ydKg9&"fxZ~q±ñLQ<ݽRxHm8P#$TI6lZR/QLEccc#1FNux4}#sP@L[~0uϏ9Źxɟ^`!Іc(^@Q٘Gݖv2zn Aps.}զSu4W"ͬ?~ ,ϡ%=({icc&'}(C`g H* M%U޽y-]&6Ã_y hI^K}߭y1"] DPns*R%Xĺ1AM o~M߼~>X;wի1(Ra< :p/":x_èk ;H:N ٴ07ΝOvU0Nc:y~Xfy-Y,WdM@Ŭ#M8cb4n, ᖴףq|f[(?D#rC}? [ƨJm3*TIǻϞ9!}(5w!1Jcݧ@o9+v (ޘC4G$~z6|cvu[_gk?>P",'KO"bT9]h]T9HuGyN9Kaki~tl6J[Y1'l!yY` 8?vsVI/oV2q䧂Vʏ5bc~*u Q /GtO~${:i|MM=8|YԔ劔60)}+O9"А݆BYþ |~10iY,ޕsDg<ZK^NuCr xgqD4R!1vhu( GmV%hQ5@1SCr8:fe_.̯MDgvZ9LMQ%] v0tjtn|/sNC:҇cx\>̳ifGoetE>[-ynoPZ]QP_VXǬ7;;d`{@S]ǔBȢ.CZSfpR|+qZ|CoAX3 Lƻ^D?aO_A4D?r',DfCYH BDXXCz0;N)P604|;AQ_=iH4V2KGZzQ( :Sgu<_\gzTsV,,m%J3\8 nQpۡq;7fkc-MU$r:3&+05pT 5#z:+i׈HgZG)ygȻ0%+ jzD3RE iT i@S9{bzӟI᏾G7P}b o}][Z &9X 'yk.\>|rJ*Yj]\ڈKbB P)S!d e;^y뜲QJ!= tUs Xd\^#;+GXF?RCާ)y3Co*W!:#YVZh?6ͅ-e}*go쓧BxxSAr@89o획lPI{gѶ 7S hcᝨ]|p\rn>d* \sqqgcJA>"߮E<8? gX;g 7D?#ѣdMO*Y(EԎS-{uT-LcOg!8^S<1C+EπD;ci]B-m^ ! Jw*Ǩ ^7"@ٗ2Pm':֩'rl(5vWP(KP[kQF\t+igxY |@:u4u'TB J$}K)=F$Ъu`1=Gl g39_q282R35x/;n]M#VZH:]ͻswS3z:BD4bic^f4Αm d]eI USf GrDw߻Zc8a P\k``_&*&4vNbS,!_D8/p!m}apq Ȝ Dgǹ*3FIk+ uf(Wvp_І]kGwZEܶư%JJ yp뼢'Ӧ'0LNc;G#= s|K}|\Ms!˜YF3Q XTtH^q4ۖ҆ 0+/0HM0x׵Sc##,0VK(}itSe{)6Np4l|H|t83}%{TznN=L{\6{V/)}6DAfv1Ā,?c{'OBA=ICcWO}HK!1☣t0ꒂc*[(/IaDݡX'5ޝPvaLH{?g~3=Zvz;4+xXZ$?@d T(=KW/WFaiZet~_ڛwoӗ.?AUpTP Iz d^hz?#X"5H͌qL~ {V1nm, }iiWW0m%}UTb6F5{~_hii~H^l>nnPAض!Ky欯a`..@R@2A N'#AI<ט4\6ㅧ3\y{ߟ?^ %o?ksT/FEt-5m.M?o,z"/Ǒ((`]ZC=Y[\wO\&`z8⮓_[8f +~Ct2ΈKtq<*q[{G=K>`l|SfZɥ6> eM tʜy1IsHϺo,pC㟼@8km#K{w?%49AAօag|F79>@zu)OeJ Ƴ& ENO#w,k?-'͒JסWW:2-"{ ɛP%lVSdp ـ)0ⶉA•gRg Ȟ6ux5UbP ޝ9.s C;O؎NĈ1W}jCc;On< 8˴I?"l2򽑅Zlg'ݣdޕMZYoCkdARgSݙQT7wȳH)1~@]K$O[]GЃg  Ǜq1JHF:'km35 ,ү(D<,e f{22{}EYYkF9'(W8LW,\$MJ:JuKe]ls~k4f=[uso\{S+2!agΛJ6A04}3)Tz,;:`* y 0lnX#R,mx6s8X?zTǙ6&x7#0 c} 5J5ng9KVl}Nci{}5`)YAPAZ7zs$+ž .43B$h8le* e@0Y\*״};:(e 1Qp6}Hk*:0F`i>8%߶yt=DcedM)pP^2~7E!C~ 4UZ"ezyǣ09B0qU@yoA5~nGݟO1J482^ ~8YM0ڮuT1w ˯RnF8Y/W0 ?Hw4~#(j]6џ0](q@0qWxEV5H|;!( x{Q A*.0VlMVڅ@3<6isz3FPL.^WL3zFɻhIFXBZIa4y˓&G'޺ӱZøZj|R A25X9 ptĴCPmIшkc"A4@w6L>yŅt5x:xpM3ZmڽCYR_浀xmi1tF|2l mSD`ކV-n!)닋%699D5Jc>#ø:LJ~7ckzVbȲM3AZ9QyK-@IDATI i~6gZ>u5CFJedg}^C,֡_P|hm{pRD1VSiAȅ8 M9sucOw1v2h5>ALGxKyuOwU }# r/g >bذVbINGT0, U Ct<d (K-sY6=9<8n);9:S ŜtG>#Vaz7!:lu',wukqJ);Vy@G`༳| LYouV)۲E{<:kg~4Z3Z:q;NkD2K7sqq:2*?uj`":ZeB"H 0s-g_:w)ou@PR7m/q,D[[r&Tv;ͱiC[ 8or`3>RYԆS΂]3Lݾ^Ù ]~B^Kߦ4 u?@<'Vbxy|_W7:ݸ|u=Kdsd XtTos\߿cS| ޓhԎ9ݘ(;(䞔9`ٞBCUbVO[3@>ƝN9*_'2n_Y9w:?+13C\iWK|o~)<牼Аq#0F b61(`/?_[jq-kQ_ =MIͯr.O`0P\mpN*\1{j֎T`mC9a81?6=믽Wi:'DEa굫DlF -NVRgI 1޴B3_GdV֥, 4غ R* v.uiSa~%B,䟀wgm' @BhHG˴PXM n_cB.PWI›)XF*wܧs ʈ^@zt7#uYuoXER( 41&9`Z#e OY_R%FDRa->#CÅxȫ1+Y+@!ew/Ԩ9.gN-\s8!;wۇ]*|bxh@\m>_d{g|-51sPX| )w.y?d~\?&Y E_}ts_;=vURcc UrTQ,.WezFɨ# KPG8>sx^H #P4tC4 _N!,YUX:Q(+["u {~Ы @KQzC=|W-]x>ɳ8_H @5%L{Q VHވf>j}ސ+4pۿb7K8VF1bc>wfya׽P#=,sctg\=dBu Ҍ$U rIE>Wz8[qmathc{QƲO9E`M4Kb/S]cyȰo#s3 '_'>_GCHghx%/{8)B:H`'SD> @^:uj"m*aC0P=(sct3k;}H}/&0mfw[7o6/ug pz,nڅyJ4e83 WQb\dH:v(SDv8(%la>csR0F@am7Q,Z?vWTh =Ed 8H]Zԩa+]޽#>txÃAi;Awݛf0"sbw=MK  l83=25V+Hd030UwįcXq7:@2l[Hy`pnmiku ] dWMȴ?::(*ƣEW3>UP6 lj[]Ts#CP&ZGGƍ{RFlBɄЋP_O˗ t O#  D 4ܼy3}s8Gy0ng(¬>՟j79"mFeѸ"F{QΞbnzK=n_xD?q3?8KrL^Zc/ SݧCeyt_>*Ky^CdmwcgbwU xmAuitz(d'\=J ـ.YP64I. b & j"N9ԝ⃂\D" _߫44c"rE譇v8%P>+T +(W@i(32mL7sA.C_UF$w |0]v.m:ug!`3NmJty>jkV#4)R*e#ӫBiss (Q Tkx*Xo CwYqU̱]8 ~ndRnj(5Jv-(;y< @ME印q_d)dޱo&ѕ7 ᕭOP((b$Ռ4LF2ys)sIJo( Ƭ蜮bsH×tTt;=4R$TDjf9ya&IB apƩf Y!̧Xpj&+C3a<0uQt5Dy;ij>S;gㅑ*Fs6o(QIo~iA.N^M5##p;;i(v>ac:Ե<-Ի]*raEzgZnϟ;g8MR!TbuK ._Wu~> r>=job4", =uTGB5 c+bN!: 7=R %ٯ0Vqq꫕Tb~zȻ7?Dkkxd_;yGmg|JyveFs4A&N5V=e2=S 쮟4Ft-9N0-p¶Mf#a{Xow.jȕ#AdHe\v\з~)'m*mMdɩ1 ߕt%q;y:;B )B,ݣsbij/ͨaf$8P-B.Ajq <$iP_#jD'c2$mU&AMd-";ɒ\wPj3^rQ'uvN̝ut9f}hbd֙W!*8_4fWx#C#qFi,M/̋d#@0ݩqdV20MJƐ士8?֦SgęAPTdt:X#d8)pS-޹>TYxaDQ0櫫+YRӕER!~# l6eCŇ#kx* Uyb=v ewa8LO/d>0 cu/YQ|p|cU4Xy#c+qqhx(mmw!aΩ;ͻ٩t㍗9¯}9MN2nx{UDr̥H$C[bL1lD?Ll؈"HsV6"ϫtC+p01vY: nKY!<*e%qXYgJ~r/[^jA)  f6`SA#^{݃^?܃WFǧaF:_"C_ɳgHOVQ5~z!x̲Quh~_;yEF⿂BZ3_BWgFU遾`2"YGF0zΜbN?٦%SɀXub&j\C0jY]:Fi'_sz!]OrjwaǪxm2EUsZF[E|fJnlҀqD ƪ&<5)kPnm0L5e!QuÀG6עBVԸG(hWEʖ5.w>5׿(), 2Fkx{`ڱR'TVX553 2^:ťd Rwg/"%LYw:HD4Q saW ,B(><ؠT(:RQA}w֝h8]J;2U!SKnY3@~Af]ӎZ%JZߩ" kW+ҹZBI3&gCWy>{ulwE:=cW`T>9zD{SO04ZNA,#ˌ>oV}D0xNPuuQG WY2ɥg8)XuF?];Jmj"b LۄtV~=nIuX$>Qk8FT2u|7Bf>O`4vTzY hT (2B]ZLy*O@ͬP}+v蘖c3NB5 #?ƥz%Z]k#J=nGW7"݁qh`OQwL(ڱP0f-lP]2k#:k: pI/^"o hwl\k_KMD RkwEw_z*QھmEV!L1LMx/F78=<^H"NB;]ܓԹ5JC:i'? )WXsActn"M~2".k@{4T( OPx>o 7;Omad6rRsF̕::z/7thOSO>pja3W R:7B{l}Dmm2{!HcFtJki=;"dݥߙ"_ñWu[ vę#)r  @:k=3X|}8 Pʁ]GAڏ; )KoquN70HANNT}{U;*q~۷n7".$ p@mgQZ'X.Ix~>FeJBbQaD`,ݟ10aSY%s'MMHu"8P_* \Pv6N"' Ṕ$ C@)pb=PN*kA\\yzO9C<{5r^dDFg&0dwY'ш85T<ī0GeY$iqf8qٶX[UZysk5224nBg~%}7~*YfX=.0ցx >ρ@`GUtwt7!v. @sԩ;őJcg")#*wF>y"8}ZQpeϿO5Ji]+KizQe=/9Ԍ3C Bٕi7yQJWtH%L\)'kpӫP4z1^[ K>FnVͥ5JD)ރs(EӈQ]YA{o% N{}%*h{D7̈ӋCeuhR"DIʃh(WYy3G2ܝ0p~FpbdH+O@/㞊|~{GuqאީL0"T#KAcfYtȴ/nh:ƫ C|N;Y~%xriB \+8Sy择2$O! h"˟>^QVK^xty᷹r/5Ԕft[(A+Ȯ6 ݧ}æCqjl-G>;K60ξo x\}~@,ìY'Ϻ_{DǾm-ձ"x&2Z;ugSwur$Y2{_YŒJV=X1SϽ`܇.am30fBOķ>2#+]x k?orߋ MsێaD>{Jy}f0E ol^4Npj3tuζ5Fy9_h4u,EЉ~A^3ⴅNsҲxEQ.O2M 37K0*ЙmD{o+kT|*"cFl% SN%30e6 ) 6v(G|gu&ѺR;1kF~d&T,` )n q)}TT:vnl(~ <?!}=c Nx7@M:Hp$ K4BA" @4bgӧ1e  ߍVۓb!5ldﳥ?  q`~$΅aW}` >(haYY:Z{RD3~܃deL s"# 9>Ѧ.svt>S[ N%۳W0xGHQmo s|އ^n/o>.Lu:UHq f8g/M8=šN|f~>zk{ o[zՆ!r3MOd h}x)] __p_I!ԓO!ĭ#Ю@FY<#.P1P bYge; {02Ƴ?{yОff B4VNж+l~$M\y l :`xz!""ZRS'p/g*E( R{HHQ Q[>kqj QXl MTqFjgdХګ 0Pz!GFAi_%G(lud0Jݘhv#4;7*l*D\[ֿ>3ezC`Нe|RָHsw{] M\}ea{ 7t.x l(P^b*ƧLwM vFȫH;7oJgfP5fVLZ>vVQssD/C1bj4ޝ!׿n rb흛򣴂CC1fr:G* t`G6Fo^x^6_*&#])ߙ!&c2cW0n+?Ir @rJ1$t>|'>8bs*t2C^Ǭgz7 /-sV:ax*]{{a;"h(~hxG)/j䴬uQh`eI;h)hsp7x ;m>`%#`=gtG6SATV)ج4pzeɐ6s4!l)K3fѓ>y|12!ÿ+[{ڈa֦KauuS@眐|e1Шm-hi#u,[:XƹЉ>M'NJ:+ch4\BîNt8#lr'}e0;[*!fY1wUS[àSȌDSG2qX{{^gN#Gs {znauwM%؝*"m!?o ֶQ0ܨQހ(` y/+iDwh 9{Bxʂ ="::JRYs,ֽwޏNy 5ه1+K}&C-ƾZ#~K0zr%2ޭH4~)md⢏)֘d+|!iտ3)?%x F8k#MFLT>_zH?X>%RmcNV٥J2[lL0j҉9|wJ@Mg(WE6Sk%>p.[wl+g1s @eKKze=eGbnw4Ƴh^fR^Pzc> <}Чa'E1 t<0v=;wh f =ёn;2rfe}Nkc \"k$Y䷴C{~qvyC |Eо%4{ٯe^"sp:˭NHo~ڨtn#M˱#cN#z7 )Tƣ~/? 'mU~2dCAѽL%OW[>8ϻ"ؗM:x辱ܳe n8 b gG![SL@IDATyχ7- [S)fd}CGLXq/xd7&:gpzGT1J e@r{Cݏ cf,/ǥ8 4l̸qo|FF]3N_} K%cWf~DXCT6~6W5yw q ~2re!88'BgVVnGKqK~N&UO/p!DgU32N)oPֻoptuqDe K[CV3~tL>8: ZDžLn *qAӵk. pM+iٗv8uvDWYwz0R!x֜uX"Hd⦦]!B C68y4fVݐ~k'o n姂m0z^CQRqo #,"؄A”%u*Q, JV&m 7`⹯FVugo X:5_,>ؖg ~w {< q`E4oɦr@≑O:T4iR +{ F6h Ҩr%ҧ.A ru<_C5J˶;ʙx8!7ݤq/mvƫF;VVg"4wҤ_ =X3Mu*1ƒR62|S]3zKuorE/ ^8 3^ *4:8&Tp5ģ(AѻiS@1.2O p>#G45JO_⟑SU-מPվ;x`@3Tq{ƏBAhԣccl]-K'9[Z76sf4A޺VNi?P^O~G9ɓٳ 'k3ҔMIx;\cOXwҟA y+Ɨe"oP=!8qKOh7Cc1jZ^ nz`lK./1O?„i;/2 t`ؼ@Po?097*4L}Օ% aymB퀀/Nk@ñ:1 k>\a|1ҚG;˾it*̑i0Adlccd f4.߸{7y.˻Ƶ7g޸GzE֢M3ӧ̍+{c'7=7>cƫuHO{~߭3&+ٗ#RQNʽt,Ers:{iU5x}+6mF[Mў~[vWqN\z-#YVM8[5ln`'AvGQgUn‘Sۣ])`58K ]TX'۝g)c} :vJ=pac 770~p0u n8XuʋֹNmE$Fcc )EHTq$Sُ4D{+߅c^O_= meƷ?{~N:Jc`dℕ7j RxN9o _e% &ҧ$t}jk.{E\ 5@WuBu)y-ʖn*.V{m++)Al҇?+kWYΑoݥ[G'7;vw`@Ltb/Y@.9ͣs6p ^GCPQ?Q@G0ǯ^z|STkoj2XiQ]ת+ LD}{ƌfu/&- g۷*g zH@|Viw/;-ԧoA km*+%M>ڙc\WV=ʑdrfXW`t_]Y/6pg<[JXRGȱ_`*P* 0^|)LׂS; r+5z.ó:3~.c*M"-(M- trv::<  NFDu{]8y3i׽ڊ3&YZap:Ɵ#`Nڱ:ZB\<8ZC+wKP/AGMun u2N8q;{^}˔<[ĝL' ,Ch4={X}('#ʽl 7/ j4c9N|U CD`uA0`fsˌhqzT*+%>51BlFy)r]W!tsΌ#w6M 2rLHG62Lf9-mGty/7_Pr[5Vѿ*7O M1<]"')qG'?ApHfV4θV%L#$ݼ6!𞄀„gyBNy&#͂G@Hc#ipAD!j $5_;ٛMi)^hXKhJŠBɮGx {ivW;ZGCEV0u:/d gLqWprzΝ>D{~׃A.ε3:5wogy2]T4#4X ">O~ߔm2Fi0p/Y+_g2tgC?OP9pV4c,*:-}z r"?c&ޢ+G=:yN_e/Uޖ[Y~MᦒLkJg{\{F<#H YUTT4w:(Z*P"9:5\80WVQQs8wFYwϯpUT3lkUhTBqޣR&YDQUo"T"PR!Mpθ!D8Cy!$ =R23YLVث00 ot&2`RxLË|煙 L1S!\]&بQ25|[Pwxvr)mXp^*gΞN_w.Α}$^2YsPR;SFi#WNӵ*{+'\Ov%p f8㶃ulitsN'F:C6-iG+~5pj°d1coJ#8A-;3gg&`C* 19d:oӶqqdqw`aN4f҂cV 1cM gy8N bo|o43uJpJP}cҞ4Ye^}uaV4+&[xwxj ֈ&/|.ky_^ AW({߇#Kuٝ*9>p>P^|0Y8߭^F#Y྇?^~0Cữ/_u׎;`P^;so-ʂ5Sw׫yc~m^嵷70]+ese]DYIyjwm2~+{# 22G[-pxNa+(38NzG:kdspi{$r$uxya27dB39Q6]V3S XTZi4䦼+n#f`'(7rΰuZ͚zՔZs\?qu֎I2N[eH:唛#f<Ȏ2;kh"y}EĻ{4{SEmUʠPOĖ.9VVNE7! ZQO&uNF4yQ\{ySޡڌ9 xEၬOt$KSZCWߟ[)W {e.{odF-@bs;᯾C_> Ώ%sʧ'@(e-TDPK|s:܆?2JC>C@2?BU]gԎ_Y71ʕV~dE/loX -sQ` h!zA&Sh;$GXDصs\ p>K3o dd[S3 ~nK+e9~/A㬧XL?D8JUhU?M()b4IPzSS ^S&G[YeZSIT䂲I} }wpɠhҝ6Z*Z8h3S #U3"[*IeK;McxLwdL䑞kLh7eݱ'|&|=p V0(!ѫGjRK2۟o*oCB%9mۺ 3b gyvyZJ?geێv tކ z ]$dǿX92O:4=\҈)SH:UWK wLj5 AIF UA"D*R"ŨWGeϮPA46cMc^r Oób$i!3DAWD;|돖/韕)v AN3ޅc-ѶwGy_kJ{t-#ET_+Ll<}.])?OllfS*5;wyδ`(g51Pm6 wFApY S 8&8hVeY&WH U\ faBq ]Go)3 :5ni7A#yUUKz, ,oVǎU$#O>2DB(ËPj,Qs6hԾx9dnﯖS'O{V2CVxV%hg(Fs]ƒ}Oz0A#`1uB3ʕ4CZ/lYsnT2Eҿ0ĞU{Q J$#<k^sqı'^ l:u&+ۇʒiڷg*ڇ*7 J%™T z-OO4(awڶ&"Wk47ۖq2hJ`=TlW>Ewi$1H'y{(ߏRW!w Q~)}@=Qiy:ds4D?ZԤ":煉<X.kqרbPmH &Vjh0u=#f> Gq SHYrT%N%6F5E(߳q3f!\uZJTSdM:[)uܽaV|^kv.L̘NڳwiihjW5ƐrwUqIյѬLT:_Kq=uM_;sǘiॼffzᷲdbF̳-3/PWzIŪ~#YG/iw䯋57Ͳ^d&_mc^t<ާ3.mhS8;ɪs S#} ^} HeMtm:1M]/}dlgGp׌ñKnymBG/[[%dePQPMhb,54STޕKB}E*NnΉnqna ⅈJ?Ч4&_R~0l=X`͞A&Z _>ZGi_޺y p#x׌lcn|2kxoky}ƮZq%þ\<9FåurAƙ'LV1&dk>iG!bl*>OڣM#6x36fO ֶƙϽtFY@hFʃȀک[| ~.n>ųX'1bmClWƼ :U<]gzgQqяN^^ӽQqjtV6ϕf8m ,)ίc} 56@[Gz˲{2c}.rl8&ssM-z_e?tv੓QD^ԡQI[9Vn8tiw gqL<w}8O99XQ*yMp&,:҅7dB*5 $6 fZQ< ?lADoyZΌb34k N6c\-##aL hy3貝?s%HRi97o ,SX^,8=Nm~"O΀mۉdBVYfB%w*#;~ȠssoݻrDG#ꞦC>Fި--s}?7SOrr!蠥 Q>™W(g *}uĨD!3}okDyg˗eJUR4 5r阑tTԹ)V]C- -N3D ctH.k8(1(YʷF7-nd1D*Ve`Zչtc 2p"yPmcP-?eu@ZWƧ^pq$J CF%Y0!p"ܔP2s(ubܱPIUPS,8unK2e 3} "-g8G˱;x7Ne= .DywkȨJ,!0uKҦ.ià>l? !u.][xhFܗƨC_i2|\FS?+H[ff 4h,.t- N-Gأ_oϥ4g?ylg} ڳ{G$`g~7bw?EJf/X\fPfݼw  3@Sͮ_*M'ANqq+-l+8Jء/u;452|DU^ )|T"I ,Dڵ,SӗV}lZu( M9H wǨ^t乧KqCxrKg[d/+p>/elxkD!Kwl>sK NȏNl:yM [8Cp*7ބ]?}}6r2:;;Ku.jWbyn"2_'<%1Hݏ#tg6WnjApzj*GK٦+E*nWWE^%*fu66E_.*QV=Wo%OYu(,m̎{L@A_IHKm祐Th@jGqV9vQ;`2G ` žJk馒.BB}2YH8Z NN`};P[cU'Wٯ P&*dbsK`30]QZ9^-v{NmeruDM(k6hSXoP07[Zփ@M|mB@qKX{X+vB}ut݇瀥_X$[9v*8uTO7Nw-k Ec߰L9seę2\a.ipda-ԍt>}of.{t2Z!@D^)],  Ii0@͐s8[ "Q1*;?JC7 Ł;WP ȰTΰ_{Ⱥ`kʟk@Kl60Y~CkjOΚ3/~u=AtޞeX ՇlcK({FV'aFO',KL:%hk @u#`"8M+{6||rwe,:-ymBiV6͜})T $ U4'cy",hNz&i= YFJ@zekMVC,_ǎr"gØ]q4*;AJwΌgaěC>L7Mad#ݠ7ܨ#Cz}oWMZnܶz,BI;4熯㨖L pBOH{RUS8VgV~T<{tLidxS$ܢיJ~r iF4ƿ -s{:#/X 0Sϸ8M%bJgT"(|=KxmPxt_1t ~1lgLZE3]{r!+*a0$R98/D~x-:{T-ooP;u*D2KQ|}v'3uj -qXkmqOX-DuTsҩ/&ͽ#*#Gc ̈9%heyVp2&3=g}ۯSӸnY9MY/xRW}2G.a8{;TRѭ lPf]0?˃lb21VNGk":h\b53t 3J_ڴ f;qi>u~b4~1Nd+cv1N& љX2f/eeu`s)d;p!ޫKQ)<[u^ОރL%fUϬ\2ǎT~rmryil e]9qNp|ޠbΖn& Cdr3aVZ[m u3`Y΀KѠ99uy_9{@5 ݃Df6qP<7g=ov8,3V]92MLi*eXS9p'#PW/OMGa }w k7rfe|5O#౥uבp~KNgUs?t\_O.0Ypi?{}#-r/JC=Y&%wK WڈQֆY'<\vܿN5bRVKZGy i8{|[]bk'CtlTR~g*ש@}D=k#3oi6pPuD6T'r/2B"|'iSq }oʜkv·gi&LW.Jð!ЀcKV$N(( %09Fe$ɺ) iJwhx@@}n89qIo z,F^+K0N.޻9y~YY{v`OedBt -6zDjB+KZdwřf;OEv ŭ Y2j?T쿥toBρor[Ye5mߩpLrjSf\~它^q*)WxM[**ba.r#Hp$pUϟ8%(A(0="7+ܚy=ӡ8EA_9a@X}wz{ɨgf>2thf,#l*XUA'xl/_dܰFXq}WKî4ZhP-0b職tf\9d~<{!<`k+ϫJGF@A>-v`(>]1P^bV# FiI5d xeg,]94kLuO4IW~BWG6~4ƟZ B:`1q: ՙOcauǑg|;__|pt/ve WO :CCAI#(]R?5L#=[mMyt~,T)@߭LU{bGT)_y^p 9=Yx/hm#h>yCϗ{g} }8 pސUdzX67O[256uty5xWp$/5U_+ʍ$lVM&{&|fP*|`}Nn#G67|q^J*cP&֗p))Y*]InItm9VIR.I6V׆SQ݃GY8ͬב̱ZܫWpi mphtdLe[hiIb"Uԙa羫-~yN\CRgf[*JqXPΡ꿞MO-RpkX1Fsf$[y;_uqC:km`TC}x0Xm72?U/rLuvX22eM ɘŅʰDԴNoM2zWeX Vcifl6Wc3u^V\Hcڇ/_Y&iE'}ЁNmѫMBgLF"_nAIڵ:h +kY˚k@{ҫǥӯvAV;]<u;Vnw %kCr- \0[V"s#kD x9jmt@f;DiU >Y̫/F J9DQT\$pǀMm=tuifr 8S=0ҿ|G(ӇȼaAޫ"K>s,|s0#$[6ȻtbԆv~ˍ]ؒg](_6y ^Kj %8҅m)軇IcQ:3Ͻڡ/9#>ҵMUloi{ *8.{rx{Xj puRt s^y {ʞݻ`2F}9,@i(}^KSdx|Oplt6Źjtt9srȟ(kUr!A79xx)0x VX×cR ְ=qJTKGux^GhH7%`Ȳ1`@rj-QzbFx m!n`z?W3 Yu{A>p\=,&h(J]w6gȀQִf$Lp}7ZoQw2r :R,Qe3\у9:33( o! Z$]W^𣶼O#2'̏٣\dP666PvSYrp'^tfмmfv3YVe|iL&x5Y0pq'򙁋-i3PW$ 1/)@j!zpٴ{r|~v~سSYnx ӡf2:ƍq{xmwov .q˟MRe׻j?k p: 0Jc;}|Gqfd:ˆǩ89zKWdyd rOkҌ'N/?x~S8h@{ˍ}g4i6**N,Qc}{]6o'ǥřCʦVݲomtE`/e_9T]ZZ h}ЀЈغУg/zU . fǪ egc:t6*ߋU']CޣmEYݹ,/,ү9 mXنU1!]CtRz+cwnާ~ͣNh:3w7c_pAKڧ%esЮ"l{+znՏ{I/jil\:-;Q<͜j3fy=LM", n:(9"17e(aeҀ'W-O2bKgN M*0)l@m|\f 6Nʣk[$~=\;aM< ,øL цv93ݝTI8JbaaH LRvT7!aq]Qc~QZB@.^,$㚣=)6TyֱHGL$|iTPļWIrn~`ƌyɨ% Qn5:ߚ39Tp-K1  tr`rFݗxet25&, \ҪQ@Hn4GqXd7)ДE!T@l0]!i7D,Ќ~ɂa>9'C|f,A!L `7M =Ȭ9z©<|虲[{G>QEA扎;vXygZ)| 2ӱ@ԕrV RkJ+__,)H_2)%zԩҭyG;&zk?/g{k\ OMUKC/N5ixXÒtsȑrTAA$tF*)*(5*: m9BLJF:ٿfIGd?BmI+*} L pA; V*"|A|KT<H8ÏR{ї [6u}|ޅx$2^FC~8Sxl.8=ZP=Nv7a8t~27wO~:??E'j6I<*_Q9To/|~ДAҺ%@O$QOyrsVPXmIq>3(*:t`cvڀJToH0LloUv)f+׹cͶTX%6?*&>~T4g*F}M1cMAc/ ;rb*c0qюBƹ:nEx*sfpG)fJdcp7u0 3Y{pT[pu25-xw]b dhf&}m?xǓ ~Wo ߡ4$ͺGXmkmE=Cy{գ!3 7HcZqh5hl#HuG${i8̇Wy2WÏgƯسw_~ko߽Gu_}+l}@# nV?Uδ+7ѽ!*kwRչcpsA~7r%؜jIr%1r_: .`t2B>;/z5~)4p3o6>/k?\ƱHS^y+ދm˽ޔo5)W"x nZѯgq>œf2cWN$f|V^&|نi˞AqI xvpvppxr$C:С$&G]ϔ]fe [8Qﬤ~/CsB\}c E0F앪[T:uF&q- lO8W[,7=M%O6|:{8=A^/X#u6ʯ/Ž KHg+)P`"ps K5iʑK8fyD6t䞞^ƸP.b{[7̠vQ0Vt_҆qok*-)C&o\_m"y|ue3bcc#,ѿ-00TeȔyJvNM'j;+" uJ+7{T4%$,Z>C4(K8`c降 k3N Mx#ߣ)kOϚ}.9Ԟaoj#`MS||׎rlKDbz5 A`Կu$ŷT-w&*gqr2 >ǓDt%Ǫ1m׌Zm 6EEG?nL(4V &! F73F wlg:Mv$)wQ]X%ZNҐ64[ux{Z!{o*?F:I_"C9'S[_^uczƚ$1YU VX'lA*G+8vu^|Aڨ7kUqړDc~󄋁(VNbˣ!ab&`o#];U[?:\ʝͬ-~Or!mvUkjV,beD2]D,ڶs/ )LC!v\ٌ˗^:RpBQu9`1&dt(!Fy$J6ΒBD)0-;FdhVXшꔓ4V_MWQ0‘?r`rg RC?P3 p- m^x! /F:Qr.ecWbxk648: nqg4+d+t@_Dy?Yߣc_ )- _}2K{Yƨ[گ2?||*,sN0rO?ܿ-C[#5p(9W0;, u<TPO8im Wi2(8fw i&}-eYz.WiB!p4{Gh$Y/>T:Tz8r/|Ӕ-ǎ-/d2M#36qz=W>]%l e;Jq/`Bg^i9cL;Y#䤍9ʰQ>|_|Q>}æM8ֶr "߇؃˩cǩC2⼀@GCӄ/kz3gƅ?qi .ً?;3M 6$'XHX)И bJ+BNfd"I=#mؒvTЗlksyY_qqx5^xF= 4x.Rgp`ؤ!sXXS-c?*Ei`.dW/JVՐ&"$#tׄo@$S"9q &N\eQ^e~]E<<'cUZƥ aCM+t4,u _iC~3C*_2Ag?,h/|s?|~NẾ?yp{y e嵍"=ym2(WGWuڏ6<8locyZk4-v\?6iƽLǔmG& Bb9e!w|CkH[e֭V/7s;LYvq{^@|}0ڞdSz-:{ƭe ;U(*4^v':*kMtə׻{oNl3eێ`+d_Xi~ׅÍ.fZ~cSn[wTFMKuN!-:%]VMH`Y?uc{p2*kCȤ'v]t\OԅXCVf"K'=L+de{0  V֧Q5I^nx䕬E N%/b-:Б秐;zIB& s~©sqE6RU&YC_] ]=&gp{zg{7q+4,33_K0w# \{t$d9MTRٮ)Oj L/ΚB݌$?6gc=nz5lHa* .K0ɂBP!q9v3ʝya2v7|9ZXXL_䫺ccg]'eO̱,{3#88GDMCfuxlGW;LFڨJ#u>,,![xS- Z2yzdNfxLB zN':`b<:1\ٍۜ-R4l|tJTZS>WuXӮNuqbPhmz:H[dUxj&HzI3ap+? .-p;Y'á t4;,s9MԪyfW9lݮ1?)Ú{D0=8\yW.~xxnp@vc`xn2 o6153/aL}^$xcLx،tۦ4'MFgŖL߱V Zn Y, ,3va Ieo`scw Ra WAI񂌋,LZ (ؖ)b*)Dg"H Bӎ 7yDcJ fi)gtd[Ll a!S}Ү1C#slo 00 ;\d/n <+SW y~cd_'tR\Ҥ_260 dRʢ8q?~:Pd*F)nf)j^2bu JO/P,S\Inمʋ(49knN=x^ (S{/v9_!O|w̭Ys!4^a@r {t;C:hНİ2㾥i^ 3k8Tyl:<xӈC ,F}!Bx>!ܢ= 8dFX5i3g-X+2Ҭ 悻:k &Wv#Suə2IM:*]DUa}葟+{_Jo?Op|y,|tϾEJOvZv#EJ oN6'0s%,M._ K$ }+5J?sæې}OmcfzlݱwTuqr?9 2$w'\|v7"[aRǐA2z뾭%LJ80S81dOkG0:& :?±(e<{rJ?{KdRcyXҗsccw\̚ XK@@:׍x>bmGs\Li+䢏5a>r]@aUq@*΋A "RB,X qLX|LIܒxo%϶%f:1@e[ ͱ-KjLe dT^8~xܳe:v3@Nq*=Ϳ+WN|7߃z$43 Lz'2?vZ.eܳ==vcYoNי+g,ǜ1v G0wX]T8ۚg&c00#` } ( gN#|}׭A΁u>/>Y1JΏ{8Eg^>T^~8 ޽|Kq$ڜ_ " /?K0֞P}:ufo-49t(7A5ĀYX^ X29=CyY={{t̃$NTx:+-M NuyմLBt^:p%~z9,ՑZeT{$*vA|PMo/.Z"|ػD\KBUԟ*2#1(YVsy ?Ĕ)wޫ=LbCt F|,OoWd~B.fF^;^:L AIm>L@ ' :?.m!V( >&(-7C^GNjnUSZ-PA?*H6 x`qfcg9sr=7籺A]."1h٩:;O[9]Չd7($rF40ٞe0bO~^,e]IrlU]9[U{^G&GWjVս}sgN|Sk#gfTqOgM0Ư!"+L30Lm۰~V#*a l'Ly(a`F짯K;23i U H޷UoO> 8~ge@@eT!2qkٳTrN.MR~:c!mnlW+1 ˟ҭ$r%ʤt cʷ.Z$8gS;s?>;ӟWbfV+}O!tL [;>_a?e"'z0Jq_T=*j;k#X46es[Ҋ|e XH!j*d tnO3*+mãqRE5 x[Nq 6z2d¯NcieE\y%/ߋEH`v_:@AaE-|LuFo$NB8smp1f= OdC:%j&~Rafy_ǐk ]íI UP Bc}QVJ^iM]5M[裴uT&{ D}P4 %3 Tת,a@B+: pPryA@ag4S=3T!7N[يˬkϪ#ٿ55whG.U$ IY*48N>w[^QM/|ϱ/9fοPD|;7 6[:oj7a=c~2dxe[e7u`mOF%tCo*t k;7w ?kl>  oGWx;YyY#їSXe+ޭ 9 ؀dvQ+ǩq&>#m7Ihä xgM8: edMqӳ nSǂ8/,6G{y3cY$q{d X ,V{M1ītɮ"5Ë^,n8ŷ[xOy7|uE4 {]z 'V"2O\}2ƇMN3"Ƒyp1kK slAG[Ҏ ^{@flUn:t{%lG_ 3VuU(_ E6(I |QGRV[[8 QYZE b3ף*`ǧl 2RX40.@lxVVɏ|Z*/D9O C&jHd]jlkL6@d֠HM7H±?Fu/SJp-r;z֠SWYiW+[pwV*pTAץݴB'4C Й뀵Gfl}v- B*fNv)P/?|Vn8@r=ϗפ\'[$"uvsi/atvqM%IѬ\ǬK >F;Z*OR3/tW8be^97ck'Ff,Q6dnl[jܠ]>1 @c![B~E7r\kY={4c]͵Lcgyrˤlg [ '8Bћ&5StRI@P0v*]ԂM'[q7!8_kQ3B>s {yf-TLi >v;&u#hF_M(_L`7lg{kHc-T?UM0r?u&}*[m&`} !#W,7]O:M|0,ZAc$0gDLz=C+MrL@-ڑҷ4+ >.lbm+ׁ{-FvCIz J 8S^vkCP$LQVp~%!e,:K8VVȀ8O>!o!{a|aM}(B"H#DfPV87. "gQ6>riJb4D2[xbR.ց: K u3G|ʔQVG܅Җw|E y|P|tG!~c-Sq:Ah:u,4^ü YQ:C8G+/tɠ|Qę+2+]L2aEOW^MeRA}7҅ǯPXr=]>qVw\g=}%|t5YuI 6Wo{2΀cFVO>9|.|-|\K&yN#D0+C(6 l ~֢4y̵U/L :3d!~y6kd&cdtf؏{_'˞A>*Wa nxZ]=OڅϦ/|,;ZAWq;72a|$]?Kپʫ2-7^'45ti0xV'|hz h ޙHYq|Tumkiriҳ~C+s< Kkx!Zה7H 3iWC*-;3r87LN# zyT3r5x%l[?s%@a@IDAT*ҩϦ3,UQ찋50C~[$%܍d'٧_#IKc洛79Α4˩$]x |H+bQtS3rR`ěߠ"t/ӗӊRe$罽O(>lMy4plx%-YP{ykMҘs=OI6}< 7򹣝47nZ1rICW0 A0{?ͽTw6Xۼs>GA5-̌7jwSsO=.| ̠^N]zNKMCi/8mӲ-}{aHK'.=)1L&tTŏrts0/&M#QrΤ2@}[iw5dPc#ϤӗKeۜoK3$LxsmI&W}9p>,> A勩Ae_԰fjF?[8TK+_FF寧(7 X򭴼8 8e ζCt 5z|eyi?s ,?3ms{#(V1 (nI$RZ&ySm7%h(Q 7W(![NScwC'no?OwQ& \G@ $wсobjmfcl碂x)I}7_3J#$yj0U7u-tK=R=XYUI}S^on}CO8Fua;FU* IV:7!g7"Πj;CTVGSדkp+*#;bYźCp@6 8үڤ 5oo ;JA>J~ ձ_1>4qp@E5AL꠾|qjdנhV؂`Aε+ 6#~jo?%ѥ ` ι&+ĮB4s;b|2V𻶡A}k~Cߡ02eM"/ɴ>쪠._:%;S0):8O) n<6vn$,o1Iki/,-Q4G5}iiܩIrӽ5pR`u]Bq]}^dvvj'KQ[(!~HpݗΪ:4|-SHɂNazF 7k]t- ;33Y`qQ_4M a/mjh̄?4&wvK%:j7mn '|?Q=m;{Rv ϵ -uBzv,dFZMb#gkYG:I]d%QF 7>0I4p7H$wv? ΐ'X:R sƧJ}HdclтâyZ  {"cAy.{n[5y*E1rt?u53)a'yqv %瓭wdp+rd" &#4C [g0MKfeS*i:J F<35lvA֎'˗`0CQ5Dۯ %ך^ˬ_Aq2OO߿mHgtBUBDVSy |P%,G܍HlC(xn֦0Cg*-Q1uXٶKƛ٢*dr! ZTޕ+d0q2ѬA8֚I$pI$b^/=!kYY% T O S?1?Qf ;*s( WH%۞轏6NhN~*~:klYf "&Y)|Nh8J^zpBf'p҅b :; "~ j/Jk??ҳ=Gg;_忉'#Zr,`efhs_CPFFE%t>Eļ'~qBb(a _x\'Z{[P 31 ..H4iHgAv1APxs ͅy~P[/^86ib|,`,4+?f Ȓ܎ii11;g>gwOpG=t"˯Ml097aQx>Ac&T rrpHeA+H9!M<|,mh@\ ]evP {zm*t'_zbC}2c1[PU 93Rrv[j.c:vt>$qI< sfT=42J"z3hn~:Z{o"{ޛ?Q86ş5*'nv7pS!\_V-,.Nln,RxzéM:9o8 Ckt)#[H‘YRK—%J$4V xXUcPhq2ܺT"\0z:&7{~kUUޫ`\(i+)-(5Io5Z4@Ow^F \>}>U^{*UxIsk=]~Rd6s n."p'XTC9 СxlO5ᕍWZ޹Okth)Aưy "#{ \d;՛G_"$Y$o;l 84 j Kk33x8\g(@ Q9ZN+ $<`ی!+RW[=4A&tc#ʹ^*Бs\k~_AP׀ZK5$cۀ#Eew[LX:*/ /N05n^f׵) &+kj[oOJ|tOСRNX%ol^dBm}YoIMؓz&Y›s8Kit-A3su4vVWzNE~sY_/ LN8?~MO QI׷]ANЮvl& @2یV˿v.ԮބgU JHM}.OKu\+(9\5Y ֦q&=/dv(֗`w,^X&讓 7pD{~2s6)^@ǽ ~`/ t(0нr>p<ag󺻺 1KBi8\T܌otu,ud P%QeD0>nalF/!w @fڹnq&+!<4Vɠw=YVKͣ#6!@V8LX?J8oN LmgX/[z|2VC I/*֪U*N2s#[aЫ NΘw*>tj2Be)^G|أ#|HP( X23gfH`Lr㺎`=_:U@URh?w6`;ȘP8 ƔIq>7  exTF7b0j( -bJ4XF^'V"m!-Yʯ2^gN.\,*Gu͵JҾ{ ,#e]g CY0ۋ5\g!qqo\@)YFԯ„/ln6pKJF Zp}@R|d8nFa{gҧ>q~T@[k@RCJYvY5.кF xՔE:|w2ٍI]xX#Hߕi*[q@'8#~}} GRE벵*5梇\sWn"KpQW/\^4ZIAf$KL ' vRgwfn_KvY ]C`Kr;|$s/3=NYU*Om 辔lf' _>o5d o@ Y\wCVhotV(w*h%IO\z:]Si9:o G;i%h "IЊs8s =P &p d[ zVE ,Ms bq{4mt! if|HKih؅xfG͹h"o:aٚs'c,ݳԅ28= ҄{OP?wJB?WB6gNOЍ:N3! %ΉW#8Ԕ<]x+"t{.p]{6!og\Kq$ܟ-lYRst>?`ୂSW˰0QzXnP!ȡR5>q@{ԳϦ~s t$T-..Cš#j!x.]y*`S{Y_[ʏGgp["U?IY/jԚh^ERzn|_A?lsN@lAڸtoG8m}me(R_o;ɴ g-pγ -$6y% +˛8c|D T$\k@9wŵkSV@og?*Q]wgyˏ[gb0ڏë6\A:Ri,`t1իTg^(2 _RC{7v 0 ֭ci7u4tE'@!5WWH׾AL <gu1olʐE| _'nD@WƵז{S½J˩bk+=ZA}&pYZ:*~9ReOJ?_3"[TCϰx'-~-[! -~ QZ}[i /ujt-x8 svnTVow SOMžL,ߡ}D "iqAktn;6'{oxHە_4@5TP[FΔ6q=ߌ@3^sq]$6ҵFOp7sf3`6MVQ7v 4FUzww5h?~xp l\cnp[Jc ܱem-  >Wm|1:NXg-OpQ-$8wCMSX~oųUpŪ>\LI1ȣNVSSiiy`eФڃ>gu0S Rt|a-yc4!&1/ a-EhuAbmw sj ]3kwuZ&Hڠ ҙ]>F $f$z l8SWթc)BOzbŠnv#2T{䌵[b̫i{4bⷺ, d^Xm'np&x/Dcc m}Yf"iEu`"sD$NH4}Ҷ/mn݉ )`߭gVް-4[ P=]§u?-dS>8"~5lykV 3-Xccvguӱ]Q' [`$/j'}KDr=:Ci'LRrUh2%VS W!Wܻv؆] b"2Hvo8* \ ?Q5o;vڅO)"S$mTakOh_J&0KG*$)3V;uϗ/ٵ+ߖ熯 >u:]*=)7)yd'ba צ?W믾dw}\UȖc(8Dĉ~(vU,LAF>W(4®30\Cz*dx ɇK)")AA htt !2&Wb^#aVɚ)䢲*̀flJٌ%  2}Dpn@haHLFvkpp EF*16(%%K߻{;ݻNZ!sA8>U ΂p ~P|tGM!}i8cB_?KHy啟f 7[ Ơ^00` ar"sי%d%9ӒkeRҸ1msmϺJ k׮GϹ}cT~Ao_;R! KR56҇]%w*L=ƒv8#9#%c bmCuIbV jr\ _ϸ&h㛟;U5(TK&GyK>S_aD5K-e_G@@!Z4 N/1C 5lPiQ |Fjdc 7p8u@_/c"c%t =G{ts}7֬j`VagϞK;2z Z12c`)h]7F )#wubw7]xKl0 ֥~o%aOteo7b- :/R#=ϋkyIYU V$`4L?s ܻG >WV"?9&O`fq3~j"ڠ q pc}p9 ,>'  ']oנqA>~5Aw}v8Yt.h$Cs'yڌ g!m0Ԭ\5`+\p2LMEA-#9gNgFΥǮ>H~TDA~^,5 m{$y3pH8JgҀNMԞsVS WḰ%C^u\?>8{*C 驏Ϧy*uxQ%ZΉcMFXZ lg[ r u|Y4#MQʡ1q׹nV[HPVyd r[N1AyGI2L6Tº 㝓~ҫa=OV_#ZGm8E PM vЩêG=͗xx\v:Uْ2GVa2q5C76V&HGnJUIc:XL4x~P'q_P\ '%ҖxhusU*f- .//UFnz/ݿ{7u8Rõ@ S7 U&+@K8xw Cl~#O?y `UMSi-ëT#gN:> Npir@@&m5p޹GbG:L5gY*.8?[,ͧ~ BU5>EhZB^cF:;< w# PU# SY}鉧? e3Fu%T O^}:]y9a^zx6a; VK7Shn%9A>37:H`[DA4= s =Tok: {I>=$OMkq&(*3S8o>>J-G۴őNz#s9˜7! 2Kz $x/t4\SN&_/aҴU5O^A7B*+[M7(xL20te^|eUcݭiArHj:mXW'^60m%|Tv&Hc.t1Zuß'ތs73'YwMjj0m~M8ܡҵLn8lO+ed28-ڱv0}tCvCَRY0đ$ȧ N :B"efz{Va{5`I!-,QJ.|`ùtx^`!6[b@{`{pOR9詽Tr޹ /?\Sgkw%n56r|kuUc$xV7i#q m-4` \X*_WCTnf=̾X/;ct_~{C}M+ YyAή/:f :4y-Ehurn&,pvoE&gC4.]8ѣ!b2|&,H3m4r:L p6IWZ_'ɞgWV2ƚ$t7J3w6 72pU8lD7|TgmV|șxfŢq9WÙOwS7LElcMh6i0m1}!>JNqUV٦Q]c|6X2gmr{6B :=JRPI|ʗxs_BW\t8Ȏt]6ueSvf4A`ρh$Dj|Pڧ-Sa7;qXʬMd /\@3]tVt$*lF)ʥ险o}?m,ZǑq}:uq=*3yޣ#}@@LSeUδ3c$(cNZY.@`z^{⯿Ã$` `&Daߢy8ڏJ2z: Idfn>z'^VfiJ:}GG0!F#MW/C*}d-V0}??"uZ#|2]KskQuxbİ2QjqDYs Yus4\!})(N"r$/_5}_,sD"AѼ3b 2 r^^ZΗ54{2aTGID,F1`$2N=y_0=b~ =)?L B)A!pӀXw-'@J.t7W1LDd=8A '҃vȨVT9pl4dix\,ȊUd}TO5wy`oθB}%#EߪAaeѱ-2!Vd0|Wvil 'O#'")%بA; _^c`=uy&&(YU8" #3}݊Q5z| 9_ k+Ðb>3{!w>:1hiӣZu [5C.-3: g">>3Kx^|>3ܧlQU= l UXddoٱ‹s C2YŶyfXz~:ɱ\e:>2Q\V;B޵gO?Iz{igyQ!SF\!)@^O8i8„hMYF&7d_vkņ<8!վdCFQ'd]/hCLu`YE)gBfحޜg%PӞ$$L,oU𬹊~e ]ڴ=E]W`gwT2X@:NT;▯ch^~,L]St{k1;jӪhu az/N΍473_ VևYD%NO5hI M~"YcY {kƿњDS#1DBȢm[-ξ}DXq6o˹M,YU_tpMM{0;& wsHKwQ ?Av/ՑW-N*gJ_}b*\x]NuXϥaP-"QE?܄<%P*_X`/%M{ٿA޹N? ۠S k]_bG[C8XUlu ]@k/x{%i9TSvzL*t-_5YVQQgE҅.,}ltڤG..vHz:[{U&=$ nYF +M.c9{>J%1 }"*7-*l `S[D!T;J0S9\d[//o'w2R;gq07@83u;;XUCq`X#ptQ6Ry $f8v n쥶n Yx9in{mpgBz<1YG49?ޢtGv NOO-G[/ T$*o7#Q7E֓taT\vmP[ @e:W' vf1(,hQL 5yMg{JI/]#&935!N޳9VX~P]0=govrX5Nh]p'%,[']y_+ߑ-x&)dyzq ՜H!*68mfz#W KX"|Apa㜇kxF1(|v8=|8a?:6ݾ>*Xcl mDmUXTK$ۜB(f* Yn :U>)~m .)LI"ck_H?`7M8E@9.Is=}&;NH:vF$ЈLT3Q_ܘy ^fkHXi̓Q$&˗.e(:7HYWBwاc\І\V .G_+]qy$7E1Mܕ &ݝJw)R=  37[n:6yWf[q4Jt>hLk t 1ZpNLObQQe /jHAdbf0L߽H$*ػUE# Vhʛl^@riB*aZTT,sdB"0^ 6TH}S0FRS |pA'Cdluga4cL) :~9YRSg4u}j̍{ n@,ȟ/ /~d#QQT2AJyNV)Vg0Qb\.1w2z6CfyiNk0  ,3%B2N]|(|w3ai\&Ye]JYѱOuLr~QhZ#FfM;8T֠ `Dƫ$Mħ2[Y=Iy,{<~! }y*M3-zPP~x}<7jJoϫ>޻~ }dA-qNSX}1tR , k=3S g av, x&3I`'Nno;z #@:mW\hL5-qmoL6`bPDW-8HUz״aYk2mmVWyei/=n0U! e@!,!ǀN!?} D+ 30/U'FAw&:p=26~hjt64T$٧.3XkN}ЛxϋZaBmv9T Z],lf0} fijE"|w؍+##\J8zkٿVGO|u"ofޯ~3k$9VpT$щxIméޜ\I{G^өCtvp$N+w4w_a,16h@ ]T<4`#u=g\@IDAT58ziR6@99::ϮV/lҸCU׌J`LQ+GtD|9Lx+UL$5y˒W6z[B<FۗpGsJ :Ƭ`c3=!\%\OGǵhAk-Z l6-Gnx?&PWb}o_/^ Bgحw&q]7E'bEI\hrugoiϼC5%pv N.????W<nz_xџ#WA`';4Ќ|jkH?贙U7 =V]tWD@* }ܭQՊXA !^p Uwhe̵Vw1 ^Woy h+mwM#?"jk: mᘩWN>'ZSȔ-]?N28ЃU`L%c l믾M{X͵5E__IXUV*zmBiG|07qCt.tUTuvemSjཝ2=7֗D"x@0|~YŚqolGL'ە{RcY[L ng);JS|hSioe:Q}ǻ*3cE>(-Ƞ;Yj[:hg`˓a[l{Jr$ %,h'a*1]`h^>_u޾z#& ֩aK{܀ek uzt٩EYCb;M8vuٛ#Gg} Mo[/v?:U9`)Hd7^+ߩe?eU0 QVܥW;(i ,OAg"PoW+x "QI<&;@* b^@['lx64B#77wxE< G8TJW5golDb;|v#:"{>U5P3DzD <@G,Y'qfgc@G$u m5$?;{Δ(:y] R ;|Jţ2&y%@oVu頒vV7B%E?jtW8n\(A~5NO&ٹ*jtྸFbJS7\=.og",^O$dkт A@delaCkhơ- 9#?,oÒrEeu:.Otm枫;˛Ѓ>gV8Ų!ރa8“*]NS1/B$omSlPwᵵ}|ǀfa^,Ó$4?~Օ2$!vU8bSSs%*۝x&pnӎe0kB:Q9`f2.?t `B2nawƊ;1xs~+ t_4O\ /rDjp3l>Xٮ07S窌0Y8Q,Θ&Onq]ur;Y%9$]Ցmd*>:<(2H7`S 'I">u4> >^U$8E\v,b;cޏf!loG;y&v:+SLV:z2((]|O1~bejmJJ Y" HR^m+ Wy)bH_!9=V%L"cG/;ߓvfqHGIڶWL# yc̅K+u3F5&&F P97zOşh(mZIc͂Bdh01@ OTi#_:`2:0eմ:]@鬑Pd}<*2quyZ:8!f)ճ@ uVJ>>Ĵ;}jхXcGw?2CCiAovvȠIq3ɐx2bIiCQOGi dЎZ&4 I P`3\'שFF8]$y2_ᅬ8J:t'L8-%ZQew]S~MMP \5CpB!}[AwCY}@N|w"|jt+ӧO?'_$^޾~?JϾt6HsvdwkUcpp2`7څ;CP,\FߥEesC`9{t9ƘZN\I[WT&u~ݯz F8^|6ԗ׃2MsSCm٣|0T~'g"H8iS}|}DՀkaϧ?r8v쑕%ZR_~ Š r8'jQ8+|c|nf|~:#Lwܡ/W&pTsepQo+ :In#yC), h o~cKWO73Zށ:ś, ڇ7AMFS1Nt 2SFF[V2rZg"H 'x *:] oӭQ_aÊ38#^e mT(ҏ x'!+tDUr: \TYw]{T/ڝ{"&[Y}M}5t8@AKfAG|.7[s33ug8%h%n ry8̴eYL.|';xv> <޹F҇'hwT@[|#XӱRљ5xgg\/D5\ãނϻ3[֓}.x|#髮6Tc{1mqnrŭ.-T4_.kITb#1Tۙ٨NsG5k:VFdVD[׶ bﰯXKQFBCteڄ^WZI*oϢ=tWmgfgڎTAxn5:U/VE_FbCu4Z?\b0:sFU0&x6`TC┉q֮5;,ktc8FS轅x:6:UO)kN[3:0/wcT5Ϥս=pDmQqdl췼!ԯH5.v8>^HUB >Dv6yƸvݖKVJ[gZy.>cs@Yh{>Dxr$H3 nV2N}lVGq} ?FXGPXZ#1v Vm 6FvBȋ|[gj}|8+>`i)d ְ OPY=])SS}nfC̱@12k@g,2@>}m \7mG 1$&t? 8F䈉uQHPok^thMj _ G#&Yi.<;qXT#]\΄ڴJ2`Y2S B܄,+ӃX[.vRp_rt |P>߅ f<Ϊ԰zwwMhV@;+t.-ܡ)o{ody}}{ݷ}Y03ID+(Ɋ$+$v*T?S)H~\J%.T\%ʶ04E2$A v̾uOyϴ) fs-^-A>z=*Y^V$"20&"͖~-? ҵ(LS&&(J]@'=-$/Y"2 o0FR^14sG7兾6=#@ids &qyEse"¯cA9< 5JR5+0Y'"!}v鴱AzW$(a;q{l{qKPc0tuT]X 'PE8oZS%: Ư{&  QBmd.5q<縉r4ԉaL .>L ~M,so44;?FYy}]UfZլFJQs}-!}/`إT4p.Bi@/*/*PA] bPr|RJfﮃG!!Tl :pwuiX@#|lDFnݸA3+n ~wYtszs#|R.̿D> -(}p'Fo77ʞpep :263HHpG/;P/^fC.-YS9P';_(| 1H>sِ1E".JMDY>xjj*"+0>6g0O `dV&HCsө%*G@r-q7w5츟Q Bf*2*o:AG*d3 sU| 8ssw _^]b0F3@'CY($=cآ6C7?=1J8u!~3:O̔38x}<380n~)Ek@1Us *5piV.]&dѱr*=SKY`){cTA)Bzӏ'?gO r+L{Ò#/3r *lq쑼^Zm³7{̯(x4fzxa&[Ekd.`Ͻ J|{NY+*x! ]GJ!,j8<.L"X i39ܹHEip.ju0s!cMudmFs 29|,0naݾ?;!3 b'9;Z V@V |0e|c㭔Sm(7p>C~霎?D:68LVj;iH}ҳ_r=!2|X#W?ߤQV^ԁ:>3lϟ={;cEq\091/4NB|u>sʁՙ&m7kkЏ Ё-JVS%x=|U87c{ BZ_!B滸^8[5G Nn5ךhJV|7C|4w[wț_0 E$|AzpHS S0cl"KdN@u cY:+*Zx* d+CjFuzyfh:(͹2U7+leLYyytB 8C-/ϓ8wK98q qʑORR_Bi:ov@j~GFX 8`vQX%qwx@cwXQ2 '9ӊŒfdqkS"5;E2}&Zg|eqVRbYZ{$"7:8E2s 8('a=ྊ\N8sh҂MIj<sÜJ K3ڔ+ S@;D 9"08I&xPVV{E΋r,X,q:`BNcNڈKx/Lf{Rji8}iaeVq#;I G>S.| *֑qz570< ^VWf3ﴧm+u8:nH<,27#| Oe#S5 };|^ԙYztdRjnMs!uwxnQA&ǎMY]>l%L Lg#pU1u6eQncl2 ^dZ9 ˄nG~r 'dZ*4Z) 1^(w'!t"+Τ2^z7+-tޮi*?) cV8GOgΞ>V<&N {T/4Ҏi!L͵`zÞ{q:e owEn .A|I6z J)pܢ o y=b[scHUUjZ)/sRv}. |6f; 2"~(iL-N}& | VvGV-)Uaа"`_1fathpkYj5 `D6*lt!\MֵyCڤ-@W珁a᳁.UA?4xOEk%XGЕU8Qd΅;i95z<ĹX`3< 4=.A VYe}=;@5 |^X,9.Cv# mγ2^9m` s .v+iTTgr7*ŽH&PMs:[>]S-X/J$c7 A"""&A.fdB2 '!o0޴C^!2 5;;8a8i/] W׬0@ 5`Z&Nx∀UB:"8~Jf j$m^VJ= jC8T9$T Ew638|=@h߇W^N]ݼ lDΛ$w;uBK-  o`fy*p\ rS-F+sk0K2WŁ`F,iS$A"Y#$s PMs0ej C;mBсC*˃$l>\0q1%Z[4=1Ef /SdhF`!@$guv)UaD 5srfwB|VW0LQQwkXShPс0?K\Ώ l8FU`?I!< :`iX‘|/rpQh\:%^w^,fF^yԏV9¯B0/we9?ӱn)O\WgY.9|°d> c<1FqQh/4A|6w't+cRi*I?xwb,)Gv5rYO{)ۚ4ƙ= tiV6SYZkV V٘;+Zfg:Cu&"# 'W0XX68X};,?;#`'dl^G Fw';_b:ɕMȨ]E=񤍶BRWq/P71fG:Ǽ4N${'CxfٮpC`4e}=8/ϰ$ZH6ʟsq _?9Qܼ;,AGuliA~"n<5UILs: cDeH~,GWe?:%+o^]_ a\AT/?|ggnoI㊷9$) `sx4,;W-e]gT贰J5-~&ǹDi}/ çFobdEAۈad43dcO4?& X>!qFgLLg盝?%^#x:gh?|E+sqv] k@!f0EiztIZ\)' n$4[ʉ~'_SIxg,p ߕn>c1d;p{pxtH\@8ߣ]0"e)eG % tFh_0K=*#m :mN{NS1{,=p{ }q|IN>B2B.`q: K9o8:M_pz${ns/~y{<48vw=|ksqekҥŧ 6Nuk~X1k.eslg6[B#nz8 xCmOa?:#9u.\ge1?oF>bF\ށ<{awi3Wa/gkr7qIX?B`ߘb6;g>9mrYkq2fjk2 Tޱ _gfNzǎ9v;fmV udgzly#m| wnp;΃3?󍟏ps,w5{fg"!󬙽t3 9BZ52FȘ~xU&$2CwaA*u,KY0Lr`UĀ2:Ϸ8<@m<P@w9NNW-:)NBYŶHw[al?k>` ɞg}L2PXѸAe*L;صеIV6{ũ:Axhh2x!C3qIJ3؀Z@J/ԩ̦!itmC tD8:d)wFp:rh0M2]n* jgݮfᬓ6R1Dg+t-SާoYXBCu7-VrYt~NTa9K[) $uDVYfOfh/RD'aZR5]\J_H8!ԠCe7{y7GYʽ+tg묟%q fnΐD[V2NUy3SO]HnI_|2e[I|%+H ;wU䉦;sJp|xf=f({ V[$}&*soYi7Xa·f X_I3hoE>#rpr'.j9#=ԇЩS!g/؅P0|{;#@0A7ֶHR%*Ù1  ~fiP!*J!| 9JZ5E]%Dt_a T¿2A0f1q3cf{׽x$փ|0ɟ'M -QfqlX i<:Ai%S2HD~'1O{ e0pJ{D[FbH@=Y.$BYY GJ@3O҄FC1*S\ykJ8JV©O3, Є]yJ#f0yTĥ9KWvV)k?AKF7֨&ggܺ}P ,Z`VeHYtH=0+S QUDž pG,P2 ЅK^JVykFzs=duVj@ WJi"v 7ȽεiL po+8~ T-C2RѠ#fKBpFLrֺL QPҰ.MSaf` `FT$k)doȸ`N8# Mj\ eAel%L!@4  Ot( }og["\7ԉf7O~za/ί믿f<`9`8HO 5(ЦC<`x{ }e3#:8s>a0(̸(mmSS+]Quš?kLL }B7Ө\rw2-0{`:9v 0`h͓_>&fn~j0f#Yk:YAe9Ng'mqKX/AԲ1&2mAC^ LyA?B.Cgϸ@aC)5f | r_B㤆__̪X4 ʡcK8KVᾚʵiCN13CN{e3|o<8Oaf}V=Xes p1f6K=`a#'>ܒvSpa1p^f vcKzmmmo=/ޘUGiE>^a5@#Ș2{_{-My~ /O[WgHS頋zjʔjo%iq 2tЅAԬ݋YKBp|߭p,8%EUerxe#+#ȿf1%l_mfPGUx<'][]&_f!3cX^s:U3>%r=A^ӀՀQP&1Y+{ww&v>Dq;6U? ;Q"qXGX}ȕy[Kuʋ]T:9pQ~.Б8o8Hvp\֨S,L-·}y09y$N3` ;aO^|9\ '~. $FneEM~aa6Zl^=r`5*י8WXr^,p38C#?y^=EyNs1;e{?Oy.GT>#Ў͍=QN9|>ָ! ,'<͍1|#.d;g:-0GˠQev8wg>\WVle[J9y, ctӂL L,F&+G'Cӿ"{7 }E BK7{8xl ֠WOF&} ]%`NҎ NhQԡA\sQɿ9XUȞbٔȖOTi2x-Dl`ЁsA&υL>NeT[l||e%p{ZiG#Ǿ],aꗶB-֠C9p7a-8[IV"hoP@W] p!t>tmU`2Ւl*IT22{_4,-2Gn#'ORe D.9^_op$KҮ 1@!D:Cc~VȬzbb{Y07ѫ?ua[+0JD38bl Ph F6v Й.p J  Dٲ 7boe_4NH}͍LI(ɳJ~w "%!X#:1\%.~+F k;>;޿v@Xc p2Q#"n!(4$b) Kr PWSULK `  YdBg% Q35I*E:`YA̩gt[:TI3i{4LS >&n‹y;юa$8.T/m0Y ,/8Bi k8,4l0gn+oU&rRzӈ #+^H*ہ#$NP21~'=ē`UIiIiNeATCe u#xZ &ydEW_M/ЖAEqѕSO`ʣ$ g}dlQ Zr,m&6a9PdciȆA@'xMYǛ#g$h4UWEΥ|e d J^kw2Z6yBqīQ]4Q?(;(SWdoiU0J%~ƀ亽4J>S0uiJ۩Fe(澱VA[CY־\Hb1j+e&4+ Ӣkֶ0*e3OՀ渏NXAw܂^E{#LZV%7 i >ӷru/<_뿚>M=v~=MxʕQaGܐn.h`wMnBFWլ#OYw4$q-?:g,Ey ˠRnTA 9;yX9:폋HyqH@IDATwCw,U1<>jdjziyY0#G~De"۟q38}Kf\|eZg7iF hKlQwIUw__sꭙaL@ UVq̝459.صڻOޢe*,yaxVX7ΨdY`01^J(nT@s,XckgD~X!?'>Af\{T 7flP%uCW[>(?r__5Ρm4G+u5SV逗t;WyaK]q Yf^| MIR`<1ypɴ./1Ѻ |c3Ɩrr| xB6=r2٫ \X%~wU~ y0_0Rm"e,ErM8yP$!8eE85>+zŞUuf9hy*Mj[D$ )cE`p#,,xS'30<`%eߩϫbg$?lE쁓U^JWC%9>_ u['CyEY!;s=.^ND7I3M]m"py79=6rq['O Gtyf 4>:O__;maT:}DziS[rD?Ѐ9ZP<tD4RcpR|8(H&oqs g" tf'YMj7snO=-ɧ[F .N1`m|H7.v59>}7|pvf{/뫱>6pqs XpEZB64Y"YRFiB=١T3P{[M2JZ^@ϡ9iJKzft %t0#^2ǃN$dVI46 1E ⱺ4@Y1CU ̼(=6!>vA*3/Vwqs0H[O[7Sڬ.ooA f/:?;;r"kivsTvn -)ZB47TA V{*NZ6kWӕdmߕ?>y?tܩ'ùge2}A8ҷH& ;&In# ڬNH/]6+-c@g+~D/a&. io{=q%;Y+ l _Kp=ITϑY39W1\I8QPM\x@c}ww(7/ں(4ؿ}qS@QM}ε \vdsuYuz##ʓ ȃ `.TuO2@i86wq 艾<2U+*+%Jh aзQZc)§hIyh _ J;|/Go*"RC! O-ukv6?9AfM^B(@&"z`R/{DPe~ȁ@!Hb `o,8FBgOU!Tk]Lad}?@5_B%Kye'ϥz<36٩ؗpZ#K/\l'}#ܻ>;{q!z ,B6Kɒ-AYG>0   DrהCTj66*2 B̌,dX>h8L9FSaDj55>>M@eY>e!9{3Ƞͥb0h44H;@5_zO?R+ߴ@d("\Ef]aZr4}$(wFVTZB^`K ԈWS:D?ݛ:)~A+91<m’J@B VOfl2 )kD^q!AyW#u>硱F\E zO~%jOOo0uC1SQ5Dj9D r|.W@7hjtt4=`>_};dKd1 wU/2.89p|$=O?W<&Goss!)?KD9sν46z c0=+ |»Y$ZlO?LX7ȵfyl w m33Dic m 'Ә2->JSo#2*{i*,y쯎-Kw,33ggKv3Csr(wR [8̨ނh -1Ht7r ӈ6g95i`0$2uIrk׹:mi 2G(v|3:߮9ivmMdVOœ=̔3'a$Cy C.d`k,,QdU4 _^4O[}O8})5u]=ōkiexS'M2{Ho;zmOԣj@),P® Bs(' 5Rx6j2Ӿ@P%[A5_-aLv×pq{8 +,4}NFöÕ"{ L,> rsg}يWI8WYi Ќ`׌'4SFNwwTGĸ޺3"/BO}޳^ٙ9 D iL u1$0|u6tF4SS&W!*#wl70&sYkd1--)^!tvCg B(h8؃ aQbdK44(@×jPGuZTI 1;]7BN@>G)dJ't[ɚ~aՃ?'LǏ; gF)~kuQ%!;8c <=s[})S!wJ y0tWWv'iT )7ceGMs``85o5w8ܪLc 8''=n4| 6t#֝&gbxsh_}j=@xM2چ!tIәn[>eI]=m1*e>[öq\J3 D ս.r-S!L1M:fIGVcQ#m*[٬Щ?[ѩv/SA:ښ <_oA6""?֡|S=cA4cnS.Fd ,AizAtp708ao&(0fAdEyW>u\> ĻČtG4֖thUAZp4F8jW]G~4TGZEzIbر0ʿv:8c}ښNb&HhGJ~ HR8t2TB^+/ xT3.]x|ZH)k|r@CȽ8KΟQϼəu kk]#m7ס iӾR -.k_Aڦ}gq _#yp{Qݍ9Zp[+8F] a8|sr6ũN u e`=F/(˜9Z|WBU*P{^ƶ{SM>~k{T#cOS8y裡f-3Q/q b"zTqH\[ÞU 9-f)g<83 \߳.,\:aYe  6\g:#Y gf}# YE-=PLoDˏIE86甗MRn-mdžScww$ ,EdT$ɩ$ģ=s22U,9u2I};B8 i}#ܚK/t%ƨc{א5*SЦH);0ЗT#{[ ֱoy{`O(P^ɧ+̜[ĠJ)J I_}!Z%f&5SrcC̡@C _{E"v1aRCo<4M#""e)G?umyrJIK;YUOa;ͲnTU&"Rk 0ыfUa[OghHQ޸)cNՈV KL~ +(u4Oׯ1'b]Z'YryeKl+v b~-ʞ;WHq^M,^YiK蟝%qt9,^ Pq˂9 bD=!. v/3C{ewQrZo|T=0^75JAg|cVJwէn 8|qnRCQB!]_ʘoeQ  .x@qhYdt m73K9J|97X^mQ?Gh@=wUU(ݾA Cy -R/kD;OcX^p%hOl?Zezg9#OV̙|g,ˌ9ra+9EK`B`8 :.8M[L bf*:ᱱ E1+aIa%>ʰN`3vRNJ >`C* e7ƙ.M\.LLu1Gl;0 ope4̸01>Ϝ(c* ##E<-̅Uo^-{!vC{ ibu-a7 `)IS{+ҿ\4d|D>N5[V aџo'φÁdZX&q3+;O]wv ǡS~-K0/ 7vпgVQ|b aqYivvZ_lH FTbg, TV c1M!ʹZ4L{@m nm-3^s="3<>< Z;uJ㵶cXٙ awAg/F(uįXk4*.k8>۬θ Cko<1yy9օk7qܶ@TVA;YAjJ#dV"}S1B 2vȑahz xeE}=?u2汈ʟq-!+ԑ*]S(ukV,Vż!{I65L̓˜4<&Cgr sohZHegMM5A;{zޅZo^bJ>@{w8MKN[YX{A]BKjrǠI{U # .ȜZ)ݳCz>gWF|9E: f9Z[eGy6)URy;6&3]z5s/ >,ږpT+6@V)V=X&E]Yݠ97N_-xǴ6^JL4P-ZH* TW64Md$hp lG5 amUjud9SW5ȧ56gQ*PR Zrx@!sPxRq2elfXy k᝕ȘdV:1:! 6ك=E/ |p)#K͸/4X\WD'^ˁ[I̞cWO 4!+m $``!7o,mDdF"Ebs,D/8hp<x^x㬬 \C PWoVt>jO2W-`ouS+rp܏ zՓ)8sbK4:d}O>:>6Up{e{ x{1:6&@M*{Bڨ8F`VʍWfb ]Cԋ-^^k )x6Ј&| }&BKԧ3q,~)eZ؍וΝ?>ԓi?۠ս4^I] :}ÌuV$ z%IŹT&/˗ng74QLz#ǑDƧk;o٨/g_Og>u'GRoJq=NܑHBj#Y=K-_z57._Xу2p|(LC Q=!o3 WAk6.;r>Jեts_1L2*K+FH97[=a,@0 etTj\T@F:e?KQ p=JjWq J{+Oӷ%Sa^ J2 [ԏ#p!;va;|u'H{93Z{^ SC7\4P[ÉEq;gKaKZEBEBY>8[@c1yY0IF? Q mʵʧV%1 "@͐b?tPFh {sl㈘swu[ᡑLtK,ņÑȜ X~W~[8}(#LFewwo*/?d~=?yB^>dOy v 7ʎ(7$y]dAt;٩/]B(_ߠ9*U1⿒%jÌF0av~8"- |LtE21bo!c 28ut4u!ǰ"UGFvK# c2?$zyu+ilV%Ș%BFE8ƘFRF ط0 u,k~z!]rg5ZAC"[[g 2=C9i^1wq8 L630IxQ@F]qEp%^WgHx49b&%H1f;jTF԰as±n._1(~/>c&|RvUd.BZ[0Maa^bWu z|8v)ǩ.JU|ilay()G% n߿GSyE:5 `<> juC'^C7􉠙I/2OLлrU8-OF0c0jF֩NǠL{" 35)ll"]<}s Qou'G?]%\2e sC#Y5e=61}Pt<8s3a̽K0n с=5P331As:ݘnp:oa 6Rg}1oƺu{4VyߥTa aV~ʘ]LNL_8o\<Φeqֲ T"X_esɞV[na f22rgl@BQKkG"7^fͿ U{𓎘zΒ;n˯_HkKcZgi|=մ U^.v1Wvgځn3ڲFo@6LgGfW|Wert4dYΕ)o>m[ Xeqv! ]CF_c/#e6+OnRBFҝ.r8=>A&2?rd8bqPo@:7lTeβc,w&)}N 6x:6@+V0GWF #ѝ P1@%o{Llpr;UdqzA"iM85}BPgؓRZ&; B4Cܪ'Ms`I pi0&uW[ kMMO!]x+TVYJ5 5;1he ݟ>O}7{{8"[K[}׶k啅t2<:h*d~*NFe$1WDqS ]T;,P b p/dNk;`k渑;8G4P*I>,P/2iGQ>c+D= ƕi [QUw)GR򬊇[u }ؕt;"؁*h %|y~prz?Ob:qYSVfN?лǘ7<ȑ^ܻ=9 G"@*O"x$ 2 \wN,igV(BgDʱV g>g©¾4ܦ HRNQmI_yYkAUTKDɖqJ8q lV)a=29!O\ :$>!\bs=hZvg3H ξ6d,;p;IB:;3\MGy}\-ñVLPd7RK?>Q 8F@'~RΝR/?aC Wwjc!)Ƽ_ǀ;Hvdq^*K&]BVcH#yx펪)_#[r>r39rй#(L'î@x7߹]*WfSK.\M=f[XwCeg@lű A߬#pAB8mdG*07kIR [pWr<'zOXb}⬟|#pLObZ%N˿ L 8QAdAXB>ck!jS2 wrReR?34AcǪNq |'/?k$Gy<]Cx2<1p?Ǡ'BiVEM8?NyB*VR=_> ±Hu9ᦱ㬉LJdbd4K1d3Ӑo仍%NNYr '8ZnA?\%?Lg<Z6)|l瘆Vf~#Rk60$бPakˁӈ/w= T7T85j(k=r^X9ggCXQB⨤GrO,%JBRt8#F n8JA{Q6Z!:#4% :APxPK{ B'j#bx03+las-x/AüNZdPm9YFNq=28@ (" (ۡ-ߚ ̳ek=z8約c2iVojMGhk4!C6sdq 7 쬭؝:C5UTa/@Ü82;,Q ӭ[\38ŧeKf,sv:\ܤ< Q5^nd8[6\RJkA_Y±kDJ[f*u?|y=$<<8>'--&f\VVɂG|eFsab"\iY\]c{@-[3f'Sϙ; H0A2:t hJCyrGZm+ p+! R?- kgʪ9珎MuW8NEZ1o5{K׋ W^GNISD |A l83GkR!PP{ ڃp&d`аHyȇW:Y,2{n?@W"꜓`8n ӱebYz) ky2Y1-+7 VNT?\ ( ]đЗ2z˹X!7\x0gu }5ap:?we D'|]la33XB46(U3v:IY j)BA6v@څ0ٺA0p{3`d<+H_ ֹ =d ci:d*V7R̄233SZF e:mÖzn@G:mfhII?TkkNYX%! a-KӟJ«>?dkiOSYM=wny#u5«8*geAЗM| JXk5mfW<$V4tw 7//~3PGzQn&:^uI}σK__… 8ռ&Ge hA:k 'y`ޞe^:ZO'`! Htjsω?sK[ڠ8ˑ+I"Bt / 6c2.0pm"iu^+2ÙуjرCj ] a.>T@IDAT*dd1:l+l:G9}(mk~̡%O)Y]|4,O(GX9^d>~W,@ ݂cnĹBopA*+:#~ͭ~"BOoUvKWFy$Ql# `KPFpy>]cA|y/{lVu<]C6RBa/ DA^wD" sD)l J,=Gq#}%:}^Jw 4Rx fq*}] KpF~ -w%|sAbFl`_eߌ b lF ~[9FYR􃏤jtF)N78J._Ht2VMɧ29oBǟuߏ>i=V?Qߜ8;J$N.ʷ !P9Ad |tS1ub2H4TSgۃx*.4<{ O{ow{W`hJfX㱝?2JL28d&(HF5rl5Z D! p 7yA@4^򰻿>S.BdTqi(7rTG@B}-ZVH123AY]8Az ` eBV„Pt]Oݩ7ag x;nhe>'q~K[ *CxB]`'f ?=Tٕ,QE3lb0d> r-(g: -.WJ3*~I! ? @s%y^>K`BnQ>3\EXg}2Y8d6tn,Ћ# ϰ;Ur?oĥl$(X6s*O[?7wM_m!i!1$/b] CA@#.%[Z>tp]*eQF_;ƿ'ƵŁ47c[T-nAjhӠ, l;4V\V㐽225N#Wurz;Ky_v<35"e1mQ ˌ ϋf@8]OS=taj"\3RЩۭay?'aĩd`B#j\atލu8WOX>JL`5!幧6kϬday/|+11L trž_=li k[Pզphjj:hB㰖|ڵɞ*}hpA7BkLEUx{:7yX h O!\fVX.( +,`/#c\JV "_W. a]P@_n[8t;Ǻ`/4]^5x6yT|8TM~^N\9Tį aڻ,U>U:fp#TPLmC/k^T?6)H+"3 }Р?e|<*TV T, p {TX=Ѓ&"bUvd:O=Z!?(]^>Z(Dže[8o9m@+ʶz!BQm^HilVmK[Si23ܥjH)B(Ri+qVz*ӭm[FD#Jw[a|DZEG[礎P/#T +8;zYY#DڒW5gmA90(H(En+F3 Er1p@=&c e:,r » F2d|t;u PM*GC26<}LPv8]C$tX24P笼 ."zvomTg%>ip-9t;{Yt־:Et\JeVϹ@ *H)=3G.nrfU۽ehcp /|S/[~߀Q=SyZ2ǝ3vw? +PF{epqlR€busL+$Y<6ܧ~=GA_ 2ԠYg>%!,X  0Gc0Aq렫R62h gLV?εJpX ˜!҈86&6ˉE/rcuvDUd&ի_쯾] z:G{u.N |F5NT^//O?HzT u5k#7NEMO!A&е #_4< Zeb+n6  @iM}T6 }&hdoJ{K/]HO>sJO|齏L}K {{.9=~OzԂNSրdq}=[$&tX L[7~7zz:8chWoGPgSErH>T'ryoAh{:34q?xV+T([S_HԷ,n; 6=8ܠ(~>Y:M{ i.s܄/my?VAg+MB9 /F#P1Wr ZIY%  xD%NpVI0_A/r+dضky>$Eiz`yqqZbE[BD*wF=B  v2%#ڊ)9N"ʯD*Kf,Qp騬];Q F Fsa_ gn-#BN`X# |9>K)"?ʹCd0D`"g0S&o0'?chh ,p!-D&05)njLKFӨ[{2Ɔ>:jd+Q.y(aT1yZ^YD`lb/ rsfc<3|W彯Lqhu׻nok۠L6%Ȗ)$Oc/*92^>rop@te/۹u*N:#kXwQSJ\){{nMo]`EqCD`( c;̆4M녤JcMa*:X,U>Pא4>]̝A2#ԯ3 9=CL2Z"S\ʲK8j냿Z˹{UL V|,g';M";2R(k(6yñs[&#cԱ$e&Z>#oEYA&1fkxWQ '8{탖vVnȲ'qJr|A_]%ةGSֵ@AuliWu8-c]9 {>~7 >z(h΋H7.^JS#dhAg&g-S/pEiRegO/Stݍ!|N ?2ْa#F2 A, J|W[|Nf`Ek>UPl aPSK HA}W7m={Ov;qb_K/H}psWЈ25WR FQz&G z/Q lMXf}_ kc_ȒflP[PX0q4J'Ml88ا]J1ho< /q̀WG쳰瞕@P&g#+r1 E)py pLzwug.n&60bֹP&}q^wˆ#B8;Ͻ0:*p&^o'_OCs;}Y)1΀Osq G4rkSCJtzC*oh'ʨ!}Ҝļ]AZ?u+Fࣿ/w υY4RQJE2 kjI*g%Ql$qS B'ns|\zKF| (Xϥ McwM]dcq`md2mVI8r5~|Xoe5lBrYn" GY\c c2b ,;/l'b@9dRS"IaDV2ϠDxuq.fr8hSVجEzA8ԏx2gc[$s:F`͔UU[5h\hNEYRױG%l‰g2:~=Cٯ:f̬{W#svޞ<:խ&s(IϟVcD:6~*++|/S6$-/ǩ%W&-{Ƈf `#\9`LX8xr̳5 އ|dg^DV#h'ma wK yGiJM bʙ1FyFTrRw~Qgȴ}^=f+=7 ;&!/D];߻t ^bcBvett6azrh[M%GQޱ0AckVju(C9„#un=6dN:-B}&wz;rDIF[srJ{{ ,.('YSq,\"EEGYHNNkoq=~u*w(;vK XΪfA+yrm)xCyj5|PaחrcZV1V&dHd0>n~-hv)m [{W)ejKgBWrh&F{O*r6I2šK D]5KV]$p|͢41ZzR+mk6;R#` : F΀_])YVP6W,f>A8 |>}l_HM'Rw{ @_?z;_'iӚi>7цxokzOAuzi`Lp#VRSJ$},Mq Gf-a;JSߊr)CFt/Fv/¶r-Φ>p<-g~R|ASTߙ>&g3ϪӇ>wNg F߁զGW}L_ft 0 ЄQ*{po錠 /qalEJ}ipvASV|`](" -OH*CRNUh2l!CQāmq<=3#Ʉ](Qoµ>BY6i!?R&+(R6 ҂.긗fd;f䔰mAVXAe/v#ΖyIe_ ДuYs3RBٟ"XUE#eHJBQwleBUP ` @ZBψL'%2he#t~I8X@5Dh4K}D=aL)VWɜ D((0 d 1[}3>k En |dJXP fU !Æ[c!#tn_BaI]g/ s D@ G$z2UE"¼#P!dy*?<'HׯJy א;u1y3D&5įlLq1} FVVQ1+\A@ Ӟk/}賻x^Cq7Je*-uX(FS8K.Q1JkD5B5-! ` / 3^S#B3[]rnaeYf JFUzH+.3@w;[t陯}u' 5BF/Ew kE\C0{*Az\q. %vY&Ce@7s+'}>QLA;@eV"a:v_ :{=PɤcC\gٗ?VoxO05%k1 TlBШCeހU .uxZ-rَ㣿o3746a|\Bg\sqeZeٌHe sQQ],,o;::~3 <ʮaXce2\͌`V򫃱DٖhҒ2بUFQ~磠4i$ V|(}S9Exx^ >%j͐b.m1G>&\(d+p oFo]cK\gܯ9N$ {/:{urf3W2P$+& yE%*&`9o3uK\BV J8v }>E66Jנ(" үr!MЏriF=u# .:Qx(KO>-"_J]80p@XgO7=hxϰˌz|[: X2N*R4|F/y{!#"u30Xϩw2m#)b)_I/_JOx(6F4mJ8LEc]:eCC@>ɴ- ]FHH:~QULQ>v΁I7]X2Ѕc2ba[K:5^DRE8#y:RI aAG( 튻O5$C 3:S̺*XmUB:6WigNY:#CUWa_Dv[yYȁKט$vEJP1gM<_u- ttح*⨥}2KMذ* 2gZ~QKog4"ݒmvlOP>ʏty&^#[߅kePe,NNxh uBc?Gܶα2^& >hw4TY~*lX|A2K%VPEԳFK Y`<^Y;lζئ)" 8U8 F ,$`G#CkH|VoktUlP/l's3S)&62Vo><g2ܣ`S+a@9<yo.5NriLs~c֦{úűWSZ$vo^t 2%)_^E0jlr`j況VÜsowVAď1GD% {JF+\Z񰀾λRp@RFa=+BlX6ȬxP2(3w~jVN (D>!dseGp|yt9HGWfwFdZH3XG.XGh_.˞c{>T+'l K$m4jip{{y,XQ|=@R ڹ8!we觴^D-Џ89d{Vf!Θ&NӑN ɔVxn.堸='>>5E%Ac>9_FE2ֱB` _ZƦ"֖y8yI8hmVҎr=`!.!o r!i*UVX(~1"{XY#8M`n/cʰ]{z ][~,u44MRvP-.OV-ZhIA[2ӗi@{!Z5#w7U`tby.5er|r)Um{;D%O᯿q%U5s ۦC0*<}~2MӖ#7?IW^>~we')=N WY%x}?羑)C?ۋi"FOˍ~Zn 8 ^k8ՖO%@U# pg-_k "mİL5qut}( o&;P_dS!ExWW#40Of>˺ 50H&=H~؅>9@Gӎ+rAUW^#|]+qo[|i@VwiXDEںvAh6i}lr Ce;dKhj>CNN3Y. OY ^_gA®B=!&`\gFD2ʮ4X r!0&2d CQAEEYA rP:@V6 _e 0C=/A{O',:$,r7@ ʢM"B ;d4Lh(݋s81bIȋYÃ1Hr0DՒkԤ˨-*FAҗTоv}8=r k6?ul:hsL_?x(2/{""zZ9j tf11/p1IIW@m!"m~IVdՉTBa-"#UguI}WØ}ƕH0P;VHcDR@: l%z2g eMgM"e&Df/]Dsme?X{e8ʓj\&!T1yщ9,GDVIB|j;XĻ"^oH̗rkFhk'Id0n 42#}3  K\ǺD. =:A(o\\{_,Ci<9xnay?g߄?}k'yltQ㙓 &*6dDd/?Jb$SGDj4Naڲ*:q<̟z82<?c{8¯PD\~&G n@h߲t/s*k`SVNp,S%n#wb*5t $NP8yE F+ xчt #\do:yyd  w^餲e/_@8'wzF7F# 3@Po<]O6o.|>λ]:ҷ^:\OIQ1R:Fo fGiI]$Up 9>tUq4 . _A'(OMU+%^~Ÿk7*kWOC/8p)>{mf Wm/Eq?rxNmjκH{(YƈW^p;x啴85Bhp1pѬ;N[>KߺrbCG?ƞ i;o Y@ ]P >tDШW!0=‘pF*C}> P5* \| MW1C.n#d.c9kedk\`| _AßL&(4htNԉmwA`/'0 c1־5TϷ[t 3Tw exao^4әo8kWUV1Jdxk3k6N$je:8c.aǨWGfkή[Ö1:{2auvO晸FXY(ss-=^"hjzx?: ^:1ZᣩQ,PYȬY_l>P .I,FEZaz].yn`ﭷoȲ+sonn$Yk!PZ@"P-+UU-B?p {4n+S1\;MF`[m nLQ3t(Sar] cŎ 'JtN׵Y b#Ka6=m mR구ه23yHStU 8 0#yVrfYiT&uD".rl-tͺf!$_su2v '%{K17vIe>h%d-]SѵZ V~L¤Ɉ]Exn!foZ@ZZvHwwY ?b?q925o+҇=n1ձ%Jζ0>$_zU`ӟ$e8ItY+ W']F8c0WzE95#F^{9O[;8aXKl2@q##df(E82%ؠe.\C6͋uMˋٸH2Y.m>sT-]ֵ /os9Fm$0SR=iru[ tMnq1پp38}N'M?DҖbդ:Zh`"!Y #)g;fes}T:;!#ŵ0Ӎb\pP}W<8dpP΄y@9Yi =~'i6/>ep:wQ RU^QIDgЩz3>E/Jo8|J))Ky{^&8`}y>G e&Cӑ'S1xw}h0h^a!J5f[:_K4o?LeY6nԊN gӻ;!?ے~ ɗ.wiL9et!iU8#t PYmkSWS%8epRc/89V?̹d/,CS RHA<( CzRJ$~L=Tidڻͦ'Τ_F?~_Q)uH=p KicS~YfS `6q॑XU;[S\)C |/a\j2McC{+Q5$M#HıMfo \Er.D?-q/-M&eńی//CsHGl3B :#s"/[TE֋sVFԑů\fbyRΊӄ-઴<2*sMVflU+ 22.tph-{(t*ʥ sMQ>Q[&fhDzqi& 0'rzmnmd;5Pp".Sƒ!i>ZT˭WFRQ]&d.Dq )Dw}U2fXc;==,%Nj$̿BYa2Ef+V`Ѓmr4V@ MP1=gSN{aA/2j'ђn'A)uy15hcX$bV> w4W^cy}G%eT$smd:Uu_3`M2ʔ uuu9[xŠB.DSۊ4Opdx=~4sF<w^}:`mYM,sDVWTcQMޥ,Ĭ8@O<3tu+WHXZ8IJ8m? –YQ?ud G d[n5@XQ``|SZA{W2Ƹ W>QN^z̖>څ;+.SH4?8庱!ix4DmuHt7 L5A`ϭ~x2QTngAƞ1Py@ uzkHnKQ|#|=:1ᚨag&с.@ I\[ȉ¤ Ѧ:M/„:7iEߠ̽=*`G׎}f}ly0o~˭``t_0.53* ԨZUSlNjI1t숷L2 G&.Q<+ϥ;svOϚ__Gᶷ84m:f N%K`h(ISM0T./]&V[bGiE4u,-*#TPp^3S#㶷d>:]FfmByuDJwVu?w>>oL_{ DS+}%}I>~xK־BЦ)>Kc[#k8.ڏnC[+ eO>`cy>Ck% -,!aF8ξgVV)2$AЦEP?20Ω-D>)b4ܷ[{c+3;WCѡݰ @ݰȡ@Jڤ%iS+<@Ϝ{+UcJ|f8mqU^Z]M`/&`n% d!AtBVZѣxMm#E;o*/ZȬ&ʧeiY{=2Fy r*ptP4q^[{S%RV1蔞Ig5D: 7*8RViʼnRQC2KF(㲜 T4*2E~'!ߦdBk?Qfτ_8Yuwxmߢp8*hCYCmkz bӂ1]Kr9VC8Y} C3>(*ҮIaZ^y O1J"_tK[HyRP>w}3 P~k%gt.4'G9<BIA*9edMZ>"˷ V16>MatB9p`iaFw TA8-ܣ\gumF "U\K̩uNv֨5 sU+9k7kƝoDitFv8LN>fpP<Ø^EaN,}a38 I VZg8a{}ԁ8tZ&`c1g 8tNwgVPB9C9O/\0t!^ SXxEdG=|fU`wz^4ۿ2r+  + YBVYݼjKRc~l* ֫.̥+G g1kvѡpmu?cF0&a5ggtPC;3;f_ev`j? |a?- kff*_3:':,1Q#`頎@}蠼dtbf^s/kԱ~hܟz BǗ&S"vDyoq9r?f ZU<]I_FҁtM*$B@o=#"59 A38&SL>j!NG8/}&pٽ^m+SUU#TaMtOyK7pOM$48 tr@Gv-A;7)tOWiY)Hklg)ԉ{z*rdj-կ̧#T"X`s%=|y8Ltփ3mDT>OAۘ>_N|J?G҃ӳitj9=gO;?6* L9WX_.V6a3t␃Jjm@džg0kV6H vv5aBlgvdmu:.x)U*$}83і:&oђ1mGE]}`8yk(`f0H/H똏:𦎻N@&dO✰H%*-J D&3Ġd±NA:Зv4Bt]ұ1-rHigUahK2p)w^XNE1)ފ@<y0 D5. y#qT)U0Bi~vRƤٌ+ 70M5,cq,d7Y"mȉi'<*NQ[k'$%jyahnL}y"qåY8;&(AC'j-"iU@nEñhh%’ *(kw=ц [&*a`(,HNǸ(CqQ 2k }-ǟ:-a?)G ?ܐ[{cxg}YOlU8m_;^ܳۼg߽UԈg)t068}vDV<}vؤX[C9KmʍNAa@8^5IʁJ(7S'mK#k;cZ(H|,a{ YbɈHkUV|}$5 An3/YNWvǺ ~ؙ}%׃O?Oh}-!8K=8^{=oo@7'B/-64zk%ej@ _亮|_:zX^~_ KD(1nJUtJmjv8D!:gW e2[YEU>RL5â 썤G\7i\| LF$pV?:9T@?g(ڒJ(9%BɅ~̣Ҭfd? zPq.;IO# 7BoЮ>DI63;pfh=Yȕ[Te;>`2C85gAkl)t㐓9FiG[ Q EG(eOtHOFdYbʖ^W2sdNkdu2tEْ' ҭk=?? w$^J5л]o}j0z9 hY _xE,OF ǎH5|Z5ju9ݚ)A{/MDraZL;Ց6ҧnJӳg4vG> pʞGamAA6~:t+K"t a "zCgn$n46(E =C * #1WT= 8s`\zPzϦ_~ r7yTN 3۞ߖqx-RIՑ%3/45 KOa@^0;G#`w5ռ`<4A~ڡIy54A4]Y~2[h`{:WX랫 "w Fa\Nq¯R#.&(3JmЂiW itIW^& x>-&D_ysݑ[J&i]^`UCv72{eK,m1Kט]$"t.;vTW9HOTȫl2[&jc2| CPY@@Ut.nb>rFYU 5 AӮ83$a;UL94J5FZn[sFfX=<}#/@&iG/Mg fZdisA`?w!뜧%Y$5Hަ09ʬSRZOPHǑ{(7}.-({ί~i,S%pdV`.dZS9 2uX*I[]+U?wNs3Wikr4t2:7щ9,@aE}G1 >Ifij5 fP&Zݯʓ  ý8tց3ivzeNF\Л<"f"s9XB7OgHTVTŏKQ` YD9w'-qnq>$@b$pYJV3mCaсD%7i{جЕa ]}* Y;7Hm\2x h"D ;\ASh(Bнo+&'b&m )NUUr߰3w¿pFh.L߄1t`"׎N+`.dCAd+~n`&- |l(oKT>˾j5 KHa gf硵dW0Ou"q:\ɵS ߖ 'L^&m*|Ce5: sT⌵>þ׊ںCҸNCa|Vd->.= ĕyJ?ܕn>s1=OP4;Oyh]l @{ URǜ.nG0V.̰)p }A)%}癣gv6[y Ϟ]}eg:{M=Z"O,@k,Jw^n#}n*+ oH C ـ5p~gq(L`hKk@tJ{WRڱnׇgh! :] >8u2g?я~I5~tu,_A,EZ ץI2 䝼g,aP>v+H |j::sLh7 L)4%uU۬gJȪ^kWkB=&3*e"l%wpN{xo߱F[+@*D5>7#QN~1%h*~Pۊ˳PKmU&[YE“UN34>ʡ5awL`ÊGTR10{uگR Nsqc$a| osg»aLI֊"j "k4LDlluAYJ_zUq{M7n^݈09[ӓ}(G8T*_P]N8<"њqDD_)"MD81f͔ #cpQhن H\ODRhxaeS z J@%Q$Zy}o$nfhЉC@g2e^GhZ"O5h 0ijZ7m!(!dS`2.K\ys7FAhqq(a֍vX es^4Xڷ{-&d~Ͻן`f's_]&h{=︎{\ޛ핟{,"{画7lWx5W[IN߾r= ¶ph#G"[,O<0i*LpCSQF*iMDN^N=FzH)Zx*kB**2tc[|NX2u%h#gT8ď"b 53K-"[Z ek"u0lg8W,?J?X:}ug r?sc\sn[a?ysS8x?|}>Aaq6MɣΥ\kǸ_9F\hN N5"Fm伙Qao 8SqdPMı;ߛ>K$B.;Od8XA xK^*9^opa^#p^8)Hˋ q[ZGP(޻*2 ݼBRyBIVR9 >zzz0Ԅ_ȑ;ݽ1sZN[ODl,YJ)tA߳^c.ןG!=;qVt=ؤaWQmi1(Q2xO%e [ 3z8 죫23k%VA9=wu)zdk|!Uc MtD W⯰󽣿mS `)v0TRAG^e2ʉGSwz`Z,:o4T^\8^DMή9FD/b9p_9&o4^j!vs>c0*Yg,8%JC&\U}:mOxp;qXDF |7 BYy 2K%pVp ^Xj߿#EڻGݗFpϠ 2(Knam#YKIX%wqQw>=>~`Τ}߻J"4s:' g 2ŊT 1db 0?@^'҉S⠠`Q/r Y"#Y5ٗu8͕s:.aK,;7I@9^EitE'![s~p4@Xͣú^¦kTp+4?ot4"7O0Uu0x!4U$gm_"7gF|ڧґG8lGtiqee˂TĻG9& azq)e?97hjF9uG$zޢ4~cY`8cH[:V T>udE^\fYϙ1_yi5RtxḎ`u=gj{T Vדyv94`(JW ko޿`˵^yWZ+, `rNp:?7Mb05I'~ox /iL` ac@VyK]!xE$%t91a]Q}*^_܇7āxM#eRu@M=XG0a1}{vG]ZMODQ~WLted':lAc΋ۥT3IG v}*+E(ݫX":o' =ZF*ľʬ=4"f9}(ޏeo4%0X**eܣp0˂l=:ZxU,MOIO>^{}JW/ҥkcs έt9W7dmJ_ S$7RO2Df>t%:vUGA[ryqJG;e|5 iUy˹.{m@հMvchj -!hѮV{v7*cyIR&ٍM>_UBKrvf[ȻvV(f~ڇZM`:)pV9^-o_=p?)7yF\wԖxcLڪ?۶隔H;UO! DIn([kCMœGjSnŗ4DWQhB10(W^E 8sG0Ph y,]a,Lʷ1.miZjRf*`g$M4\SdԙnkŲ+ai W3=` d|4& ѹbyFzPvm+$:kO6O@Cvo*[&ab@.$ ǎt +z`DKygɆK?DP3@/SƀoJ.<'D ?*uW,vC0N< R 掮J`CXJQ~8h8zHfP9h-ز3XH4Y ً8BF/P^d5{҂5ZTVʀ}C%d0-EXFp[* z۬Nb :l#;f1Ft5,⹟tThL~FڐO4lp`ш= \\a+c{/kuυ +rVvfSfZgeJ'\%0}V%ЕTU]M$5F^[ | 5Q28CfQc[}dVEۮݠcTYSEKIo. }2x_3ae΄#HZnyMRO3̃-mAٝ ri~zx#^3c)_`Nk8/MZӟ2]BNG/,y 3g}݇AzN7"S96/-9L8bx{O-Bi~LuY-ݸf+!pPjtq픛GOy ifȐΑed=Vct6`/`뽗y͐};&&&R`Bw󆞵k;Jfl!8~[qNҬ:Px˵|뚻<^tLk"fvn)e՗a E.PAeji WY9ڮp\svUY@n5Nڱǘb~! w"{f޽G Nwh #05eF8Tvi+f<ugi߽}}ݮp귡 "qxXYmMFˆ =+l j@X'ֆvѩ6Ӧ=\ _Bkqay7k:uϜ1MnFgzDǑ-IRfVL)s)+[ޟ={& t$*9y|b*~^yŠa@ c`i#>.lUncƵ7EbC}B I NGto&v*jOlΎ&&hWb-᎘]s;TQ9ߑ^^b$#i1mklm5+zyGA#HykWjy&)O+ w*7M|c _{$&}m;5tr 9dy1&8uZs`wBkK=>w|){j\׵qxҺE{֭u-d͙Y͹<陵9aitgfMDw_'I$Ϝ. uh?PJ"7#x!BkL#6Mh 뛚yv4ܒ|,zL:6~?L?1<BC~AsPq BHn86?(ڱq'utw?'f&'bE/㕝y+PVqiX8'y{rl"}_L_7SPP>@?aЍ+/qzn;HW7?osa1r3U7;}dN3X}IN}%'oͶ̫JN?>+>)W֏9Wϔ7b=coҏPZ} )-3A ȳAh(gRR ֠xRxOCޝttb r71!qBqe6 +%-dr݌2WֽF]=JҨ82YZ>ὲLֳ}2tB$QFk{R2p1 * ̒Zj#69$h;Tlۺ п;vl=I9zI b;<U@շՋ^WelڙAQ"6; dwxϪvG6Re)=JؐP=$hQ=d=M,uOvTRI`ez[$.6 GY]p^gZ|VLymqbb' m-LG[kqHc|'@IDAT.-4I\KzڣD`ℑe} t- g7#\1;];dYZaR]\`&X5f5"q=nM<>BoGT}`]A>I4{t oCFcZ*)lK 9 .RsMrn4M.NwxX4Ȼ,_&y.xAmb> %4Yk酇L*NsIZg/̔6ԅil&m 6m ': ~޸1A r~jggM^Fqo.`{@eȸ_=2]Y^9LoBK Kw҅CRһ}1ثZ/M{*}᳏o{Tj;?lI>t2C'O?dV6 {He|*x ;m{㎙`Ź]FL4L:H =DbE#U%bny:#\L|4jLd]g<&Qѩtbl7[}GcʰON&aag9ff)BGv/+Zl^2$ߺfs<ڨ)gm;v@:pvrr0g,9ǹ V7.f`i<ɷ~Sa̝Źt'a:>5bt֕tᱧW Υ!\ß(_>Zmhm H5_]6TTг_b^U )f, Lc0qKW> =Dݯ|`pU+!P@O&)laEH0pC6*`KDRJl@#]@lfn>DHa2-m9 Va < Ct< ZvY2'1\tl0v2'k u Xe X#W{:bٸU*%.n6QPcMUy=1fCUf2F 9& pLe(Wqaj" f|(̢3$3ƘaPA0 =.c;BFpE+NƼX[F$kkƜI]<&m5PLwv䩇BV|#.VoV"w=CpJv6@k&ݦ @^AP8\FTD镐w õ~-њtl-ۂ( rȾVmH*81 P!p|N@{8JK;躧@* ,·^Mo&Ldtu03qYNtd} Ŧ_^WzUnY@Rp>+5/kJ ^E,0=c?_B) <0SW_ 0M ;KLp^qz[#}u}S#c΃ QuЩJRZLq|833 (B+kk'q8R2dv܎/ ̗$'2`ǘ3CWoE+~6M |Zsy/^TA?A\#vC{vs3@3?B28M}6"u>7CL=&3qN4<>`{#c*V=3B >7"(h+oG R%_]ZoGE KKs1ɂ>l5dΏvhR<@ (fiuT!2qE=k?ē*|W~k.l:/muUked4gse=Žu͕ߙʛfsG- )%xG"1O`Odci߅ =(Y溓~7.*db$Cj堲V&C pqlCZPr@ۄژ]~9d#hlj{L~i`B0 y6I*k񙓧O"[ ldOGVҝDvI?,:@k%C_XY^þA=Kǭ|;e5f?kcXYL.m ؙ0 @#YɄEimb̀'ɓ]iWߺiV_5WzuoڕؕcpP;_\K]"Ρf'ಬmO}gzҟob{JVh0[iaSbLaL*]V%l(4j pw $O_H= q=}tj,յ23ՙ5F{-9~vTrf[xdTX\b}iO{G<ʸo>DU ul%e@HV#83i[{ڪ'OS>qcv:1ah+EqYT: vs|.| f/4~GHh>l0 %c`Ղ&% סh[-+B#Yucla6dgJ/j.cˬbwP5wPLv갣La),ULmvq }*ly9%ЇFRH{.yX EZ52O"֤t#:>.~1znmm86ϩGE8{܋-mO Aj 4u '[Z#x٧MP-|6{;DӖn!!yr*CHs£j7+@Gi2;iFl1Y-cP`64BvUl#> o{ kۮFw&d[\vwq -Qѻgi[=8{/- $h5mWa#_O W OU|uM~_K*EPN*i1w $GmE. ATMi@ƎA,3lFiCi^Q>;:VA#buh 1m[n=̳S| F ENݡWS>lx8Eq|ݗU-P5 1ehc lNىsC$19JGqɐEq5`LԷuow'AU9E5&0mH)oh+̪hzBHwꢳA;7黎ih\#I5 4,?wkRM9$ ]xG|6 g6P4kpi~ITR偊 c}v30 HBj؝jn) q0ooxAZ0Z/Z:z 3,[oj;x ?k d!ؚ>2}Mrǵ} ?N˃fA:l&,~`a0S2K7FC=DeL}=4K>L$z ;ޥ[zz&K'mZOH~#>}{Se=8 g?z`;/y1*υ}!Qki~ d7:2J[A]}~K"=HKts,YuZH3ky]WK83nVg,Lt i-Lb:l4'DY*džipQilLVP? }7؃M֣Z@BQsfe?}sϤo] Zn~8=̅ }"_ڵ`Z[sd:.[^eoZp݌-Uar~@g&O3fB@@64LX>/SNk;hX G숿LS\ vvTmoosM_o?rn})|FLm}T (9d}:nm,J.|1h=ȲwYĺŷ]hhS2X_?#XA.tS .&qL`W\L]vЧ& Xc!.63@Ȍj~(Z*۴xxG,`Ʀ&Z ԲBaPAHŊ^$9/r:sbk˂bul44yO3<0³ڻixPO.AGڢDxdL۽D-0VY{ ( {#bf #M-*_T!*M>ڪls%#uM2Q e52w c؇N>.<$#k%`ɼ\)cUuwe8 S8Vv]HZ,]J< 79 ؼfE 6,=3Mb/A鐍 r!5.Yl(e UiZRB L13ol>C%d^aj`.!$Ӷ$D :IXq]Oؗ }g \iG0ipY+LzѷBpum{K#%6PWa2* Ys"hcDr5luPaDuE^U`"[~GMÄ@,j(&<B5vߙop5^Ro[yFhk<$8~| E&R|.j+o^M +ǦB?L>/!:3f.ς `W|d,:I<HVRpq=mq"ptAgW7-iŽ׈$֐GA2}\`6rN$Q Lα 2:w,ԥӨ{S P90#Q0>Fi8GT]Lf[-2 kg_x"Hf :қLp[XK#c$Q\0JWxH) :=ۗK#vCDn.IdtQHwpd ˇ́ޑ==Jt0Gv~|m8YYDsfaV\*/ +Py-sFK5te!Z+8|5sB"㼐 B2 j`.ZTEgPөy=ٖ$ٱA ͑]stў ˁ e>ݾv38Tp39y!ۿ" T Md( t3[~ZMIbTjʛ<=JX-2~T$u6khW[VȀq։俉Qj':Ds#`T>6.Rڄ3S[P& X}Vhly9ΛVv{muu/ Zka2#]#)"4z6Q྾OGzGOT 5s{釯DZX1fMPArǢC,FV{[MF$e}~}M0H:aT1v{ɳ{t]RGGU?ReAPKü_K_|F.TAxg%i 4@h\Zp\\%jSi;ZlھgoU&ܗ\k" YmD=w X`|dDdGmO6kS_OWPOk!0 vb|ͽYs r(sLV|"ޝ;0k?͸ұ-Tz_~t'g}ƌDnXD).{=7b26}c:Jj[f'{47,nc>HH0_}X'tW\5tOOw?]q*bUdſ^^[&~ېV湪~| @E$B6V(7HT@yI0vi*4gi oHG򞝛'!R VzG_U{y>Vd όI& @ܸ}/X;AzmU՗CvіNF) {We-6C>)OWY ioj`ݷ x9W"KWIBm0^Țg]ձ՗==&X<)cke$TUКU=?%@?7O,״Z-5L3<%BP |Nj0@gR1B2%ջ$1'&Xw|4|Wdi*f'Vʢ \U^؉ PY@&6Z8la8jǕIن(03]*%.$0V~@B5؛1yMvBLI}J_-UOjGH}~F0lp=;5 ^^aTu*X ж7CNc3qb]5!t!W74 Ѵ Rn~.߼  rl),_*[S/PE:3 teQ c\Ц*_ZI2xKG.쟫n? ɉQƺhr&e8`z (~b\>G>~ݑ4EW+Ty!sDхPط rbe{GtlV̉uV6".~|?;$*UagU *=mtyĽӶ>o@uy*H"DnINtMFAștFk|yp1dAjO?vD?yqˑ2%-{:<9 ό`k#`umƱAqK 輄"6^/z~(GLlm.Re.y+qToѐKpvj+j'c=1xw4m}F鏾մ,F~+iyݷ-xvM ?Ebt^~J vڶ]Ǟy@ aM謢%Q%٪w%bD0< 'Kk#I m׏Z'Gv23 & li`>\cqiH&i8\e2x@%h6 ,F ソi(!gPD 94R>1}MjeB$qD@Ұ8fΜ;]}_03f㏖|7 b-R}Qu{oHO=8qtΞ kvp]Es7?|Z7_3qPrhcpX4PD{OC0=q/q *`V1F8DX-^I^-a[dg[ъMCzkWfZXl6Sn"mIGU9 ֿ?_yhO)IAJwfʗ=,5|H}%dF@~7ۺjV\E,  }0U`odO -@(2ʠ[A_Uy6UZF!cM&N  zegмFmVP\3+WҬaka]X>RV4a=ƖLщz92ci}0oIX6X[S:+(~?rD}G"Kv[[wA[U=}Yo0yȧ:rQ- N#Z?rbg w0ݽs%ݬ6fi @3Fumר796Hh7X.L$$ݹG=0S1Ypۻ78cw9;Nr+s89>嬈: lӣV_.`y5 ]#L{eaD%IƜcv|Yn",մ] -8miLCe^[:>4^\𠱹%YU#Y0?hۺG={}]/|mrqĦyi'+8weTDӞ,l+O,ĵ/y7ߦE-Q Şk/G<2[Z9N:_ot_*Y+Uڰ;&L@%D5]wy:/^H^^}Ml l=LlRnڵD~WǏ !;[ozw꯱q锄v!2zЁdl%] 84Q!(;Z,ڮT}Uh v i`i@۸4GNLN J3Wt bF"(ܥ#A@NK9jNvz~czkJj Z`m J 91/hBBf}Ǭ^&"ƺ煼WPBBi'0w)b&六{|d\K3CdZƬ~5YϙKy]@辎Q۶gv~5?{1?|9l;J1B#_ԭWL<|Gɽ+K oc.E4?"bbsR1H[/s.m5 ]Ŷ♧n5ɂ A0M\_$ѽ䶠9-x?u6 $ish>7K#`ID$H0+7Ã6wzKt?d@A=E!;[N}a#>ݮm̅pNw>!f6APćyTz Id+#AI_NQǯgz49{>0'~6=zQ= ^TN2OlAr׸,V9&0l(慎>̇3Gn`w}w N9`jݎd#<*Cلu]HЗ41:M-C>F)CޣX{RW`U?XJ+TJ{ܔ؈PnULYcvh$AR^0 *õ+`^1j_!҅|^ S%w9%|VF!Na/>1IMʔM4ēsD\-AG\г묝j0v N~Z5/6PU^QŴg[򮒄< x:xې״ ~Cc]ԏewU@tRu6rUJ}% H §_@IDAT&772\FlX,(Ct:LNL\'`͞/|H@<ù.R1|_^QWjѵ:&Z5fo-"+(b&VA&Dp5c"oSTuyĎ+;5qN@ψ-Jl#uArq`;q @.|h'iP[4` [1) BR+w\KtY\\ͅfE4bB]n97G̘$b_g9ZWL vA$_q%CS¸QLaXn8>5ui1d Q1uMf =\L+x(NWȽ8 wKtX͜HNYV ^jGt5ք[3TO0|y*y?WNɇA؞;5>;3okzhQ@k-^P86vsR$qʼnz%i+sFF*b-h x؉ @J=*:#@7u6tp瞦ߟ$]uYڻC(*h*:X>3edF)i9yrT%eiӎET#$AsQvs|2c{]vVJZ C'7É1AvQ1rNu>9h;XgRstI= ާj ,|W#!Կ4jC\P|H,*sjD٬o9I>A ;F2wYXMhCYD87D6E.)ŃkX$aMC( T:g]ѯk-"Cwgl^1YЅfC2T,%933*.ΉqbKwuwCr,P8@Yκ B4#0J\؃%b)vijJ_yif",9Ws(bfSً!|p/!noA Ĭ5BȊR0r@J 9\^Sbˌ]U;Ƃjm,82T FBAYѦ!c++ ,r2K{KCư#$ΩiqV_E\6!)USǘAFn}Fƶ-DSr^۶|$ry^\~!V`{R614D5(#8 8fc0~Y:ȓJDcŴn&S cJN'0ӛozc4f(+H4N$J4 U#wUf%k`-@$duηNDiJb&JWa[k1@EpG=˜1{ls* 0@#Py5# C[F =Q5"1Osۉ:_ݱEW9LQ*4|ͬksr| )QDq'+_*ċ0c_m8&.c+.0. !swԣSy^>m0 "ċ9clC.F;Gc#Ά2⬆3K]H9[}co2Jv%SM+u !g&Q٫(`#HlBD jm"DЙ61ǠK##jɞk0_朵lDHF6ie~4[X`TJVN.Bc+XGƞ/fd`,uK\Lz&I&{dNa8hzUJ_wދLx;_#ť H(cf+  ,Z,9(BȔ.t*7WCWB%FpN<r_ն{=:pȿGdJVu~L,)ޣ 8Lא5woߎ*w-3d왼9x E *I"pg@]-8AM7[yMJe c>x]`(x ^*F 8{ƞ:vCtgp?|츽tƇ\gȬZ sXoetfO=DyY3{D*D߻q=M._#V-̄~MЄx#ls}0voXw*Routiⅳ'kLʛh.uTOn߼n^BDV!&(-4z; 6p5H D< Q;jq*Vw-T•/ETo޼]N't bU^VJoV6biC)4lo0>pNƒζW7:b_l52Zny"#)n>udp=/o@QֳE t$γ*IȺ3KNgҩ~*H؉TF,,n-9;/jĠ~ F}CzGliWۑK;@@=iGwy,x6yh;oUb'R7~nҫ^ׅ}3Z{h)ٽ g Xۗb|T2Y^WV*N×_ZG~Hdu?_ڗc_ |[\h=Sk Tn:)=jeKdЩ$S?r 8/#N]U'/ Y/Szo T&|?n& } ]9_wJ-;J7xB[ȸ=Lb)42"!mK#؇.pl}uP|.XF۞ :2T<2/)?~'?G~{L,蘶Cw"H'Gc00η{!;fIR~t;?ÆJ?eL@I[e-WL7=Ɵ .{$C՜aZaaKMLV ϾW768cM; .8hG׀ O = JBfa1 MLc1I¾Ad1i~+Q(<#\m^`ElEU1KR`+Wv} ^ڼ&kmE$zdG)`5jA:0F֘J~]589o{yze_b^Ӏk+$ 6Qآ_q&juLp=ND|-E+ʕf0aR m; i,:؈Y8vgq M/O1tuɨoj4l6Nql\_UsfK_ Zf[XKq6_ md&3֕"YqbQؐxT/,GRʱ>N*7IPl[y* yLi -[}n *{j+ gYwUʋ<%i"cbR>=RTu=ud!tl=έVY"*'Oq D5J#7{L >ΗSFyB69W*ibY`1btb] ]B!U>]6' ep&uc]]XdQPD_D%0PdPV*w٘H>30Sĵo߸o_N=XӞ^!c$)h>Iuئm $`~;'2Gwt|x;WX}=WT1[54pyYy]L^W#xO[fIQA؄ClOFځOJ fB#Z Drrqmfv5n(@_kفY\/;1 (~SءaGЃi?9*\/i͵2(~MOm{j\wq8ͬNV-\Jeь];E lܗF~)qˑ&ͷ;2{.cn!`$g?]G d ىNMOn$X(WTBZ~oL!%q,M!s?yr)qOv]Oq8tRY`/k|w;rH@؊?o}S&!%ZTT!v* lnE CP&y5lq6ea[H!ЃUCUuu],1>L=vC?P2Aj'/y}#{{kneUXD -?E򼐌amh6R,v 8NRI'2]$I8͵.m FKYZaY (Iݴ)cByh,&Z9o"60-? '}jU 5^T$7 BcB@qf5f9,:, b:N <~ϚuNDuqf@;Щ_(`[Ȉ -705hZg->ݻw믾9u8/cmm,c쾶24X_C1Qia -5*z $QGG9t枸.-h+RtTfFuF:xrpv~O Fӡh>4#!B2^Asi;4ˠc񡣣1 3<\˱`A\Ccpdv~ EAT^hGca||kqwxxfa 'vFu.bGhչD=fǦS!/[9kՠB%mFdl$;V[XjPV 0 dc|s>?k>@c _0%ni;eI;CŮ@} e@2}!zKSVܘC0wt6E\4BqiL3.h0RW#ͺU:.D%}3zS4v&d"HY<1)EQ71&?97}ru:u:J0)%;wIeG79@m07!@g$׵k/(4ʠj kX0tIQO ƚn-׫$C{J%[% (/p @-3u(D+|H Y`Kl;|AЋ{%i-a%Ѳ[@"$ܤZWs xK90ĞbL%}ۚWCO_EWH^GD77 <{8=;]ΏAL9f 97ύr&owTԦ9^ :8ީQa۩ԀͰǺIvҴ2C>0_}+p&ҷmTo2,<=2:r@cӤNXC2 "~g|lG/-ߟ3~sfXao%wߋ%)l y9%8@NR@,96bɱ,ɲm%ކp\Rr`[~v3u_BIxT7 MeO/&%ޜbaÉӱTK@*= 'z/g(Apºl^M+0j;$S<z<[뎯]hTu?{S e:p⒧x =4\+81޴W%9mZB`57%\gKY`oifIYLf=/:eK_#it܃ǿVW3@9LIWM h$hcwp_^k7u]kǏ $Lv!Wd܇3N`1~UZE렡V~%Gm{ԯߝ`zbјn@9Zr4& [wrܳ%f`.gq$X7xΪm^/ v$U\ݤRႽ^4M 8x$_˿nIHmY'/HM _gO:8Uјm|+:p@4_Jw˹PY=uU&tU ^b7eckr! N|LɊGE><㳵[o-m0ho$D8! Ow|{TaTxnyov%ԙw_tetVJI\ejzؖh{U-]+<WƇLҷ{τ7ƾ-0yNowv=슷s?,%kq:3޶AZI??p@ue2Cn{Hk^m50TLǡ{ tak:]>`oH1V|&I06}hk7lIwJTe-d5_u04V Y~vb6>4U%:ܣlITz[F=:hSf]cLv,;o$!@czS"J-o#tZW ;=ZQR*O>C#5hGroC kFV{K ulJ8mwp>]us:u,/Udl/:]UPcOܵ<&7_3gz|lwN%S:$Yw3[>[6mfmGkU' DDϓpΞ-#\S8o]X?H._S;KI8k~ıh?TK6>OBnjn<}>"hTZ]vرs6MGW$lcȿd۳,hnxf\39/oC|0n~?vud\H>t#Й{Ki%d>tZ2Jڍfס<6>*wdWD 7nHϑZRFu/+RU|cG׺Eċ%`4ľpw~-Ӄv̀핿3}ҭu_- ~ࠑf4L|xnY2 &{ͮ뉉jh""H2}+'|W :'BdL;C~m:ۧFKM8VBk`-`qfxOiɅS~y*ǶnRKo dٞ$w~!XǏn7bQq: TSb7jn\1>cyfr,yY ǰ!Z%óKWeSǧԾ`A͏>dś^&8KЙ?~Uꠌس󳍘[w;ՒgCX3ёw+qF虝B˜g/p7Xϕ IݹξXd\V{_~?{P-ϝx'?^]2^ז=dK[s=]<1'[Nzt@ i%1|tnzXUW/-tbw8C9,p(aI9)BZѾ_2pskSbs[v[q_s9{)RU /-cWN1+#nNFlU[_23Bq</<|#!i>|S< ʷDNF{e/z=.KƵ`ș2{ ?Z0TeA.]# K s`[:7oNGO FK f"z x?2]TOKoL/ |fniVIڼ<+k(*YWwq8(Ti[vg ‘=}MwMه)9ڮonS8GG3JRlǽ1rp`#@F%='/JA5A !^YJ콖we(I#!xG8.Ayf= ֛CG7e%v~b 88bD]D`r bSn-[_E+9{=8)V=K94\9yfĺec[P+H*Bi0ozqQ|db DR]cG׽)5j+SWg9Q1ȓJ \1 1{SkxJ dS: @Ӟa7WcOa}Xz!+VzǴj17w^ߛ8>hPf 3t .rC( e-0z|;/BQ^k_o e0g8!oxf3Ct~F F)pk>o*j$Pm"dd\Z= <@1Z'>~?%1d֋>n|]Hj#;e Z=(eo?G;8{tR]v<88օ*]T>J’e7&!4-3X=)['VeAg:|w$S|N1Ux {Ɏ㻝>5 !2rdfsdj=\/^]i?e)%x0 25Ҵ='`*TC,¸Zb v j竟sUՁ3g4 ,8W:y/1GV;nSo֕D@Hgץ˕"׾ k|I+]-cje?e{(sėE6k'th?ϛMiLS9t#쫵eط/=^OC X^f?O}p{7:tgQӌ7}t3WJFj.յVcM-F_)g=3@wU;@Q{7k"xRo yhs g@$L$d938\ML͆)v*XzH\>9lo! |sKbˢs"1 U]#aA7@Jϥ9>t/E_G"AK]I{1uTsad]lTYt.. 6U˕,>ΆO2=pl=k_sн]xV֯∘V|% 'DBSn-Dz3Gp*9So%_RN#TꫀK6tomϞM޷GˎW FG!_2:q-̾VsUO_mk gޣ|V_ͰޞK^z F ;w peUM^F<]w0 3~8 ".^NNC/dB9!jrgl<3gbk]Ugֹ0t>k=M|􍯿(q@L(ǎ4 u!x *-پϳuBtT g dW66>ZKxw;]ɮ*KerAAhל~D?3Ɔ3dLAN:4g?`]rdoi۹r`{:ч}=$Jckŋ7:5z /WZmlG9񉗜3'p Up/ٻ\zk8 F2zx[l| e /wNNBȮx35-9͚Wbt~&hC035[tx"WrKzFT=pZm}4xt0y07/]CA=f+I% D#}\'"I+MdL\|?ϑ;ׅwtٺ޽< G2&U>"7&SllV3/O"~|md/g.wk%Aqmdۭ; $U fiMlH_t5lmj5]AZ\Qh71]hk~}x'?t9\s5;h [gG:^%Dubh(]ָ乊;~8uk%g~P)J~InH%<́ Z7xbvF{\Zb% M E cXY+ɝ*=s*wHO*n왪N7~$ 䍶ѕ1O*ӓ@F hTpS,l4VAlXrD@P6D,-%Eة\:i=޿wwe͇&>yHl^3~{;n>?fs I`2/^#/T\/ ˒!TN=yr!(]Qc׾l/rzpz|+*ۛ\t{IhAt.>|\Ǧo;%0{Kg¹ &mwu!h2=mSHf_ӵ7o5JN]ڣDvx H8\Ϟ=3MA۶KlB)q]~Me??«*i)^^>0۝  Jw\j/ Ӓ5Rt(Zw~1~jZrXR o 6w,\g^xřt$NC79M8G3n_ 7 z_GMcI}t:qU7*xry^ELDѢ`p7::X7wu%l0].)pk ZV>FzXthz3o/]_2ȾPR g-e ?~m_U6۬`9WC=ur-z}%ݯG*;.~ |ߣ*;YEݭrׯkNL{~w{sqzJ.Eo5CRWxm"ԩ7z&e-dvVMؐ伭O]4<@KG̉::5W]6.eFUE{nξБaS{Ek?#/wOξeדQ|zPpd=\6gO[hrCj6'NO72uJjq 874HKvgo. s1oa&y" ~_)kk_gDe3CiÊU]l%Ʊ?g:*Y'<)Z(2n}@n&ΙWl"'T!(,ŦIU+קW? Ҧ)SeF2~8XimBU\QQ>w#6Clm1XAwo?3sOK}{9+JY;sl_NׯN=W)S"=Qۉx)KPT eY#'xUZ>δ-#S "S8(wrLj8Ҿ=CC;%@CB'|#iPfu[+̯{~{2VѾJ)|ha G9dΫht?*>654Qߴ̅K;.Lw0U`{,pR)p={C\wl/!mKUZ%B_7̿a(DGh]9{ڠؿgr 8({QjPX^+4 ֕Q!g> Y3~ܰI[{5O`` ';fՑf>|dy:λ[Z7W}jMEFKKGɎe0?^OHo<<^e]ܳ7eM)ƻ $T\_xt>7#Ι7[G־ʈVtE)Hf J 2~y٨ ͻKh0yrh>z|72[עaǁΙOߟOWpolmG7VBIzA/yGu$86YEZƜ=v|vV?+/ Q$r+HF 93r=eG{fꢻ)9)_ )׋C-Rh4gxO|)7r^k=e_9KVrƎd|~1~! ="=R%=g2VrCczŎ[De_3OI0t~zo>̕`)#9GG&tِ ),hޘ(t'U }3}9=m*2XJݭcN1`4 [JT7cԺG %!&ַ'x$^1TSϐ`6=ƗޒT5YF =Ӿu㉜>M!WHl^D~y~no1>K?Ƒ̡1LHZ±$,auz }u&ޯzO?s:q{{@j2)p1E~^mtfBJM}$x*xF@IDATn%Ǟ d%wZPep^ ~ f94\lTF0u_?rd[?ϠqƽA89v8I"M' S=O0Noˁ]Å▒Fw_u=]L5>ȑTλ ֺ?>/1ǛENkKz*ى6O%n!=ozr)󬗟9-LY>_NGugl}Vŋӭ4kHC?mg;/;G w-}遪^.*w8gs9fe٣مm g3{:F)+1"Й&o֤.x\gtJ(:p핓_BǼHRy J虽9!9T ģj诲i^t%ƍӵFPofÁ_f߼8-5XW* Χs?}$:Jn7#:Ba77b(P>~1ȧpʽK&9>ޙtWţHA<s4Φ^~b vl*A2U <]Kx?<ݿv!-sq׫3$#;Է?eP}|CC]_>q.O9uO57{yqW"%|qbl`KI$ݩ;O$ޚN`y/%D*F~kxU|!%Q4x5{]YMA䖒hxtlƶ3jpL2Bׯŝ=t |>;ϕ4*ˬ4R/~rgD'%{}ex$5K@ƙVIJwomٝq zኻJt9>?~^ -v`/wmQpęI2{<-?~ :-OKVh[쥫wmD _={wJ:f5C6]]iTڼs$IYtdb,) ?t((ٷዹߨƃo(T=|6ڠߍGs#I/'ܨҭx{{=j/LZ,7ө#(0k \׾`{ T3J~{*->%E5*t]Ю_ wU~B;$ . w| -Y~ D"2NwPkNyR±|22p,t[5G{`8#$)1|nع'r:oIV}1?) tl;4&Ut'ϟ>ayW?Ua k+q8.Kr{Q7Ӆ+kcζ![ndb12G z$Xֲ,45Y<| :mDol|  l( `.CK;PQh96\lF`tv) dGBtݻgF b}\@*{fgS2g3ؕs`DZ@I%=dNLe*ý>ȕS?3⸥WAH֡>1Ow̴1 , Ώkd\ EH;ߺ_0^U "@ wpp9k! C/(q. [kA͘pDV3=ՌAMM#pv jAS^6kaI!&p#qJ ӓǏ0^H3=fΓ]}s r~ZerP=e|̀|U%t2Z3Ik;9 ~)xϒ$I H۷ytHStd;d%wtx T¥.-9\bEj eAƉǚNe52|>"Zs Pê-?˘t?:6r؊0D%ڼ<<UϬJUQ92;< RH\/KW h 6ݐet [.fI r>S]ըJVad@npќ` #95LrF {g|M'=}.@}A#v#+F@C4yp(yrp FPu0J߻}y]c_}4dfwF'ӅC)0ZŪ!H\1;Z^xgwϜ (|W~eYIT]Օgs6ëupPs}vi"T$3rK kؙdAwV^ek$sig4 /tF{osZzha{GI8K`-`C/pb<1,U,lëq y9aQΰ{HrI$ee؂p/ɀn&IYkIF:#W>\W5_m*YLm-lvliu.{n3o ײwlulbf?*6LjW?.m:طI۶h4^}tA=*@*4UڊerWdwSt>y`+Ι=9&80Z΂2sx}n|>xq漴6ݜ'ydp J_>@o2G<;N:w6ҧ='y hV#W{|Xy̔Ļvcm#Y%'[~Qss2Q>6lQ'ϷR:Pb##(qw\V8\rD:qlV}x]pOf$9S66ɺU:~O =pbȽ}'[1k7}]&FDYV. TIs$rс75`?]|ӇEՓ[{}@_g>`563} 33;)Lg{GͫGBD=r쓕+=Ewn|0x`@NdĠ?|wa{ztL貪*N9rӺi}vq:d:\3g>.8Qc~:'i g GnZ}^l8D}I#; V;aaol 4CTsACmV7|339?I*HIgIxm^uDs3g?k{jHYO|tTqѱQk=&; }}($f_0L׮]n>NU`K'К}v> hwk[Vﺈ_/N'f7'__\SGU~x1tl9={YJhsj‡̙kBJ{iIPȄό_zrAI^ħcxs> %Y2\8|zRx[0s%V@8qϼLK:HnѮ\,|`o7{G?8F{T'/\ ^zZsﮥק$ɐ#0|Q!zx%~W%2د`ĉFfo/7 |3\o\4ݾ+Pϝ]L UAӕgɠ$h?jקC{* 3 ȉС܇"UD]>n+ _|$!B}If '7eO4.,NDw|~ϼk>%9*avK#A<[gҟ_k4CIxx}HӐs%. uM/W/`t"MgPC+$k;D LV~ٳWuF9a9^"H@+}ĉwrD?=;qb%;vrȅ&]?۽OՍЙVAxሩz8p(w3mZނ. -u8;WQ|zU7"w_vA?-!fڨ^>X 5Zf pf#U,YtQ~iiN8߼^k݃|cN޾6m>ⳑp3ta ӛ컇S'prFӑ%R疲L7YyrݺO_uj#t;#%oI4(=ZUɧ' ~~$!_'[Jӎft5{NoYbwvB&|j#qG-Ngte[W"T_W\'A?b>փ5:-LėM- hjt-0O#qfZ ΑH Y`W}EI);_Asp5F7ccDbQk0f{|!*v&{S)pp#^WَF`2'9Q,e {X3ΗDoC 8ķ'!8و9iރZb=@SFyTЪA/@pc5` jلeҴ >HI߁iCp]G9B[C$:ziRѪp cBfg96iT5c2/rIY*)Okͷi"Z6@ֹmZJ՗WjGBI9i0`LXXThM wm.1͠]8=!NT vn<3yrs"8  L4` c06hfat3n=u_f,S֝{GpHI 9_Жԫ@x<3GNyP5Mj g050d9BmU l>ߟ‡A c1`G4uwUv&cj@ .=l3:vsd?LlRQ7c^kF[)q]PFeO&((&dN ?m˃ͪl-.@+e290iL/(oKtK6ih xnX2X@D%wY39~ t<ЬirT< x2`X2  ϗm(H sȕa8mK6{\H䝝4N|Lk_h {T{ݖ"^RN'&%Bfr]h,Q={gD}v$ȉxĐ:Y5?':0|e#>`۾eQ>y]0j(Bq?< dM4g/f_d]Xd-c?s c{/'/+ͺTiwOz`Q%w=w ,s\p сTn|*{Wk94&9s0`ǩcG7dlnKgX{S2JƚJSNUD2h)Pa&or [%2VI"4V%l<\G84H1B  -Y=8{Ar=C3XԎ9k9Q  &U 9TvoG GEnIs?wWs0#Jhgkw/IKkSŏY4l~j[1 zd0vp AWhC)[h8oO޸ߛWSm>Uv}9)[-Rx0lUUG*ͅY-k0 ;.zLw*|ګdHJ U|oFM%i3pVYkzâEc L2oWr(ϏXسxLOպmI=}pЁ3sNZX38*"2ڳy;sUj!y_tV`hg-S a+ _p߿oy n r{mIUCj-H=%Q!>[g^d(؜_z8 <8mtfc:K:g2h&N@Q@ i5͋UӞ4}U :lN?2l]z_co3m>[U&dkoe=/:.S6;/.'z~9ϥ;*iJMz"G 7: YInu /R9yU>E% n $·:Y|ŅO?^uv;}s}ݩ[G>`(:[^^IdZv2zD m%z{ۜ .*ѕ `g?}$oUy#il-J0ŕhѫH2(˂={f&+SȮX7h/z՜m/~>Ƀvg/2^fAVNNs#3:&1~4Ϻ '^8N13VL>i-0.+xW|` +~A~nλ[vdAP`^_HKLT?sjG-~ݗdGAA@lFL1\x;νcQAbt&cF~/ r&gߒ/M ,JT .{#I+_sswhfq]ҩj OZ*5ւu~x]F+?Gp#y%[cit7d˗6<}?a0rCg!.gmb4㼺ƵkchJ@ I/H&g;s[@Wo菎MW D%sOKǝ5ׂw{/\t;A!XݕYϝʷ]PR.ؔ -*a㱍*"t̫QUUAYsMƧ9'IcS#O.Wx_Nww]W kބ 6^CNpS ;gy?K_08n_/=HvṋEg:Lqgu]);YAoB#;Ys Ft:c4>ݪjO 7gR Fx9oY*Hiew4~ޓǵ/8J/W/,ZKQb> fS%@{7bs9xzmJ ݔu"yEרO_3V@KXM" m6,%u^42Op"*UER7F">%1ĞĀnޘz@K"kWh2/M_DF~M<Ʒ?2i`g0V{>ﶇ];Z3uP7ﳥzy:}0|rxGb%-Td\}x/^trӑǞ G U?@˗d Dכ_|sڞdn8\w9]AL *1=V7kq\__Y OC.n1Rea:R"ɑT$I]yQ'f{6޷?7)Wxn/ QGlŚmx!|0T2Z84J3>@St(H3 "NY;#@+p/Fsd^;00f bhè`mʄ&0a 9g|)90J(S8r ˮu,3 _)g̴=aܶQ4̃FpS*sL;03(CF9[kRqY 8yPoӦ 3??/;ZjgUX;z/ \%uSQϣѐ[_y7Ve͎|fkΏ9,s)[e(7 BıgՑ ?l)\;&ZF },0Ĭ*s;Z >YTFzJ޳YͲT[ r$6  ){jm{8) `h89-( oNO[(@]:;f&2 8 dZc36 aR;R3k&|h.tO]U0݋b@+~%;j87sP9<8A Cu 3E1kj3˼L||6>ޒR7r~aOH/ߚ??}qZ ֺwikZx4~ ,j`Iļ7uXKx;J̈0gN~[g ocJ6a!)}p>ڹIO7#M (-e/\vF9BU(Su8Ϥl)1`0KhRPA9d5S=oK+'? UȰVt=R_1|_c4/e C8XwaRI# kס^0'pDJxc$#{PNGJf(uB^eZ<mHhe%~0[{hs1IdĠWsV;Ҝ I$0D3aM~d6C ohTɅ3)8E`O-c lۮZv$]Yƍsu 95>P)p\ =O%3OE2L8O#kѽW`on#2U~g)f ^ݳ`tOYClhq}O'|NA ~/UHm h^Uvw0WlTsd}hyv]UG C_s8 wGch*i蒍{<9qn~PbA>x֪j [s;- 5f ~P+ɛ^!=yө셹eƵ8؍䅀0tڞ/<8d=WX ǹw#`p2}I#s<݆FbVq$3fӡcM ^J+Wh֫ g>o>y.pVŲ$kM\}chp2G7o~Pl$zUd?"b7^ڕ+Zʮ=q2%wM=u?}g싋_LbZz*F`ZEdﰅǀiT V:fTիKcT:|3יn@VO~ 3ndkLk!J#O,y{-w悲/> W5\ڷ?~`oeьO[䇩 k87_'M;gݹ_Wp|tJX>Wd|RWp>}1tFyQ%-I fHޅ \tCJjb簵k>;%%Cb|N] ~,m}3v6:mˊZ ]l|=^Kx̎3SwR%P\C7xj9-3iFӕ/“l]G ɠ77ArTZĖRSΜHbnLK&֔q'}kG0Y-$ŁkvmB#O}\(zu-xN|8gB~mɞyI1H {%ˇjv\wMGVpk{FYg2}ڠ =޴q:v'GI] a7r>_xG=NP2+0'Wg* KXP HSaUq͵~6wUHĝNYL| l:nk)wzYGѺ]++W7--%_vO~1}G8l9~l-]t<0짿wz`>k݇?D׿c _CS3ZsC֛twdO+t?64rղ7$[/DSGOݙ~1mm ۻG Bd9 k%D{SLuZ],.NA8N/=_!W_3ڮ(+xG7*EFb=ME\䚎ůÅg%K^  >ᆰWgy+:-]c}BK89ݒm y[kE6ϣO{ZW %BW]Lvz?uOz9@N*pڵ~~22|vJɋuHҧ^AxOqEf[pzileI:<2;~2?w赒 ?y8:,Shm_DnܦkO /7|&bd/E'wKN|dm禋7nL¡{Ō.4X~4*F[‹*ܲz5Rpoߺק'J0v߸:hqێ ީ۫GEzˮ]1f>vs[K֗.zNOaID4nbzt Bsγ O:ׯ'~Ca{z[bRE|xMzQL7]|ż '|5 >:x3:;,Ƴ/|;D'3zetFؖoEqxl<#ߙV|o.<ޕDZňN*nAta: \1/ncqMWIpˍ sW+ߵ3Y^ ESV !0:I|[F^C@ t~Nn7Sx3CJM!ev) oU! Se/\ܼ֡f=;fFLmfUV}I>7v.pS O9ra#FӘ6cBȰO1r?]BB?5^{s 2X{Z`'LYh]gP; Z匠 @ʠeNeoB|F ;2 gղNdhYAqHxYS88p6={ 1Sl[j0PU̞,JU x>r]0vZml2u_ܛڌTW e9~ u S_o9 ze0ZђCyì"ƍZonCq 8 )›cL`?}twd01Cۇ+g!ϩ}GI 7đuyFBiW[ooOg,կAj-RùD0cqW;8; Nm]/|);f) 9oSqR3xB]wςw.@IDATCLem=9 8p)x{l=kQùYK:[ke2P( ]ܝܹ?f10Yvb:D0Li}Wf$øï(az(+)G;ף ӵ֩3c9=L xa(H*\5/N"%'1@B3fk_oQo~ڎ5A$kao])UʤzZ9rlfۚAq?yEfFu3Q p̅#nt6-~rJM6~Cik;] }Z]g3h 9$z8hFlKIn=i$ }mP/C?[.-xpX0kp~x=Wgw&T?O!CzPu7%p$_6mC9>I9t\z+\P5[E5S'ncCq(LP] @ ow~ɋ@㜰^2BV3VPнe?~4nK^p*Mә#qs`oPfznW?mΜ9=޻)aW}8SGU.3wSFU_9sbӍ52ȡqI9ݏX8R0^A;}Yc$a$A|+ϒ=u|$6/@Qqg`dD'焖FX0?sR@ddc&ݓPO>|: g~i6~p0{<9g' ߝ,ʹiG~=xݞd an@ɠ=1!A5j fKG58SF d^=&Ylnm^IEq}2 xNXvFU=Xha g+Y h `wN7ڝax42L~J/::s-]dBsd0Tbtʨo{UΥTPh@4Se(]cVv#kt(3;ukn*+^C_z[|Qm|(3tdqZlQ0w+ZYڻJ$r=KG9*=vi 3ڙѧF?J,uUd,Ҿv<_\ĴD.I cW97)#6mk%eJ3?m-5TW /b_8BcK;֍G]=}{YGVA*ϏL ,qt. >lד7f́; ~(!%tk!Y.;^]57?QYA|=; Br$gp-g/.5оƏutb? R)?b宿ZnUl`\?w<{OEI19Ҙ#U?T{^oI`]pfGu;ǟMϟN)ֳF:سUSwe>swƫ%H{Ndd̙{G ܇%[;l, J@@S= ۱o>GFw1$ZsiϒNU5#}^6zeo3mi&iє Ѧ=`ꜣ6g&lf1+hT4e={3Vt#tl莳. [jތ3J&u3vP†4/y,vA1F*aKnwz ֫9K3W4{E5ym##ϋ},8Yu*C~a E3/uF_ɮ,MN {vuLs8 NbB 2`phfztuWH 2o q`ŘSs{>Yg zt Lu}A"]2v`bȠt~VY>|舯.6>~64ͮq4'OpvlnebE3|Q::*t_P@}tgntLEDϳ|Oln*e m| :Q!yboљγ\.K׾()%aS'O N0ݞ=|q{&1%+ S*8R@1YZQ#)}(:<3>΢58c)LQv[W<Ӊ3uQH3X~;֢˟aqLʿ?JZ#L߳G׍֙xVc6K>D_hp ƗY~HX䫣O2}W 71NN?bˑ>GfCu}{J,O/pt~w'8SGBɰkM,1qsEe47z&/%⭥ǭ!qu|`}J-?@חbǀ_^;;k9KHȗjaTX{] Y6H^\6PwV0x EC{ts6R]=$Sf؂=Qg' ,JlG[}ϲ{^~/L_O?  /F?;Ӻn-]hMvYbxsѱ:rx֝#f$5{Sɾq䢒+zIOd._xVbm|ZY<4ߜ{.I#tk` Hfbx[ZWjl{QV77ɮ$ -,d4}ޯȵ>¼X 6O4^1mbSn4{W mzF>9 ohP!G5w\ P :\ynN@ 7m15̕@4_͞d΃ >WКJOr1FϊXp8誘=j1һZӎ,pA"+o ]ggq*(Ka T/KS&_۬Bl8 F&)yH& jArƆ ѱEiR3 VNm``ˈcoP*@~+Sš?0r[xlAtY>A=30wڙ "d@vkpl }~1F$=édNtsv~ؑy]oqHl"g\E@u L@J}wU[h") UF].sڅi!#A _rF{7\mO zvk[ު_&70\/#rT4x+AcC{xdԆ$mq=[Ftn)?m6dn.@z3iFFwdçϟ`ғΒn,PB`ޖYPR@gƛZ~Xoʵl`zP65eaNJAhx`e(ϩv9'7v Hgh/AEˏ X@8ħkA %XZFׇMzݸ%Wx_W.Y+-;kZ%l39"'%AZZ z5(K(Grk1l yxyh(]=xwғ" k=# t16IJkɾi$>}sn.N8>R-#a䗗<{'7\n]CUg2/5vo4vmk2@gT `$d2-:a`sњ;}6xpδ@uF3b2f[?8Qu :VUtkn۱ƇG4In2Sٰ .66=0~Mh A3وKF^&R `JY d]*2l|0PEk#8-M"ݣ2{wng _zok FGG_N M`ܞ<} jh3ـC+e?H-+a`ϟI^n޾7'ΌXG, :rd]tP&_y7/1 Z>؝j6cӝ}O뙫%DRvqW ;P;WUl-nxn2>KF0Qdv9NrPܯ߇{l,1Catu֠- ;Uu/U·M&nGZFO2'$GfSqFOxÞȣA3wKr4Tk}~ `R֔&C&=Sgƈq]v?'1fGa QUszP9^tws6?D9뭱nl!z8]¡f@z(wߞս{%jn~TIuͫ@U;E^}ް'Z"#̙ј="o?P)˾f[;nm1:]pa|O`g C 3RE: tC%ɡnM?|q{|vd (%$=v'c,Σv>d 3-5;xײˎ*t|yl[a:1% Eo.+aM;HFFmotեdm!:) a rXn>t7zd|*#`^%C_$+%.˻29#4WrqB:^ _rL.QaQh MƐCےlT:d/&Es?6ы8R iu$"Qոg/WëI7sݯ3]љ D~hma-&@mM/"cA+ܙ76ɐ$ ty/yž2p&S7g=_77*P1ocCt ~iS4p]Faa{Q*xrajη M;v?EW ۪+ɫk%῍A*^8 φ>?Nk \? 39s!h3 QuJRғY;諷L[?xݳ1t%A>K^`xsv`k%3g3ۯ${AO hDs',xMG\jزO-бۦZar^Ijo Rv]瞋o,?4\h%Xo$2 P5ڧtb717 }H%VoSGB<)P _wOgʻuwx}H:'@/d_?||rW(eV5ߒV=+7o,8wx.g:JstMhʰk6ٱ!~,1qaA*wɓl 6ӠG?(rwrK؝76*N i_>{'{_"[-h[v,a5Br :':x zQæB3t. qǐ=}oȟ잯+Z9Kw_ů ޚ.\::Z^ll>}ΎS7tښoIͿ" m_xdpc$vƋ.pl\Uě;1Lfѳ|b m oU~%6GO|w\I>|s=Қ=XZ"${h.&AY:qnO_d%VIDz|I0oSmhphIhu&,9KL;2hmH ;[03^T4Qd5T¾2\pwX}S8wNSKu.Q]2Bncd`H|¦z E87uc{\gdI:EK=4C]q!lGfᗺKHch]Sl{t#{Ae Id6"3C?>/B1)8b}%JHKgg·oFzImxmG4Efl Kt Tzނ[D-norŋ4ʋNϞ~w əxd>q;]\XF;>ԿvV{K bg)UUo/isvrE֡C?Uu޻dgsLl+򶤊{k_R~TJvNqBgUZ75UE:՛%lH`G(쀃Բl{nnor_wEtv;?Vf;DCcI^?:E[ctaG#d":Kߌ{ϾptˎUX6L7>vonm%c7F|y]>VG$%I̒CwFޱK%coyG d z!+l?>Eg/ _/.FdU/7"ud)o%miNG8ֱ<z]$&q~>JUhF;d1"a]q d7Zs,k޻ѣ:kei \=2>KAV#SўA!_ypr0zt86BtgxY|Ə%$wŢ%3&VQxlbUU9֞0rRn.|]2,?x6_u!;4?|a7n*\O?Ao~:\p…sU-Wzo@ӕg ҟ\{'٣̏ဿ>_bӉ|^zJۥ}f]5dUbF%r\u?GIC++Qw ˩yU֣cK}o.:Ȟ*}*w'TN8pl+tiGWWuo qIsVp1\kܬ/>ݐA\6䵀0~zc lj#ѭ{ fK]ؽ$J{gs\Z4D{|\`?l~¾X[ВGV,>xvHxj>+#]e`<^8qdO`?Lw`ZAP ]vF|Bnj4ncZ0j/pgܞg\>֠qhh]s3[WCf`R~ON W^{Hlgۦq 0AwyqPXUsF /41g!D/nN'/{a=Xf!oaF>X7~ Y]{L7ߞW-IMȥ6f>-|{L񗿞Zf7UIz}nlի'Cɲi ^[ ݜn;+8m%ջdCH ; Kx.5OGi*VͶ;SHcޒ6'5K۞ף Ӿ{_24nG jl ;JdZ+qE5@={DA{@p pKU|Z{UTS$xP)~}m̴7M8nl'1 r|"1p5dain"Y㢗1L_c_<ϧI2րΎPٍd#}xVwsx0}Άw̌oTOf7 3+!K}5gA΋Xg~$vVɊ W+Fְc^] ["(g7;3^X˹GN]`o]Qbb0;݊N77G6 H%$Z$OZ#˧Ս؛Jօ1;[JIJ\Stko}w>J%"/C|el|ƕ#l tj9*wB t [ߖd}C9ȣb$qbVxj9]dm[IXe>':'>Qɛ-h Z)7t w=\%hj8Z`KbȌ()`+y>x%8:lTAJA,5ܽx*̖lX8[fh m+f WZ [,Ntʷ4'sew_сW,-Y Ewoݎ{[͎0nhu|_38ڈ >"!et_n^dǘmft9>pӗv_*:M寇PGO>iw%\/YD4K ks"{|W/M )EIK+|%jnXszHLSˆ,ac,e.H|#sn?ޔq!ŘnW յ8]Pb!N0!PkTr/B 4lV¢12vP6QMLPn]>#. Ʀ}UNjI/ 84)Dah 1/&7 52G&VDh Tl%PƦ,  KBڍ"dl@`[#f=r@?iQBQ1iSRﲎLeڽVl`PBXc@f轋@yeVd}3?n7loE3 ƽ5~4ư6˭ h?} ޭ9 }Ξ:2eNxs2g](=W=ƹ=pfsoMQh1D" Nw2H +@>`r E H`Q&ret H PpƷ`2?=ܗ6?h!4OJ+7nO@pl8B >?jp52=)>~TpZ`%XgN-4~Qڟs[fZ[@[+>2㇁x|GC#؅@>mhHw̫ք0? efS|"ږxU ƞ};ڔHRfd 掆]`186y:ƾY_/y>C}gFvȒ U(مGw|P2p6V@1由#=x4|!m*I(OrhoAF!ښ:Fp|l$C$~F _/I6Q'²G;Ѕ*2HB Q24s^m-Ku PaMak}̸`!Oy|C9A(Ij!"Kp]z @+ #봵"G]RV;G[=>v Zb.r^f#GnȨmr8-^ANG'kMazT{&WbNxqddhrո%IY_簥@ߌ3x7wrύѷ@8qυ8W3&ŀ-mՐ9_xoh9sZ'zvR_Q}80'#w iWw8;CHhPb;;ΜŐ]HI\0p2?%0/]d*vˢ)vDq|#SF4`M]8lj[!kToOOv7h3<#qCɩZp-{`bE is-wew-X. 1b gG/Tݹsjfvƃi-Oȥoc|UHhkroz[ у4dⳏ_С?/|C Ϸ^_Tuf޵"20ǗF힣~M;cpF?QݕOΤU;<>=^e}R^+קO/_ywܨ^\K}M{}nAk7U@ǵN|tؓWCV8y"ǴNe9q4Ph8'yE#ov>> ȝ9y|ɏ2Gz}@j ɩc^. ټ3{v| yI$IP~g sG`9k%t( oFCo~YB6 >{o=g,n[ TClybߡ@|4^_Z&FQ-j+@gxuq_1w M\5KJfҩt1A#u 5q}>k={.:ǹC6yyؿD}6Ԟ'vr}}-C[tr%}\/AO?/#q[Qȣ_w9w>VRop$|x* nIz䉓 A5ӧL7oޚف"/ۑs7,G6O<~lTx=nǷ'mN?:S`ysgΝIV;w;yd(dAOyk:{<#xe||cp͝b G;TQٹs]JɃ%,/Y`p^?=>MOU}%ĠU(]qk/K!zHu%k]Mv/}Bg:D/)><ǾSiސ.^UhCˎ < l)@Y'Z͖hYy ~M6w3g!N9ArU?vM*A􁏵^.Z`??->Ćd?s] |7ovYabn*Zۣc&dUśc={{E1}:G~|Y`^|o tWNjv$ )ZYWX-[еY a+nh :p/#يy{o?,Бu.x*KƇ6$،Wͨ$o GMϤ[]+IÊ1Kϊlkwe6]g=a+>k_lu;~B؀$/G1 R Z)Ѻ7߄7EVq6R Mu.f;l؛snjRI{zoɷCoLF(crϝ]6o6+6Ck]G[m.^7 &l;u^y+Ȍ,$ȓGñAh#u ؟eW.~+nί!{@IDAT5+x֨ />}{M-O`-65׮OgϜv-`g Dg^.G)ZB/{`a=+%k8dw#ںe7UѢ58؛Պ?:h5&{^HVתUR+^uawO鰹O̭6dlŻ: MI|Uuni (ͺ$hp6mxM6hDaW;6{=Yc״d~d_أ]I:hUL:Ϡݗ1[m~kUZ:2Z=7cbF+rIFOۍ(z~ɜe:2+~\+iBYYo-U v779O#??F8a-{[Y"tQbt(xc Nܜ;1;wF$ǑW" [6-%@JgTaH h@8/lV(/\)(i9LXF͔QVSʼʨ= `ۄƈ~dHk=w@B-:;3o>~rt{gq6xk=qy@q UگhAƀmLI=pxf4DM)[WT; R!v opcF]JK4=~DéLhMymR( A8 #  ܜC17ABp'`7QA&lsߋgY֔,'e毥Q+AosapR3gUr>P2P83)Sf8=57q-Rbp(ƨ?b¼~q̳Kc.c2UhEXTL="Kcy0F:Zd[ -9RY1%  Go#<zgYT)ֆL`1zP/d0 @YH EY,{%{3g&ȴΏ7w{ ` l-e5c/G9-mZ Zhf nUN“ʶdgZ)O9x Yj=c[" s_|Z]d'`,|Vr^fTpY YFF$O23̀*Z -dc5-9phν2禸?:} ِ%tO; jM}'Cb\YW LB٧x4䪵N@w[kkHo-)LIvT%!y@W$9,MsIGU'G>٫|_@#Sw" ϸu.X}QH,+<~ ϫ$jsf V[d:n'w&|!Kf \ =c(Dg `PDE5 [3^蝑@!o}૾~J4ۣ ^ ENw=LQ5DG&͆<@7Fr1E/KV1.L6IszWK0GF$`U YpZǏ=mnLИǚ5"_r/BIM(zdh<{7e-xwG2ۯ[7&;uD:RO~:rs%ŮX '- ζ]cFF-}ѺDTjYž5x^`}#@ dKl;Ydzyp&,9in\4CoJ7t05:V{DX0cv]U2Vi P|蔢1D1TCn(+=)(d$8#=/ 0"Pɷ3x((#8eO:zllݪDzW{$WU/ P|>X`⃑叧UTSǖCϹdO>Umoه?\{yܹZs.t = H[\c~&N?\) 9wh._ͰZl* g6__ j_8wvؘtsO/?s]T'?|!$wJ-хsӥ%.~gyx3N/Զ7/H}$ZId~HvڪH~ܸy{"@dS}m-pf=,WJIQ fw>dzggmWd RGvQQ>.P') u^ :Dv5w/r}<?7Olʮ~7+K2)>1~"i|]6S5~/B sӻه/-63;j[Eɖnb7?n(gIx i)MΟRKƾO<;/^Rr$ T ظ[}aI1ڃɇǏv&oGpYaVVF󁶌Jw}V{ОD?. خ 5N?Q׊ Wf$PI9P믿mOJSWdٿ~1}wى#)E~2̏>8ɪϝ?whIKO:6 I:?z. ~OIL!#.WT>uV%T!KrRO/'ss%CGOZnz#N矬WGUG\ @;Oxr;ʢ1-9\pێep^ek.5_X݂e_3fE4;ylxg˭轀YI>Y:$ϺuI4Jl,(ǰj㷡ޠ}jq+'Ot-kX_W?+uUaCS4Ƶ-_|๎Hϛ‡)+=L.Dwa Hi|dDxQ|Tzsэ|u%SUZ1aVPw[<ܭ%>"v> hEd`Bf^1٫h; }"%iTwƍ3bOv%֢rmuRqSԟj"|ǸC҇s6 þKxo7銇sjrs$w؞JoV hhucFD X Տ7agt]7<]t%;|G 1U7fχݺuQgӽ֘hD?^tRI 4dZ? а(ٶ&ە0<&# _ؑ^?Yb"^TG =yVa滐%@yViϖMIpWm'N~~F/?w"Odͽ#%ӟ_L^KJGp@R6?}sK0:v">Uto7oլjtf# ?k[玙Z9ڔ 녎U:?I>N;ݨ?rǗC6gf_ ВJyBz|:>پ?{`&(}a˴<lWU`~󿸒Z#xi4LEn \n v5Vޖ?dI~i 2u=aݼ]I=$#x}4~|@~sVpiX*B[[|W0Ѿ. hJbH'nq5-wT+Uų _ݵsKi߮bg $: 7 ;G6Mo|3-]MWXy+BZa^㜳؜XuÍ~qپ%:֑uzGŠӱKz8a]ǧsr=Z~Jߎ֦:wwoLOk;0[z >ty߳ktхuM_oGUY7ĞLghn;QWpqu{nUd>!ɝi/a;| F^ ymZ>UDmE=t̵Q@}c?Ϝ%u%qǽ/6߹;>Um{nΛVSf? +S|s싟`fڝ5}-Q]!jQPbـa6U7%?E !녛lN)km2ucXB ˒ޚ_07V1kquf-᱐bsI`]ŮxvP9,xGkE+Ab8 117#-`ldA;ܼ;}KON' 4}/Oi`*[R#6fMۛG@iK!Do1 6cSu5ΐ]B14f@um ׏ NraH31'%> d*im>!+vkQZ;KNڙsxTԯRci1c sڕ"Y-8`r zV`mKk# Eژ)g%q)+{&X102$Na6F1b~ZG# Pr} 38˱ϲ J"g{^p0b̑ J32jUgF7=GLk8&:QNqGX췠u8=baL-Md˴(}o8:l Pk,?:$ <,ZFy gt&fj !Nusо͟GGZh%0H/F`߇ќGo\W j5hTexK42yȄ>aݬ;mъ3D)ߌKʣGH+?2_[ͭ=Pp,V_Rt~tݺfvecؚoI( }46z cBz6 }Lx6٦Rbʺ> c`hs>2U5sB:60MU5\k7砷7ƀGsp½?h^w5Mk$mk|ҹTt1w/|LD:baA/{]g_|Fx^1dbb_{]dk3пi ѡX8]H2|E>-^3ِaڏ:yK3cOV[Jn ]Fpr3Bk }9иN-ȐUUq$(ghv椝bس';W~G̺ڴpn+`_A+A9My*?x.U=x J}&[* &O7$<ǀ1Mk;KLdh:jȲxM_=tk$ɇYgku Y˂*W9َd==UVp ku 0,x9ツ Q{K7:K`Օ8WIHi*ڨmT[٦8B9nGIJ*5$>%Xqs2jOC+`aa 9%@p6~`%i(??%ڋ' vVv@9{[m<1-1E;n*'X.@ T{,ڰ-?Z43'I%!c2]Aې}Ȯ#W0Tap{g9=#St::>b[hiïX{.]7t^ w| $ v"?:tH l]=A. ٙ37xf7^{{';]18_֧{qiwh'ӿj/5p6|<O&Zq~*0grg裵rkyFY'K,HcNA`+,= &.ܸqkM;^I@oViZLA͛sgwW=x9cyfsx7}OKɐN\:]sI}Qہ:۫0?1GK'u歂{Fʳ!y… cLD}v9@o7v2TK[;UJ,?8ư=?{NLmqG<||TY`iχ=TdV@VZ^t|GbgG$_LudagKFng/K<"ozmUl5_^TF& Ӂ׫?xE^U,/Y;yf?. XZb-?#rM>vXu' ֕D~|&ѐt S>,K2vסOߎduCҏ2vߨjGBJSi ֬exM1 =653rSwTU|G_Y"dh nmns/~60ϣ1;6#ڳXA!_-T/U}Gs޺m:>LM@oW`:}\O."ypwPX"!DsѢ؛fOR|ͧ* lQ]Gr>r-v\ˮcZ@*$KEI~} 4&bgS5ւ[jKsv aQ$}෣tϜqKkTId^qϲ{FR~sVמ2V}=,仌k>Z[|[Da+8Թ}F;qKHܷph髎7Y XtBI%̒=vd{/ uAUsU5[cGaԝ|gI[Fg).=&mtoUs!⺾3y7א!K2SdnvEcÇ/ue[`bgvZO92M{P^_޶oz^b.g$?UT2GaM2q୭Bցe?t`IMOVdbG9u ~j:oO{`vLѓ>RYR'uQ}S]뵭Dxd_vZ:9Jwm p rGߺYsHse$mp x"UA_>A8w'}zJˆ%?ę[{_ nkt"/cSSr8lD~9yγ;\=nj/^"F̕Y.8H47FӠTv֖KwH8J?EM;amr3p8ٲGKv$nYKiC=CG@qamxJ6ׄ%<jA`u[k@bb.FE㼡ͽ_ CY{-̡CG15+F{3_HM_]{P Bc/Ml%Ĉd1-1zg{Qkղ%w,qSUo( oޟ漩&"ۭQ.CgGWXFK_̘aqp~lvːP u6-%$)]9C`TcăpTb~Ƭ*mlz(x&\AO Hmr3ѼFbׯ=3E{))hdk9 0N hnnJn89V Rø1p}=H'>c W7aR^ڛˀ@*}U{}Peb(4'o<{9@m8$c. g>O՞7fǠ4 c8` %'#y2ţo*Y9Ief]EΨ1qSx>2-%,d^W.^vW~ϓh58!>do;byuK3/_W γΪ?r M[ ޽2!=o1hͭcB=7i= C7ER2?x+ )xR2)a=SEx.8G6܃V08%g}LԤ!}|S} hV>(VJݬ PI9F9: +d[ڝKtΔ}l30i -GrgJd4~^mbS6޹ Esq@ p.K?wW} INԞ@vxM  =&#']FgΔ{9c9g?k$2jOsn|T=d% ?p`wF2uClid !i /xB-]* `g@xwA/a\#]>ltz:<Xi3l#l2h?y*b8tS~wNIdKD|ڽ{eS>׆Tc&]2]zOsue7o ݰH^djSg>"Ƚa&'ܘ35m@tth^cs/<RƉκˠqs8').6>lo.n2c'Sn@<ۃ.93\I GH\s7Po݊VFUR/{ZMn],_OԵ"<17Zi mѪ/L~]A;][{-7{*h\|+Wrt:Yr:va|E밭1y׮?2ƍۓ'ӥCKoG#\|qzzH?|g5wN?: $Mm80.~k Nxa=+4u1ƴ{s%h~¹tZ~^[\zu?9!K%N'w9 Bkxߟ/PAvnE`ԃZZv7ٴ7wzrOZ,ξhM8Ir螜"|R8|Ż 'c[Aװg@VPW ?y㦮2zG%,`d #F6)7\\kr4j:}%Y1aGdոɲ&9 . -׳2Vn߽uF6+g?~~^rmѵ.= dc5gW&֪0ZKhnJ{T ܺ}`okSLڱf3,ޓ.Ml?YgObOo^/q0;䳏?ws6vײe#?z= s킎%~}Gӎ?(6Jh|>qjw2 F_*ym$D{w|˾ j˃,pqà;t)͟!3gބ~U{tc>Sh;Z3`,d}L F} ~ H=Ll.!2O$dg1^io 1Bm:79#'; X#ĩ6ZBW(IhmȩQ3 ̉A~ +rt&>'|,wx}Y@RĖ? ߌoEZݷ'ҭߝ~4ۙ.X#ag "aGݛW`Z ;.kLh:7F҃J7;z΍u7x|E W%nX#\kO[ZAW[W_U ѩ*s딓/~/ӟ/k{uAǗ.k>|~܉^{l b۳G++ H\J><-A!ڑ@JuBg]tû{$9uIͱj=:?nSPwe^ųoSU7uy_RLG>Q.-6GEɞfnsYx&!af?dWv޷]T:늉w¹СHl!AW @Şscm$ZkM[۷OJTRž>75;Y9뺈 ylj $ IO Y,!|  \2³oclJP/Ɨ{:ji4Бtmhu/O>|7yu]d9orNfc;wb c]{J{ZPAIo^:K5}c%c8O{%t h׭}gO_MG# *}Z,unM.x[ }ntA]3,N3`GTb1Gm-qc<71ËGW&=W|lv͏adM:U7:=lNG &v%co6Y day1%7Ӄ}8EEd+^FKFwx_U)߾q-l:w|vh]vs;%YZ3@6"矞Yr|ɣl/] ^"uSX-.sǺHjMhW%ڃ%R`س*S*F~:rlF/ *TޙC༟ɩa Zl~LQ57k VͦHEo'8[V*U Y]㠪|K[Rdlhy>Uu1*T eض''1FA*UR,KɹB Y1 ȧjS,a`6J2lTIieFQ|u)aXX[9RZQRy{k/~̾㵫ŻX { #27.[&а8H2ebf{;+~ 28`pɜ*kRuKjɆ%K{_À!-{avCMYLc FAsZi-VE2sy5v\Ào},u%W3\*!Ӷ-]TS ݴҒ!Iذ.ƍZ5LPd~^e*y$3Z uáaBѸ1 =)v\eS$;۫vz tJy #z}-ͥ Rsawf-m<9=wF6 >Dcgg# $wuc,ֽ=x=<@4CK ̼}XƈG[֌*ͯl[ޯMKˉO.l]<===ehykzH|O#[c??D{h]XbM4eLnG?2F t3VBx&o!+f@!o TMP{[g( C=R۬ :sLΊikNnoNF&Jsx+)Dtł^_16/{>:2b3#C-Ѐ޵{7i4w1azs{W7~ mf H,TGqDn..d8SG~@z"&ͅ-=Q@eFZxXƶa1=3f8:=~`P.y(!ၜX^ |Ę9 *5O-w4jX&[epwy2 DzHZɱΓܞB=EQ)Np]A[sBƦ,qfz3 fkǰI Ky(h&7Bu sn۝]5Voѫrsr4|űfOrz0Tdl2e#k?Ue|(K f8R =rk$䄟:uv pdߨ8ڈtl$<^}:O?:GQ-F7.:xP3Gr|Y%V HkS'OS`UV<@(:=xlK"Tp8>$ڇpz J*ao\)8#qߙD o%ǜ͐^K]V7jdhU(9D'3a>wO2Law-0vUnZOT`-+ YsLxޓ} A3(-UbL܋-)Q} 'ڶ Iݑ>WS/Cz_Fֺ{̳2lfAgQٳ;ux7^/pIA*.U8DcZSe8+.ۖ#bq.b{_]%+9P%ͽH^2${`݋?t~(`{l $|{Os׻X芾ٿI6-Yp69~Vim[AM=ɵ-=I@IDATvKrw&#FrABFmjZִ7%Ʈzit!_$p]'b%S6/bjK͸ͷo\%<й٣/N9}{=ڑw7jU=X~tAowOa0Nx "ouO ڡvݕ_>RZ.`;pj-vDCvJ]01t˕g/~ra]K6럜9qAJ>@mсP%a3xNz/ˮ1xa=>  $iȼd>% cF9|&[kG1[>@;C/Cml]O7[;?}0AX=h$d*d(<}-P 6E X\ ?β7R|◱}7F4o"( nG+]ۡ}̑֞P8aߞmFAJc[)6'laӌaϭ{<*\FMvC.4Q 'qv_>ŎlR>){;WƾdA9B́ (X9{Mo-$Pʈk=l{qi}9ƾct`G 8$XwgS 4!ƴ O:am<q4K_#!` |N1G;kO+"t5_@Ǚw7Ty u*OiosdIyϹ)S"9/EqF%mmvBG|WK|/*?ΗЍWt2z|ܬ__'7U'ccz}3vtk)LIr6lĢ$Wzdώ1i1Yi&aױ -z-H^ 5 ;5{D@1?[y:W,Ry_C*upl;d|sYz[: Cmg@=WҿsKkޣ KtΓ~-ѿQLg$p[Z͎adU3yd[OO3u#?l:sR ݽic!"{lϦƊc)7iv⋒^澟Nwgo+j(yXɩ`rQ,>SjwX5*)u, YvWB%ɤ%ݠ1{&w3kaH7%Z$zΠ'wfub7~zqW}&;v̎tH zHZ'SR1Kǜ%Ov xe?m;[a7KedKt6߄I'qӗwӣq]Ɲ zFxT~{~DwHflYǢIVzUܡ9$%>xOg`Բ}( AYج"8ګmNMm{8]@`ڣWXSyJo/>] mPjt@W0218j3dV1|UhEP~ n\g0%@k @NcYQ9%-Ue)ec,?N` Uy-c8 ?oO̬>.X\E"$[z^xW?9>Gkc=VPh¡ʠ\36G,ֻIRףW#H;x(!bb`̨59z>i3 @2-d`<[.aV-)CeR^:e/.}ܷ3T@ʆ(ks:1CŲv)1Ҟ13^`nRֺf#y"8h0%!SP;#C+G/نAx1!U{CFwѴg&t8y2pH=d 'sȁ)@#Ae,jײ|jyk<tOGV[=-:/8s3, 0g)n_\6gYr=E. *v2vM*2s쪌ڣUȥ*(Xt&^y^FL Xhl'rb *@lvݤV8kϹVP Bsytb8ろz&zg @3Mّ)ݤm*"ɽ-Uvb8}W+"m`!RaϮA&RiFΚV>oljJ3I;|O2e/oZ -.j74s8})fb{c[́4m~ ̳v$>udhL[;8w 'L~3\c.Kbkzv.p^yq%ݔlr.(/3W@!\:D;ΖL ,0m{JqzKY@+ l]4hlRAK9ֽEod֜ ?k`oG^dX: 0Z4ֻVYr8}_ ln*GC.QGǕ/`/ׯL/i@Zk/5chs@ @rmDIpO{T#.XjaLDo5}PPu$`qcWn}5ΟڿLO߱“ۛvxPm),9wFqW֒@ ɓGI sgTEuz<\{ <gG`tƶ١uRyHViV#(&O>to1dsv9,uNUþYyNH+K%UWG?~|d ;W9 ;%*񹹀T&׿OK4xB>AKH ] 8l1Iv,{!HInt]pvPA-í+: KV$iSNRUG=.9ØUK2 ,/Ié1mI8n5v[-݂tċy𼄗-@cl[;t]ŃT*I(]kIš_=n2UKO!t*` aT%efQ}z?2H G:yJl./ z0GL։ Lf3ha]ePzY>V u4BO7bl`7m~gzM7,rfgszB͵4!v, Ml_6a${[61BrVkE7Qh5CVZ mop f iʞkT]+`1qx8 Wkhd" KR~H>`f1ٽc{23".,#۪dPzp{֍KF#|i3e۠#> :/m rO;f8^l 2|G]H'|U4^0J}*>NO#o*ۇtvjgXBemTG6K|؟s}<ۭgBKtd؉UX{4@~PwHjϝ7k§0љu9T"-G-NQkDeO<= ~s ||vvlĖ- ؖeɀM#?`*6A W\Sh$+9@|>k1.U ݋@>5"¶f'+'iaL[7𿾻reߏOF#m1o6^gw^0|w1_hyz_^kbƇATn?[dv$辪a@ϻ#_eˮ7Ç(q4\zQ>-uQ~>f2 cwŷ_O_3L~{w yqǟM7nߙ|w|IϿKrC?/V񜝂%pσh8 .nPUtgIg}鈒׸|I_ut%y;߱Vc@2QX{kUoT*V{}!Zv-#gA ßGI#GAc`'{0.?0|'ҭY4oN{@ X'[6tDFML" 5nQ!kthdBLNvZɍO?KZh<[}꽒l6J~%5/vs6l?´no6HMcҬ;i Ǽ^C4.G?}5F_N{f5srdcWPyK&HV#Lۚ H5Ԟz>ޔiAO=mhr$]:~F ̫uqGt?VTg>J^,ID{muܬp"l3'G 8'7dY<.іP]l\2?֦U|nݼ5Q1ܜuMp%ё7إ}3wӧE랊`̻Z'\q?:FN`hB`#k;톾QJi>|[7$f$h㑎Kḑfxq|h]@i͌VGbTv8Os_k- $\.+i=8@l4hc#Ej~r/N/3Jm=<Qwnd=:VB_]7p>#@= I ,$ed+E?eG)Qbah 9?8R"(`58 ? P=VA8}`8|Anfpv-v7kA a 9tt,;4J@0|ͻ&FXG1C3+DD[Q> -.HeC͝#Gxo##n6J j-mpf`?u@Ĉ@ܧ !Q l6gNE6} =UMsٷe>bjKMIQ.-<811U=KۧdT#҆g\T-Uư-ʄ{z9`ݞ=c-4N`ԕ -׻1vcv0v`,xxMf(zec(ڽw 'khc3n_QY o_ɾR9Q;Q2(͂e2\S:Woޙ5=[,{2#|}<^ v{h xbw@%ahN@'OJhOy?xHu*Շm %AHPyrߗInoG.$0tAMpZ8t@4:`a;ÑVgH8HojŅ8\!ctkQz@hjcCw}Ю ]H6KJ88tDrg{*^eezk'U?_4߮"Z4 PyY?q`?L7ro^P~}$訊\b:SrбK3O k/<=!)/1 _Ĺs૳g/}S)/~qd׉*,k&@{rw4u70ĉus@]e>I!Ts>>Ν=Z xi٣ɓb7o (*"Z{޽G`ƍ;O `Oq>҇9Kg߁Р_8[K@xdf s?pLbsV.ܑٖ{ek=x`y~/PڽعǭF~f>}{gOB=U IAѣ'#൴|~v-fܝ.4,Z @Z/-q}Bx&f5 tkH?أw^6GkDd9~v-9;xAvg/Ǘs9ٝn`l3kNUlX @nNve^$>n X]kiݛ!ir}\G6.dz$ѝ*G Xu_WI= ,#s7-HZ@4nONj@`/[SS |7{`~*=CN&i'vĖ"cTaGJ8 `i_Jmv P tMb9ד[p2Tt% j wqd4eZѹkkUѼLscHm-#bKBՖH;'\喝lUaCixpIW5t|ά^bT׻GtZ .ޗR?_ ɞgKwvǍw>A+kAG<^:h 8: FP,mEfFw_,ZAedL#r`N]$%?ܷ:ucJ:>:hÎ omJB~$Xg_ TtR{{ ٺ 6Γ' X%6{wg@Z5p {hc>AhN/z Gh^ܞL+V3?+;jj+l׎ [/Ϟ??< |\ZuV.U׿~x;6E k_E#AUPçѧ kN㷿d7k yBVē #J'_~Y/Ӄル߶%#DZ.9ޭ;;xٛ5i}b^Nb Xօ\OxZ?h~`b0z/UIed7#z`G۾7Zh' F (_s/ GgQ]3GY}tJ8P+5IFz̏ VGgkXO+aG;DpV 2-b _7nI%Ȫdf]zpaYn꾰-k(BA~Kz^!&׻tl^JC/JkK7ۨS D O. lIT5-ivo,m=bZ}o$ȜIkw/_9&l$O4XC]6WjnHulX>zЋYjW0< C$ٗ0QO_؀A} LtZؖd L ,HNhGp{xi-"Z _(:swDҙCv_ [޿u%%l:A3+LIhBRw肞GPP0ƕeCVZW֕nl=mZdnr{Vz:162 lb]pxe[zv,)yOܝ*ϒ)֭3svT`lUkF{<=&k!~?ؾ~<|dj),4v]QzE|1+;46 :?fs双1UUm< ><ý|;xK6&Cfw̅lr~zk:9q=W;J3y|kLi:># T^Q* G6:q]Dƪc$fEK{%\m⍇t<|rq4~BpӟإOΏʇԟ}vivuGۂ3=9al-6?:O ЅNSg+דۋ;|Ҫd_ roM0l:n \j#qtLzxD T? {w߮ciϹ091uQANZ<*9ud1~:wD*G%P#_&߷<1_fz>8]ˆh'C5Ϲ> ضzxwtDg%on.bGFEKg']yZ}_NT H3#.z˺5)d)}-|e7h &l]2⇲=Р) ՍѹIH.AmՊ&4.KbB ),F39F 8O8eDX;/|-0PߦH{ص@m YkG2hcckYp3Cc|%a0>@ac~:-$9*"Unuj2|w EY2@' (JT6#s)FG8v̲m9_̨ADя=%j 0.̩%%/4^mAG]ځOB|fldj{h{ɘ)@A-d=ȀѸm#P llmuSb |ΰТUg̜ޚP@1KRhF1Z@.b L&zycKs|E)ٽTelO6~XWAA/N@T[&wj[󌅅& %b&LW?#*$7;d, ՇSG g4(jk}sV3$T(kQ &@@d3-3CGT jG"Kt< a99<g!~(X;$p,Vbȁt Dٛ7U|2Bb"]eH[#G;ВI^ص-|5sg:" C=wz?+[4%+<(DW41RTtp X8R"vƞes٭e\*+>fۣC)N`ɪ؛d,92%k;K:5/ Ȯnٽ9<סH[ssPP{G;/Ds*~S@Pi&.Pm'M!g83nOF˒(v_m] | 92 3p '$_S=uT5` UŚ C>Gk׶<"[-[GmvgꎜkUlyYwdQə/ꭿ?~bf6ʑ*ު |_5ꌼG7kZ5@e݂gwݹ}sz=A灦:<^p@+8ڟ=_Uq@?sM|O>4ҋn޾B['ahYp Ξeg :SN6|1Qh=~jdNw~[g/*y[rU*3 M]׫7'M' ]Sp0ޭtluw8JP iO:?O\q}6?@vHyŮ6肙Nr9~Qx DH3=kZc~&[_v%̋z#:{ޘ2$i8'Zgv/G'ue ׹i71~Hw~q[rd;Pd6=ӽdݶ|U7ϒl *sc@-ka.o>GX֗4 ?с`ŇR,D dM>- SgI1K8(!C@+K 1'-W%3%a)- g K!ăa0 㑧 ;Lx@ Z!V/[Y~qKi=wo/wƻ q<ə9ϯ: ;WW@soCkԖ޷Y%7VE'7̀Uү_^|gu. `D'M:@Z]z6Oɸm=ݿ[w<΂tx \ k9ZaSߥ_ F\ɖi{iQJb:Y =5Ev%}Q=i o.M=~9|LuZl" ^aWεxu`Tu0#p/ c'OO'ΜkNmUl7^5$4&/GtLOI7K@ﻓ pUϐpÉd, ]q tA%x6pְdN h ,S"$;kΔ@Ҍ6E=qGӒ-v=mc^mhcЁBG렭K=/z'7=\@oiNO Nj.]%QH,aD GүaG(W-!~ 2 = `m C sTh=g0'ϟ7_@:nwe?ӱ: g'fd%-GxcKfجߎ sVGaN-Oi}^k͏,A [0G2 f6G)6o/wm9"J'c.c A;kg=m2:d'ײۢ_>d G~D%G_n2kN? B2ztJV*cqw@{سdf:3GBкkU&+o4i-L?m>au:;l1: cpdkY^c?G[˭Pݝml0/Aw3ڂC#{nO<(Rn{ulhZOQnG皓Dpfs)9" _`kyV6/u>W_ =o[z.u=?E 6bNVpڠ7Y Vd-qd[cX]lcǖsU&ASO{`~Xِѿ. MwȾKfm;-;th*l,f[?BhK l||Zy_W=O _CQTLWE&{vpڊ y_=ݼd7ݵ7/a*GJx3OgREъđN;=}Q+ũn?\3S7gXCg8vY@I-ƾ}ujM,=ϗKkuHgn,{Js:?_L幃[/^EWWn?oU8tӟb%?ث0Ltz0G%Pk bFuCe |OĺFr|N4ߘ$7$ +$}ۘto%ݽ{{4w|1:$ d -\Y؜.ys&m~Q %v6~'kśفi=S`GX)ueT#"‹lo䂤΄<0*s|b=k@g52#.=Hk?B:l8c۶L JG@[2==ɈAȌpE+e4Fo=BbР|fP1E%-5sЦ a<5 i-5B>Hl 7t#=i.2  a0:fM-[p$ Ay@aS*s0*B6}YcyRd5%U"øs V%!D$0Y`c7:\aQ1he_Z]<ԺnFg>XT}p¬ۄwծ|:7xqi!mFÚђ5&?قp:&ۆǨ2M PO󬥡dD 0v' 1t%Oxyk<'>ٌƥ!%&(3>s1@}"@1ʂWy@j9ד7Wl27L}f:CC6d:j$#LLsaGmDݻښ_jU٭z^V NyN9Gֽx:Y6sd^_ _ uoS7<5mS2Ğ*>忚9=xS2ɩGtܩh=&ٹ=h-TtrI< 7|[^[gÃ*Kod߹u@wm|R@bG\:Zt{3 qJ"9|J`4x(T Yׯ`>DzpڋIU=fٻnj6́H7g8~s nܼ3W`TvۑT%P1?ZٯWo: ; QpUTѤ0x{=sU4K*v@o7ktφ޿yFa;ë'Nl[F:[b4BNloZjtVqϞj/Ν{%X<.]LCL%~gCFҥ +_i/_.7V&j["ݹ#`;9g\spT~ϓᄏRζ:1'˵:Y=U3]/TcOd󰽖TqLQBÅs;G';<.~]j&GAS4v"GJ%l,D}v a'vrL߼/1\Wb)g+7T4:Y~aծw;]&gyUU;VO:}#9#`X{k =OkC 3]sgC]/Y8gkе@(t8>fw设gdޔșJ>ɐwɞauõlѨ`۫8h xY.BkG髗\{әv}Cͷ_} ArJ/J:ufw`Qyw)FE{vF)}dY||5`xu;M 0-pb6>>"zmϮ+2 ˪ 2BvJՕ$q=&lnudY}0hVDE u1`1بD{:9;ڽ֪XP^P̘T%~t|]#Y#ے:7uT{Ai5ws ›x㯱E EǢ{-%m^OFU [X<>Y[Sӧ?EܬC ryn/`{|n~9\$gGlNHel~O/ HhCĩ~vNf4WuW=}gIA|l,ٳaQ>ç nQk{U#ب\$ >UY(KoGK>nPR/|֧=w E sFrXv(d=$5{o!%9t'uġG62;C_5&[qҳ|%<ĿcVt+|?~WXwZp%)!(}#5g${! $ykUIc\ְeo ɀ_)uE V̺&y|aXAt3}U[ 0k ط#W$ ==ř>K!56%TmY&D[J{>]Bv~KDRkMt@`&ښvh gjo8(*`#u.> ,XQpo(g*$u fTB[^MlB8j ^]݂ у}7m#ө=u7z_G %njͭ%9+>6_ Zl#8Y`? ; nܜW/O0 $3%)'P (sãdetIģ@8@`g(M+H6 0S}ܙnj Lxg&´]?&ӳfZ֡w&n٤RM^n7?KGlr/xC\V]bA;:a&=q&7geC:[I#$%Fa|<9J^8y|Ϥ.t==)Axs4] )ߴb6  u|8"3'&쵚%Kt6cFNNVNgf#I-paI62nC~ڡ!yKs)L 槰\]]k~#Q_̆9Aغȉm|Ĉ>)=Nw-Kߞ\/ԝ+ǽ.7tTtoTqU~|s\tgQy4M׾]TZ4zzsjUOIRq|W*vh®L'ow~>hOޭ@:V=Á n;=}P"(;u"Id?tɞ$WhH@ОɄUa"p#`} 1 #7ړ+A -r2E%6[S2٥ V-ES2]m,%Bi0P?YƋXK2bf,Q1Zd05+~\Nu~OIim6hd>f oAۚtn7dy$t撜mC)}"jFxr﹞#[ R6_RyBHb?T'#5 y1֖N0{3LY\#Q3(?S:c`$uv͑ 'hXǜ^fWCJ^Ho8Ɇ s<9F;/} -1^In~Y#D_@G`YxA[7d{=h[|Ɲ_+pA%sS'kӷOV<.ITt}N=w):źCnu[}v./վg|~֭dWׯ~_t{]tdʃ Ɍ&nFSkɛʷ}nNg]J.U<\ָg}ҥh[pǀHZ`γ::>Dz~\rjW;{FKpxg_`M (/ڣU:=_~O'/n{.UKf:V, 38!8MF8DB>\vټ'(%QIvz>?Td`#KˣPsU,Wu(dnȁrs/=CV$wM' ڥ`*?=s-ޔ&t: 5>]+@oW^U|KI(ۓUJz a1`Qzq:W/ xp'R-PYrAroG&Cfkh~%^fȡ=ߘ6ɡ^|IoQGJ| :;) 6ͿgdXj$Kwgy7Uh)y/H'f} aEۗ]e% Dΐ7=ḗ܅3CozdJ !yr?Vuvzxt3otɁlŎzHo.DNj _8U '8 ߩŀ%~?}/ կ'Æo~?}zĽxht\ը?}mIE{/|i݃ZpgDo+%=P_/: KJ|Z3?׾l8&0ds{kB3fwG ̈=mf{v$M7тw|YZWPQ7>E=pd"E~tdnd[k2V*HGdzw]񆍃2jJ67$Y>.|ɿtpa1oAdKKZdK8J@g6k7H^R8:t%Ǿ P%PR6ߝO{FMu?mBgzb^+YϽE6pߑhuGa3wTqߎlv؟X+ɇCLkى }Tk4cg9^ NG=Jpzo)gJw6 fϹynIW ɒKϢ;?q|-aY~)O-$wkobnMTə  UN8f`pt TɩO?s\6{d~9N'S/aG/6/^ozs]|xMLrZ6OUKJ\̾DgKUPEȅZj{Q{PcZF찑HV'aӯ' Y>p+<ԭ v#2sɶl)sA7܋&:f$B :Esr Qn2_gk뫽ƻCO?&s7|q헿ɦ{+Ta^G̾|i됐=q=9%t@TO IK:B_{M$+dtZMfZ,Jn셾%5C|O 0(,,ZOFC_4u_o=DjZd 1!tv(qeN2" 3 tXn2zK}pH:jPOثƭ o/(yٛo:kao:QI;VTo1!ٞFo%8cfB ۜqLZ?=y-܊ @lxxN cd㺛+sDtw>~9e¾x2tr ӜnSD>j6C'*sz#޽`Ɔ RrjAgJ6P7>9=ixXҵ[8`zlgK:YKoZ׍@uvA J >~PEdv@yݹ}y Vlo @>y7;NKػs֐}ϝ+WoT'#s.\hm)`: \YɈ/~ ؘ>xl7\/O޿ZO.k <I/^ѷqJ@p$/], H7}p+~3tܻ *l/-A]𱯭ݮwpzܴm}~G@nkr2[WЋݡ]3}b돬xi[(;L`RC3zݛ5G}=;wULaHT#Tо +BЕB $aZ␜kž'DbI @{*[nȋt |gSъg0<&ƖVCQ~+be}@F7n~::: g_Ա5hOS(?;ԟ_Vh%w6TC#]}Zi/2=MqqI/n摳&HD^I&ɸ_asfHhA U:h_b$R7԰ISj^4*ȆMrF: ~[/^" W6kbvB0I]1AⅠGij8@{h255V76փw/~m2qe>XmOIyƺ^P9{Ɛ|D%T=&XYCh5*g RU:F$'  oAE@ ]!&K/EOy%׾?"iBAV zth(?#(C?;; V̀tj9N&k5 :{jD82dT j)S@3|[.1 G{psnAi&w刴f nd[s:ZIb |m/ =om✲ |yMk`FZc5f[y4hE MM&6]V l,?9=4\infu|ek2" Nb&[1}۲4ŭ#O2vqa3A QlYr۠.wvX#aM T7]~*'y_5iN3h>zCd3"Gc/_ ޵O 6Or*n^֟Wֹ~KƓ"H|q2@ғ؇ߕ vґ.&[G1 93LSEm}mY+Б"ykũkwF,vjI߱K=LP|\pŇO%V@B8SW95AuLhIc3 ^?^EE[̳wx?=GI]} W[y|P8Cٛ7؆C@Aulݑ֐<8[qۡ!?O[:CtgO>Uvk$MMlA3g=x8=ldJj9~ZgmfL~5k}}3aWt]$ nVg؎v`sԐu$aDudjJݝm ڊsFQWH 99ytUb6tfa}E ýtM ױ =٣s#/SGdl4K3vikN%`d)xCmw{'ձCUJn:x|l&xul3mq[FvgVoMk3h^ k_/+eowhŠ<~b%pG$ngBG)S k$$櫝~LN:.I}oގ8RӪ8q mSx5 _@{PK fmI(LTQg2Z~ZX^ l^;$[z}"&ZoH1#B\إMf;?DP aZ3LsR?&u$ >J:{vB_ dY]M&>&y K+AJupGY8X֗_٩t5#I>Q-.ўgq/9]&('1 CYnIl$^z3' ŧ?O@Ṃ +[L^FƙcID[>Xx</lq G ܫkl 1y՘IWg?twNz:g k2:>ga9GZk7(W8bGPgщG]?'P,th᪠=Փ3 s=n YvU(O/%-nΡ~l#ߪ\㽘c7D 55O<8秊1- Tރ86 <gwcm:?1qdss<@)}\Ш̈WzijġӔOKmGѷ2w=ҴUzW}-;N1fyIg@'Fѫ(ӎ+W^B[ am1OB&3΄3q A}5xu i:Q8 U2mU<rDg>b)AF8:7h |aGe"R@(PNX=q:#sbO )g[õF3k9hB AH9_ƀu%sT1`^@E`YւJ%@'B^HڸfKjLG1[^0|cjՊN} K31m3-0jct=f?LAu*rhs*QK+75"(k t̮(~bVaP|h)ޣ ]#öyڄ];┟,=R*5ZUҷ!>&{)/Zi诡ޘH@ &ֆ RưBƘХq[Xu^r+EЈs #VT04vB/̅G%N[5kg<톄*[ŧ7O^_~繅LQ]u 3t|s0`!`e`Xt> Ւlgqv Yӈ3q.p=M}pL87?= r{~f A甏Ґߜo|nDy㙸wj0l!KY+ݨd_㓿|7=6AQѿ!OO} m10GT}C Zf:B>p-{kd2lц<u0e*5mn=7E+*V 'Xؖg}W_;tJFùCPŠ`H"{L[nWȪ NomTMpJlInVUx܀6V%[g+o1V&N(+i:gT ,xˀ:mo V1knnP5ϺͷG` :;*9?|r*c6~ȶ-VK:Zyvmff✎}f`-gY"ɯ8<&Ee+w .Nr ;0xUUv6ukL?ZG^ܞe3WeMLfP3R^X\}I& !%3TM)ӹ=l9ݰ$E4f%kPӪ!"cO+ m A*~?N$x?UA:+|;)nC(oa:[!Ճp]ݦ}m?K[N{?HgU6]_&ikxkۮ8.Dٗ HEG"zEgk@ҖWc\|E%ߦE~Fnnm?/.R J$ O{;8oVz.rnCіڙG|mzv输R Yܥ!- hs\#e'V <|GҋO'QwDi >A')A /"|߃>?#9`%2 voC&./Eg>`]޳^LDY_ 3a5"EW7bk8z;@&Db:ȖНQdii jހ>=|͞׮$-p +V8L9D+LUʹjжk߻V+ Yn ɷMH B]U%FpyZ@iHt >Uڣ'#M;ߑӋ^*!ٖ*HYЉ9-$Ϯ+h>:ia ~NM2C~1 9х dx; >n~5G hqxWqYܪ.03.&A1<AXE`씉Q*CЗ??4aÎ4bgV T 39Z_AumP[,}|v޽$Iup|0#'/]<^q-$I+&<drʢ>Jk1 K!]{HzҸ6;aΑ Xs8p g }wIW )9sR?y‡<-YG7=>>9SX̣%k7'e|{o:& ,F Y.(d|˹\Uӵ @IDATyNhj7Pa;Z{v 잚^/ dV?gLITvmB\8 .c^_ /u˟lOZ4Z/1L ]_¿=ln3kj^q-*٬5αq&<\*^N{ձ;X9?1"c-cbT ҧ{u+Ha\Y+-Ń8'ņQcLpXI{oN-o?:5')DEuuUC6XNI1r;/EBvҨ2NR[ jnBϸv-nsخKasU)AVsٰ^w<[m!oKwxdr4[,oߒÙ]o`??mEs,i #l\4UKO[֮ TdTS|Z'ྕ6Q$kf|ay[ure4g̓Ci/Cнz&U40RL[GpVߒ 9}B܂;KtM'ěđ%xA (꿛Sx1 I j0sJdKSD کJ&BfAs_5 ΰkC({]F2.ѳ9Zو :]d10ܐ4J` Xɧ>S`uqZkh^RC4-&_!MO 髙T5L*rFE;}u]`rE|(qiɮմslRwe-&wK{\_Ft/櫀\J^a?76&^ >je`> 0p#),({ μh`dFyXQH<6sGM}] gO2DgQ`Z5r5u" %]Q~Fv B 683 L /1fU fF# ʴΔ: 4,TBTS0\6c8p 2+_X|TrL2{@;8d?b.u,ML!r }S ls ؜U `ppdկ@@(pU5m;3HgM:"dg]7w2`5MdmwK'2TZGUY80*Fri@"oaAc^rtHDwv0 R:yÙXae% J]\ag?;utۚ/*!:us%|15J 2,?9; 8ó[< # Y8M74ȣdX py NgŦy;SQyrXs,b?F@ #{VU9|Z|.a/IhՀ08k fW4t xzƳ`{!G8yF d,͐o6ahh{\wZm o4̨w>z L8uΘc12S@wQ8P!>^VӖ G}ײ-x\Iz0 49J_|'-Rm3 1 HnH}}g!Myҙ]t&)u0Mw*(6pӍB,?4>=;d|ɍe3fa"?7XG;sixE1Ƈ ZmRx>&я-2*Or0cg  'r [JAwS lV@zu$349c @~v7|dcېxuSU|ls8[ 3ԖnLA? "LQ#Y?`Y0=|*r}>3tjr~MbйF>T>Pfٷ>iow^Qvrx\G~X9|t]}Zݤ~>.>ggi}=8R WȂmeDݣZJxQ2pL NaVÊZK=B &P#Q.ACfB؝ "Q}3tNE#cU-\4ۮǺ :Uq+ݪ8-Kc*{NNٴf:W ιᙝcn0NMm5s %,YJ| hNgi]`$mme Tm뾈-,KVZx{JM2߬`F * 6i{]kNJa'G8\ґ N)1 4א3V+gv N Gɠwf8I_;~ʃٙ:KKK8'T ъ,e+TRr=pu8Qd51,@JsVH>dO666[Z$Xηzw$U |W+.tAer NAGBpF"`o7O"t@t[3jʣ݀bW mwd/u4f6pg[QGD󯟿D,61< Z( &ʂ k3+Gd[#wʊ,osH/@O_ ?H- NMގC~aC2;lw9h۱at p}8FW#1׵zLrӶP1ȹ`"e`Xpwd 9 3Xx}51 eNɀ'\Ƞ @]a(D^yڇl+GUhx=za#!Oʹ ׯބr>- hnۉg ku+KL~}1=J>_^^JP:=)bo_Wا9M\CedC@>oo3}IM>'Hn`<`a$d"?~DJ 610Ȇ,`sS#h`YAY@U麌#$9|kLFBgj[m!Cqv|pL6hUjw]̤#\?:H?$ +m頽 ۲xrNGk̀p" |2VjQ= :{^PHD5]mm6ZȨj`$M*ס>Ŷ؃yMd 9Fi[\L.3i^='B4a% ׭SI_SWA[c}H5m$Rؠs|u"A=񸼢zg{"k:SN}XMZ5َ/to< z+m@m{/ߋ*Tng=,V2<ww{ 3oiIa'_#q`ҬxIVjlŦD{qu1p?q]Yqth= hxz@AY~7%p:ΐwkG8v$'>hB;=^'|ސ/UΙqӹdxMKthxyL]$7YpGYh'mW3v&ͭџ :W 3o+\%,7)Y/1p^bN(f,~}IR-J &]8vd%ΤϫMN+V{N҂؃NH|}|-9jdX5w,TYi#X L<sE/Ld4

\< 'Smv*/|@֋!Tw4IN >P~S[.G\ BK33Ė[Ott-\L9vQ7!L,V&M,?g]^n1Q--DVF%S?ɛ?Юĉ#:tDU9Usm`*`GgAO| 3Ҧ&Xd8oJ$3RdBB/0(hq r )qGCAS!csu52oXBƇCPEg,JH6 X>ϭúx7GCfuּ$HkSjJ4B(9 Lgq>a UW)F`}z6à0 װĪzًtj h 2 A< G-'xP 2dBt?c&Qz |i0*8)f{ѾeF3U:mfxheg% c׈RHDu6] v3s^ BMNj%0SOa2.{8rn[>ֶ 6Ѝ@fل *ysf8D90ھ[Z%BMQjuRQS8<WQ) /ίS>y4PuFkKfH,.jzM*wt..5p~0TB7di }4} kȖX!eVA9/YhvFpraSnEϫs=ukLpL,바?0Xk.S-b09S&`b>ܟ6{PUCy( *{@wj ƾ3*QypLx_'>}շ!G_GdgZ{ G&z|Sg&'OOѪ9!\]*0̶򻀎:_"!) H~rs+kS7y~Anܣ5K|8ңA'^}LvPs=?kA <]&wzB6yY03(IyΌ3zO#`j7Ayd'{/v{c =O #pL86 Z"j\e%AJyo#x;LpDV4;%b{}7-^ۯ~"5vp+ hۛ"8*[io{'|MV3!7}{X}2p55KP6͹{ֻ͊5f}n??d}$PFzAS홅E蔖켮aBghϮK­mk{3-r3:7}>5>"a'5:xC-Vc`ݽE"'\1 DP 8k0jx} "'yVT9EM y$Mvh_n &59 W l$}쫕|ArMtc WxKE|`m]$m ݈}ȂeLqVZBٖ'W"ԉ%8_TgnT-,6@k.i7Z޺DyH8& V:Nq <6{<7/a+~zG扠Cz}J$,hX1>r嚶]yVWhǶÉǩb*0G@p3hXՉ{tlBB:Gӑ$֤cW 1m L Ϡάcǡ 5_{Gg6e6؋:y״ x C3Gm,'3PYD$n8(5d< J7}&hkh߿rۅ{ݕ{.Vk0ܒZzlwEZn3-rhl0}IFYt%J$͒21L' >"gHنސMjooo] ygGхE 2"dtv)ҚR`jxl$WY ߖ`72zqn \6=g,mکr&dZX߂s=;7l^;Np '3+O Bc\٬'lډşa* pNCz V0]S绽Iw*W1f3%X0Al 8$]3}-.Cpau H 1`7.SX-l!gؘ`bg(>uH& )9oy)]+p wx bY -e6,%oj_)[|.}7y39M[$-v:W&}iIV;gBWTʌ 9:vߩ y9^(F9y0֯eo>/U *:C&īcoy/ TϬ$$_XxC{Y*;;q:Hz3wnKW~! Xb0ʹKً'%QA?FzɰHlC[3MWFldɶA.3~*bЃ>i1}Ga<8sekmK%!v9 ѲIǠZÂkq\r/J8I~`ˠwg؎Gi ;෉=|҂ncXyydI9b\}SWvvuN1xzLyEn$Vv$ӖvHwm⃘h Ơ]R4H)'|jL|Y'41ɨ1}}:gz݄1S[ tú9?~WGƉ oO&g?wHW &6707[/#o!LH!aDԤ.o#v/S,}^\|`aM^S"-WP !w'<'rMg}B_bVz¨%b/MSʛ+Ji;PhjjIvfۉ#^N7~'O-Rd1-sN2y#N8#s/D ,`2wYV+gza҃?kY,a?͜/`aU=(&k({.gYm $h :2 HĘYAj1vӂzBc=FTÐ% Y]da *50L@8CCs !,ySy '(74F-QW EpjF%1TCPVFBz4P@4YV>>\^XB?7Z[l[Љـ4em̊vTfWeWkdD!7iEwZpt6NiV^H>:| h  XLf%AFI68 ^hAt^DƳp5܌˾wAr~@;ʈ<eNhB+]\ %#=ˮO:P+ٛ&xOVv[zA5l*fw?ۛq?ev+-zɈF~xk[,HY(9w0 /ʖ\.sDV`rglu7A7-Q[:btӴ%R)#of 한UAȆl`97M~Npg޵۲+F(W[FLŠ}&`6#VI5VbH{ \1sӁC=<#'@ed]Zt/qzohs97uhoǜy{8WYԪz6'+w[ȣ )-ٕȽR"9*xN g3_92PdH4AVY)&y]_hx'yxN ϼy,O2Mq$ǠYc 쥞=3߳, G$]>?'@Zڊr \nHT ly`j,[L $Cy S$#qBp`ߊG-Z/Q]N p,iݎG:T 9=)4dÌ֖2ɶۛځTKTVȀ 9#{J+B&Km-zS8'^G{'mVS^6,*l,CôvoZ;3$Tprc/ 4daG"2A1/3v?sf `SJ+K򮾈 (΍5hq~8=5c`JL,$&$;8L>Ty&ImQ@73UڑAVK]fg YgKse|bL&(׫:{<Ԡgaa(-fZ-*Nܡ7F MC}yq,}hkE\41528$*9: lybi&-w@g|li~pyѬo~7yГ=Aΐi[-pT*Bu{&TjAa{1 L:V ~OlC"&:Ի.y0ř8k7.d  uZ@ؾ\q3y/vB˙qj ^`<.4#̓k;BMqwBIƣ%͛PACڲ8.N.0a2ER<鴵:y#sa{lL:Yx 0fM""}ѱy:Rݢ3bgMcs?2Qj#GC8F`^/"vGTSùh_]% '&h:z+Aȑ"|rݮ }1>ݷr!oLx%m^}vwb^&cqCc.F]hjckJ>;FYn|khbgR6:)dziS'I_0.e+M0Da$[$eAgh>Շ^~ŐU(ow,UwlK: 1fD9(TGlQ&]d~@b{뗸A$D\@}}tc08|a9pxH0~D#H̭+M(-)p㴁-Z4Z _p;^8FR~w*wt6>h שj[fnX1$eISm/i`wq]V䂣ۡJ̗RmetPEjimq3@-L.Qyhe%xNakSsq&kkO_1JɘH2Ihz{"~zzD:bP`g]&UE1 3W69 &^zu7}hNcwܚ\3P1za|& ?%A9w|/K+~)D~2_253NSA#Y\G;l"c|uS7rpYظ֑~H .]l p,#gKܤ9;"@glҮd/*"9WF_Vi[hI%߆?Y%Yc3=@֐4SM3 "bRe(ح/Y7d2;JZ ŘN\js#r2 3>w7Av &!۟K0Ѭra* &p i:$g;࡫l e-xfS" ١*1@F3a 7uxOL7µ4 C,>d Ҹб %ZmT #kB 2 5ޒCfv7R1J'S@@Y">"P|w=C(6ժŅ`> y彶}Α<ʰ& R‘&0S`ՂA *9 ):OU ;|Ϊn^A'!X[( IC:Pue%oA0((l lfΜb@ #Kʄ { se *=+4Ⱦ òWffl /.讋5Y% 5yA A%WIf x,hM{-6K@xI'Q) >#ߙ'笞 ܳq"a.f *e=G/nN2 w =D_̞٬OxT:p]ҔAԡJ91ۤQ]tez8p'Hę>P\\+A횹dЌ:Yوpk(>ҩ)iL=~=>Gy.|#+6k³]\$ޔkp\$^g "rs\{e2,v=>t0?S9JVeMM"2*C`[~yζU'dL5amMH-fLX5@C{T^v0HaR9Dy 4L7K-ux\m8CaHtSߞ"ӡ8?4eq `X}sk$&ęYY^7fw^o\;r/+0ӝƊtşK4+0td~x 2A߿)[f]d((zLS:/v7K66<,77xß8.a̲ak9**57SR'e>g7`@'쫶#:p~qw쬕cc<^Ɠ_[O T1- 8I`: Cc=N&"jBpynљ,KCLHE: 0VV͔XlZ>td{uH]g;:|`hA~ٝ&pƬ@ mH/\-L?AktArpuY2^P [uRq. Ö(-ao9N#+mBҲ6kdrHMu on3_{_Qq9MP:! \"]V;{N pzjf+ V@uQ?<8}+  ?ChY6vзtku;6;س=*۱E:/yvE1Ak[Xs@{NJ͍U}F&+gཻ2I'ya坝uy2YX[~D9ۯ}{дAQ:~%gBtT:#[,XsrT#HO[Yf,b'Yrm2UCHPu6c0|b6uf2k 1tb#I~l` V+ -ZrV"SvmPZ|VlÇ*F pMK4Porsf*N]jQxNpA tQP8wDK$G kˮ:~_-#V"As& ab y܎1*K4Kż7:*a0>9\IWtN\@&jBaT+QՇ@9p ]Fke&exC$8΄l$ n.xF;ۍLUɨqos$tޏzGgSWDkv*QL3TlFOlo`MDc$6V?Kjohh58va+9VąkGoR"W#GQ>w;tJG qcF?s4tkV7I=.l8ЖNϱw_19!vWʝa1cܓ aiўvhg5 R?;ǎoؿ"]F>  \DΖ%ɝ(KEYµ釿j{1|k]ҝ翨pe8S;?H6@?NDuwhN޾z޲7[% ҃:qG{;Ou: FUcU;b7zW"gxrV|Q\XG|B)[x^YBv>{Xo'kҡOEG_*4Cb*`&H㎞~ M'1&l{E$Ƌ"mgexG6q h?mmqLWhsW^ yI`r`[~/ƆIc{`$^-|8}iuY JfljDî 9VgzGuxM?};~Winf'r;e0.f8{Y`/T:@*hoFxc{QQԡ1q`ؔ\ VI lͺdNɽ5$Kj .#Y0W jVEkrfiJ~f!>-y\U痟Wdh@*@JR55)@kq/ T*+UN\@3I**'=<>, *#dv1jg-]-OوsMR]|1`x†@]:D4|$DTL.itsMRe&*vxa/6NV@eO'V(CB|#MB6ҭg֐ qo&U-΢GP\3o^=T/gF:{ʀy;ucmb1xx<ơ2Z'Hڶfp~i>"GF< *d4cuY5; kM|"9pJ7V,<,mML#TmoA3Y oȸQT᭾~ >/Ǘ:;5tr]|(ꠗϿ :(]׷D!գ1Ϋ5ȰL(c#!2PW>t>֙yc+1Co;5$([u e O^L ^滭ؕu4dydr|0h1+ ytRb |*K$4q ^Ƒ:&1$} JB\g#VUs%>Ý̔OydL(d=wm ı;0e2߬Dߑn;~~ Ru=]Z!a2kE& l&?a^#bRCWv'reV㳑|ʞkgdD[AA!G"KZ}xsCwyݠ,`Y̴]DYi"Poc-GD2|N ]a_^0@Skt3xJPDP}z>r<:|[[Ks|53&iM.0aE2\yHha4(kI+V3b˸ |%:T ۂ3Bg6Սy^?5pQi^+hL> r/c\Md7 {_*k?-m \a >3 o9 ]5i]*xrJZnadKZH__|Ml-f$~0*6usČ7(i=ߠ[52!y! NaAY:##K89}dN=;L{+f$Mv-T6{Gs {׾% d>MFm'`0̧}5י~o SL+W0-g>jP<=NQc?4|}7߉3[{WNU+hzK{uzac4ڗS?*!&V5{2]}3_T霤 wPuYnF;/, >v-W966rVrwmo]/:8=Ɖ+WauiM᏶Pg:K.Jv`I~5BK3p~Zz)EeFOm(o3Dhyvr3gSRl68c.MahfVUkܫ-J،gmO˫mMBfW;u`Z7k7˭,3]h:~V-yn\OsJ _|ѶrOtٝ>l?Pt><+xU޻lvlo 7O> :0>zڃdGLbpKI<4f8=/*|ߖc˾tç6:r98`CgxasRkjϻ⬺wtC%,dꍂ{{w\b|-YϢl8d3r!޹?]ARdRk[pQ:.\{^w!o x˞G=`x7?6&8-[#㏘wtp5НW^#au6^Oޢ3;%O8 r -;u@Xv[]۳Jn}^7ĝKlsOxom_nsI/)`_jlտ_t,d,vNP;aǰm$o^!-{[O2ʷwϜ9^s $jѫnPE?˟WL*0[yk9 \ϯSAra$\OiMϢ;] V.$I{nܗ/q/:Z˧p8{1~SZҚ[>ugv hٛC+Y/w0g!2NQ~6Dີr [ _|;%;I5XQ^+/\#2 = OxI*GZ|{.:Em>}7fG}{bWٺZl_.o~scváT}#FMO/k/q\r"Kn6>p2g*ff窟ݟ/:NV;~xױKw\>\ G=Tl"]}_ Qvid7뾻w>5WuN'凿֯8ڱdpt+mh2{66CǗٽײ]Ts,KCp/}nVv#z}hl&ӵ=3ْc':CIhťrq+1c'W]ɖ:rPwJjhog2;PrjwIZ=|={K&\Y6Q|Ul𖍎W; Cե<~Rj],TZGaޚثs!]Ykg^gClL~U(zNM;vIu~۾CҝhzYZA]}y+_]^7)q˒rt"uoXێhQ.R 2r@u|5Qٳnt"#ug OLw Rv hpP8\g`aMd. |A)[V9 r̙x-DVL-bHK2Z՝eʴj`1F_$8tJ!YEs%e\[ m1xשB;%~ QL"n<_Em[A: (pƍk+A0ʩyo7u:?6ZR6չT['RY '$\ l+եv'[ n{ ?bP06s_v4鍪%pDgᩚY ۚH/ &GсT|idC%i3@|p -.hDBRgoӪNљ᩽p4/?_KM);J;U M 6G]JJ3ʼn#z{IX_9r22 ~eN>. wN45.G?!_f'= s*[7xlG8jq0ڑ3 Yn=^O_~y& ̚t*iM@/4Gy?tฟ᪎;KDܟ=dlq`LArÎ]LPu|%ž85ӻې^͇<#z{3rژp@F_i@vm_;\}ptb>j;|O9RjDn yVɛt_I<*pNcj/K$qDXצu{ncKBq4=bV oR5۩s%ڱSdstS2j7<9mu`p>۞RrxmQcpyMг@[;p:,ȶ^ʷs/:VV A:D;K۲u6L1%wlc%k>Tsr0X]-D: '~r$k--~h$ث]Ul>kwC+2ڵetθ_qg>xwԪ6{Z#/{t'⸵>ƾ%y&a{%!faGoܛ7mO:f.g S}:̫~В7w(3{?T"hQ0~󋁿;Y7;N;aRV24 *c&adEՅS,;05yɒ}0YwFJc﨑8˾8[zctڍx.d|ܴmMQUT;1ԭH@33>짛W.KufnzMXBsD#bx1>{4:^lo GvJcpUآ:O2^ʊ8&±f*$|n˟l9/'.f-66dI'[=$u:{X̽W+ּ:d[s^㻇k!8!ɞc_ Q%$ SwdلH/P),>ӱTK6#pcS 4"8{JؠOKF]*o/~9)&.wWa勗zcot_Pݾu :Q,ЍgO~c@_qIH3_:–Kk#.7N/˯}_~?rSvo|k Ξ=Sgŋ;:v)ۏt9RU7i'^Yξ?Zw~eGk'|pNY'ϒ*xVݻS6GN?MXakqh_zU=$o/ҧ`-f$;zoɖ"b,VzgGbQ{*L8nDw}xUpk}~Jƻ2`tb@ 3@3BZ6̝;*.\)8F'18K198?B=HR*N@>w^eC@9`/m01@la՛9%ME35>x%:?*R KWoNlۄuALe2ݫ˜7)x 1po֌;DL$ >E0rMr 2,g#]cz^zkU-3xOf 1 ZmoseAHơK P 5 G{>LC׮Deق[bMza9+Qr? ؒ-8&e ɸJ Nc+S&jvfu&TFXeppn]Փ2&Ku=טּk9oôEmÞm 29;(/ku@6k&>֖) %pz=| (<΀h10rs9 }-]MoJUS^v̺;&ee7͡=푖SMiȶoд|"KUev/j㱫Қ#wV;6XT,oYm(cKh8cW0fO~BR2Qx8ԀZWTVb>7QF@ic\RWx]т3ιV=QKk N Uia7% kt8Cia5m;B?Z8,|9__ϕl+OI|鼦2SERshϾrN 1<ߒ.r26SFùOf`F_?*px,~P,?JS9,<ke()O6p: H^'}T(#ȩ'U1bႠfsfH8V/AW[/.j%#>$h5y#ihMn7MkIk1It }X.y-y GS1N.*9yq"ZxOU" H(^"nogRFNՉ4{c%# lZ`Ì]UssKj]x %0 I-‰%3IǕL&%]ׇgɵ.Dgr Z=3~s_VVrs EӏI ^wz:IdBMq5yį,0<>g/g{/@e.hhtر}%lH?V8`w3Z|e5< G{~[ANSNUypӐN<5FЋ؂w.|[7f3N svՍtisفދN7&$9M8 =&=-]Q/,S|.Vs9z *m<&OdVsy{um}!FšANfb y84/kµ=;u{-/gh͋ojo{->*|q:0%L4w NC %%?KWj}ڣ?lꏞ=:uРn䜧uzTZ=6/)OPl Oji0ݲuS2vaFM*3I"xAK[ipj?mMeC1 ~ Yblg6 Ѿć2x"–16 ;t|h88g~g8Zf#9_7oש' t%y+ҍ1s{;Xɼ_gqvKhk3Kng}z\L?*資\~J=o|ǎAP) }3@?ժ=YG5p ^}>Õq3ҪlHmOuj+%AEAUG?'.9@tB2BۃǵG[sg8f{lϚy3n2r  'Nht@0{M5G'Ӿ;pw]0xۀ=S+W8*{x<_w4 ɞuuiLd"mm81_okK+_7Y-c N{\fg=^2 {NǾ9@ K~(q x(_kI{w*yQ8씇e_}PoW7N<~w~䫎Xxqrۢu+E(dV᾽I,:Ucy#ocM],= .Xlg[oTU$vzprKnOw,_{r7拼S;] _/O|?^uu[idF/J`Rwˑ./{PQٽ?戴m%8(@~u1+_ S_uU65z(|Ï7"x&1tO&_ts@;ɷ5.6b/‘b5&FkrȽ{j۾5aw/7=ȃpG%.4oWE/[v$)c ۤ`ɣtJ-SC!b\i9|_|#>HG6{áؒAm:}ޱ!z_}팇s4eL~ (SC=<%^Zus/ӊ f̞)q"vN?XG

U al?oQ1K<Մ_"&cFSskYg,SRi1XaY]cDm2Tӯwp1c.Jyt#[E$}G8ܼywY<9яW^_gO*NI2;< m#z. 0X.ھ{ӫ_ ph> 9p{[2- 4{giaivwG8&Fwlr(*\1"Zb1 >#t@ 3uqT+=YBd 6\p8T|}JPpP@cQr*.#MfJ&%BٻE8 W[7x~A ֠n?v6-eka6#M@)AyE]!+孄w =,g9ЊϊV8n*EKtuȼD`T$ ౷29 `,|hd`45 JS9hes50&UF]a -WiKe&?zghc3z;V4rBX#huq'vSagRA7͠s%eg*tV'+4 1gȾ7J-<&JxUܧ' B#w\}JzDi'H;~aQ8ӽ;XvȘ /ϩ^LN[X'MaJB%+MZ\Ų'yW_{)KKxr * JעG*EfH"n\0'.5a3- :ꨅV4ڡب D[hנA CaZnd^yrͳbtXs!g.&mAjle~ΘiCI'׌KTb(#{[*l&hL9(-<٩R_],,1- (XQc ʓ ZZ4lN#>,Y*xq,:Ȩ̫븧_KJqWY<Q" 5멧(GQI%U܉yGƟhkܢu7k8/ꃏVwEg&: hX,W[ Qz)@"vpalCBKAe;6nuyЧn$^u2j4}y̧7q5R%qXPt v7 mPIVf%`wtzkL[fFd3̜ `T89ϰ56 |~Y?;^ 8_,0 娾S__)W ܘÀ9u Kk#snd, ޺q0ۗ&$g޴SHH anM^; P*TF'> cvz1ӄe F=gWH~lpKׯ_lC>s.$* #q+^ x K8[JRWw'(߰I$~QE6%$Gd*GzZ{$N$&{Jv.[3|h+\zo|-Ѵp`Btxm{Y}i7k@bW vȪŮ*F` tO%Ͽp߾)-9> AMk+x/bL?o#坤rl3bld̷>0 w̯q)2O #+;33>sO2&|cߌ'|+Qg6 89cgpVPntzV) |}H27<9U\_,09(G{NT<G DyuY> +ͩDϵ@zE횪x?~\}8$.^x|OR~oG}rcyD$><_ -)⫌keU)Zy ;[|v{$ٞ]D1 g=^2p fquY̚6K>| Տ@v)Ӕ͏x79fC|R2= eCSKM.@4Ç~Yc$p--_]$hZˉ;4-\CGғT$>.\|liŞfGP(+k4 E;Wf3P'/v^]o?J!gS{נIdʣF nQy_nG [-r-_5)Nu|'~&vWmN٠\6e [MA~z |W*3gڒaI; M+9s#81FC%6ՠ*Y =3aT ﴋfaO,SֶWwQ>gBױ(d2 _[1[%Qer$I}-~뉾:f*zwt&4ZNeEa1] Hdc/4>?gb4 v?cP珮zyV| w:t ]0n#_50mb>&< {j#@ V6cx^.CC.8|EBynٙ1;G">)9ϔvw^NA12xm/ Jy3eu5ף)bg0qW1rmu=I ~l<]ƌk ܻ{" T#< }Ӛ)z2ܫH-ZzcTk B{G7&2_]e*n݊qj45J+{ݡrgf83ތ.ϥS%J<(2i kgpP!A>ӉSV2`CD0iն:l˕*i`duI½= g%DV RZnx5WP2]`'c81z[:Īo`HB|Z>jptE *e\Y ]{c1Z֦/ L'A@%ږpH0>6nW8-Z32*P'!B=gi*.&&<җNɑw$fe( V@_Κ%SSY3*zϽ7vc:~:ֿIUEPTK?}o4+陗>GӏERwɯ Stk} Dybl8 _$/~=z[źVe+.uJx.8G1c7 H5 mTi4غǻVn޸#\0|CweLNOUaH'\fս~K?Y7ce=WkAth$=qQ{Rc{Gk p_缌^%u,ڻt44<<@[n):gQef& 0~s/F;;ֽ;8 7#i׶9Ys 4?6 ûP[@IDAT)U$͢9kDA KϽrNm)f''ҩco/~wA`@k{:h_ݣo2xwl% +I-u1iiD+*eMgy{)> ND[5gPB H.a<ٶPFU5 .B ّ yƳ&Jߵ_CXԣ͠\V9 R1΄O[e{=ե徾4xH8xkZ OVaȩ8Xe :vԓq?H^;wy(ΪϨ G$YAb3ÝiaW:աF$NgU> ces*RkH%un#[)2 =7Ƒ;,s+?m-4-0v;S~'E5gC= evtcI|#p,}ϷD=9&8 :MЩ|zD埶J$56Wq؞ʱ%' XX fv;9-lgkmzK.LǮABpÄyPѶ'*ЃV(e7%hY&bi`| k ԅMƴS17[~W|tn:|0|yD283ìpĂKIjjMKcep c|2[Ymǥ+. rf}I/Z֒4ppp`:eԡй 5Cڿv@WT0 c Rš%qOQΕbV̀V(σw;8'`"nǃt x/[d^3ǞIsߞD":gzER=g:ع{k8fH`#Yn! @YG LLAXKMbM!EK؛oW뵬1Ч*<>kl l 6Tp"pudWtP/芞* xɃZ>~=pF3G,ԱYi^`D>Ay4$g#[~Lw|釙h¹!%VXڂo@g/[zeWd0NłXrB'۔a0 QQ *W Vr"`/v4uu唶<]X 兛xH 7\XH]#`6;*ٳ ?۬B{ Lv6 iG9Ky|.>gȺv1VWQHϒm9Giڒ;>fb~LeARg,,"P|*O)OV^he8XS$X@mU;I!C+oWʗ(?]| q]|j5Ld'N󝣢[: qAsyN?] r^^k:b$gfԻeuR/3 g577{ -TG`oߵC} iؽcK18/ٟ"v$gL C $46=w=ϕE046vnpkܓ]_W3Ϝ@=|TaBw$@QݮIwOG7 _?wQ3↸ ψ:yp<ػ8 gTY"Hp+maΡCknOc#[ N)`-t૯5]FbC(@OuCY>XRt ~xna|Xf ޸~5yi|5pއVeCq15K)$S/g/bISiڗgeL'="K|=S4)ЊA+k7nkƯ=u'$Zs'm2kQ% wq^ b/4Y ٕZ/|˳Eh3b4n#[lܣ-gĪۮܫ?=9pЛc!&;@{̤wegZ[zyFF2~^#iGa ;x6}: YX M]r `ظSĆN} {yX +е>:})g@EM^=a`EEv)ETgS Y?9hny Sdའ(;$+ &LJm4 *;+ V DjЁ' QpŤB 0C4  $xIJ.ϼ*.%JV("As70F寁]Ƅbpekf?? jp`Dh re sHU!o1`/(| [Md\砫 BxT.edgGw:M ^۱{94 /VtpRB*ݻk OJArc7$<:3ʕ<ߒ=nF/ͤ'lΟ>J|7OoVO_+eh{lA_ F잠ugւ)_NO>ۡ,~& ~t8<<8}@^/9=PEרf|' ?zޅRY`U'QAqՠw+u4]O=Ba/$xM)ٙk,e8Z+ H/Cރ_n*U&TZhA>};j%xw @Z+=S$w<}C csX:3qVe0 1*$?yPz卯D`߉wEI-NTU hw(C*N]=y(/eL"I$׌ &a|jc!dE{I@*-@oy(U9] ᨂ3G>=K$,VZlPZӈ\@!qNE߁9dJ 471>(0>`@aN] +T7Aj7`'aAe|i[pىe"A3}hB l ;r{]"YIe/zw&}:^p.*&ѱSՑάL1lj`ߣkL:{3@⁼H=qVT)g.y?b Y4D׊ٛMu/*OKT"Vۏ-Eqfe #Ačj^ EUƣ>=c\ЀR Ɵ/hg"4b+׍FEAm7P{N򸱉jP"u4h6uI:l1F ƀF֍e~14ݾG@ c8)aLN 7=bʧtP/,)Lj'`5Bod+$TWL5rj6DEN>[ZZɽd }V!C\w™SO"0ƆGXGvLL&9g{{+xg'Oq\_ <[C7Mt pUYm@gL@4eSʩ'O~ d8&^ӀZ'Hvg@co|`2:@V~Kҷcn ;Ogϔ)mΧz*:RUCK|_%v 9؊NFR4}+MЎ\7'3 pR;Rنl&ܔAЋ>p.<:]搞VEr?D\]7Y920jUw{:sػd&zJ[dY)QLuƿenU>ʒ>tḒKҮɁ8M }D0iFmB;aAQa<@N|Xʤ]MY<%8glnk繭4F;9$vSw:D@ٚxGOW40Wxf~!{}ܚFF ޣ.{=_YLoN 4[_Ntǥ#Had yIagWd-\Q~߲WIw85|㰗&L.gh*)fȻ \왟Ϡ|$>(Vg~,F`!$K ǎ_y{x̽JSR U_N썁v7#nwmcu_39'mSF%ocր:@̞A4};ZuHw]ěC pfS؄HvѿZOjC"}&wnߌs_Υg-&>;kAsdזeAzC ;L3Rb uyePwɮ/@vH7YIb $t8|3u~Pg.v41ѽ[A`y*Ga82wxnj&D<<ᄁkˮ1ϴb3гs 'n1 _.+febX €b8f2+.TwOVX|yv?G `1 `uM0ޱQ: Ja({4fxJpsos҅0~A6Fɳ@\50.ـkϱ]hд4j2%'o~i{Дşl(.+&Lo؇q s[|-\<[XvRnMRH<~XnqEPVLd~myʠRr5~c"~0k7Mm`~mn1\Cã$;FRd6*vĭ!P-͆Yم}i~H+S<$E*a 0U4o'/ "ژn30__W Ky("D$"9iq}v]d6>Zi@2g[y"=Wl|tKc Liq,XL`?\͹vY3+$%لw*_ nFz5aqcy / :u4mU8kNY*JX9睱7<5B8khrrU:M)(V춦@HK TYd16~UT.ώ ';(Kq#R?~m/K m2Q2i`kL۾Bz0@*IU!5`O2ȫLFAZe > *2#Γ,"8z 8A)X;{9`H@ʸ[ev~f sw~N X-ifbb4N4r]WDЇ=*@4M<& | Ũtrc$jB>Dt{wH@XgP z@u%JO'Μ !Fׅ_IW.}Pfs< A#ǩ|9Vr. }Cg`<ձh{5ufZ)K'HEE]tPJs*(HU( G`+{3*2V7?UgLh5Y΁ Tt6USɉ1ln٤^bFpΖPUjULP!ݡ 24@Si/d=x^Z8KUSBN*u"` ʥ-$tj(O8U¤Gb(*GUjVqpiΣ\FPwٲ*>x yKyt,!񦽓Ly2f;IUs5I\K:tܠ.z)6C=5m1[VTW2Tg|Ic $Xϙ pL$ku?AN>w%uƱL:ȵ F* pݥ-) -c%9 I6#y{7)k?t|J-\TПgƇ9<3E\R{9V:4|}zKInTyqޏ+xO\\g~&0 |gG ΞCy#ҠAcuQJ3 {Mdݾ>g;!le sr~־c< \dtL3[ŵeK>2Tg]H߅Y&焣@;WG^~d&26cfwN!3?~ksSe:31*;70##`k Հ4bIJY]h!gAj;gkLpT/z\#s Qۺ$z>G}u]~E-v5̅Z5j.|6VIԟy%Y1xcxC{sG{<SgCY_!CX?p6QMX9|i/Ȩ+  XӒ'|0tB&\5k輮-*sN#BAk0!y>[]]QlRs8012ihTGb)cF⁺4U`*npJ bMGYNσy|>}֒]e ivV/бɮ*)ymݘzx3MV4Įյ|9_%&#].WϑO,Qm|ѝhЫך(,/sҪv>TF?]R?I҆wۥLvxep"X?jZb ؕT^c6⛝"t?m"CB /'(j|k1HA+=d]N=G;#YMspᰑf788|!;f;h,WZЮ ҇ՠ^{j2ֳ \MUX책mqmydIWv39 +#{|Ne5YY[H?5>5 Rg-/bʒYiԪyI"Z^97lk{2ݹkLk Ԫ?.r``Og,aso\FWd>^JfC92x_TuHPd?ܵ():W~D/M1uhv׶,cFB16+}Z\&9#s޷+&g}.]:?x`fm<IuCKೝM0ͽ#KUUFvuY&xBɞ[1BI؀^ l21|s;F<BWL(< Eݠ7}v_d9hwo GEڥuʉ0"plRp` a YTNUG2zZ2BG}*+d(|e"~`@1€:nU %b4 fʴ ÖuVzp20<f!.aŌ/|'mH hnmGoʑ+ NL=~uswGOeM `jkn%eu03zo-@ 6,0`y͂RP>*lMVWJ *iP*KH&a-R`HҭSճ bP]T,}0%c2H_^g਀a6(3o_"84ޢG{*뎘?xX OAS[n_#y#58&'I4;z2*&b嘂AsLۆs( TRUɤcMOO%xWDW)e|:?V8*~nV3_ LMq4;1ZM* |;-R$lSyP%J CL/??8_x+'`(M Hu\0z^ gsԵu*& /" 2xi*#3r4VbK:գlb8^GT `:uCS!pz>4!ys}]t9J]|ߠc39SGڑ/N5Hۿ+i#G{3Sgd[ZN0S'mG ݥbV:(dG+LpD'w<d/XtwSWOAtʶё23{]]*:8$qQxb!V^nl]A~}R;ᘲK.{0Hm/~~D;(N3 t>؂oR1>z)` {9n$#4S&3I⻕dk6ẈQ(zH':]S-i}iAoeo sttQy0ٮNϲK )֦3@j֝] _*}id2i3Qds%$}U\.+B&iJ(Yfm(@bkQ53~%pX5e=//ۗ5ʹØK|a~߯x,/i 9DŽ4z!@}~5XZÑx(IpԫGtjHKқH!1dԖT e>M/9 \~Aŗ:Jtn /e ]|;PLܹcr[a]bkAKf3<6eп/ p*x0 Zϱ.|m1WGRgEqŤ';e*\::& VVbf $OdUO8xpSgQ 85'D f 8u m  Xyӻ vlla.KI`z9܏|$=dr)t֤ C̡lCY GXN97x,Q^PCx []];ݯ{ 0kgbQmmUڟ:@(rkNg/jflkU-36<}n6<jMdgTZN_.^;PC:!5(Jd@4ܵcIUWrm~A$KWGǣ#c!/t <%:3J{t&8  5ReU~$µwE[o!/KpA-[Ѩp_ffF3⿷7ոeeuT>&{ 8qB[a>-LyMfd?N>St֗bSM-.iw"A5t}GH8`onfVqyv+S1kb(Х*uh.Ot4bn59m8#Gm!Q8Te=90=$ℬ'6ڍBi^^-IO!gthTgi;uT3^&Ot.zctrҵT$-κ*ڀ' #(C̺4ݑ:?X Eɔ҃WG!!H<1q) 8u*Luv!?~A"O[{М3MMs/A` _Y\Vpġg)3S\fLiޥyʱ湚jlh R `n߲σm L&h2%:+P[0-ma3~ =x֨s/i'h z$\L"'<ρ[&/#w}$희*z32rq "@^j/tS7L![݋|RVpVs>CsAL-+ύ44|BF&ן$x5+3W`Z3›߭ypb[jYWCo ]#g`JW?Y<0cd;LMO2>]·'۞2&2QָnÆg;00Sʎ1xgAcD<sԶH £B>Gg& <_>e=̣6_Rvq&c x.p{$ź x={yy$C"ʠ"s 7ߡ?VB 3W,9s3H9//l$S8el1` T: sNe ?ұտMzqBSyDq~;Տ?F&G\S}~ic L&X+-iÊg݇lE&utvE1H{W7~34'/5*~ N{O=9I4 %3 HK|$3+>@{fW̵%UoIk$׈-L?KW+[WIXX_\06q;y:6_x%l@ǜ-Mg땣k{l#nne}ږāE&-xVOrAɺ | 7 <]_YtSttfNY]ׯ[y^qX35eN&҂q5:a]Vmyd8 _2(;әyx o} &#ȃ(%on,AVrlv19v $#зjuu}X{wtR2_4צ/6EV.Ʒ->&׶z+(j2G7G/D^ar_@2vj]0ijR6^c+6U%~Co`na=~+-\Ƌ2ؔ > _;>O6j-V+"yy]Fq_aؽ262L=:wƨA._ДzQlmkkEgu:@ٓZ-4mIL:A8@8*@o7lCp8|_Np~|2-7. Y HhzvN+^}Wf=NUR:MZ 6m]V= 00-Ye*:tZy5Ž8aJz[A=m`-V.Q@IDATTX=cfHL SM`e]&Tz?|Uu=w0mmpd2T7LsVsd힄6w%jҚ}jrdFֹ]`H+| c ~` g(ϔbA^xM@컦6?Df?$S֗tD*f(=~TbE2Ӫ`5$.6~5)P;7C =N?s9^z (6ڥ|6޴;wB:~IJ0CGKr:ăS;-{~#Ю]N˦y*hNฬ6}/HM?Bga) f4h$M q;xdTB!%oX#huq:=΃T48gsnLWu9}2?r{./~mR'C:UHLrG |}v@8J ze㴴'+pwl} vW5uJB*YƍJa$@C9VjLm2Izݠy: ;F`@;wS-&lZ]4xBD<{1eTab7D@U5pR7~>|txā3ϑPRc8Gb<7kGZ{gXpVGA>h2?$M4^|Ͻ9o.xBd'KҍmT!{̱ /DBMgCZDa%O1l<ƖҹW(>;qL50"_;v @܋|1s׫1 mЭrz 0& :_ 2' iQ%^q1? hO߶2F|v4agW-_L3QKŴA #u^f Cc仨'2'_:M]yc9Ep\": s]+ 9ףaF5H{-aiv.YL&ǨJLov4΀Ԙ)ɘ5h6Y?! +fX )/ om6(}X!^ &i_XIS@w7t"]+ud.c5nr:2[~\TGц'9A\}=ڙk#9| rd|D!O|s DDɧu{C9U` O'ok?x?tZ :#dpV1:>vnsޠC?s*M[0v{q7:0N[ǁg-|S._Cr_=_*@_g4I&}tc&LZm+M[{gVtxa/-k 1I U:+)m.Axy6)_tZH נo6V t^bKuxk:W&IdyW*/.{S{~c <9Pi( O /U@Yq8P{CcX3dS۷ :K׳4PڭZR[O.:wE~AƖ7 ?rY;6:Ař];Йյܙ lm`lsXOGQ۸otd$OIK {I^:>|:r x6e8#3|s,K2Yⳝ3kӱMgŠUAà|;CeC1zdl3^G?Iܐwy]_"GrAYHa\iĹtfITȍ 8 r`p0ॆg+3̻#$Q6)3})`]SM<}Εwnxzz\ݵMa.9PM4HkP0tA`!@]Ga"POs]ͪ{R<kxV)|5Tp ~tX)cL&s?v)ݳ[֮ۮ7S&xϪɼ]ez¤Y4d9L>$'N]Q|{%}^{R}gL7qa ĸ2/z9+dTR{3"_˥ȣd͛7??o\W՘~;(@ssMX,9Bv>,AؓX"\ q= w-;Ҍ2[l`=&Κ;7(5շF`;-tJ|k/8iTTw9#u&J9/m5dgڵ3"s]ΓVW^?${͍kxSC:pO< up: =CtߓZG'u+=:obA%Z !~cCOgDžBc{t!Tu[=E,p-p͊*?˕o)tOVl>j.XPT ŗɈiOۭUդ mrC}H&)gOAN}ȡܼ| (P>;r\VzUz,x5$C0(QB /dYgQatyP4[ϳf;|ަbCM=`i9#=Ұ+]ozV-vWhCGͥ Cf"Q =bigs!Z֔t}8! Cv5v/GȒ((^Huũ.@g#Q92Z`V 3ZCCMvV\\T~K&u/ `$ h;S0#vn\CRF7ocvE~K)&2") [w{Z ~$j|=즰)W{L m q_&HBx'4i_ w >1he?ǔ$kOb[>`ij^+,^q%gFz[V=_Cr|k s;\xEv4v Ûi?aN]]\`3a8!M `aҽd2@5x]Usw;YHX2鞃]cH&lHՍġ莊,-6;t(kogniy8u~gZg_!EP23pe 1àV`D%ne,FgVX9HK @#1f= $l:>yx3 2# *ԖgC&> t"LSdu8i]:&azgTTiTKXğ5pц(2RJI)5>tBc['込c , fTj7!h[S36B,3~ߡ&$?`H8%1*|yt3(n"ȭ&dnqv/<ݷʉs쏹{gBZU<1_ALpWP$2u6 Gυ^ L F'l=PKE /W!`VrMkO$4As/c<G(r?8GAGs CJBGo ]q=P_g.^cay>:2HN8BkIP}zK'ZwNȐؚkѭ32"uj fQNtUu߱P?61X//z %/1Zk=H8586y-2͚Ķ.Ӻ @ zz_wG齟Y*:0p/;w3;?i']mId$+Kڥ-&F>o3V!<YGBJ܋3`.Ѫ`$ؙ:;3= hC1_|=zgKiKmv]6l@=KZUSpT:4[dZgmo8J1zHqT?n}~3}=No#GTf/: ~0棇qܬ$!q “v%+4".gGKҗ,e8HGJsS5||ܗ|07O#_ 퍫Cs3r >k*ȒmUpZT(g_wJ9~koF]3n2jZ-eAB^MhտXE;tZ'4rob [9Pљv*(ѸmʅPgRefqJ 8'$u>VJh$qlq*h8VUa>[hq`w1Ghi/^EqʋsJ[҈F:$W>y/>Je]җ[,WĦzHiZt`n #4V%p้0:T@\7,KWq0+s+]҂!r Щ\ر4I%\l"}A6LdyV;qtkk\z,P% f Cbߕ0X&m$ƀOyOFIE}7h}6Ax`* ,cs4{Xt-TCts|y&zS69/H&cmxgsLaCѹ#)s_= uKv+n5]GBxIXz$7X\#5n;glq:Vɮ3K%*d mnz^ Mϩ'B<#4ѣk]=~::PTx'lk\G-v)D/&ӯaG-q`=yx8N}&وOl ?эWš]H٫^ӻ} ڽ©Ϡ`Idj Elzq씣#-bżg/zh3 }qS MހqPe.HЭK.g6E埰i얢2O0psue~J3\0!C6P)y4'WG&<H:VY>7']G>$`jp*E*FA5.< |lƆ-*hsEWq0s"ú z&pwqTWvúK/Deﵻ_5 v:][Kݥ]&䑫t ?֥Vjr!3W^X^>.̔zנ3~ y$n#FGgS؏V:OX-jy|:1k^&c8wJf:B*[{3y]M̺P/ʻ 00gdu(4oWPeRϘpf2 巁$Phc%tNob/~ '}>gqf-ǣ&Xq}Zാ&|Z[˥S 6jM8nghc,QΛ`f?wyv[~eӅ$-u*LRIZBI$`@Sb5 Y|!PE3ؚMt1deRajߍ lB߷PR>+ѧ38d/K~AYMݖ?QMSLVz*|)P?4fg<k6eՎ/'f(пt$ndbz| 4@Hc&>zV'L](M$Mvƭ#-:tR|qs<}@]>T^}-|dC^yU]}s6(nE4פ| #6~iY~Ey n{tyf5>o_JoeDFv(灏y؟RY^^ǡ:[݊gJnb+ؿ$R N,SPXH EdtƗ K k E2yypoG2qerzvXYJ<;{TOSˑaCe [MHA/+{/ XG$#5Gdpٚݛٽ&iƍ|b^Lܥzswt~!7QL°|=pwq1r *J.Cy۾c/I 1oMVd>'cwG(4ˠW!cH~*FC~pj6y\LFn+k~~H;6IN*=9{꣘Ï>N6^;-XCQz ᐝf9\cd~>_hZ"x.0oI>td|ԥgT !h<տuxwI% vGw~ 8ɟaMо}! N-nSy߻rU!:NteߣXE_a8PUm]xUsyy״$i'2@ AY&\un2ma^;O}5yNT&hbdwWy%:Τ/2P;br!Z;ǘ=-8k:ҳ?bJ&'X/PŸkpG| guqQyb 4_ȫYCC/ &loq!n` p /gU]w ]J].l\%V:%u*筢O"z8#>E:mqr4y{R $fݼ/&xa$AHۚmL`o$}wC2F'1.abb`P>lB<]fcG;6t"\3o;qqΪ 鎁\le"NC5|A6_:;M>bp U,5tuMs^rG6o3jˍrߖh Y^lY4QQun)ջVtАTVTeZS+C49t˵HSHeW ҌBRF{ku<.%[.n2ޮU*NuK&G=9c:u~`l8m |LùaRK3!Xm9'~c[t Y N*Dt_=R/B"uF-\Aw_F$W nmTD* M9pi.S5?@vYjշv`3IG\w?IWߑMV]`= NT' Nq6/V{vE& 'EvAI=<.x"gNvVY3dT^챾Y˜7 Py(Hd<+%N),ugI!cMϩiG|91Sd,hbEy8X!SG2EpH!G:"lb/)f|sb, 5<@. ]%d20OS]"9fG]6lm'm]tF| 94w )-s3_Gj jMRPl%:f86vF=_MJU({O8Oqu E2GϣO_2ey#&w=^=bǤgm90+,b7ϲ ލ_ q!X8,3ga1_W|EMT[_տt5AhWosLϿoQ"+4{ (7%!wyr̝[N/}n¸;Z\po,Gw\C 6@k^M7b>}m7sr*&ye){NW(LJGFiolH@)찓@s`/@1Oyq@[ |B SL XܫNY kH?2D؈j֦6W (lӂT^7 }\w5>6~ [v(mu/w؍pXJ=ָEƣTO@4=zlhcǎIG^/# {m_g[o]nv)xFܯAؿ[r)ԧgP')C7;~{`dY&}v^lYjx0YF[$,!3#Dy<jESf(b3FCh0D'%HoGN(4 BX\a(CRrr|~0dyLQTPwZ͟WwcgהU?_|0NR΀Zea> }8^1~6t8,sq? LLiv̪!!b7 HHx92bp=2{heNwx+nN8 qLyQ2@S(p2aE4-$63PpFx0`A۠τ6Y" Bi6f[Zڢx[5~ig\YUEk``! ʥ(yi4hKػ /eǕz8S){;prC>#$jt~-"bֹ FVr"#W׮daINY3QCikc}{Lt9}~ZWw-@2v ʭ5_ku!>=L8X\qTjbh"%V609}!Ӧ{%<+ZHT ?UƴͰ0. }d,93xI QѶz&q~oy ^UΣ.ԝ#YL`gL2/3%ΆnL:hgh{m yZzi, m#LL`4)Lg΅ oÃj&(^ϻ=xm`AEz@nG86RG'6!zNƣUʑ=ҕaDdBrLwm8~: '0\vMx< ILv1|֬USQB5׮\ Y%ϲ}xqK ApJ5fc2LRu8{Sc56Qet| 3$K8.՝=;~:YwwHgS;af8T6y3'C^ ]#p#A'} teKesL#NH48!&13k6`y:I *LA>zB=-j<ʽ7Ʃ ^Zm&tI[fzU;b]6WHntºQ+:I{kt-oiX3TgvBeIp3 Rc1EZb"lCX+;z4h}®cKo7 q` Vv@%Ųy{v?)'̠9B: 23r ]̦nX:`'[pڎX(OLa8 ރ{൉0ACG@$AJf_eGۀk3fXhC>*~ץEՕKH:!zILkעffڗ2I[h҉/9!J;'ys< pnn7qn .>[0 g[G!gX1~"ɚ ګP/rұ0Eb1C^.N~ʼA(:ĜѝCyZ qꞸҠ< s᧺ b-"| f߬Nm~֧QqXEt"aXghË3?du **1`c_Z+'L <'guDaidqn4%0T>(_1L{HK 5l[KTW=Ϊ?0`j%9gq]2I# ! ߹6qW!}n@<7A1(R_5W~i$hm+/h [:xG1{5K3~c~wC뱫msތ9OT&y0oS@>p_^!1Ŭ╎/}Z!/oWβUʂ)Sa.\;B>SFcazZ_XFU@#ɿ{=ܵ;Ojwßz܂.'=%JՅAow(R 7I0YΙvUh΍g\I1֘w7k4iiטx>T&X~Lڽ?56CGgj3Tϓ?u-#qfÆ\{|1G=$;:wN(AE!_-ZvT78,^8:>8ؕ=A+u|OWoO"_yjKtSv ]GB(DDUuS~YQ;y^p;~jz飒yG]\L*SlM$׻L!NQuxU'gDHJ82if?޽ /2yed?Of^TWp/ *\^|9nGeϞ9zzGZ:kG^)+=3y-{ґ#I/}dzrT)H]=@o[wM>pr@8c9AG~,ݑɷ'.5'|:]|>,?0JpbK5Tj7`.Og'':]qVR'q0@NWRwO_H FeÿvФ[b ;Ψ: z7xpORIrڑW-g~ר X2O(}w/ 0`KzRuH/?^M=8q42O{>|1kQJ\tbwhjY1აma@>9:1u>͝2xK4PaZ9 QTv:plߓ3t+S_E ƇT!4  _j:t# sf߹>^-\|gH X [{]y57 W&ݹۑ9 wDv7}UN'|*h&|qrԣght4MJ0 xŌ-Z5DYX||PҁkpҶ-||8?Yxrzk \cBfk_dN!8i$h]v4@m!&M.gc-H䳏a8Y̎v'V݁#@.N#[Gyܮ^3g'"rm*4\*1:k;7AQ!{8<6gʾD:Mi8~X<0 갵ւppAc`?oVN2YV^[ëQ]6Q.[ׇl+Y׮\wjF4ЭAe,[*p6$Uu#nԿ˱';hSC9t[`\[ յ:hN$]' ]}償CLt_"l+=glj R9"w`MBǏGux}\M'SJGnNX;yl71il B{ie Ya*h/~<*=t3@07)N%vW>[q{v~)Sc$F_8{NeE ɾ)͚N!$XUAā#79NRCP IC/G"V̍XN]S+Wuc1sԼ ~މZSЙ+ԩ}t軌Y]hySfdSct7A"/Aŕi2^'H{e p3GْM~[4`{Ykش*VBbW/Pҷ h"38HN +f *ێw'b?\y׫mVϊU>S9z&CĐf?Bsw+MxgGY[&jCoTUCzt-07t CFIdܞ*KP.ﳳxT:4t9 ȹ[tx>}9H?2A&K_#Yr_0!`ol5 gCWt._pO3sv_{Yg^:,&Qo5(G=ܙ3t H8`&Jʃ.:0uply#sJӌB vi"]ږ.-bfGy(𫟍1FAcc''6C9ԳvצU`(M"l( =^%} oo)]4XfWy>#n*p؛m'UxoOoO{ル xyٿ+IU7_()Ŧ^oGRmr[f ~@nWRFTy0CDX}_/[4c&KqML OqI'ccrE\.}]!١,B>aZ\JG`2wkF$x#mQS d4b"q=Rx x$v2O?|>!ɲ2R{T&RY3e-ik!"-^1SW5R&K <2ktzac倁2NeiTi SXiLZmK+Q$ȴ_Sɾ6 mf<Q⠳T%fF19q=hƆQAV( PWVJ¼7]6k~D!95ZG]z쐑W@mPK19ぃmnT /njq %[VRP!P#s#/I_?4nt3s߽xDqOw$I˒Q^*wpA߽9ܹs8xNJ\=2ޞ>2nL̜]_hmM57>~%< =8JRiϱDU{~cd؞go,J6 gPQ蘫!k͵򤫫'DE Q^f@,A!p..] 6l(xUw4H]F*ȏ50>!ugOfX0Ikg>z.}D.|| gUrŃHr&{à X}Ài>]$:rswy̽ʍww~4@!r?bJ 8ZB. K{ٹ& !x8 q* |S8D܊7m. [1">,*uАoc:M9>Lw[ۑ$0{F# mk6D`@awꐱ>ߗGuYN-|wo{ QZ ؙ& 4k_txbF$8nGCҽ"CG{RARXC Q1 % }![e.w1'D%r3b'yL֭_+x2g, [j3 m$y11h+&ҹ"Up:(tRA)˞vav9m۹ZlLy襰$P'z c`xesR-.`0k7e=9Kn:*ՍEeN8ӉU.uis( rҡaHz$zmhnugqw=|>D8sa#\YWg߼=Z8F # qZ!/_Ĥ?H]:YӠ?j*C  YuS+Yd֥"QYv.1R~/QY :pld&n2 .,s0LƸVLRF@YG@w=axCh6\DBw2 \smK[lgbUcUcy03XUҡ$2~H1A&t$,:IUr%EG?8tAS/Hk =x9 1yy#+Lݽq3i/N{D]N~j N&<2CA!3*cyR9t8ƣ;ZyQg *2&@ȗ_ e$^#BE,Hv܂J-Bco^ pq^ VBnr ]lO ,L3Fo%o3G^)Lg>&/ 5Fs?P`KzҡJp9{lRZ0@UfG&e.aI3_> 4jpt(ҥh2a|A` R\$O^;)C K]?G> 0u|v몧K,JVIbg{ΥZ!Y綈;#8~>n|g$|Q~-6τCIV]_u ^~q9EҚ:|;tNZ='Wфo%>x`lҜTVWu_dyQFYX&Mŋmh,ű=(1OkzTt}H";~"$eG-OX.Z/QRYr{㼄x%c etnv-252-kxq95ߡofQ~1aW/W0_pu]@vKhaGuqTy7,S5k 7e]LVh?s"J&zze{klۉ71 +i:sd);)NV~-#<:XjB% 93c";;S VW~WXIɢ($few+cnltbmn!v|H*ndvMW=Z_HZ]H7F((o* ͯhE?GQјTx+A0w:Rᥕ4vr*'z쒰5-Nޒ$r/ll BC5-M:p =Ґ]lޜ>KϤ%)UIVK[a.ٝjNulvK- )@%#*ޚg`ckW11`Xd|^#ŋЉp+{7}Bk[xسU v30{_|lqȐ_<#&;wyhGު_Ȗ!qNQ2L:G]ROڑK؃W|7 ^/$@8fz;}e]pg%l"7D^yn[i>= [1=Gs{j}=8[Q,zIgxo r-cvD"yC0{n burVbCCSTݺ~ 6R6s 8E !>2@eB1a#CgiefUWbg#sA"REEgV=4ͬsںuNMW݀X{|V +OFTjVH ųnRQvQh.Cvv@lQ 2O~΄CYE| 8+ ~)w?w O* |_Nޱw8[lT{ҒW>֑lջB1Ǡ{6hKcdžh3~__I/=B`rBz;)} I=y?s}Ts}3˷4W0 _H4}%귨rMx5:ח^=Q"s2J ?/RF@ (` s:.?=` }w+燀un~~/ rRn4D SyR!ugys ( -+5%e< &}+uuE`yk uђSGv[[;G<6i3M,j}RJΡx⒏Bmi_^lA `'pbqdt8=RBVR[E0Ci(qz^hNYy8?d@znyhGK]Ze KLj"'h?{)?O "U) zK[F4~g4 ᷿g9@}I xE*qP Y/A&Q=F$.?="*Wv4:[ v :e|fή4wTG㨎a1dU/W_טzSG|B喕Q:P0~6u,rzGxkzuYqFcccMN%P%P ,צxp~8LuDt޼4(7Zlv]eq:5t2 5p$?gPai\K|n!+T9]5]oy_ɞ _d!kǐ" ^^ynӫXXin%';0pN%.aPdӅ> yC67ߞ;}dGI:`֦ G#O~m;G$Yں>.^мD5J : HhvVu/e*E'AKs[zpkr\9ܔ|qam}b5Y :V);+ udQ~\Z9oV~+#?@ ?E7 ѫ vN.sL:D9Nu_b+ #Luq(nHf˂Xlg…P+p2;wtAa4 /u.iԐY`]^ͻyo4U2u]m3TvmDbzlO8-0v9hnWc xcB|ׇMJ#KᨹM;vZ#ɸ$b$<o v-L71Gm؁viYEb]Ji".|6t z?L>tso=Ej?[!^B:_2aPZ1r~.E9`] c଼P}Yi/csC43Ym@@[6|kCZxcrD̑o@. /.2Ͽ? 9Q[ s'就.CL:W 2#S>GxY&ph(O٘N2!+yN swfn/h,[A/ ɇ :ѯ_p-pmlC(oy}p KzX%Z ~G}J>ė0:5K9iuU~뺅[)2f GL_Pf[&{ ,1$e a Y"}>8Lze:Ϲ`N L n;gU^d'k5 ?%ެՔ!>cl߭a[)đѣ īӐ0z^[7|7!ueqwy;8o7P&s%xz `1N X~1750ҽ=;qdzqe;šQ&yHwN&עmt2x'(榌d7v*+ek Z;|혠d!^с>>&S\cg :/q#y#0cK$ڼ'xufsSp)'wG7ϮU!1uа-W6(OmC׬%va28pɺ|Zm]!C5yy܃>Xްb\c*3^;rf+ϣnN~VT6/@'_st e\Hj;{:7k84tUtZy誧Gkiss$ ٓcWҶz^E_-8J{:|ɤ+6~-+U&-S^v-Քy1{"Yt[]#}X]&>=~,`E.}*ǗCUl[qzp/jI\ƶW16QGR7fBg"Ϙ f.hnikMO!;{#lk4؝N"lgE䓥#6ڄ|y~+dĦ,ju `Q<Ӟ[c>SLNQ| HN t( xxmqCy$.:13`e1[ϢJyPG7 k{؟dKzN#)7kf^Q.pX^bR2&MѦFg!-o{,G&im?] ?qIVŃ ڹɤg(.tLO;wnd'CΔ󅞡SC Ts3ID$~f3`* X u Ju0P%ХcA:ZԚUpހ Hc({Uߴ;8kՋ =Er q'%r*J 10.@«c#ce٬p #Z{B-DJh3hu̬xk"!E tt{vbHRu0L25{>8HN>+rb?+ŋ3iS3-%ԩC_sWDWu+i{o?] v;(`Еx7 g?cЮAtege*>s'Oo\u3 ;w&9Yq0caY_r:z_EpKy'uG{ yD?9}{a??l|q=( MhL9.ɟsacwb:I|9,o3cg}*ށ=I:5īrc;V{f?ۖ^1Yۖҕ^*GB mmhϕafٞ=V\Y[U+@y5<3A@EFoYcSsб] JY5&Duc:Ojs[l#PPlpu_1o6D͞H3ζ% pX/Qc+he)b;2T 8V^.^4@@舑oUrqVOE΅ZdtWéiƽfZ$଴Vid#8ęF茵B4(#} '?}w~+pnJyiT#]",1p:˨S5%P]τU߶Q 6:pã vە^yʹ "gbdFcW wf0v$K'FTl>h NpkPSlyV߄e3_usuY9S@,e9 I/Kg$Aslgy uT"]J8Zl q'_0GK 7n#)$'n%|'-d-| eplգpL6Ι2ည1%wpp`ET2Ȁ 8O]h- ̬.,Ćb:J8~h$7EbNjTuG=`{}֮? Q|ʤ&hDL_پCgҵӕ+$?HrL;|&ԁ=H•:t } 5vu:V$O3ƞ[&- *MࣲNς$> I)H[~vH, WP"3X䁋[*ЏrD9@xs&@C35YɖY0NYUA]c] H0^+tu&HPǮ+'Ae)#f֕I:cX(Kn~~Hzҗ~+vΧo84 otWޭ"/y}PW^a.o1s^ܘ#8snc/ hbռKD̤뵝p]}wVGzV:WT8 Y.c{z[ouO䍧~_V XDr8&^`YPRyGۉ_ ߺ'fĿl noOJ}r"=qxp&1{b}ΘF)71Uvk^Ls80qQS&]Ү8/;y]zB*Z6|{i?)X[ki^#eU )pNt~0?m9[ooPY PI$4}/+[7l&1c ,ty옭+s#I4G/ZOB5/&֣^n؞ʞedjRTi|t`ht|8ˮGy 9<[b‚6wVU~i+t`,7'*pe..#@֭حNYO#cRS]:G*V*&5C;zzV1J3p-ŖAwW7 +*M"C;eȃD {^-}K/(з@w=vVw`I]%u$gWGQNiᶼ$T! DDˀ&*l @phZ.`t2PiA<uRg+blRcL(ڐ JJhMJҁFlH1mh ((|o5OpTg-N8$l5=eM ZN#:ԇz[~¯֛Z t !89tg|2x?pb/3OT`l~[/={}{ErQG0+tFa O/k7Pӆe &V>M%պn$NM/կq,#ÜJzA/q>7o3 c`9mqq_wt\h*ǎ~狿GGOOwo:gX5REWWO(2p`]yOA;|GSo-(붦֮[GL=v쭭qυthT~xKb~ F=cMQ1]L> ^"S8P$wI3{o iUeG]ٟ~sE w?~9% FP><=wx챿8[Gr12?Sw>^:93 ngj[ţ7ʒ 2x=FX&ܷ])*ZڐC(BZP,r:6!oNTa[ emhj|nIŲl8xm uU>s2پژ 1uZ.R.ߴZ皩 z23U.y?u@cDNjUsƤguـ6V%mT t5Iv\e:8V۷S ^0['/EGp+|t:HQΖaTr4]ݞWF9yNت&D(xm̼vjP m5o!KT\GE9V5[LZ5!&RQ"&h4ʌ3Оsձ5fG-&(&fhQY~9}Ɖw4o57D@IDATg7ikkc <R =- 1Y1 rBBx3?HEѣo7yb) o$`_Y9B1#Yg_*t6$u^ vPV(K"kޛ~K_$N|"hM|L<ܓwkꌀ|uFx Sl(6+Ij y`qEd\6g%CwE4gXg acG~h'4&TXo\붆~K7 ձΜU {+u[JpXMl`u<BãO?Sou,8cm3=/}M+,)!4]]$ʶ 9+fљB<X)~IWE,31*0 " ۉ]xn%-k&:gp43G87W]ɽo('H$NƊ2Qq@^j'%"|NUv5GY"_\ /ز2]NS7pG64KT?슡oiEH,\Sg G"j9S^yNRqP&=]ǞiQڱ&3_EIH>mL z]h^ܯݾHEK25i.8ˀɐN\Y-ԡiD@Sc8C}_syl;Qp @x&`ƱWY'ۃz鳟ԯc{mAJPqn_ǍBÛ=|,ǹiHQ.~Gg{\=2 {c֢tu0J2,#ע깁$nmCe %kgFbx`RZ8gLT gvuy5> 8Hv,l##i ~([CJ^:= } X[,Y_c$vd& GgˤseNv܊I" [8gTzoqWfQe A5\` W^{dy&}sn3F$AHs%r ;)WWrZo׻5]{4#is$b&(0D$Nht9y=3RI.f5+p$9۠3p#Ʀou,ǩD=- 96Ҳs{֚6}<~cOw}w:M0Ġ //9O񙕹8+ \co_ĝU78gdzCiyC)AcZG/)w (\AL9Mt gS_|fMF L&-Ŗ[Al!0l~wozf+l҉ |/sbڳ/?z._J}mZ?,t'ρR njTroTh3p,bִMBWG.Tor[pZoyjY126H_b}[[̰ y}v^`SXnYAFhmxЗ ,~B~0/a/v"fQ/GG:\UdR>N<1-J0022H~Ί"ʪ'pzb82 V`WilD3gzs@{%LfV|^6+ Uޓh6j`cX쮦Sa?qi:A͠Wb0P ml-@0E^uY7:4=}LGxOkǎ~ַ~z_?fV>]wyFh }3 xcitмs70JwPUݵ;_ YizG?Ga;{:u=Ddk_Dޅ!&=c7o[Wb0*7|8g0Α O|嗞5۱W_{)F!s ͵,;2w=tu$'CЉhW+/<+'PLC? \xW->OzL4:G}CI*?oQ~* K9MTn: ?@\miJ `*&Hh(WtE*UMf2:m\SWO Hr2l, rL9qSBުTէb[%]CF4t$snT]Etj~'k7ua❴.bKIosxޡ#eeD g#S5THfvN]hY,yS=83xf^ǧ*&<[~9 -V~1og(vPiH7jGs'iIKbYjH׌grȀ'wו0j(f5;:tDEEVjDFjg킓};޼^[~\ :q= k[ Uz$ʣlD-bzٽ.ӍCaPXC |-IS& NQʅhsDI+$@Up&A&>Q# FYqDeXA7SE<څ.X|R:ڹDngd-Dк7}Ya014kݪy4)h>VÆqO_92" 0tӀV"FB/`x6u9E`~ ޥM,t 3z̒{8W })7?/ C;4{5w7ూk5Z,˝K8LYz8իfI:=0N bq-?#aG}/]|]49Kev'p? 1 JZ͗k7" l"@w< g Mg!ɟrMj-k7KR[w5ݘ5vm0 Kì_љM,㱬 ]vҮ7 Q < `hH?B1*&--cZ&/?g*Y@._8zLA{`8lu}mM!؊ߗzx Y.YtvAaM|M xvv:&oDiQ<3>܏yy?;y4^}XzҵWo.WLGݑ/p~T@cqׅ6YGC[gde0e^⹳Y(8-"ٸB ;l-SѰN.. ]TJw5kKd4U.^cOC<+iAk!l:AsNMiE  &| ɴ=lNW2t l[{U9AyWN DzI6Tۉ"bJ!~q X9Nd* {.K"Yd6Al,5gk__Md1u3 uo,K6'h(s36 }89c(PE l`"Y rs龴jgؽJaɵ5g~|e6mzrr8[: 36νS?sI?>^ݖM&~Ɋ412&ϓp1Zhs\ഃw"`S[oIz_QQ>ւ>^ʺ8 pD^@CrD u@啭| <|?yBtzco,aCL &Grx|G> ![W3q#w[GNZ;A}ńw}Ů7%d5A)#X ߗ{cO\_?_pd:]&%Xuh [cًgrW9WمbkLdE^2mE,1pg2LW)k[؉[>IB  ĿSʪrΙ *IMSV¬(AId.2-Af[0 ZR H*|d7C@M{5T*V. C0TZx"ɕe?L PFG9;t^N @5*:3kljIE^gjߵ/ #N({%l?]vF)?C@0L)(*"n(8wGŴJ e2d{v*C:̀SjsQ^KlXU9.MC2w=Tuvtt>—>P~qBxTFPnӧNG]ݡ|\u{2 mG$ٳ/=ǂc=f8} 檿ʬ?(#S?+ M=`y#pEco}kw^QhT&(HYgIk4QZ )ĪlEf񑣷p䶥|!8x EQ\2J|oܫխ?Reᄂ LuvШUZZvF2~Gvfk(:^8MNʑ-Ŵ+5.2fh 8c:ۄRFIJd=Q}G*_-;: $N}狩c2<]Gpܻ #fQ 1";-_ ʿ9r2 [P2K 뎁"pmb|$X營#gc`KTY 9rFr7o% ~3Mƈt@qlWc]qp{{i,st9Btas՗ed/@?"|0Ǩ@Y#M舑o(^zm+h͎beAOl8tH`@VԦ!gLx+ѥYsK[!lXoNFnʳ~v"WXM/Z玜Mc+[^S9C&,ϰ*70kkpE0#Hm\ǼW ęLq-T7u-Y$#UqS?~.lv *Zmpu8#L4&?|㋳Q;n w YF+Mt9D[Ċ2 *̒8[F|8쿊$Z種2K_vYs$Ae3蟜v|W8}? 9ulY"̂%:*Lоze5$Zci8nI!* t6ipRV613VgjrԄI8jaDmm>gqҫ-i{I8^JUQa\lo$<8#YmM^&g46cS-R, p20=Wq1>ߣ |wsyZPn:ٜ@8ܽns+xSJc;jE'?X=H&ᡳϼT;PSE=g;=93m=IѦg3|=Yy]; )k"Z`oUez8wwuL%4ĩ̉jY\#gjJU8[ ^Ź ,>d=iBWOO`'^LkQ /g3dV }T:muGpX(? *tfk{v1?U٩,uLɐS#A= 5d/_2V@H+,4G]R٦HsWW7,pYB߮I\ԶpmAjussc7:WLXEޣb_|fbPCExK&BCkq +uB&c8[N@k%)_@D/h؇#9R]~gG{mR|dՠSƕy)Ӄ(a#X `~~G\:x%н:}LKKk ԩX+V ۤk3ﺢx/zqoG,O9Xѭ>&t3X""B|>%;8YE824]&s=g˂5o*y|%pfRTю> cF2p?qE,]yiض+W1>Q7/,.ڣ&|kԳGUMnS^ʻ=?TU֋Ɩq2ytyN4-׾FRIvR(!9ݵh&f$e~{6uæCf&)Y66Fl^i ^0.:mTJv8WIZ:ڛSO|bV`rBaA8_Yk T2ꬡ5fF 37)JPQ}`ooCˋө( (WkI"sֻy'ܖNńeшJ@j T ӝ.?GRzjm ?uQ;vtou#[G'ijn #SmNeY+uUNMV@уǛl/i[a[޻#+JDx(rwni+G.|ְ Z|`gHCF|e2\d#+40.2$%7놰Yĕȿw:<"*g؏{N(:ʂmoL)-Y:A[Z~n |0^.B\Ί'M_ ^FG//4Tt3f`heM#QƤJkpT ^dcTI= [X:-*/.:r Y{ܔ$4:3;[ "%;FctV2*q ~ X] tCl[]焐fUT=ؓm#>Z.J(=@.CG S'iRZ 4KM0b&{GN݄9s:uwS1LyHCV/75Ӗ ,|Թ fOk~+lͬCїRX>>:|σ6F7H6B5(`Xiy/:>-7k8EF]@da A<$TtM8u;?ZՙpXws5wOFvVvS4*QJ {  ,_xw| B əb"p LdY߅Ϥ=T M[ӉaҚY̨62MGkw0:tX3*+UN&;FPQ9{-6,taK4̩‚#M2'-Ҏ rvoudy5۰#xAi^RI*O40C4 2ǶFƢN a<>AfA<[:7ziRهI눶ҬAσðYa0@ua4W[ڛS 뵂[gp+6:ǺI$4'tv\ G1tyBuc/ﱡ=ouwĩ=Y:] 9o]^zص #/ wp 9eGKA%vXx/~ 2_I4(1lE֮#5i-;&QxVV2XVϕJYqY ]~l+,m= atѶBFU<VGq&t8 OXUuY^n}{n/}D`* K?=&9v.-P9Gǖ̽OX7)#RW7Ia .Rs :A:. Np!Hx6F7PcA8c CON.J סMH J3$KzbE$ ڭwOß~WLd)ـ> AZ,qFGWF)^=;{GRHU'R.oUfk[:#bgV*ڞt&oPf?>30\ G0(G- SW(3@}'K(k]%e1A;zWna/rҧ:ywKUlfF;Mӿ&./mFߞGW+ߢk>=83N0)[u/%`a!f,]uל pf^= `!R+L0c'` LGO1n ,6)`ԃ}#;r dkt& @D>(]3/f߼0<6$;Z;~AimqFϜz'u0*#i"VZSGY3 (/Pv[: ^OǶ˳wEHr_Aa/A}8AIu1Թ\I<)j W_HGs<; 6~]$L= 74<)'IuD|_\ s%zN&y\#z:oʳR P ^,]=uoe8RyY> +r-bd~vd_ڻ1 Lp&!' ?G.in|nEi`쮵yi@J:+ [q3<>i/]O?[t\B=xg9;K/Ĉ;>^"A:O[4:>ࡄq2:~~1d[w0*zm-6FqAO>nQuixۂN\Agޞѧ}-v%ב_LΛd^v`LkiŪyt0'V;H#s>zƀP\{]";Rސs$G|6o,M"ÃDokd9*Xxy]g~g0U| H]]/P!v Wv} *Ɨ^[[zz/?;kVa8NhɱK?JbFʑ?ii~ ~x{Jn X%߇ӟul"Iu"8ZT_Kol^V^ty*QZq W0.w>UN^vשю!6*QR򣍆Ъ'h aC:V Uaf[+[vd!}W} ƟU4qva?L`rhhS>O?q2nesy_]U@T/KV~粊N(o+S͠J?ORq*!s"mu z38uئxU98}o ]yzd,'f0Le%3eM#zGSQWR: 1peMqwU~Zo} 逯*>I;'/ɹԼZNg}+'\K*!0sG<*°5ߊ̠hasn!*Amt_$S9hqS9XJ0]U56-$h3@eS(fAFsF,8zuP wq< |]AV/#5 0$ }7.Nn5h0dsѡ1>&r6~^ 2JL#s?UNg:攟:|y+|ocd7ԇp<,Y6 8Qϼ62J6h:;{WYk /~g}7ZC nŠ.Xd5ksZ>{(pSϪbv:"5Fs j0=_7q=\3y{ט] N'eϭ\:b\E9+8ᰎq/qE#_N>95*4F}?Q,\0S XՉ\6K8$pw-%׹K4{q/sfzU^OvjD }sssqa:m*Q{QdjuEytՈFM8VWDH хSJp=zAӮ8:` B~cnw :</:G;"EoŅ1B#z v)rGE̲&ʲՑ` x<{@qC &.'vҧAm/:cښuF.A/unqY;ҳۗkq|yboӋZ`~FcI7Œo%FsHT qurSŔi7o*ܭƨhPPI[[ޒBp >qmHFᳰY8;Dy~ޥ{_, +*ػn`˩mK~fvɡ{|K=ɱ>W}Ps?}gkp KHO$G{^Q,lGc͍sUBtlre4ת@@j)|ch\8PSk0VtYD]A2}AzL5T#b޴ &[*L1S@K2sE,KٳQPJb 3>5bS>.8 ~y.39{y/jV#&H?rSζZʣLE@IDAT`8FOu5FW)|J]leUߥ+{>vGby{K5~t,/з6\~2?W.Jg e-su^h|5Y|)1$ȁf3D{Lޔ˪ 'ku ]QK8ȅv!jJa`lkR]nƔA:a `7*.3KU'*q3R ;#gKp{ JÍ|(}EF=A<&ag[EsHG*6ҍxu=s&?Dj耐3#I&l rK1F7Z+C} =]0{a#>uYM=JtYx Z7D@@3ܧޥ*ȭ(q ;kUQ~myRG{GzVBgnF¯~bA_]-G{ϧ=t=BYS@w{δ}[mzcҍ@q6w~p*ѸpWǯCp@UN?〧D}=̔C?O)0榟=s:vUxJn:v1We-Zӛtw7H0iß::T_A${Hw&ir:J4hC =h$T|*6XY]]SB_uԇ=g9+fWPSrXz:7 l$rvȘ&AƗg\%O[F$ t# xjVbkȠZ"SNDɑ!2p;d0 ҍAckw^/MGQi?8?!a&TqQQ|$G|eq*[u2Y15oSiw>F"t .́F(:G^`FMY諬I^ɖp"URV&x:-tu 4)$DyfTjKr?l)pCSe"G< UҠm q xFToAg$ǐ0gqG2UX2AHEN?H☵YmD|raH#95~Qx:6Qf,`t*]TF#w# ߹;_l)< MgbCB]&x./:t#6\g0lo9ф'm'_]Wqe\i`M=Xn2083G o5čvt㾫X&^qE[ 9Dd: A$T *.*v [.ywk9O)]8DC;SKc}Ts.?|(K478\Q2IF ^"# Z+&HLi% 31/ $ BҶŗ4'*e&ZIvKy5Nl |kS!+OOr^ybw>? "S"Q*?pG%{gЫ*-M-8盙}HMs,1.O4+C:ܕMh~d:pz[0WkF=yًk~gUMۓzG:6k8)̚(v:TmJee3v_<v"/y|;!gؓ:wtb L{et e{mg) %d_?aC8.$p d7uC_n`;yx ԅaX?kҨ⊟O%tt$O~$=G;"hٗAS =]@0yQI\g:m} X {32> ήj`OmB_'k{<[֫N`7L`@s.LJil7seYt_\õ!xϭ^&"~\4ΐ 1QІd n.;BM*ю5ACiq#T+ϣvO;on݃l+ 8_+^_bR<>x>U[vfgӽc HnAKM.Z"JMYϮ.'^M؆@vHHZƨt\^զE:+붧9dϫ=琥i;]+ Գ1i? t[^I@wq*!7m%9g_鐅Ovd +k!TQnU>^QMGC\}ϥiꨄfsF8'k4*&sQ( @Syl⏱۝4f$:D:ʣÃD\:+%U_(|=Fmo&iK}Δ6BU_zV0Yܷxt C擌,`H(|#$xc錛;NLj'#+c iB0a(gsz*:t8 )8pardب9LdBs3T7EkL!ԓ Fk KkꚙՊ1LAxn7c$| b)hUٶ6 ;©n"Y.% KCAe!M(m{rizw?DEhį#'P Yx?O{ f{ώх@ pa[sn1ÇoGq,hqi7پ+?2DN{r#|> ARɰOO3mߥ{lI=̱I_滏={>2FߖK_LğwQ}/IzGU~;(`ydxM/\T;Gw7eCl,F[yaq+Q/|wv&F;o-LMox(Vt:rwJWܑs wCOOg{Sߓce>o-/喲NYn{߈f>Ym04ew`MD|5gqTԄPaT}Ť5I蹜:n3\u빓&[ֵ93 R ,i./g[W9Z霶z*9~*:KT)ʕU9Gk&On2EGOH(Q^ZIWn.C7Xyy pD}OBIU9OIr"}[YDGWʶݥʻx84G+MqMAg(VJʭipެkĩ`$׾TPMPu*]>:z)g . i8`8o]<1Lֳ=4X6 qCS0*tX`VTӘ:t鴵UutVjY罭RY3MzYIT`sƚ2uS~s4F q+ [l]w2+a4䳼NnF@E|S⺵q- dypKdžϏ*1YGp> Vp,e_; de8x==0.e;;0=CP5{U|WV׻ kX\_hW`KҠ9_kgpWc?0\92m ufqƃAmqXlQ3^"7IdV\ G #yg!Á  : ʒ` Z7 EqS7K2^g&/PVDԌg /W3qn\wL\i} چ]q< q_篩ww3 Ws^eL8gu8O$|CC,gL Ζnml\xZ-,r9{&&IqX:>te~b`NxepBY#~M ݘt+[5=q \.\f6<|m0g+|tW9GrH߳{7- !0~!,VaW8AYP *d87hɼk< ~%er ᴌzTU0Ҫh f%VΈDS.V2p?{#0 *" :v˕9O`/[:t£t"CqWj#% 7ƹx@)-6HÆs׬=IP[vA6O$|aN2XeEyd{#@1Ѯh;v^b{OGh `G"eu` x sϮ!H)Y~zS&㠗:|֐'"!!|\ݸ{-OQg2tUoX sç0d/Uax \)Օc"P &pp[ѵ{_t̒Lh,H}#=>ڭ}}$+瞑ؑ[$ܱx v?#sgz o zq%~.].V"f#8nɵt{=lhl}j !뭂u&x_8+ ,R)aor~k,r.s$p3&^3]d W" V}a忭@UT'|v[.o>[n+V B.'ŮTK% \qdp[{c$h |ʑZ^STDL!44iWl3d" `ىyrz{Үv7t5sU)IӜ&/~T(rR]#5zItu-GA)I&\_glQYĞXߨ!Ka":EƼu}W ^C!nI3lKA7,hpMXFu'61I9kw7z8c6eg4z\NZ.o>Me&gF9D:s F}ǽ9LSUUJIys>s3PWEyې>}:bI~Ƀ%e2|ו,PKN@A}AQwy4mŌ7Jv&x_" c=NuAevvB|tY\# 甝q&S((Kԋ7Ky3?q`˸hd1,~ơ=V ~B':UU>L(X,3+v@o CʌLUfSXIiAv& dFm-͊r&:+5;?0 B,!mN>8N7ƖV~9CPeZ[]O(YuQ}BqPlF{N}1k[#;'A ?'"}S!,rN0[{3u"` K9=xm^m|1i2snDe3z=d&j֕<Ϝ-dho8H[qD?ģCqi0n0VCt[9SCI8i Vؘ1lfsV$ HN0v0Tpxyߗ^5a86jj5#gih3H _f:<33g {71?|G[-?fI;]s=b4 Gܷ0 T[~gmmT7 :0rsd%GL x(OP&2dg,\/ Nlo6bxOꝷNy ~=pV8Z ˌ6B&_? :t6ʵ̪[%Ȟ+qS 8I |ND\c7I{D nq? !`=+u>Lx |/';s^O=>N\+< s&=8I`oV([\4=e }&bIvT+Yjn|9F*Q:rrפx0RCǘAyiM!c5y҄:rQqv|Q [Nq)N: dkϣѾ ep6 avE!R& xdAۨz/sx/-pp#HĭXUc[T/:)6h׽˟كA9gG}hK<+r&:r* Ϣ*wtkji39ΣW&x q$$mO؂?K<cN4|("ghmՐ3 bNZwI*2=*!ӊ=?z;tH <1aOWgK&u4%G>+w(wmx277= V7KpY-d-(֘Mj*Vφ䟈ʡ%x+o_"hXC"6>#0t[i=iҰ:5O>l+XkP(LRϑ-uikgځ IS7DIb\=w1~}㩷RQKgOMg;/O]֦CZ^}7tX{?νm%qiMYL u ?8sݾ3 ZjL`SOӒOib__-eFλo֏_ tpE4@:aQƺ7}y6$qfS\GyB9L$rv-qˉ*wu t.{(γY^ B/`,S٘N=+C!Ks8RQ69~M m e/(y#_s4jΝ]dg}X21@uP2+–8KEd)A)AqPfm a? !G5xnR4hA)!2NkQ̲m F=VԶ3D et5m=p_"}m~w}LCoQB ZyOK/{} X+D}9 'fsgQ{"(v޷okNÀ6%r+:;?^xᇴٙu/|D(smV1}˟9UQdjki R!ɤ|T?}(/aG]+3Q& Fw BtE[e*X*X=A/|~'{pմ|C}=VYTk]|B85ҿHbv 0c4cΫI"h^\s8} I/*N^C Q 8=r_ }*նâOr}o!@@5H 9JEU%9/%UZ7a%$$U$DW583lg0wPBEB}a(0t8zǞxYҧζy xT8iO>:U|\o)T4 8Dϒ9f0&DϾ^ Ze(rc c9aʬE:6M,K 1䩄Ϫ.F5UJB 2B1pNk'$;$-u[\"N-HCVt0͗zժ>s +K6t#1&x4r* -mmN YD," i }=LdfFUnj0M<65DX {݄ɾFgљU@UGz%4}iA|x&U.I*K vڢ#AS_.Ȋ"=V#`WEJrAb\Gu?*K?ZE.LkEI&V۽pPgN-?4LfAm[~'=bQi RY\"`y{tk|ױ &hlh@v"oK*u"X4UA%:OE]AJ mu1\6ya8:KYZ\'AQn@ƭ- :UϪCxzdp ?eYzΣV@ 'Thѡ|hI qV QpTz{M|.Rx?5J,`M I ~B OĴ#Vl(g+1AЋ\oi0/ cWQZ!sc:HLz3Ƴt"0菙ޢBВNq$ loa) Me0tƲ8%pf ~mOGλ_ Xh[{0Q:p$t 4a(ZsU"~}0Vd\l3>zq1Vn΢7߸pw:qt0׉G\|_7* P:$ҁrxO#x+xr:0AN"6g VJ |4/nru*\1Ћ܊JŰ T)&X62S| PlNєeMdWȷX0# {>$Cw?_w>]f|IlK#x6[{0!Ym(SLgq%ҥtLF/g?KH'6{AnͣSEȵQ[R⼣:@sCtoKDcI߮_Yw0N"CGu!v8U+4zٯٙi :"3q;1ƌ9s)ˋf9t1A.VY$.g{`2q >I`Ftk0zT$u0,^ؕ>hN;UQ_E[\i~[BJ\tQy\Vs#H=HtOA)8^F>5OwUݨwй]!mJtNy1* eרrצs(K Dݤ }/p"\о/}W EE[PNkk;6 R_$!9H{kDZ OЮD6`/1ivNu4`L*-DƿD <68~u:+#H3`y l̝4>> oa;樑iJXy2>p+_e .DlNwr|Q\ z c&VSuRq^zajoHGSaabף\."v eU]AnUezZWLF$VܽClr^ErOmYjkN'P_Ϣ#Iv 6 YZ(rC+<$'9bT*M[yyt5 t2-m]yEZS-U˜ύ%br#m-l9`ǣ-a@$O+"-+k_aKMRɿG*iSyT|س9e:Gh)m^]  t둁U!o8c KD95¯iŔũ*aO{mWMȳېG 5ݢ#Je}1g/5j/GbfVo,΁O]rR3YmM0-:g f<zb0lBitDg:KB'Z@sctkyPQء@/M lR&)h4;z8ۦXWd`z_MU$2?s-iQQ Fq[A@#dATTQ!Pko|o[8$C)ICGiAj{"&;0pv* {ɔ,;iڵ)ʭv2h85P{CqWB@?CZI:V $Q1t*'M8M-EEA6Z/Ra+C?w\~JU*͑RKڕ/K\#EZձ:5~=,39y-azPu1ݎf摩|`s҈F]E өCXNJIsL:S"QeAqZ U|*R.Pʬr]"F0WBwz/A|=!(=>1t0Z-ߡccV lc`; TȢחi7<Z}(1Dn-1L pzF&1!cR[٧⾅\4m{-[w9Fr/sԻ2:GБ+[%SopB { sn"2+ gպYug) yU:̂9e?*a(}Ĉ7!55ƋNs:L1xnl8pQag' H4futsVuh{֖ #eaaG\!R>; sWWC,1wZבZafND&yY+!le+ s_Mߣ?bϫo܋pl`1uσZEGQ-=pPKW r|*>K{<.U0wiߦ-IR^cc1l&8@ň4itOܛhAkKxlm2 B#=fnaDq0)m$ghҦAWx}5 UE^]k]±s@D ( ^֖ !ςzS0Ay$xLo`]‘G>ey3 :|@X({A)r$6Ĵ:U;s do|KO~#su"O[&Ih{H$آgx%{慓sQas uoG贄g1?c)L>jlfc%>>+IO GNc 2'к:AAϰU obZc2b$_n^BBɍM9KIǮU<#qGli"K Cގ 1̡y#d%*5]{qT6p\ЉIx8\i>|F=JmXoI]ix!%}nϼ[ 6\>]v.ѵGͬ*<22j}oaƌj;NY:q U9?_ФT[O76lڍv1`77xK':1`i#D[,u6^r[왛$sBXO A匃N-c uܳ peAFL ݦgЋzc(vݍi+{4h|&˨^A7s)w@C$2g\Z?& =`r7j,c,J 63c{ԑ2$7i)z&t++6CL55H-ـ۟d ?dr l=m"v/TnKİh͍LDlG~C汉.XCh?GV;pS\ekBӑ44=4PT%YviJy|+3^~˞'ϱImWu=fU[XMQyk&I{inbtZW'ROvtI 6W.tBG2\NA6sEi~٣dG1&7+ r]CYTp0=Dll%ZOoqRu]cÆٲ 7\HQ/3h <]Nu s&lե]o)_ [_&W=b0+ӫH: KEbѽ`v~9m,)L}M7U3tU,kQE@*Ytt݂#QgМ<#:@3â#}[5%!^,ϖLރ?iBUO$mրF9/{l#(^nqLWθ<KO, $_L5}]GG!IUv0=fAS^j_'?3yO;7mcY^*/Wȧ]< {MZ'L-%UQgnb5x1{-Z*Rf˺w]}S[i |^"8GOy3ӡ䕖D5u4qSl@a&](rC7埨vP^/8qIܑ9U2+޾Kଗxv1ڶߝ^?S2&;;DƠnۀT0TA^!D+Z3Sh4"2AŠBCdateKsQSSVFp^*#hY~`IJM͠U'=[N%-HqNF.${$+?|3Ц6C|qlnstJCevs3ћu ;G輜uvmqp>eoZc:lfK!JUŋ0'O_:Z <\B p|}K:yc%0wEZ O߯qM[7Upfԉgø9W׹Vi ,FפQCIG3i8AC9я(+(WO4iqD8Wxsa}>=R%O{WӗIl%:smii I ` mp,TA3G2|51+8PP;p0򉶿(^;7jqfxkO_N+x@ 49EЛ4Im!Q3ץSi09fUZLgخ͠'+ ([k_D:VݐKMy |Yv$)/>)Tg/ Qc/c5 b`S^3Pce!!}J{דޗ] $4M">װ h2<ps߂ɍ|?&thԊb9[5sVuu5ur7l:F'{D0WMz FS\f _a4רJI5Ž#m81F=yci ':9aF̲4XE+u( S6M<1|y0 7٪]9sg.8 /&TTa F׆;:;V\*XY\EXC kWU.L T]TgZ5X8`eWyvS/ֺ̜ ]ӱq:u7`҅U+RZ 6vya"i̽ =w)WysRH:S 5:fR?0P&E~`~lVcl<>[:Jl.-r<;;[8<սt:iM 7mXnpV"8An>xN\Cq&Y$CG+&)ro1й \VڋvNV(PRE<\"P)~)mґ2Z}$%Z׿{a+0?Xulwҕ<î:7 {`~.Һߏ ϔĶ4_@9G<#,TYoʛ%"ռ2}}/ؼs0IϽ~A%{wsu dIPw\s WL3&291 \A࣬_ǵA\ 4$>+D#Y)?q(&h}+G;7n0*!\ۄ \=uf ܓ}ȟ6so㔯fiWo.哰v/25P~0{="Exx>qIx [ATڝ'ө3q۟uקNZh^"`jΐ @#-WW$s/e Bĺ?7BBS3٭Xs4%C>e"z{zy/[8iYf0H'ur'.3|Edy(L_d,n.u7^9΀?sl`r:fS_]ޠsor?ۿo3ܧr$n +iSZ,n38kN?tzuH:5TY%D(6fkM}3`%T9:p.{u<׬ƢDv*vS۽Z]jԘsEDdN95DI-iQo4@>"+2tF:OE4ӹMB~(qȤ(qD'>jy&{TEV=O\;ʝs0GAҦcyؚj耪n-/ĭ|ooL78Vѫz;O4NaCOu-/+oq*gۙv5Fxv<}D^d~=KI<`_s RA]ڦ$y{l v߮[$Y,3Ai[Mm ,s78~T+Ud5] -ö#-;08rWgS"ԑu,wiЫ9"89N^ܥEQ/Au X^~(֫$t|P>v5uR±bG--Ko]N1c#+~t u)Q)mL+MN=c#=M Աn4AiG K ű_*ײVg o3Ƀ_~6|0lnYW3zn>m%D{{7Kkn= EKtOz\?rD!ㅽh.ea7^-v7/L1"Sts,'m\P"m𩫻A ,!bW}ó,)+Ol(t+07 6rPN/.$~2)2Q4,lK[^<<:A@0Uxfp|W}E;.~gtl۾PR;/kP Ǿ_<(ƀ*I_Ku'?ʗ pvss{R%/}"X>K弮AtDkSaO_IO)6Q ?65gYÎiż:g* B rg06;Bx] lKFlf>2z"xZÊT&Θ]:~^z9]czh:1Vc^|u1i#k ƸgGktjO#-tH[ᡌp0C]^љxU@ ilt"mA/QaӚ*qҬ]qM-οq.}3^mSk8Ŵ%MΜ77m,s}U(ЇmlZhMVCT}\^`HɾIW$  fW.0ujj<)_`0ު(Q 6FPD?^e^VE $)m"{]C9 s8`f8L@X!^'cmu~d ѡQ3Vz0$6nm9ͤx{µ[q2e ͻuV]Va0y~i p.<\5}eo_MY,-[%aYƽrxp~|=UQv!h`Ye|)aC凉LҧȐ) |/?\ob?uԣSDIp"k;)_"'r6xK qX u95R`rRF\|^3 X8?rpC@G .aD=zX%y4 d)u"a}X<Ĵ(> nԕc y@+CM)!t"_x TT#w:T %uc\1l:MzsKU,'qL@W^Ѳny0p G>[iZ-atG9 ]yYdG;6r=^!ᮣW[¿4 e;?ȍq_Gt8q[cOIe-;gPͶ9839 '湎q\;C 8GNom.;@¯r}ިn nen#9N&|BOM;r ?s68U.!HW:9lH/fuRv|3[ǀ:2-(4[Gp9:׻<>uXfI$19!t ߑGw8tL^>x /lm &gg=ҝG S G).%t;No%z@%wqi,Ȑ",~qcIp:k[,x&зOI{H]C\k#^\??DF ~>K͎m/}<$p:c㫗6"q~&J|/V [Λn#}P{I1ա4XPR !Ҳl0lnTx/rܘ 3m&V|/%>{ ;.:W,{Υ<`_h c%'?ER3<ǫHU'd]ΫV@u>"ՎSJaMI[mb8R-E$?ջ |Ϲ#$odB$h!/{̴{R&Y+KgdHEeTe_OEqqEk5<ĘW Efui| s3Ξ6c.] ha]Kv{[izY"opv1:Eگcdn;kiv#NJ}kF'AE|$ڕmz܀z:#VP~~v63؎v@B^سueD^OGN74QхB,=[`BC0{m JYBjռg/-CkAk;D8$EF v.fR(+XNaҹ#18(UTo>6lj蹜OXD5p.m3,޶/D7pƑ<:3i8pDuG:YtCMKq[V rsπo:;ȟAQ''x2E8ǽyzq$i9xggpтŵww 6YD(;l-dx'ʕ!IJg6Ӆ$M/z!pCʇ檠)k7P9T }-zHtcԯ.\r8ٔԐ"8s*®wm݄W u${i;//[c-/FpD Ǽ=^Ya§ KTG3Zox&.A5:t8'/6tcg|Yep AVy. eVP5*u4dz =%] 8+b8cK F>GWPn$3C@; n:}%j?STuvxn~"uyWcz H`bO?g2 g\jc6o?G gy4-h@!yp|Ssg8o0zH8tN%<<x^Bᳲ駟LЇ#oh3;~أI}1,]=iV?gƙi:F,{}jͷJ+u;9=48t9?z2=~S:GPGIw.]kU8?~c=YTGc.^<*MNӧ3Quތ/}/i֟>, K}kw?>ǻN~~| K|Ɍ7T.}w˧> I^k@rPrH:җB٨."%:MJ2[~=ZOS&󨠴DZaj&Ξ0F1,\k"(! \gd=3@ǝr$? LQt*x*ck ,6Ҫ \z5p+| ,X luoCSMOV5Ha\6I3*f4Tq4Seͫ0ʤꀇx JgqL;V8M`9ȾDgM-^͠#_a6 v`v([ΞB|GKYo8!.ޔuz244^@HΤ9;'m}'t xo;øvB1ޚ訯LY+zPCb;WpuAqE^!Jn>O8Agy'ARtO\ݸ[z~1ួvq<;ѩd#N} W8=;g<;E}  wy31$ӗm]IH-uw3@A z3IWp^gqaY|`$]EfթP79[9&~\Z܂&0tCNxom{O}+Z*v:F9oY{NC{ѽ3N1g\C&p&7уM.F_}] sjs.Z>f𿔣}67CZ{^z&z4!鼊mVL@v߷jFg#w9g~mAл-d]f691!IŽDG,_gV`KCfV~n v* oqՒ1Cɴ+NϼlSSkwEXPS)wSu -&KuTx2s鍡tumZP%?v du6-Ryf:uMgE_ V'4ZE&_2E ZbW ;_פJh /I;$LL!c!lѫvӉ>j"~m}-؞YpZ/L˻. /JŴ|FZV6AEFө5q]sLK샅HKbvz"\?tHءꐇēRh~5]&SUisꫧ.Uyh!6Ic&GҒLDŐYByko'}`QmG"+&i3ZGlcGnC5ɿ2:#? >N %|7ng{umܫ~$7g&=>GTNb=h_;n@¿*Jp' b‹ϥfhu-u_an_3?&8f_ù}SzgȀmM?҃T+oCQͯ݊PoY"8:5}VW,P.:`?Bhm$"m3C%=4;>ދCFFDZGϨ3;٥k NPlJz ^5ԇtk|iYͬ&NV춹OO c[G˯tk;Xl Fz**hÅr:?>ۢZB=9ii3W=E*' ζ0&47qsA0;* \+cߥg̗9xjWYcLz2pcSҐV&x0U'X?r(9Fv?yΝYŶ4K{MGf <蹒$mXC!z~bLZ$:E܀y7iI k~5ΤVΏ3846:Jw դ =1keAakGRe^APT00iyGND+GE$j36utdW^8c=cy4 RB<e$"46VB:nWzeha:ӲrU' X^炰Gܿ [a?5|9L>%!iBu~G=!H\O2G/nnQEWqWM o݅}PrDT @bvUAp<3FH{H;O+`pJ[P ؑsƀgVF2: vv" <`)ߊ2;WuA/C3(A1.Ѱ,򬻻i ;toArq~)!OX,8MSf-Idu i m_>D2YRlO47J1SQZS1+kU˅ t#4xnyzNS&n(yQ|&$FaܜM?wӝwݕG'G1Kd?v2 O/cLn^!Q„m!OR^i< [rkǘZpdp3 rsz٧ӧ!O g*WOR}{4|_J\A$kTŅ{ j05I)QȿC^W9u{]{{;vAjhO৹=p[V{,Qo$` WÇ5xr+]t,0qòXʓxu .:;]ǐ[$z֑ԦI?d|t5/OCҌ,r=+Nw1G!W@ 73 "a'E;7)g&v{mj2کnbbpıT+OˎK.NH Y̯Ϧ#m=n{^lB0o$C:+ T`KC 9cU:;輔&aXnF}Q6oyL1\W?o|GRzPヷ9 & @6n$kCLs<''co,' _u 2NV! 7i%W2*fׯO1-5ZZ>POi t<֨$+a\ǍAgQm8TfHF:S`hhz Pr/ LymLx7>~W,|2^Gպ*8U(ǨwHwc' `M=E޷:EV]'V?>f|5I0@+]н=}R?m>°A2N݁筪;?|w(]{)2_awZUĄ}}y8 #G=uw+ǒM$t.|ơ}h5*v)sUTLzo ?%R>x>\KVю%h_b>}󭑼b%o&|UТʡ;NJFYnȼSe*3ChegIdZ(Z,nH8V2unl,E9 G+$ᣁ_:l]UrFҠc l @6dg+(lШEy6l駞o#agي?CUUm+*7D x8BOVyTwV2›ɬ$<r ;?r'4/ cJ:#KCuz 70ڄ0ϱk6PN7. l4Ԃ 20*iɈxx &&Q]↰6u6x7eПѠt8p/oQm9(+ rZ-4~#?ta;?`Jn{5A9kdT7RQ. ?: qWYuj+USy!pR !&4:F$Y:?22r™f IaK;"t$ ֭,~ K[8Nd뱪R|aJxu|ᒿIOy<8zpetu@MP/CS8\"W|W;aGrBFz H- 쭷G{%̡Kؿ ,g6yy:CMcDÀmΈ_iC(UVdxwyTQm}ChKO= ǑmTb64()$reE%& #{ jRL^8{fiyuW xOfzz[l3ɐcu&V m_F0[H2Nhpuui+Zۼ`a?jOJ#Js'Ͻ>xڢZx:0n^\_P6ɬe*:1I'9I}&[Q ?!hQnvR'#,o/0Q53}T;mh-)>a~H'8 0EC@2l5F^ͥ`tl!쨘f@8Y ߩ@W ,vgIF^DߪNؓE$D&AJRUߚfW6Wwͦc"-Oto"AEڴX#@YeNn3&%N5pȺQ R6P ~AmNJw}t9]!RXΑ% ų 9mrksXLN䶾y=rwTk\&D{2xt͇HLiR|x  G$ sJPW1$BLT@לKZ@7i &֠ULbt3b:oܣ9dT8bAtiT:&Bk݂iO!||lq33Dr`>8a.w3c$,jx:mPd2kң|N1YtY,dEX[XnGTy_†+t~)o 3&a8 I# s)++ vP(CjƠ社-@Q@;'`}_['_!H72kϔ!OMt OKǃﱫoPw:us(5E: 䠤86)ÀUNxF/0>)Dnl3慗^v0ffq8y:*ƚ>jCQ%9dNx?EϓO8n.1c ֹo(rv@ܻ}(#" yWdɪ8z&i\ڕ`"f G0U}-ZC{MT8jI:=S֓yAC剡$,PX?K(7 ~3utlPAO0>[(n^!!r:Hbi]x1 u9 l:w]uwu t[b D"A:UK Xmhh3djE$$CTtIgXqn*~*mV#HF/$c}ϋԡ䴲IL=ЧAD LW:+LvSNYWq #Ǫ(|d;*UVnh˧e~a- ^]aI$|:1㻶eILyD<ʰ"ֱ 2rLҜv^f7lUlɏeٵ$ #[EKE/NOĴw+`qFVXQcQ1f2" V^Ft$IU3iuqX!APsu<,!!`5v:lS<',xӡCP)+΅vWVzLpV*8HXZJXBDPQtԭ+4<=5\i?|?5u@Gpǖ+\wqyDv0yB\# ZSapPNj[Ka de Y.93TH$?xԿ r ^ꬱUi#C<#Kož74"2ϲÞps=?ɫ˘hk@`pdZR (I^48f";<`46Adl#!o#T?2CmƘ?~\ۊZz%T]سc.NGP&$^CŦ|8@x|]\"@V Mc:I=ӄ+}za 9옑#Luz|@z G^UTR1 goPy))מx#uCwѸrtcYZ?ww#H;uvwIPE}͆Ɣ!=a~Bg=n Ǵ50$ҹ뽑|$bT19N& Jsr: xĆtҜN#66UsU|nX3{~r?6i;0+/"#TyW>{Cv0 O)M!yVJ1fRqf0>?N3Sj?PSu=ur`.kANwvw7uzW|.^x}a.l`9Z/)+·bE W)fЗl9LXC糳SgĤnJp8nN~QEx>+( \bJE/ 1RG`L\y-4QV_ҋs#XcD/^yXcwOG)K>tqQ3L+<&TQE z6] #d8oQ:աs/c}l"ӿ-$3&6${1v156:^yyH?z`P0x[MK,Ǘ! =@~c|yjgv'?2|Xtb.0hKՒdk8fڙ[ΤOCgp}n<,!/~Lx>ƹ3ӑǂyUIPԩڤUtDgJv;ߘ>دn򛉻Y?_ؿL,&PW_.d(b(7Gp<O:m,GS~9JG&ba?Ek*%ąa8F .<@}M(׺B z#UZQu(4;p2B<> yצJe GRi6AFm(׿o+J<7 )V &gOxf#w٦Xsg@fhn:8oG9mCeV--֕9\kf/ʶg׮"Y^KeWC{nq5ϮA7n}bgtcWeիsϩ.g~#|T<ӹ^S\ /7m4ߝ)[@(mleJՅ;O`k\=7/_7RKMAL8[YipĬ ``R yi|]L]`۬bzd73kIo!CyYU ȑD919VثI*Q툞EK$B!;I 2: O{J#|nV8-Mıl&cZRc>k9G?[娅ߵ7ҽd+(c@)I+6*[ qt*5 C̏\0Gnݫ"^.Zm--m4偷LqAW0ќJPĥ^f&?ۤ\x!Sx| K }\V83;?10=5:Uix hLq8L"۶eTФcH` m?9:Ag Da-^y6' F"QgW;=5d DGAa Na᳼j¸4JI4dlΟ -9+Xg|]f Y)3}֣:&ttd~7xf gJfI #Xx65t2u_1\(1ضo/|?vlK/ ס%z-"iR t`Pww.^A y]g`F(:VAw.'mG9c-+lˬvItk-aAC%ֆ2pk4YdeFUp\gU_U! oВ]يKj[ghTrJ[% XA6V: "}:Ufyhp `뜥nu& lBb h̪WZ 'q]І*U+fB{@.*s0Ҙlzv>?ޣŝ{unQC[ ~70O+*)pqU鹵tzPwh'^E8w=;KxV.ڔ%LVlwk̂ev0[[:X`=yX >f]wxsʖ@ъ&::zqjUYs`&C]21 MHiep?;:@;fP[V;[ֽUu`u~|O^Gt\3B'.~s ,h~d'|*& p$K&Q0)cyv<\q~eЛO8҃&^|P.ԱokJVڭ7ߒx5*gHt/mWc_-puZ?y':<[  9sROww*:?g w-% [mgq)|$塗=δr Y&Q^ah w[tOTZOE_-pHU.n@>];CTR1Av7Wvw~[$vH:9ZhL/EL 4?я"cqL2I\("qI+FVVI ^#**A $[ν3|˄g>tDAgޓGCB^AwF?/_^={UHgHY(8 @ =I]},!`/qMN[)EWVeI¥9.?")MԔ:8kKG$h1wSG}WR1Ns^̦ C-[[ Go:qStrrtel#cX?=uNUvLS_$ו*W@߯vc$|ٳЖF9~J*O(܀mjZ6ҹԾu[to[W]Lx!@6OL*OP'_}ċܪ,i$Yiٲ;A,ϲ29KмG=u7 Cj~k&F͂i" ̀t- UcQA sF1BʹÖ'cA*]DogG*:x _; Xהv_^cJlR^"t}bhm-DD.[1 9Bc$Ѧ&s# {G TY|H;JҥγlDLvIG7`"!b}^_Ŷ%%CT`O KHpTk3\.SoLP@- >~e [K=MR}h LUAA=t#H?7>L j$ms#k8zH2V+DPS/v p ۟׼LW<Z|8Ih輐\=x$POw#7{셶J4I7aJ%72>i'pG}.a$؋+kJc1 ,𮦅ŇC!x uUHYRxeI=2":Di \'ɼ5pPۼŽ M<$|F%̗\zœr˄B(Yxt=OڤBvymJG !CΪ7c u-[@֏%Mveodƍ6GöҖ;ct@rrL9۵{eݑ_:ytz\<5͜;tT8xs-UKa>deY>2`jhEHrGְ c_~ !2tdķkqCF#cWzTYCkD\:~h:~L$BzϢ>;> ϤQMjݗP:Q}:ʋs{8Mg8x?Yõ>Fddڶ.*·ޞP$UmW}a7rG/nƿBfk9JnLjVS'80H~/]8>xJs&l߾-ǢoEAt+ ǔ\S<7U<;W%6Q hjj"19޹k7^e.pZsۺsR7&S栉nE\1KGJ T$br43@8[V:q9n0V}ige #r {?t_=?5x4ԧ3kpn{ⷉReeSm?kyʪ%<<\븗Cl rN` 7ôE#VaO@[o$;w4-?A`o@ k~?$%tbb݅$p:*FZhF ly]$:t^0OloxiU[$/y9UV t&<E?`b/uo0&Uю5sp[KH v~\넟DsL*#sTKxݲ>{Z:nM" (M3D RNp\ ~ )֩]zW[XAC;ڄ*;U0U[樐U{5) X7t^X0e14UY*t{ _`\RG/ ć77@\zVCou ?q Y{{;e|1ށ\3]'kd04@Z*sT#xNe=/W-J R\.D'uI>C:䧲NQ!z$+0X9K&d⋕W8y;v4Fgg`]ŝN]Sgdnmnv+Os~0ue[m$igCKcB)V-^wLJ0Ad_:r ai2_ik ӏ|Bə" ;X\ޠ.gٮD7d7;H7r8zɞ贬[ A|LGτ!٫Cd&':Ne ӥ >k@3:5Ad+t?4O >賎$τ̨4ſx|]*jn izy{3q>o.݈!ik7`c`s!L {v 4ouiM$/V|ŽoK}9.pa`eRfg._Z -).5~EП AWe6ז((13u{aX.ddޭ&E UDAA[* ,50< Y'!9y#k ೸$ZA+v*[ CX32ƳsQ a\Fe8Z`ngR!򨪯DQu^Mcg6Jy |h}3| L-CѦ$=O. ϼHtIAAbX]pf|YiVh" n-$'.Ձ*:_I]B`PQ[5Tߗ+h{n{1[l~GG3`,^*.⵩*OwKSVX ͡$?@D> wT 3IlW7YE9 2=V́_C ݠ#\V{+2ɃݛBSmL<3,LŗeyHEN1dϳɵ®y%tcW~")" LD>^t!?}M|@]#ʯ=F]ژO)HR$$', mQNcV,w9)VWBo#(vvCPD*S H]}HDW OaqmgY:COw_Yɻwٴҧ> Fׯ_/Ď-PI$JvN`yVX| K͍Jȉsa`&:'෢I* 53.`8R~7٭ e%UF;wyLtEf׎i}hJڟ2`8ub:덓q& }'MMCVqK=`A@i,}? ǟps-Χ@ڜoٲ5p@rЅ &2YfռN+O6o}<0宴sn ☇BF?v'PO@4СCQ5 s1tLH=`ٍ7ߚ:v( lAQ,CaFOZ[8|=nn!AJxҽ*}@!o#9Ud#lDӟ\#.mv4"qnq|Z=9Uy·N)_xU ]jL$TϹ. \ _6(NPH\u&.%^Hgqϐ0D []vrHl :t xPA6]#7k^cy5C{s[~Px{u{Y&mX9ev9|Kctǻ@>H-g ^N )1]wWR{{+r4"uOXsS@>a@Xvt t>C t.ˋ133Q-${+)#;B'{H c]ĕ@30ˋ^-ZTO7Pwh.xl%BzX{V֡G }u>zX9r$1B1 4nduQmfs3| sMR6kk 08i"C硞']~F:`U0Gܴƨ,'|>kb<'^ԓؚsK *v\%b{.G=Lvn嘃ɪx|^}${9L-&0 {P"OWR QQPҿ~W. ve05覝/zeI-/ioۨ$_S}?u)DϐoiIS%%qq*:>_ZVY У v9F3$إN'-R7]&x s':4 U3WjbHYyP:tx:07>YG;z-s==,&PI+m8yXs ~!n~ҋ7ЩV9eKj /y%[eV:NK<A>QoBV$s^fH[eW~ֱW6* GR ٱklބA8J&ii 6lm(i%$C݀3sUxFꆟ7_g[1w/l.~® =SgzTs`hopϡQa4 ]0Hig{gϝa%_='ɇjy[F%kkޱ}Kxx%䀎u;eNL},ϊ+Pꎎ%Nk|Z^a! &A%VZHROiKCr81X*#od|\ .+^//C{>rSBwЍAp@{u Gk & ga1h:=} XoL3$2Hg9cbI08VpS \o{Q*5l pi_8ī'sNtt9Bךة ?TPCV ?{'P‹/<˚q=C8/Mi{)>Nж 3I)ء{p|Vw$`5цT s?VmJܓw&M2Z[u~fRbuO8dT]xo9_t0`c`q ,^ďZ*v}GyhwVd3nDYSg $`FTܦxPr63*?a6xT*E$PuVy`k" MQ(j/*Ex:3Ԡ{ (4f! S/׹PykBv Hy<%tsZм-K9 C>F?=uUtJkğ6 d&4 Gllވ,&a/7uPi#tpA|1ANַg#6Ͽ=R̤# &QJV83&!(Sxz4:ZU ua&Tu@E;iWUk+6`k7k*,8KvD6fgADc 8I@3;o8+E|-鞘)Kr'B+#UFznTyI&:+mUvW! kDUP"[S WZ;6r\ĺʋIlv[7Cunjs U_rgU6FGFhX%=}=#RǓA2UA/|)}_O/:>}e3>`W>fqz8,g@!S 8uJ8zoK_,>h]MǎMwƫc}=s}UB0Jg~,m^?v8`t[W{9:U>aݶm'pH`$ʳu}Ͻlw wG~㟑p3L6*0Z`P OMF% I*8J1H Ʋ __%2\`m!c<݊\k>8FtE<049lKљa6:F  :&gL;\0P3g 1g{ĭПէ: f]2Yy,~Kl:4\)0R8\]/<˥ГNdprpʢpx dP5.LR^pYQ&K|^X{FأF52ճ}k:t0Qc4tz6τu`lޱA LޮBHkf'I +,ˋ &e>`>E.s ЩaNqBFظ>[| xYQl[+}i#ΗQ:NMg Yv+ +}LTQ >̾G&ѱ'ұLs$._ ? | #ج`m@ܦk }r@D %*mm&ul-8 ȉk= sLk&^<tdB8b+}8ց'S5E)uzzIΞ f@mV:TO*v 02@޴ms3b~:J P"Bg?#A`HV{ЊAj1*23QqN*+üͫJ4+s.]JHt*AQztw҂gҹ3g-:o3Z'ì3uBU֙hkf{v-YA1^JEwkwN zB@CZ4VDr!.:Ģ„X#tp[5^KL'g `cwoz0}}敎iiԟp~ܤm7|J>l+HSۺbNcel:¤GwYz-vpTu._5V+g)2 Q-i ֊έʷdVUwuv$e/ ?("ID=_2%lޮSϕV&I<_ngM3gP`K9B`nл<%HjMrF 2M,2"8z1D+ .gr,Xp:S'k.bmj@mo6KZŞ W#91:?7H%TTԧi9,65l8 198&#32W4|dkĞA5`O7Fv% SusG"vΠHfCT~|]mܣᦜ.OҚ:7DвmcEjڜsϛ <=^=r9v''7<@9G2kM$Us3 t L{"v{j'`痊cMX+}TeOӦcS~nN:RA3oڏUOѴo?G~qv:+s؊N5yX&‡&>^hʢusqz9~5F9Z/,єG}  ڧkҎ6fl4NPhvMX.0^pSYNNc =\>EGo)}O(\'=1~>c6|Ϥly2D8@2|CV2n[|my*§kґ eTf&QT(0BgYл%/&dy~!u$IW Hz frE<W i+CFq)Gf*NE&6F2b SXncM6TŽhaJ@؜+2qLHnBs*g&p@f۩0 `?"UQRE gpxd YA:Qr[M;]L~Nïs{8Ҙ3w g`>B 2pFbEMG+>|:t8?ʗӃ~;G(!>H P?Mkڝ,1G>WC0 {=s- t~@|_A4nN:o1=G~Gݻ@1~ȸ][jz߽TZjHH__, ";Ph}\?G;-{{w05!x|҃}/a)܄*B;ޓ?Ln?{W6 k (y뭷wODrs{s=jX+\~! hGaimϞ} ;cbιsBYn$aklCеEi;4p&4T]v5 3gfIJoLG\: pWKڝ F285X^}S@%12rݮX~MMdXOPyׯ?rs-qE]u ,^*Ug8mW!Qb`bHekKpZVtO35!(*u鴰JȀjbf PC];(:z25[_}57e!tLjHjjYM#B׸9᡼C7Ңua),T^2̈dj)[c1 ]Jy{+gOryܫAs{5=: K+k#4\ %+lѪQ¯B=crcDVJS:/-V0{T(pgaS0uiQ.א|y}V+-%Ηm{(nxxh5Rɥ/ee?loXe{A6@O`KA#={F-8I&AbE+:[..PyHeWҡ|RLaZK<$milwtTunNഴcc|o?pEӽ=S7~z7ɞ]`Ñ'%EY{CG"8'mD=H.]Sܚlp2J.H߄vcI=~<1-*y!\u'8x <'8+~٧<Wx7JniH&>G^\LY\hj(c Jh{[=yxKl[%_>""Q}b|2_GϔftlҩI03}U:+ $آfXiz^C~9~,VY#( t,SAw\ױLb}&pq htsj5`Pm`NPlV$eW<v7Ҧir%8q %$M۰( ?˚t.QHT٠l@2`>7_ G1Y(&/.O4(@◼kdx)'RZA 0Xn{ Ug! @G b bne(Nx7| Fpw[Лĝ !jk瞧#tfc'VIe)<]}vC=E]|RW1H_oʹ/SA}-PoX#(* t 3 -0;s0(CZX^Y \թ _ćoєd'iΠW>oTw}rwȢM֍ `7:eR!fWC=uLā-۶L6Lhih26('quҘIS2 k7P`;m.?bcS#Iv`ϣ wV=_N߷B[$Z@{5saD-B9RL&IiL]FV,wYkOy WԣE]]WZ쾩g akW:s/sV7zk{z&Iyig^Sv Xj5p 與Rz5see&P-I7l0dx.7Ϣ' @&Յ>70EqP=$A~a@_^c>h"qSouy>B;;DyE5U܃:}]8oKK WϘ-_5+!nus}d][\_]}L*4Dw NJ% a,!VOdn{h|& hRȺV|_"yA[C\[[%?;/Nr, S$9y܈I&2!tdA}f #G d+Dz#ظʇgϕ!Z;@,'9j71un$G<>s$DʧJw=ڑNҙm3;GmyF1s9RL71t5Lc7r>(G֚dGY:y`c|Df/vGb/fH.`hCV}]4g]M!ws"!utoҶ\*2*r8"8NUPmcg\4nmeMr sig!oy x9VBm o_KL7<]Y$< 8i{6!(sˤ2^RFh3A&=@W0g/dځg zo/1Y|.>??CNqy5|VUaa?"!{g+)gˑ&+#2K{%N};7UmUNGR`[F2y'S|GG6UD]+ܒ en"YB%,4Sp`s Z T _QҠ̭#eK2S`GGGf*M=J-!>cs-$^~ q+e^{_bbL!t13Ǖ2sd64f57Vɯ_ 0?oEH%4^&#[1Q/3[8qTzCm9Dsak֨|˖?cʬܙS8(7œM:G?$ 466+WƷ{hsy gmgW)1MmQzsWSlBX>ƛvygBq޾톨(B覛n;]f'~o-WݹM!KqĽ€BQ5fg-EsbW_ػ.;gqՓV7`,)mҩ#;# kLQ2nVw~>PBy:%[94fz@ Sidx0{D۶J?Jdj߶;EK]tXTٔ^: M۝ۙ=&{r^, z圆z I ԤёPMpG G0x`Uz:2=t~kex::T{:04tقqte'ar ΅2:mhy=z-^_8%fCϧ3x(TQ(BCv:= F$r7*dL A)l:#`^:lvO`x c)]̙9HbH5t1_Sey!3бΠƖX s]&-px-z o:tzLȨQdU5'vYc/L@7xΑtGC/30< >>›po GH@h8׮=Ec6"a;v*rۅ:^2E|fr{cINn9zg@~f:7chHzidw >/ q$mO>%pFnf?:m;x#^]A|7p6Jc}{>po$ZzE{cy WZZ_n8mBo TwO)0[X^sr6ƞyn4!CGg)" 5* dϏa8 O-%YHtgu`s\O>(^J:WKy$˫kYKZ8jԤB 32IC謴ǵӎuH /uddhgidgN$=3AN_ˏtʘ$|_v^3\!_WҘ]溚vk cſ7Q|gWo!zZGG6ww`|w.[&d רb 2s|ʯku?p/s]_ϼkn| A*8ST z8M;A $`0ǐbZ,%)h$8/s~|I_&YM(t>Ь2-Cx9;: @⠶Jv0m^&Ԣ6I^:}Ot 忎]yl*y @^\Tשp̬R1ؤFNtbQ^[wf H{og# E!Tpk3 b$QaSyNJMkeB<o)NAn fڭ4*YzJ>1X/n{,P|Gu[W,uNļ|fG]Lk^XɊ f#v:V)˥3[@WH%aApS:[$*+7A]3Gz|_fbגʹמR_d, ZTxfxad x64s0oynq!gX]AY8cd>T9Bz65mED_ T gd&Gؤ+8vct'Hv|Х$j#ֆ$G@Vj.j. ҳz4{a{mUЍA: q/aԅ]OK]/\jtSZˬŵA-W%$ItauF1M7%ػJ>]H'ҾыtHç:IȦ|l ?b0$xEK&{_J-YFz۴5zqrN4O`:*'>0pg{=/bol[D9pehNٞz'ҩ#$̣TMWTpGU=Csh|'eQ.S>=ٟ6?iԁc2|`A<q &_Lf4M-4e;(_>̂0qv TD6n*:uSu$v@*#2'Ӕ‘mM_@6A+-鹄AX*[']$U џoz]TQ]G s{[i4 +GGV%mjD2c;Gy`g! {}ӕ?}Qل>Ӫ楱\̚)Vpj+`+ hӊ$Љ5hYta` XƶUK5hN|̡41~8'i(/Omb:@?>3<]8N|# Gd֫asc}aE\UwE8^fv4C}V{QG3q9wp k\|Y4Ō&xH"ILMMM|y1>MSd3o48A\:z]o?giOݷ?⍎sgOz1 !<̱ラ41Aѽ/55="C. *2:*h@J13(7gA'n۞.?@e镗±4^-i'&J?}{鱇3 īR)ɣx~ykV5O`I j҃.B}){5ZWq+z ^ Ɩ^M!jkrWl=DrI*>4c`З^ɋcQ>jmm˶|6G^}%?_c MTQ=%`KkT@@'<"ekq]5w(U * apJA5X9s4 l铲-6=ÇLLݠ ?hX2u, ϶:7tFҮZ7>s:msk *~|_w-t@IDATU^b]~^HE-" qyky(U EV&QWH;c B ϡIf;ɐtё}Vl]=qq)';C#M"6EgDHD' u{0୺ luYqo.L9ҳcFGq8WnAZQҤRv!p e/Pr/|޳eLɏ)ɘh#m%:Jǐ/?uP}gceetE9-&dHo?Bk>uR^\ugzIA4QYDgƹI烃!C՗lp"gQBWP_}sT? }9Gp<*sAc$rcxa~$40~Wemsݚy9>CGgǒ~K^(߱:?D8NDA"G 5x#<||*IҹLWgSWRSY/3m;#nDK}d3Μ:Ns^}u~.u[d>M8~ ?d>Ê>>#5ܵ|̏, |sSA(vz6֣$x9<9g}׋[v*W-SQKO"13f/F9^%A_.u,nnp-^ Fɩ~=(8-cI=9w|FZ.> w(BVdg8/SwX@AFVR"?(gy0Ǫ_'y|#Qׇk3$|CNzտ?;py dzٽM+" isc ζBeZJF3ag׮on(a|===i&m@G:Rߌ }vo~%ح V xsdFtuʷ#0C1Cc*c=@/VZ@t}+# <3h)L lpP_;4OgO3Y 9h*d3IٳK 4F~GdCM&ۑݔ=r|#}eiqWҗ۵gMPR\L* ț4lHW,_0z֘0Sf l(OGD/ɒՃ}ᕅ+V(7w (`cj[ZVڋL>ƔҘנڥa)x͑p0;?A8m[_ WLTv+cl2]; &qc>+)%slCNбЌ=̉/PD PfI*tTdhN^n^d1 [6mq%Sa*S ˗.".`ϏZ)*/qCAzr|&γ8\* =?ع'TVd唡7G?E @hxW*gP]<[7[2e*])Rko'0~sϤHD <ڵkw%}or-AwU`vK?Rjz҇Rm'17o F{5 42όjtbS(>K8a7-{D0yh,ZQ[t#Stޚϗ8sp6[J@jMY[}uy ,pL9^{(m@wǏ/?xo.e$}I:tk<9VRٚe 3 Y~>-h( B z0ОNeԿF Z|W!Ns/Z-*GFXCW(.uaFҏ{#lx:J 96eYbN:.V7[~AgYWm53W!lU' 7]1xۀky>q:Olԣ!9(fG9 ?crHy=3;auB{KlOV%Ѫb2g/[F$uצ&IŪCo5wYvpÑ{:t"ͺ?|A'~8}xq{쑇"1ڎH>qow/~tt(0_yOt0ck`!zyg2Z_}۲Lxiq_i|"$ ?#PT*܄Ƶ|QjurY] !dt:2~ܹpE;0ٗofI əNlɶlٖdْcI"邢Z4(?@hPhSIڤI,cǒ(k_IqIq}߷>{ٴƖ+ g{==~;7wHϺw!S@JFxk̛p dLafkE+Y:-%2sܳbCǹf;!:Pq`0O۶eSNcy-/lde‘DGXǡz0t0& {~L|=wgғsˏKJ{N/ 砖mo4Ƞʼu D_^)C}] tcZ a)ؠTOio]# {_y k ֬ ҥi?B7*E+Ӿ'>G0OHk r,S%h.CBH n>1\tVWcsRZ/S)W=cu*+dwsƷձőHO ބoE:PpR{o^$ ,;1D[[+dK\]HR]q|gZ+3/_KM`i V(WD&C^K: 2ƿ;G l m%nk3߹@1rD8z>q`/ aQyI"҈[^ ?1{cB8פQFM(@1pޢNv& X3"c{.2 ?wsC;/ 'l!׭}!ҔAM{X3]ԽBܽ; pH7vP^*ݻ£=|@C$~ Gn/d&**i֭<1oњt{=/yzhŪW817"6-64E"#;yۡL\F!|& e\(W$:*9ɪ7~VY) 3=3}K$lsi2W2{С{Kp4; MMy5IvٴW؁XW35QH`F { ]i%6MKØdه" TRg_/%.֒W4H9nj}EFz6SRzQm+ b} 8]@/|XIƒ<#h߭T_zGASw+-Hvsst[A yI :_jk&v_/#0Q%V9gڵJ{$? 8F#_X'7&< z۪T+KX|$~䬾@2۟gSI1umQ"#-Uf%B W1 U] ^(lZ2"ULBGsc0 lxzC@JpV GPJ'd'$2{zpp_**]kEgo·1#/S2L>BPG[90}}sw.P38u,v>XTm~gt?K~ 1(o})=paT\/sDb|`?KO|mοͯ:YfT>s[ilʶȊ|gC ѳۿ!H2/^w GwΥ6#qys_ ښct*Γ(ө_zOSv9?8Zrʋt[𣏡6$NPΪctĵ;Otvޝtj6mck1QoFI ]XAypfjli$ Ӊ/.Zhuq`:tOJ%/r zpzPg=Po~3x8a`:KqyxQ{Ǐs|wK ݟ]SV^%gw`(n\l{muyʵpF VHD N஭笚=ITZU4=WH(&+vm' {FQCUpt**:o+ .@v⭌diem} bF:$AL42(JdoA6χnhf3IϞ9U% 0S$!S3FUC<ܕt&jh g PL#TjԗVO= j1Í L8l j̮s[`ٕK1p>w$*Pm֠`A:1Kv7\3H!YL,c&0Sjxa6i%2ot#c`At4CkoC91sg@4~5aS Vgh~fob]Hׯ\$C^:(!ZTrxqh+P:YV Ƹ40iu gj7alyLU#pцt'S{u|3 %[½9E _ل5̺ۜ=T@n+Ox4o&/~7бF;:6- }gb|XA-#FXbNti{o2G"eY7x(RƼk%-?c= G1Vqa|#JLE䍶Q? >HU:t\/kg.?xEn~H`V=1Zfw`'=,j*2q.<&g<)oz]]ǀI X?Mmhu7qv. gڤ&ݠer}$ Cwo/P9MY߃]z]~;+7uX%>) KsFO> l}F t +r[ŕV!)q67vt#2sw=6?#n?@߁++RQOR'1Æ[h2goZ9)|:)`t|F\JK }51`.<tNkhB4`a|Yq[~>Iʎ<.|w>z-ymCO+Atqf#W#2rO7n`d\W(!MQ.w49t} +[x#m)IA68'qQ9?jY~Omnr"H͘;rey7~6v)ՓL)uuq_š b톩 28W 6p'iXE?GubO̱\-,/,Nx9rRqM& _mW~g`_pl Ah=:D N~XUVar6upXe2yɓ{Y>lrxYv:P2`ʜpu q ɛq*DC70+]${د l+|.>e^L0ߌ\ٗC= {om ,b›v8U v@u4.v ʙW._NpM¬"0Ğ,oYv7[K҃:fˤ0 R+M{ 'ISO]JF d"5dPܟ+Cˋ|^$oOY#6^D"Fm +Q=iS[>^zzmI0;2O.*gװ9:'h ~^S]@)tQ޵m$! WTXen376qwh @`#mm{ McԛW#_9ND1vR\Ga.Z,KA,^# ^۵9B0IvHcz ʣgLq\}K|uOߥѮ>cOSމ+|{ vޫ}gRv96z*<׮yet[G7[Rmf>3cbf3҂RP N |7&HүCGm{wyl#LctA{8^kh$ٮD铯ZdĔ>VveW0 ܆^Df:s)3}By W! %0))"_ޗWKV& T_'`(2yYZp&*]]=}q.0dlˬb/Eo 83d~ -c+>\+wy1>v3 Z M>APTZ'8C|.#S=^JK_r:BM[Dϝ;~~+hu*ܛ0 _~%$$ȥ"7~p"7Ns=mao v``%ɓ8 >ztPƬ=vtױ@۝Ea.>t0`bO=EDF8Ѿ3#CNwݓoz>ioc#>gK^L֓ғg"Ѥb~1J/u<=98lk|W`S8xTJQaS++?FaZ]Qs)ﶥQ}~(g*tڸ:):5TS}y0'kw{3(VTVq:YꋜI;+}TGosCZЂz c9}ֱVS9xQKO)gPejb0p\> (0J@!:')/a,aV6{ldz ]dT7]g5ϸy5̌6 n$AK^ikkQ{3j0:#%1aG%e#﵎"'FgݿU%1& im,L?lX HҀt]ÂiahDZƺ]PVYkTvZ7N\3g roMH'LnagݶƾVֶ3TFǰ]V{qc4^; i?Gkh#̩'fkPVN$2 r}ʺr0gb@ :{Ƀ~ =:-XG6{@,Rϩ5d5L4_7A8:S;/y }^d}bo5;[qR{wO@ }| Ju Tn[ש]zGL&5D9) ̊@hϱ&?W).Ύ4"wB~U쑕>`@??=7Yyʓuh`W~iܻ f|a'E+C+} Z/+`_Xo0?^<'hHlո :Q:'3锪Ş%Pysz0u^NC2 N>cB~V[!߫$DsqIsEoVl}=8tH[t۾{MlʺK;9~GyؠAgfj5K"sXȃ^&0VMgv vQn[O[ф5ەzLn"u'_4ɮ/QyDzTFޞNơ22р{DV=?<7QCZ =) 0 ?`[( 'KЎ^8YcHI>]y"{cqD${Nlגɺs&dX >0= wC'4[K(k P@hI']WbSw)\O]]D.Nc Q2wub}2{1)ӓt`ϬPV}WK hA&K ћ~7~=Hs'y&2" (gvȦoq*^"sp~Y{<ysC>G ܔ'K2BQ ,r, eYνʆн?Kʈ ZW).AL@R3an翞][VL!D2"XZŭ-~V>& { [e *  , ԋB ✾i[[+hD` si8frYjH^D{SQ}$ɱǍ7N{ȣ<*3RYt_ZI1VM;/ Kwetg2/ŵkK&yAQyGC|4􊫗/WHlEV^B/iNׯ]EOZM} VުeYKOS3MqC$1?iHzY&τeWI tۖW\XC#\f=5M;,b9Uڻ/"~VKxt#Yltv\!xk(=Pz䑔zve'-=wس1T Ѽc|f aciw7 Mn,.a_V질,DwΟ\-ػt%uoL⯝:]9|A:Lj؋.w6RSf\`0IG*T455G*ŧSϭ & c/Jլo6: nyJJ'>juzgө8| }&Bo߾Q;9z_'(-'`)p]wu7>kO}E>!\>'S]ƹN!w%_Uza0+lAؙ)xAo*Q&u \ydݑYI@٢ǟ{&_7PY&]a7{1c=BRxz㜷Ƞv(2f3y"=?!j{΢ldQG lC:;'T8ѽV\gR*/}؛Yj z+uU)_>,~T:OǗ|V֡ v:<qNmXko~EQsr)nytdtlR(M|'b}:~1Wa{͜W:Bɺ)%/ED*t21y30&?bz*-.]8*5pv/1iHHYmph+ejMJVIX>D=28Scv˶c6}E0Zr  yy{ ՚յxh+Je]ƾQW@: Xm <6bϷw>hKCқ*N jN+lnNc!I#a$rdzh/0:vxwN槣`ccH\ލ ":*]d2y]dey]sglX lCr2M{3ߩg avmB*&\8yxA9w/ ! ‘(RO/>tBH13 qtHr .uF@"AՁpt4ju6f wWD+g|ݹo0y*/[{o|>,g6U h^Ҋ$k +*:0]7 +sy V m#1}H s.;j8N DI̽${D%-*kKIpA';Q ˯ j[WlOuK 7gØ:!7׹:9:F]I:rY YǼt\Wg:jǼ{P+d>p,u0Oy-2ؾ}72Ё-L1ho"|11UUP5g)jcuR瞗QG 8)WݛO} 6MxPcQEfYzlAx_8QwV(դMvoIRǖ^cᄐ[U??JLu/r|  TЀ=lb"p+KV) t0o C;c#$+]fy0\^/gR~iD9jNLpI*,2RՀԈgU{ys{c]|,/K*0H ]X', _Md f˙wwOg"VaPSMx.Bs T-[: QU1S}^ĺɹY>2y.}Ron$ .RfZG(Om[[.Qg s9ys]&INYZV`|9ѧ Bʯ8AY>~ ?eV\ yQVQ+g z1XTב\90o?ҹ7FfetkRU:>U$`PA12rSڵ_`mAy+kQɄ#?G`P_*2s?'Y(*}/SRx7yxs}V:VGCLhϊkqC{zG?V~"ĩ7h2ݬVTeOq]$ʏ?~"ɽw.?[gIֲY͋>鱩@Tw{>2s&cxpjN& ޞ]wCڶGƀe9x:GII&o-kAdᑾ^HЗGK4#Lhbف[Gn*cIۡÕP׶gsJ6{l >˷u}ꬑ<΂u6B>m1޽iws̅~dŸ]Ӎح&ha򖶚Etr.@IDATյ i`=[܎ >i>d>W@bAHz18'm߳M ssī8ijl&3V]Tݰz%y*C4?I8ho:7p^&l9DlJtM]ldkSKd9P nb37!L,\_N夈;p>x2uT"I&T8"la@}=GȡC<_LS+Iօ9ή=8drYJr}] v:3y~nŇ~fٖW03(闘4Ogൡ`FeBˀ{mI`(v3ZK}}TzfG;7~N_Zg1gݬ-ZfڅV<@v@GF8s0d {w 1g~0>1`b4#v: .G0mkQ{/ߌ R <@SJ:`8yHHh댿t-۞=> ;̟x<>૿֑>/2FK|PC{τRfK-Cm ^8>ϧ=1Մ?[M2YBcqs,UR!(H?; JH⇎Bu4b`wvv` y}a@3uP9gs]?Q>+Fҟgh4 Py/yP?YV kՑ0WH2諂̊WncMzdpod\! MTO!vZ/5ZO, : f*o{t 4DnMѕ\:_XI3Zc!FN9J  O- c̪ҀXpTި,x Ku5'23*:㎶_%ܳ9 O}yP:[ ( t ??xp8 e Ff±P&`cJ\-֪ r1l 2 w Qs:gµUXo6x9 ";g5-R64s"L ka;iT{9 r 1_f͘dkKTRalt]gAh{l cVp -:Ê_l}eFϚJv+*tRZjfddI>D=rKZ&ƭ^ou5q>;58۷T`{ ɟg[/+L <gpa"{" m{hy%&xy3OY!jX*֭ẓna>ja>GMҼN>2om-~2zs=%yR!dGp` >#ză-7R\Vb;o/ 욤V :k~G{A-Vϒ恗<ٱ-;lLu,kPtYg?V}|0+.(g|VWP01dO b-טJ&Óۘӱc]dl<,Ѕd \A;whL q΁p dÄ}^HTEtbU:[DlI>+t(\χ;t*O\,1\خ&8JbO2<(c/|gfJktN@@5Lt\=^gUR;%gkHc[ybRK sd%3ܘv'$"ǭpZđFp0T>6#ؑF|Lbzz"g Č*WJ 8:,]!#oЩYkPGb;8ccR.d.>$ߢcgN<V< DZb]aG3'8>s._ IX+dh+]i:t}c#GOhޤK.q--?>V~(LVy~!ORIO&6]Rމ3ʾ͡^x|% {9A iwm}=݃q:LlpVLLNAhws~88M#*Ѝ !-ҭ޼ձ 7/ p0V~<慾#uF+;vr.]յFe7HDnz)xܪU\\"P{g# b_XR,pϕFreқ2GTh֠p]<*pR+'Xe֪#؛*\@*#%uע s.d0匼MLQq{Gؒ_; `z 4P[H8Qi MY@>UY=\]F9/Keb6u4Eiϥa*w5E ܗYNU %85ۻgwG iq4!ְS;4 n'KW&( pGUvv26w졲fG'@!%oP7ab&^^<y_KAhPe Cqr&ʃ%)eү,# IfJU\kHM')9;;vUVmH N![M7W樷"'|@PAy0s]ͥIY|ʊrd庶iELh,~6},$tmd5j=Ռn1&c TYIhu{sx+Unn2?A-8~`pg)1T:*tr4~ytτ4AyJk(ieĥn# Αm0YCKEA#l7.׮]M/M CPA]|h)o*NV&B{/Z/ 4s!՝zc:xe:+T N- ?2\CYdDV߳wo$;>W)Þk \_|W#,8Q^&y3\ f'fvYN+{34rGvpsOt>|, 65mH|s@mmmZEфIPTWpow~x?B@R^`pvbpNK hsJ3i0_Y<껜%ýG{9>N~2;4`J`/EFPaܢqy{\)ө!K@%Yd Ƙ4lA݃C#$)xxdqRӮj:ڌW/s!:Dޘ`7Wi8~ <3*ǷoqULwꈫ&xRJe(R٨: jtu,FĚ`ܤ 癣ZI/\6A%Y:I:#߱wo/ݍN}6:{6ڿiwoo$nw[\;/**oe8mTg|_6΅ .?rvXmXtZo_q lGz%V\oEz4ͳ^aiF+FS.3ЏM2}9  ._*c8% ]]oݿG|W_C &u*pA*w&;tuJKi}Wr$CgU.{r 1A Pn}9anX/JXՇwq_>gR~V;0xnGZ$gOury@`oW:Mٱd4:3Ab2/L<I&ӗED:r=lGx;d.c* qpN'赏cQmep]x)w*8{mb Vq:40zYMN2.g_vQ\MKg|lzV Αgz.I?';07і 4iRǠ[ER=+E,2~  ʔdžܠ9>4Itƻ;h+kgл#tggv۝B]Q~־l65ds)u2 g7Q%*ޙ `&0Il6:ǘ*/mbܜ"Џg$ ctJǹ64 Xk%GP~"꫐MkM:'aV"l _8~+K&laۚ(  K44LVC˧@̕0wnn+qF{<8 ^[FRR#mvvχ fz|L:s޶"NBI²ɲeMs#TnS9I :͡H$޽{;M^":&m. /-CvCZ'7R4}js;հo$aMӢ@" ',1FKJ5.0詴mo/rk^%Q{cgvN)mSWLfxΞKǎ4tdT.GoY݆V mdu=Ӷv~by"d2 0b#MAϞ9]mK"8o~}$IMڠ G] dz~@09S,BOD'G2X8 ߕ,W/mVm9u 1WҊ$B {R0@{S]o=J_H҆|^|7@>-L#g2gO|!pt|:EA[H `I'(ܶـLU*㓣iUzn\2s$h.yqC"laEUG8:sH{84K]Jyj_P6dƫShRbzM5T#>tc>2K=l~| ܷM}}TtF W/("X7mM!;#JFOv^!CsVR ǚ+ ELtW_eٷBξ}5nSy 0ЁOp@FA{{HRH]G0VNqꐀCH~q&*N-fk&'gO3X_}8k^;V ĐQY\CDgli}~׹q%Rm5aIoycdssT<*bvRX+o`TN" ^Ñx-lRS 瑼Lnut^ijggAs:C1,̢ցn[`ۚӁl]f[N ʩS5סaզN&+YZ o~m;:&_AA^-7"MaQ8*0^p3[z'4a7˾5rk''ǠHuS8^{XN7^{sbN@\0qKNxh G30O45!Xqq6]ү{A d\ݚu|1?9a&]isa1TC#/ DE9':ppܟ8+d:f1ՁtI//ΐk=}Y؎5 [$۽$e?<^[vpa<7 5/*\UZ1eO9jeu ;+ 81x,m;s둻ο^5IKVbijto\ j;YuQd$ϚkfN҈{'0@6LJ6vVL܍_Bn|#~lQ|HYzY&ykxv49(n+'+m 3a >F޹UyGzMH!Y2w`rP> "0LJosCjUc m{yVͶ^ Eoϑ/%;' ځ Xߍml+eۿ: HX#~ ao]bk ԡz^L_嚶0AW_.QmPнXAҊzuGtnK*QdrW+غʎࡌk6M^):MҎ|M/M Bc~Ѝ8"sMW٥e[v8Ar|o+k ̫ `ʸ1;ixae]gq{}2 琷٠ "uϞY X2+{7 l1uB]څ 㭯Y) ??e:"u*B&n>baA-8CmE*<8OpW-}]ۀWN&hSIR Byb#[vc1p|u ˴[/wQ}$[XmX ,䭍 8 Z $Q}PI#N&[ҋQnԓP`yq+tHanE"oWt& K_־Eޫdx~<"@nigې #M)0a<@u{-ݯ j,soBx4 36ʅU>D2a53ׁo9G3Wė];ڰ  n[fCB9G p⏽9[kPyl>K]bRQN% 7ZZry2@Hcହ y`$r?>]8z`]Q ɭFW3qg]QU3&0'?BǾ)"hhVIia[p&xo%W†SN$VnC;A kGcn.WIcQe|f/6uU[e½Q}p`Λ'QSV_/=qq9@!웑t<:a*^Kk *8]M@ԉGs|&ƉÕe`B:(*Z`n6~]C v=<Ǝ3HggԺfNa[KqէIhio^;ߑp֢VB'F' !}07[bC|F>zyЮc!GmKc[lhbzbs;TGw=CAӑmevj45,tkӅ=E %yx,W# /c/:Xg/Y>&|US$c3SuEU ؘltr*,UOW;(Oɟ;W7_ y7ށ ]X"OPW6=;mبâMṬ|p(L1L`w]F^ڙB\k A2*RX7:2B:G]r >B>Kʹi9G؝vuh/$^MK#`Ņ`62`>Vf Q>Hr[^JZf'ɟj-9GX EטI%xx*`UnX L7eyYt/gyz6kV|2W]l"N}F wκR1rW!9uAM8F ?47SopܮihBo|0 F3<}dz2P"zѬS'u_~VRJR +;b1Ҝp^V<*$:WiUʥw2hiᅀ}hd c&&b<+$߹t1 8Ȧ ?Q:QE ¼C J㯧'_2~;ʾ޶T>s"S$ ܵhMSO?>JTx5]Dђ fܶʎ[ce^8Me8J4˯nk: ߥ!BG=/@?ÎQ mr1ѩc\Sޫc Вc`€Tu9:ZZC˖: TBww."){<6³0qa$6l:46^#VP"CwXcC(:4= (XـAFA\VX-A K;4 L)M\REgb +Tu8cj@C ʹ 3=YdUti͌cYeLΎ^q -g_s`*ydm81 8|q]6 X]0^ ^8'W8|[9>EF/X(& %#rSyTc;KP|EU"g;\(G#HZg: M-$`O2o&F5 g:u؊':sul 2NZ1&`𷊂$LשQcBNϙ` xdLG ̫A"n`$UD:g|#li$֑ˁrchhs֟.X1ksL/ʎuzŶF|su&Cᄔmp3\ YTHJM:Qfg-^Բ@:3 ?&.ymo ti\" hlˋ//87O^!П_|T0 l(z9Ztƨ>ɢM.+E k Cԓ@fm.ڶp2EqKDZx8١#G38"%, p>n)gc{hb&I18,,=Z'{&7&(xҽI/u^Q 2WťsC^dU3]|̇x(ADŽk7aDNtF]ޡLH=W֙@@~ji}iUyУ>Lⓕҁ"x Nsp:W \׹+G[^Ar݈`A`r8wAޮ,@L@';)mg pb.BG{:7n B>pai_=!-l{Ϟ4n;#\1=&/k$\7N`τs 4Q=km! `t2ϑvX^r/ӱǖVP'xW{Caձ&t"~y.ECT;&X.n9yR0;؈HhT"=3/ eN8y ޫY<S~UַQ̈8> 6Y;N/H?:#8 mWy\@{˖E‚m _Уlߜ\ow"G\tD~>feج3p"ֽ['d%]vL4?y:4:sL/R%zW D0v5 ?"HλM`ob "5fCT.nWh=5E$n!G5!4뀷z2pFH?|Vw9#KkSܱݿ4N5\Nlq|Kи m{coN6C&7c,So*L Lzil"v8oV^!>ۥ)u Q["GJcL^"ބ[oV ӽ;RkD S>j(n,ZAf}5oP>M9$t$i~Aw釒f< :-d c~TGзMw`b牗ROߡ^pBFɹ9B.g;a l pkc3 ewo;J5LR=-P;Jc]$[\='K]G]ݡƈHHəYL&&MV&)&w3N<͵SN57m)0YyV<7 M1gmMa~TIˤ w7:\!:ހ"pة;i9;As v@%z;D}@f}sazl.i@,$eUѦHYfYVKE[,T4eJR(BHQ$% ("l Sttxsn~Fr$0}{ .U,_&}yoUXN??.uFP*ڞێMG͗JW)iɔ|O@ӏ؟%qQ= Ϥ`|ܹg;>s1JnEVJ捳l}[#~}8x=pUA!R?4iihG^H:u֭0e4]x.{xdBq1C>pO49,t?FÑǏߕ~_B!Α7)|ܙcLS}K>LZ2/_[t]AzJJ/j"e;t u|{ez>Gͭ/e|;6˗}lM_ew+:,,рB|9 UrWs7SM-9j~~@.LD"u}845|4`w. Ho[ *V;uM*db=FevdNf2 >5jucp:>@*dAiC0Ϭt5{:m):{2:PAme6g1q<}\9[ vwZy|DLW'<@p8S #2` /{EʢEaRX5 8g{̗8LbCh9},X*d*quu73 pzt/- ! :#1W&8B @>^{p 01yޛ%bEEfPQ rZ^Ӑ2!*n:e$H_1f*^~_{HBo>h%k`$O_/598{\ev= ٳg,k)83tx fs25,M,P}L8^i2OEb#,/#/roYᛁ͂{GwuC "+Q:e,~tJ:¸ET5#נZ[6mTPyGPU -|-wp\su>UxW?A[8D0d.0\yV ڡ@:77\{;ҍZr`` _E $zOB#nQKа9n[(̿.lj |RO" V j[ܶ;>f$qIZ_H[lgoئjU{ITT? (5Lr-H\x%S$LtNׄ.JݘIiWY|?pU798xfU'; Lr8myVII?c1Yg$Uu8cDѫ؝l 9^ ǫ-٘!awDR &LpaLk~RIbesܣv&южV^to0ݵ5 @~6Ю\ f$A|YH><RU&1칼/ɓβd%ϡkXcw0[k,+ρ8FE eu s%o&>V ]DpUd / ױ<⠯;욧e(~"^ڐ]Ä#_oL2k *_J/)_ִ 20le:=XE1m3'`FTF-۩A=XLWyɤm:AƆ<$6|q4,n\CǮ^ŮpwG%`WXk ׂs,õk/2=Mhh ѯ2HnirIv+$Ege*~EKLHc$ѭyva=MoU;ĸh@*~ |R@)?=}G;4;7pvǭwll[#]txxܪ+dxwJA_UPgo37'9JO>1g-GN1TW ,ƹGs;:Q _x5*#ya0\z=Oy}!& ~3ОsY3+li@Ť?9Im_ }IVk׮"#Q@Wy$:|ܝ N{ϾhՍCgsx9Kmu>UĹ\ATQ"ęT?*O:x-F5mnnKmuA>3l,AV`@DSmLѐ5rSd<{]aa LptTLR4yW:˜q.hJD|+X^'UH5Ayf:Ð70x숀 A0쳶_bBiKW {EQ$1qpk!Dȗ dX*`&nbN f:N2}yUz̑^8-oyDأUZC˥3䋤 9{I|vQkW ^Wtu pt$d Ⱦ˃s^~Ws|_@ @Rci~~O1Z |ώGѡV̶Kop~~k*_[upZm3V~msҝ5cY¹xDρӪ2'3!BN:؛n"w}㩭#=2AEdȿ_WP$ҕ}Եygk$.o T2uj PPzc.q;ϑ+#YWv!ޠ݄ސ `UqQ1g~ᇣ:YNܣ։{x&2(:,Ƕ>'^z 8C0Po~t~%Y$|+J#\"aPvw&X y1lM<^:o`,?ґ]+_KSo__T   s/y,۝ Y|9Q%P FmYA;Hf À 6:Np}j/]E~3].y&-풢 vO⯪'[ jmjtE ip MN6rBˠ3U!d]=^kC4/\K T.Tq/vU/X_NWH[]M[cnm kʯR6*[+Lr{0;wJ٭=[#lnjnCo@<|$M.TC3aǶs~eJ\uZ<Ӓ_6d[M;j hS]gU+^Ku`{_)ĵ2Py3'm c%u nQA8M&7Hg%8F-um< ~LnS \9_E EbG=#GI"pCtҏuEWUV4?xb5ṕQ0'4soZ>:N1tAz&gX/ lnG y/숢>Ӈ-T-C+<\,A3K%oleG*O;z/Wv ]ض)/22yπ#BL^Ta)]6hkHsSyܝzx[`291ASk%8Ow-g7ٵ#;Rz :#]A*trMj{W7Zylg*(0pZWA*s)H[lj7=iqj{sD{.t,C5`voê2qԏ+mKm 2vڢ*G ;9lmB:\;"Qܚ] RU^}:L3٢.&vryt.v8%"$a9[^(dbB8i{ؕ@=ζ{$-g|Q&>#JܽZgWIvo&dT-drؒs=:A>[ʪzN<,# [qjD'E3RO8g$L3X{g {̮{WzQ~S3(@; O^g*`Ɍ![[>!@0Ä}LCPGA!+\st5Ѹ1`|b>_!Q@^{-*l=Y_{qFޗ7H?F Tp2Sf;oK v:9[_V;Ⱦ89H5+T1*MV |=yhQMO}D ʊRw7Uܻ9*l HBY}=+SYeBdr"Tl*'@^+~)YM&P`395PiڞQL!?tpV+ϟ Q,f`}m<|QcUg I"E; ;[G8j I*dUg.z$BB+u`fgVQ`ch\A8ۖyf;;F뫹{ԙB|G9.Pl^g {YDgY" ne2s,ӎU^'s4%& L KJ Tڐ5`V?plsSwtoK_N[ٗ.lSc+S})τ1OUzlM2/51@gHym !uYi:ӌGzK;D_$c\( 9tPoKs8 | :"iZgkND^H2 l9Pf B~62q rGTKm{ # gQ]i* /xygЅUg"4<`ڂ1v:S p'wNRT'[Yn.(Ci;RNnvv:<^^4ζfMʩF}?B\>Y%86$E 8=x.<8]G[U"h[iϲ ;&,rΙNt9c(G8A+{m҇&a25:" OpLRp {sXX76l<&=ؗV[޲]U_>Nw?=aeO|$8h$#'^~8$&h=޿rBz 1گr:O"#twI#GAyMjcPh|*aײ6Y4i- ::Sdѿ>[`Ց:1BW{sHњuޕׯ3?O?!2IkVl#sLBq_:IZ&- -qJAV$DARZLNT^s0egL g1&etxFi Ah͎P4eZwv N`3AO!墕 }lrAI .HIZn8] 01CaNu{dw "*)I<f58 _8{ߛR'|+Ҹb dǾ;rM5N7NG ` SG7?#/x:8|)i@Wi u<'OEKG~O6tЅ,5xooHΝ9ttv`0ki@{RmY lWrR[YPޢjѤ+{*z ]@cIj"0zR1VEyh`iN0В9K/ (\N$1'yO|:ma^Op|*C;ְI|~1a.#IŽzb Wa8MMt.b-yMe =G6JPڪ}` ^Cڥ9u GG=F&" 3t:BU! VVoZ-,F 'eW؄8١UP{;j/;ΨgV Q]w"9†5uw Lf`3YuڥEk"D@dvޢv˴__UU 6+0<#ѤvW0?Џ$ kj؍AnN_CqSV8w,,b!7渴pMGG;إ{L R BꏴsVO' J!_AfR Ek5jO%'o3fw ee) UO+KD5g,0ed; .\{\Ϝh#0@`LE Y#kMQٴXiZɠͣ_[sEB {[刵͂ HƧtov5kV:8r|mr J_ՇP8?AWj*MxΉ+4_$1aAEGVV_ѝ"ހu&sAIJ_F^q+ iAvip3`Mi1xVsC!zO|<7ѮCCǎ]<&=eI8keXN { ˠ-015tߑRS'if 3g nWjv'`."ߖ"ԙkL4㛉y6ȟ~n2`Ks|l^dv/T4iZq%!dm*~])_x k$&}ϥگ#y\kjhͪUAeG1z|^NA4^wbI&/)L PMou=ZXdۆ}}0NBv7;tʒd|%L {V+m)ʞX1za! 订3~G*ޥS"]~iUnjM%GDN `<%7q7X hʿJ)82bγwX&6Q1qcW죓,XEW6ڵ7H&P_)lRRmq<t55Upō !"z+`e`JgSCG5U&9C~vv>tX22S7TAڗ`kj͠{fM~T~S- (+j`lXK=:8OH:][__~]:J;u1;v@i֣vŷ XY2h$Hr-5V!2: I_=B\Wl"Ѳ @cdv3YO@qWvNl37!yV _p(->йt 29iJy=[w[aϱ\L |w?~m}6Q'2<ǽ+*ӯBӜ_ͽps?z :_O[nO +/_l._y BX$Y#"\罰EJ8מsq0N}Ns 83KqZb߄|&!yn1#&=4bb3lw-3򤰠; ㍱ W279zʀ'COz䁡CS'e2y^4q+\cc<<6ਕ2*t<J[  Gb\g:<{l!"?8?JPdPR10"]зGhs#A߫0cvݾ՟ν*} Dq ϡsZzL$jghrvpۦ=l6wBպZT?)ӾN&FU/F @}C/d1g;s4nO|+O8f@=I'5 ЁCq&|9|Rv@/atA`ϹCaERFDN]kcku")D Y%Y"L%7hE[VZN5fMWƄlC:z:Gmmu5\1Btix~ͤBh|y&xV~QɛU3L\2# xTG7ZZy]vw1iDj"džy_y)+L*-Z>szS1t0Bڇ (Jq%R7b:>Hs_=l$,;Vb/UUM5V8wԳwqɚ+ASwO7?پSg qq,|n60п-LRM-kF¿9SLp0(|"L)]PĘg&S_]VAO'} 宫ȵʘS1a}&lJI(\= h@]ϣfUVQ銊$ZRM!FӷiAiwr3 Tsd|S!zLDvF)bY'8*N$ }}{8{.卬MSI yV͡H@Eo~VQ9niODoNTR^NDZt#Ak/rdQ Oy{)GKkSA׎aN.^!I̼m_UNmKu4ϖ}~i>J2ͭ.QVp.4e ^6G q.!̊Y[1._2ģM#GQy-qC-׭^Avn' T{(l@f;f嬯ߔk/hP,N&j#jöx(v S9eÇu =Wҕ7}k96];C19x;tP/P}zOP1ҵy+aBhp?0ƖHdTv\c2fCinFZ_vJyפH9*·<>cݔz?˿nֿ}(\nyNԣ=ƵY`^-<c5ɀPwo_TlF_={211aL!QQpރǽ6.7iw4Bl(c|uñҹ׮qFe7z}99~Jk@Ά?x{~gQ $| >k_j'Ae ׽he{T@՗{;`4 l!rw b[!$.`$Y e%o0۠眏&jZ48uno:swq}±Ԗp1|P7WF6Qnvs5x"Q 7hhEgdіh-'Z_7>#=7r5HdZMN]=83 h`e2UY>g00n5U8OCS \I?:q(ӗ9t,8(v,Q;">O'Z`+t3Lmiiƶ:VNtrm V/_Yb50]BGc 8Κ4tmW=L0j|ܶaf4n<"P#0j{mΌR/YQoŔ`*]T:VEq`% dS:EZ]'`Ch"-h&n˜V)mUYEv9>{soq_l߅755[HGμ`p+|m`Uw!'Y讣fV ɥoDpaUe&Yao3Ixe~~pqD{gUtOVHvǎ Oޖ#@}kKN@ s2@)h]Zl(h̨r-KqxpLyC_Nr~:875]kyi`C"π˿Go_l/cyL: b`>;Lё8VC ;}_H3t~LBYIy[,@^BΑͮo`My'O\ |#c1\?F"dqVq B~y ^S'"3y/*\;EN%ṯ)c/B\smQqph@V;`=NKt|N,ϼ~:hRpq̒X`2OR]\O u{3T] 5e[ͬm."57 q|y7(գVOcP j"o$?w p _+أL,WVHϮ9:}\Kթ{M/|胞ށt™Gs!"Ζ&B#"1`ӽp⮻Cԓrc T δi<ñTU7vh=zEIϒiy*U (ӨZ]7X7`#:Q~Q~ gGz$#JL *ZV!ptM[VaZS:d"!e,}>Fe1uGi3 {u^d;n$Qc s(gG[Ţz{(Cv O;As %;'?V8'JWiq-i5@_i2g5Y$|t7kj iă32R'xPY?MUVIrǔ\:IFw1F"XIlDltu(]wQ +̤ {xBu+ijH9D^-eϚT&/ O I x&5`G]X1$,DE3[\5\mH|G+^2+؝3墲X=[r+>ݟV.km@ggKKomRnBbtZ. ֻF/Wؙ$>;^(IcRF^eϑSY JSB[rlTuA%\zi 2y*mOfk*j7fs[NϽzǥfּ(ߩ%tcD.>K`|&bd`(W%&TP=:.8WЏX:$ؽk|{$A)MZ ],FȌt*mjUCnF\z"iMNbC0jRpmDP8 ?T0VǞнlm{s3A7kLP];;9Cg2e5ڝ\L`1QvD/I6 n ʹ n2h&aaֶ K|o'F+?f1A D+a;$ i߳j~RM4𸫝} W#a>򽩩H42p)= ~6q /ׯf>sס.*);+tSņRsi =SGglf4̳Nϫ/#E|4KTWGz4z`N,ClcL|[o{\4xnR4cg>{m6.lht!2W{cbj{p+bi1'hױ]C_&PXYN +ӱy@IDAT&诙xb`fav:{ͣXJSHX߽ 97 :q^C`L)mvv;n17m8_OrAL/E$>?[+IGk&mkw}>X.}vY=-'u=kJS7H3;p?aK]gXy~%NhkL"vߩIm!r$ %$evC4r:G 5I{HT$݇O!",c,W_<`["[-BKW_Lu|dkW3#H7N#{*kfrAU7 9c}~.]Ԓ!Mё3O4YoYv-U_`/{:|80Xvv*gmjmePfUk|O@Rt+46c{`Q^b_t9 ўen{5egV_f~kxs8d# /l/C.4NZgYῐ={BṊd?ɒJKp?e goWmYaJls4uE𛬯YPi2F$э@yx+{"!L^{ kF$d"*k\f1N]Ry;)z'wzs?Z%9N]N_85,0bV8 ʩ|4|gҐ_g?XR׭έ۟g'p{mmT}^[$W#Ø%Vz|+z^Kܣ xiixE`\x51Ϫ%myY]TaX(g | X1:ȶs #)76 S1Ahp -ktt#ZH F5=. F5<G[/mEA6vid}tη^u7Ff'pCb+Zz0sSׯS[aYWG- ҡA@3VƆȤU9mm3[*< H@utzp J2~/F0YcX/A:|(٭ǂCUg A*I+ZWRuwvjU =#QMSKtnk:hI#\ GGb?嫵u &/O*W?8uL:Q,o2[%E笄9A5:Cj3 LO"8 jT!ceX-tt¶~~Gʠk)NHRW!l8&tj6Yc=mu-xUK%6V? `ْmbmX?~ 3R ZFFN௠`SWՑᱍT. E%4.bkOTh3LbV$f )gUArutk]`=tzwg>vwK7@y:&8Ko%AN 8ӗ~q\u1Wu]Sj!੺:t鍯/CN"`G:NWjp6 F`ٺ^kCÂւ< Q}=nv@ّ:O%>V .Z]gs@"=*(].q(_|^ H~=tc#N;ȫI`8+x Ń YQ(bNAf&! s^ @_<r!w6%@{Pr wt>:t$~-̠[mcL!? |;+:yN:;K/Co֠ZHb֣p_hs]ѪkȂq{LJ(H1s.W9h/XO[qk ,2#KLvilqv=h Vf^xA@v=nW=:mdt,xz AsR8gnRdA~7mx ,Cڹ_WFv%{X%N>>0Vԯ`gq&h1i'{)C;3B"IT]e5k@w h0܇EAӮ,5('V or]:+'`0׸n,苺&0u;qysll+:T8Dv4b 3QBK嬁AmMd i5QHԘg8^fgl$4b;R94[ yC[cȴgv6<] o:&hE(GSA&Ľ2edlK;E%$4_$d%44!qae.اtj㘀iC'vw &3L*U6ɰI e+|/U3/a| $x {'ejjLR`= YA9>c&-ο NڣT8Ǯ4NL}<"-3&hhIW&iWqC9¹K ~#aà:2ɻkEqhNx,e~vO3$4 C2rymr#m+;̩d #̡ȳ2bRbC(7M ^e-LQY[-vP"H=F}y+"ލ,*7Po8:;0#|$ gRU2ra eد`…G*YYr d^& ]6ذm~go^ ?)Kf'E'߲˖2VtdILyEe?Qwuuw(F;})dln|9Og亸菸_ADTP4ۍ[qvoTr%fpO8.a >/ODƷAr1[MAhwY4@c?\I18Cc#i97| rPV^@k6AR5<'pjii1Q m+h dv\>j%Nq.NCCt&=ߛ:zz"u~24rds b` zYotI* syMBcJqA΃摨wK+AeN[ vz_&yrEzyvX{u|$ke`&6Fzm^&E=̟1hEb߉ޑ/} }|:3% 66N+6`Z/ImgzF0gX1\KԎ/ޢ#Gk=ףj=dZ02|Znz:1P}:d [m.?dTuMuDy/m^]0`42quc/qWZ;Р{΀mT:! .ōn_o-EpG/8\_eF!m+/]"/$hsIgx-:"5lC[H߬VgK j/dgCڑA%55.?H{+\a}I;t8GSRfMMM$ߡTg5E2WIS$1nt(߳»ڤ>i?Ž`JcW ϖVjH #`'@͸zWqc9~h2833ͭ:Ck_L{ =.='ѫLGzT dQǪ 0iKZ 7Y` ]ɅD.*FAjz;g'z o>`%j%vrȀ $Rf?`u;tigo_})YܟO?Gx>ws HVK熡<1góǖH8>_)EڹV/"L61̎Gyva1_ml[R_x7#?~="(]^|kt08|$5vZ_kiCӾ2!ܔȨgv$g¯i(sXgv+;mk{{yӂP>@ ʦl?-VmK]RK'esLܛb'BWg8;ZaqĐ7a;0/\5"7<︃}3%](M7W_LN}wUciU9Oٻrd[%b+_- JE&^q9gX vYľpN{ OQͧ8KRsֳMnPؚ$ZZ:Ob7/\♼mV ;WGJ9+A9wR \a,u; tMAّEFmM|]x{~җm'MH-u~&]k*]bdشR&L_̽^DWGUx$ xM[ģ|=ORW`.zt0gva_sMGYE1I``2e"}vbYȣ+ }yYrȐEKH:DwґAluaR0rLONdz ^39`K婉Av 3+KW.t=M9?N+-&9qmĮEgeĎuì6 ծE}$ "Abe43@Ur^b=&ds7 .R$`osoro 3*Xsοos=k0ƦgwUveZ@#i,3 v9hXyKQhƖ493{Z,P|[u2)2#ҡ\SYdB 0}}A1PfC;o*F7 TN/o2f͌ 0m"2bq J5ort3o=t8̈׹68c|ӡãm`<ڷ@ 4u(eY|n5%$`Ln ,+˪2lh:cF]F`m;F Y9tFVۊ*e6oE#sϪFr!Ws5j ֖GNx HjM_j8-Hא\[쿙p @oL^9w#l4+5#c`ý 7 xnh!jp:2?q9wճ._Yjds}{WGjjSqd=kubiRTFǵ[fh7⻖Y[gck`ՖTXaVik% Lz>x8$N\ آ :+é%0nƹƵ_91J =- yq@ MӒN0E9*xA+!շ/N X[q 5*$s58__ʍ},E%@)$wzdf3 H 2l|1+Sg[GTy<mk8|)R1IV@}G=XyQDЦ꺽LߨL~. 4p˘3O@%*.I7$h+/!x68s T &meJ}$5utԽQi;h:DyNô >ұ+Z[cHr/@(䟁aVԳJbv贂$`/h/,}mpfv}W{(* ^*cO)/BA'5/JS&G ;æPiɏF1ƱTuϱccTaɃ&. )hZq#+xOV%G{xﮮ.:wAxE8LT  8q"heK^.7nL8uLӗ~4_NGddѶa4+;)o* ,/Eq#]`퐫++$&TiCs+/mO-`[yS>KϿfz'xQ̋9f`$,҃7>v4͟k陯SwFrٖ\vRVo b)q 1jpN;ǎclْ"[Hlmy^8WZ{id7耗^Ѓ]g*}iOsx"h:s *Zi,t n@m:d 9 -6֥<.;WG.,48@bJEppNò$QkEԹ p~;BҲg05[9+g=VF$Wh: }鮭tΦrgcc8u*{^f=l-v-ef2H|@s3PUpo^Rf""ѱv2ˡ87Y Ú 8D~ Vn1q˷ nSqn#SȦ__!22n VZTkS(zu*UV2WJ+S=wtCh TfѹUih^9I<_[N 4FpB%:"z$32<-m6io~JV!v=rf{Y5pw  \2W tw9|Y-#؁,͈ieϋڑNy.gWGeKh*,{8`ۼ:n<ͭ(;d~̭tkV#j(t12ax ak{;W5Gz'PSG41ЧgnEC.w>u*.GN`$z @8ڻ(:2ԇA@N1G3@7-9r/0 0XxQ{v5dYo",:rP2l}߲|,gQ^4--ehk&>/ ֹ0p:pg_05t|odPΡl|}|'s{&ZAڎ?7bгFi@Z\e+p|fgƽa34\54D&(lתr~y(|t= eΒӂ~3E[_0 Ƹ (쇤)8C|/[uy(b/5}>}8YiL҉Or:?"]w]gø|o? w8]C$@=h:$)K<yȬM.9M _qO{gfeJ)~gvt~YqŲ|cg^9~L_/=+S!㼁d(Ϣ_+{^Lpz eo{gwˠM`f8]|`_OzwL/( ][Dz8>?rFi#G\@<J9tʂX)\:Anu lZ{:1 f-Oi@{ci\}@vw#GOw|y TNT2ZL mr8e9 82 t|:cl?b?uR@1췞02ЋcIcw+[H[8t Z+N4Fuu6`ulm(x|f5gXc5h}Rw3rf2 S{HhU6RW%wQ^w,eϥ}s}sl׿NmNvZ3njEKz#m#o v;稒?a"从7ie1rzj"ǵ7Xr4 ՒF`[8ȝR@UzSnj]a%W1Al%7s2K #}Ϣ#g:7!3@j>iJ%jpǝ۷a"޶ SKCӔ75hӑ 0ILS(:Υt_l,W-m_O*zz' xWJLy{??W_G.:NnϏ}uj+qY#bt٨^k_h'AYEϩNz]z:6-_k?`.=L_? CO3nK=bꫴ z4x4oIi{[E 1 Z'Nm9)LxʠKp,UǽGh腬kho]N^n@A^:r*Y%خegk|ydg%ܯY ~@WЕ]ܽp/GKҮb%H%Ŵ(ЀouGY̡d*a7  ;xLBv*sܻ3I_h'rLA6 ȿ3Y˵W.gҏUXtfœ86Tޮ:3'ufȖz'P_wSz8+:L#ϘǶӱ9r$?oϦ/3w(XؠqwJ,A&㹻j#v$4/"fr26Bv#Y`V3)+@T~*]̐:H/WM9TǷ{>Y[{éh~:n_L[iVy()[U C74hyM[ɧ7   m = Igut'[h,2cdp t_u6x3' d֑_*S%[ 62F-ȍԄ<68@&m8`NZyZGTv {"S/^6աlaBMt#xɴ'SZ\}A)hdIn<1(۴wx`6$3xI2'/QVQea|x~3%8A+дzCIA&0>t\=l@x\xHmk$jꚍ S-2Ye^yx kSHɐ=zAhs6uuu7lu}Mۙ:IZ)v$ *w+W VyfP}b8PY x =:fLPʪ%Q4d-+YPQpK􃏧2%d]t%c(g=Dp#JvzSalZҲ(Q@Cq_aث]A%w@"@{:܎193 #_lOrkd-j%uH3jTd ]`h0]@e ?`42n { $nV<~*7ep 83TB[8V7{LNvp._1Z4t12Fqr a!(9|gϫ-Pl.M3]tFJ%``b י\ )VADiNP: g44̶β`2)%{<d^sJzנx69+?) k fl ﲮ?Ү Pp}4nKj xMֺ FLj;`Ҡ8qts]-[%Sӈr 3pm >f,N )ٓNBa@ң !FK#qv4uR'K. ~JsLT>\KT1uGjf :$޾8.?` p$ISsE,]:pWctFNϋgV@B pf)FKQKCz%=JY 2)9[ܪ%yhϒ5,>wK}slIs"l|Aҝw :uvuU'4E pnlmM'%8I6*@IDATt~+/x^%}5d@#CNF[Sgil*~i2**RN[?WPųZ+oiN0sۯK{>{u޻SZ1Ua#_!#i`=f+3=:ͦ9p5 l; x3pL4s>|y ښLwo{->]cuNጅst=]8{}bDfIt-[xӂֳʐ?>E۹b6b5sۻsړ{۱^I0;qGXAo:QfgNՎeڛ7i JZMiryE*ZugqNyCO:,|[g4`r*8kٻ) R(f_Yw[ B'_$}ĴpeT2"`L<Q`f4 eg)F|ꠖL Xdt%3y-oSf3Q֚}W^X}l۽ӿO҇?Y=w _gYu9yM#?PNF*:~ufWs+(T(t ;cO><۩uJ/7{P2H>f<3]@y'P̝ot-ǘ+V_)oF_wf9V[Qv)fՋdЩu{!(1<~ǰ=xz$=ᄾ}KPehit }^GU-9]"iCҲ1!ξ:,:UGB癢=:MN//˿p28~R#môj /Q~Σk(Sow>:4x>i$ [ lϥ>C3ʳ=A:wΤ7F?J,b3I-pB{1V%Ӏ*d?Ɩvff͔7h#\~1 [`&O<x &]FFpߛI~_CŒ9Ζgyf`=:mx/ `/g1j}֒Vz {"H3PݞF8?%ix8ZmδF'3Yk19jV慎[Y}3 &Ŗxv凡鳗V MנJq}W;JK&Y".2 ex |^l%5S~)ntkit#yߡ@GAp%vsV{V)tA?FXY$e L@Nm.rGshx8d2vt\^HvA6=35R!A1b%ƩoFЙ:vJ}=$ݐa$tk`I_o̻30F[(gLؿW`W x0$wR8mgoߝȮ4T~IR̲Ejs + IJҰƤRF8` (*g>QbsTt64jGENH @#vY|Y#[YYM(ѥʟDxWs(pqYE?C:\FQZxFv=Y4 [$ 2"ri]J/7e}gc}Y#O>gхk?zz?EѮK'{"=»9pVgm3G 8ӫ(s?~oWxR37yJ:r>;Z20Ÿ[˜d qٴp|#5~z Z BAr&_y+trR%aPߖ*(|A&&荌_vX3?6=pc_@"9v Ѳ1V 8Yqg]Z b&n 30^G\[V^G:fgVfV:{UF (,鋼13іЍ,ů ضg9`ʖZ=>䂥2ܟ;Ĺ2ɊA^P׉kd% 7f;ޥ;un3}} ܾN<{gi+.qysE**$Hu*$?51ڠ8`9p`Xy[MV+dz<0 G'K:y pK4QE+d=,PA)NxƖjgp:cܝQbvu!d1<ދc%"e"bgSYbm&C)liofY2nM%z|i8d4V:SWvʟ~'@__oRqH/ϫR͏:su._Β)9~yV[r2ttBGqu."`#eoe)#`*zry= úo|6Z#D.PV௜]`Nj,(ɊySpBWr JocӴɤ쏞*ΊFҴY0tJxvM4pwWd73lu};]y'=#w':=H=x %boa$L2y]|KC[],|]mPMjphm*mY(rE>[ bRƘOeJ٧AxkyiRJO=\Cͼ:烳^xoٕofz_K_J{"󑫞3Onk![XL{kv>L8zCu mWi^O~*Y5w0yEw iJ1hm@oNsOڃ[7lʄ`kkG`A^k۩Щ4pU:wVѡQi.7bٙ Zy,Qum{ñ(#tL:UxW @;1sF=3d acm_,Bس5Zmԩ87l d 꼙G[;>xv6Q:`o{vVNS1Dx}~bf;>iU RCG&Wt;!9:VߪL{LH0$-m|e']zbz{GѥR\@;̳Wm^CE,0eGeevq-]Ke T9 +W4ЗbT(Ou耹Q~}}nE\usLBPu]O-5!;eXrx[9 F[I}mX)fo(8?sv!4e_*ATBb V6vtvTLPaЧd ,! Uj FSϑ /*;x}*,/H%ЇhsjB?UҾXAЖ_ZQ%mA Q؀>W`}o|Bmsz:!f}=wB?w] ;sd*0ɒ2m;Qg@8]˽A2 =jqvVܿWǹAÜ=cgI~Bl3~H#P]1ƼʘH܏ Jo-F@_fgJ-jF}5Tcd̹>Ia$-v-kYfdĻ >Yu5ÞHMT TU(:h bHs:/f/}Ϳto[w/~?^('O}07pr54_ ufl`GEȝ藅:54pXL۷IJ77_L}g}ݘK0SZ0M}(_Ae/ rρVMFjZkH;A oܸ>s`d7@kRK'xN_Qz껯A"wCts6zjtΏWY +_P!m_H>U=Fҗt?w~;}Fz/uo:2v_YFG0ss.9d{l*ΕgE?Fg P`F,MΙ% }[NN<=HqP 7 H{:gNpc_cN{W+8u G Hyۡ4D A7t '\p%,23w' $Oqo3Y:`! Z&RPP׬3/a_<2\|zife+. 3,JV? .ĩdY+uL '圔/8gY-Q d[ xUU0Νiܱ6 [D˗" op?[h̵7^'h0uCWDyeT~H 3smb`_I<|$q^/U% >waܟ=k/p&H?wbk3巴Axs/}^o/Xԕ\i.rty臎^8s/oA6u#x:Ne ᳂)^37 +ҡnPҙnton-Olen0.%P{^Q-PgϳT;mO^:uiaDu%_Ę[1g v, c"ӔkimmM_)AL g8YX؁rd et:ۤ?=6xP2@o() i_teg] gzǝϐ[ڹ9e/ăd'NOWgŲ{dMg|Lr>סz._rfjtGexb{=H7?]@C.N}}n_\3uOR޴Gr8yN8!lm}Vpt,$`4`Lຫ/.ׁ0< f '~__Tb0E.Q?̸?O"?gH.l 3Th5Nux4e21Sgdϼ:m# t+G큩NgHGgWjIlyWW7H]3^SUz#ϥ'+>u$x6(并׼%;Uޘ[Yi=l DntV<7M: hKcɓSB!ePo7@{ȑRa |󟧚ljkg-CvAqX9gat3[oV "45Q9rp©ghxizLA"ý9{<+! #Xs /ۿ 6tm̝8ژ[͈-.r$ӇӪJ{sǨ<Uk t$)Bϩ.BY}s>Jk'?|wٻaڵЅ qj}3BVVS'pw} z`or 2lcV9S"VLm)1dSߩ^gr& {T,YG}v jϺrQoA?]GN:l=cg1^Z[a[Xtؕ@—:K>C{nk*dAY<KZzA_O ܜg .[(wXչ4`3|c0b;ҭԎR<@BS}0@GX08oS]{Gg-]z=ufoEEBwdaHC]Mn.L )!uur8K-mMPUaaltyPd90Q}W* 'gvڝd?(JLt>@`N~}A? $ ( -4ʙtDJw+!^R<{r]?uMg /tÞ &ӫ.GEEuWSɯ œZ]x.WV+x~z(?WgVȱ/=? 3Q{ k{ gCG޵%зlTG:39荒Ac5B;pcqKY;@ BPc 7bjSx֜|}`ʗG+g6Ir<A.Y W;'b#*`y DXж*6(:0Ifa **xb櫩s>*H<62ר?2}3D_++\$4?_? HըA:Tsq9!(D扙= V N34&Ψ'H1r&a4WAT)5K0Ouzj<>9ĩ]"Ӽ @(ƃ(E遇#qg^`Ncm\4G6FNcd`H j&(((N/ĩS@/3@ @xL2gt`:O{ uvLK ,̑c#S&KS >.َR;W<^ܟ f1{ $hAO;ۗd]1/i/;1` ˗qp٭8`rn [d>Šg .ͭ նF> s9fWUi'8oYZy`!joU`,h)_4C8BBضi`5J|7)ENƲ>r(Qd1't5Z h[ڬ2cxgov-K櫆.'AbƋ,d|.b8(("*k+njk}cБQ&Hm?*ߩS& Og Җ~~>0wRd4b/Wt;OAl(=y1:v]aLoZr=/|Qgk l1+ϞtBy8扶Ͼ7=38_K`O'zy+utvA;<=9@s#=p.:>K|J &v!4k'P~ݘ Cd>9ұe$2t ̰>dnQ_ _ ~U8Od 07)53a|ѭ Ҽ] 2uS}^]<SFX'^N^ޫNlL gϵtZc!ussPGX25ES;R 2෍lJ:_VGplxG8nTdukXq;e?XTϔgZ}BY%QR.{LVGwfy{'rEP篭ZgAVJ0 (Vn]=ȶ+y[~_Kۀ~0 2/`.YDKm *f= cg{ZC)!@cP0˳pұavkkfDYm>t1OphTy>Ⱦ/+_ʠ`'|&&Y jv>i~s2dX%u4Rt^NDg [>YG.!X;VЎR2@y:H: &|޼>.%zb*x:gZ>dx1U7؛5 Nm *lᨶ͵VwI%8~kW/U!>.8"tgjkmft] ku3L,6 F8lJK6dz01x5diˀI{]$١^tGe̍S]]yt7_jTўՕo, 3lhnjMζPTUQ~z=>:1>,TA6^=Ey~-ik Phc#ǂ_yjwD=z7POՙJص5$sO`2!  ^5285Rk|qi'{'뼛G/+Oڊfpp4k-  R2:8z/&*887L.K"m_oXikЪtT/vɹ5*^R}{_`*>c\`HgYK L+-=^Rq6UVZn` qbk ^_! CͭѩoC<^]Ҙrgzom^硌#f=RB;4M;[ݴ A55Y%X꛻{qI:q%PQ.8co`K?Q9_x@w,3Wщ0Yѽ*|-e_. .3*[#E2Mjmkp |x 8}\ K.m+l8ii\leFr=>~g䰆?pנ73@cKY_ͺ̲J54+PG]N3Bu* :r4]{0M6PnpkttGJb[7ThӉ ϦF9ܛMU"5F4khpKJԩiy%1 ,'?}Z҅7l_f*1]zzÌupZF} О8,a(ANNe-pqC>fπA( aɿu#1FM s Pm x-7q=%UI:h"ۊb>f BF h N]iIg :rnFqL!RTЏe@0q-sZH䀦 4~ С![pa,fFj=tЬIȘ*;D %2/t&44q_Y߂m:<4by8紻m1C+1t9MqZ (!SOlO8_ Yʏԟ3=K1ATq5c<:Ix57 [; Z(n7˗F7o+L/} K:[qܹ6 #XcF<3%Yv=:__?[׾?_}<~'X%8S؟MwlN:yYgN40cB8NMM@'d.2Bg{&=S]8GuMl/in~lx^I9Fg+Tp.d Qݥ+63Sa+3g*3~`hsy s [# !7xS刴-8 ns{tzPk% +cL$֌2O((ik~A/- BfU %0He @AV =uo8]az)u0@e@mάٰ'Nu@؛Vҡ><޷K_D!z2@hsf#.,cڬ-xAeٟ8O~>>n=BB?0Sa506ղ΂=_3ଡ଼2Hsej"8E8 F\qw"ʯLsaKT+iÚ9=vff@쵲( uWy̹e sOY!Ә\6[ Eܗ9P0.3b m[|s>֫TK 큆gʨh #~x:gQ- :㭞_u!*isB>)Z\ 3Rw 7vXrNKMD$m .[AE9nCy5CiRDT2\q湀\g8 bѺ Vu gl}Oq2U֤ *>ZyK.8 + >^f&R]|>ǖ`r^bF6--_%d Z9:8i-O(mJWAŀmej}Z]''=2AiwikRZit G]my>lR^wY\w~-{&NBir1דWP V6/ |B^6k_nc{ OFL'҉,y*PmS_zk0dhhN'L KTryiT&%p?KYv\'jsFm8y;cwq$=Dz=͆ hm;Y=yfQ^{p51oime2#^gNu0q<3R' @IDATSUulmwYG:l4*P4ͶґmyeM4ME|. ўth6@P6 bn ,*'{ɽ7K  d_Im0F|d;sϳ|QFkitiHN\~-JGi YmT38qk؇۵t>,BhX[ȬU;AT+k8uzo:8pr=]M@fϵ@u@BV =ɧL"_Z@:8 ~XQ,&N:YWGX#=Y ]|pm&ycϷ̥%cqcpk̩~;# -t1NωU9arq'{/"Œ4Xz:8}KgF[$g_r ^Kdki[lOǹ'xd4ͮJ#Q΄Nd@tw^Sw~ȹ8G:؆B:4gn3Of.+#d51 T3!W79k}l6~ұf,DSCA5fc;^[YFGntH 8.i<¿s#?PX(â2kl;{.ϻA}>MmlM=wҺUz)_QYlv8B@]*X}fz~˾ ǧQ_]PWVA@??HQ0&3 Qupzf}f'o+ߩ W,tʿ]G[4[--ȺbJ<&f9>|E;!`] =vs&M/Etyh2vGCFխQ~d@ץs.e] \t=9R`1RR=tR :Х4goڠit˅i)1L+hgo?WgC{*W|erTOsXkXBecDtcaN')UH) u,.ϲ^:k]}}| ǽ6cOǞ|&[TO/gR3YʀН`e }Gטf̓5-u Qyܣ[#P{?8Ubot+ocom?JA;wwp"c5Bϐ1bmۻ%*L m9YȶD˩GL2L׸=5@l# %}:$d‡ ։ =+|G!2`pY6adaCϷ?r=j7=],[\uH!얲4O!0uICy88ܶUEg 9|ga  U$9ø:r8e08lߡ sei^b[#.il-,,vڥuAԽ#ІV\ 4?<ɹ3:=[U=ˌ}u zf[9aAs-j-s 5Q +){eT=_v $EvT2']%yu thYVJ44M+m6X'97u)+*XmGƱ|az_v>k|d -4LR]:K zpי"Zg jd7xM(N%-Wl___iD*8~h04:g@Fڏ/*ҟE G.-{Ʀᖕ0E=PdpgzeUV K Ƅ"R2h613# -;sdq;6\sPM-m2R78tf ~=˂VIPW3fq^ PY@fYZth?u=FԿ+M|6z!~t GA}=a4CC?Le5L][3kcpW1s'O`L,b#??@C#6rf(؟ڲl)`J1J4{%4?OXs^d>ٿQG%k(Skue "VC@R c è'\̶l ƤZ%֘}bMu+(̆ :tܳn^Cƚa-(35# Aр|!P{ CDJw`Mkr~Z֕S~%#}3I-1^z6γ!  xe{44o p{d=Gw|Ҁ52 j/Tq[0u߯ H@]9оh-ν)xq )d}|to;A>C4psc )fy !]\"pN6nf\/ +A΄ q=`λgY{T`,(ggeu&&<9i⽖;|XАRafRi%V1A !^K-`%ұ)$6,K@Дel/JiTʸJY=9uǪ9:*B'i-aГs`q,y45a:o؟um! H@Jz{ҙg*m%!SjT6t{u xvx@r(,y+%1_xf:2G7HV.N5ES!t ȇОMV. r* 6]d K[]܎ v3!!f(2E4 ~ɼQGE.tMVQ3<;=?g\[zJ>?ﱑ=Ik~&8|c{%Y74tԛ3ƒ1=S ^j-j?Gi_#M KD-,+`,qmuF`9K; h)8ixXЗ (|$Ul3P^"3s\~WhR"Ry[\;|&:ٝ?Dz[ĕBte%Ǣ^N 0@vbۇun-sH;D'ݫd!C_:9(C+-OF-NrP&bj&uF'K^ f~:"! Uzڣ? _{AOj4 y_+z0@7vvd_evw&=3DZ2s ^4?AGk//ZtxP__xȤCeTe$ЋD;xQN.`P@'kZx")ilQ~~Eb/5 ڒ}v;"u^Y/0-);ʃ<:tOBH/_8uds;d ϓY'RWG{8,D+W8{{qZý=K#!xu\EǙN:tt8xBl,ꍺ >~"Bdkْ;@E&:A: e*|rFӆ!X`ə$6N6 VM،(֫7<1z!~'b'X '}+T]ig9/nԬ=l`?׌+Όwc#1@b++h]o-F47Ž4*A;GSHVWK{t9J厲U;4 6wZCGȴrVPzV_UpIp_-yrI0K*fz ocǑ3e`F0bWM|6gr6/ʁ_z=Ëm*Zeͤa%/+$̐٫ ')xb5d PWpk~1YACH@˟}# yY[hqzϮep u2/`M j ::+ydG/*:d+,1P~DVB ֨,џc4[CaiT_A4/{M־k^]ޛHJ)R6eIq02c  0A;ccKD˒EIŝ약Wum]յv{~RDF}z}s9YnUZiYLA'7o9 36tU-tp= @{> Q2YAISO;jBw9m>򡯨+wC{LI<ӽV.v(ܯ"p(8 ,t+~/vftt6~ϖ?7ũhTFiϐ/AGՐVZmܥs@/yۊ65y:$<' Lt%#QًuЅ-kb_c#~z;h<ǣZ7ϸF/9 6LLODsyH'E"+s(1@y )4 4 tlac/rp (LO5|OAƹbSo񰢎Ocl- .|#XOVn*y_x60֠&"m5M@m Yse@qUFӀJ719jr* [:V tv&qox 0^z+k/co<i|0ڬW^~nO>dso*mpr rEuXVa9v7oq3SgL 7deu1!%0 ~jE?{h7]^a;_#6V˚a0a|Vݻ.K,LYi7'\J^zws7?uX gϖ7L:Miъ&< `3 p+#8KE2C7<ϊ=t=ɤV|xfVQ9̶R$ehDQkKǦ& (EpR9)!&@)']*$;A3 :p@ŵj9HB`nͭ}sW!w}^/fm&~ ȇﱋ,X`ɳ*o~AA/ m~E+W P{OuO- %6A^7b c7E H 5ytȀO/ H6~0>6[~ҁLs9]й)^@X,FoX%d`b||%(H<|T:=>'C vN @AZ$2?o ʏ:`\ȣt5Pkғ?*e`")V {np Rp = ICGe}2ݧ%_w6d/eq'M<S5u̞sLx9zW 40 VyC+=; 935ʜr=({MF?sX^צ̳S4}vՃy;7W>^jئ~ܚ t r |?jOciroGg&r>?`pSYFTiۉv$,$29Jn 5Ri>>H_J`G ۠aA&+YbŞṺcs9k8y+/< Y㧨 L#ϧf?Ξ=k&MgН7Rlp݀[2SOeXq2A`6 ߩN+GuW *G!q0$T]k6~/=GR@rkHF[US}]0!HB{82ɀctUEgW}_Tl{؃lOV/~aQ{kLh717_KG@GqtOA$pE 86WX6X ApXI[s]އ܄DEY6Czn/<;>z> h3?ɾr}}y e݄eaG Af#ï@-CgjX+求mH~EP0ƀ fAE'VWCT_.됼oWW{b:{|*6Q]t4-W7^k1|t M,G|mDX4hh}9: ~ x&2Lf<#a耣_j0}kdl<ӱx<&O>]kX?XF y$̪g|]?w~w>GԕTm֖546׎2p Ok9xFU=d1ڍO+ ̚(/Vop6?s=?ldS[mBC3Ǖıjt ?/]?E[@LѡVmg|שWF;_Is0 -؃PwVy)OV_;F'QsFFv2@ؿ \ߠ{r"V0,Wښ0ЉG?-řDrIV{s@; ;:c+R']`tWsKA??E'A[$Xtevj*O*#cߵb3HTpKll(Qe+$d҄>mC7ADUy( 3$m z%7 ֡wІ€ 8SviNf%*<ߔ:y G .^O/ 2j8- :r( 6J+5lk /cb<3lwQۖҋ Yߣik_.G.R/.+)jҘ;p0x!`4ŷ|:>ݟʁ2F~7%N{vK 'ٷ,IF9%Q&H|A7iN].sݔ; G:"z9G~kM` ,22ָ.ްAb/0ʠ)>+8Kc#vrL]AL u3)㌧S O<SP˽ʻ+/wB Z F]n`FBSM E'/`d HQO)?,\(eUN4 mC.fœAi9`ƝHo@)dH` !#n[ve |x1Z[i0@s8ܛ{gc\Krs<?A>K%j[slgN0-S_,hq{3`|d4|"Ix:* 4*}iEEww_:t"@\iJձ:;p3X𣏠!RjfV_2a+m  VjT¼-:f 9ڰ[NUw ~ B*q u)G'Hm ,q0 r X <Gv&6L_?#nH= 4uw2'ʿ SDկʎϕ* V-ĸm3-&aܧ(48@PfO2Y'g,(m9mU.(c*9)+kIO-b1տ*-5oq)ۃʋ^:A GP **:VIs( 6!L1C*Dm!-8Ť*lZS huڼ|뭛cQY #kܵ3hk˳]$i ZICXmu ljъT-S 9'1fpI'1\"qy`naW޼4dUxq YS^Ʀ I\*Z:l Vx^' o0Uk-**tW7y?V?3ʫ`@}|cLB`dkՏ2͵=ձNm`A\?'cc;oFCT 1#ǎ 8@9TC}W^mO)'8'ys "^ ʒ`bȩ Z >99 VI6 IF gD?\>R..0 lنPW&(]Ck gPY:X6NU 6g*OL [z s|Ib@2ԑ?)f.QM;!M9Gn‹NAK/4eF_9^@$@_4h.r¤F-;;i/AFwCđIѷ9fd:}Fvqk y$ѽ6qKj{ [j?#wcEA}ر$B._~-' gl#ȳ ڐ}ȏUnwG>hoϤlQg9 Es+RCSYtXgkdH$P3qP=ͥ^H(hlH<]8w&q~ӿ߉.,Ȏ]cuv-MvCXr g E?g6#ZqQ;xgc}a iw{5 Ὠr&Q?/}C*J=]Vjߎ7 ?ywݳK=V89%pm7}b?hDp@߽}y %y)?$;c nT]y75`TXd4Eǎޚ&)!x yv&SM1-bG,w~H G398\Plk~N0O~ߣSIR&OP43Fdc}ŋrOR j5Ih@6tqٸvʮnՑ&fiոѱK/%+Ὦ_jGYS[HŦB@"l2w/Zӽ?ǒi1(_a ^+3p|jZNwrSkUm&MYRDkx Iώg>aؿ''qn'M3|,~t~5^0"'LMOI~˄cilk *}3]L`+LV9J=eq{ ** b7>O|﮹:d|5|3;LLbG9.tI5{>Nt\ُ Ug/6=XL>+-ė8^\?M KN_G ݠ d/P%^ؕd"eȞM-ށFTq:ذ{лkG.Yi7 \dYJ}G)yo9#kcKPGt`e _?7=D"];xe8ؼ\Hkl7#m9WNK"ޣ>2X yǽ~Vn`X{3^_𦶅S<1e Cl.jeQ`Gv3A]_ZM|u~$Y/gtrwLgQ8lxϹ"/|x|%j9~dmy{ST척yochk^ؾ?wh^QMDž t &< 1@y )<Ѝ+/ @كq\+f_:+O6tr.3 `u#{2ӹ1P *$P:]65F#^tW(* jdrS;*: ^ N \yL|+ hjm8u<Ѡ@{7+ب춲I0]QIy/X{ 㤵)F)ZFg H?'0.+G㹞gaڻt杷q NK)U8JG:p=WcV-,q.<wnzӊ]^!~LX%UiZ)bE&k/sBP{\reťPkf΂:f : L>& DP ^*dm88*xx/A"6VRi]sҧoNfg[gGOQbA )y :o:vg8ci' 9ɲ6pL;)83r SMZYU:Opv V: 7s0FF%Ǡ4 x ^"8s_yMqNέp[mZ;W|wRE|TA7۠c7 Z3M\yÊawj;idSK ({+/ Yxy EkJ8ߎ /E@`8g@ >dJ1C`K \i}c1h$m҈.t!~{@@&ͪOlX<ϵɜ.$\wm>nan:+Aa]r puX!-.g;dlmptXla9|VEF"u<Uy5z8OãФPr"pCE:eJn'{ͧϳ}{&Z27`E\qU   gRGX|bѪzZ"2\M+u&@uWCA^iPH7voJ,ܛ!!mKԤ!W/A_e@fɂ=vtyk93I 0ucS4/eф cwh%)/C׮I2NŦ24|f TJ]AH>C5WufC2AsT'p/ldy$ IȻL辇>-Չu$OL҆1HKb@Id5N FʊDQϠa+/<;ž^\h%DYݗHRLE5 4^#Z[N?vX$HJ<7a9q2@*`@@֏{,d *ncf!v>bܻdWt&lD{; jkA)[(nY9.?Ю`eu)$eE{'x@-c;DB6=&[V#?x[ߧ#Kս?݃IcoA,|?ÑL>ɧIS5{{gc+\ bݼr+@.LrP B\"l63GmpeD }`;&OppyE2d?oD)؂٫c/L=0LK[K$)IS/rdGdY=k؁k9~Mxm#=_L/F8~⥋16;h&٧UN Coe59 5*%crLBcmWX-sfr%zuuQnuGsA']]t9 8݁.fek-Mw& XEa_'_*'~^uo=~qWn_ZHEgi@or@cS;v~9פު_񣵑D'3x#ݗMt!CvQ`#b/u$]bvj`e߄x/sO@ꨚ2\=%O7eGY >e0{\{:<| |5Ϲ66]v18:ݡeH5yR_'Zcsi,WHra1t *tHeS{Žh46:Xo1ҋqHэP ɤ y_{gtF`K$*4FTos.BX$1Mi ew?~mVYwF*vť52& U< ﮯF:dQ: ~B"lU9Wө%mO{ta)*[­4ORJR M82!g" ~ܶ\o2c݈5W/@wi/gX`b·vv_p2Rw>u\{e^>#jc;? gDfb&o g(&wfz#}se1Y#괇c |n$m3%kWB2i |w^ v,PյD_QEڷkc`0dqǽe:612k{t@39i2PZA/1 iiD=z}z~<}Wy )@npɲAJ ^{&ødȭ>ggߛOB̤0t3jK8i$s9Nd  s~dUvhYŞkAe`!u[#s)s-Z gA]=>gxnzN݌7;5z ij<tva@IDAT/cݟ~W-M\jJl?\~ DGF- BL;G ǵٙB@`"[i_s2/I*jqDV'U+bM$'s,8 uMUwes':%\'Hk@@Ac>Zg{/`0ׇ<QPf7`]3g.EdYα#݅8򉀠ޞK 0-#%V z \k$/D%6cc 'c DUgM'SHXo8Yv2 :H}| FpN'ʎ`]"V,q+]jD}YV3$J̱}tL(>3ؙLxK2bcs]7 ÚPxsT &p[ H\yW ,-7vZ9if]q*UKE`s4wR4c$ʞϧ.'<_&PvG9 s#[\PRߪ ؘ SIѪAk; 䩻;`? ܯۻ{Amx>μ΂b@*xQe;_A'=#A5m6nQΠU2:}t6l 8: +/ؼ}"ez >zYg4%k?jٕH<Ɏy6轞Ak !"=τmf;iMPYKжDvgV>ۣgcQ׹qӊk"8x KO:\0׊fu[ص%M]p.k#%8.t1R-1X}sXn`J}O۩#X.}KNce"IۀVسWJfc#lVWުr-gZ;4r[VߥRM݋'5R6w ]moRwo)$iX6vrt@ 1NֽEpbcAuxu~e[[cQd1CӡST W/?>L[[\5Ifʂ{C߻V$no][y\IŴf@t>=Ο;/#=yVF_`D)$!DsHʄԝڵe2zIr߁gY:!m|GF%Vv-]nOO~FqzgC8n6Z/w5뤲 A唥=.4YY$5hRÃ|:faDwh%666#t"ХxUpJ֟:|-zz]&| ̤ע#IAs9F'/ά-3ʊGi@{tFX&&18AQ}eUw#X%̭_V-뚗m|6;ګi ^b&Ё ՟޷kt1A ?{cWG Ao幘gy4Tǭ(&~wq}/!_ &՚tYE ~ki$ب\cpLZ5Vhj$Kf}Z CѬLO1D';[ Oݚ@Z1 FF"XimB6t(:tacIwJ^p5<×WL̷]}L/ժ }%ϋ+Ķͥ$$GtY^equ {F _7(ԁլìuMJ]ASu8YIq2{iAH"w.$!;aX# To_23|F:!7Mz6xd$exHҪ~:Қ10CqiFt; #Hn;Y(ff۾TU,{oຉNآr5е,`6"A/#[]ܔm@6t.I&{*zme}'#tz; L^0IYĎڀcSp"իH9~c#P"Ks--5U嵂7SBX;,@n0gon8-:qz<{^_hWd&.c?Mt*g0vq4hv2Oeezp@9gG1*W_ǜW|^nl=}Yvtۇ{Ռ1|Wy )@fj?9-FYU j"#^h+O6:7A U1iƅASJ`Ͽ ]~Ƚ5^1+;A#f Op=Ɏaΰ@ΥNcۘړp3m/gt; Ch uR~R`\ܳnߟ}I-*:48bު]e+[@E[zނ6?X }8s{*+ äv * `Ÿ b[sɻ#اN2޿@ޣ##%wgGզ΢x֨jbw= Z^ #1\{1btՑ4;_ضc:Ǭ.nbNTuB ,t'HB9mya7u?PԶ[%" ?8VdN` ιKE9S~55@U8Lۮu#79WdU wg.WZ k(+er4'}>lw0)+OM ]*GcΠUN:K+ST@Rmu_'ҁCo?C`Z@3P?&<;̀u_}:~yW`oUUKT'`z 9DYe~B>M=7WRZZym9O6Vlnu.'i߶܌d[eȏ:: Y~KU'`nH{흩vCB]xb M]yeq!W%8p#v $ΘAom)&qGA9[Ț#0V^,Bb ,bXdc5uF%I&~vQ]5&z<7@e "F^l ZֶvV86+ y*dgVtt^mHpQfm{`}Im$di>x-:=<A^$j:6֮nւ6Фo'F}ŗoB[H :H ! Vaė}}$'{;4_b'@QkrA;4&b&`wy<:_&$a@#;e#wkUTymyZy62_!do^ڵ ,x믽 mT!%\m]F]]B{/0#h fMq IU)ql!#،i%8Y_ [,F'|&Pu{g*vEk=~]xLE2 {tVݧ==J\Af|z6&1Hzt\&,//\ԭOYzDP]?Cr«{)?r$X9rZO#Yt1h;@IT fR 2OS3tLNg^/Mw:m/cBzcs#^Jl<9v3Vؼ]PM\Kc7߽@Uw:/']|ӝ:;+O/}i%1uoܟ\h>_7qϰE-g7DMS:%-1 3W$s?>K%e?^"5rrck.l}~ԽܜkɜXOMb1#.Z``r3aa'w:Cdzi %긙;2 vMZ c QkYr۳)CV[CRV.8—{;MwIr)$)c!-snq3J2.{mB%렮Q^Hڵ+IX4 6ϭA, WW6"x^PHlb{dV`YsG'vm:&wqL A~0k |=YL?\-`Z>z6SLFu F{\|w yr +bY%[K).v&{Cǿ8~/RXM[]C}/6v|{2?o㯷4޴8@&$T,|q!-=VD#|Q6M5x/Usݢ܃cfL+ҵ=&*9d+O<SS %lj 7hf*ڣ6(u56r~hy `@`d@V k,@T6ёt)J+rUhvz^tvt3'--)=/`5j{J9ul/cnuF&c,*:̌ _h2Uݶif }u4䧣UtiK7Db:}= 4R[)[o*vZkLaKM2=q+/SE|Ng[6l:t0L7A6qYpPiYMP)^g 0R `Ffs^cѳEO8,fZEl9,]3UH>@Ktx+F`0%[vt20`{Lᚱ`=@izںMG~:*qXuH*.\ߜ FD>K t HjjiCUV{zOy2mh.pb\ifVsTWY2BaR 4lM7Fo3m1lR  4 `ʨ?̐>ޠ{ $6/1*[̄I=!@P' /p˝4h yoí)_[%_ԇ_LNU|S, ﹯ed[ùV|K៥j աӴ/xX蔊JƁ 6V z ۚvE=/!gA5yҵVKiY{h[wl'nեduҖ ~=mo[0tg׫ssU~3$ewftc\ Dq#q$4uvb`CIVw~N&eaKs_%y$UOT!!+Ttsb4]p&MυXu3יȊж K[4Zk1AOe5Vّ Glm/uc;GAأy ^Jų]=~]au$/Vk+dAKJ3muH%PǦnW]݈E:6׮|NdZy{ROWs1WN<. Uk2wį|=zdĈWi2#5֤N}7ZJABLsVL3m(=*^ \L?L6h dzv ㏟5A q?Htt_ӌ_/$D13g+JxG(`GkȟhkQEPtYd(d@B~Uٔ^2@%syٵ~*͎:?e멧~dGgٻaq~g5IǡHAw5W3d7k29K̝ tzN1DvTR/8km=ߤ4y*{K:6/rlAk GK_FC9dTiPn>/ ,YG[ؠ$t-l$p8br_REBx˵֨/~!HS{=@{;fvz'rg†soRWI;P.$vY฾-$ q[tB"Y@6H)3g=KY1eڽy2t") Ԓ`B`S}k;=WLs~(#{_@Ym={ V2sA!rU-T7~}/w9B )MaTGL9>Gx FZ^yJv&HT{b?NwǙ`/dp?vx1%ɋ94g.eu_q:pS#IUH rVJphQ؃:X#{nrMkaOs[Y/ ׾e_7)KϿ-I&aJ~<.&E򹹫s1eլiQkܺ]O GǦc_ Xh^f"@$m[ؗvT_Q8y&!lؽdy((ԏd% QS~yݽ@^g*P/D|YeD7숇$|CדyTJq=a$;ouzaPӟX- t<}H_n~m8n$yFfcLx)gO_@0WmLB:찗^|&`=F%{{St$ F<ك%A&|R,Nw? HGDŽ0Ni꾻g=]TDbv^%K&= <ƼMrQg[‡c, LؕV|"ή.'Ѯz+$&xĵ!pqe%$ c q6k L<`_ *f*`mY;'@OXmE1e%2:7[e⡾|1&C| h,[b2|:^[)*UMp?dx<_[S:8(aYA7҅qloJx(_I̢ >'6Ax_~1)D _ .1tS O<S'4pMMqdlS͞333ƢWSo]^`wuV44?^Dlfa"QK[a~H[?k)˸OKq`B%9~xy[D|+!‟ v~*#>#UWΜ6c7p|^| Ë8i"gylc;C8=}}]xX} 2ٖζǏ̲VV=/b` P`t.Ǒߴ)Ь@'^BmFӂIM+:謭mR ȞL/%q7oլ `@0kX~7qM1+/V넕7Gg0TYg2s ̐' ' gRRZHy@*mp f(n< wʜǒx: I*Vk'@£֙w3 \7)xh7[[O2X 4#Јg7p~c5k1, Vz4 ^؁uVYfm*̕Q۹Ud]Jau_h<}3{lȣz5'l:vU ٩]0AQLO<κs>'M|*Mutf-_pg 2jծeM_X.ʏ#g`"4I/ 8:&T xS~' Clp^9 ^eMq.b~Cw v?M.-ʀgW_ҁTbo=)HOȕxd#'Sowgʬ0õ50ParG zԈm[SKSe}!*lWU4?,7 d1? \Zo `Retw@T+ޤ{^*]~& nZTm-^Nn@_`+v;p L3{B0C^ $ > < 4ٹ=+g/?+ Sͱ663~O3C?I֬E]8FĶPW[+=uD^8s d hl@i;uo$lB_+H΄{f5pyL8,V/d4yb q"ǭK#z-p ,o0Q`T}8m keŶ+Jm$8Ҥ}V6DupXSN]*"=܇v3ёT:^JZ{/ekll,@L 7:;{M&W'?OIOs-nBk$ sɭ>zࡒlWgW'v+Tœkpw.b,X_ Zg\7n4BP!X19/Kgy+ݜHK_HM1;UӖ9bcC3[ TJ 7Η& b*k&&#l`DD&z}$3(W_x3Ux{2c :dӹ~4C"[& x:IۂsDf;#BjؾV>5zWFbst] ̣k:|$xLZy]ùgxL^u, C<3hO 3_|G E~2ڑe{ޘLTֲK *|^]ʅ~rw`{NT0Ef<\ecM?:OPons/'!r rxyv.`z=mOG{3=@\jX\( II4,Z^d (O*,wu>ң XZIff/s;Vzv;DL[H o{i%IPL־t^kYk ;~J2}}gon y'a8( @N?Jȍ].l6W Ϫo$`aJ9Zbda|EϽ$qcVxn1zD؄ 騮TwM8g-ÙֲI )M!_y ))ѩQ7G;S@MZ?Y5K4=9A 7v?iS@Ѱ՘ Ww5P8X{Wq<^V%jEE8Yq^::\L^ZBH`YyU_:]]igj|c[~;tj}$qaTK/iH;lTB/ kt` ,`) ]&V9gO,< /A> HUXڐoJ8+u^|ؿ/@L:g]!K0m+W:::*V},b-BQdrcC<+@Z:Q_So𕆶\4(c@u@@4k`2]I<-oNS W/'Xy$kiN;=%)+Ƃ/ 6:e>X,H[A_!;z`!Р Ydxf7X4/sl,sP gm g%*=wl)mz 0bfD+mxs&GGqkߊ뀁_ {V~*r>nl@ (crW| O"1G1ܖ.\;¹3gMMw Kh/[WJhPwNྠe5ri=t XyȾLUAE@#xeTL}*k<{`1-mf <"Lra;*a *ydu`(/:0p9:)pnh`= `@ۀCEmϳݬt #pecM6c<:.QʹsCaz>1x5ԇZ: d l keAD+e' &yT4YYm_y^ZSIr|(73_ڂSYl񉘏2)K r/Z} ZȈ"@^m+JIBh)$#'#h!/X`h+ن65ͭӰ]*㈁-ùN3La2L u;[jR*wJev%TrPnKo>K:;; ,1HJӇ7r9W~gGVKwGIi/\4(>OÀ{vq+=q_=w΀ތ4Jk,/ IYdC5-+]1M6TV LMcMEGPj˯:IȨ|>A\"vjmW,Ї9W"Q@4Hh$|F˂!TqF0n$S`/ʂ& ,rc&v e.RaW2)J>\όػY;((V+}& qFV` +-- so k$@ǨDǙ$)`ȂSS7V*_1kd}Ȝ|]WojYu{ 6reS!2l!CزA2/A{&yȅ{#`.p|>݀W nK_㕗|◉~&u_|-8q,a@T%7wVUW gz4 Dd-SLz2RG hyx-|(*UQV/,<NKK|V$X[ۗN=p$7vɵw0X;)*{ǔ] 2=7?EP?`q1(\ K!z7>:- U#T ik 3Zutc}Q/a02(VSDÕKBVZ }h/1ʏ'&bt[_l7]ev~28e oknn5P{_&#̓8RKPo3VROS\ tH~NSHa||Mi&Y'΂򬌏]?Fi/u6YWog/[&L,dm}2Mg8[Zlڹ!=L9˄ɡsSϑbKK+ti}3?Yۮ<&4 g I&#L/\,A^ /Foh.͝ ʞ Lq(s/g/oK}}?$dI!D|^{G <& ȑ)3Ig,s|ͦ }<.oj6tdN&LZnH=Ag2qVϰ1Tx >cLZ3 yCι؉ ?=ģ-xxby ="mՇ|$ ~ \kkľ!kv݁"ßF)>M\`Υ ,?zP88q-Mh׷͝yĎ`|4poнƦ?&?ijiinGw؏/VLbfRY!jpzJN[IUnLΕqT Fg ;ȗr+ݼv d n ldY9)_”SGS 8i0YjX &h5C#'ƈMg9 { f7aK_5彨nQ5 {(OUl<:B:>'A<ﴎ @r.J{bU5.d\QG2G 4k5 &uD~3@IDATv چ,'S5瞫9A:If ovA |YCѪUL|ϗti&8cuĹc[Erchۆr9^%@`N@u1/ُDOܮfWhgVSC>j5 ]/dǍG 4 x܀ATA'<sU#1Sȫs @1&|3v8|XA*VA:Al3e.nۏLHh7::t=lvqMq_dk$l"Oѻ8>cֽ8Kj:T˴L?[R[پ cbrNu[%}$o|s7*r]hiEBugJ[*csF 5>|`Ah `ڛ 4n!i9ʽ2@>9@fK,FϮn6SK^<݁6Y;g*b̃&Yur'ڵyW3CFSrۼ+=o@--\1pJòTt> @i۽ fWVIbC yt>ws ij6Cez3f"泳lPOOO L1g~=VMT/[,"Nq OAC%A$8hZ5R""REs{/猖kXX`r̼s*T?Q1`g > q,3 RP¡= 2Ond@F/}tBxOg sTa#yAKNe>dM̦|:r}}㽼R[d# 0=q&756Y{C%YtH/Ҁd.Y0tG02I0Ya+8f 6Б'^D&{%YjoHYOkNҋrZr69[ҕn#Wב!cxE/ޓv6%W 2sqϔQ3uw'V.IӭJby[jc~C:Bo f=ut6&g?{/Z7cd--h(ahp36UT̂ pN7؛ڻ^%:%,յ7K&xQ̕8֜|˹^*h Vqf#tww3<Ǟc#b K c ~TFYIF: JknZ1K1~źKֶ\Og @35=5ܼlR -^]~J@g\r =V@arm# r͂YF΅Q+WzT~q x{߽~@Vŀ^Uy[kB ][>z0A)QFuٵ2Y:=eATpk &&f}hHd|ڊ[/K#3YϱCGW/c]'{hO dJSjpN_zI4ބ\1hTT~X23ubPJ ѥٵg33iXoaU33\o l h qYyvH|09eG޻w(m:FSc[KT^݄On|y&J=3d0=?9z@|FRΩ0no_\= `Иm2|%}5!C&7wyjDg9QҍdEƶfҞ 2xvKc+ߗk;OU =#|[0y,%Hhmo%ƱIf$L7B{lUsϧ^cLjjךe p`jZZ~b>ǜ-uѴ@ \[XXaYol"i | \\DT9} N0H8,TɧO혤)+d%M3?/gjSk)ǑHT҇/ >D4נ/+p~po{e 5s824,r/dg /X7\%TWx Ѣpypf0?5dӟhsŖ}˵HB(o;6+z` KΛB-P_d>Kq.C ή&zQڲd-`ѡRדqg#@#j};Z8Z+Ѭ J3-7W)W[[ݾ(:?ᣎ~+pljp1ty-)Ǹo}/u׼sBᥢ?qSp_~FC˲]RzO^Lıs(fPnni0LǵgːYnjK#K T#IDaI @i)i eھ?L(Ͽvl=,g>ϳkHL.=B8DG`#(kGd7˰LeWHYhF%8v?QF(́ 028(4ߎ y200ð ##ĩӑWcrf_#}2_w'?)>_K1KY28(BZmN'˫߿q:Nܺ{i j`I/C  qXr1d6D 88ua ?0ܰI#V|0bX}54k:W2(h1ƕ1ttTҒ&؋M){;6n8tlX Q :aQj\Ǿ8.\x#1ݸ~]+@{^{=2^ØׯF@ r~/ ՝[H{.h<:(lĵFoa,4ԣ#8p@kQR=0Ӫ>FU`\{uFRϱ7]-=EM^mPR%j  é95E0wj3]]c4Ïsʹ`x2gA.;&x /{N2Foo m^\4g^ݮB'%.Y +A:mYUlmE a|*(RglA s?ȥj*ks%;M.؄qpn"q*:J >& tH/c{-?ea=flSx`e8\3:i czWR->Q},tg>^KOJg:le`Oi^x.p -,xUUy:9hlę6{̣gܽ7g(Khdϐ qmw8 g@0 _~"x`)ڪ)C^|V`rkVy?\/E+ |t7WRKkcgzA^Ǚ @"u4:ߦ_y Ul3 ѫ?))SU ޭYk{7 Ν=Pi"G3 M?b?{?Ν@iΫ_&\鮅Ooٹ45OI5yWCu k"; R&u|( 溴8!Xj%`9A456) k?G$@̗_x%+1}w౻rCS['U'gK@E_BԛM bfraM|r3~ޜN/]n"gz:v,Y~XE3t:) a@]7L07O)5t6H3-aW?}/puF4էٟ? 2ՙ_ыʶNgұcDZA$Gݣz Nu2^<pb<۪(] |""09w_\&OCDegLiuB. pQk[T];xo4{wcC䰎E[lK b"m{79ijVۂV<mȰtIlN)؜JO;y5@3RƷ]YZ߲Eu H8 r@\̠4DP U5 7"#̕uZ8u:o|,ga#c YU)Ml3Vn%/CkjrmWߋ M+nyj |~uV}?SNMaq %8~8O' suF^ "53`,2eΠ6e뵭 0 nU)XUO.0ЌpyknZ#mYGPM)Ύ 1΂&IB`%5+ yJ%+ծr@+,ɳqAo=< &.~}k T4@q--k`RHU9;^S4c3@ZgOJ RiU/2Ọ s &fm@1[ yTFP"||kJ#ʪ e0Lz'1@pK+s*#8 wBv:Q*jQalj:Jܿum-t,e@ԥGŐE t%:kC.t37{,]z݈_'}֖а/)ndk$ C<@@}KSdpp@hBь:M%ێ`Ę%p4l&h:'w{'y' _ .!Tc>>%i}n·}GE9cBTvĠC\/0^Tu,*%="J_LAz |af3-#qTp6 0 r cgSnfN2퇬(x'k}cPyWWqZMצY@I.{*xԞt$oڀ- fA[5Lm&0(p V] 4D8N4)0cZjvbgxSd Ҕ4KOGEG:}~멵˲[̑g5hh{<ǚS >VғO?K뎐_ ) ius S2$]f2&F h90.teEۙ.|)?3=\-I YcYG`A1ڊ fH%3Mi8=kWe7ϚskϬDy_yCq&| Ǥ<o/~ZF h'2*үYPS8?{Ԁ\҄L,#ʠ5|cC3Ͳ :Yuϳ-LW2AsIy[\;jG9g(3</yUڛK=z}c ǧ]N#ϒ.Ypi,0M-Cg|y2k23| dA՜džp 2@Ք:1S{ :e=Cxvg]9ͺؗnzh5_^yoЙ_W3:Yȣ/sw]@ &5Xm XwָF&"J2͎w_/v,32y0*uX[i uVWf{k/VMQ'~׮cd2wp*񽹶8;KP_!y+~E`s-ib8dtt`G_XB*(ij[輶=}Vy~s/=]|^xI?я"{==RGK=@u'p 1^2Z|/π½Zx8T_RQ)8fLm2̀W7y1dNzWs=FGtdb?qЯKe$6lG^ 9nmd{o|@*??~eu8,,@#bFv@Ӹ: -{yo UWOI~H5t)C':#nhJg:'O³;o l[sg˩`T\LkU|K&dž8ngw7i$!ϴ-;Pz?&ѐXFVhSmʉHHÓi[~f~ʛ=CTg/w ̲/E?t1=bo~+uJzc+W)]o9yK˸O`eѭ qv/)TCW9-BF`1/T$SEVco~*͞4ykk"N[oཇ 9u%C򇽽c\%ϋA6;yukeo{okT5mޜ2[Pـ&0iRʶʫ6, n`d4ØXVξygڏfzX3(- Rguo;[y}g# v12CнԾ ި?B+[Ww(܌K~g`es֩WKI $}dgB2!C).ip-_x]櫛9ʽ!YP݌9`~+BTb0>5=$҈MVLk[yXb:슚hnnm/gxsV{y4j1ʪ[;K x4-['L:ÕO?M 0dE0+Eˁx)SlWJF}X{n!aس mx5J:GI ҃o}ޣQ:: k Ry{9X2bJ1fu@ge.8viX=սg 89.EL3~H<εH9b`.<N̸|ZyA7LC->,δ\K[Jǜ#x SiCIw UV[PDfbi;-R9a}$^D 9mX]Y{셾YkϲVr2VU?݃gN'ͳȅXVh>rhV+ ^% $r?}e2OXŰ(SsK%TRy>1qL3+ݦAR(aoC3>9>HUw:U\T Ut=?2oټ^.yqKZ{~'0|8{) ܽr'87qTn֌kfwBjdkOak?IW(aϫi:$z}c "ZFG'q /w~77ETٞ,Pe 1jCg}c5MJ͘7 H?=[O`䧞n z˳.k?OC]z]Xtq]Jh3(,#`9-OKH|JSiy`YH89q@92ЕGq ӓ#d繻 EJuϧ4OPtGSGwO\xIYiDToZems&*\ #3ye UAs˔NkjNl<eedQ˷~y!2Cǔ~ -gYݗ:qa RBF:<3:*j)54H'AW Ze]uI!Oچt8-2yZ?v=MXZɆg$-/ң dm6 &.^br,:FƣQ܎Z&뜣\ 8z)wp{\2~g p0!gnR*ӉЖOo@+ x~)yg~ɓ*-SSHvh*ØՉ`zEu@-rqv:g!?S@'*t>[F5Y}}>kYV"uֹ @^yՔH23ޗ}4=&zvw:cm GA1[jXJ5y5|ƚ@TPɼ?1qSUne*y,=%6Tr[s-9S_oE;wsf3u2:{"xFޙjNoTs7Ktt W=2[JDKdhzn7K ޾q-_*1cf >m%7qLSThRlb4.eͬ G>5Vq~WS}Sϥ`,i{XBw)-7pIpX[^Oϟgy 5XR*`H81"xSrfS~[pklju-r_z@N)s/~$[$i3y)mmXd>7ϕd/tA^ \&axYNSy%,:"n HNw7?Uz3grb,i/Aq8#A[rΐ) xr*89H%P+땮M>rm㷺KȋkM>}xE:y 3ޛ'&O/]NǼ>vv(񘱷H{3AՀP:VVҘ$ "T4T!=Չ}5-#^s)c"Ҏq؂ ?A?p4hJL8-nVr&dɥkAyh6<:g꘬aJ'SW<@/1z,U k Y"6k9u'?}UA~c"h_R .]8{<JV,'4v G2^yg-YڱdB%C:OfS6>rK3\ {(RA˛ 賐YƄͳ=G٢mNf2OƠCZl3W[‡C}2I9S^gt c0 *!y`Z[G 4qJ^;N)zk)=+)3_])mӢbn)vxgs8L<_B]!2 Ҋbz9) dgk?2+pA݌NF T=wg;R@e9^t; CJ&9I3sK&l-TZ'T`;71S5W[>LU p̗<^1s/_ҷɟHy,cT@-yt%y T P`嘌׺3 K}^584@esZt 2DV:wGyY :VAw,HU 4.\@6S[.Txmn: hb{rce}hTRM`Wg:M|᫰RO<2P{Y3?PmlGe>>#+RUd[5suȝV822}N}uZvx-v-8Q.ʓd#/_l,̠ki'tϏz[סa@O|G-ґ7wQqwQ~IUWx2+?5TQq3C-:> ᥽BA/:\#0[W*xjS5kVeo 2-ػn08Yh5]G+p*h:,Qfvp/OId,d7a\-AN*k:c5^t:^A/]9_M#Utjrߺ@e4G}ݷ){u"@*p`JۇR JrtK{Y uyqid5 0!TELѱ-q)79F\85q5vNJDOrNvS=P1x@V}q B0QS#~22o9,W@o:hUGR񁥣pPHI9A6R@o!uJb7˖{/7ʴ>zy3YCifl /MikUCD0L4!q~XԸO} #ql~%0w3uW䤞'JoؚROF(_e:= Ɗ >N?4SOzd@980/R =oֶvh^̯JG~.?B4|ܝ }5鳃sI}Kc1/a=ӑZ!a$ ꢧ.y8!X{ef~=3o}U.^z(3gRf;c+83^ 843a^e]s7#@B'jy1q`T|jhK3ЃƤ=4FW:Je*8< 0`V5+h篎`WB_?,0c\?zJyRWLޮ?31q{dsuaϞmdЁilPە8\ P]@@1tot7>"W)v:(jҀ:`{3/pP=u\fyw˪BN.뾜{XWG_fH6PĬvA*A'u=tz޲}ܒ;/{A3>!͖^z1rufd_v= @_هDV ?;n ̶ s/V|Cak.l7oXP KXv!# iBt2,uN ZBZȦ -.ٵ 8ml0e2Ƚw9l1a3Ys-Ɉҁ+ }8sҝ<74e lmZ mEU7rlbi咼K5@+=Q}' 009K aFsGoġ%'@[]%ؐDY3 wų6/^m7*-ljy.w],>m1NA%^l*"` =Ax):7],+"}4cy,PK>2cα|>2vk幅Ix/!ˬ}X+]5#8(f.{ XF1=2(U 8@ 8=c;e'E2=lsW! 6Y#EuV]HPVyA=873#aS>wm 8qMKS=繌5W\Zu+j)ݛ8#(q{>s8HC)=G)*w.ce"Axk>ϱe:!aMGeƱ˽PNz▨>p_ZAqP 1ŮsG+pG+ptfEysܹ@)WAwA"QΰP$股Y^ά17I8DTn-#Pg_W K<U2j (- pA!q҈hՀFfU\~iPRms;L7{;sj3-SE;fTPɬP~ًCQ~άq{[\cе lNmYVqc(%@gb[NTDeoUj}Q>s^'^O>L8ѫ{3 ͱW;80Z&P8kK1 j@UCccI@o0pVoQ7`dh;2ۉB}D & jZ 3##3:Cp@-i0N͐VJ7`_SRX]orddhoN SDWӅ+Iol Gqv߼gLPXCH=!kYy3N¡3C[m{c3?u:JWq>R.pjާ8-UXB%\#lre4&p40EGgxiok{țCq}v#kp?sDIM–ӭ!yؒm:sKq".R꿜 2 KV}55 K˷͑ 3/htx=]KhQܝeK(c~l._:,Ga\>ɥ<LJ?X~m1m8L6 k{ GSa} p˺:8sy^tU{qR>scOmkYMȗ.:]q葁]8<5E:@4a?^=03C]gad$s\f~N,@J{nF:L V "8-oSX=spmm͇Fn,0Wmk:>2&߃'x77ޡ~ejO/-856LIG"y"hikBn P0,1f UL'=_f6/5q&kCR:j)nKT Nti@%`[[ovjj2=30룔`v?/W峭Ds{w7[s6ӡ^;zO p9u>i@G.K4#`\/7kV"[A9r G,3՟zz{9~yu/3YMŒ.ӖV7\e8Ygc84 ڻߕ:ǕOϖ3f53^"NۛSk{{u\ ?^'? esp:^\0w] eusqrfmXIE 6ޖM̦g?{c}fBBN)_Μ=079Kt.R9Yr߶ <$L"*1qś/KY0 {FFn),%f)oANiXi߃,2E1SRf&{]Ynry(bJW1_ 7~8cНHгdꄂfqVwu>3>Co[FQLdS)3)o?ǮCP |!3@h I 7˚c {WVY_2kg9Pb NtR. h`: <^m_^u5`Ksz  p^;Dp9j<0q-AF8VJ `I6u0`?Oum@=)r3~;4cm@ 2iJ۹Q2 `Y`MtiK(ڔִAwY=UBCluv60q=ڭ!{x>ڞswuJ?{NMr2t-b_ {H,R͖織 @ؕ7S铑Ih$G^h?N]XF;:C6( 6Tk?dF<i\T5Ԗ-!`nAonPsF+Ǘ#;zhDuY[0uun66ײ}7.2BvW>m+r7ɽ=g1g/=\`?_E%qB[D@p@}i; #u{`I3I @BO-  x+=KRkCej@3 ^Į/Q}G 6A.3S(al&0,*4ޢnh.GYSx&"4fs֖W &JŠ\>O+0x8ʁ iMl} ڰgAX/,UZس6CsE\2cԖXkW+u:yʒ:,GY>]0R=%ztcILX1P Fe/|*f!_r7 0_*Ap[~޳kθp)[7fy~j)5mBlwmSIL}E&,|g?rrQY}Ogmaie#DȠs=qb#8]yfA K' WqZɭ4FО~Pn~?R҆,r085ct iP,sCB4p@&lL?q屧<Ϲ(xsp/HaD̷Qz J ~xE`sŝ-Fohzqlݛtq.]Jʴyf&(kϢ߸7LҋJk s8Cop**8sOG?Z~QsG+pG+pp\dYDuVXpBGγc'3g:$K:Z+ܖ-`.4nJ`:=ZO``#uHALSgL88xC>\N8aXU4uB˿j Ŗ2 1'{(5ױ_|Xde8R߻oaګ4sx';,QROO9=qxR^[[nu 8GFFR=.<8 8VҕgӇccTU[y5O0qcQfRi矽YNJ0cif?ڻ{q"QOsɶ/,=˫pH|YUB2"1|z`hϓUUOu E=t/%1{&Q4д3DΜ"D4=X{&G*0䠁A -D!hlK|AdЬ^L^ CWR3T .%,P u N@anǰ,lH7k{_ pEGd`=ʚNA#^{'~h>d%o_]o_5F;p}oCh'ϥ[aþ淪cpvgQ:%tT(Ct|B]e1gjXtl$&  &hA"e~x1'tl:7>^: utΌ4YNpsyo)g ~碣^kgMȺ)YyeI;mlx$u_oR*:|V;l+yٴs_|@rK"q}_tr.*_X %*%g?M׮N"w(ŮSҗ_t>ÿ PpfsoN諈`2>~:wl!(-IU#uVPv57_·sss} Q ύq>>/>G} 0/*)5(}љ]3]No4sDx!ͪ g2#(Qk1S>cc+Qvt):sp  @[R6A5℞M#&/fI薄O?As)֠&\c|xCWgѹ؆.`_3:#np^,-|{s Xdn}tpd zV1c3zCf &׳7<8A +?\ &p9xxs*JDb],JUL%6ꈮKU,ih GzOνXڪFc)cl1:mF\K[;YdRC~G1пvidgMwJf;̚ɝ 2%X$O>#] ZJ5<29ȂS3-^uʆDH㹬k6CPql3:.ssћ pDұV#1@+"t{\ueӱl왠_."q @e[8p 8ANAHWt_ُyT3yPpd37(3;s xy|:ny-xʫS[I xz^tsFG | QxX16v분mZLVT6yCރ4Tn뽢\54^/҈zmGr8+]#)HY~y1&m]f=K[5<mVfOQf q/={U6<3#qy|ki 1vl[nH^W='eRJ[ {{ssxNLxblڄ6p?92C^/_\&~%˽x#dIҨA߼ qꎂ҇qJnq^Yp5f:8_ VP.:m_Az@ܟ-q5_`fЌ~:A͍TiȫJXǘZpY?Yъw>ꑞ;y6᜛l{m=oP۠o/Vr2hC=0 k.Bkc_ AZfH;'FL-XgA)+ $]r1kskJP "{9Gʖ+:s^ 8) ';[HYրmavwhY:eڥ#؋mF0tp4]/ D k={qhЙ4s(7֨]{=Z8Z8ZO $/\-c99~(**uFs3^uV@NeX~LeXNo{#7;hBS96L@YETZcIτ? ?a/X3fV ~{~>~Q+DdOftu!ʫs,~On&%38o45kDb4gy^FI#^ bmm2'2,%#xU,Cҹ `0prutG4}nYý]0_RNr\o0z{ץqx0v,:wy=O?,rYZu\TZ9(㚯-TMtTK^ "cEd9Xw=ػZ[üo$ ޓg?A[{;A%kdx~,R>J@)}pi=}?d5Et%|w_Iqð87j֒Mh8&)18!A+!t{tǻC,o>x O]H>ɶ+1kt@> ̀W{гrװ\@TG"5ǧ|*ӌ#})Ӊ# >Kʳ.:HcsW*)ؚrKCW6g_3/櫡4yWgPw^|ln%+sKGZ4BI#Cq&:{mZ9sW_I([YY;J{@Y]Mm$ 8)&.v`m 7Ϫjqw畁տ:dJg%[ T›\g̜/U\y~6p.tqt>D!-+?E53ulF_j502X_1T7=NDn ?yr:ݻu+=t!{W?"otr!zTWzWY뱠/ 0mki$HL Yi0P쫭i\م텾`!Hl,NCienY:I3GY3,Pޯ:)!5޴85B;K |^B_8<-m uysV/Z`A<{I4i36}gLcGYȒ8wΣ#V@Rooc0*FZ`@VpҬ3@!dki䃶*_k3ж)䪼Ǡ 3ҥAlH>V.MͦU~3z=orP Ht'gY/&uG;e jV)G=W b`+ x\ (J]+xX NC堗p~ p]o4 ;u?"Oym w|E0,kרHK\G,Ae"q qRBrA[2##\?. g Ty,VX#3C>C0ㅏr,y/[} bl:x3϶1pۿJnskˉhU~ ns_" ,ogu<,C`ewH@X{5ϙ4rہsBQ`_@;|'&ʵҊ6|=ڮg`$gML~Cu1<ҋqbyG%! e>:>}`! vGnqNg9`&~>de0#X_ 36kI:a ]6QyW2Ȳ./#p1gǤ-!/Jp^&fߘkgZ=lzM97s~ -^d~V_B>/̧)>= d$ΓrߣhVhVhV *]?gJUYg|;c8lG kZL%xWY68D_{{Y (՞OPR )gaY9#"Tqx }=UX34~Y>*^ǘ e!ˏ>|>2-w΍t5gR(9i 2Zq ܿ,b NI.h JTC, 0P 0zmwfۀ:0B*CH v -O.>+=q1љW뽋ҵE[,L5k39^[# xav8dO @lz0oo`4=r=?u7XNKN#' тRdn: ūdfcഫ,X)L. |M~Kw=}-'Qf4h^Da KwkgL+ Z5}t$i괲\U l mŁb{n̜?襧zBYd)$dIoϤ=Wy3:,`h 4=Y&QǔevWS'ڟ@u@V`Ԕmq~f}zg9 &{a\L7ߜrg>AdON;o ;pwޗSJ?dCP0nk.5Uയ[/}k|vUu}85870,mtYpd}8 KK5$)VFydgkvnbnm8p*6ptrSC}q^HϫjɆ!a.?Z:$ XKB!St<˱G LK:kfQ81+i@{]eQi~>U5N+gz$?&jd/̥QUym\[xg\g[D/Wdncв& {SVBU|zZ]x"նւ CLj+Yp3:;YgI3B3X×/d|댲]EI9Y&իT԰$*]#MP*]FȮ YL&BfGvxϱ3) f/tv ʐ1 KYcSuC{C4r @O ccUưVr+S]Ua>Y lYZHu,{RAF[!΍N2ԟ(hQ8&bFklX]?p&5BƖv}CGVSEF|z_wWdttusN[.mmG|GOV8 uZwt=:2Tu=~w}yHC9]q8&[/dC 0ŀ@2[5ZԳkǽ̮*?n ӟ\&4`] AKuevS1PJ;udVךշ߫os4__,,=!)IibA=^e3xEƿk띭o'lf r0,+yss,byu*^A.&i"gW=GHo=^Jd_[:'b_ֆ SpxGh.ֽ{~)sRڕ=33Ɍ.m <tˑ+='?* pSuR@V_wV. ;w58;,<<:ƹ2%hC/zZe!rtA`9tbկeta,)#+zß2z @zw'2' zWӕQ 0^s') _IO<:2! ؓ4<25sz b%ۛ=JXL${kUP 4p^:afmrl(;>u'=s'>_W= 6ғǨŹW.]IS~9t_>ڸߔGe0 4Y]7L11:7grX$%c|M x]d; nm8{'ݚr!l e6A{kΪ9J+hg/nnBoeTE}? A?j́"R; }!HOVPJ|=tNKߝ tj/Si~:I>u$ghؒxjFNα ma&gtbl4 | (6A}4PD I}.c}o:z5vFo 6FV"SBs'ۅ0Y}>.{gT!yΜ@>c]00MO^eJ? g<g.wAwnKFǦU2[I;I?zUL,SlN %#i.K764ϕg3 Qg888z)kgt8axwϔv<4sރuFNg U_V\Fg*UtЛqrn}Am5RD/:5tyr05]t x1ƇY*yk\F]1`tkP1yWȧ:0;k%")}DX3HûhP=f{#RVYq:D45]#YG&h#x+ml50*ye #`gxl:LO=֛KBPz2{ KiHR<;sTW| g ?8 &:\Cx!uF'!d4=DηM2Y ƭwoBਙ?:XZ)R\"0܊hޣ;:ERn0 Aǭe̊M޷WfA`ch}<ۼoA Y46H'?; o8c> ^iFfHTdsiwކھzjoA:N1nn5q&r9\CGX3ʂΔeJ{y:!Ý5I92ʾ i}hPZ/Zp4`fNpr3ynU䂎Oעcm"cr("XSS8Ӊ><xs0"vzSg7/*x9$@p8zBa]m={2 h KB d9EgG (4z5[LDevC?KgAOV,>}F/`YF RfT{{ b 02K8 ơ4WTzn}z.?.Gp(7ٌL^H75$&Ҹ+K2&)(zDZ_Z\#2=q駞I˟`-0\|H熇K_Zuc'Υ"Sz[Ɣa m cd󀦭dK۫=D6mozůr>p|Oߌ a<7>l>&sX]N/~G>30$ 8! g5]K:T>':fd`a~WV#V<: bBvB_ߞŏ'K"t_'new2uU@ 733S[,(J~ Uvtvm+ 6&R3sl y) 2_Hz8>\Φvy _z<}7nf-@IDAThq*c0|2u6P[= fM셁Ad[ֲnVtZgfr/[_y_cۑTi_B -h>qwduu| b[ѿ`*@ nV؏X6I5˵R! P@.zqa͏}} +vvIrH=sf^2 8%wmN*|8_`zTF&wӍ1 AV<.18*OOsN@rm3řPo6hЀ䋗 }-UykO_?Oχx?\]uƿOw!33 ]E7=08BC41禌)tWߨ@+ 3kg*X!3Ф;OV><>|gr3K >?g(J;FFv'ggkipVEstMȌXllz矴<͊lTu)/3ր N&2nSЌ TгXQ>&qϨuϱXd:l{ʜ6Y=*Pwufg4C‚Uj,<fBaxƒxƲ`aߪ쨝k&ug2Y9檫ϪM 6|C7@4;N=N+CMj5Cg3aǙms?rkVϳO+ANߓ,(o};y* ?G;tVW'ҮFπ.sq8fF_mbkVݣ~RDcrnEU {܀.NI$:N5}# g y<!;~"L}a)_4Rm:@g-^g8(o@S^E*ϏqDY/UNLJQQ' g?% cԌphڱfik$li084!-lcjb'>PaCY CJs8tR:#¸yx(F YS'eU{ 5٧1 xe_t!~aȖpiXOhVNd9vvLsȀ̒.K:4noPjNpVmn?c['(\'c ȝ}J_βOwWs<: Γ.O܋ru={8Y ӷ44^`Ɩy^Z Q/X #PK;=kp?z7>@Yz!@1{TZqrdMT+'``5\"}:!b3)avFuV$Q*ʔJm{򰙺aoc"H,+`y 9Y^'}%dMlc4(*+]5RNL8C ܤ}>B}a1q@%JųXWW2,, {p) lNK[6d_4cZ|+l(]GՃ/8vבs#$&:gkC#df>9&8ejW oՂUbU-d.؉`U0uRc?lEV npI%σ5uJa]8؂/hޘm{C#iF:N= -l6d ^Y\kn۞n[9! @FGL7 qYpg%ZNC2)V1g,)J+4,Paѱst ;b3̄4t5/9jr2ZghVX"h *gid+ȭ@UB*M8)G8Ua:Y|Œ}W_k.۟pX,wVVSPꠏEtev߽due~V"zg>;E%tWZQ~C?Ʈ< HAdU3Y Z:SZGL&!zBT6Dڻ#q :vKA-='sG ~o!Of!id|=_ã#VoYkiw 3;'Vi싀řQ{*3k3(t #sq_q=+i;L##xF 7Sr QUX#qd%2x1g`I32xI+KGfmnc{pgOڵG`:U$fՌzhmP!:_g:ƃ~Î8s>]FTw/%(L9&ym:|؜f'`>I/1A/8<S{;}cO'?6cnp4r1$[9m؏J[׽=;.s6(]Kxn!< v+~=ݾu+cHe?B6o([]% } j5<,=9 2t}]rϴ# U/70à :ǰ><ğ33/Euqm/SeZmԇ)QmJ~_6'z'^b!1&0{ӠrLylKƞ?:y1V+ř~j^2YWEp{j ;CKI̙ 30,Ѯ0`M եSagEi".͕5r{Я UllaiCW>B^٧vaGuh!@>i䱍=lU Wb (h {]y2rMUږul< B`NcjGs3lD6{M6?o B)<_MV3S*mT HW{6YFߊ 7kS\Y=͖9zgvvcOh #xh*N>BH zvh5Ocmg `*+q˵fV< Q>Ԗ4~Ϝc[Y Tё7kK+__]ŀ؇Ẋ}7wKl@nn1 hF~.(캟n!}9WʓU%͂:2]]RG% 涍^#=byL?H32 2n!KW*֣ kYwQq;%u [z/']|Fԃ\0Z)-].ӾaHShoR2sr}˳jT8ViiKam P߲f琥b4N(=RC= ݓ5oJk(f"v~ A@2d[gref<ٿk 5|vs#$786^[} C '6%UJ7ݻf:zҷCRdS:6PqizD:F g f6qt# JX\=7hL=][Ǚz8Ssdϰ3 jrs dvb]^%~:uS.|otƺ7c-Lj!pLpdiq'Z/%]]T, ;XcYgΔQ{8'4=(8pi^Ĩy 991ʏ P۳v&`|0̎=3l_pO1(1ӌ}(_3 TOߛ:2(H{@.8*d?w9*-@{( oF)- /3?-WBPCilD0-:&tznR@UwCj2}q4d =Ͷ?N9,`BaAzaAۀr -זTs XwuT:z 31L( cѡ! J{{4:FfsPNЁ;u<4X楬dR#2r8[= 8l9w{2өP͔</9?e:']t^̀ux\5h̀ &G2]wPֲphxs*}ۑwt 6`KJf+y?>Kg `Tnv< gP?cSg|9;QɵEck򎿣>3##ߝ Bg)gVpޝJ >c4׉/ nd$U{_{3QfGoQWv@0YVYo 箞N`UDrvda={sM8_elHlgJ0@G/y4{n>Y<K+o,Ym0XT? qjɏdɫ7ښQtrcOƜQCҩ{|rr2_>ǑAl˽sO(HИ}%Z4YȳVp HX[=.Rٍ#+98G/rkKyXB\xcy2ݛ 0 n*V)B_#V0;M hnV,z8Ng܊)L *`tXoB 4BJpxH^٧‚g;00&I+џR҅Y]%{ٱ/Yͨ < -|r{5ٹ\u#d1 V'<6+\0I 5ޑ_0{NP|_MUty5:6t~߱ J RPeBnFsx?cu)*E.h ܊ 0e:;;Dؐ.HQZWm"ןU1S)Gfjr9s-ww8 F/\B>Χwnfuu3U`kbErSЕ9?[k!?xFs~/ڗ?Akȝj3<"xA A.tAgc+}lLP'Uė2A4#"\!}6CVN |ty-s(dLxb  n[5 `ۏz6SPi3+x6ijMSwk}|l33nmxZ_뭾YF qRzG rq{?$@Q|\VM}%M؀Vyz03(iy!F P?*~kR 1q?b+gL'9L,~} LtTW_"uP.#l3LA.9izNi*C#}$ﹿ;}bٳ-:XCm7O`(ˍۅpqǚ q}կ#{U=1v~B<)sYB]MlL~iofvy؞["Bg}cG']RO#w~s9~'y_:HlM+k<=)TGk`i3W׎=AׄeJ'՝7o>j+)ǝT3 (pF3 Qn Li|LQ*-:3rsg//_f60ݦyԢAӆ!*pFlkp(]R}% * WyJԳ-^J 0:{/a@@쀎%, 5vY@Sc}#ԕG 7 F KX>ЊXYAWMr(, 9/OQD04@5`u [ _L$+/\` (;"Ace/4шe,f_؛ 9h y(p3s:c՘07;Z1mI rEcOg{/e>7@M'Ya2}^k!@u9:DJ/UuXN[KROzoǑY bP(ܔȔ 4?=U;dTc |~48QYzNG{x@x@9o{fkhAlN$Lv>8 Ij|{CGoq.uc-Z;f)ۖ硶h/] XD;{4I:q07L|xWm/Ve2m)ϕX*,i \VS%r:xhjP^AK긳CFɬ.^GV (10Esг fnN:ye&ndw5mrLȌHKnV1|k_NWS3*(.Q~y`z1Uwo燑uhØ=8&MѯaC >yJ>i93A6s M3J$gw4ci)*XYt|s{K/eg`g朆 Z2k,d`-&Q,3X~u^=nO˰z}:=oi͔=fxW" }Q|* i%MP,TGurzO[<2%X\B+{Rq eG kXuc!}AbjggciR跇4i2i| '=)c2r\P{|@aZ|hhW6ov:RJc/AthC_jz7SP.2~FS bSh>`XQG0|=uGi.~x0逇=y /~O7rAfs"&R׷v82YEEҽeUvZ7LSsk>v?3?z^ght sOsV0U@7 ʐa3d<`@wfKe*2a"@U$BgDe+,ADJ_?S`nr)I}yrǑ,U  EkfW P)cNRm Yd =3AUhME~}O{ `q|c . sa>fv3n앹1'MCk8Dfm)O3}'jVd*ǃ|#cr5Qh1_Lρ,89s yN, ߰ڕ{֪KW& iWʯ3)ϩ\H >So I%mnS#2y o ;{۩ j%$}K+xZ:מ,V#C/b<}ieA loa(׎H/y\~`m]v}j ^t;nh0h6tǦg]9o2x(-Ͷv9Sp ?ז<5sM^$C!92cWa(/ϵonA3']{'wg>@ܛA?] 9wrq` `+'Tvןõ1F/kK\g p g.+丵9[^~:H`RQFxc|MiýU"#Z!@?DyuF3 QgQ)衿0?C<84=˺{p Q;0!ta6 |^g3 $))Y*Mo_Jo7MJR (Z+8Y7nfu׉AZ$3K#j]':5T~}uhw,Q^g#(Ne g'Me6XD ߋ,{oDu6uJil,N5]^N/pbӺ Di;1ǯ?EX$7){oИ9 A>^ iay.[d+P~y]uk)%1tlvpHr3-Q~ r2|fU-!r O]%w+`e p~Ul5nJ@Fxf~`Vgw|b,>84O'O1tב)5xFg%1,swQnJ^b~ Tu,a2g.sk8q&>f౼@-bt7smnKřͼnKlpe27 lNDGI^`hZmdsjNuҺt,YP=E7 8&pUwstXN+O :NJ)u n3gr A~.:Y!(&Oj%>Y n'mNpƟL0fj"F؎EY|Չfd{L`F}TYvnjc\pG0Ȩ!_ @O0Ălf_\6D;ء! [{F`UA2eSM-ō)Jz†*GTz\y2cr׹yo>  Oή_9)"?3N/ Kl2SEflVA7@N}$`JCQW>(<ҕK3EKoyB]Sb nCGa 3~6VW~5zt f,եa]=g 1)WZ!G GGe-.隔<;qV3#T]:Eэ?k?{P}n2;n\O(]eqkl"P6/Iy`juP2vh >`ٳKPy;ӡΗBrjy2j r/͗|<7= |Et\{Y§ 4B;0DYw\o׾%-;/Β" f:\f"g瞙{ؠ\X^_1kW_IޥRk}>qNI~~cixxVV@W?6@TyZ%y d;(\u¾iYu#SY &v=ߙ;ފ{_@ÏF1P*7AnR.$okf졛7h5t؏]o}{W0@LטAծ=Y9 ofCkl"= 4Oi?n˩w=26/68ƫ_TNuxf175fnԀMUTSzK 9Ni԰~nF,h 1ߴr>yXUl<?t,k@Zy4:GVXCKע{#2Ľ?_s=+ >ЏN(򖽩LuNU您s#Kp(ڡ`x{z+SZ,o#ggOPy'g>?d$GZ~ =l.R*M҇ @GGT1uYu1: ؄!T&y恵 HZeD9X|—Z%P̛u_N%6 G̬imsi@vurjx_Kw$Gy~2-ęvv@]ױ5!'''z{7piՇ= Cg5BKzO[ H3Jd.k\=={3#g+W\^'{ysp8u6Ƴܙ~M#I^$1ayI9Vl ߈<ÏxP-D'< tZiY|s`2e7"Iw~'%>>>"P>4:Ṫ5&xM@>>a(pF3 `𐜜=po|]$D~{)!~ШC5<2 fY a܆3M43Q+zV GY= L u( *:K*o*:F6@=ZYT}a[~[B@S%U hsLO#cW)xT;ǵnJ'!s!L%&,tx/S"f7@wuvg`衷2Cp8nS\pS!0!`b6@ǗQDhN pfbkD ɖÙUk'yTngvp #ЂRb,ea1&X+kk +(6qAG_QR5:9w F4 QK}X-0b~oyqT jYe@J'  ONw'>uMneA+4jgg_2 (٨U\c]Kű8QpW݈UPlQ~9fppի+ao)}'T=/ZSp-zkPvtdS|cD.]`if4Aql75/_+= Fc(0,c_];G]3G ,aVqU7Y[b[вh-,ϙEy}1bV7HyYefQSi1C%ɕ G8,\ƩsU10~q0Oj <'Io.!7)#c\' 884p6T;Ȅ7̻Dr=zۀ̮v A,]g 'd WWkQ ;26tW n|M6k 3=h8} NP~fQ[&ࠂcoNg[ h&/YL)9x 9wX]C8Rlٙ)x }|_gEGQ0s/뤬yL*\YL[+* #s(|o3 x?2h}yCk+m- /1@ QԔE sS&2[cDG]miDv zmdӗי%gUS\#}Bnrvv~6am]F<(;׽e&{:Vj4/| /\.: {ȽyJ[1?އ2T |:7O AxL&`F}%fG)ղj{h3PFr_Խ ZXk:ϔHd.!gc绞7:/0rؗo~3RvM-=8De4~:GA.z;tm)\#.a葜1}]OHc4yHCJ U7s7k3|U3bl ? dLSA6@rGGU+Ge!m8ݟuofn` ru_f]y:i67>k]@,]Rf%; +xvy>qXn̽ekE_~fZ[?p<}Ҟ9*&_5_Xdmq,JpgKy+{n ODS:{s p gud Um: [҅cMgh!Nۀ~GdN-R]@IDAT} `=Cg2x9^b 1#\}$(-^eܻ˽)HSZolU4 ΗpC#{n6y涽>EE*3Ky>2ϿOB3 wZo( /=E>«nP 4e 4,^- bPK _7#N1u }dF?TpĝT!h=8m-mQ:ϭ`&cA oHccRQ=`+{~Lf>ng(FF y^d*ef?z@S>ײnOu!c._}$ ^f>뿑FF) V7pJ+i- - /ƾʅB97c;26(t@9_/Pdfkz/f@ ]Ǭ'A}Pp+7ΝA~2k&2sEWl$lae/Xw~`U dzTT@浱G%;Vhc+7غӮeQe0百~'0;5YP.xɎ-^~rz߳ڔmrv1~jgeh.4Ҁ5sU "ۗ FoHGiKSmn( Ak{j]UI5җH }EJc|O(C>xOi{KFSw'?iG0e {o@A>vD"{=S3؁+ Z}>_~rnQUڱµ3p]k/O9իx`|+`:Hs 1Pu੠ߋа'4cheDdw ߮/$?I^b* `\$^{R@n-G%q'GXe o͜:Hh .UFe gw{uF3 QG~-㧃Ũm[ 3wȩX$tl?CϮ;z(|* .F8ӳRVR}47Q=OɾǨm2zV~NHC R%BـCcU<T|~qj\9mԸ7-#I)D3-Gc=#ᰟ#ȌK/mmf6(׮©3 DJl+=8T#s˞JWñhgy=A薾pʚ 3F'i*qevtY"ǀ:eر Y:ȥU[Y920%JR8405k8HU,a}t{ f5J7 ׏uf_ l5Kk02ri  Gxd`{K|RN3|#,[(r&F2m|Y t?lf,Wb>3Y9D9[Bc̈tՌ_mf |h}Uc^z9u5䞥[Qľ~PvenλfgHgu:th42 t1 E 2 jOriñ @ )4-A:+qT(QX1SGSBޒ܉2a8-S>OFr5a= *7qv{G,6O{b -MLc-a]g7X8sj½]5Lpf} ]Gx s]ngr R)^jSW@vJDV^<+H9!l8 *X>նl4WCY'γc|Aǩ~sd#r;Zr|Lv:|Wսs?ˑn֞ra9˔'0ÑBABs\ [zxřqg- Qw|7oe_:Wt]}zA7րw[33iwmm-Γ-}d!(Z{lc \?%{"c_ !f1V{XrcG:%m|ؒFV.+-j4;5Ε$>PNB[xW|1POKܪ'xY~ v(}Bw[`< 5j=gU 񾤃a|+ˀ%Y:,I7a $X+~*{=["XW@p~Y\ݔ6{Eq V3w+Os?_s{OG*U2۩K 35DZ4 8-ӹi\;ΓJVgc,;5y7ƭ^h,;ekynP 0[M9*\ 0ެǟxoЬ >}~<m@`_O3tZ&2~;W^6e;x]B=|im.~h%剥G .lrmUg" 4+5=wO-×\ w->~V Y\6B1d")KQŊ<8[6: ls3ז|q "S {8Fycu&*{6w:iw;!4w-olJ3V/9&HL2 UN繇I?AtKt]#>Z'Kت EJ*KvZHQ!;*gA4V}NOLհl+3qut\`jj,QEKa{8ݼ*4^JhP, vwq.ii*SxL ,[ vclj^zkd ~Y5.\vOܲ/cn 0 #=ɾY_83*c@(ش #6Og} qDv-չoɞW@ѵuTU=H!!`ȾzwCd7~6cr 7Ndm^=肬z 6(TsՀ->Gw'v3ѾK@bЉ[>RtY!$BVsY&z-"Z1X #2!¿ޤPW!6 ^|ncx˳@oQ|Z h <{CYpE|~?SY{ZA>޷uhz౼HP3 h5G绶Rqͽ1ifP 7kkgӺnُ5*v>6řhpD<ɟ^$ʒd`<.(SVɂ$O:JT rx?\ãat:&y1 ]y u QL~52ܳYmr&K]孾;hH9Tb4SNBO1~'<߳q" j|pIGJ q?s u䀶t7 T\T+W5Zluh'Y[DGC GkjՂ>{;Ng8L &Y:L<=,gY+V j$3<Dp!tj8?& {JK'/GD#SM>֐PaV($[i&)}ʛ}?5aLNKnj0z;Ph{0  "pXrsQKz(yM9ӡp@ =! P5:3,93*8Z}+QzY,Ȍ+hm}lo‧9`^˔oiKK5>q~qzZ Ȥb~#(%7 .-@Sg7*V)0PԨ8T,@F'!fU\[2{M0 <ר|Z67LHjF)'y?J_-D CD+KFʲi2T}ZȞqh%o+x?!cYV%c>2)##Ӫ j!ht8%jZD8t`cz/L}x}؅iHMp>Yw+3hu*< h{It&A:3q+~%wVg^&FU qs}%.1&>Ƣ8di: QǷhc`:@ٯ_ЮR#k[(Ͼ+a3n#i kȚi{ n _ 4|lȖDl`϶t)[K2͒[F!ƠHT>`_5 js}YP}L x(=@ {oX`V'h -Zaq=zE-RB(M2+now3ݩ:n3wqx FRV~PNbbpGbzymsE-TtGNi9wt08>:i?,kok{BF:x#٠L ȴ gF.WO>pc>%p*0;vI i 2Ʈˏ ۸Ng:<+t"帋^ɿ"ZCF t#3yH'q\+ TRF_LJfF:}yFXsSt{:c3 WuΒ8l̵ۅ7*QCf:)~陜QΜ9֮T`9JV-tGA.cuDRo/rВ,"ezp|\<[+hłֽ,3:lѵt4Ş} Q@434-~f7h!,a`D}& nQ&9*k'>/=׬*Չ\;Cg\63\uP= [{^|5#=qNKS_mP:@h< 4a^gf(XG,{h6kn~&5kw MGxɝvrXbh{DۏVKٵC ,3@ @%e qs` ^*rRYe/!2+͐TYKikbBwwWR ?5ɚoݴ,lZݠ% <.H)R@z NZYd Lۃ cuY3V{:>[+-deAzySl>=9?8<{n\g86og,%ΏS@pb x('upMF?<{p:wڨ= <g>dtJ  /ˡݹ}5TA4 C霃ו!I[Vm2`q;mb܇{[>i9/̜ߩYf ƤmtDF~Snj sۊ>L}f529LebY 5etzgwiC {wDLrRܒS\oi{Ȳ%D&r N6[$EHKF!r8ŽpO vP<&{u+v $>U%P*os]Eqx&%ֹ=QDǀ?*N4h_cp)C.NY⩷Ђ~vVQp4pO[0n:.4#]G>>R6#OyF*֠sYӵ@~߇NkFp;C}<^1U'R ʖkTDשuk$5U p&qj2k -;R|L*GA x& -- +FŅiigNc3w (fxpZ*rBYKeC XOG7  +")PoJ^d 9,F |zOʮ-9sf!uޭh w@3yDȏN@"F8ꩬi6cOhp;n"?߻Y!(#}akJvgs)q=\[!̟ޯzzq($w+drxEoyÜ @*@0XQP1@]s"=b\FP#'Mf1|,ãvUZ zDdJO&<xs*(|>XU# j3HxO58ø BsZb>~b0w߫!{ma=(azsNU0}–)C̫('QxQaN!h=cGR6ÿΥ#p#s>cB<:J=]{Eԃ#ooܕKwQ5(#`QOm2 F ha}TϝFNއ~7DHu}wd :/0(aH:2NdsxdjDr׊ c\A7EdC ݗFMio< h 2#x_Վ=(1 ,7y ^CɢKit :WGH#G/oxF\+c|܄nzw*\r7u@ѱ 8=+Xm;Vo^zrwE5̲ƍz7q@t=? 8aC;RgdP^CJ\"$Oz' :?MTc>(*}M :Y_qo#]]'*'7*mV*x-|{;;>/XO_|Le^|`F#|[1>OcIq"F|򎞜J12 {Dҡf5F>m;T\۷UfF6a'9? Om+h𽷳k_V#/ϝxuWY{w;ƪm_/BX pu]P^#mmgNchw=g_4>&h18=wb3z;W!O<{*٫Qo³|25*/ݾq3[\5-]n\>bx׵i2*'Y5 f~0jNӷzc#Kg5Mi:;78CPIً;>3䖑0sj"Ћyӏ>@T&Y@@ ƾKL+3j X͡8igu-FP^~㘻>#­׳an:u2'"2 }> 1gxl3lSD cr-gnaI KW;3' w;⠁2D8וWXd~,rr2{3u0JIB"=0pc=;g(Q/@qFg %@b;xK(T:0|YP~Aߥn;U `8i*ʗ/"C0{YhᚢKu]vl T=̤!A]P.:P7ܥ0yX)eib_kD ^e܏RFYjȼ V5e:w`e9w/.q_Y'ǟSUxD`>9OG|8&?>'0P~K$/tR (( PpqwJl:7Bѳ\%7i +} 0G!@Z-GTNB58 |'(eܘ* ^x b0AυQ7y XI\:lb|.)Dt"qP4tyw֢II@3{t7=tsc!}s-dhC^ZxB1-,!R6 ū0ukd(QIm 6A߮0HSţ4SO$ PCĚui6lQpP UХxPլZFGI޷n!65I.a1iG oo$;&=, Nzo5)MmA0Q4l-֏gJIӧ_TN}G: `o4f.Tmy^qݥ^zE:W**X<5#z{~Py@#[ZzN9bLO޺%塺k@{}$O7;5sn 4(Wyj;5({uy|e<Lo#x@yS \s1 T>HkrwSgnjQHtxo|TTG}GG9'hݦ͌Ii5 `^4}N(}P87TK<\pqpDZVҵEzCtdƆaݤp2lCCiɈfG幋NEv[U<PzHu-p1^`]UAZsQb*YS=o AIǑF&w#CyA~t? 2y)GAee6=f @W DҍTar'6]Ob: k$ M#nZh8C(dn~+>T޹0,။):? 7'M&]MdFhV:r f][4ǹIKZJ 000t:xi8(m_Wx+HEp2LIrr @0:`ax d_拁JJ% "ӹGtxR=]?z۶ʶ޽[VKx= ]95 @*< 5V zI& O;b:ǽd {W4.92%6`y<k*j%PkH 4J,!׀{!o|D3Skm/?h$+_ [`}+z&lwShuǦfU=N[ys@/1*}隹^IyELX_c5hcAM K쟥'sf?֥ LxW @?:B8/9cXWDžgǖW ~s^_g ,iDݦ;BQpXFW45#"W}3M"?Vi1%7D/'mCyM} Fhֹq>-B^8j}5}wLhj|$(Kyzo݈}\vFq((PPS@"J zaxm~@nc:(oU`2ش޼Ym,=y*Y!,={U; ;7/pC*6XT[CS$S0N!DbqQ7vP\ Oe*i6 + ~N~)0 ۫^El7Pl { qS`Ɠg/gɭ'PAH$!Z`Pu(qi@ :LM!!U DT9{ ! /;+x)׋P%?Df'!6*lVD9u!O]|3MP,vFf&ʆ"0 J:y ~`-ݦwc%]OLs7#ٖ"' Ãz@NfŬU:ۮӭ^x *A-n-xjKh!fw_'&%aBpRlCنя09H '@'|vT(i#\| T:d?yOzfl\gz+,ש2 e:i-l.͇fer~n`^SsSY u"wkVv՟F\TԘxqqJi˄a{-[I(VYEi>=th7ѬaG 9]cڣ!LE`(Tv_Ht(WBc#v lﱞ |<сII)VmrQzoCWQZ>Dc. =«`ޜUyEndx @{'үT~9ŻR{nzL%VOѩ?c=^=t_l냯xtXFōeƜiCp~>yX?TeQ?Exrxt}`?(#V0~aĹG*b9EM*٨[:2ICж!@C|{u9z&Az FD*`}^?^XקǑWexΠ:szqqE*x<O[tEo9Pvz SO|;b`\ESs:BR{S6hz:c妡!MX{i.Ea r}3u9} {Qkz*7ͳ}=f6=rZWS-B/(p2LaD(p# #%9U=&x=#ӱz07 !a7{ͤwD4D @4mSDz3*Pgi^`u ;?CMZ$=W1bL2ƜJ>f4~lwbl4ǦMD?ӿoNуm*7~9v#}Y# aǖϲ p7Fms-`^cu?}ucoGkD];Eh{\~UƓ|D_zyg?pnHGZ.F!}491U?u?UAsy\O:@#>JŚ}DJS@IDATqR9C9ތ6X9j |ܧN~WS<C3;;Љ&AtDPFx'VBRt횮q뢆(;y藷~'h+~yIi4x&[4Fxbh$BJa $0$wASG@rRN0 hm 3`{00޾]w%?1?}0ƄmS wҿAh8e,<温AwH 'caU ##h3ftdo5q[mid^^#th? ~=*-Ap9z]7OL81cp a~u4-Iq'L5.>K i-)Z m>kAI-OMc-S^^{Ngw'"tF>XB (w nV6% 3H /׸Rppu1L9lD1ͮwcDfѶ|?c~R񌆕0BDqVi  OvV*k)B}j0 )׹TW:8Ƨ|3>c]wzg} !h]pZQ71`ֽk'm f RsK+#9IWu.eˬς66X((PP@AP;??~G^D7\BJlhY$@pW޵Kx.&f,Ǽ8UPY(@fYƗCYBu]dG+^Cd2ܽF}o{ZBK!"ʑI6I( z)9׹szV:7^ PٜM*[T\vc+XV;5Zz]!1C+65]n}-S`& ^W̰[cxm#`X$Dz_ФkvxotC X!S᭏˾_D|7  aJ#,@vhr0C*mB)*SoLe;ݿ ѓ–:FoGB<$N7f pjP,{Cc{s-(pOA?No)v 9GϾ$=(FQ;χW)w]*\'=ƅu˂9|;r6/s8T uO:G_'*##/1j0x =å'9xna9 Jq1nx :{M޳\x?=ȕ&> oґd gAo֟9ϜcA(n vpc} `M&cu0DRc>sr=J\| G~煭-z?;:}Q';}~2_~Y\(ک,i* s~_1"U޽=SRuF:ڂ5hGY@SᏇt#zʛ+?1-;_{>3{lIG͸s< Uka}8{?6Ócx~y7?bd}mIi!?Cql&# D04r-"78c:?ru`14>ǐg]=ek8,U=L W/ZGܔS?+.򋳷DCטtE.2$=kU@h7k"_PhxV[%~Gmjq,ϸ?H `ݤ'Z sC;x8ﻗwaB/P/iDEjg/2癃\+o8r>R?f#\;\s`,z|nF9& wݺq-{9gIc_ ^ y`0 :W\d0WRWj[do3o`aAR*=©BdB_Ϯ~}`$=[s (࿉|!5 ѻFr9 "?3z;ng{c-ܷs`} >A61f>d#Cو}$^ҧNbLEc i`4J ( G#+%['"@YTrn I7E3|7`cDv7{v?)idPU=XSf6 c6%wAO[sst ނĞˁ?Sqy/Տ:7ެҖ| 0.O f^Xcu [ȞSCn³PZǷ =ig1w۽|nHuGy؍ס͂ FBe3,c6 C̐ni=?6q-xt}4\c[cA )m /qe: !(ZZQ+$瀆CI@C`zUsów`|`8x'Mh Mm /v<{ aA{3GS)vCGD ؾBV BCK+뀹_8pZ2tY7IH}?/vCoxަ?\W, bG_^~Cw25BWDQ̩Ƈ- B\&2Qvϥ.F#Gmiwb46uܑu<=~sNE1O x?3X]ybDsY.lzoMM#(&_<QPR@Si;op\{U^n td{;@{A!ʹ)k>>g!p<3=w>IA*hYPi y*s|FAwj *Bͱg$R0%)*>} ~7H9y( q($toQư4T8,dŻ1!)ӆ0RwZzLyxlalfD 1wJ~Cژx]A\{~M!u CݥXU= P_{kQG_v Ig/ ְx$/|k.@:R˧)ِ!B/3mڵŻ OPD5UIO=#tyI e#ûWɋGF= [)o.!^(pN `L$o Uhw+?2Kzh - 'zYfLMG<<+G^3׏<wsۋ)ȿI9ϽFOU?yky%9zj>N5N{t~>Cmy=qg{yOs7U|˵Cن27xTK 7 >TD!X(p 2*nzNlc$9$؃Kп+ wmYZ0p=JW q/}{?d~{otqE79ayכ'x.^i{ɩ&/če74Y7yq-~)aIEL:;{ ,p{e-x{Nr~{}GKHeRg_ˍrz*SO?l~vQV*5/qcikɻ>SZ5KGe`ž Z5B0wzV??6&}z;5tZ#/WDo &ݼ{)Fj( wt>;3gGѶ9 a~xsA9>{NShK1y_{(eDEw-? 6)2D9xo^itHuW::mqIT#Hj KR 'Fh?~b,iц89NnD6>r "ia$ Á/X z/I|+O4<1iC)t?@tY?Cs`3}y2hLm}>Fl%k%G0֙S!/d64~qL ?:ķvX.nSDJ^S{b(;7DČjvTqoTA1ݦiSkk/e[Ռ@Ew )64pgPYzn!Ouf`9$waÈ5pr4Xm<`]ClU|~JtȽW,зlg:2 F 73D0`Mbb#1f]4#aDϽ5ua/͉c8FFMn1Z:4C|֐ Vzk Acͱ?uLISK8Ffhl TV)k:bhPe5~?|BW i-Ycg$ C+SFЀ_l c**ϔ'j otwփϬ GwO; f6iACm 4Ȅk^Xu푞D@]l~5e#O8hsLtof2vb>2 S^mM'|B|d$sv 80Q)h*l:cs{:"pcRĎc EF!T]+<d¶w [ahU6>r|֤Sha$ S ڏ(׋]-+(PPE&ֲ|m6/=H %g y6Y \1A_)a}#YTiwܴ+-@@J$-OI BK A94sST9T7fêpU0 ss=+dhJ7*AŽl#/-v<) Oޟ+A|f0*,л J$]3=CC`Q sof*F gr/n: 4-C9ij 6I! &") ww>l~O{9_NQw9H|Ee|ܪ2x[=X]= b^f)c{b?xk4Fxx6Gjջ[o Vb~zZZ0ƈ &KAWފ]º:wbH2Z~%럑F#Dw!%ߺuz/\^ק^C~}D 0@ 4Cۧ9_h[ܷ^>Uw]Ǖ-i|&<T=m# Wο~{礹d!Hu4 t;lPjzQ:ܓמO=s@py @_{7<\ީ.=wCwia>4ʴmMƍ!)*FB0|GzDo0g!h/{*ɕqQ?޾O{rA̯,~3"b(gBsG8>sшn3"F_`;bPc< \λM)ؿOh}+%Y=$ %/crܹ?Nxj|16q5lm\ޚk'qV JRc.B7"2:]i#AXFxHI6?&cJ6. MJ- JܿTupfT;~E }:tiO1?xdowFP'drydQ m  O } ΢ooau1%+#DU9,#;<bQ7T>/ AvT^9L{ @}y_~ eVp~|崝6DROWo!t1qhVzw{1%jܢk +u>4EoX`CͬL w;e=l`\H\96DZG^R ݹq-[XɦSgGؗ;;%u)L8 ((Odn*\hTݹYlJ_z=6B{0툰6ȃ=5`8l=ޭK|nyyj_P"A:T@Pcagc@CaԿgO|uBJhfuoZ9=쓠]+5M"My(G~^I~\g{s*psvz_|Oޖ*_˿_G!*iԹlxPl^e1GXhzv:|x{voڏږy:x)מVvOi4_o|>?sy,Mľۏ{-_]Ժ#kܧ~ύEX8JGe=czRlS"{}ʛ?Wܥטd㔙&"p"c#1ˆBQکD1wBiM'PWs&_ ێ8-e"_ ?,y|Ηc]ݗ3zя;ݸYvcӛF?"4D7|mSY\^ƫ^ %Z F+zW< }t~u<;[ / J64~bb$fz|@ijւFF)+\8j :iVYL]ʨzE8o͆ݞ S󎷈޷ m p}xN kF&tȉ6^僀KcE1 WQ9ӫDڨGJcC᩾J/ \;3\x r =DیP#m.t$ziQ bPz;zЭE>uHCc\[z @aa;uR׫`!=%7 VJ7-% 6@ap .ڄsԏE/dt.7v7h`"ܽ ;Xg#p!}>h15q?m otF 5(S݌1#izxuBT1țQϥ1Ģqv9f c=𭻀;Ms4`hcH[ӯhd1o=;U0! A,J*NBD[?#i4Fʎs"w-]QP@An V*@M +2C!N[X&V@rlo]ś'Q@A.}#/eyrG\ABӿ*(^_=G^v׺wpq2z?wo~ιl}wVB>>+L-zʏd@`ˏAދݏUOrV6@©ʕzӧg,pQejaw6?rP>'N{=xsNà7 6f¾:k*EPEMXSH\RA{x[0T7Dtz7\CbCk/'WTP@AR *U :&:; [K4eMgK`ZEA i`54>zԇ{j/D2 Ci g j(7)L@s{XG]nZ-)Z/ ze?//{Woً//BCl}>FarӞn|Ry]%C4ٸ5I 5g/SwDcTOs`D0:r3g9 jҺg4>+2|o]BsLNw0a -j l;9O2pyja~gMeimu-V7W?Rv"u~ /K }T fҷY]Pyb"eRӐ])LA2x &upĶx7kҺ>D9@=e[޺#r,Ϻ.n ܏sM{Y0֨}Ye6V%-hm)=7wG=pN>C[,BX7A*7^7ycFz<@uc={cCpƖC% /g@H^XN.x}Xύ;:s`c뛄׫ @ ZR;Xɶ\/z(B[B&z[Vø]s]E{Cc` 8A6Ԕ!uAEH`|T<54p@ :Z_| y'/8v[vrMIA Ox٨wt+؍ ^tl<hvF݆nz;4&WJ+BOGZh[X?ƛݛu@>O b: 2#4u=w.! M *DQM]4>0BF {j#M@A <+\)n. )JF |Ճ7By.i2䭞RY_]WP{?7ni=bCzXar|qNet;_@O||Ƨ<.*=`,NhϤ>@=3Ba|PH~y٧dr :?//,&R=ўz+7#)|B'}̋O}eq@A*.#9ϨD=Y8|\֛-JQ P\#vk!@͆0&Kr:Ң,C];7;Ox3Uw545 Q 5:鑾I*!r[5?8V @aC m?lS?n>o(]uicT5{ls\׀[&F< LNqbuH/<ہ>ȯ[׈04s# O:0<(kԧm@b wa R-b@8]$h˔Gao ] , 7 8x82z} Dz3'bߍW;uAspXJ\ۣ;MRgYe>4t{o.n}szֈ]_k}̴Q#)jh~6}LHK.<[xe@A[n,&,/0dM8a"?5BWȿ((PP(g"N&iuyz2gyǯI*ݟܓ<5Z<^P@AAQ% HIhTLZ#*^=搬g7>|(UU`j,"m>E2v'g/~yF Kȡw`ً|QVA_O~>;cΈ/9_wi'.pyҹ2U:\ƉLR7!D s<>܍uܥcMy^6{duk-eo(%RJT-,.aEojA6^6( a &% d?7 36 {?y\G=di%Oev޷_x w£:YXpg{ Tp0RP`7L#Cs0/.z^pAW_c7a>te`@!}F?ݜ΂-0[*Ui%Û`ӡM>~ӔDPYѽD^l FEo*amjwNNy%@lڭ@~h]m ({!<덬l7ӎC O;X9/mt44D3N2T,׶2ۀ-CS#K ꏁby../[pC,3IARhg8.s,G~h'?9pQɭ>7AJ7+%(-?MEu On%.}M12[G@^" # i R^qEXǤ9ch}kohQ#4YLk((PP@A ((PP?^TqrT> t5wrѿ&gPføYK9EA}̆xrvcJ`#{W1^ xLʌzTU~=_|q_Ƨx7󚩜IJ'GG^kѷY#9k0;w&;26Vs/z#]I6>1wt$/x5[$A42LuAnTAn=#x@VD>ߦ/,)\1F= m.@/e>e WOWhS@EcV!}-7?}gPxъ-Y}Q_ئxLyzHEz|wwBsG@N+! pQ'f*X3wsaģ­SSr kuAQ 6yw+^7BD^Qu;FxƈZFY8nF 7z_ JQA{vv]ݓƾ^.1_#y{!~6Ysnmc-XH'.?/&ZU AkpacY /q5|061X_~wo/øc{=}5ih F(a=HEQ u*H!]r)!5X?,kt?Fz=֍a6xo#AJ~֝ԣ^CgBpywh hhO-RF`Kk-ܿ^An4Fsƃ-YN_}Ѓ+_ ((|pesiomx^{`"6]B{qG*i*l\WcA 4Y̺, ((PP@A |LRu " ; @rlЩ NL׆h ϲU?ٿOhl~~>*: y1@QLAPE識楟vNʁ˗c^ W^m6[̇ˀ!Vw7fF㩩t#{Cϯ~ݸ9e.0}a4y_i Oe@JoK{#ЬM.u@ Ŗ׍.lpyK{xo B yπ}x`M/xfs^FplVhYR7AHzMf(՛[ gm;ynڮ7o|0^rL |>va` 69gw tRnӞ}g7ӫ@ @0hO `[x \kڤNS0Sz;s[o(z=-rY眬  SuhF]C;ó;C1re7؏bKz[\3©wxUI 2cJVa'oonqN:-TE@ ;s{y i$Op 0GqJž$z*NXo/s^5-# 3/}B< ynixL-P,$6-._#{!@-uC'6p(D)`Zu7dLjV .[ztN8Je?b9TŰ0 aЫ8-ck>|x] jiALs(#z})Z{{o5WvUN@{=hj6Jl0zgys%ܐzK+$8]foWMSZ h锣\vNVaHp֓wm ;oٶ t=]5zUxy\Ms)-dY1 &s穓 ԦE O_'D){'RtXp|)A@?tl?s\^͜t!Wo܈1'n/G7A BbwOc}ɓ{_[;\35  3&tX>;%l91٤.1n,>|@ƪ~KY9Q wӠ'Jq((PP@AVTBeh-&N]mS Ys`*Xf%@A ((PP@AM  2Ի0*2Q!o=ˑ5= d^m.VJxֶtײ;on /z ]_CNGA <'\̻l܌Ŝ.nL6⺶\:Lql劒oZy((PP@A ((PP ( Uw%=.6/P1-0|G>9K}Jt()oܸɋ.g#]Y\ijq @5oq, bxDHޗ܂X0 !uK[lrf[> %X\N 4lN6=s@|ϵs--qZke'OWgwg+L*֬zmLo l Ry{ i>QGnsnTLXpXiT ߼8VYϥE`{Nϔa(#fY @.\mmX W+(kD2[7;Dizװ}z9j`F6B~gQ{:";5TxX\v`;"N7^ˀ^c` iN ^~gzvЫGn5G&J[|~TNzrOp|E^;&#A}nu M]<Kqq4.kmh}@}hPЗ+zXwz[k6Ə~FG1# /^#L>x ~rX/kTWjZ Q}@mW}ACs}O2y.95@HeOg)C`hC @"{^-ڨW;%mʋcbT~ :(wS=w7(4@.z[7߹ՂgĄ xYÈug ~D{㤅9 )#` b4Bf iÏU1W|^[!:ߔ .CЌO_RAǺ2x1X[v3j֖ Mp@Okl|2vR?DިIENDB`colmap-3.10/doc/images/incremental-sfm.png000066400000000000000000004031261464745566500205500ustar00rootroot00000000000000PNG  IHDRQiCCPICC Profile(c``RH,(a``+) rwRR` ɠ\\0|/” RR N.(*a``K @ [$)^bdo!`5 g ͗f3K@l 蘒򽆡&~ JR+J@s~AeQfzF#0Rþ9ɥEePc JJNЪ pHYsgR@IDATx] `E&!! n,x-("  ,(" "9}{3=$W0WU     y!r^%     ( p$%'  p#0,.d 'NA@@/Ԇ!&ݻwcɦ`9h׮Lrϱ|տ.X ?g%Wi:kڂV.  6WZVe2u" Ɋ    @E@[wsA@A@A@A@>|\_`v؁;w^\Ouvx~#@=E9/`=m۷mi/h'A@{ũ/QdZ$S@رcXdMD[mrrq pы## A@A@A@AСC-i5E@^X%uA@A@A@A@K!.b    \XhKꂀ    B]")A@A@A@A@vaA@A@A@A@.hD*R!    pa/     \"vTCA@A@A@A"`K8s6oގ|=QO4j ]1QNF$*(meI5%)8|, %DMZ"j\>jԙ! WWIݺy",4 A~5Ʌ^ ,%8r8թ GIVAS4/ q <@fQ4;LJ,A|(IށyLŮZbw|cxnxQ>}qDbŷ3bu:q,x(Q:@_WPrӸ5:ۋ9.kDrw)#p71 =1K{˖ CD9e(g7xbڦjՙ]??tMd4YѠI8|*%F$*j/al5r"K8M΃[ C-]g-F-P4Gֿ?C&NBs\/x99 oE`wVOM!m>^/z ܴ;:6HUUg?q]X; ADPΑ/w\\~BNj]T+>"XKhڟ[Im\5&[uRY4yi)h&%G_LVE,n"!Tl VѳjO>2tHHHwd+6EAvRN3!"Ce_^K%KqŐjbUՍAـY "V7X bd z4vlAx$ V9(I˱N׻YdHV |Vz#dI>׳Gƿi!C`v&t6tu=\.wzSQA@|PB@OAVObjdB!̿3sV^ڏ"74ʡ=ӥƠ.q"5έ iav' p^Pw'=B>~yE4<.dO?H#567>ԧsg'%!%W4CoS_D"(#XF~ٙW?*"[i.3ΰ:j\.C ˏ 2pS9Rpd:߰ Fa>-$⠷ M_gmzֆ4 C?/#[wqh6]#'fuF7&L]3+II\n0o F|diE(b^0A<9s^[\.'CN&azu"EYy!|ug4,?Ǐlgrᷴ5ySrsklK0 W,Ɓ0j +/eCng*w`r^0oOQ."ar8y49Gl}ߔ)Yy;mFeʮ:FQ+reֻ;v}^ZHC50Zrj\|G?}jjѯl9G3@9m^1bS.ʉ@;>7:՟Gax~CkdY pӽA9G`OQiLzݣ2zi=HTѫp#ޘrw+\7ݎ t!#)  f5͚{h #ѳ  nOz3zi*Gu=;dV#_-=ob쿏A8n10QsOP:8_ԕ3CӠQM}%'%w~9mD`du)usz}3qÌ/1Z\w=޳⺮nywQ4FߑԓX2|جY1uxj7b[}D: w4[iz?>㵍/)0ZWq}]źҡtr!\x@VG>c010' dDZw[} D.3rq{74iJ3wA -ZTI>0IIgЇ##_}z9&lNegjF ,$ '+'Bi&FrZig裃&Gf>Ȼ*!ӌ<gRLݛc k V=L@bيMN}!h@  qν)n5v}xdhDO-X>=1M6zXL*VxphR 9"4iBsA[ Ńu^P(rLH4cV Q5b䒑s\;-{uo_+m{՜%v"h}5c"ZycC pFyv*ϵ[|#asi̐v֋^FL[|K9D[r"@I1I"ʻ|ޘ:sk OV|{ /}uy 0l^~hcJMvo #B".r+l.k=Inm9F̃WDDP}qىF9C=;j.G;isKO7ByqmgL/eLq' >& |E>iZ<"520;X#HLۿyCNP/1rW/ʺC]W]ҸgXbӯẛpeybwᖑuU ^6KN.IJvI鲤ȞYۺu)}9.i1ee̥,?YʽG4Op+]{U,XWCóC{8ll`6^_[]0!Yw6<7 Hmu6l[_OʷgA]DyI=~1k$*ͨгK,ڨs"<_ 1iƴ34GqIl$}'-^]Z31_7 izzo4(Zumuqh&秪zKl)@$+[}_B(m Uf8Pf"%c2,]#H.Y`Lj+6Q>{nf"R(\,!>XlIpvO -ol^ĸQ)Iz+(}qF, 6M흯پmAK+NqYH14UfS£!ȕqxsʺw DL@R1-hk,{ ﲥ Sҡi~j'`C2gfa'cLJ^FN;Teg} oz;Kq3EQT`saRUG(֤N|j'D#(H v=?8AW3[0e*éų%ک^ө#*:v+۷C+V8͵&x0qV鏸Ȯ`nP1cx[܎ :yzՏ{Fjo,n|9o ɩ𻩾AES]tUuAA61|ůuLT#>4C >e'<u!e,&,=B٪jߚxaY-7 HIQ]m\11ja1EFY|kB׾i> 1>#a[x#CwRJwcc34@֏#GC0nNۃPfc^EoI?F.O$ǃ}v~6+2(=x8Z4lȆЗW<;ꯊdK.x|J6:+7plee"RKqN+2f뗟>1A=az3V(2後'M j3Ge،uS${D]=[hO/DoSl,G[׶T;Ρt2Z_˨70= }7o^wN#O;j{xO!=l|utum0pj{EWɦtыH^#p>{HPΘNΣQ's.NV*T@m#SFF$+i{x9ʄMp(d2ws0\Sډ'FL@Y#qc>ێ ‡Ȏ9eAqDy/rͦCOaM* I<Ŀ!;^,[o Hi4v۪-z3wk$+nW{F=}Q1fH6 䓏! Z1C#w?>tg? ?Xݭ?=22}FHvsLbB51}|H6αGp{zC\+ 6d}mhY/z8<1F.Yր> {1 |@cQEH.Syxp#ל'ٯ5_f^OЈxc!ErI?r銇 p)"|dgg;RaͼV Ch^1H67w .X/ĐDKY_k_SNE܏`‰?~}9∔d#Ky$;c ,Xïun[ҡSM4o V.]%wi.6 {nͯ1u\SR$߫)X8! h颏OҤ}GMkZjw=9t.>;&cW!DxfgKJK9yE ľf61{}mtco-o eZ v'FGn!X-hn5=qb w=^ zj`Z dϙMfcwr>8v(Iп#: b?ީ_ w9-I1_d<Xkx)bA OCFG]`='WF^јgQg=ﺖZ1Jı}:yLk[r,(JX]RD ZIvFhZIrn)OۛɎhtyfΔV4AMNi)AYU7܅+췉f\o 4aiڬ$'X,﫿Qܼk0Vw&t$yy9iwM tl=2tڎ[Qq3/{7vEF45v?mwx0g|-@ Z$;ɧӰw <:W2R1z5?YmW-UVYhiA=8>-^ڄ'8΋ɿÀ>mSFWuLQӣ9 --T|OMnH~ Fz=+,4%pD_a\8îU IS_fIz~Q]ϰr ϰwD={;Lyg:,(qĹ_s\An9gRq:9ZYUֽOJ@ IXdX>[.[K{+B5}++A5?nUnheU,CYRZ4e"#H6 t=ґH6++u=;cӇ&,8ݯiROBIJ2Mv &q"ڐBy_G]fh]ɂI-MtO*vI^><ѴmKфE!GZd"Ho^4׎hAO7mBDq3}Q|qCSpݶ[~@[A;oCc|nImI9`|ͪ=K}@甦:tS˄jw?kd?M ӮjəzUVPP6izY͂ZּL*9 G̵ CHw=~h[?'eX 7G10F;O}EG/w֔1)ozSrXz5u2SA@8O\?ˈڲ?]5yډ|U=є0Me Y3_nEJ1`݆cd˝r,W[鴭et:1=:q 6_n=>^s3%[ykiaHzӴA|.6MH:3f/D n޶;&^{4w> 7nڵҼrdwf-R4s]W. \c;64wނwQ^A !b&ueY`AB Ne#22px7ؓnT$%bJ-I1vQ}B 09ߘ9Z5FeC`\}Um{j8v&R]<2}o0eÏ7AYfvw̕+VPŧFAS:ۈWC󥱊8A@rY%@Coyy妛}* 0 "v*4:>BegZl>S^@(h"};j?[XnРQcᙃs!|Lic:&Y-L\K)YFdT(q<_|MVw6cöpe`W| qOjjT*I&ueM$@E 'fNۺbZI rNbױv7,[~gD]#U^t"Îv",vl dnum4xO9g.B=c0rHgr)7TՍzPtۏ6q샦&NGT֦ML=ϵ(f|*Ӥΰ$zWPk5UQ:9vvYb,(B̬Ip?슬?~>:M&<9wZdQQCxNh {c:GՇ-[9iF dO؈F09K6) BU.iN−|185VhmbH:,Ņ͇LxMNʆk@K؆~cP`7+Ym2*{޳4vl{ed:sˢM3(o6JK6uH7B"Fnxk쁃$k§Ys!4l>:P[9k`4nԊ~4J>[iV17&+gIi抳38*tt]5Uΰ$i.9h!!E:yvıcp($2ڄ(*$^A#56ÒοcwƟFGFp b.mRd2ux4J|j ޺IJ&YLZ?]I*9VowD/@QҔH)ܶ' Ih-{cWI[4-v(@~ ]S8q.5=-.dv# r^wc;<3 g-B lZUE|Z,m;܈i$U (f^[+:\s-tE[/i0 dOi,y!=Z F/)2ݩ w6wzomeiITVM]i*io 6dM(,͛5/:]Q3ny<ΐ8 ξw&~ bh2ߺnci=j\_M>c 9GpLMru.x:$x\=}cH71}tH{JFuv,KqoDx Ń@$OT;c&ߴ"->]=6COÞWcKRXmY[G;BR5aq}#.oZQSM\݌/n8E;?5MV{a*{a$Gߜr]wPbz&N<9ϰf@wϰ9&m%n؉Š +\ L̈́-b? gl%"̟6g1mFKLtaX]?{UPn-{Wa[L[f*?14eu ݫ&<@rFwbx؏_g1LpK24F~Pnw!x}Qgл|mkH8MNz>|;z6d?Eo9)h!-5>HE1$ۿ߭^RHnl:6WWa\.wENp2W=z'*M:òkPwt\3DAsǝw@r25ln 4&hK1zgXf2jT /n30m:d0k |򫦿@^G]"ґB =k/?|(rKJgNA|.C&onhn^"֫Ǚ}k0nzȯM ]&2j73@BT.[=U#mjHp6zXt_vTN-Ov.=s;LWD$N|ܴ^o}3 y|Gx֍';O33םqM&e&Hdlk%s?oAsbEkZ_m`)?z>ق3VA^v|/ZWusC{C΍=MR?| mYb 5*5]@TrۗN{#M(HWoV${t/A OC?=DUp$ݻTq.=ިKW QGF H6|OH˫ xPv*eotd ףK;c5Uں=k1F/~֚kxq8c1~X#꫿zz1Lz }}э>)GFr_MqڋcM{,KA2E:܀ݛf[w}l(+1Çǰ fߢҧcƍظqEK{z&ovlY]v wF{M0fHx*Z4lz6S3jZ޸FM О:mb66s,ɝ9T$Wq K>2]o-yi +ٚVDcۇ ȣcXhعg7[b$b{G{Tzu7AhA7P|95~vM x~Bwd;Uď{CdX|RaR1Ye0lhID,=wF3DSS35%KrK\WQzmuMCŸ4l ֞>7־тy$VYƶqyxë|*{jXiX`ĤJѣv|¿#-ŢRӺhj4m|<9j)Bj4s5e?j#~?cڪ۩|݇?ϚD_zv) 3>nIʑ߼8F^AG\G+(\njZSA@pmGgo$3䗱,4Y)-]j\gŹi'gKo+7`#[I%FI}[-mLV}|83g`a8߳L; UDzLϜIS|xE=<^-8X1m Ϗˏ}v w^AV1y |2V1ZoD830lmj PdG!H}z Q +?#O{wi=0tnG9Fz_.MV܆_{v^MRy{1NWPu|+P915V^sRϗQueI py"` PYIZ=qC}嵄!<#̝<* .MdU TFL3QSP~_W}(8 @pXhsl Zlirۻ֎Iń4kMFzZ(M׿;[]N=U_ǼηswW 3Mg ;H>cS2YoBO~-дF6b٧2/M)c7ѫaIe#"#tТtuLzmA$#w)LG/R4m!S~nE@DyueNQ1Shk%ae&قge{jG[Ljt\9 dƣ"eao TW z<"L6sMQq]9  7ZBsƑl(~jՇ:^,z[a&:t7VQS|~"/ĔϨht6e1g\;>3aH0z 5,()YDrȠI-]]G6QWj kIYY|sFؖ0lލ&_+=p\u6ʗX֡X>h7.B1bjtɈ5lM9ClL hb%)>F7I5Krn>2rFݻw 7On1~;Xm"шUSIP~xoS"z#^۶ŒLSd!7 -U_eދ;cS1d$+V9+m43MǶ "Opt6#дU~(_uQ} ê~zlڵÔ)S單nϏViԪ‚L'"=!E(qSy83qP(^q1A: mNe658X|O7?F44iZ83)= (&Ѳ1Х,ϤӾ~-Kh,V DFU *ПP3q"V+›qN\V*#8AeZ j.r$!1U#;|Bl8)_5/.ӓ(Omn7!MVT/<:7|?SaЫ>>I?1]_3-|Zo6U(A|@>zg!%ׂ   EeC5u??uhߡ]VϱB F yp+A @49i~Z\J.9A@A@A@t. /ax}owZ%:vUO&IP87x̘[qs%A@A@A@A\VDCqPA@A@A@A@AFHZA@A@A@A@ABhA@A@A@A@jm5KA@A@A@A@ BXSA@A@A@A@B /A@A@A@A@*DVvMLLė_~YaY=DDDTOXA@A@A@A@.:jh;y$-Zt>eSNBr"55Y(-+eN w7U'/%%%زWqeV*'NQezvF _l;Eh׶n+|/D@A@(2ZPRRJ@^^.`bI?7V6X^T (\YV檄, Dba@Ie]GK)X<}(Oʋd4u*Q#ysl'.΋rN QaЕɲNyghr nX={CQqQ-h PY%J/ڵ.ݵG>Bҩ52@z!%%Z)%"v)%+q QK_vߊUbCwV!A@ArC@1D z @mnNH rZaQY1(28R&ڈ0SDE8.Lщ+,,o!9*ť,X4PRıX ua26"HŒ$ >1*θlSL:g} 5E ic+ !~t OO*q1oꛍ?o?g˂, X .vhrVDw0A@`0Q~:9 Ϗ*d'̖l$(|댺yx! gWDVw;*qJI .^![GD@A@` *~ gLX\FɸO˕*ƀ0DN=৸% bͥD)IE?.@cc5M 5PvKtfJ(>3itTDnYFrjzf(N)G'(-Ҷ59ÂMMYqة(p|)Psdcۍ()Hs }q5иI}:*:F98AԪl"l:zijuQ_SJ#Oe+svl޲3H0;W+^UKC n>hH rսኯpm+(fI7 R"c]@q?t,1friˋ?Ĝ 54*`2D$馑ItDjz'tL:R 21G?ʌ'ڭ͘l+A91!cKJQ$M?Mw")?Eq#-l?&4Y=.fܔ9Y1fґ.tBscaĝ?&[ΟlFuQa A@hg%ߣ|=زmq[~e[sVvqXr#\0ծ;o<-_\ WeU<5.yZ;$ka"K[{L#"-kL©2J{a2X?ƃEDTO +#]eLT)8Ci>V4u8FX#-ZNcBNcMM5e= 7Whtk:J}QolFe0[FX kq P{] g ?9^XxwQtQgK6#L Pw/_GD75yȉ  p!Vl%%Ŵh>rOa.hULO-:bpILR[DC?E)- s'y&h!M+o[Zy#)6J#ʍ-rLU5K1Si3٥c(#AcZYkd ?E)ʧ*{J?bf]Y+iG#(,*Txlr|=l89qqe/nhA@8+^2kđ  P`%fİTQoooFm(**˕ԲPl}&b31$R>d-ƻra7M'Z7KpnV J պj..ǥ%Zm.lƖn4Ǔ3&lq23OR*W*T3"ȟu_&r4vw3erstҍ'*MlUDsN&w,4&N/{m shTdCS1܈!$?Pg2R]m\~m'M 3(vrFҴJWZi/CU@^ sS/X7\QQZv9tƒv!55ՇcmDNYtM dbʉSjHzlb VKq7flB!ZRc>c?NGWfSA@A@.y r3P h>G#NA@0lyI I?Jh*ۇJi0JJkGWfZwe"B(2K'PƛpD\ m&X.H6KIYUwOwnL (2ޘ@A82\#r5-\7x{!Qh2d;q*i)IhB&e;D Gd2!Gt\(5q7 wEЕF l+GUHFi2IB;YVBm%ͅ64`5&FfK7[1!GBT6]\ɏ3HFnLĿ*"0VZLVB?K֑6@ţ9ڇ76Qyz4jcƐ'aO I0MxKVOɤd4 \ؿ ذ4ybcm64Z!BϥM0=CEcb%┘VGV6.H(x6y+/HB" a-@_ ‚BZ2wbюdF=|I4Jz\hMbb;S鼌 @@s?"232(V+ y`M10IҔu<m)njjpZ5Gq(iL)'e;%%4)hݲ];/huEr}:m)Ւ=!z!50γ<{F3[N_}$qI#4d)mhKKK)ҋlۅB²-RGq._ۺoi>?$[Ƕ$=|u;$I`&v9{DBUM5uY3㿂s&S9U#]ol 7Q op۷(m_yzqI |*7֢|\- M\4x.Za F@#/5Wo3.|+X\- Kj0@ \1DueXRקʪJ9ƠLu".ǭ޴0~˪4d>PTq|9zu[BҩȱSYmu &Yv-ȴjELb?iI ',r4Tblh oqB3dR X&SGFj*ʥ'LB! c ,N(IA楸ΝX֥|ͪ| Te3 @QGsQjԨ#FeH5.*g6cl޸]Am]drOC\fKTE&S4p)*XBz59bFݖL*u.95۲VZE@dؗi@:F<g?{' c6pb @ډ"b| m,+'ă:PI3 \K:]F@#XFT_#wyp[Fv9 V|%IgafEjHpdT ֋u&Z8v D]xlڰ 7J|rRZzĄ"-|m'Nɏ|[%~xL(BDH~;IWjfKd`9S c/u>̅pD2hF9Yʫj6R.M SOz'd6ɎZtex'Rf:y_yX^~K&_ԭ_*j9#yfX"~Mvog"$ãh0lLߝ$4oerM77WKZi c|NS/{6îZw͛Ϋjŋ{C J^ N~g֤F@#LE w~BnS[ʂIPР!́@v'c9rG'QJ,̺E~ZR \W8pS|T٠sct,$cc8Q4٤ $d$[!IPK!b)Y,<'LJ}(Y}@V,62s25I&x4 ʆ@Ё6j)E 'Fx b5$'rT1,3Hwļ%9xoseJz*K,fW\'k02*ȉ@ߴ$qi2i>A$&goBTU-?(cv_#I9:ԙˑ[8VFsXI f4Fխđ8-Ͻ !U~lo*N^{q/J`rj;3mz5ӑ<.D) ǚ6q6P &{ln+Ȱk\s٨klZzq'S#3C<_{X}ܬwE[dK]w) h2l<r̖cvun`^=9Y^jLF} ȷ?af_˖m7_wL5ʕ/OWN[wG۩쨬|kU54lxxpH{ nw|x'L#R[[ր|_ \QwG۠y@NLN˜ۑH(RB>;pllw/y|p.Kk4t46"`A 9Ȣ^p=n[l$qϧ8*bP#JChŏoλ(He16oPP8P+e48WWK2(nNSkq +8[0!# QIk+8 "骄ήC)aTso-A*QfR2d18cTo6[n08탪ME)!ɓAYPhFTkd8`Fͳ'ʧᓲaf+[6]1K1{[S Hc-Ok)yQEvpCx Y}TQCׁ:( [V;%ĹK%WOH7I#Ko'2e"0 #ʶ}PvA1%U5˩_ )6p,ԽEZ+Wx^l|\Qi|9z.p6GPxֶ-krl|L>-r֛fK}^Za>8|?gik|MCVZ᫇_rej[}@yyli ¹yѰ]E9*dTQg !pG쯿0k+;&csfx6-_2^)=HxH>*FTGZ!c| ^|( O$<HT:qɵPՌ[fd}r:攫h6WkgF6$b2P^9̥$,21I`OrJ/6_ywØcd&6eLo_{񩥱:_Q㟏oȈA wV̲mKY߶Ir{I,\0).^՗7|Sԝ+!_=Um<,2W _D*YV_h6x]~s9z׷Q/ɶY#|YZ-υ|N|m}4aށ&@ `k̺ hJҎoU} $8 @WŹ`a1aQJu6>`fՄ("@+9&a:V/$.&22\Oz]Y:#[KuWɁai\f1yc:ҽOv^AiQCZ;[!rfQO^yV@Ncn3q;3myv0\sYe$s*Y4BG^z8;:6sG66oʮ[vYr '0;R^4[*lxWO7'*<'h^ Yzgݚ{o}a<[8$o_O[)Cw7/dTx٠p0I6W7 Pia8r*Ǟ4^W{j\V~oƮ{i=<1p#$[8h$.!<ܮҊr Sw^`a1m$?%JaI A rl%+-)D4SS7$**0z H:{BdQ$`F!1lVGlORp~'+ LQ# >ز@eɠb N^R65@gaL9Ab2p"XR|]+3Á1nŶ20QX9ƒpAոk~ [)N :kW&g$͎/k,VS.]Cc$X^dO݃>dR`m.$ {6GLl7>#ymlgY>:i:߆gO|zJwݤZn9Mb\WJDu}EX\q"96ddS'Gs+u" DZ<#yydע3|RX^=8UN Iۚ~!i7.%#B%=J*Φ\"tzam7ӃI) 5{n)+?=ϗ%Jd\^, \Rez>qT@EV/+KN>sėȁo NuK=z*My!_;Æ[ ߑ$yr؋b-Ur}.w/lcZ)_^Y~'MGNa[6lؤ([$+.)IN ěYvj1B r@RffY$L81U[MO&.V(2H Q3ONj3N2`G+b† `( XA'l"G*6m'}U;6- ?m ՒuEm$J' ҳʮ-˄hknj{@~\c4m_("M6s#__)5e֛&o.XBD[TN()#26ǎU\/\3|csLɕd?(v6Aƃh*ų_.f.ٲ룲6>Itwo*Z3tEŋ7S? H8y)O9Nn'KܛO\;Y^ av#S\O~ &Ey<0="U{~?#(4Vy|;?X~\Œ7sMwFlKfbVf]',8@PQT?׈I<|InrĘ0cRҼ›򑑻su%LqŸo/ReuT\߸WֵS׬n~Hty _ɇSl+! _H_0 `~(}d2ND&`Ul4#F2WtH&ijj)ވq,ZuD1Cf?2;C0 pÝw2=$>T\p-J7c X gv%H7+8R!& >uPQyڄ53`H6[Tdr-/rNG':$مO 5i$cYj Ono[P//FFI6Hth%3!( =>G2 Ĝʜ (qAY@MF&HzD-ѕ G &sK% ,5v$28|إYl:e$ަ2:"ǐف}\Q*#?K"i, *43'wʂ2#0ac2p|ƙ F'hj3BoL,ʗZfA7}IlHvL.?=*4KeEd|D-Gcr sXPR]ou~jI(峭:3OXH]6r%Q\7#}7XY9 [ʓlkG6}Qq;Gqe3|nvj) K.3s~umN(̈́ovߚD5NtLJ'GU{:!\za$۞wwʽts\pl?@]Myaܮy/F4T,n/}#v00gGC;07:̈́"ب`%`i\g}e~J8euޙ "=WhX^E/2)9~F\~K3Mr4MQT|%D4lqVM YHNQ+l⣲b#M3e6kZ܎ wI} CN<`JY?Ζd4BUd&,kpQK+$җ04HJWvyKDeC/لFoQ0I'\X0dMJ)vŠC_(NOf{USYеis{.q;rOV!]\( W߾k|쭆P7hag"q߸&?#ϞNF@#P*4V*$u=Fd!immUf݈ںz2vG $Zq6,SJJY dOJ< ReZEyRuc8 J(@2B#ԖˉU=W+Vɀ@eAdKt3 =Z#H+H3+iI C0 _m~PAx0d 8ivTrY$᧭LQan$')G8nmPYAeЎPp V 6+ ?N(P) Du*Bhr?l/DF9+ӯx[dcȄ8pp~bB-rC[QIi[.47kMDZ@C2MDh| G)-ߣH6GLfꗵu[$%%#|N䇯H6l "7>"?n?T%|L!gk$|nrj$$7v3]kߡH66?jm.}?&pKJ?y~iӽҘ&b:"@ߝtD Ok A`ڷ^4݉g-{gH;<!mmjZo^!5E|mߴypj:zvRfr[?p4A/ JRyְ>۰~q(Ӧ~P rs5wZ{|&zn*͎s"Tv_tⱨ*h4s@`Ǖ#6":F!`*и'}_A"P6;8x,{R;]xCJƲf(_!HS4 Bgt>Z%UZQ* %<=@IDAT(ᗺ ;F`ة|K\FMeK`p(4}9x  H|)E6SQ>Aa'5*u[ L$ed+F @:`b0jq(ʁ IGevTdoƹ63LF dӌ3YN3#ڼJ3 TSʬʽ8| ԏsh Jֺ~g8| V bKzGhWܘk{[}p PwUM@II )D.eŎneH>{qSVqj}"g_ew=WSj\|Gj*lUS~QE@ѧEnG2 y;8uN7M ;yW[~!]U?*Z3{N^ D"jt.W֫&ſ4S^f[(J%Rce1qR'F #!i2(U%kk/?헶?-;3߻5~_{z^(dHEIL<kA;qf<Òܵ=(%[7C7}}>eR\zzehdZe:ܱfDD\YY8Q9i0P6|S7Ӆ,F`VFٱb$̌*Hݤ`EaΎ"0=)ʓ*ex ` NeLIaZX7Tiv샦}rE=]4l(0&MR9!ј)sB]^:I!)O\w= i's).=g/ۈMr jN9\9CTN|\ %xdEUEN(sfA êq'GjV7S&ɖcq6iiDnys՗Skߒ@ 7+2]?o8"˞?~Bظ;\m:F^q`6+Ã"lsGFbJO|] T@7^'>:J RAycG߳+ȶVm9 ;Iy^w3S|%+<#;w3O|f p oca ن/$l5b}<{SvTe00!' LQ~v~eXTE3yeoI}Gw3C &x10}|u-<7.lGD1 *(|`2نa e,]6[ᕱ=F#1(J0"J,T"XD4hJFGU`7"k@Y"b $؍Ϻ GDvEIf~@>adR5Cߒ9t?ȡ[ 6aX<$U-TR  6Ef9$"pbJIF? Aj@?9AsAf%41@ %ބ:`Bw wTkпJӔM_LReI1j)=D 80j)lm%l\6c62xDr&, E谄;0.RE !uzQlu_B[D -k+om|jxErF@#'%I P( ڕOuPߝ^eȹ,3S%/[ \MFI V'K{{ KY~"#GKV]6T-TR3G@T%itPNKKKl\F ,ʏ-eJY@DU6\,PZ]Vjw9afźUBc}^7ʢYp F /mފ\$j pTGAJKB1DBy3i8yf2G'` /βDNKK8Fl,NDȀ?:tI(<ei1f2/і1MozE,m oH嫓F@#D0`&6//Dr ?:-cCߡW4i@ElHr )}2 CNB9BdQ!4rZ+w<K(*9~[i2+FuŸx`0$?E!LJAzl3O'vk)*)F*sPE൮MVhYr GVHz:1I&@ 0SE6T񡃜:i4C?:- ȧ$hR7\+?:i4cOSF@#gpɂ?'Ȁd >هGF:l޲.(2H"̚f WA4ʊ٪h:Süv!I2OLe1 O$( p@eU+fe<k.7F7lX?BK,)FkvE%&<E! d ,3ILQKV;S& LRlNjR8,&2Q9gQ'Aj9'i&`* &CCgHI PQYF Y>f!@}v;nK`|`'o:>ctA)l/ Vj჊AJ@uUCru˔}zC#X:.LxᱹmKxu)k[ ʆS Fpe(M|h$G5@i Cg,<:CPP,oWPV1a*+r$H{KHJu6RDɅQFYt _5ɯ†F`plĈ q3"[らOF|J(2֋q'M>s}6m+BeDvbAGaN+4}Nl8^ $hcAE.&$4Ɇ;@ԩ:sةqE]i| # r}f؎!Y H5)!Rua8D+@ٖ6Ed}T6k6  *6ƣk ΜPerTmFQ,x 6M7:ݳ*w ڢa!V^_n,Q]rB a'CzE#h. * +aM`$ ͭT|~?BpGI5cNQPoRB@y&k"8܍A:6˃O XF:|EkdE}x@%Aby!X:KJq9iI 8YNO: άTy}JL 2 6["3ASI !38T@a͆dL9y"ɨZcyф/C Aϔ6*H@:FR&_FH(l#3¡_q#RE=:-ܒ'zɎkXxF@#pIkL7\=%$~ |Gol[e@lbLz^9e{R7^Fj4ŃMg=SNAqt[/]0Y(2<<yhf26zGȑW|gygyvojVxfq&n\hclH?=ϫTȱTKـͤ7G~_ΫmT9HKH4Lž2%ZCp3T~Q" @sR*Hŗl26IJ, Ƈ&*H-*K{v'6RI0$Ԕ܎DJd q jzYVP9V4!MB/-(%$t:?޼fyJwoX`\vByQ^?uiF#DD?ENўoi_oϊ/)إW爀{o7_/iٲWՒN%$>aq;[ ٜ.{۲Á~~mX_Kk4E@@eddH\! t鑾!9|رCd#r&d#F$LRC*.{y&12A ȿXvN ~/= ,8 b%!s#hfpIDyṘg.Jm8QF)2+5s\ҊiKFP}ĕ~ڠV 0* (6O@ $Z3BÌU&FE<4CA}t17TuUg'}2 3Hʱ.|d90D"a9bC'26y!`GW8r9'eWZх5R#gFw A_`.kv)RR/˴w?t E[.c6}95ծ*5-U]FƉA<SYx1wRKk4EB Er_i5UU|ɉ'F75. B{c~wOˆf$|> osLG@VH1sR,'H ߵ!b<'"*+C 44>4܀8+SI ^$:(bDLp!@70CM0in)p6hDee`\N8)N~ppB /e(uuLPd$i&I:;qbYf~XOqX']^LHxc6?Tl~Ȧ2" qb(@3 Ru(l_G`E}/ O![5h4 |24i 9%krw!]|Cuu'qDZs#}]ٻAeHe\b'V<18QLJ 4.@+$z&"3POpRqdu }ؗB~bTۡ?>:7M+G+=H^v 4 Ulvymw)x),qЊҠKe^kwn\Án&::}k ז 2Yn ?=>iiZ!&ܸfE9uI#h憀I*Nx5>e$ b'0PQ0CFDFWVcRYFN*;\dbr)ǍnCٌS px$\Sf9'Lg^Sr,L jo!Bx ٺ;$b>;PŤZyCs<$To[U DHI>ϒ ՌE"|# EOFE0X@!E2Ɏ ?gd"I*e$#Crl x!d  OQ~p"8Nq.=>x#C *p4)+/S*suI8eȧTn@:QxpRc4U3ʩJ)]oe9qH08T%jBW)/Ͳm,QS1~I v{Z b7zJe;$}sSkC,? _5/޶WnZU7uh4<2m"rܘ%hi 6| oU^ERP520Ї` Y۶(]fPd@dD2<뫩Q$Hґsf]jQC~،fxߊO$Ҹ%6’ )Q-* Ϝq46(;>C GbμO<$&#^~\DBmךIȷaj\LX}]R:REU9J)cAΥ$/ 𧤿 @N aieCQjd#E s2 \P'i VRB͸Hpjh$UgQHS4>>R d"^QiI[FsN}YU'_!? Z}E To4'Eyׯ`IwjrHG)i&С0MM9'E#hW uh4r@`5ۗ04%F"~O a`DexxPi]ܚS[*jm H,؂V ''%-LJ9FHJ1e3Aۆ=h$/tB2`Ψj#4d2#38QLxyU h#y Q:/eI_lX$I|AQAY"uD:#肝3/`CQ:MCiG*Џ1HMcID+Jnj,oy,$ٸP7D\g8ueKcuLj QUE 뷁ʂihlVnts-iVӋlܴД:_gb8VR2> w!'4X(Nt&l @*/^6BI" @qb3g+V6v(TP4jȁ6p륉i"gBp8@GGjacNȫ?? ~gA8I5Hq|c+IGth4  :i4F`9 ƚ͚hˣW.wb$TT!R Yg>e'7HCCճ?I"*bPXy $O* ?^RG CpZiqiU&Tx>}|:L$ r&zy)"OAu$ `)8eJ\(XQ:Kg'dttT-&Mm-2)-i6KW]i^ HPCv6(7KJѹ0@'M>X-RU8u<D Li8f\4p2FK#OR`& 'qIUrD%ŝvgb'VY] AeaZjaCU9M`pmƐĿ CLT4F)C'F@#h4<?6PJ3dpecH֐uwaG$ژzzz`-r1xjA1 +F5Hc@%9?<s-bN%'Bc$ڊd+޻gF@#XNވp\|F@#h4rE i|< $xZ[(CxO@ZB..A2h`tXjs GN;vI)-^Ri#Jd2_"H)2 c$xemc[V$WcW&AM#L@aT 8uT2b gn#Fq|`j_cH̑$c?Zfs pE4SF(ik睼9^ַXSI6uK_F@#XB?fͷ^j4F@#,/` O)F8܏im A)UJr* ʪ*fDWʲD"8 {p?S^ "dzs5!}Z0`YH20ӕk@8gϹKB555ɯ_~4F@#07pQ}z]#h4F`!`'AC8+ ׎mġ'9pټ?BV"WC9*ΜP0&۷m1D(}♟h׭C0Bf<2a^~RlaGe?4ub 7R9SL"\lHh!Qa.fF&5@X4쨩jl/S@bY}Ƃ2:>~Q|TA-strQ%9ï>uRdLxp^RTG%9/weAe4)i> <[uHY}t-%n^#h4D@)pǹ`^h4F@#XrHK1dɞTAG)]vJ8FW^`e8x8K[7N}[ʼ jm \lzUw¿='(lQQ*$̊-hdZV2uuZ`zKEMHI WNndxX`R Bh`50դ_7q4ȧ8H,U:`^i&Wgs_%VsX@3ZgLBa`nDO DT* ʾ EnUUWK+Rݏ&1vr|=3gN)k$ZZ*men0/m<^v0tph@1VI08.8}PZJB}s'N,-.}K_Z:=h4Kh'o3GƔs|>CIntd?MK@"wa5?W.&аBh _ Md?Ł^gqQA0GlFIC E4Q\Zn˭p7 P?@}.Ԣ0zF#ʬj2KnPx X0/%鄾x<|Kg*O$=ycܦ57=,"TIʑL@IH:@1hB!U|T% 18u60 qhAlS"wpA<&B$h<~G\eeG` 8Tl$l-TA)qc !W< B-ɯ>I_~y}. +}^ht2CO>9(؉o@k _ni>Neߋ /hJ#]}7ɖMm%\rתl4)EzWxP8EjbekrYXm˂ Oit R$,ȣ<>qUV\(  BkQ>2 vd)[$h ֕`7b07U*1O9ެ)L#)Rue@}z 2ĉm2Of:?1c?`b\ƀUcoajc`.J.#:fшm xB ԶjM'aqp#ٶSI6sm_E%r9dOgA%mdZ+ΨK,H6`i"OfQ,"mV0T 1OsZNAkG-G&\O Qqd>p$q ¾Ujg FzOu#ر㢶{1Lȳ/os|73I3 !*J3gG]uj%$sm'yc ';$;,4X$*7 Q(A7@enY>z7|`މg4H&|| \*ߊV9I&ˈ~ٚ໭\GayF|?ý,M!SɆ`4OQH)kV.5JH[22o"џаtvH6]gK$a>yf8_T)m؞hҚVf'qU0-.HؘT5g32,)FvlcFj:do 2Z,DՂ|@ǁl6"ڦs&p?4II2a34Y&ˇʼnW. g^Li c8A H:+=+2(d,b)3裏͛/DzQCbʊA\0Hs!#ߔw>.XR=~ Їr7 t/O4 = ˧l+v$>'ǎ+EueIj \V]PHq;.y%1DT#CPU[ 8\ՊaL*hX_jxWa&U&VKGIB洺`2I_oA4SLǔ[#9$]#C#$P)/T`.;HyU2!$LN SYA) %vHv.crq.7c$Bb _v*##*qv""]FGFU^0X>~[x<^%vz 7H/~7协~1Sڊ@,%NmL}I aDސbqδ$ D's sǝ73-guXMC2N)4:JMXLE 3OKy&KZ68 +FDa}6H9 44f/L7XgU*5V.eeUIzXCuc uf BEV12헰k.NdZض&`qh+Ad?( :P8 aXk_6!Op@$1A#IE$TDryk3egnf>|)TPdpZ &)Llf)}}PAI'H8{ϜnٶmR!NBSu$wBo`h*qm3}_kY:{ aMXdDqe88:"2(*ʪh@ a_BBKzߗVJ4I'4P:U;Ww*:TrMq9JBy(4ˁ/d&x޶Tl#t^Y1^mٗ@ڭǭΙ4ƒj% LrTBot9vK@O kDu)&*1 ʩSz2JgMtb7ٜR&dHӆա\ S_''b') %T摡aU[d!ӡ5Vqvg:]u=]yomSI뭷9kq.4*X^pe ;y8 (\ |=%5ă4@IDATP`:ޗ+c$?s~D _bͮ~V5Ԓplzz< d$X jdGlBIJ"a`D2wJ-w#dhLW}JGE`H?oLD]S%XT侪]]f\;sH:qr;FaThπ˷ond 3rPo>B:%]CCۿ5f+Nc?d)IKtmśxb x A LN8SN T睇WWC,h^ȉh|WaNI,40ٟ3o_9s'_m|;~>KDK$9>q?4Hl4l3[UU{.F2km:@a8Cv5׼VM8ѧpy,bsg[GQo~xEP=6 Z3 To %K@jG?qĺl]_){띈IDeG ML;1\Ynd7轶W gWo=~=o]oɾN-hA:ykj\D^N@(Wʰ[Z0lAҸGGr-)5-?r>m_F3 $M \Μ*CAt<23ԭNx(@nlJGGމ?wFf-_Am%N@yNZwk EZrSE_)r+[ njq][{R)ٯܮ]qrëDVXag> ^í+rQ/q -0) %g̰j IN2$I"wѸͳF5n[@׍=n#e%%ŋ;Wc}\IJA ֞HBrA+ K`^Μ 5W6XIi 4 _@FݸGVI\n"mH=<(櫇~.\ Щ~crCZ8еk~wBm}w({l~/7}CcOusu[/q -,H@HttyS_`d8< 8f,?ʦV}h/?-(3; !M9qf0PN^ ¼}ff_hdƜ;{.[`EkhwiJy(Zfvd#l`(ă,Ve]- E]ŬȺjy(-hndF[?72Snsm`jvB@YT^JP Mtt0edCP}(F[]]%N˓lrol|{k]Ғ2 h(lU;^M/<~gA~c8ĻlοlQXֆqKU7'*Ͼ_J 0 X 0K ־\L , ;X's WAmP/bEk\z@nv<&EM,d@A )oadb};zV=ZܫK0aq1" ͛\D6sLKҙ1 l (H#vϬaN v'+jNNAp5yQl ٯiQb袋i 'nVk[37ю/-^[k]hӵknn׏7h{9BD}&(p6 O NJ*kh~^HQI#VHED9r1(޲?dLFKO d̥$)Qk%!bЍ{% `)b@aBc-;8`YSɅTJ{H8o~[fvq}W?uDfdn%A${p`Qm2NqBAh@I Q˥p ù>;g.@0^~y#|۹Ѻz:]_|H(>+DK D99i.mye |˴m;wr)K[X>ۉ Sq WFPCiKXxDQjW,;=%pOEMb뭧bm2OOL)hs~*VTbĂlZ8>dy>.|0 ,h}Ou @1TBcgQQCUy;VoT+\J/b⹐Zp$0M'F|Q@Կ9-9fs!{ #V\n32Vo\^^?ʆ3fLMLcqtRKC#nb,05>%-)5f>j1RKQ2w7q -0?%a*ʿl˶Vnz?~6|+ce9O-4\_1房[UY`3zUMa*œmʞ`vj9/+vzCc'[UW-J>+ nid:gR77eˎ]ol iJa 9s2rc{;}n#@2? {+BP3!I$g!2(KR81_0G`xsCr@qRzOA}C@CfɲSO] m&˟2JyَJJJ:Nx:Ӱzxڿ@caa> ˨#ߖ,]bXuj@;?S\}{:Čb: on,Vj>{&!M*= <&Aj]ƾR Go?\ay4p'7 tZ$dAHͷg= gt&^\ީax:mmh*6NE|%S!q c8A Snu N$1B[49z`iZt^ts[i on[ckp$rl~)N?<]wuSXkx3Zk.w'ugzA!ۤ*@q L`z{Vۣȃ% $3 󳬧6t.۶ۈ-ItRۼy{*WVFW^!95V ^!ՐUI.X+(C6H2U ",TG#rFDA#s@֜UeUUbΊy *4>%]]5M,|IUб~ AѦhI)( Q%ks.^rmzM3L K'qBA^%nMfg4&Z$6klh@tہɽWj_[ n)G[tiԽpʫBAbcK^Pu(yfU37$YAؾe;`ʦM.n[ <s헇TrXKjS@$C(R}CoCG(u22ӭu! N1+.Jvtry N>bA1Tt.z>2 +/˰bŵw>#W)mbqd@A7dgjs5.7$?郆Z6BFStabv/Ds=ȧȿrڷ gi)<`>2ЁRWG/ͲA-"C?Nn_9 ͺqGZj9 ' t:ģGPI¡yE~x"*J`wA{_[ n׳ȏ^4ĮGzI*}vCV_!n8&j`޽{G( 'xcU>-4ƒ顇z~QD CBU^imϒQt%Asc/m ( Օs'ۜg@=J<\3ՃZؖ#==ӹI=t+^[ckf27Ö4R@Rr Ceoi0nvہ`CVR\% >"WvfIҀQ`;Ý4G/$k&N R)&DEjTjIɰ W-e=U4mmm#h;9HP:vݤ\þ:ĸUi!Ms#CmA^0%$`*qqn߱U[*}sb,I0dS_R2bg =`'{ľWߌ,h d{*A͞;%b}Rl,([OuJA0f&%680'4[N0d'vY| PPH \4r$$![Xč؎=i#th_'Y.m ),tD|2< d!^QNOiF wgwP.C'+uŖx@ QZzjhrQ6+'n; -zpꁛ wIΟ?ߞy.kڅ^8+-@GK /9v=7og_v45kּj-@XP6Mj}L@X@a-<2.I555{_bUTTLT.LT 'J>JK ixPy-&n1?\.u&X$qje~C&hp Tiw-T+u[ /$& DdrKu}. :ɖZH\z++"4UK.@uww R)aVv.@d8򙳀HRD ǢduܪŖ HZ.YWj<[q 0-S$ (EŨljlL̙(WF- .1R|w "{xgΘG{brU] Ń_ˌ}ì[j)HҀ^ͽ^ 4[SWdi=j0!H~@JrZZ`r!B$T;/t>:5icuP-l',ʰ@v V|9GEyxcA|~M4BG.%%=Y;b# lVmmXGFK!Semq3llWN2hZm&K p!'ʹ 5V[[2f (+t4Q Ec (1BRx[ n}k]7`^DKq -p@%f;e[`*, xEEDP+;%*hm!k&;Q_6 ^2Rbxn-mNqDL'X`U7EHq%8չsnүp Kv "T@!֭(v%R).2BR<m*S8%`p^2ӖírڐDl8%_ )01늋KPR-4Su(\$ i$) OnrP2LqRl%!u#dfJ݋'N M6൓UN@/ӹJWzYeMOzv5A;Giv( kQ,f,Cp)J)_'kj߷ŝ&wP}{JmZ"Hxk #, :a!NNj$];wۼӖ.^Hܚy2m9S[l4䑩(ۺ@݃j9$_N>}> 8$uqUJ7e B@̀fI'&AZ I; OHgYimQJΊ Wc3s-ŏT?Lb ҆6{V%{@TũNe.YYΧw|ө-@etmjTmr=V:Bz 7x|Ӽ?u]=MY\V(De ms책k޺Μd;}84Qղ+,g?RQlɜkWۉE3zS.[ms2OoΛfHhفk-8>wb/Ϫhw[ۧY-v*, PͦM\uOvgLEszmwH0Xl2mqb{Y8I!JhrĢXlEe˜*TT+nȅ+A"xC 3TXKT(ƤRFO9kGUe⢙˥\4+fVt҉ Rs s (2fShKmߏB8%p.:PDKMC f@SfzE ZJQ%]50po  ᐟXsy9ԙMl&OB(!N]+7"[j>iApUZCijs*W^^> ȸlk%&.e.zGK.ay6p2öW ŋܹԞzh>roA]!arvAPΉ ~k'iJ Mz֡z ?Թ-ZSSgmrTTh#]ԁ45)˶Vؖt&   I|*5_@GHLXv9K!Ö`s* ,mi9'.zodLCzHLmްV`dHM"iB.Z{g)j;>|K%\G; n(# f=֬Y3bٶN$q˛ ;km{۶t;Zit~=co VYF{𩻭SwǃӬn˛XQ >&]\4SR%EPrEoNp]iP>|-aof-9H2Ot7? kvhkN,Ůzr[p ]Jb @`ל[F~C!=xꙗm9Ly>&FS|3vI#E9KV jWÎ9i731Pmم/O+_1{Wl7|-z.oxж'vٕj$yn/ntF@C5$L4mWy-A7 c\f͚懓m!E//6>jU#2:&T6`d~\$n$/D`3[qqGHX0H`| 2a*\R.eeY>J.^W2rT>D8N~ i䊙NdtWWގ$r¡,qr+MN@F<9Dcbc:kbNs墚RS ,݃",[m~a^vR2oIԳkbu8ݍj :mm+*f+)).N5v)2j)5ݦ;^.KE{e_J/$Bes#fvlnX&0K$JCڗ\sKU窷[F0O*;?\WIA_8>ԎJڰk[t-\xlv jxwmMh c`&f3dV|Xc>,~mjʼnHZm2Ȝ3ܲfH2qV's !2Z_)$KP쵞ȁ" ct2 )fiC2:md5G<  ?IJN.\M,`P!BF{?N%FP Kf%L7Vy'\64R*7ڦukƽ_m<޶mB[mV<,7|;}b18WagqP-mܑ?N-Nv~MG{/hCz0M@DQEqQ.u&M=j͐I-ģ7S!܉!3 EtxH vQIa5V_Zéia|Ĩ6JH7ٽ5v1PfoAuI6hn/ 3GOP{=Nk!\˂ŶtNH̷wü\k(T{I+F(9pѣxoFr_;Pф9a|އ<[Gܯl?Ń. h;;)O?ă>h^{T5msP؈2D\~L싊ZZI<00,VࡧdSHib ׼Jgg?F"1)KK$9EZj86)(Y$ڻeK5qĩG!q*!+.fƅrT~,ʍUPfX2y'҃xFSI<ELIT IHR,4xbe쬝rJ%(xWTTH{ϊqלDrCu׃zncTOCQ\AT7ZZ kv]33+v<innmx\p@X?*t!{DjC:J@eMaXevrh΋K&̙Rܹc h' +9.hmq%d؇t2[@FBKh!E>~\> bWgmv"hcum߲PYO6uuKs-39 *`aHS' .Xi!mL'*W;`KpQ .lDm͵\gy4hl‰C%G 鶟A\I1c*^b .`ڵ5ޠ)fP gyO  WVD&ʇўU~µ߯;mm&߿- vC~ؾoY GZ\U:cyz<67?n+m_b_e"ϷU'msGw0v[ZWncP&7h>! w ckts<`;ƪhj~nl![wwߏ$l"ї_9߃ׯ굳W#z5OXz꿶sq^ѠX[O' -G/1zSQ]m}.X6SQl۞={J*)2Lv? N/ÚBxƵ[nQ.\oZ-c8ThAa)4ٖ9=.E0tN /Xn-dlt.mm'S(FDRoO"IfT%eLⵈaM57! {l@0·(=E'>P4D@Lbw Y__'ˁl~ އ Pص7Tn}+D@/\ }e՘[I |xr IQo ͅpiW1ovra V H$od2;zŚwJn=8^I#՟~_FHRMdwHD#!n;!@ݡڠ)+:0N' p.XAzB] z9`'g%e6QCcի%\t=̳da 2dƔ⺅P۠ۛWD`A2{;j7撤 ;_6΋t_d $vp2**)@'A:XwKx /Vxp*VvOn`zw.:փ64d, $y?t; 00J.Y4ȑ^eݺuvǻөDz-L^:n鶢"_a~eon_ \K 6Sʝo?;rQyK>uR+GoC}[oSV/J2Ѻ}Գ%'.\@unՏ^'z}.8@}[P2\-@\fr|{N m4Fچub\piv NtPk3;VYlmMd ;(`Ûv{dYV(0bg{'[F\Kʹwu*ٕ'G_mS 9s\ >3meIp'"*]:uB[P0v>~]V5'[E]'swe{og\j޳gէTݩGz[ ofYb$u=jf_A}ӗ-؃wm?wWd,ln?/m-wSaUO<=:T[=r2UCMRg#-VMrɄ YC݋"0A .u9wрS/IkE׍,C<S_'ʵC!RMwWڌRB! 2I|7JJ;-U. !=#P̅8lBrkM2X7 lCn+G@@]TFwq^޸E[lڷ2]Irug{j]S Tp#,JʣNr FV=`3z, gP 1PBe)‘vI&r8S{ xxcc"2`[QcW"W l[wTuM7Mf=d{DženoBv={Vrrk&Vr+ͷo1>wL"%!V>"u,?=xSоx}FW ܆~; a7=)U笴~3b9]Ąa0ox/xd]q&'+`WsUD終ӪVzl=m 3;Ŏj6WߝDdkmO/ħfndՊ,p zʩ9`g^4XW, u]z۵# Ga̵ irn{*b #_8?_Ώ_q,k+oKNZfK{"r˯@{f+'/þсmS bZnRe3b˭qE <>!d=?w9>{fw0`6@LDq)}qɖ'%̹Pv.2ۉ+#{qon:mm_>쁯_m%}{8)ˊ]!*Wk֏ݥ"ߥ\ei> c=cO]}][9gص˹O<%ShŮa5ȜUlg>icvJX[m|;휋GhK}7 yАm#GEc/zjo){E[csA<3hG=6*p2  ig}ήMC^㎦f ! KE%1SCW)04P M\W\$SDa(5.k䥥M!l\ۈwV R0O>|UG0iؔkz(+e1%)f'&\;~nġ qe:̾33%#]SGW'j:}N}Yʄ q,>!Bņ-$7IB'1r,x;QRZ P?ԁpW⸕!8z&'sŃlztr'ܘbY eU'ػ-A[ rf3<~w ȏ>y}U g#>݊y= ܛ#1@&˝s]xb6V3_w{[~{_ U؎[r莫o6~ .`{Lf6QOwΝɻv:{Oo/}1`wk Of({P!pe͞eeYnmkU=}WmGilTsW;ewnxZ dC9y5rc+4G];B̓[#=AP#hgm-?nFMOIԍK/EPB_l ~b[-;uU`dK\]ao6ن;]Tae2Hwx,f> ٺ[lEaikV/v3k=m+:і]5o#sGdG-I_"Ńlgszl) lϰ?~?–:|3Hf]Umֲ Gs~>1eeY SyzYuoNsGZ /=]|ɀuuvJ:*~uM` BGV~lt{O{&5W 9{5?Pw>_=qͮsNmr~WoJ٢k6m`LCl%;}ukxۏAu5wƀo"a}e]{mWgLlXlum "n=VgWxa;CN TmK]~yI/d |hb-^jۧ?&uXj׷LjݣDl* ${[6{T<32IE(m29 a55֨NevʕD7(:-kJR|}P@Rw1x4^@*nB*<ܤ PܵCV\<é0̡E\n;[NC+si?ނǕUvBo f)9sj6(0ہl!Jy7y͕RJwA SB^h@L@)68o*L\iJjQHAF\WB!DM )O@~=Ė˨>{bZBt:Z_M*sz&[F ٙ@IDAT`P$pYifX! '`rAZKCz۸?i.ȡ9T';M3N`W h^:X Xyl%iJR.IH?+gխ]TP (0j@Vz Hp|cnI*.~ E\0m , C*JR -z2ĞW"]T?ho;^Ò7^Cyq][7j-w; hw'~(dj\oOrVzMv٦ E)t6kNˮlm-UVTy-W,.9/q,To/ǒfl 昑7|ۭƸ)Yo,vԓ͘ DەlvozmK]gE1ѫ0[i]P.?_u?Tu(t,eHG﹏<s1N7+>LL|> oQZnߺQ2q)Ό6?Frg9 {wwd QzJ܉͞O쯣s w> G2Qm½vwMdY[#hPӾ[w:7O,=cMW'=Tg:ʷ.TyǼc]c^7o~"Tu[o΍v&1yΊӻ3Nݡ-0 BVyb}*OU+}}%\}_}$ ]h}o87n\=ށ޼S#;`w1?Y|ݜuP`eȶ@,[@IMBW"‚ (VuMk;Ks! q0'Zm&*;Tfa`Q8L{b}T@K'A 19҈k%c X\G{sXrdjDnBTa,"%5Rg ΥoL+%Plmmwϑ sؔxL@Q*:Sۼ?q&[ۼ:rRyCAH^')uXA;z( CڀbC#7oAF2w #$#IRp5so0lH#x hCjƥ \XdLumͧ>PČ> D+I;N,&RAM;zZ][:P@*' lKP|%$<+  Œ@g&:t.ms˗/?!kN\sDF<&kZZu&d[žhE6/:~ٺI `*lyY[_c~n? ,IXR=~^rOk6|~,+P˟_2Nܔ ߶UԮC9+luh魾Ǿ#:(S;]9ir^k֩8(ŷ_[ΟQ>F[mWo).~muIdr߽? 4i {UxgLk Fzmm@#V[KAeA{!`}V\CBt}M :[ow<_ ܑ&R^P9Awu^316߷mԅ~4$ھf} wB]uj(d6:~iQq6cJgqUi}EN(׾sx|qgCO4Җ:'e{O]{Al2ldw; V^;Riݯ$,ƍiF1__3;bc|̓l:{ݸ0_)치V}9ٴ6u vhN>Ξ}asyz}VّW"9I$+L:BЮG!(Ga{bU쳟7}V҄uwkIg柇˯QSxU[&wjH+ h )HF(@I.grljn`*eTـ#bu2봲2b1䢊{?3fg:I"aa6 Ul-"v6S0̢4a{|!CIJ0zL4>TVLls\=;bxC0pZV ڍ0P0ϩ NlenuڗTz )V[[nG_1 %ЪvDژ%,PRH 9aZ2HzkoSO=fΜ Ms.?ʤ*YE\FR,޻G+lmO0QE`MMק4-9jO'ӎmG?LfC.BTK@{qzZ.>r [hO#a.~:U)U=Oaqd!0=@(_D:H?iH!! _zq.>)ծH02j;QE} $(gOOJ)Pm guÅYS\-t?Q|,H[N~\{ŬmH:޴B6}n'7'~vUۯwGx #Mwv5OGE~ķo>zhr83F?$~Si5QqE꺚WրPeO+y}[zz0z۲XE(fumfA_kg3+Ća?0XdH[ \m]w7(=w11uKll_ꗧ))f-[Z+]Ubj %LUϾ؞zh5gqd?l%IJӖЯ=o݋`/u[VL!鮶?~2VWDo 峢I7z|5/.igivuo/Y3)[FL?ůgjkkG!ъS&`ܜr WH)vPZ Z)SV::{l@ 8Dk){"jb`Q^BU%)*<`}<^n'rs.⼷ي':ՖD?}6qv.9@&dv`YdMֺl*i@&+[jFدJaUI JsW b1FHD .^\#m-i1xrht!%C>bwvǶe%F+A|'VA=@ܐxW=JKKkccZ[` "Te{gC#Śl(me:lZ i^6:me*޶seavvp0m^'ϵڶN9냝\FrE}>9 GZ[/i5YZ쉍DİN. of=nu(C'^Hz{*H=zv91ѕN&oc-N 9 c`mwF$ʮDn3ۤ8B1Eq \nœ`V=-vB6ovSOYw~^}?=5Z[~{28J_yxU^eUUUs/bC?UK󦪺cWV΢f MFhQFas2M6 "/g,ɋLMM~n+*/$+sL~\jsc X;PQXKYVpV>rn}isxuVa.J{;?ztzm owf\,CFᠷ0A\J:S㼉`?cHWƟ\Drve-`{[~h$R6yXy鉣}g ftr͋Nkˎag]̧ɿZZ1΁:cu<`YyK_L͙]fs=g}RLV$$@󄙢Fz (8_4/E3h5{ZJD h@Aҹs!NZhRz> $(I@71Hl0">Y C{D@p,@R$-T iUwseQ9vRf!8H %:e G庻"5 \VUC)9JȨ oKƐN&r ,sNUtŶn>3P)^U&lzV$@Y.±(F]Ft#Z?A|}.f\ ,G-{a t)XmN6\k(+]iV]2 r)ɥ^S ! $V:%)]TSC.-#%hjpII#tTsQ6 :@Wϟo 2w|뎸WmGl *Нi.^x}yM_ +NLGk+G(S18N&}2󦻇Z3{t8N3Ĭx{,DJri=H"})~VN\~=Sn{OԀLTT,byeѢEVIHxG0J xB:ڣm6o&Csf`%靓_#q˾sYFgѸVk&Ӌ1DEw>Vg'upxr5r&g_D±;^`Q_6;o78un'eN똕xBN|:~;v s˭:GWS[-LIҀJOGtP ^Kj@9G_\#pd%bNߑʹ @g;)_p"W̓j<>-ȆɳV pHee· DgӉNG84 .v"YD)x?,!"zeMsAt#?NNHOHpfL&CaeR e *(+Dfqfق9KGG]R0>kk\'tvꢑ$LI[00W2bUQ瓚-^ތxޞjYD.9\Nѧ 6f\o'F!P6{tezׄ. pvy}ϿXz1R4xEӬSГ-WBd_w,Ǡ wfj.O|Nu.9vCYvQ论IV⁹5F({蚨-׋ʐ|/j{c$82As]~œ# (Lek㐦+{sw؎Z KEvN϶F h%מjGX.Z$RٓOlsZ Sbxyq_v1ϗΊ럶}]yAAGƼ9HuBg3 8[m7 xzZpǟm tܔ%np>aG}‡v=j_̜ ׼Q>n@<%]2p+`O~a ~p'\ӳpt<۪7W؅(ڶY\e ׻7pEEEv'A OMm̀  En3gʹݻvXKcU.ɢYP0˹.!Xj#Vn@=RI:Jd1[Q@ u*$H0SP̵tm">ETv?5РvD2(…m,hmd晓1R)Yo@.bib%@RHƐr]Fҋ { >̕}+mJ{e&{ߘ9sVlaᓒ$':|>H$D(SAh[p9(pX/VJf 7oݨ$ѱ(\WKKC,⦅ݙk%Ye[ 6c v!BJ !R.@ Z>m1jV/٩Ύ4╵kf<=s~R P3<)ht+{e ] ii;eTnZNMǕنue?yQo Sy p SXDG EAr7ǀ[;9l0 MTN |DIǤ!R=T@P`o &+IN8U384PF&aPg EtmA3 rX\DܮX;U*/˧?3>/A^QP$%U\;Ǝ~R' NXK){xxhT#Hdklݵ- ;6 v+?ozXnG![S5Gf#)e؍Moz-{#ov-f W݆f uԟ-1?wԖ5q>SI:irq3ӽBQgu \{?_s E(ahOhs |Su걣š{J7-+szA6M?m5sw?#A^6{ f|SQ/RO expc驕O?y%6Ԧ;Gc ]W\/G/˂tt7N] ~ b;=zJ?chTGd>87;ki3op7?#Ígߏ'"|\^<@ n{FY܁)@ڜsC9 Q-E ƉqzPˬ`SOvPMf`OΛ MVWYR<}rئjIj _R8'Ǚ$/] Bȴ p)+,EyV(z=mTBDBLWf&&&`7JݿKJ) z{mL'3q"*H.erq7R>bb&mxl=_>,w{GP{Q^?l{rf?/l&"]򦨏'XvbCdkz#4fzjbTv} d>G_$mrjƀhY|1E0e 07!Nrkk2AJ;dAf"a$ G!A'Gm4ZV`{7Wu7\e\,ʷ (Lo)r 68CDVGkG;$PʰG8Dr$'> ;@d֭s}.ƭf1q?]?K/-yѶgw/$δuT6Vdfq/dG_awf׽(^v;f|\?߲) ,Ͷ#mm ȗ`#?ekn&RzEq6Qc+믿YE,t?Ӧk׼voMT/km_||/?a/L^R-^JsO}kݟ|VP~Լ"]/vb#&mt[}kvgW nxf3Bn>}Hu>f:svg vIv;l?}հ Z]}3k%FתW>;?9N헽K!>2gWHqW>&8*O-f>{ǶƜc{-14هn}h#LWgd}?&>l.v7; l`鿷? d:o{!B3v'?lnB 6^͓.c#dО=kIe >{O>k}˜Ӫ׍/cM/{l_N+7nZo~H%N\_v~sr3KկCq~s>8S۾gپޡsX>_.e3Bu[)8E>]jMi{t񫮺ʚ?/R\@2J1ƦV.}OGi8ΐM@\jD+DӋ"./ M !P 2+hZ)4QbTX.n:(!UdB (9a:~ݵ|a,M/VG7>q>gTQ aDc?h]'ÿ}DY+{/}|Ԑ*ӔnxmeޞgdҏvEs& VR '(ZEd=lELU2:()Flr#-Y@FmB2=?;Q@dىwRlhxĩFITRe0?DTxRcI)(j]#(86J,Ƌ?؊TfJIw0𰨨 xMߍZMF3 C0b@Ba(`R^:A:JlI+ ~֏Ăs4R?Y(JU?jEDU`B VS[DGg1TMjnn[o}o;O)F"UѺ5k6ڵQUݹӶe{&<"޽{l߾dFp? 5vbk`f}e|C&A.IIdK=+j8 1e0ɉlV/~Sk b Pfl{4òO~Tn(#.3=:YpNDZvMmdv~_pN{[qgn1i;O/|~Xo P aձ}OB龜nimHm}[ZW+]i%D`~žxqt,J~Vv*m":mbvko|X~f/}}v̋ځ66|/w] Ǟ'w;_}ݺc7]v߿ էjc[:w/p)gr;?|ߧg?ve*L56ǣc=1V'X?FW߱?omjry@\gV>Cֱyg)ENyUK.ES"7@XFɚu 4Rc-=dQӍDBjzM8wPʩ+PO->WMi"|D=cP *OMMS Le`+i:U3 K\3E(Xls(9d]5z+`U}W?Zq>Ja`srN &JQa3IZ,z@62x#>.g;xBS$W/9|dAXYf^ h%TmA\flݶv*kx}#Zm[p|k_C ^kɕt 'ny b=?2{uv cN\E+(nٯ5vG/FCZlW*#*ݭsۭ j7S]\9&8 B-EP^62s,\RA]~$jݢH5؎#] P5ڞ5H.ɬ_D([nyڭp߾}GS.25Qټ@7_AWF>kg3o=׿c^uvUەvn>V϶mpGvF=x'Z9F62#=FѥSDm_VW-ӑ?=Yf{'̣>~*|>DXZ\bK~;SޛK.---gz%?fd OK.JΌ M 'J5jNL]wc^!r::ҕJOv\o9l~ǵW^kr>p_>P9ؙ 545j;μIsw`pu&MZ:w;|NO(&Lc.Y`5f˧_pR;1n%tp<١6 j+hMΨAj5 "3¬b*ZgO'I򃡳54_`; iꎝ; %\8?$w 2'k[.n~?kX3YNbG3|}/x v+`̀6 RiC-pHwۖ|${hazfv۠V~d%GֆEowzGMMo\p*=~.՗Q~V}Aɴ{ُ };Gn_n7#ORڮީ%dG{==~ձ+Ƶl`HMM``3ܭ/^Kڿs n+^nkөs!tۨ@4mqdH-rφjHRS&kh#&(F\*~cuvtzmr-_ YNJR 8 (m[PYV,oakrp Y[Mg Hw8%PTL&"R(s H:6 n;*TN*%iS|$>9T3(͂[ur` RMĩ8J &cɉ);źrRU)F@Y!F 8LFUbE} 宪r^%%&!SKkAGwfāgJ4oƑ92 wߑ|n\˩!?VgEymx&Q؏@_f14UKN_&\_;)QcSpѭȿ-*h TOsjʭUT|.6?0M0+j& 45ϡ:StZa8q$y_ =_slWkX8h $a,\f r. z1ע!wO(1vPd5IݸD7tSy޺CiT9pB|rRO20"y3P)+i^C.h|(RtM?ν,L ڪܪoOء Xmr`#2x=8O8y8}?s%ÿ"^nnLa]wsZٮ.}Z2u>J/u->klchV^z"E`)D }+aZjYeeM^>ni&B&&qԌSiQ?M{uMOM5*_T;l@IDATX\=#@qK.eem$i@TJ*cukjRqmڵD'Aq,:11];Ov*msZ[K+}s~QY|dFTKT^QaB@IJݥ巠*\Z 4t$UivKPKY:g",( f-Ny-R JF_UxpkԾ,/w (+PHUٷX YΚ5s|~?*9q1ֱW_}4^mK73)x+_xljZ2s1嬎7j )NsEmIqUPָs "PIjB];Vf)I8H_:a&u7ndSd!cBv|NU=![E *m{_NCF*ovz]?D"2IL2Yl.r|.>C\],"t}c\xʭCb(n^HqbC K%/ar{͋#p}큫Ͽzu4^#kvORK/ G@mk四ネ w}<o/ynozeByhHؿ}/cq/rd{~]VeἄRic|K HVWYk P ̌^YQD0`K)ʁC2T,+$S]@v΢(s( <Rq/084} jȚ=X5~ɧrPH*71jek`03>?蠦 ":`Kr*I}(ʁv\W KR]=ʰIT>J9*p.˚m B#$RQC-6#CՁC17,+@Z(p2TitEx?J)QJW峍d#Vb#À> .6;HulW-#ڵkMo[ BwpM956NXTv)n:iYf n1YQ3TR",IGw cZb!U+"/XESZB .ݽ;fK{;mCYe;(k[Șt':( f"e`3!k~UMU4I 1M0\P~.b7($Gey  8=G <Dr)u%>vx]w)=ر4R\PW~RfD"0SD%A xRHb6>4V )E[1J69PA΢"U((k#8e^W|AXZFyz <91:IJ^ hUqpf\q@jQq!ͱTX'nG <(z?"so\8X[-> +_lEE@YM7K9Iey"pN]̯+|AJ)Ea갩>>[[JrɮU]]܋aP9a4ɺ+-\1LqI"$UUZ{a4kT2Jkrɞ QF`(H?j6rOؚ8F <¡Q%*+mӦkq2 qW0Hy.Xj:cOwj< .B 4|A1΅ 9FP# '4J$mى*xDԸiby1ڢ6~QLRIuvP;x6_{=9Q@1ydƒч*r b( 9je!8BC0,(SA+e VWw.|Q_))a,1 2E3@J)MXDu!HC |Cy H墆3Tf*{o F^d- 1&MzxX"k8xgϻ_+B_.VnOo:02 zZvتUXS(EGܷ֐2/XF$L jDʆI_R*Φ`}dΕZ|A{s?XG%-RA_XX`S #FiwrRr64brWGtEUW /m퇁f~Y.۟,J/>-_MH0oE[XQH?G_7!AEA0pr\h7f/aQ)lhuەM倱Bz82`Pz$ jx0/  GXqf&$*/^b4 cACt!RZ[\4)*ŝop5=,"OG:H0R*u\F5t[uNz{)[b9u4.#;~43Ng4q2ișL¢6Q]|1ڄ;RL  G9oC"ӖQ0LTޭ/fJQMCCu;2pGQP!p[*ܗE(B) d €7B FT0-H!.7Y.ik$r}p\qW?E{# Fj+}iN`0)ƥtA\P6Ex={EҎv5=b}ϖbhݚGAV5M׼x8ɴ*nH=ZM7>˸D67=쁶%x.]it}]jsj q\JTS:e œ .;t[$SJ3$ TVܞ$&QUІ"FNcXD&V:n(dܱ0F+@\@AEgg`TPʶZШ+,*jUV&#A8=4.3srR~$0iU*QI?0Jr(3oS:ǪJ2x(a^GgƇcgMe5|f~M:p/ B &6RN]97?a)uET >268RJ[`4e)e#vaS[1A`rʘ!ЁVH ֛#dM˚P:eeN$5JgnDXwW8ιNW]5kQʕ+*TT2QIG",AC)ܤ"T+-6ZcA}pّw;i@wuMi 1HTO?.3hdfj$c[ cIQ3$ lS~16WdJ?uE28 E藜(0eȡbITN m>+Z4ʳ9D?t4DM}jRh/}KݠZ }9>HYTTdZw| 5/^.4]ۺ/?ȯx+nj$_&{-\p1g/z(Gi)o;_u]Uei*r=#0?7N1Rkr;,ѴvƸ! |E0QMÃ{Ł*?.@cb1E b1VICq&$ؤj%%؀Pbq'NU ,=ZZ2 l7a-wr Cr=j(5r+L.fP 'K $e)MLR)uE&uҔŧL/A@0T8OT̹A2\ &X*U|>'Y?1!lDBus%&%5Mu(dPģ)ZH+2,D< AWTcSANiyԊH .TJmXF(UIY^CK| mڴ^[3ΣZT -1~̨4rs6T2§gQA=lNqnb`8vL'!*'Wy-.B_U9'@EPYMrki[{=9+\@%L)v-#^5Qt,USo(GP:r5sV$$A!" 4ԤJj˵fȤO)AbymW\k.]SJ ck^\TLp]}#YbyjThXm̶n!2=vbpAׄmںI2U7 og@r}(mۼyL5yAk@tᆁZJ=bSuORMSw,L5ܺP Rwp,A -Sb'q Tm2P7s9\ ](0;r 6 ETK]~ QNEs552>N5׊G=GQ,2NPq@TfL(GxRۘ#Ql%\59S͸"RIΝX!tv~՜h+"nڗT\*\JVLq4q.P2wPٗ xs+EV@"D2f"Λ9c,R9z!+dP@@U.g5Z}Q[Ue%2&7SOAv,_T0z1ꪉ qdzm;v5_4QM4X'P'Ct< kK a4(8i h]m[dΪϦ\ȦAr) ůO0 YJ k^\ Zaw ů~}gݹsX}y}# IR/~s؞K7|&.Xt3M9ʏTG)Av1zW.u99Crt& 'Rj*nݺ zH)FD:uw ~,Ч 0@#&l߁fjXT[ͨƁ)fe6p5aR_yTž0hbj;+$׬A Qu,r*?H|JTSs4F?\OUW%C(ÏȌ mBF2W-daT|#15 AʣEy8xSyJ{+Q`S).8ql Vܞڵ˩a`!?JI3 yH'O4BL34N(Ҵ~.t[eI TӶ N/?@]ʑbhzTj,+''ŕ9u! 7@~şUy+l㯻pF1V"__X{"E326K^B״KvmETcO#S,2׼x8ST}]a[2v}cfHߙMUdX*ܒ/K4 ?7]ORX=H.,Q)Vbʰ\et'k\='e}>bYTT5T㝍B!Q $pGzbCC-e>+HՓ29ŶN<$BM`<'COj !@Q.9 C 2LW۪V !4 X(͉ ˗r܂{ 0(dPY]:ԩp Y_2=8p "L\n m6g}Mr #Ã7*\YSS3P<Ǫ:"e0"~NCy۳w379NN:J0^(@لFjbFHqI&S"H[VP)jV&5T=T^ϙztmQA{ĺA&ʫPR3QI\ɍ,'g7vDWXCpm{r;.md\$hC }1Q)#Me2ÎRWMrS.w_˩RA:& ') ZʻjImtƠ8M䕼qNǫp9݆h'] bnfU) /^tn}KMdyzRz'?h]uyEIip9P]kӓ6G-X_2̇iŚ(3tI4&!L@\1x2 ToJm .,.I b }=NEN)(DSuEYHv 4bFI'CU%0R Tbp+%!S^*IA$А+6SM Aiv+Q Q['aU(L(1NjR=oJ N%ݩSelڢ6I,R8 <%t%UMnk ;|Ӣ^XOG7=H38b;4uT4|lraQ<\^lqJxvl<-%Mm]tN nm6qޟ$[nkjlQ]^"Eb@?o[w[B /ǞiwtRs/|_iI!ťklU[kKEA/|_7 rK5/^E@ne(mʕf^bT{Ip+,dKp?1:Z;O:"E)꟟@(PP7jNbG0'4R8lcfzf' $RyZºSr7U*̛Lv hI/b%eK'NR[vQ($(ĉw0|e㲙 S x F]ݶR qPJ C:uqt¤ێ22TQbًlRfqFtB@-%t ʈ`vCeAŠuw:V43=EwDkCkpr\s "($ĕ*v#Vf/N冋Oh98˞ZLmQA[5+ŘvziPRFf[4)}q" Qq–-k?sϰر@2BqEfes<\;2mq'{E/^x"E/^<} *Y ((&,F m'4IZc 3z 8EۊUVYriEayE۾={]0Ȥ~_ ^hd10%PZZW9)R"W@w7"Mir&8F y l7xe6: zI &e[Q=9@GS6>UᄁG(!3QRFE8Ɓ^p^WG_n:>SvRǮ QA SNDB<Ϸku[ WE#l*+pry-ȕr)X nNAs>0O :bƱP+6?[X]a;qIs1+^lCc= |!Jc3h@ CRKID*](/0k׼x"E/^x"Es@Nj9<_!O5*!_ʋQpr&f45+{Hƕ5Wmr`(U[# ܲ;\ꤡ6CFDC36C^:gRR%TVR[C̳k7 :LʁAs@! ߍT)2/0p)i/tDt6.EٮjI(`+kc?VZpì33 <`)Z>};,ojpnRe;;`Q km]A,ܤm9D< FKgi (2964;2z@"j蓊z*1ku=t%1r A;˔!_(]K))ʂНR76:'?66A?}r*ٲ)TAugڢ6g \:<IE`Jkʋ!+LB}AU OMyhhfv2)wHDƨK϶~,kALۮ]X`ՉIR!7W Y b!uZZs"KN~܊8(9tR@׼x"E/^x"EsTj o|@$SZi#vo+W$.hՔ X pGfGgK0).lHge0@8lRSgm2*TQ x +qjnHU7Z9JÇls9cvP1V(3I}6J}dXN]Mu5.똦}@B*kmmpQS)}q |~zkVgYvNSD;|K,R00(U#8`J6*ن O"ӵSu5CCjRxQmx[G+M12+++Y2vY]uTKe(ffP=)JPIgrb*XCE:#Ϥ^~(s#'G(2˩jG3-d GHm7wzDS͝!$[O{MI $tiy^Oi\X,>ڏiWQ1 TMwN۪ۧ abKP*OmA2ne޳3^z:U^fE/^x"E/^mةJRڸO"vP)xZwz+BLjXՔYSV J\z&JDAțGA&T pDY0\dӈgqb'vJ'm^LV f^eS(PT2 T,>؉j LAEcB NJ ׭`͎KY1XRqmjj\1) pHMMS Gԙc )MS9_ :K:@Vq%R*q^O104_#ҥ̩Z昲i[E#  oy/^x"E/^x"E9D@d >i*$M*IZ%p%%eQ`i%b}]fZzzn*P!bcN{rVakP]6|dbbU%Ek>:%Yte"< +l4Tl{W7PO &Bzd lhR+`z]m ̑: ,Zj1KQ*;H0uEH%fc0)*.QFTed:!'h%! 1JgIGkk+`Y7 =e;_bt21  a>Qi -) *>?&2EA1(ZWit7S9-R)/L?N܌EgQ@d'o3^x"E/^x"E3F@fj=%\e5L"F{>E1pͨU( oW_}c& dm-<[m}S R]oE9cQL0YCLP1VALQ9W.+!utȚZAj,Z9Y935h)XOW7})WjAK|L>[˱m? Q,o@#㘡O%ԕknnV "+uX %T ^ 2B_ssxsTî .TsX&X__@@OQ0e$ 69˯>T^nEji5 I1P3M?U?q=(mk^x"E/^x"Eg+i&أ^S!yf>K`rR2p\boQ`;v%GToaT_5V._굏NeUL*))Q)PPMYeuUmfFxnSTnb J3j5)A46\AU_BS9n6sIZ>ɂ>Sr7Ue_T4,rЩ*:dA+6ZK[ |N(aziuf`@iijJ'c@A .[H=WVZaފ j!,qBC>bTw_RI&@ U=2e7WM=sj'o!=eQ@6M"E/^x"E/^twu:" RjSbĢ'Y- XLeX:#@bqN0EV['(0' VV:*>*7]4Umn_2@WA=6 9PV@kIe4^680l=]vu7mhqʚXy¨ʁm(dIRFβ*6Dzllm< FW^ dkVRP|K@jϝ;w:_Xz~l뵌&,y+*ڕrR2L-xeQcB),^,VKQ7z",vN`Kؿ'{lι@۹[ڋ/^x"E/^xXhiiqEZiRM)]P6)xjuFmVouՓc VWLJ3ʄ@EtRd%6bPN<@b=VV52ZbMk@ W8HPyAzBS՜2-kfv9}fK,H?mb|ĥJjH_E)f\@H A.K+/P\eR]ne/ҭc{ _":#J/M+;))([=rLV|ҰJA,3os61*RJͣ]iPSMLC}F9\Y'Rx#p3xr󙛠bmQ@{^ۺuM?<#g/^x"E/^x"twu9v. : 4Fp [o#uuw/~q/`1?X a$ $ LPh<Rیzg@,ΑD׼L*qT>&21eU,Mi@Шbd# j gQ0>HJPsEYVґQxPE6AIOh0 xQM-JGX`_ADi g4iZKK hg8id8hWZpqrsgpaYk2sc)L%&*՛wY 4M̳٪ܲuμx"E/^x"E/=iRI_JG6d6mz`ܺ5lYS=+CہEeuFZ(5i@Sc{U@I͌r{tS?)T,4(P xmЕ0+CVN '1eqc͐F9kdpWIh:;;iS+!rQNu KsI,6 նͮ m p0I-;G90=Z*5tʩ_pJd7tK)94=KM*<)% ռs89N+ ӹ6d<.ƏilZWγgje3ϴ3w果o~_YUu?'m-S_XL}N |}P85Bȡ``3<7Es 1UA]GEjOql"` 1} /~"E/]:.}e/^"E@)-Ծ!uVj&ctȑ瞧^"EX JlYu @IDAT>3~unp%wR`)SHibq@PyQnp|_cՀY[ 9N()5S)rՔ)@i)ΟTqR%b#S& @ _RvC-P8NjfytU|z͘6Tә?tZQ<]ͅIh{tdٖ-[jeGoB4Ob 9t.*9 I&棿-irsq%>joZLj=m||' XK/N+N%6u+avn+B;2ojv\ j*3:ˀ`кE%]cmE ']m uÅ_EҊ(Z_hWndMK^o}{'{?zθ7Ӌs=E(xʗ¯]8&~?pJ{+ou7 Ѕ.SNm5%%%qZ_n3i <' {B TQGb TR QΛR 4 9^8{RWL;U m|8mzQm6IB5aLV(pM9hi^'dJ:i Xjyx@`-P8)bnի }zf@]- r4~tM]]CmGˀ6Xֲ&KeߗN8শ+e+ }:Pno}8Bynvozzw:}w[C=*utvڇ8u_$=E`iD@@+U{֌kIy>㎩xYyеD{F Y@~lFoM怨>7?P:&'hnDBBƉ \VUW,<4%<}hH?W#b0;R$94 5>Lj9oOtrw Cm"AIW !@}k`#I)'jRFڔ<'G3r:#Uӂ|?Te TJ2<_TxI2̏}85DKUKтHKXպSh@VyzŪjMD $р*G@iS0dM{BEOɗԓGO<)'AO΅'NP |v-Th=Z_Mzڊ(F)LN&;: W꩹h`^8kҗү$Ěl۪x*"HhD\Ft ]Np}A&LmB gmqn7ymeszx<S¨mpiUsG #(4h4y5@6w)FIee~ 8PUYtT+*,,ƿ{~ȹ8\Y>ȣ5@6/ h#08P?P^C}sDn-*"mhsI~/sM_5MT#4qpX:%BD֭͂# !*#|*II x%x i1q c1 kb5'H n ^WP*Rzb5*VÐ1km dQlOH>H_DKnK; `i͆RO+GWz{&"'۳\/R)QJ\X@(KIr0HksTkhCUő~)HfJh%yҵdn hb8N|usЧEd?ɨ NDڙfNtƻ/N{G86: 96)J U垞V&ppXF&_A .t2".pD 7R)jxrgٲ?^ 4:(/"3r?}uoh:@4E@ xt kS$O'A#I&A-vDmS[em۶e  r%."uMS\!80ʦ~yHBCnn6AHi(:,XAoZ6:q 1[~2. = ]r&d2 ri7X}hA9%ҽh Eִq48`p4p@_J kP=>3=-f&O?٤,,*ǓmϨgpB‷$E-V 8o,q\J# h侩}_YQԓښF ʥ$@Ks1488HQM7kG;^TDoP\,gQw f **vUTC:/z,! BU_EMEDD(S1ʹ6K0MU[l vQ bN0 (y.4 }^JjQ9Un-4Q{ -VVsk[ͩ{&ʶ,AiVyhg$y;-&hUX0КwAd[gw::PI(*ԃn9Kqx>ʫJa2T\R˃'j&vnM7q vAi66lQG6dsÈ88޿,Sw6sn۱AObR`D h('E)'vKJs-RBnY>k|G18`pQ}/O~ }%Fhȷ{Ď(jwVzYSXHqO;W$]T5Z&Hi;K=)wE%D!yA \/LRB)'3`z'(%˵L=7.HUS Ba.FEI)bS6On,rCKsĒFE4TnJ]J\52 p7sr81n#08,c-}b(w\>i6h28prqUomҾ\K|wkZb\Ҟ-/B; *9Ui.( >Z Ȫ F'lK$Jԋix T@effdHT_ȧwJRʭ}tRÁ qb׏K #:dZ xt-_ʱ4-_x-)PYz7lت)h΅C$h|$h#/4d*N4"U-?OfVR`J?#h3jXmD|,p+MYd|!JC|< o[YVXy{=W}PQU_ ",صi-!XL%ۖi*Lvw8&c:1hC  łf 08`p h>Dz5 Q&ג'w.m]2h bL56P %HiiR*XFqЦMA7(UGg%%%(,(^칻 [(eWHډc}iQi/ZZcZ9籖Iɹ>ގr-9:DLN,IJAg')yDB`7/TQ%FtMP_( FbA" &V!x%R/Jc""lHf<,sS'eD+ʩ X|\A4esކ豭R'bk;7dNvo7dg$^~qpxelEcHT4+]vsg_ 08`p 08`p\` HNQELLETiiGp|aa!rrr'"*uıq  BؘI6%T@Bҍpjk\[:ڊvN13,w73.rDBrR J ~6SZL3N`3U VI)2 Z()(=۱ a~t\%5/,g,CL18k<EDW@6H̙NI;+]ۚ(mC 81ȸf1ȑ݊vkJƁQ'z]ԥ}j,~DŌ 08`p 08pq@rrr,##Cq t|DϠ AlEEE)?x$_&*i*(,TDM@: ŧ<ԆBpSʊY}łH"IuK"PMdlٺGJ2 z BE7DshO@6w7֣BTgrBЫk$KMKoDtnmBA1QZ)()@ud $"T4Y8hOEL+d/ꭢ:M ]tz@2Dơ0P|C!5F븆&h|0878`p 08`p2D*M/%V:)'?<+͵`uT5iK.dH '`R 1J@ɳI7 @@:C!ɦIWKWKnE6b/jբ7lJqQPvǾ=(*Ɂ76Pt'ܨ?\UJee9VmB@ <U#=e F}Ѿ Ete$FUQϢZ*QD;pb%͍n&J˙*nfk&VR&nn ԙ`GmRt}}:2 >D[!3/GA-"!'*YSQ RO΍pp ~ø⡈ ͇\ $[߾rzu5{Z7]Jj]Ec^ `§nL=rJ˕#$J'Kãd/>_. 9{yTYɃm- hY@`etWM [.$=U- -ᵏxQ8/\ VʹhNW-AZ7#7yzdLƕcg@^/6w^KƂr^ [tϾ9 <#\j֩7Νβ§~\Ԣ= g O3QýS,@T=E2͓CBB`L6*l[VH\@EJx Wii 2=8TIm<d>$]OpH5dE6=_OGT @$|1wy @Hұ{%"-ʲ<384 HD1 ]׊w4w /_Jq"NT@6x.J 7QGu%n PNUn)fFɛ.tZjE])#W w/7 k6`bwuH/׵~` ߒ0:n၇€V~t /?\.?#lRuk.Z|IOEW>i}@[T3H7KQYSk\640fPO ͆bmRxLpw){j.-S ϨzsVc 6qO^1yLT3jV!oeS003YGpe/fӱ{ Lhf W tlvIQr}0(woi4Ka옑zj}o9 >pēЃׄ53VXXw@{ƠQq NڀWG}ULN/ 3a@֞HZ%n7>srN:)UDRM(;mI&1%RnV* %Tr.i'V^@9=Ȧ}Fzm/ gMǪKRm^U#@E `oh]B:($h}9GCwz @d]tS9y(,Ce`ir\B 8l?|:_MnyhGDxFn,J:Bͫyrf ljGЭkwNdoNZOP>Ǐі8mPUJdsIƣ`IA#@ƉtoQL&g^Ёl8g,[ '$ [g(Cz7v ~#f`Dd4tZuSoG5f)?2pRˑmxDGtv͊7kkޚH}ץ%y$B΃Br<̑ݲǹO#u|{*ΦieR;nuRʚƀ3zR%g" .톶3iܨ79ā<9-۶=g2[I=n-.@fV[0AG^~Vhw*Vf$TRaGJtIndNی7)rӕ6q.>T=hi8{$^5>&58P#itpFIPc)Hy'[@IMM gn-*Egf+ZEO 2PQҚ.j;{HIK-2xX|!UPthtPlT,b -9 s0BUxE]qqpnrv"ŧbܔqp"r>0!70k]ph!vLָ\`,tK'`#ޯni](cJwѮ7c]NLF.-5ؑ&M#&ԍ[]WwMw%ᖾg\Ɵ>D]v)>J,}n-5;r7w^(,Al;/mw3iby}i$Tp>W͜p$>yPSJ+D|hå9#[bc Jɐki6PŲL0upK!7}J{ŽStyZP"$?¨v9s>f;NU~eC{6βZf 4i:gZ}ik jǜHkVT;q'[ξkʵm;uG7eBnn @T YhN 6uV){{//E}t~э$>=;RVKq,y.~]CX٘utU%%8,iRrQ=Gsa]pd*DhQ9BUu W9S/ÇQnO}^{-,Nna9_.ſ0z@4<˳ywa͍h͊>Q Ǐ?nxtŶ. Gn>PpٌI0}(.oHRofAHۑGi.CǍ!]n~O/!q݄]unmRg[hT<.f%s<=P:dۃNi?I4݅jƗmjy1XAm!ﶚ@[~;sNyGcd'6%Y0K1 Xh!&`|7.»۸!H;j$2G޲:eO.(6.jE5+JFP#vcƟ֬e>=V5.͢Ye}P;NC618|l Mm4$@.fmp کu&L_5Z6vP-Dښ88ѳ`T'o3$u{"̛*Lo\^'Io@qG'T[U&o_%`ڧ}~V݆mWZ q`˯x?[{!}q̡ ᑠ ~a MIqю}.`k4}ٺʸ1O 9zkzG̽P^|`T|-H6uOUOrKinjk/_c0fpO`S@7dEa8YcW0yMࠀ*`Hvo+>o=V-_7KR"WsH1z:}b&[.u[س+tem5# 1R UBi:D-W2Ϛ-KSmnayƍBRfFmԙuVKߍϾ6BtJ%K 7qaV ~m ÚKj؏ '78H/S]32+аhN08^k|O sL ›+*qm(eru.A1aѿ6|50G鳹q!8mf59K5 #$3=yt,BMLēM?[؟@ktf8\~˽վ= ILn3WNӘ3Eհsg 0 z s?hs& G=+1;ӮF 䝏j8`h=m[-\5BҌGƼ% h4+W>SH){D`9EQ֬YmeJ%]|l3"X{ZQ/Gqڳ`̼jn-žتs9qN(n-8&-@Xeb.O֯  Y0M T#K;vT Y<\*B9#iq(op.)fޅ/+R Ee+K_ 5;q`AHA]}psq!*Qw:iiRE^JɋJ{@qY|耡J|8 !4ҍ6m6>6qX :#} I_̐t [1l޼ ~0A9n<4"`ud+o80 s<#vJ>T`cݿE6x0ۍN.\r1VX0 Rq8t _M} hL-Q2OFdj鉣{p5d+8`?b l A 0 z v)OuIbHF cagf] a!'VF#IGajErڶa52`$s LJ1̝cf,ݔXJ k?=Jr dfb/ˑ\>Ǡkmp9X^JSc'o ԇr$#;}łXOߣiNwqtCۖt\#q٭sSngP榍*^/5w*n̸̬x|ׇ@,Fy+ ;lNZCef2Nď[2G)vs|ꎶy/c^ws#zDx2^;@ۯ|/8A,lKGDsVkZ:ؠ=sj)n@6k1مb_6sk̹+};mtkDM\d'`b,;A|:q]1qHGW^{vm 6'_'^=gnz;tTDڕwh$&̘K۩LY6,[6 2<56̝RJ:8}xoIL mm }يN`SB*ºF 13{ `ߐae FW<^x[gn߀[KJf1EGvKP/,mF>^!tc!KVah׶ |?>?O|LA79ׇ~uVagZ--sոfi (ҙ\TA=m)]\MY ؗ Sl\;.]Gd]ߞk7Pcn+ٗ/(tCi/)FsexSp?Gȭ! u͟~8FW=GT⡃^īW a܃ҙJF͚c٬ٯwp_>$ K8\fy Xq7g]vjc_+z/ԤYwPrMxeen3]˹ JMaF$KKӫCBߣ o2k2!$hzAl>*޽ \Ҧ̩WL rAWˣjBmu?U(ie/Fcy:Tbொ:6npJ" ǘhP+ڷ~ wcrucޡ`͙дXvuP^{_5}+_p S"Lu#ߏ`_o@.K^Sg'=={/>>%llN?S4Ɵ㫞?R\={vLL̛%5Ʊ,e5C%_Z FQr{*&Ĩ7JlW_jzb 4Y9쟵V|} k_Lf8kZS],ú0߄oV&b֭1N7Ă;'Kz5mna܇Dum X^ʓ:a) S,ݼ@H9C>Cxj|LŔ^qНٝꋘ쏒e<8oj-umbz{,rFEl>sh{Xݪѱsח2rU,Ad=`!ҖG ިWZhFur7wl+$fQM;4yRL 9QϤUϝd"%2Xn8:Uɟ:@6ɵ忇AqI7:tҝjisͺ5:ovl5t'!k+H֐y$a5--ҸkZ\.rSS<.+ѴZUZ4v]r0dNj UkkiHiU R$*( F(s%{q9zHk?R@' nŠN.>W_W7ŗ5 ʑ]VS-UMX g:?,›vH1%f /ȵdX,ۆ%|4i[+P_ \M:*T1ljի>hVE{<4gY#Cd3l\Q"Պy;;@6IfkCErg 4gs3]Z#ÝropM|,lUt:PFUT3UW+*@\UaKZHT67%Y(_NI2 .*KaQ_~qj1(F B5QCDwۚauPz-G63zR%)OHTC4F)6d"~&^KY.ƣ2dShύII8X#ŃG+oZsRm4R[6WCc3, qjm67ҿp48@|}_+g|)iwhPvB1\ƂC{ @+сa6#`MC!L6NOaA! ^+z#U灶IMؤPK?Kkwڀ@IDAT z5Gsx[ګ6Zuұ?Mb.J:ȾԤ4LZnOd_ ꫱`CKݦ'=jITlE+sݟrzQB3oJ//e6zW_x.Du-'Wkm|Xa^!{sʯfո=ďvi)%èKvBv$^9JMgzQB)(qR[*Th/zJu^X(oOy/6?J9MCg9xOK6p$,YEe["#gp"zqy@u4yEx|^?LU5EXɳV.:uGkMAsa/:QF L{UuuO3qw@6 Fb}-x|nı]Ip4w"~~?8H7?"? >dcMx?cS>I;Z_=[5~Iv`u٬xwڴYPb";/Wͼ|v]נg>OKF 4c,Ie^^(Ə3 k[]oǼh&T[(AbpUʷ0-AwdUVW6tȝŷ'kV4"Ƶ~y<dVTmNo7V\t,)6\fTP W <к WU3V> \'}Zq=3|F7ǚ w:u覼SDjq#G s@GO @_4zRN~3Kuw۸K&aܨKrA@\+n0EER ). _pEW0&FyZx~zJ[#jSAMJ (Q#G;{96[(Z5 7Xm.SV+ tvggԣu_ YT+.4H6V?]2nt@MM#// cjYK }ZP(@YX*Q3Ղ/7kj09 k ?|ͩѮ#%f]^zl&aJAam0NDGkH5m`c׬StMQ G Φˣ b4,$IHyO?Eԩ04MX1sy qڵ%c'UPҁAa iǨzNR;Ώ@ .f#VͅVf6?uM,ۉ|EZL-QT3 6OKKӧ4xRuTѤ-*eNܔX72LUVR@MLĉQ휬L۽ Qgcy7:L(hZHWQjLҾ)ؙHɘm\WCW}R%pP٭q51p^ %Yyd$,z ܲꢎ7n^/D̛S v,(xY;G#%bڈSvׂw1 чxI!DR( #su9;Kyb7&ݱj8lfDWٶu޶=V_lX-`H Wt`d[eG;{DPDڄ|J։lK؆]I 3ˋd7BC[NhkA:Lp ,oj.mSLG-{qg`ht;f]/Ҵk4\0lzD҇_ b-w ~bC5mI P/^( iPžj?ez֍xީf.OMgm6Mxt5yhD!ּ#:ޗt"`i;W 'Ć:Z]VE@֫+F5!)|cLʽ{}5g~G>~QPx4HvF.:ޟ9$܉>¥c1v@O{ ԯuǸ #uE|y*kg^Sz>FW/"pI vRǕCYo6pn&5k glm/h3(=G3?tTG\/I̓@S#Z=3}MUs:A_ %Bu>8S/+Bizs.U9N Deн8O=_am\+9}ܷ3yZdS#[ӧ`[N |? ֌;#ZV }w5;5_PNh"xaЩNclٲAΤg9X6Ool|TRȃ!ExA3)+d].ZJ4FTW7#eh,^9w() A7&Ms9l%tZĽe;lEKFL_Wߦaq/wdڻm ZSL8j5!qݯ9O9i7C٤տ68\kεIj6⒛`ЕOgl Xw|B'~9 }FS>rI1LDG%Dƭ7.1pAl.7qL9s7BG*ё]q#QTn^GjÑ:lyy1%VĶS7Iw OG;R=mkeyAl|Rsu@Kǜ.$4Z#rӓx]z҂=ٱjۦؾx8 ;ա:qGZ\$nz &)EN4΍5K̥ƧK8̌ x1N5#+ԙڠ[*EƏ0bG t0#-Mv^ ƷOq?MB0r֨s o(HLWhB'Iko)9미ӝ?{>&e8(YڳE/*@qiJQ!ȱjee2Q+(4^݊KZA@܉J`hYI9yL?E#KtB(efжZ JX+өAUP q"+Y!a$]9Oϋj7XVF.x{(qG| XF`IB:e e(=Ac"G/R9YӝD8keYr2Ӝ:MvٲGWhMn? (Qʱ\t۩b!\1#yr'nTBy"l &|MGqV&%FR?fj0&PQdZ; xc^>Oߎz]%&v~$&x!!̇POg߿7ImP•o>橒dF%T57_R'?Įa4!]uͼׄ<חÃwLJ'4o 4ƹ]{HG"/鷀xbJV('Z:;ASK1γxlt%ئUoNγa(WLע]%:+cɵƲz0_GE-9h;'t  .HItyECcuQr=f7?žC-tGȢ@]Q#1zvlI Ry߅+n>KC`,ޭ8YiҜե$c̳تD_Ƕ|[>ຉacb{eoŸyԘ7Pt|7moϼSrFx Ҟ/N`mHO<&.kX]ζq=vS&-݇`vCFHf*d^Ai :Q3"bb'ש޻“xf۸ilVg6?ۧ^)CWcpϨ0m1$|_|M%?D;|6.W ;'%c6h z!aʯq[+|pE!g'X!Meoތl ~e_]I;eԆq(hKp%;:bBjFݓc<EfOz%UM*Ħc%wBrE{i H&N8q8R1 h!E!mݻwEϋzSΔkGϏVS*"'^O=Yh6*i,hG"p2@Jѱ/|*.mbI~RŮ~iq Rw=V{ю ?kl Ͷ ?=MINѡd+M=T-y)ܽ:kG`'V/:lPrT=C.~vk>51+^wJ􌛣0q>s]@[x ^NW?Gsr`:}ERBF*'wu$sQ$L[ي3S.YbG 9HG=ҜkQJIW%w H#9:pX$!$ ;@"lFDҁ=Puq=ZhO;s 5@s"qPDݡž{9K̫Nچ?KvHX\Jc^9m{/x/K>T!e.$.T݅YVيұG:ҕ r-&|-vz @{ʇ{-)o71]m:3Hk'>>Hx:@]UHTI`WyY38;9P^z20s||b_8pel׬ƶlu"X)~]G#.o-ęd+؍_ I.,O+٤f zDkغxm}ql䆧B0xXC{] 7kVsE(ӁlG|i (lS+ϸn1J2J;HS" :eblPWЁlekJTmOU\`Ӟ#/(sCM>ZFѣ1e d5 ˇU*(c%iiH]H\\9r$n<Ө"ֶS'n܃ƻ̛&{%MBB͛㩧rqضmfLbg\_Yj$BDrfR~tz3īh9U5E~ GEH"l꟥S$e= xqԗ(e8GHF)A ֖/_Ilg$]qkѽ ?`iqЙQ}aŗ c0)Rx/eZWSL\ٔVaQq+?+>öPUOϊ-IJ DV~GOJݻoJR_vNO~jTw hvIF*ڗb2Tg#)q vg60슑Fʗ%6Ŷz m~(ᇂeazZm,9 B՚|+Sa VfpͪCt`iKuY޳=g JB(?_xYokMhֵhb-0 }J1_r6;vBi5 0{}5뺜9T6dhS8uԪ-Z/=J^~yW27x=mn>fNsȍ4yH4"GEӊŒ|>]y~{f=Z`DG JڸѱB3Mk9*\65,,(,Ƅܴ uѐN?Mp 7#=3;SM_N"QbU@8W ͋L~|ym8#joԮHIuƼ::mBdm{c9g32h B>=&o ~w,}bJnWGu"pxpb!i.,޼{}k p>ݸv Nj ŒYц_$7ͯKVbUjk!{ $&Sԏ8ti OjHeebբ]Hk̮;Ag.sK}m?*Rjx\kg}UG;y?W᫯:%Ν5NF5-hIc4]I;oG@9s=y2)4dsHٲEV\9kq1cc@@ cFG'Q2yuN_%ysYi^..-c?mT -%d=*kV9c>PVe;qbzrݴ*z#w I' ~~>JBH5A*wJy h9U8=h4%Ъ $cY֋ŒK)JСr`ر}#|<{[+y+)W/w:P$}eVBq(?JNAH4m}ؖ@VnVh >(=u{z2V4ZM|? 7`n~y5 &Ge!-S;qwFJf]п4Y@GmǤOB׬rvXQg~.qaVMyc3nT3l$oj[ޙ@GYk}LBBd_dQѺ墧[sO=Gj[{ZSkmmKrRE!2v&H$L`3'7H}eѫ^K_M6쒗~zSߎ(OC dJޗv:ή3SbT/wחWsYc~-R23Ǥv ~ּ}O}e}X)t&1 ~l V40D /!+d:v@PK@a hҥkhɯ8qwCńO~!Y^}fEV];YR .ܾmŸ`(4,ÄDevj(ɤbI Ǣpǹ_,qŞZeqF;4*h# `660PL_5?OJJdI>pm)fOuI"EX#(-0^  |ijbm:{ Vu4lm@42|ts%PJ8#cq4Ah+yϼZyrfY&VIJFPqIOW (C>K=v[CJ 7vv5s%~[)8Dv3;vl*?i?58c?z`KVC-cbY X/':"1bB1K 7[UT$-iM@eKAmqǹMi)pPL*A&YɩU-pY0C:*6*k:+DiY"-iO1#OڒRXBm 77۞"xvV>r4%L9 7ҸZP[Ii ? :PJ@ ( $Srz=tT!q}k

'/etp ב|OcXՀzoㅗ_ur"4iP- xԟ5085 X$X50KKEV2M7r|/d 8 <sũR7,4U߫T][J{j[UA¬;ᏥаkOk]Hy2Vj%Acę|굔L-nR: #[A-3'ý0Bt ElĐ#H2˜`_ FWΠz%3TdeR^ltJ?yt>w)aЇ7mۈCS׼Lt3l5GjL ^7ʾ|ʕ'#ϚASO emطkwl@;_CڍgR+5e rྃ`l䶼+1.m &Ji!&h±.}Kƚef4[k7 ͻtWCz DžXxpWߘ^x5X!'-=YX0j'fނ1CC{GPukjfAُYx[ۢZ`um@V~TpL-*"_7\}[bjJw鉖`Mu#a6/GeuVҙRv^V&܌*QA%h ~vN^dΆ(yY7C!: 0r@X`US4,'%[nHgl1_Mġ֡cvJLd_qyz8{͐`hl4hB .c9l<7oOg<^k ŋB`'{ h\Ukk/*mэ*SBqАQ)%ذu+ D6gl<H2cqg:xҁSXߋZpq $Ox:hC~YH0OuYrd.Ų)Cu4}!&( [ 2V{dh #ݴ͌2L.אVCm簁/umpQs"S 壒dRr7G :)cf.#NJW/Q`%}5#7xi;N$s)XF8lU^/i$P(FebR>m\~`GeƃS?WUMq&`GϚzT k~ Zv׿m 4wR!PxU71Xo# N#*7TNk:m87kh-gѶC{řRA]>U߽b>.&ɀ\$Tq\_M&ō)KJr1c3X9y7z]Fg e(}}D Fs[\B!MiLJLCBbvRv;ƌ*u ńԔR lGi_v 8F;}n:}_ѫ_&NFU?tҐ4H=g-ի Ymcp@Ryر ;V$m[| F~5\Z; _/ƞ-+bIz*H==Jѩ[_v̰ ®SorOXSsRW8W/c]iB6Cc$$8.4hPBj#4=`r[E%r?\N%h0Ɍ޼gӘP!Jr?b6Fnv6Ysھmg4طzO3}kݹ?tyE~Ύ.,ۗޱW 3t::aIFeCsrߵP'm z{kSkC{\T(dq-FUFUoêJH`*)y& WߠPԀ_5@K1BV5fK)Ov( E1H>yUWh=vbm9ˣ.`& F1X([USc{4GM0G%njnl*pr8R5+7 dcP0ap~)%>,թr8qɆҽ?J  {79iշ1 fA${C dR29/3'0#) 286z zϦT}>ןr:CG*kxؘ֮_N+/ ؗu@k&Fط7Ɛ omת[{# *+t yiOk13ڴmk=eZ T< aԉVʖhKIk5}?n}&\S K&i Y-m[TV'$b!s]\g@D֐//ֵK 6i~TP% ./k_Ć ഢy/Aǩ|%8 =Vu׌t c0̳3) F1i=~g8y2X>=UBSm 'auC[CI$uA׶wYcy5%_VۡFb$yΞոqNtW:tćE. G7_hs$?d݊ͽvD2Lgrlo: Vq PrE5Xid8NIb,!\@>/~I.Z|1OlzM,iCi'}HS\=8~SmBoϭBUebo+s/;-֌Cxg1XpN:"8(PRGT0m8:~oމ>m,Pyiq9.G~YS,W.nCO=U;xnZ!P[θݺuWwt|^3#鿽" E; " ?ԹޘfKg-Zo硨3OB2[4|"JT< mhlںnB xZ׮}0n_g|D]wV pw7aܽu(u pAJ-aCѫk [0OmPT\R\&* ÐV&4Ę!RhxR9 g,Ry/ϒ,T@Z2 *V)OsUZ*{Mr_ ϣ^|Uڑ+&Os@rtt–k¸oUyxbTD.'z'L z}Şݿbبi8! M#E#EAk`1o5h*&\+W_fz.%r,LKJq1!;׺9[WvI]bLZqL27.bp3Z@XMlj4o像pDp].c0:1>K3'p̘Io] ްu-/Xao댤܇KgSA3=؏'|lcK[$npsƸRVd!\ ӳkQR-mutj;*H)+sh8ɱc;vA`P'k>y!}Ï󑝕};f~3h) EPV)DWK˔8ڱDJ2QYOډufv͠ƒ@lhhYWC|܎]#1U5 Rdoo:'kFVy梀SdԴCs2,>_J 2v24$H=zt";?zH}ܱLֳuoP-*s8|o߮c >~Z!~zzIV%9L77A Ooum۔ 4wS^O2y'a`ڸ^)Z2 2ˆ~U)>zXbXO5zlm~QU~ge6*89Y~ $ɳ֌g.y*YʸyP 1L[|:{v|Z&ge=E+e˘!#UMRSج[g!<蝹+ R[H: ޞ=d<䫺zhJa^D[UTd8)Nv= rrf>pw:\{ Ʈ6i}sl#…M[@O% mRclamqZo<} See>W[{% cXմq:<=wW@T;'8ފlӻp=^yGǦMq`.UEmnzR~˵&OzR̂SG 04L,F;i۾mE~a5m^xMYI/cS'{D]W98ЁX wR'crZWX5&HOT @*u>0=>pcL3g]sdY㪬A7uM"~^/dК/UɿHeda\_MոO-ާl*ZZ 8ʋc01\(Iƀa+2Q;"lWL`NnJ娃x2A9#XY%J֖4mSH#+pᙩ Qvѣ)RGKL㲺CFvNSd%aѢx, ys?G+j(kH3A^gmPZPKC#U88.\LB>|(Q8}$qK'v*rW]s)W@.{aʂKuL*bJYʂ4xyyƶdˮ]Ѡ:4ƪF3 O"sՆ;aZh?X 30čl˯W>.؀m00qO&|۫Ȩ0 WSo |{ؔ\6w t `x^}61͆fhHE3Λ *+aorUmAMm52w2grKa-\|\i0>d+5!DUf;W+^r/06^aC1u,HBOD{ւj乻3f-J9R!LPdJjq򳠗ކuZ_4N5_bt$ב@}T{,Z1tJ)Cͭg'a#\gP´)׫U#5/B;-٪d*CJumGn_>uj 7+W-9*, .$W75ȶ! [w[:OI_Sa Ѳ'[OQ-7Pf==2tBgH p/8! au.ׂq,%ߵlǤ)q-/ bwlal߯> sp:] k^XRVYd ˷9<r?' gO—QH8 x$'͸"1hgwxS cgj!Y>i㏦ .G6O1.= 9nXY;7,O%]X[oc&+ј/n w{ݴ~=y$?8zY[N;>d֌nmO=Udlj;G߿Ý 7SV9izOF4`npl(|~P(..(d.Zo&(9xx^|3m+`esdA'W3>\VWQyPތ it%TӑI=|ւ㜯~F. ګ:,NKP`CLLZmut  >J;9ïE"1&qFlY(jc/7`^|ac&Q<+~ 9b\:@!~NyĦ}?>(aZQYÈo'"I:ʅ{@%g)iqSdٵL_CF/d:Q⾐comNKVÖIC)~:,CC'9a*XץpE{N(FYC{y@FE!@O?[ w+a'z<җVYoЇ44o鋣{0Gǫ0G6Eޜ5o:($c2rۜ!*Ԥ|c܋TGkWOĘckV)G{l5(L2-:> (s#df>^:㶜+`(5x+9[Pʓyz=<2Vo܆?(4/1wg8`Һz螷r-kj2Y]MZ࿮P%Z~R*:]+\.c5(/J<)wgBe(k@k-o,, )8q2WFt9|շ 5AG5+hg"1J {sܨDIq|Q[ƫ~m8L2u8V;{x)[;N %-?{>"s-߶^/̓{+{/Ibwni~l'/JQ/}6pA.4᪡)B:'?0q[** &Uz^K]u\[VTdѾ׵׹[Wnǽ6]-hjhjhjr 0,20}܋ =4c¬~x [X~x)+L)#Y1E7]32r0flRPf2%]+!FGWOwŘ]:w|Jy݃ϿJcOS)9[+r6XFkTq;! `giG~ ^|)Jp~(ͺǧ<{v`xb+1 S}ո}!!/IY ! d.aR .r^3$˒߷{`_U꿑O K`萤UXp쐧VyJW{ɣS3ڦ/$uXgNFY)L%kSBW*Z$:;*r]-\}q vɅ-׬P)Auq!FV5'XCV]5 [,h3XxϿ x9ZFPf ke)LjS8SR1f평lQʓzIޯ:+n=G1QN/'`M;1 U-N%dЖe6]I3x{hk߻ZNCʽ(y_ro |Ǐ`,^|_4Z9HsUx˩f ob/sqG(d}j3HNOsQx}< Ye ~Ы-U)9s'k&=5ɩWўJ /_[Ǚ)w(.]J˯߲mU8ed^-,G>L~IUd*YB5|(1EZv!OGǞ= 15,ϕ#dz%t/u@&L֞BykƸ *]5Vg;Ďsl<6d1ƷQ(QXpcXǡ8YÂ>g*[ܛ|];A8v/?:ACVQ#SWM'Oܯ:_0QVֆ +P]F)YY~6ξ"t c∶fB؃hFE A @u11p4 Vq AP:,C5: /ϝŌiP񧟢{n˗NFĉHtъͻ%3]ɿ"Iw3ݍydx>eNYt2Ñ} (eXtmsCVn>>LR޲X]u7nGq}IS+ **ϞE{O$:Vcu>~|"1Nz`B2zGbt j~F2oN2~Z+[ΣSI ᪟>Qh림sG%T\ \ftNS[$"I=;p\bb biTڸ/bbcuS X:sF9N\WKgb.ͧ_A1oWذq3w 0j9:uꤾU{|DCƍ- d #pt,ŵbRQ%ßO]S_GK֯DMTTx+Ptnތ%_jLQ׌r_R-r?v]GWV`ĹH Ol?R6M-M-شb.(VYFvD8 BmBy q4#&Jq 2 Yq^?YQ&믾qOg8{}lI¹K3=c.㚉|A+IL< Ջ J:zLQZS|oY5dhJol ̚v035?gI z _C~~!(TmX42lWw/oJG8cm2'z|LVUXe{vwfm!cmI-7';@⍛7koZzw-Mr<)LcfQt%Kʇ,kHa6_R2+#46c }><-PRY77x:uEWUIޞ/NVjsUJLZգWYe+({";~":t >[Qkׯw0T]eZ+ 1!j[(DÁτ,6F"sC='W *tVQQ4_*1d0f}g9=XXA2߮Ǥ:iƤ3W;"xKRى~~{+L!!Te۲M U)1rhe.[|%NZI9SHxTqŊhtE1g^رe+يp5BǐP*)ؼ2t9Rzpf?PUY?G/զ RO>yUtњ,f{zA"&Ͼ6d,\X_*MA}٦'~^G 7Upst/.vc;7z\%<ѢN>EKaiP̋tEUQ6q`~giv>%pprgLD\s):Y?MsG>:9)2,`Uu VjB?q?[VA,5z9P]saoڒ/\go* RoF232p ڭǯ׮;z1Q%TʞϪ'$m˱af8<2/}hOՍ'd^ذ0|ﷵJ+Ɇ!o ؿ*M"od$}*cUYHK5^ g*Jc#XQ3q+L!a3i ޾|Un ~덱lo~-LSM .?>**?ižTM-~ FT^=5z+O)240kKKfەlټޱ`!Y iӦqDk m1bH>p7n~h^N=:%"뗵($/ͫnޫWL%_Tj:DZ? +H\ctkGgxdH4e+}UW2(럛l儿?O6&&u}0X[xܗ :5Ln鎛ZZZ_ Țg:68N1QLK2H:x>CqaD(L}">VXJءC;4d(q=cǟ#i,+P).cƇ+jjAƭ„L&C;dHE-6)$s[F؋ 9XVm%4޺UUxEY {Zk@v^|1yj(ɣ1ٚEF/?R3^$(7醎u}Z%S=O}'{"ɢYDؽ.͐F2, 8>Hx (ؾ DIivsբjB+>C?Fak{SX~j,O@VIiɵua j:c k3.p rޒt*v/?G“*sO7xhjR$gJVP6P[ːzM&xA]D/[ 8w>/>idBƋUޥLVi$ǤԤS? H])ߥO?ߢ3+yĩ~ѿ_\&f8{ V5?G\&;uǰqJL6N- F0% ΘOJ 1OOJgv{yQ1g)fo&w//!5R9yVgcٔ3o DoQ3(2/=;"m3#P t: ]Vxc@H g1p ޕ${WM%~;B+輻GЭxy|.XޚZcG#39ι"!OPg|9} A9*S7 +Щ{t  SzHUY">^֧Y_́2Z`V?}xƷԜIqIxء]8 Gp$*F}͓JV3̺ǟ^,<||=zgXbOQxgqz@LV/o~B¹xxJ޸pݷ'͂3ǞK_E{FgrRm3οaजnffKAvP@Fn*1Vv5/7;пwfafL4)髝$_HHe~t:24У2%N?.dqzd6iFd@BZ˜`ay{4#0=d]ŝ:-)dS͂gavX%Wgٝ WIj?#r?l'NFa޼Oh}c2hQ7դ^nʑ{P:ƫO3'sS 4oV:MƚU+Qp/Xvr )OM1Ao|[G[^:{b^Ωo;شZ࿢ 1R$M3Tɦhjhj8|Ev8TGTGC72cS2 \ĩʾ`zJ:~:.!/*s`mR }eNz5| L9_e'cŋ/f6#>ѳsKap[8d)eu۷F|ƂFo2X|r!eG!7/vvY}v=r-F3 >2Ye_b1l]oQ0\łkDP@XyP F=qԁ 9 "^6]yZ9>P\Rg*hm0JnƵ3\iTJiKrJB54TrLmĨ"Iwz>TRRyV!((q?E_J pQM D=w /HGvlډ! CĞepiƷFWo?tҳ?,_E(>KM`'`Koy+Huťs&|>>z ^Tg3۬5M`j|oaεxp-~T;Xehvԛ),G! 9WG+YW%^@ǶA G}))}y?=F8J[[bؘ=U.21zbYGUtؐ8~~aW:|aORR_|`lw08 QvW6YJ)9>mhh%Ő)+|߅=My`~U_;Ѭ1pi<&۩Hmۆc] Bs-u11FM}~e ڲcͣ}p8nW3Npx4W;֡ψ ()-Ws]5f=LƝx ^{~ t ܽx]0kJ~r '㼃”W_`s\6Ʋc5d Ke/S[O 8ʴ"گk^lXj' [z_ ןOϠCG fLрyn'>|:PܟBvǏG*[ym_ehߛ~4 k ݨԔ-zR|9w.:oG|t6B$`X{l7_|IGFR*DF S]1a<7E;RÌmccyZn,u#s$+{a ,Vë&u_~j~VeErsMZ-o V; U>DM5kjhjhjH8}9I'@f>Y)QBdZk3v15҃f#뵬xDK1Xr 2?Oa%Zzaء5`| 89Ko.m(HYUI QTRd7wtn.rAXJv Kʱ7qJ- ofQ1?suBr% =eZPQ;idt֮)%)ILx tńDJJ42")+e r}|^ Uu7QdhC&j ~pQ8b/Ō;>rJVFGi[[OϸPW&do)M#UzMul7o~AN {dj UU5t%ٰvg"8d X7 iȥH/JƅcnuUM6|Ȳv%]I)SNV8GgG'y%Xr|+Th F*Woٍ1 Z^@$+`ɳ0Pi}jҒ{<s 0"ui !Y>\l{5uwG1h޳ca O*IoGʄΞŖ;PjJWA1Jes {-yvl4Gab "OH"]~^v_W_VDEt.?oSJК( lBj}_uB!,{4xp ) >lm/7|/;T[bX_?>{7AŻkU]3fΘ!+'bnM{ĕ!d+^XreN'66U#C *$eB RA.ItW}離}mOuK{EsUN^=nu [3&hy7[P-nLK< ]K``F^%Va_"yj 2vtW7ۖ6H9gbRB2rM |eXܙSH x5o#OvKAdC7̐2gto!ˢ\و?$vg;AAa3>f̜ ???|2"7b/o 1撺JU$sC{vĆ`y\r[T%:(kT}QbIJI%Be{lo--{w^E hktٺ]?bVO579^ޒ[zEb,=YBr;yBbw,*Fa=sVb3~ md{"91Aw2d,,%+32Mv̓QMpp(m/(F m1sghg­ V Q,Q@Shz_IM|{MtSPrb^Т<;E|M61gzyCȤVғg?&fRE< } )H%-ﭵ4ttïAb|9@uK=*G7MMGn-xI ,л콘/JH8hĔi0,:r/jK `on A\V<%6NZ6~muGQy ^,VydNୗ;9 N~AAI7eͫC拏jrys\7wXJw>eo?w.lOXZ!ٙ5\&u0"[y о8u 6>EE`_bSc>k Nv2lĵe\ @7i?əu]+{:0`faq-ٕb!HIJsMlz 5o?5s/8=1anjfMaEܙ_SO=v>~}hT 'M{8T7b:TQʜuCݥ,|ބ/s>vSؿe_eMNZ։@?2c =%v̝/JWP}6q T/vًw7?3! hu){H `U](6g"75GueydBy5e;}u ~d3XFدWh4P@VWM`K*5'.$ %q`Q:x'b 2+Ǟ{a) iO[^A׳5}ט_oAoW=]hic0l^X026f;5S7k/DÛ9l)Ǥ#e [[5kV:ǜݮM+a䫰Aua}9_yx/T?Դ߲wa>z{<(7FA„ &&KqY|g sg(~,U`6*J) 11R~WUIYZ/"*XIj-SHjj9-\! # 6f3O!:: >V,./۹S:TlRWOۈecO::ĸSQw]1Wx\~-nY hJ$:%!$Lȁh7l]+GJwubƠȝKS:wYΌyM3v{WD9.=@'Et(OfN`X@̞<yYhԲBCs3e[%FURR٘ >/R:)nWYb - 5៚&ؚi3aL4G >'*z+,.Οݫ*|+}mdCy@N/#^DiHUׄ0AtQOWqq#(A0o"뱥q n?5ҫo a`ei!pq^_Q+Y8u. XXbQRŋ6fRņW /W4SϿߧTAl=J:JMV:LEJa"Se+ֿ+s;Xr}]LVi+|jii>rry{cOY[{f[0WJtpdYx_uׯ}1;$ZX/,)l5g{; sf +})+nQO_~qS 6'9!#ai- 5>FXzeu($w,B%b!,\nXEIՅ~Od&Oя_)(7>`PN<Gl!Z_͢NSGzՊaʟk}3"lXf47p-hng]$DFp{9&Ca?b;qTX#1\Qё?G.ä/2w&e̽3rajs[?02FDLIA4hz0`MAZy:FegKNr[y "}@ 2K֭~[\ܯ(fЎzwW'7an4P۬M6v>>sŽRW}r8z]~=,1u\ߠSA`0` *E̙ml9M v,4rtt.hn_#SqaJjSҷl%;BCAḙ j)>ۘoDw@q;ߘ0mZز2}U`PI!qb^i+K甂DDn ;;G `$[6_|h˖ؿ ab`,I\KJRvOr%x](s9EHI㦃<7=Sу8PW28)oh`g+nrsXC"+;i3:Jy50虋i Qha{߱N M~YH$i☫ ry[W>_.{!0d폷;]s[JүlZ]v8BЮg E  L~:R ]m =Gbx)+BW61׆V}gb/b\F5]hEO@vnr ~>SW<պP߳n**"jCv*gSJP-nV`d2VB1d=Fd'Gs柒Mi`NsS-K Sh^0+) OEhs5 4TH@nI+V̴pE:p!SO߄ZPիĉ"K-jb57 ܇tzqZɆh:8ѾN^o&d>mf0//Z { XWh$1_dDImm&Z2״5NBهÆH (*J0d`堝⛣2)afb{QPX=>љƶuf=]lm4'<NΕgn4̓{U!Sd3kj]tI-{2 {~݀ttEDmzI!rz&[ݠH7W1)khO7OĊ4ĤPMT0zQO^C!FoHC V\ L=)gXOF  DBi=XW$[ėtO2ji,$1Mi Țe/<$G -}#>OX%EFV^#oz}=(_P>c"ĽP!>l'[P|+"{ucר ,@S1NX2;` %ä SNqW3BǎǗ˾&0?:ϝ=G) _&{CLr>x{bR L" xf";3f2v;vlU%R՗15%YM[Vz/ۊk^1[,^$K`^ #}aHֲ㡭7!sk}0ςCa_ʼn ({xȩ%;:XeF#SYFh/ f `7GFHy\C~mG7/̞+E󾱿(mۯ`=y) PP-ś/TQg"1M+>C[u&<@h+.l_{c6-1)|.ƜL,}z30%q7~-G eŷl AahdN5K'Oy1ޝ֖̃;]zD wl|i&?#;W}Ii[ƍ > *o/@Wn}l/6=IX$C{ś iJL`E{[Xμh 46֣$uZ1TpurD;[W}eP J&Hka ;?o UI2VUŠk[j dNqѷ Ursx/멺 R(oݏvUU.Ϯ'ES*Yy]dzp#XLR2q|" }9n}.n+:1 xe[`'y1CJQcR%ϡXyUv%t;LD>`.T@Kz}GG 'HYvc=Zrx 0ЪN2HgssBBJ.VK^m {4'S¿?%fW\гU0lXRW_c؈R4:wmC)lLRw(%bq_8q\b9; 6zn\j2vcZZS~NtffKXy_xL7ɬTfψ~BɘMDmMn>+wߵh2Qr˯cZm~ [=O|jWU,M,V#z-̖}f u棭@+EɘlE`p !D`"iSh5yHͫm /0i*?zì|Ӯ|=}2GT萭i";B `whO⮔k&rA+C.8!dKY3oe3y᱉hKX?`D!CP*Lfv>ήΐ[M\U9Yf9x4)bl +R[dfZ/@RwF:D.(kއ-'pbu4*RO[oGaA!,_}FXt.!%Ф#ؘAMm)W8(;76K~IVhO#l[|Ž?}~Y_|p֎—fl#' @&ɳJkK2į⍏cة!C('oƑ=0`Ynu5*ߦ@%1̭`CUҡuX PEϼ"M.&}0ȡA. 8|a&2BnI9.+XrQY;^c'a7?]_7'Uؓpۄig혧@.Δ^eT BԬ BV]<0%2|F q|ũ "& 01zGg_9ym JrawXu~Z^w*92Ȧ:߲e nJsj_,@IDAT媵HMJfM6vg0**VS塕 g|>ؾSg΂-02)϶_~"`Y 32h`n/g zE*r\6:pDae!8ǘ@8Mv U)@˅s0NKH8,$UPLb H@@hol[L0lu;'#\Xlr,lA֦6TO6 *H!֚F4N=F]p@k(eU-:vcA58_X[ZZpת^']sZy=&ġn^snנE@sTWs Q>zH@kϥz^Z}c{rcB+S/YS^ -0nڭ#]J6ѬKLSeY c"P`1~a<{x57V6JJ6"P5_(;qi2xa$5(srz!1 ]*PX TUo+J}=X.f_LhABjS-GZ`ŷ?Œ,M1Z`Hxyymٍw7lތ6̫LxhOsX&6 [ޯWۓDRn\QSqa7G\s+BYU]KIKU-)WL&)=F1hSSԖM%y(/$-umېD~J 0>#x'g3F߂},B:z(4U*RP0ʊJ1sd4VCAYપ&T+J7 i`k(^rk,0Ӎ!<6lG!܅L֙5qa+Hc",֞qt<[)l߹+*Aiq!sO!wJ--%U:?!I4 qMҚu#Ž*J f÷O0YdZK:@YɛbP{=%(MUK\Gnڑ%%#R8=*Ig ;:IX'(?H*S8[ xvӚZ_|V!Rڽ.ƶwkawKq+lް v?K s!5 6oksz<7wp72ѶG_p׃|hyaf._ACI?Z>vhf-Ŀ>xK}X^qt˒TT$r)oOr}慽Oߣ{P%:G3k|QOIv& s'Fi坛aHJ3>*) e,,Ms$3gq*̽w'WO݇|iiU RӲx-O@h :~︧ӱOoGؤp4ꁍ?/|)\U^JE M-m{ͭ1 SjF&* ưc }3+[qq1ގRT 667;|qI6as-Fg㾇F.;L1f$eLl*~\5Ӑ \XY / }54X )#H`V(Ce;Qz ŹX7|7(J%&ӳ1r4)K_Nxu_g9)^}9}/oT/[qu(\}d'o+ x}}Q}u嗟c9ر+e6,Qcvh"Xϔ smSdSEap8ߏI`"i8GMYnŽ*҉h&8S_)9lqwft|^A\߭Qŋ S' `տ$?{ FcF*'s gr xI676֢cmYIg_}1.}(˖-ӧ1 ,$)1hUV[Czc5f6w ސ(I9CzF|;}PH} ?`#qX! jU1Δ@1֔Vqlye)}P]߅EFB۪2_ L>PY>S"ٛ ,3`G*)4.VRC-pSAֿiLn (Q!(ʗa?H{S-P:mMyɩ;w@2 _.M##CYSq tS|L,{y[b:8S 8[lFFLk>c/A9Uelؿ^&K ;ȟ +m| ~2kr^'S e7<:* 9 Sk[`+۲LTV89 uTLocI3ϽHPO_zVjfdfKJ~^ٞ)̹^Y¤; T%*2p %9 EfYo/7e+7KN X_1/[j2cV%l $V/]s};ڽV$n=8\2TŘL8=c,'V&ή#E(匲;A0|P5l1&jE&@O .mB'R.!(؇FR11Ԁ62` Êͻ7- `Tc|÷JKY6>y!8p>_/3Q[Z+T[aA?Rz}$G.E /O 0d2A!mgH!.AJXU}苮 F8Jpn"6-9˨h٧n-TSOuW"3GZ; &|.9 mXYY`έ-x_ױ41٪qߺbVFԐɚ$n]L$WIW Ъju}bRT̙2@X>MV+zZAACjýBKVk-$*(y5ڑSTfi 1u^5/wHJS@Fz|sc*"b= u5Ujsp4E َFv(H<3±V~w͗Ņ,BJ2۠%p?( } [ϟ΂2cna1ֺlGfFҲ9(Cgp~3)x~֢}]$mEYSZmGP~71Zd 3U,0A#Nec܈RuQ8FǔFBPUm/T< .W-AjûпdlBcNϼERG\b`cދ 1БVts͖}l@;ٽ}܉gW'+xʤqD*&kegڤI(a!ֺ_yN+fZq}i3OZ0XO%*37ND>Go!㻒!r7bg"FL7zM?._r>ۈ| 7InGWb;~5h(4uR7N٥ nGkWb,q߄RWnt Aϧ>N 28fYs#U.-FAr*0`Gg7/,Eʜ<FZhjdv(,.C-e|{`NGƪo#W}o[JE%Y_tD2/e|/Zt!v״ p ceG2AsR/Zd3Ĝ}8{7:`deņd.F'w1}-<썋dE;bNt[ꪘfZ!d8VQ)#9B(VEDD^YEIvX \t%L y:[_3㒎S/*pqW:,6JmN&- I;A B̙}֧D]} .uqLjjrql G;k\Ldʬ+V1Ӊ}AUz\!ԖQN6{U)eLZom⏔ oia5 cBmS:ut Qj o!]DA8ԗ6_"zܪf}L̈́^r(A=1nu)Np>ܡJYkKΜ< LGms2+[44[L6pq4G\r.>=&8ΜOF1n`(2JQZ7e;A}<_tтu8bl-'"(?%G&w3cU. `>מ B);sgil*@y09 fՀ8yJ9^qЂ2vn@L>T`;*L(t/Ζ }o߈VQ Lbs)w0:𫥩s'Ub>5;I+u}}Ɍj+N&uwf9!Qބ;`OoL? !a`ԋ[}D)U|[1﹆&(E|ycӨ2PqI;>cTPx$ge!bEYF9f0^NcS2n `88K)(!RG9LshMf2CiO<~$-382'_|})L0zf߾2Ul7sO\v$[hA A@]8XaĐR ߶mF(s!gEqaPG*VS^xd1=TP_IUbê\*;+6A)_d"CF_<5)RC./eNN7q| dz ~R_'+H)ǽ$('Qѩq([4+*%@?ǓVqF_<D_-~֧o&X0MPH O0m JƝ1-AV\ `uN?'Ώ=8؟Bp ^ez2[k :ϲs֘QӱOaK;39yt= kpΔ]* ›ZWih5^WS€~^ވG|f`nI&d=}~LQ|84׶q Rj? q pR<ۄ1<\%U,K׭OX֋cz·vHҼri C"J Wڅ(*֫**]zW[@ S[@<^[<`azgP?[9W,dȀ4CL'L 2M1| 75 % b޹ s,ANU3jۘ{:G^8wAʷgK׭)?+L;RE (L)|jHw()-'U4W#5dlX!!<"HYM dFœz :pUkΔQI Л ["dZ葝Q&3G9PʾآĻ!=}?Y>`z)ąhhh;w{US$|4)q t^ <߭=SK=.ڭ<f2hor1̈QQCvM*3)g{E;s[{+n;NJEFsNą3arp#rJ)coUhs+Pl3ˇm›G7Vyz3jXK#)%9W(MkI2yd0/_oף^8DL33(8r#(#V:R~@Fwߏ'I 4-_RyS%M2CMHKK'w^O*Va $ՊӍ03:3 t 5v` T˯-Ł1`[4(} bXwR?)鵘`o g|IUp$5 桰{g 8B/̯ȭ$[T B^$Ig+ ,2ȎqprCȀҷ\ ؿX||&vMU\θe\]ں:i#*s^" Cx?5Nkw`aڇ)||T5a;\>V2HWHL+!up褁&Nka`}RV> pHr UTw͍,P/ɿWA~.s 3gֵ(xӲBL>2lWX {ߐ1rюog>JNsKұgدFYq^.QُOwTp]ծ`sUUPZ'svsgtfTCC%smK` YWo9ic)%ν JdnexOIWYmXg\B{n `nwo!/OBƔ q@N.\TZ!?B_/K pjQƾ[<b5 >nl]}.+{ /$ЙD3a=mGMY1N9^>8z,)䲿st%IFȱcBmmŐ:TX!0+^*.X^G]`A]N^{1gc%֘scؑAIek~P 1߅E{Kf]?_aҷ܂̍sF&^9Vba BJ@1G޵#c˟?>RYo /6XBN}&<yc9}f<*Ȏ *ep`zU{&n6 `T4 JIw76u m&RiőGY@3TRe Y7=\/XEw2c舑R:u{lmz6eepRYk^[ѯw;XU8֑M4GFT')Xx%7P>Xj~XU3Q."bR-pPWnd茛!% oB)&pR7y[#Va DG9 A*U)Z>>ndN"E(94a$QT x{1~8^% v/ٱ{w cg9턓Qgb\e8yAtr1? Aᛕ)Ni:Ğ?Ipdiѡg.z VaDu6g4.r2\+(bCȱ/H&:hv*\aS&8I 7鬅2q4k2Df&4H71RgΝp lg=BpA_f5NfXɐz7G0g£/c]rX8\}$bOΞ-\5?}02G i166{ヌ?@F.&L,toP>dS܁`"€RV۶߶Kc:d'? aNp=䅷a=2iٓp2PVR8: ﵰ E?n#/@8DD:BVdhU2dEБur+Ec踩rJL|Tbyՠ n5CKacnG] `$ #{A ', 9SF;6 FXzpԈ#.!.UeArSpbng}f6Ml̈r.07~M-jHg2Qw3嗕LOT]V| +vYw=1L>d|ϩnPVdx"sKXrj,݇+f-d'A% o#wͧt"Y&`g|ꦈ&}-r9JsӡІP_ 7܍,sd2/c3Peo@,ƪ|V$$BTr;yܨx'zjd"Pc1N~ ~X؇##]v|X@S4Rl+_ UpiXyy82@ Vז#3/6n˗#Y~=fΙ cJ[1J2*vُ)b|=Q'0e\ru,?M`Bd]#A00w!VK2蹢 \tfsӃҹUA/. o(+Uc_DEAva#Q?lCRA3رcRN[xiu2sFJ4A}acaQ6`;1H"Cs"qĺrrwXww!>2C7}ԇ^RI74#M\=8`\ޙU_cE+ɍYL)HbNJrMYeXa@h?滽&J+l Mf@ay=2\*=\[6m`܆vJ`C$AnT_⺭d(%qy}p#SL cZp kA ?[^8g 8p |0rDs<6dVttT6Gm4Ν܇ 4=,ۼi=( .=cxJ<֐[r"c&U=ǞyH1npHXF&!+ ]x]Q..$ږ-u}W}u7ԠJw@ ! ąp=7WF̜{̙Z˖%8ȝ;v:BWk(/*)9~&\vRҺSEݦVސN (҆2w.)NX\k ,Uw% "j+.nEƙLa}+MUdbÖ m4#&hIؼb-;r]@6'2\eI楜'- 56@dYux^m𞩓f;LgSZs/SUW@J$sFA5 TXin&v]UW6+V^=I@ VFZ֩^wXY1z21/mWB};`N6܀ ms=3\jEn]/moW`m! n *ytŸI9hĉ>? x͗FXؙc=O0) EpTwǘ[+7*={HΥ"%-]ʯg;@ZSrRz&[y?5xrNaƜ0Rhl>ՒI@W*C]H>a#lτ}~l#̙6OP:7:`˯ /ډxtDIy1?{cִ xg׈?˻V}r~ޣ )ExA }ARlJvnX3 2399 e3jN=T1aJ|[2( ZGz3AEf"Rncb a!^>n:.ڳWodQ+}r1qR̿"ʜ !@cIpy}ˢe9Yd7D-L'&Ţ2Y #ځoH__Fܙ(8{bptK ξJ=cԘqpՐi4 ^g&k/wQ:@}Gi#,4ظi}M/N[gWe 0nGOD!n~B9̴S[_~ odH2r2eɬ򆹵I &E_",d[ѝv L`-)72L0ӳ}M_d!,_  ʲ=$U٫W2)QMU37'l?{1k:}v`pߑ-%їR;{+ p1h5gу1oL)Xƪ %epf9P-An9ki1x,܋jKǎӲoþmk1[@Vŗwc{Ǯd~/[ΐ@2U.VD*wPnv)8!uWrYv" mGJ7ڬp0y3Ȫ2nk1SǶl؄ *3.)[֕}HF&@nHVD :L'dRD?6ur)dWס{FFX 5CCL4$#۠bJ־%`H0?z73j=OÃ6 !!n4meMA&1T(# 5dZhZ9~jxVV"qϝ8J{#πVUO<m߲_Ok&ь=mP>yU ww.aZ /dyݿ IJ +5cN2i&zA2I u,ﵯer8654KW9T|j91u pߌ$|dbߚr5T.7 4cd΢>3oX@ߒ{KJ 2)bY7΃AxDC)ǝyQO}z{)nZ?(w<} gl,nFwT9%ț$*VDFpPHvE@-jZEElwx'L7O:㓇o`]e։,WmZivҟ Ǥ<ɤ/ҥr0je%SN;T*DǩXWZ~A 6=~6җAvFuc'Kb$($" |lK]E"\,B/(q~g>?Jx-[69b^Dmړb"L+,RU>q낭%^z"} Odܘ*E%kEdEз-{Z`A nu۱{ =!vqm ś7nLEa=|D05+ An,qt >[?)f@l;"c{LF 7s;c۸1 0g6QM)Α9I:x1nÀIz0`{Lz(O}UYݍR^{5 Z `"c.mlN|-m1>0ol SS'ޞl6mCi`;bؼn9zt J^Ȉ `]86ʑtD9ރ;6 ̟s zm ΘQSu# Ⱦdcw"CϽݻ/<8kݙ5t|e;.%Ks[lp69C2=C q/mؚGEں(݇~k^ qIH}.0pRAP'U}seXǜ=d#@h\Pks6G ?W^D8|H#)*0w62/%zl-m zRhd1=uD¤fzt6${ϖ~܅C#%)0UGOCAN*B{ ͿghLi2_VZ-;];#cOg"% cnA(eZ6_'X'yg17 [J`?8~-څ$H2]>]q! YkaFqkd"l!@O9 Po%=ۚ pC?e5?<}&:w&!L*L^i!Cݕ MK~E͜1 L2gbW%?ÔN:bE)ϫcܺ~+^S".*!wRG/&xxŽI]Lͩ|.! 09eJ=^3(S>Z3Q v(; >8-\pܓ \.psU&XZr=Em[*=EXe\תoou*8X(/cYIu-M3-|GȎ[Tر|\<ҋvwNzC 7e3l0N8j&f%&\_>A녍mbnLebܗ_o}wgG-8R݉V!cz&0<]V]GƜ(~lnܨ'~F@wL.unUю >k*12W^`r|-} [@II'60$Ҫ~з-7k0?-"L_+g&!?));A&n1Rs=gG Ep$c2SFPXN9'Rء3 DBaAC$3 <AAN/e Ss[ʽbk9%s1x6(*L 1 ES3w&?K+?cD qs̝;2U=.#6mތ:^x*x6 eRRs`2621cݘ;NĞQ}%)=o AzeƔP@?##E6o/L&O V=L;2kCq Z>q%w#<0rX vbO] !Ed El ,p6);#Нg҂ :vxw;dn^jkutr~)_sPXk3gcH8C֒wAzFcE-U\Gdva6 gڲNSt?d[7̬ .6 G 5;G,X!@d;;xE?Af?&Vp!6f|eG2RmϿ;wOi‚622}Fw5g0̢Y+;h:/5/_ [!$YfV%x$_¦u된ƍ{y "{D 3ϣ!5"eq!7'FʹT;w& (QZNc̨ a`3 X忞Cf%j)ẛI4x!A~2/#bh8V%(!ѨєME6W**SwUCZyuV̸aFKU2֗"ѫ;ޗkN{|w c<>6 5kC;$30}r*W,vdZpcxo wk TuaR2{q.TDrlͅoRC hc/.\d&[h&zQvmdE^|a̿Ɗx'ӑSäg+dЮ8S?: ln"_TT{`J z|5?R߳s+NHLP1CSS,]чl gږQFa Ҏv-#"q?~ LPRZ@FG'"+=QLnI8eQ^?wmd"g~{ԱЋff2-D;_e:t̖c0#= gXMO=ࠣcb,CeLK_zW(fSZu`LrXwnYE&eݏb`*v-M G%nfWT?r rkҙ <oR7Eiy9(Z6LF+xͻ\h@ BXeŋ*uxܷTzmwu"ŠVk{K{EU]U֑>xctmk;?۽0&gRYb~>>ރQ2/cu^z]+4LnFpZ>:Ч-6oلg$IV~ЧZQшvFȽTMl?{4b!*;|l/]SEExL ej=&Y `,jf[ۑO[@~]Rw-j,{з-p9azG4w|5xao=2*Ά K-Ė,U$؍ӧI_ވ[A)Yؔ$0w8s=>,C Ȧj8JgRYe7E2Nġ3'E8n4`JŜNDl)<_EeϿw%RuEy6]9_O!}gض~g墫O0)38}x; AFrn{J?&@u;']'l+od`܄`K@N]~yo&{RkaPAU-2N!wW{DzVL" ;WX3)@vz10YZۄWlqsnYܾO6,g*b ]'hSZWc-@sA7SK2s~{+ǘ($C[xX*w$CSP&aŵpro A?+(,;%_yn/6 rӐ2cpҕ֚RD_SgW+mєz5&KJJ'eruPyHv'QF7a2Yz`/3qxG2$Κ"z=SCC3}8CP)So#1,'S+QQ:[-g6ڶ䶽1a5Ƨ%qtprVG}9zL_W>@]?0ӗ}Yid/#7>B1cqR[n) s"Ԃ MQѲ^ IPWeM2-M hYCUс{Ȫ'hzA+IHWXu*6:xj4e ; ~뒸_U2,MЙC9A42l,ʙ|ڹa}kgӅغs#_y2 Ƿwj5-,5].ʡ(EXk;Yn3ig0܇n)}GU{{?c6*]n̙0!E[QdDRXW~VVYOI6#/è#?BxPYt #SyQWe`炀naʻ2W^P-W ?+(hGӾ 0)҆ziY*7w97LdBR&RO@AEߋ]aEؕrxvܹ ѧSɔ, *X񾑄/!5VN:cAҵ%an`=hjkd)[Z'_ wSVĈA *C1lXܾmtKH3=\ØQXoukUV;|p.r9v>kTE_}U2q:ycTJA[n}Cډ7aFFRbΧ&äYwbhL>_c׊ґ#LɁgxǵJX2i`$kL3᡽dӖRHՏWxZ9vd֬Xp55aT?%R.ړm(PZUM Br^ac;QUN}.fxT`z>zSF9#53S$;”rϫ~\CXWĝGˊ֯R# )z<&r7=< O'xv JEyʤꆮ Z"Ig"+ȶjbRA);)b=N*޼v'b`˜%fL [wƬYspwο^Ow^~ZTBy |Bu"2[Ņׯ/ 6:?`v_|f&G!%1ϻ4z$Ėەkcw,GGwFDJQ7<==pmS( ѧ/ 0xe}O0xM}sv@^ WWq6EvA1 -4w3 Ng/Sy_;W&t2܅u/:O&2IPIQAIDZ䙠~3\ 8gi-Hԭ22]5#ސdrǫ ^;nqB@Uiy]mkԃJ溦}vw0< \adh7K"3UeG >d }>}vހ<Ʃ3m{NdM#>ث{Y"$SÒ+WdwsuP5,kYi˦&HJ@$ T-t& ;IoD{%;+t}p@ZD[~ `ݾc-rؖ mulJ9|0| O|{K#tp8"o?\B0f\Ӄ5l,jꨘ TtJK)\ "S'C=IňQ95;h PP k܄>* JR&Kd#\Đ30Kj9L$1Z!}.8&'}#5>H'g#wϼ ;x2R]y~hTqL i f@%+'(zy8kQꉨA۶\YSQأG'aŒKlYu[f^\:bdZlغ?DKD-?[ Xy P^1o n-vCƦfxÏ0̨Uleb *&ϸw^oY 9.ʗ"}c/rЂ\& `ZV w d#[׮"I#rOR{0sK*?‚lyٛT)/_ *MsO)ÏO={c'/0ifOeXw FJ0K_ʔ߂7!ȿ\ `խKalU?mbUe(\Du+6XoNbD7"m/<$Ru]Gx3\}RE5<ڱ R#HV}e-2ɒ޸؟} [@dK*E]S_*(^ [TVrRLWi\} [@\ UXX_})Ի@dF5;ʜ\|on|K-YE ԗw0%-+ol1vDt!#n䠲ZAtRN:ć_OcHɳdԌRdi= 7LW9axe+VS꾖\/d֪ O(F}ʺ|WH4b`7K22M,|JZׯlQmCOO8{GiY4q%S|+ꋸ曑v\̆fLnA&%Z ڼfĴXu\yVXTB/ S"Oを@ lrLܯ+}d&Ȉs'=C)t E ~"":*o.n{2ܼя"Wz^d$ca6q4 Qb} E+~H9 ^x:sC{}XI&XeXg\YׄO<#Bɧ6)dFxٽA2] \=^uO? d$@CP=b(][m W~FgToj1ND+H>{:KڠNQǷ*k~K@J*?KM`!a3GG&E+0{k wxZ%8Y嗽k⨱63eB2 Lş"޴u6@W?p3fp@ LtaսRȤpJC/8W=BagWr|]$C2%,3Sѣ"mkBF6RX{MOބ>ڀ$,]3fÞQ$%|EjkkOѾUST p{n߭Q 끬trBTJҗÚǐ3|v/F0}F wܱ+KJD'^(aRF SOgHf4x-1UeڈVǧ~ټa1 eĬ%I{zz],8WQ -+gw wJws/jcG,6!v֝GՇ_^R"@t[KKclo{I2\+ gk,hh^=`_tYbޟee@ic~Ͼ]egqK8iYSHe}XD53 N5)R*Ș TpQ*zdRZR9񫱱:Wwm𼉀|/yM `2LHbL[L8zVNE궢sXPg[l+&UkqUPeQ|l/^6N9/U3ᅫAc^kIg/1cM&2^V\ZO;lyxI@z鋥ظpLDu|.Iev0Ta62&Վq9ڢ:!"ߛ$OM0Ŷeʎ&ce)WԷߦ _SI)Y&.tH_.ԠIeqPo8/?} [@*"Iv/%Yd@Jujo+4l)xU_}]jDsm?yYH۱[cеp$%CuQ.L=y,bs3$:RR LHg7<P7*8 j0@ѽDZJ$eeR ȺSGY)',a=CWػ"4&MT̿m.WS@ȎaY^!>5ylaR6 }㉍>7ވ5W\);)%gMڏyCFGYֺywdhD䓰mj(;K>E Z[v2]wލ GѲo GFREEquuA w̞+`,6Mz޾/(;y; ̢dt8GXO y+ aM~:'09'd]k$Φh@ˁV(OKMチG#F>v] P]:J:DM$&̿x6L= -r\IcN|sկ=xj^-u\ `dcGLnYw} [5dca 6~d9+fP{kTQE;t$>{ RBF*|12o>!/|`)5tƮc)(MT2FJv>>d!^zQؒY&,jJu牟.C)#{zv587J aXX `1H8jy%gXOֵC 766k6LLAdf)+^RǠ!X O,*@L .M``}mG(R_.=ze[{'cQ`T]IK{TVF].uV/j% *`5#;5[VzR͛" 9h2s MSo}uD yёz!Ov@H!֥Gp9]pmMYFP%+]Uγb^ZR&ںڑaq ܛC4mVYTT~GNH\R>%qc+L:pY5ӧ?Hy=Ɠmx[o&8C LħJvRjK~ ;~L9j7ʧł׶2}bac&("O#-n+o'W`%U8-1eJo\#B([?zHZ;k4q 1i8&3x^/JjS~@U-֘ 'g_-洄T?#+'aΎJhXAJ+++R;0oҍԽL"ń}zd&娷wF0'(`qSWODڟ~@UpՀc3sVMA׊~O>D WhAB9CpU$aa~uڛ',E[ϘWY߇Yvשo} 3v̽drl8t-!w*~;|k|HLa8R0Fq5DŇ`Z $9 /ev8Z*+K OXXt?Hg"KpZ.>ܴGʾ^j mLPZR Kk6+uj ~ᘟdspyrϒȑoչ*˦LY|PWr8ć/mAaƀE2djm1l۾w{쉮lFJ*%A:RRwRQ\o܈^}MXuSOoyR3"̤l1~Pٟ~,qa^kyL⋺kYȯ]^GYGwyοLD7 l߰IńၔW'i5) "ȔIJM͂lHWOfHzU{_:E݉nS3Ε?R)ש.*;q(A__M/ƛϞ`U"GƵ(8~,{Z9.֍`[ `Ⱦ %SYp, M52ӾrknMN:F?6# ==ppoMu;R,9A'ʩ{( 3Q {?وux|.k)7wr|ꋴzx?TUz|Qͬ)9Rԩ*=g>y da˚jW9S)=peZ凅Sh=~,hБ2rz6gÝ]SU%2Kp+Dq*Kעx =SS&K7EN֓ ֬ D=P>\.[=ǟ8zүވ,YC7]?/>τ3K4V&$x܇-`tAVK&DgVُ <ȃdAyl_"XUXvA>Ǐ ֯ڟ` [ۍLooKX.Nr)vʷixXR)JMH©9qlxpLvrǗ< 5",`QkP؁~Ɲغg;ns~-9vb'މs|Ħ^ AM{DPh[GyFQ, oq*ͭwN{e9 t-}<{3:~l{f$ɑ* Kmk0a񰼫}>9񋔴+ܜVXEaɩ7rr} [Ѓ:We{ae5#A? HFJ/oY{OSQ5v|X9()z%Z*A* GKA{¾[# Hx$rT46Xg^~7̞C Ί@6g7N+K2'kKxt)w/e|`G. I'_n_FU+}5;'Kd5b(yh }G;a@'W$즇h1zf?c+sCY9g1lTu҄񺋕gb#)?lQG(gg^LN,[|_sSR`2i|T>|R N}@=-l8S s3 0S ӻ?'MduJX$`S >55;b/P/dff`KKFfgu1/ed^kȺ%L7K32́qs`9}E2i7/LI+;zt9rD`Uxt`>s}0ش}+.g _}Ha>#GVKuj̳7dQu#h[VQ{̷"K"Y ^{ :A+I_%`EВ qױ0kHtظ~ ɸ$t aZl,cfF:&DU>|mv+%;oqv5qO@JJ]gfv;L&ogw'+6.$DČ7Љyyg1ʒ;VپcC)= xc3QLоriUuIOA2 H+݆dj-7bPG! |.%8>~ h_+vs#Qt&" iAzy&uny{FwZ'hFL1FJon†!heJ]/Jʈ3[xxD nJ|Ji?k};Z]}ү Ө1qʎLp&0_ 0 cŲ~B^i{7_g&erCQ\Vg)/ cFnt)E C=+&O8YL0=6,$9lLwG?K[L8ٳm⫅>݂ae)'vrd ^oZRW"1z7>m J$gv3&gbDkg/t#K$#td?{\aynGϤ4) VX Μ"g̤@@O\JgDB^;,N *󶄄Tz`u#p Ego2x2:F]ֲOʋ5q!M&6SaƤ޴pRV]fuY2[Sـ[¡Hx{S1߯ہ~E~Fl/>rRA޽{R]5*X!Ep:ՊU1~@r%,&k1 LD$Qk-eTg"OgFv6=0׋iѓ.J1XWlXZzj߫;~lKh;]3Ld>Ғ&WGSWWdd$ыg5y2iZίJӳZ[z A%+X%Gee?-oZ`d?+2kOdVbu"#`c3^0C`U?sZ IHXM #6P|@IDATWߢ;h@h~2[#ғZ֓ F(dk"Nz.faǖ h]¿ŭ߭؃qQkHD: A>e3gar(i 瀋:=WR l^m胓M4K >&:*;;5A9aC~˰s%&rM[8Bi3Uw='Xy%ٴUQu2OU g]Y5p&t&ѽVj̒r L4{^EuWMsH$$tBUR]+CłHJN%^I_g./}ܹ3gfΔs^{mg;z ;=HcD!+LTkLI.R S¤3yJ>6"il=|&eG?1U[RSN Xv41*eگ/Ԡ^ sCO2%T-73Ub\8ӖBaQ܎Cw^$kמf~/;;5 <*1k5Њ)\\.hڻWde󟂾y wO4~ 4uzg1B=sY ^';GJϸcҿ^=){VՕP6 XWq&vbnH:yH'KD6˫%_}sbF@4 SZ:0Н`~[52X,%8w H,2YA5%ځs٫c?w2G0y֛o }zv ѵ9bLGD姟] 'i; {RZX2֯=(o`?jg)a@+QT2RKsp֞N^:(Z?:t* Zz}w7p߬Lmt)9>CQWJtDg |) k V 5`ѯѳ6yA >0Fo?ظ8DiT#J:92uy1ѩdNG~@:wR*߬X̜l/Sa_~q6^Z%#0u ޻t!v^nd;Rygh‡1gq>||z(D;K# PPQܒZ }ڀt IS@iA!Gl(~K'(շp,Lg&}[`hf}lr4 ?\ڧ>%IϪl ]B\s@vaY1&FU0ZJm~ O/f& fhu[kp@ gDZ3Hkq9 laAUl.d0%e0fR5VW>&1Ly~sq4.Mn[ӈb[< [ځE94!#O`ʔ{ }1Ϥ))b+e9qv8$icdgMq ߵ'LAi ,uP޻ϯAU[ >nȉĀєZOr؄idCߜx'fQ->l{ue*8>־"A.3g.o>'tk{aGпʙKGA\J]ģ>~~{(KeAv*P,0m"Jpg?'mCat1';%]a\ʏ`c.%njc:->.~^s")d6tO3I:y`X9 `Eua}b31-VلYؑr!Y}nw܆_}  i.%[B?36~5T;mMG7? 妢\Gt L%)g^eA3#HHUK9 Lg< MЛBè7~ƶ'`vIc\{dnj+\VW| #/53H mS SuV+KDeD72=;Da6^/;-+g2];hL4ja3k. [2K54+hj(5H@%Ia@W) @`HKB!g~.]8}EOR>'K膌cXf7 2x픲)f"!9u('kTv(.}3{ΜU;)|RL9cƎ\po,Vxw. sF:udTHls){ĜPD(Y[A<[e em͂BuD#9#qiջ;O#\҇2`M?']ݍh: M6WBna!~-P\X=lS^zuWS,Nj| nFo=:ZO-JpW ԯ^Vl[}gs횛"v?ܢ* pz ƒ'7$# #&NǕLJ CLZ2护c#B8:3?%W1Ͱ[,/ 3 0Om7c-G#>$Nw+E}+`z*R?-)W}MFmT%rXj6AeyvdwI-i3pcţԾS!&;$E~NBtxvoo#AĐ曯OG~0¾sh)E߽Nd S;K; [s#4Rb^pTw>sS=mHN~5UT؏sT 8}8 RoU%)Æ2M]9xy#(>y8GV:wn 5:{FkB@>Sj\([|dۂ%lw˘'TBV)az5K9xd>dG٥ңoǍaҥ;ekMRIdIb#x'FpLרakXt&Um/` |t4̮7NZrPʰrEKliu<+Uu$ޝ-;oZZ[)=}{2'Ѯ im[HpUXU)(,ŲO>Jh8΁j9 9;;۫(bY/|a䇙ÆV ?z O"[rRREUW7wբ:EߤaNx2kSQ1N`' #/*[/DO닏(G ?jxi0gϠʊ0q|c!L=>kGL9GMOrl?Zz{u =j@ =,nDcfeWS׀25qk֮Ʃ"Yܷ?tEE_,)Gcݏ3~J2=%W)bYjg9h'1gwmJ].0w.ndm<7ȂLĹD%C~` +m۶2[ /c3hpl#sXB޾W۹u=.\ND}rUT!sSdM כ:x665U>oy3@ǽMd8OI,}90s+)9nofs_X.m3IɅ6]fOdk5Ow`Jby(>DBk"HGbRPE0hEaCC-peRZ-{ ~`Ȑaͭv0?.K.)W5C,s L{5 Ŋ/d|HǧX-|laz)Z(ewn'+K_ӯ&&>rFeѳh.a8#X8xÜZK4anЄ f_t (OF%ޣ&pZD2Jaࠡظ;tCdc>4Ey/LKat<ϟmdv V50y*2P6ծcޡ +68|7>Dlݹ OŌ{fH%Y1 ˬDid[Ǔcb fX~Z3+]Hڷ?v(&θ^t+z]0JpH0Qbx+AVr|ŧHKuɓ.:>a7GcHrJ .yp5T0`קe\_yxswW’ ~X@&X/deFYJ#9A9&FV =yVX.HN|SG7NPn5eP= ikn47VJ2!f{^!mX }+Y,)dLe9[wK?bb#Nc!OߩrJrOIRȋ&2Hq\TȱH̴]cP~XwuJ3SЍٸ45$kI9{ ?c'$ 8Dx!#soVTPUQ׀5u⹨Y]vxuÐaC\],MbС؍LD1ع7nYSZdfx2)‚Zq|- R'kʘaS÷,%3R")cA%e)O',>ejq/sZiiiȫkjX֯N+{}&P+sLr{Sx Ll޲ d:Qݲ0}8h)B,s%gejOg!3Iv뾹 `?mJ*gՙ@U/*4lL)}FC MF⥳ho,&xֵ@:c*R{m#ʜDLx7_DC4-2߬=hZ KKcimmC' ^gk`!5VƸ0yIBvn6& s 5ܦy#\%b;s=;8#-1!=|)>"h<aCG251ed?[".DHEӱj5jqxN|姨ihA4B РĠN & 19{Nxۚ1r 8-w BvRʖ@)-FJ9G}c9`=N˘Gg!egݻxWֶv_WwS+q(s$d1E?!Zp%GN_@\+_ .%XcjLV++#S$_c@<" ٘>}6 |ZiŕdF]nÔQ5_<ugFY" Kݭac&`ƃK4 X8؉N|"&xqǞGIOK";-R گ (ݼVi3MOyu Z?M؉Rǖ 0կ7(PUOK` h"cQ3W@PMqCR #0=8eaڽw|!3/ &s@/8=}w筇 `c0YK~RM=p]!~TSwy =UO6U@+baZ| ZcfwӵD*H LXKU(f\[Q9:~9OD3(@D9۳[Pmȣ76.Cs\tX4 iJ;p9< PӀLvsSk2kJl~sϣ -K+K  saE4̚~?ێ%.g.f`PBJe$wlQ@q Cٙ 1fDJ libAfi0Yvg3oX=0!L^.>z!*'h%Љ]B jH*.ېLI?Z1f>$´w|:e G[‮53Fwћ0YQ4tz;)7GPB^Bq >^b~/tRFEA,a cy#{ aDF=d@{G"uquCV:ESѳwd$b!d(yRQ3f>..S9VD|PdUb|"#}In[cPU #6u6\\"lA6+eU썠04A %VsvA;{1Yuu*Ρo>NGFU+K%BL5g\\o+^p pjIVhVbYd/䫽"oYLpC^8SQX0ɠI/OOaۖ(#hL,VoCIiPA8w(Ν GCWA~.^c!<(a(O{xxxu=z0WlO,\;~6z Ev6YB-]FFZ+>s0a VEAo/CP; a^2qߨI^D(Af FV̀oP_^M *_w .UϿ6^zm<қ&|+q1"ub6r PZ.~U ai~ IR\\y=?թ寝nw ѩZ5M%3\1v˜,ޔk[dW[Dg@>9'44?깗Гjʯ8ܜr!\Z*NeeͲz3)][ۄ##*rE`1s[1f|{(\J'qRNόFqBU6GfOOėx{0>] ۲"EE˓;ytk? YyGT@[W#VPA~jߨo,w +&f'9nKx{;7zWә?/ sz+;;8PEu;')7}."&~+٪JV_P~ gۤ8.9;*&mR_Nb~ 7# f K2xޟJanB<4Ac'Cm_vr]]wD#dek%juk(elkyzu o׀YIϺ+)־F?y\ZNe%ljSEb/S.k=C6f39ڷNhbBc: (A۟ }_K); VdZ&ǟG!UT ^]q^pȾP=LVHLّ̈́J?Q_|-b¹˸ᄍG&LnŘyOz%^]Qy5fWW_~ #K+H`IO'@zH#Ӳ S":Mбpj qR* #JR7%y+T^mz 'mA^^  QATއL]~|xt$+n =}> v/ٽ6̽OyT+g ~.%88w gc^z<+n@X?PL٩aCc{QV^"FN,sEK-{7;o@n6CH(|Fܵaބ#cp4V! ajǮ:bG0عIђ8 Bä Ž8+KR2K&(?}?IǐUڿx64o[nhh/k38 )}`vץKܝ~x>Ξ"W..=+".Td?Ģf]ːK>kQR$NœCiH(s8\玼\tvǥmp\mCH4}AekMo7$ )z2qFj:MƌCvp({IJF A|AMM9Q4|=d<Ҡ Q1dD=O}ѓu[vūj2taMNcc3Fb.X'm0vfB^^|E8tH>X@ޯ|ldOE@ df_mӂ؀>z9vdM{Ȟxds R0Yg}r]IHI@5`.(n×asƓЪA8< شqΔ~? @l"[;b tbAXG@ՒSF`x_C|9AXm;Kʀܷ[NQ]mc4=@:`.X7D92 1L:!Z5?RpmXJZ-6e<20k ػ,Aȋ6>=@YU۲JB0̰_y16EnV&¾ƫh@V 9182CGSCԜ2A5b SO D8 ]b] 1BtI={6Գ&}\δ0Jfa$wqROK+VH f܃#sg.\j(] J6teZJ]!7#.!'u?!.1 EU8rꍊ OO' 3E8|yOL9yr62o嗻 >& =Ocr!6dlz28Ql{0+Ϸ V0Z.'">% QgA| Qvj x K;NF?w J/ Ք+uܫ8>Gfs9J*LyRG3vQ ыb!/LԵCK<:Q^Sե7xj|~0}x7m=i.Ɍ!84L ~4pRր)\驓G#_r픞Li_z{)羔I_Bb^G &EnMJ?z:u2w>.MG41+4pe}>my|,/L||ن3'xʏwqCؘI1n 1詭V&ZV;rD֮tvݖ < 1']w.i͎=^SNvn{>35e%L|pE^` s*د1Fmm+j+%=zceX_7Bb0oZ6tYccш M2\&C3DŽH-9eܙ=+'/6}UY釖mxF}a/J6g_S)Cؖ}ߴPրd^T)gk@n]?z$Y(4aʆU8j9n̙[9D"5Gz{u k@ԀowşAMU3/Lj(Ō*Õ,vgL#2St;+%t$NmFE/hڭȳ>i.VyZ/< M+l!HA&Lɜ41GJ^) nc01w?l @V)M Z%ǝ]EALd4um`܋~x7ޮ oN8)\`/'m(YI aOz7y9"Fȣsf[=j[#=] !Pz!<{WDˮ-rtV"I1 GO[e2Vڅ#G"E%%d0IL7 &'Ģ' /&LgV'LF57bh?~c&NBzN!sj梌8|0'|VX.2{ڴi,: #vcAq(%G@1Rx +PVQBdj: "Cv/e˖aܸqҭQۤ6Z)^䤖V@8ּ4ߎiB*χA=|}&9 dO=(j 4'\6&J${ΖkQ|:uhЇoW1kkD SA @HOC;Y}}QmFy&>\Y ѣ{mÏ?|!0 Q!_02k"6&c Y_JZn ZVv &סĄ3B eJ FQ|8s(5VZUdkSU[ׁ ArL̐?Ka=3VڀtLQF"cdg>w M[Vz8sN^ [Sٳ#6[{v deY0ep5hbyzDBn3j{Y7;Ĝ3T:vE^|uE8{T<:IM,eؾ{/ҽg{f{CFgoq wusX5doũ?GMĈ#B J܁ R+2Ȟc U~ SCZz/q:;Ľ"N_| u`OWoYcpswt}/DG]B+[α>;F3n* ~ S_ա$oNJPcGyݼ,ݺwZkz+ǵ-i0)gp`mkKs3AlR:Wc06C!|c| *VOUW>0Eu3$ݖ )GmP׀jNVqcawk+NGv{?6nDˀh1QjmoA6)8T]mji)aϨ]ZXO Nwʹ$s; qퟧzMu ]k@ ]c5 -1;  (K|D#)ٻK ^_%_P JuXtv^-)ž]{ FEd [Iet۴l=SyY?}.{n1Aj 6RY]oʮ NAF !mu ?S&DRrp֟ T@alA(` \| Ѝg.i6z)|M?(sbdy| dXu(/c 1{r;At:V~{Yi]2tF.zm]8##V@d9@-<?ımW(> }37Ե#ƒ͹vFdV^J,6o}[{sMzd ݩ,z>A֭\l3MMAtE 0u8#/ d> Yz l%XYq,2kA7&5)6}zug WM/i؂LuM iq> ?^ S{f[НCzݵ@{ֱ+`YŅxwdzh}\ɑb^*/%I8do1S:zRZ,)R2FnV7t|Ղn1_/A,zd,,cl<')O7r`C!!lL6蓏;U{̙2'M:g<m|iV䣥ucPrf h5.Cz~3rO`ġZLfM@VP0m4U=>y I hZ\]̱aU2p0@R9b)~(,bnZ/xztEzy^{p/X{baB ``lK]M16d SM)G37 `UXUz|4<˸GJ~m_~I%-8q3s绪 |Q `JMN`\؍dk%#?I9LKCjs(#dJqNq l~ ,C1Ve²۝Ԣ,k*`rWuUr \m&l"ۘ31<5wK_hYY٩zFg\+Max dKy(egw?@01V9s!=~XHS'F yYyIcb#b#bPע#[\c'_v-rz|[8VtO`}ؼ͍V;Uۮl)rӝ>4+L*Ni%p8͝Ŝ?;bӯHG6> cǏGUJFV uo692OP9SA.hQߘX=_yWejֲz;u k࿭z.*yEG{[8#nۃ@`9 H,z-4PQ達s+PQ(J5/$3r_Tprr1@XO9<{1ߘ+~D2<'fΗUAՙhE9R >ZmPk@ NK5pG5 FJvzu k@]ӧOLeļr̛?r0h-O k(%ɗz`7G4?c!={`-kG؉7~ez:Z3GmPSW.]pB 8Bܚhܴ*7LX,v| _G-`:<n1f2>Yۻٳj@^@={̝;3wCowy| AxwΊƩrډ{30m9V'P 15I.o:b0e{QpϾu"ck`E7HZ#*045ڻ8^Ȍ;Gʒr `.;cU#J)pґ!;}e(wUŸJOLf!I7˗*;hkNExLoܴi;V6:O'*xrϑu+11 I֯3D!KA ԛ` kH"3--~(Эf boQȀ#zwQOE^I!b٭ Ч8%S&,l/8(SfCJq8٘ҋT%J3=utl2~Zwܾx (,`N& uQF: pl&L3!):ꔨ An00` ƿxI{ gFsI0 ES7``KJbz__>WqsC/eE`O| *+OGY'~%;Mq+.qOܼM{o`Ii߭Rhm.AܸT>DL [2Q] f`XQU^` ,C}>ؘVO/HtݼNnnh66J}AZJU_X߯T+u_ܶ8B1A~}k?6mľxcV3%w(P4>VVг2]bW `ڊ[=P^!`U.kD{Ea=m"=8_0N !+׮HnkF^>dzzqs`^^ &AkO?r\!\ kQ|vy-GO૗_Ƌ[QA~ИtlF|q,{E:O:(**CVL<&[ e+p1l8,Ȣ՟2^ `kPxj,8N4MiR&[6Y376VVFYR зwg yZ,_0|aB AYV7$E;*Ny޼Hv%0=;Sv͈6Aksu S6eOYA9AE--L!sU2x8!ɒs6x;c<'bEdŎDɷVZ9 6zwr)Z(t43 oL9j:kP9+@!¢GG2F5v($hkcס-m- t89X” cgŽ&,Udn^ڼD)מ@ItWFFy:b)~+}R#=% ԅϽd\sKo"p҇IE3y`7K̴D`1c~>]XMUŘ_-֤j8rgB f"դDm{{Rցg&E SJLw̛!UK_WX;29ypp af5BqK+Q^Y!L3 1(jOMVÕLGo#lH3%@Uzc@*'*m*Gba⇊qcG*֫Z*vU{[@YO0Mo~}cP7b*P_l&攱j+w=)h 0 ^Xl'jwȕ}hjlyhFzv`O9F߽j硢Zjhi91p #q!-f{G4 >gOI071DCp ^yZ[6`i 9 ښ[ΚjXlNRjН,LcqqkA.K_c'O"I^H]nfP'k&(*:2 Úps#^j& aƣ+ F5"V Ȥ{ٗBP?,J |G9Kq[\`*/X۶F^,>ͺUQ0qc>do0Yx@$Vь9d ?3)' Zkӑ!8}*%P׀bbG=6Ràgb"iFc$2=qPDfh L; xr vT+Nfo#'uч/}aFl+M%s35+'[ȼ|*,!__?u0.A[$롧F38'Ҁ_Q.kV,STQZ!@XHHsJJKeAojr=Nݹ{L>IN?fW54t@L8R2ߗm"ӎk7Y8cdm~XwCFk)%ޭ-B BNHA=M@Y^_\׊nc=LɔSQۻ•}2*}d:ww)>^6+▾&䐁MxA+ ɍ@(R̢MN{b4,B1n4C+c/E7g*ЪcEiK*}-*mMچrk#dh{bWv엒hZ:{)v-^M;j&\ 6v҃}V~PJys$rq)OE?_O<̻￷{N6)b(6ֿ ^wnI7W{.6,u+-k`b)"sc޼κ;d&͋7WWYT jƮ(—FUn\ ׶5Zj{s#4w1M[_ EJ8.^'pSꫯ A܉cصvlIdW fd63h*@ٳIրĴJ^Ԛw~!6dw kjPnTV,=Ĭ`;gO챟@%vgyyZ[>~ڛR׊urv !s߽h#X/qrD|DlltWuBıӵQPJD]Q!Æ#|X ǎGU%-)9"Cċn](I:r} rœLB>},oQc 'u6n};0v̄s{.LJ;x'(H1 Ĉpad/'st;Fdg”)S挣n!מdK#v-(Bo 3aTLZ[)6'/ z\D[[@(cgebǫPL?^wR0Rz&煍}2߳XX!e\%]MT {yց̎lؾ\br6X87D}Kbi㣰7%ir$;Mi/ѷm3)/DZb^ggamqVۤ'sse@(nٲmDҀƊ7|'y V(k,;).?s8%k1uN+c+Y9Tw\2cS5veu"QF! wm7 /&Lή>uEeXS4>e:O>X˃ KyصfϞ 6=KItO'^1E[cDЅɳnBN^K J24,mpD3J ύ u#V3`2Ce~yV؊.X1P77߼>CQG =5VQ;Ȭ~vWLy7|#x~i)~=Жu `% h,@?oJ+… Y8w&l߮4յQܞN=6A UQ]nعxR MMLY_ =&Ei.–竢(;b&{T. )-Wucg[3G>}Q5ńt`4!5  %!$i:@ iZ u'S>퓏E n%+֗+7J 5i GKg7eɔLTq(?^[iGb?_B@PJS1,_Wd}% 3xonNL_#?+5yGTJmAgmLC YfboY*TyVA3At%RV6U͚Mo/H+-?plxdxD z[Jrqqx)iToe Xp {`b5Ҵ ~GGM㚋X EǞvOSqkw3TEMchX4gD<|HmîCG1yQQU@o):AV3~4ңv}|֏OJAiE%}]I7Jgz1^QЪ#a?XMjc*rt~+ƛb%P7-zbh>yc/͉/ߺXQIPcA t<j7jjU Z࿪to6ܶN{Nne},f>Yc%6L -Ю·)%aGUN'&,ss)9{kkf懏7?Oѓu©3py2[s5L5l߾zԉ? c[lXaڴو`S`GLMe]dV#Osh10Cie ):`#79l,XOC=23sq Zuz1{)v"r6^`{ⰰ 8hFyfMvrԱ1O ud45Z1YZ$P"UH;:c!h @ViKLg^6): +6`FhjiEss3lXȥoe44gOBYI.dˉׯ|:Ȍ Q_ f`0enVs`OvW9^R.K=Xr217^㉃x H]:8A0Вi5\1@I(<{.bVA!%>;Kdy8 F֍8}^He5lǩ|i<<*I,YΠs9Aŀ\*"-VT1(D n>peYي߈rš,g6640(B޺Re`OEwqrÁ&szZ۾gE8VL QQbRq%5Rk@ZV.""SGd={Kֈ؉LEk[`nզ$p.l\8vF!B&C_HKMFq7JLú "=a2A`E>?NTv#d>d;#Јh~Q6-8gb&ghlTQG~ݵ dN!8t1TQv▛f!7' H#PQ(&gMYjqn==)lZMu!Fo@0Q/%oZY~/UYx{ _bF]j䔳JvVٵ{'vفIT|1CҐQjjJ3!N=mU2z{(㜅t73bzQW3Qm_3߱zq^WWf8XV~LMXb1%kT`U(n׍7$ve&6̈]s7|.}i" Tj+QF _hswdƌf+ӓ?v> C*N1a QhW WmxML1חV1=lF1Ғ$ţc QFL$%,&K<CzXxS7J 1`۞h!v3f~Vt}>(o}g*1/HU!%=Yblٶ&:a$B5~U3A&2+w[U|I 9%'1e@]K!*`ֱ͍fqe+W--MX챎+d~E Xܻ=LJd6ʥRsQYlhD 40SF"CW%OLAĸ9x%Y C$~m-/u*^2J+*JQi{-wC˒@> JaLԀ:Y#)~=0ºMX.77Qf^ŖGՁK~׫."fHD}Q3  4RNiLViLD"r[,S=1gzT-g dZZD!0 >vJPnxȴ]Q\Pyq ~e7|@O҄ A-udQv"lAZ٧XZ̘4_ uxWXe쬍0CGK-AAƤq)ysgbŰ$p6mrjt?5#oB = \V1 f˖eOYA]J~F2QiDFf*Zq>^~TPZpZLMQ()Yn Dܾd3ReUhee0"f&pds;2,!'EAtZXZB FkU%+De3訝} L ĄĐ;_@l5K|h'[76z3x K/^MD%cmA!䰽#Jx-00'9F'\ `ɤ'%ÚP#V7'Mj r+![`Ǽ H?ɶ`;Mǥz1nÂ^cS[[g?|dK=ww4Ì@:sQIaqXP:wӣ>8NU9e} ygyVx0_o;2͝v|lstʿQzAԖ!$jϖQWWS1M~ Qoh?e#xmXTsi EQd>ⷊҮӗyZq*!$@M_EvrY`cX F=_7r;c0vΒFZ|󰞕uSbko_d&ӏv3}oiik+39kPc\MeHǝ6ƍ /BA~xڴ)F7ANfGI,ʰs0#K>cTtǷΎXt(9Ozu0`a)-=sCqӘ\Azd.`Bvv#ٰLWjJQ{o~aۻ%yzxMM%3;c?`cOb.Y!qc@,2Wb)5$E2Aڶ~Xػę0|$]O>d2ō4 Ж wuSfLfG-=ں^d01d}@ljSR&DqǦ IghΠ\\>N98~{Q>4t1,znZ Y+7QjG`z51qH:z =~bd@k' )Yn HJ_OOq}(Ldƹ AaΑ cJJ*މnih p<2j=L?w.3$?|RzMm yP2d-hl۾3OQSg$f/.%RU#`xH?,+&Ys-:ܓOBW gⅹPG2?O_pOvMU[xO>I V$` 3gc(v_gO&GyN0XXqX+Gn;Gy^bYV VUw_ f=ME̗(WX|n=rGΕ XYΖRĭW.`Gل$*~*ovZ쮮YKy/IA@V0/7 F<Ø<$L%ɮz@IDAT >Iiqr{iâfZM*Ȉer1A<,ƚ5*uysge1I" "@Ɩ!DF,UD*HWckJz滲>R}3/ uwKl_=T-?*vƷJ&Ʒj -3+@fq/A(Ϝƿw-ϧXϤੵ=0a[W 331* [@1VO@44x\x>]!GJ@P66v*u& #pOӌFWW?3My0㢇H|.eji)dcueUq j3L۱Ch딓Ujot\%7 qX]{G/Muy62"t ژM+PAsKSwv ܯw0<ܟˡ2EGC!Ɲ~O4{Z@Љ S; H ""oA֪XFf4 1v0{} B(y:%x`f> )rnuԖW.bF̀'3гfQk2p'[oj־> h]GB'ĊWH`JFLJ!v .lsmdb) zTrX[ɩXoK ζ>47աm&8Hm/YA[u6FNyF{ܛ `…pWAێc̰en2+ iA]ͼ)a[sZ 3g30Nf[>^,-lMWHGGAdjS V[39$? 7؎>$`0A0&|,;XJ6 [8,mGȩfRfXIH<*1f;k.KbZ!o&+_y1i߲UejF֤yDRPjj]f ^ uzZƭBJf,CgURLGHd[hNUPJ+-ǐ~~_z~R|PP)T~NVR=ǟgV2n}>]l/TN:DJ@-DPZū03҇*[ d[ Fii1R7+"sG0y%fM]U O]睨#`yr1[-~*<-q'%ULfVh!&hK;)c7 ͝hm[Vgg-²e1q<%0kLMpLbEE #)oҭ {{ @C4z3?'؇.WWh44(%26AYSaSt 2 a2ϾԴlzU3(m(( F`N'P~WN󔗤Hwgx0 6̛w+);lmara"t03*+V&,Ruh:ںٷ(/-Jݶ5U"vlJ$@x g NA?||e#؆-|6.瓓ɓ'L?.䜋?w7\ ZPB]}<,8@! NnQJpU 8u l2rZIK s\}Qֹ-$z`XGmΜ&1 3_5h74~^ޮapK [7@?O  qTb*h_^<߈Όu~"IuzS9 jzlkL胚FIt>bO_Z\zci8x<˖/%;܈ʋd_Nq`}𡥒4ރ5A4kؙr>aM_2O69ŕ8NI`=" = } &Y@YalΘ1j6bA˞`H>el<֖V-n$m:m |<^LhmES> tQN]MuuK>%jIN2~<KsNC`ŠަIs>T1y n_Fb2( :AqXW0aQz51AS<8q Ef|k!!%&נu'j" 0]*~Q3fv./l3jTgC@[G=3C/jo6}687r~uޖwce rsve͋gj'h-=)Pʊ)3}]=,\|'qt,h;SShhYQ>ʮژFW&͘a8|2k!&ܻ0rpԶ.*lT]=/^VQH9and@\k?UU-/ɺLSwV)D0=Km j3%>!QCF(OEHI"Ab$r{w.% 6׾+j0Q3ĶE b b,'Iew` #*DlV&<"xn-YnGXja *7|2_1/2DQܐP_=r~~׽{i 'qgϞD櫘0R`"*~#xp).d$(몃b"Cf"RGTߘˆ#)J Z;"ADw)S&2hM9Ax1`Ƚa`G=ܴ UTE(& Z;pX餾uucbm 9Zow@@֣ ޞ>tv#=qS7 O<%_`Ri蓝9"<?p.t 1VFObseV68@|gJ^YHS/rL$) _`O 7U}/_OXCpĒ )X~،̌;MɔbI= &&d6ADO̧@fj">c|s2ed&L1P*rI)1k`L97/SQUi*6$&3gk#8=iEOD م~]Z(ʼnNނY-Y{A5Y|xl<|w.YH̵I0b`^ U|hÞaFOF dTF$h]?yb U j`XX,U^M!Hik{%ӊytSX+FӉA]^06nC#9 _\ɔh"jzUԵ" M_($>͛b ȢZIa1~9DFF|09 ,f$^Pz\+09't T,|u…3p"7V!dḺ{.X.2Fp1dt5 $Csp/%i$"eIسbiAyQɨO=Vz ..8yٹd6̽u ܁ (8ELVw5i#<-!3wCrFe33D!?lI#4D]3>1fT,YV;Fc=C55xҷq(a[oJ)Yj2d0$g`j/‡|;41,v_q}8$rIGBj:67^Qp|3I8ww.d?ى> &պXB"`i瀠XʚcJًR\Ro(=eTyQuGrD%PږSP褯ΥbȦ}5llO\1:Nԑ[ArM& t5M^$Przw?DlEeS7<۪FeFז½}wMB&/7uQULpԄi h4+~ahF3GD:RKO`q㗑LZ%Ey{q|q7r!ںF7u~~&oH۳ 1eEp"OuAC;A2ṽ7Ϙ"IecŨ*/.7rıhJ_*OQYEQV䚙x xѻBPt@L;beY?{,k{ރ 8}p7N˧uÙL{QF )'.S*(tpH~ ^b>W_z)~uWXŏ=ap mvWW p_ϾZFk*VLg(*"P*YT(G\ky|U Z?Uu7׍/*$(Iԟ;n˫ d_<$ƐHc}8OfWUEUӿ[ @ֿ+Ut4/Q~O[T-z@WK },l1M!~KȄ L믕jzeY0pOۺw*ȡw=-(K< sɯm}D.gN|Q `o@5%%!48+JH.c 8QzT&~@^9dl°t0N\5BldoŬ Tc2~3ƍ?_+f27mk!K`W~Xp"tp}ԧ" 8|&F'Ԇ6F o0V d&Rw}~c+ ψ7 ]g?jp^ 6Ȑu.Ayǝ46)l.8o0~p0s a1cmnJGlhöʗ"Z᳚BoC 1~>OЈކ'QVDv[[*-?SZ% dCBZbBzc TO ?Jjl֗TNn|@ZlOdZqVoZ'‚M[DwB5|#ZDp/ǰ(|sJ7˜ ?7ghv#cO*\؂.?X:GF3<Dd41=[ dePRy^ d,!(p.-_ CV6aɔ7wA#e%84N|s_{dz2hhZSzߍ'}پ\SWKG31 auFx;➕S.fe?>LIL5}(Og3{eL_uL7l}¥]mMhl큞JeYie_5Х|XYO7)9x0 ^Q_F|1ns7ϓF+tyJrnN?Ucyx,(3s780d5z =O; etB\ua#hdUAa,蠇w(Tj4f#}@={_\(ov TSj^R& SB7#bFHO)#ރ{LF܉8P6֕>6fdb,Y~9RAu'_wXk j;QB6ϥ|fΜyEoȼB>Wo֎2!edON^&GP DOVwmց] VxPU Z࿳}=;+vZ)3Xp^(}5ptqk`5Ul-"t(Lm.b3*Xb`؊{ݣ_ XzK_܀ꍪB-YBZUm>yD |)X"*7!q΍ٲjPZ #:2tp]bˌUc`[YY.&'ï ygKcbn!UC+/l??dرkzxwkoVfN$#FxbE/["(oS/1/~H/f՗Â,bJ4j2q. X^0svEUY7z#SXAv)̭,@ZƅL45$0IRƲ7eD %gf1)i="YWŠK=Dc0Q~r*^U;rh .$'#FN!,};gbp4Aх3naz"Ix0G6 zy$֧ؑ%/ǎÅo{s3Q%o0> ٌddqKC7kԹPM@+35 r0z=]Ȫ< ‹ ܍%ClVQ()4d(ldOeXV ?.vރ%[E y+rb=a"KV$ŶDX3. űןDW:=~*%۫$|#wq#d~4[Zxշqp(Wc]C-%7ѧU[Lwr`d'(~!dKѝ,~?m0 }X`1lvP%کsur!h.[ zA[L_ Xv-0DcNĢ%˰pus',Sx套  gn}c,xw.Շ X&zd{a=5-`8JuLv:’J3XGLEzٝoc&pײBМ2n00QU-&r8*g`Ҙɸ뾻I+vy!z!C&Yח}h0v=RFhmxs%I_?q@<ML}S52SOP#1~8P:l߳S?Jpە2jMʠi9E쐒^J/nSgYCQ'}7|I&-d׺ZyԀKV$rqo>&Snl4Ƞ֑ج2&W lNGGc!:m_ FwU\ks@BEZZ@K5j*uJR $$ĉ?gæ -}-7w췻gf]ᄚ>.LFA W3㊆s' GM4OVSV0gr c, M,4* :f'x[+2q[#L%: 6(E|ZޅDZ+5O *Ry- 0rurD}Y! 5)A:ºrvARr֠PHfW* \W< ==]넔%,^t;b<4,,,.JLZ^2θXeUbιE֎023 .d2ѡtPK?]BF)I(\>p3[!(-)AeJQVW?OQ>LE+/Ŷ͟s r~*rBz"Mu0y%=}KACGBX5p7L}Q!?Ĝ93..?fW!'IP&;M$JNU L=?#'1V -k61=Wx&&%jNTYŒ2&Ommc»sPځ8|W_|X*mƁlAA!~m:m6em@6#ReK`ɤJ{F=~/Nk%KlԉꕧDRكLEwX7 ~'Oaa#V'SY,́[D&R"?Ue6Wn-U (ۂ2Z_ }˳\em 3tnf8E?k_ ;:s$^OW6@6۫,>gx!D$&ݠM.!;yd} uo{=BL5=h0<<0$4ٶb#P&]0ȡ0l 256;Pd{Mc^~<KF7?c [Yj*WO>v6'IV3oK\SĘbNH }}㲵" SUz35Z,ߜ1a1ČڊFO@Vyqt^?}("*?ow'Z:T|nwYNN{dRL=zӚFr̛oyJuϹ^A"("'D@H q_o*F$DRݕ6T-QE P,E&鎅p' Ĵ]L濶_y3oXE}*>"w>5~3~'ÝCA =^9; \;wY]":D1464&G;#ҏwJɀlE>|L ܱ p deOA֎ 4bbbFӀrJ;ҋP]nka"Il^%`w("EM[Pz0!goҵ5:XiZyWrҗ1QM--Р4r _LHmhkFJQ5eDQ̚)SL9ke MxeJ[PTBְ4g!Ç*\Ǐ9of[ I s܂PL֭!;=G0({d hW iE#G'wP #+3$g^t)<F Mχ>;_iL_H|*=UM橒RYoSi0n @[2E23Rl4Y[힦Nd`9ּM;}b("L9~{/O& U$Hׯ 2{ x KQJ=aGevay1׭x`ex2r7w:;R674c5GaDzss!m}L'~MCGcgqH39rv=sLHΜ9Gh322$3,(k4Ѐ.%RCLG2e:-))DԕhdSً c~%傸D/xYIelǶD.V덺+H?T(bkkFPǰjd[[%ѣG]$@Ԉ=#.{ vnp2na(M!Fݑd^D/`G'1zow=,p5`b^cFR ^lR2}KD&%p]9riVo®`壏"_nfPH'!&A,K[f;wL0Op'Nu`"1Y':?={.{JJFMdϊ0s=G(&zDbNczeU`a/u@!LM`a\ReܡMTq5|#*Jx?4BP/w%G 'z!EPWUetbCȣu#-#h<\Ou9h_J%ɲGvAAF^gB u@/gwÆZd7³ >~"X˯EUz 0u22Pw:ѣ[.Am}|'p%ZPX%!d! ը$?yK)@F**NOAql 5UJ3R|D7>tBg U̴5s׌]N+u;YI <8J݀._NTVQ1#%EM %5Q׀{{!=xΘQfEKX:ᄁas9y=|O]EM)U[YGxD$&̜Kw7 8HR\W|ff|{vSD@EȢAl*!+%+ZkU($Rs/HRTpt<ܣӟhN:v?  o~.B ݧG/9zf'?(38bԵ kpnKLFgL){}|[- J۽{~)Y]˂2Cvnvur`azzJdՖW[ &% ^Xs*g*/pT0p&8Z_z!j#6&ɩ5v ^zv?{v1(ymMЧD=t sUI Y/FXF&fODRX[bsއQW7{ ӫϐTHjGbdyT4h_q2A2A| d0M8117ЕY-XpBi[,cʒ `P$1+vz7wT:Y*B:w&u'7]s} NRqJΛ} t5`Es]0!Y'K+W4giO#sp ?,z |Ι8r&p~w qQUe'o&KdN4c,tD_+ҵk:k  K۟30ȺuGsN)+[*iXZvQ:XIz}F+!ܹ~?t *h֫x̺gz_zlEDk465W9ߍ$z-hh"bFݕKoDq9Qa^O\ ڦ6̴:YQavJaƌ1ޥP&T2aPG RUdam(1 gJJ߻x1_H)hQ߃gz~EI  x6rY68}>4tM)TfYLYb{àbޕ+Ae|B81$6*TJصk']VEAajjޢr1,zwf9wA\@spa|{>\ֆ۶o/K#F˗baHPO=4RAB5h)5`,HXء _OGVի(FLJ2`s<3 y󟀾>~s$ Ւ~'#>NjУF6O)ޔ6!*;D3!`!ן~B`چ k9Vy]-m]%X%b)իK5 ew!C/(h`v$ّy\h"}&ljv}B~fFLDFXam2۾ΥrE0foU Kyεn5/!\ư]ٱb-T2\)r᧛4jį5ё6nIn[W&XJshVOIϿ!,LIk&rՋN%u&SX=UXد"G_E.CGJeU *+K  W%xVE[X-hrc UbdY/"sײay[,Vʓ;cvPD`Vq`M"(:uA;n qWHX drI41m켌 [hb e@SCN&Z+sL[0b}wWGщ/-1C 4dO47 `EF^F?J8Ir2ՁoMA $CY*0+?eZY,X?덈MKCuqY6 xhhSxEJ !TTҳT)<r u-LpVK%1w{/)P[jM2%VQqՐZ1"0׸,xI2客~~&wY@ƭGwL#Kl&ңME聩M_N[G<+HD/CIσG&%U٭mEd^`\TJ0(37,c-$*1h~Z17$vŸ`];T|?AF%e/_BDt80 ->5lLvc&eE7bC'p^dd3>$CΓw?R淔'OGZJ =>U{zO&(f͛UWl޸As!˫ʼn7@pԾ򍿂ԇP<Уd`wsZORbzc∿){M<3h':~}=r s*0ݷ>42t72}}F@GOm&) T-5uXlik4#Fqט ' `ϟ{_ "A?kd>Fה.!1%1R kdX k|YO5CvZl~ b(>_%2jW^e<<ԪU|z5y)mD Z[Ua-MQńbz?sb2r߹ŵPҶ$kU )̃4TS׈fJd;o:.N Ex"@Ь(+}@9B(k>LdR`g2N1Ϊ$ql[x4vmrL1'Sݷ `)|hVU ]5sC+`NmZheȺIFJ2i-YwSքKN~N;OW_'-ʓO>!XWDE/_祏"QD&*ߛyl[kpjz"龷v{vN: DƮS.2^?//穯X;`=}.~sKё^ss)k4yaY&-xA|kܩï?N}Q;@M  wZ;3`o*XGEF%}|U1ЧJ߆'cb#XN\D{tŸ"(@ֿYj#QT]EgFGI`*HU%Ě@S}p>|*,~%IVuoa⴩ZOnA>N9IB/R>Y0_K]9FJA–-p^ z% ` ;o幢$;'VQaL%Y_|AVy݆y3 "ĕVз:Z8xcaMո,9A5Jg /&:R UJ(!(stF4bZql#G|)ѨOFr4ؑ[Wm dK#RdՓPC9*\݌[>ĹNIvY:>Բ:6mޅ!ACSTzXΉ,+C |p˰N54;SȾ=aP%(VT"]vxK:={>ۺϑA]3| '_yYZLG#{GٙݓPfP2B |47 cSby(\?|K؆]?Yߋ.PVk9̙]!9uGwK?#($~#"Mo]w{tm@+/ YWaՔANQSWC_*t40z(XLPFcq_š`jOg'gzE@V掄|^PϿXǴA `FlܲWiKj#PGޛR٩YL &*#mk9HUR<>x/tn'eNԽ4Z~%+[m-΁QKL{1jD8&6?/WbfKRadXѧ(#\SsAI+ZsK<QRDC G}`iHC2,n;v.̮\AvzR ЌF p7Wط }Ma5r3'}î`4uH =e[Lnem%1֚ыu ;YJLwA#. ןYb8V=RLPQQzL F(:Lk_)S$@S =9T!Jrb rWU)˟XE f3)Z.l`\OE%zy7ʥBZW  SJ ElkN)`<< ] qƍ ˝+"< 2}yjѦx{icJ2~ŹAf6Ȫ=$ʞ}{O5^S7%EӥfJ `nm^w./]W--ɡm@jRrBlAÛ;eU#d7ƣƋukK/ߋX?|-&u[qFj'&7'ރAN ?' Xb\= o|`U㳨"#Pnܻ_|h%3U E;f'';u$K*~=",JJp.XҫPZq`#qOۯOZp`@/<ɢgqJgk+`'W"/U5homLNE>bn=]z7>a#FJv pSi6ЃKH'3Fـl4m-*A̬l݃2&XN֑e-XeVeF^#]>vڷ,fp3A =Dgw.ܶ&/)iK)Q٬ SCzf\J.5arEzGme`ehRA`ˆ Ì0RvH #hN, mG5ٜ4Ad+1JY{Gx)I%J˪ bR fJ^: 5ͼz‚?G+Zz檫Èrr\zE9Y ;h*q~\ٙ^(MKDnz";Ӥ$֑W -w^3k`s?zX94D &+gº`8u2v9iN1?) ( ӭ fx?R2kHF#m {% d[#e`~!G"0fHTVA]S|).5("ΈV>Qs[/ĐmGaɰ0FnId 5gϡ3Ylϟ4P5Q$G?-]#ƑJTSXmvz|)ͫͰn69j(d t7E$eˊΦDo&xmU~s!uŃ˧)aDְ(\@N޻@*M &w-` (Eӏ3 0Lt<||稣? m[bYeU7nw#h@%D6T '#׹2..ז9Es 1iǭ ;a]k$X$) #ggoPZTΦtإ(!߀\9Fq?D-xŚXEIS/WV塇V"!>LЃiyՔ!KXŚLdʁZP_UYNtLIðd7fMkUNe]jm>#gK V^Um(8)9\IhZn&?!WqjJ+Myy-z@_[H1a1\j>Tz¯ia6 1=z|h8O){[*P_2̜>+ôakGZ KߋVJ{w݅,fcYmmU>9~*9hTz1=*싄'%=={Z@r2+Ķ/չPLZ,ѿ?ʦ Su1\UYŰ7r 0VXWoPQA)aLP`*,G&svʝ҂[X{PD@Etڔ1#G]oso[1*ދED|YN+"ode!wXQuEPDEWW@6找d ӤweZm vKb w22(0& 1m i`+Y~u|czbR[&J]iROZ7@l`Ea.K.3PU _v檷6dàDyy讚\U^WqFs7Heꉕdg2^8g/z}$Utq틋0"9BO=rB)?~l27]Ov5!B9D6U.j={ z(M%|UB̤"z6ֳwzN!%cddzXJp&`B 9]HjS69Pb^*՛Vq,CO|dFHJލsEoK@ٛoЁdw/ÀC*):(]J]q: UU"a8v| ]B]h0[ Pcǿ5j 6*KZLXH5{u=ʒ`SIk,xV`۷lDSO4TBR;zBtY4 )|q9TJYY+a'T5’Iɔ(e7;N@XA<(/P\,,o¥ 4,Fd577xUU0yF k1d5X[Gẇ'l љe4{bq/ӏ[r||p 3\f'ghlBOZmX!&fQj$ZWeل' FhGWz榦e%!2H a3Ydۑ%f*A:nѓۗ ܎i^i_Jd=wJ\ "]3K+SޫK/|N:K̵Ux~s>!h`T/3`pnf&̚E+ƥ$>B]lalw %P~\񓍘lQ4#ZoR/mUu?~;o482ĔZcbyܖv乌1R^V!6}7_xK LĘgG>X1nX&Уr@~J]guھN jb.3cmNi[ -pv޻ X_ks_u *LDMc42!>"gךC9 wnP]ho0]{چװX5(I2<6y+U1O^{j 'X}M5AHB DICix;v}.|ҧВƝG.ѧ3PF(j"芳'3ibb/}c@[oիwG(acv iǂԱsa('_"^dDҗ6"=1lpAěـ/:^|f%%6ǠE pn4AQI[bl":&? #BO3θcPL`u%ܔ\G cT\x9Z!>$ewdCUع@ l DI%vi\#X-J\0kdFp|SraVU28#E )[ٹXa=s֓lhAۡS8JEM-u%KQGg?Y]7{@۬4Mc8O/GGEJæ 0ҝqcǾh,L l%Es}{7V݇#&AiY)a$8L!p. g~Kp${|#'3{aÆWPT #c޽zEEE%R:Ԗ@uUpv--W" MEZF. άJS-|GU&oHb<4:(yMģ(? Ͼ&gc/eW~]C.[:JC'woEr -Ɨl?~k=,^{a &ςZ7>hldF ںLP0DjV[Y'/t(ʸH|Y?~#CIȾd̥Q3iw6p"OMB 9w֦%;TTҋ,۷3d.ɓ"OBv&x*d^}u ppYθJfU@GU1IhljĹv #Gd06d:ӷԉr|J1зCRJֽlް˰xC|!vT+ɸ$3YEjՇ33d.YPaaHp+Yn 0`'1h!+S2oht;5ˉAID o\HW O$$-ZVo0aNEH|!)ZOo+hXwnӇ8n ߅+;3$m%'wgA = ̦F= $]-'AVSC#) 44X1"X6Fl";үi!!)*(.F e{w^ %s9P2kaNQ۽yDGEeU$/[}SKxƠrԔ'gtk63G !k TAu2 uTkx|UA N2}@=A:,ʐťc1,?~N;\ow=KQTnx /o~; lLgFM *(_oxK~d${ֿc+]fc]u#-y_ P/ѓO2PU[kFVrO;s-">+="A]g3ã'eWTl #؊lmCX1%%`kE2Q՝,_[dN`ֿ }֭p.lU%Kշާ[] mz\W52Dut0m,>Rz u<m{ \fGcjj&4J,&>_.\%erK%me&-Hkk6lD sUNUǙ\$"676g $;Ax^ ?wc'9['1byQv݅L3*[[{~oE^Nb[kʚW`XF.m0􂉚Y(Nv|JܛO0$; a>s08::¬ ZOûLX!$memL_PUs>}&Ttd,4b["YH(qQ?q,dط`:,s':S 2 ~w4ҵ#K̋=j5wgغ"w&`I}Ilwf*"pg#ZEՄ. N_ۺxiWjW -}>յo*/+~;tf$27No!ܾ Pk +[EPDoF^)_JYB84iOv:%>*TufyzFG/jհ+vΞLH[,[y?|=wei2duԱH#V ~zޑ^^ċӰ[%P1M2(\,$Yiq-Ces'' WLɌ\v; w>pz8_q$NЖࡥ+ec0Ūʎos2ļ8 OGeToRZ{'O@)=HGˌW(8~883Q*>BjQrc-}SW-թd1h|`C0[3zw 4Wf5PGRfiJ4y 2LP{mGL %m)! LuiY߅iSfSqtt2ln^1dDŕ¸W"2~=]! =:5f<پEDbr&.DƠGOw*2J^J LM&ڻ7V>ZެCϞtl±S{(/|6?|6ew"4+ ڙO#kw~K Pӆ .`_qmF&fCM( GJהKQCxץJʡQ#,Ʀr2eK*J(gMK-W̤ Sl9{$\VQ;kWeAa'/&L#FÚ?M1yH㨫Ĺ31a??;."Sl35^c/ tG#WuPW'PBM%<@b>3d< $ !!3(,,f"J_ns9XpB6*!@ߴ䭿>SFNĉ`I@5.>خ'bb-FY^x\e{mdl68{&-9kB!b^pwrRiִ⾗ 1u6AL^2rJͲb]9)C!:7E!%M b;Y~E=*9wrm?BJ~oc\Z<*ktLlkGĻJg*Y:Քڕ>%0ה Xx~6dwdU^'yb"P+AEPD_1_9oo62g3؀aTYsq/>C(Y*{ ly`'}WD^VثdiTooM7lj$=N ݧO ®;@ (L9$dy\H)ؠ{ݏ4: X3YDPE*ecm8rzڡ/ gq%C+:.^u5 k?1:^x{Y~&$8p">!˞o[O*ycޒz^H4=*3gfHK,zIyi¾o7QV8JS 0f(PS=()yJ .:гřKwM +MBrrܔM+ BԲv2[TM}"#P34[h<y]6:/si~=K?8m݊lxz߁Qu9)glӧB(%<q;s_CF"XIhR5)5ރ O_0եDh0CPU6S/GiXsG [2ӹ'x匞< r^K^?`7*v.Lt;҅Ǣ̂"=Xd_f⻝c젾$CRG&"Z*ҵ "5:\(6r,jHxٰk&"## 7y$T ؎9[Zy%7}1W^D+lx&d6媇!c ewT``%D6 E%xݷ`j p篾:.7b/a0nX ?ﮃW9٦a|C7#]:nWABŵoPPƅXЛ2}$k ƶs,¬b*{o?ͺ9Q8^Ov 2cFVoאcOy3]eJb)wF 8=]}u&ڃ΀P* ]]̛HE~rg6xN<Nt-#PրZ`l{iDű+"wH ,b(O `@;]wacj 65n" Uq ("""OX(HJg ?+/G ='NV*1PZZZ'gP!& 8-!;sI.S7)'m<ɬvtV/_ZJye2ŧY+ӗLBQ^F:P)7oF6A˛ƙG$Ջ7!)Xo~\ߪ z3YUy40cG M lDM*AP>}& Iw9JO֐͆r=3KEv>\(QGʞmRzZ엷&ف;h ӯTX\`VvxyTG6S"fU0_32Z5@pS/,xv ~UUNd)CI9!# 9.Iɉ#(2ǂ$nU3w4QvѸpt0{^?0v  !R&3}WA':@fnCfNv0ٮBZHߛ.KM P1]#T %5:4c?2DW=vcϠ!3*ꐷua,G-6 [6H8IIl3 \, DyU5J6c 0 뻍@vېDyF~d$# <]EOCso -.D ~/GŜ +צaV,716%ؕBFL4O\J 6d! ̈́#e|_>`Gכdkz=˺9;Hͭ)l +~%zHr'O!.VPRBt>y+\׈ѓ#'!}#qהq2c5Lp" 5sfL#v ,mƺ``*,P:5%'yWT`ZeI]I1}\#h[ RU k{uDO&488_lGOlZXI H!Iqd•ZQZ%o&%kt%ʝ .&Xsvhe0֗,ܠm;w]RrJT4wgC /*ާg`ɉs ?nAVk̍G}>41p@sZn4GÛd< H9(2ƍs\MUeIZǟl'٘ ^;e:ɴHƴI?k6}Ǯ.qs:L>Spk5gs.+ TY#Eȶ1AnI$[v};HE{+[D{c,nqr!{X%.Go@k[;4Sm`OA仐GHWcX<92a-־ T{ WٲS}וO# @O &# <#'"POSʟUud]CWpʋN>4#nY"KJ נ,#Iu@c|9 Yc[ke2E,++~mHA3}z-6 wjXIuKLGZj&)=@ '\-@'٦H hMy=5LժZEXXL_.綎vhI,Jjf\8}abvvcGgx}}Ic;":{JfΥrА5 P#8C7 |Y[=ҫjC#e:7Ç/!l$lI@Q_Mu6(jJF A&3 "H]iӦÀ2з񅽕9}Ip1^@[eBg5Lyy C!~БnǁЦ:2ѵM-4!tE!.< ǐSk_kQE/>%sCm)iEN~VVNq}#HbO؞c$F!":Eٰ6*/GnVjj‹o޻gd:Q֔޾:(m XۑEK7=PQ݀"2}9{HXzNXłȈr(~ dϡ[$<Y ֬xJKNsٌ~C=`AL}]]l߷$ы֊^—x׏k:d_p#x0m{GgL2:7߄1&da2n[Xwo]T&yUP$; uyX%Ubc!VO!ȊgzGdRG8(F FIm3~N-`C&@IDAT֛T~<8և|vϜ6 s*z!Xh{ Ʀ攰+Y ,$r11q(f;wޝɉ.LD&s V`RZK"6(oPBCM%,Ar>|ޫamnF(қԦ6cԑQ?uwu?½ z)L^l0VYLV%4 }VQUvv$WXkX^ u C7u@`}F_Mp klCuB]eipsEي%`fNh2i3s|23AGwȡh۫+JŔBYYYq31w}{ʍl{1QŠDZzӱh_D`_]q?~GZ.wnVL 0zX)OCv?5`pV#ܼbBVZg$t"~X,~OT>-wT;gUvrU K /%}{xBwG?y);?t}%0s_<E@CGWe/AC)'%&N9Xspn~פSyYؽu>%j7ݏҚENș/mE>a3p#eF7)(*QҨFSPD\KeU1noSUB_}2Jzz x>8g)oΎS-^siQ. 6d*h‘jE?ڊ|2\jŽd2nje24q^۰}'8[K6A*gϝCVv%v:u'c4~W+SN,: 0qw YV!{ ЈeQF,,52ظxaPUϞ&KOd )5ǡlMEuxMaef An=u)oyE 7CnP&#~LfVScǾ+ Ά<ԩ(\cX"wU+V\z/=!g+//Q\dŒ3'Rj3PN!W-u [ qCl\"NT" K^+}ď6"1/s{i4K^SsjwwqhGum=vEwxb F"AVU}公?s FDlJ"n0ւ`.=)dCBCC#0t =>\;{'2-d ?EХ?Kuk=}[8lr+qpvc[ Q`I9dZ\K^AuUgP{jo,8]0%=#;//0L\zv ?,Ϲ5doÁ#gm㛱/%Z7khBZ YQ8 dP<蚯WcvQĎi^ > }5\8>!(Ql&TTp7= \:?w`Xu~bYsLPV*@+X\S}_qGJ3v Ͼ ylJJkȆ'sC]q%16UPfn/@ۑC_LH Y|R{pP0*rϬXŲ|YvR} |Q;0$~crMUl !@q5Vζjءx0/2QTTq6)ARr"s[ŔCmnE2-ӓ@ ;^xGj?%R1/dr %"ul7=vSqJi6#*ՃY{9h%~;0ɄUrV| {gcCC]Osji.AcL( 7YgS]=Su>#<E\:Zɞ3f=iؐRoJ--$OYZCj䨋1޼m=}{})*0lT(oA&=+sh a{wl%`G#1pT8L=!KFʅ (cqL8J.>`\MOfVOػJV%@Y!{QvW$j ŬE9s,`۬Hyg}_ ?YJx"$F/mtx6߽OU cIm;ivJ6[ H\>up֬Y$^&6~@,z-x%#õ;f^äS1kh|=tPWWSRºLhAtG"39j #}0fÆ~S mKKoPT~u,? ݣb}^ WeE7܄|7Hy:2 Dy4]*֛k)…&Š IU8}4UWGfM;Juڍ^{ YeM4Nq&M͵2ydMRPP@}ȏl\Uejk3AՊR&4dz )-OoϳOb3eG9edoc"T;,$"'9QHG^~ b(%bm.NgҒc)-}q_Ï=FO7zZe؍0jwsTut)3L2ӏ?7zN$,~)>d9ˋAלR? *̊mo݁:bp_(S.Q JCSj0tΔ V2;'hkL,4SӡD'rf"@(uŎwEMYl)1->ƴG3{MYZSh4K|v`\!q.6dB!CQ3~iiDt$,-+~㕟Wɒ2*TI?D4%[PnTW⢮j70DuNbx 7 "^Gc0z$!4RCU;cTPC$4_"SёZ3LJx.m`Z)mΣo.t,`K9]w3MmO_Rz`K[v/ :NNБc(jxki85M5sp߭5vVM]9 qQ=2Sc W& 81ʐcmu|pd?f(r3p1۴ꪪlڱϡY_[6/.<M ut7^ " 4 [VEQ`H$_bRCG܊ c 7^&cٮz"Y-?Wub6h0mMk~\G|x,zIG.!69(m&zxAAʷ6^YBY\Y`;Р `mZO0sǶxEb_*? /=}d4/'kz)$aAa%lxDzqy?s_z`k O'\]3vU dr1,zC U\eߋ|^ =_<# m,Sc kIAv;dصuycʍUbpO2?X!~dA ]<oCcSQ?j*޾^*tc(ŻD*[D"S4 F#UDmoEeE9ʫo{=p!/.@Q{vMiLC'΄2fM ?H6]3ZjT;`ZJpj\ z?qrȎ*(F]-eo):mƜ/S_Ss S-{L8߁ȴ\ԕJLچf5IEx`J&O/~k md%'STV"3ᨧiI~:\. [Nt_w7":N)9oeF;ѿ a,/\ 4zR>x lE(.d`y /Od`$+4552:x_4"BR[Н+a1h sc=Lw_DCdJi܅/% \#*& jcʬq$/*5C` k HܔB+) 3# u3#T7y+ ZR5tڊ7.†;M.58HI{2|<(kNob9+j"|k7Mԧ2$'^ =n RPCph& FUe~Ӹ CYh!HSᑈLʁ&O +ȧTx\c&uaLl2%0 ME[ʕ^SلҬ68N b]`QVR42@~3H|6+ n[Ο%`R|zZ׷Z;kJҖں|2!S/'eGEOI#Zvs:&mO f[gW5`M GqkaD6(;t5`o"m'#SIͻSo mEƵ \`wX6O-NCULFӡ@ɳ 6ArzLHHKNF}-xY$Ɯ?r&_GYTH8"Кkr]ΞF)Z9nb{V'l~<#\8eC{7('ELپu;j zN5&jxx [ 0vP& YN՚'ѩHcJSTb0Ǹ(4nd-$RN~~=ޭFl}Q{#Ϡz0%aJޢD`iBnL0Cs5BAUmd! uEm训"McKS^|ظc/:0Rf&ذe?2#OζoG|GD% +3s,-wI]yyPۄⲒc2^r)Wݔ%Qd,A`YY3qt{mr4;%o'I8t)F5V_:OV~1س{;`BAbVοg]CؓI$U -[1@R-,] wOã-mx(!wK%_I>PRTX̾nBT]9"|Mwy R%U2=ƛ&M ͭ<# ?&56$ͬ!ƿVz%d棝,°$U+X>bY s.g NϻV$bVU0p8ٰh*᝟1r +pb V"_-65k2n*vM:w|*w"mꔳ`=* -%9E.p5j6~#''J$'("Hhxivih^?{Z$J'&&"2QщdvR֐5&IכCR}TNF :|{-X;c%X?"|)`PX8,3K>lex1$,ɸ+&KPՄ \k 5Tں!]OI!NQBMC?Q疢xxle|W0~J|ryhocWW3ΜW=8s~ziK=SfSuq(E]@/9)Iekq49(Y /_2kh}<*JZ{km}j (f *@uk2 URtZ: 3wo(Qf5;;hm_ [Xݺ& t%UJӃ>$y.(jZ][VtrsȚ."PDC-L3PR$ Ѕ3TTƖGQD'`g|$akmի##F$UXS)mQH11W^(rT&(_\\+W ȷeZ:NUSccEQn:.R2ׂrؠPe#=9 eu)?nM4Kҫ ZU UVE+Ԗ/EPӄn((KgCK F/S7s[JX"ۍٓHۙYqx]"GהIoX_LuHO$V[,X..JAD\XqgNB>JbⰞĕ_VxWPDYW-kaKaN aް";O$2U2SdbCV9c}_?| s3QDcfJ1yhi#ا6;7l3IIJ*ӕ(`"kq.֕f4Rzl_:2OK=.HH~D9c NA9wli=F#DbAv.hM' ͠_xkc5 0{Ђ3iR~GU SQXccc X+e{p`GŋaMXi7P^M?zNvp%6!hI&>(Rl읡HYF&0\J΅6cDus%ݶU|M{`F~5SP}Cf[svcyN1 =A-$ؚnX!>ПI IXiӎzl/T L*u_Vǣ 7A)h%{۔n+=*6Աe'  tw?^s-x͓־>x|&?|C}gFroﰒm 6vD;3U^JUygDJ?9da2d'{m-)E"pjv6mxO[?de `j"#'" YD# <#W"p3 yI0$#i N2=Lnf"=LBYfHFwAV~zN=dyVf_WY9Vya'{&}VwZ xx"YJ;ԙw!%)6 aljwp߬%kFx!=ZNڊlI,.”Ȃ3"+R&˦@D~z^L.쭌`O&Udjjh“@YgȳЊxƏJRRU;;;0dマnA8 2 ^r?V6dbQp|\nXg``7=6+G|xFf\fK%&VE- & 'lni´Ak$>+?vdZghI`oI/QE=u/g`M5eMdl݆RT㳱S#A_}Ĉ̵`hS)/u龲@VaZuMf\!Pd[*HWs#== 4^ؔ?< GĹQS fCEx%JfbԔ x m ]CI6XM20\cx_ޒGFMDstİa4a<<Ȟ/*PX\;[#ɯ#rC fONF9mZ,;Ts % )[ E&&k*f@uk*O=QGf!P}0u*eu.OŒBF\.>YƆʎ ]]dԍD =R(KKiE_&ҴCU\Ԃ1'0SN8`m'<5mHʁD+Owf(mHQCdɄ?Ͼ@6k9RҎK؝u #BF L&ݏ,~#.>>ñg?qNҫ@t~1%Ҟ~b/Rb[ 6*ע3 KCmXo-$//[skːL0? ۄXX@ޫK߅c'ϝ`L7 }Z<7VT|IAq d|8*_t#YڔF?!Y U$V/W {Zw.KJ;tahvaB.T:P\Q,a0P0 $'Í /!+8455̔ /*/oaLF,q2{-A0eEDļnd UN W$E!o/J}fm _sSO0c.G=pU$!5+QϹ1(ޅ 7!^LƙKѸ{ӫE™cDZI CBՔ^(/=fd~ǎ_?H |՗j"ɤwq 9 mLH A; G=.梁^>z֭!]UgлZh? r=ZW/L60‰Pj6ax<J6#P4B U\h'rv]GvE_z)}'/s#0etw-~B].6:9IAȼak"Na__ y~'rw$_,<##xUډVOG_^}i3e:MosWΪ woAslnyWWNU+xl=.zl(H@0M4Q.4x^[_V>TbZf5~v^y]>ʙݴU24 )WZRN6_< NE Je0u.YJ s ;ojc@S)x@`&DX #' "tVGQq1t#Sp#~Sѯ53<̳2d e3> IE1Nurq+&kU+ޒFHT#coTe#\CQ_ЗTG_,C_ACGR#.pKb89:FUQ3nXB@g{`d,K G9Ӕ;!RO#yRP-0 8@v(X]u#*`(7Ԕ.VB'T1Y #>@;tuZmǏWwj, z<Ef 3|UT"k5T({;Sg=,#C&2{q ;?pvAci:^u <xӓՖ-U RZRFq̥SHLI#MV+8|:?AIGK :;X8‹ dV#@uMS>cGo_3 uwm9*PH^+G_+Ȁk6ytG}} A}GP ;#6W?#JeJ TtNJ '=z"x.J"7+X`XJj%C}{|$ᬙ $8 !CG7t2.FR$Pg:]); I[?\>F,DnǩMG)YʔTҏvxO($#0t8"xEw]z_ YE%aR2E` yg`=cʕ|[@ ވMxK7I\9CWr2 5eEϥjCSiń'qZ^- RBٚ dMJ)" 0 FӇZL6%-PYQ&[U=+ҧZLI з CF`-/CΕ 8 Wbv4㷶Co6zQOSH}Vb_VMb2M0ib=S3k G &܎2.Np2פrҠNprA\5U陮(e"CF LzLJJ.@iYx0k7/5;: FjlwU!n @ۋ@oo7|ImTm%.]GpSXU_"%q<awݚoqA̟$^^JO-!6I 1xbg_|SGp*] 5upeUn,˖ _t?#)%q~6fW( d" 凬vt(RfrG^ 2KzM߶(iC{ѽ} i vumDFew  $j2!ݘN:|s2AlXx'HُBOzҷQdS@JthR~v,&Y\B2Z@OԔxsz^,bd5QJv@F|W2襸{d?ssq5|:ee†;91Esk'=#\{;hhP꒠[JJ2A<h>Z-X%eR dPׁ)Y"]"+LpSJ:u3VVSƚLW0Õ QZۆSE;Х SD9zx_%dt$4E_oo<)@`Z޶o؆adc_C ?DN`I\WgQI%GUuCX٠8/ f˳l6zب1SZ:zLưXN5W>vb1Iu4HfՔr#.mu'_bɚj"eE115-~AbJ_}D3q⭷^ƼD#|o(2HQ 5וLΰb.F%mpQa @?WԵk}ömd߇zRJ"th!޼yXzⵗ_BeV(uM0BLX{-_yY:wO =l,٪h1xp oooż8V`ekTVx iL_#ÞCxa|)Jz0[k[~ذJ{4[>}gF 癞 S*~' i$wZy =wqa&+dϋ|Q$(U&9z˷]97Q yG@ߎWi⿃7r\Ԯf/dudԕA *j4FfYRgYJ԰X!08ᇰa&l`H@̒j_#;Ы2|\+时 Yy>H&ӴW3^ 6Uȑ8~0zh2BM9^kۼ /$cmj4&j U*F[ȴTԯYŅ[-jj`K.\}1an:AE_MS4Y?y&}G?@7em pw= {-(JFsY^K6!ɬxZD NC#2t͊O)ElDɢ{,ʖ&PMϢd3Z;VPYSJkt!%Sh"iHLN: F[sGLb2zAK p=yWȦFNV"m!ek[뛑]D+2 D萉\!3 I~8J p22BW2-*m2r SZB]>k %5+OW3сpp-NVХ7O("z ѣo } `={U*eg@@5@/͌a?p1\IcW0.^ >^<*3pC@`BHH _<7fV wz&(6c?.Veȿ1z|d@^d2߻=;漧vf"o@Z|{O<`RJ%(޷kYYR"ͫݩd-B:36LΉK,@.#!]E6u3c=wҋPRB^*%Sɞ/yݯ(L.0g={vÚҿ/pH46u`cPHg6n$ 8+AjSy)+lp#z)2u~7geۿ[(.*`g U gqPumWGVG |,1ТAm2`?Eq+)G_ic03.3Cc/O?B NcPQM҆LDFF^F ]}l\v]2s`1!KQU=۾ AzZ* a,Y~d oloڸIACo*,VYS-A{= +3&cքUku5iήpl,L"}$)s+Ѻ3v`*Ub>@H }[ʗ# <pUi{olX tz a#dS?< ?>ʯBy#Cʢ;TE 5!JYl)o(Z]W4Xw؄];7q7q_?v$iMgf8|0Aذi# 82\1#bٲ=fs'-۶w!~eiz0UĐwGZztȋvXwx/)8%I\˞}qll C[I׷g^/2ľ<}PI/cGUy%ٶ9k6eȶnAK5U8K ɚCUYgMU73)M!奬gc'N`[DGŬ YFz:$`|"]K;}OP3CJ*Xq1zP @0j3ZEfnO.ٰi(iPB*3k ̜2AҢL Sڎ> p I`޵kvއӯ0iu>ZGu1Y{Aֵ 7--TIx| nvؾ(+4Fh(SAm8)2]0 ˦Tυ٣ [VA>٢CO>>PPR ꜩ23k*.i ISR؄0`#x"N2QȂG%mmPSr96{qzVȚVZr2>[Ka(+KltτVߐ/\}#rON[KE[)U%k;u7ҝ # <#l߿aP6r@;6#|_G@Y=X>SLI*՟YD硃~Z :93INg;MCjz￷ `zѻݏWa}D';bO-[SQvsnA$PF~)Uiˎ.C3Datq>=Q>xs7uv@_2v#1 >szOv휘I @FV2LOƛ! ,ʯu6fpϖ/kI:c{aĹ-MkKKtUlC ]X|LJgW7A#F`Рo}2IDV';3=D=6j411j.?#F_~tmYnmy)XDĶ!j ^HDIHfjg~9<4u@YffL!GfC_0;{y;y .?bB:dg!4x8.\8 'WP*0-Z\MCQ5!3uSFZ&xk/#-1y<,aH'1-"7Z-2eRmh3` <ݝPF߫'+RrC{Zq[WJZ0I5-H<< fcAhU[ϿY7{73PzV\&3Kz|8qvn[Ο#I GrJ.\+>@V=2n'aѩ潌KK^AxTD\ CC̜0` }4]@{!jE&G~4[&TY*b,1O Wzjެ}ɊlU1Cs'_X6Is=VL?wȣ Y¦(kEVnuzKN& 7v1ل:x7@db^y-kdz%nZ5=W&,Ɩ͛y2X##)~ .~8M4'(..h-|Y:gdey){mozQ/Ix|!_?l%L&T01%#9.8g+._#f}mU8tP7삻d*gS 1yPH_a/p4Ġ_HKdO&FP:cϕڎTBrǗ,|aE`:jhO̕aCfLe_/cl[ dˆ^[*&ܫ,&AZUG}m}-T?{EG?:g߻}N9${r{r# G#Z\xL'\K9YU:cψrE2UNꑙl9CrbGq55'[OL A1L̍al(E F-3iMJIQ;se1D֕c 4uS7#= 1Rd(ǎ5pdXӫ0+r`)nhQ>ҶDeY1z %?o%3(inq E_ER};S+Hm\̈i_i <>* XbjZғn0:1ϧ370Ȃۧ'@FPTlRr|c Zݰ&.5BQ_Έ')Gf>,3)Y!''XdbIO1=`CE-"#: %J&ڪ4LkEI[|\72A1Pl%U.,UJ9vݤt(!; 7o$pп>{p&Sṵ)FN!pZ!TL`kcm̝7s澃Ƿcw_1^/_.t1_'[k:.]BkJWɫLBS|:ܔLwSsؒdt#[6}G)de wPEH j/oYiCV7jZ$4U8}r\bڒmZgeW`pH0} ua`n޶3(-ĝ+غGQ0id`p>d$vu& ^ ]MQTR/@yUn`ݮb1`̘ R܄#1zǎE@qHw(:|$Zʏ<Vzt_y嶭d4ec+BLȉ%p-ꋶ^KE[BD]C!UzƠg˦ه*_ p.#<ޙ=@ R^sšך-fgy `QGH 7n<9=&b!-!~UR+'ACmkr~{@)#XE KVQ~{r#w@&>Y9IjWz2&7m+D@Y gI9Xx A-%% uϰq `+K$&Rr6iS4  5*vۄ|PZYXu kg1i`;,a~{{X5 gB{WX(.}&-98Jݻ'[IS _C3;$fZO{ַSf;:F.z\i CM us@ˣv ~XT8p%-!(@VQ*J%t`Prw dǘC[ 89Q*U=(ߡr۰n#V}Tpذ?zcND2eJ #@ 'ʡp:u\jiX9oncS7X6cR*5|c}r.\LlX%>'iPQn}W{TXG%M_ f0Vť[PҊ (mjCSu j)CKj*j%c@=\ьՠ!c1$R$Q ?bɫ:u!yD:]*d8>!Phi@Ђ{}&7J`ݕ[pt.&P9'+ҤdV)VQRn`aZ|#Xw ti&։Mgd9AGۍ[R\\;5d-G$U0T  fVǻm!gu҄IҢxd;N 3d־l2zC֎  FRUIuKQW_b°QHLCi-D2AaM\igC64uQZVs 1.LB fcx9SώWxlz_6??q9^^^Od ؁mGO )圚|twCYM)EdEaa1)1AX6-Ǐ N h7y!\Jv 8.ʭ7|S72 jq;d܎]ڷA{;#9|Ɣ00+fYjn1r2{~DD#61=a)}W(IeS^`ڪo:cjxuOg.SYqZH`8.̤ع{&JIȋaCǠoDe7pu۵;>&> ۸rgxZ 9Pg$dR^A,(ϣ3vB{Sc |< K*XI5S豚Cy󻸕QB6f8y*R*gW7wx8MFLJ4Ukq'%acPW oZ=KÇ֎Yq<`Q3U|%e ?P|JSVr+FU#^hQXEX  bb6 gs# G@?][JWsN1cr#O β|r$CC[,7l&f+Z| ֖k*KFdaբT,U#C!:(sŜ EWbpI|z6 r@\ }z[/ѡ];̛?L-[ `.ɉ`kHn-݆F{MyPc8jCJjȬӈؤl݀:wVH] 2ޓ!a+'šmAc[2o_y3QvϿ6V=*k[hjbJ:^3OfmYLxʫԦ-<:yKwDYY)prՌ* X[}WYDotpH,2,uvټ،7efu?%4 i2"E100 Iۅ$ɻRwq~isqEh3jV 50> {Dk6#cvH#IXiiP6,k߇mh&%cxb0:wǐ!c/`m?~*^gCAh>ub0Y.#{{?Cd]'q7PO0 փ lw,~5o#~X) *u7sUv*A"AZMV]eW(zQ ">nH#3ZIM{й9jB?O%,TTexqp\q'۷8MMaFuryt!hN,+?y/<*}c=|R~G%dނͭTT UkGG>}}(g"PISinaE^OΈ޸2|$,܉@DX99XAE[~܎Z#^A'MKv._gΜDk-f~Md@%dӬT(!Go\$u?<^9 :̭rN NLs=Xd|-^񱗨

x%yd>Z8<2=zG.R3Ġw~}T`};wRU0.--- zI0@!?3oc%@u!я.3;d%Ɔ#$/߃ %u{?ڼ}v%e:i8dNlO"#tm/>`'T piw4PhH0Ntx8tYp [-m5ć|EoNYY40@,K4zVVFA^k} >ߺm3HOF &3:Su+CzJq+ IuޗD{++}$Nܹs$Y>ઢ њ,0;UPoa,S#Mzѻ OFRb"\ɚ6&λoKY{lCaA>ZZHe(i!Ȏh6'ӺIfߴgEzPhT !d{z`0A0z^n}qm۶.=v !ܠwGϏ|D@U ooa ${5 AXyL}q?= [6FZf4Y۵iOK3O=8sއIr= mY~~ ABEKKϭ=LPWĒIbnFmYacDָ ͙XP-1<[SHNbRvxi{a A9s5ID ^-Kph(aIy046ٳdۄ=E)mju_`-/G"hi#|z8OۆC[~ Ÿ #<G2nP 䬫FEm&"I)Ϭ 'sm*d5M6i&=/ fDan"OcgMʸUdS;&|VB 0k!8꺼 U"sE''l;,1p LZP*Bg`Cr\ #}q}S/aρ訫"L2 )ELЩAS9=[eZSyjK5LܪeG~/.-{DGVW&Y=|t0ߺ?r;ͭ(Ba:)G@9rEuyZR1UrVAֿF3*/[ F6g_D 5&9H,JruD({5)e5b:Y: 02o.S˿T`\ԸY[-$ϯ9ѴޝdJ(&\j55_ ss32b򛕔3t2:LNITFT"f(Bdߵiqsms:8:Xrdz刦՟x^l5&Q0DRWOfQ5^d2rim]A}DF#Ț@GAu)Քش~BbHdj@Ԙ Ci8>ZZzv&N` @! HD]4>u>p:z8u0>_D&Z=zaμzs`T?[ʣJkzxҗ嗣.!42.E. V5v5މ^d'ܩp6j**OocUAz3n߳(ICm)kdjkHҰu`\5[=]]gD\W޻ xҭ0d<3e2, $vRB==Yɶ=+WD]uh i~*=;Y9L%{T'<"70x$[_ᓏH&Uժ^CXb… p^G02,9={SG/e0z1jgNËȸˠI ݏ1lㄤ0ѷ¦[0p=& &%SjU0om8kL@ڝ#$*ʔgK&)AjZY'КR8K)ho\Dݠ\+{+:y^)?~64ݍ^=Ê%'+M+#ce3>({ {-|{HՄjAm+ FkNH'C/FVtzcK^;= HڰuSxWܯ@W&%j\$F]Fzv% Jˡfz:AVy%H j%3#X \HLW;L+ )1rS6BΜACVӾy֭kWhSg_(Mo$L1jȣ Y]$`/ag7)ܽ{o\t@6%fzჇ0m Y9  1?:*غ};ƏyMVq*d6SG2ia#VQQE =?  FWY2 Opr9ro"ou~%?JRUl#Pޔ?9{F@Yxʭ# GYϝ!ȚKEf/rZF@[[KBSS5',TTBik@_7P|L?3}hKVžu\Е5-?rtp8v1ِMU*-ѯwO` `g6duՓ畸E9wamo+WoP4E%hb"anf K['2|ʵ-GmT$^c{蓉[C*/^GK`pjX`OHܺC'lT1d1ݳ#,o8mt uPYJେT- ̾V4t e?^:oANm2_Ҫ:W_-ǨQc$pu*F6Yg__ ⎝{|..IW Oqr e@M,e8e_Bg:hӾ#%d˱wFy:ғb)3+S^F2FF/Šgsp&cLxaV@%c!ڑ;sluj\|>WNeT1H!%] :fg`ɍ!QMF ՟Xx!jXΤH^dnV)AJtw҂5ܯ6lJYPW_!@9؇$X`ŗש'?ItJ)AOߵ߬#a:XtϦ%@SWSзG_\ԔdH +t[b[ƹdR 31a\ ?d|D ]ӧOKұZNo<٠k%]  Yx#5vk1F` 8l[=C~Lћ}PYo!׉w'߼qQUPq |2dyvE8K/ܻEX姸 E%{絳sk$IC1:ΣW3)%Ю9NF ALMJϓr7ueem$ܾ]Xꯗ0y  i[!k,VQCOZ|֭PP 'N"XjD/tIJ-OFrL@qh#k^_lG:fFՋad KU$%{!r4:vۙEsAjtM[w_z1 OOO^C%ssSJֻd ]w5(Qܿ[|aazyn*L=Sv51IDnm`P1C9R\PI|DAYfdBą H.+ԧ7v $m @QUU &QRn]Ct=WˤŶlCQ`Uԗ?4@׀,*x[т@_mzfy9r+ki"7;E@xo54Xlg^9r Oҟ{XE 5X2*׫Y* 5Օ45O;RZLalkr?Z V*7B+-_P/i04N&D-OibYqZ%'ͱeسwl͌$Prq-Q&--3H#}MVQ~DG2Vu~2&Kà 5*&QĠ]َ +sovOV"TPK~6T co&TU֝ {2BIbGb(7~sh. ς| e@uWIբopaLxޚ WbHڿ8īDM_hS:7;wopCn=N[qz۳t#O&;35⬗Δ lF,4u v;ܦ4aǯkz ZndՖ47ؤcM@BJ smi^HGٽR](M'0GV3΄=*aL|,qS'I0}Œ3Ɍw}yZR=aC`έ;^uX9AKG_bЏQ$"d#LV`m 6 Û2:xzJռ\_"G)uPVlJ.=y#o^/_}W/2Q!f4~ܺyYYKG/Q+"h(܊dë!?BDC)݉IT(.44XrhkI"HNG$ ޱÀ1N%sdݻsڅSK,r-&%hA[C7o#٩ҳLxn۲<\COJ .Th3/HUPFi^Oڷ'kS-؃nxZPޔB=&0i- JBa-现 }H`,x~bʜ8G^}GdRz"qShXoXS;&,~mU{|"e8Sai2B|rTr}i~NAm_dvUJ_E ȈmUq}~ }5V ܸ- k&3d.| dgW^%vy_1H,`񯏝9r~kDn \oL߷0koݏ1ߘBXxE?=2O# G@?Un߼JY惹 ZkVRZh,I+_ ffƿjU0%gᕕ` =G薥AS|t|JvnM_,E%s.0@Xv'#[5gb2"M QD5dš{\!XH+6RI77'o¿U')W 6y\'g'8XA0j΍L#mu5ٹ_F[[s8R% Kdcoi}~.^y/G0Xbp6]rrX$Zd>RJ\m"*+++S1+pl:JzQ =&_u`7'Ι`Sgz [bﶯAb*BלL7z>3PTZ1L,l8&3z5*YE Eoٺu{E5?eEUo#͂O?Vo: Ȇ54wu~N\HK$hdػ6xvK!y>8w }QX~y4&;ɦ3>5_bİ1!?f$Ib7 C{P_;ʈvpqѣGwJ:$ kdnɓNѰ08k-.\JfNٻw'[ Y.p7v<(l|Jn}!N5<-UD^!MÅKqM$g$8w?U/z ?Ыw)M7ܸy. h.,z&C9=7l{NZ!,PYY58w4G\]6`DooMgȾԿJ=0RwNMՁEU_#ƌ]FIWSJNĠ!C0\ D"A:%e&\1O8i 8wĵ,}+1c5Q8|q.AYμo3!{?+3 ]05J^=@M,jz0;|PQ#ہ n|~%w]&wZ[JS*&| 5+mD5QTXao)I^V|=ץ\sTQ26l '{;ĆA V*صL.,+!Ż`Cph=xLF7.kQ5+GG ^[z>8?OMnH ɰkF=VTCOSd& eI0Y9r#?@Urr(!dwo#utiP Op-|R1' ~9!U=9LO*/Y(?Y `6M@}mzrAֿYI9r_%6l2]2kvTq8#|H?mpʪI|LdH݃bV*U}vJQvDPsp؀`Ian U @W-jOҤyi `L-$5::r8B!nP~xWRj!#flk0kv f4}c P@)l~ @|r{~ӣ֯ZƶHJMQWW[T`S $jz59e+m[;(6V#]zCGu[ZX B-+70Xy@,šUk$OۉiNf#77gϝƲ% )[#!j} wb%ZBKKЮ}7i)⧀Oٺm{D?v˝1ؼe5aN C۸컶jjfkOZݹe&L*%FṊq 0/.*5ƦDp}挗x~EДGZ2II/}L{jq]ߜ3q,lW?GlH\^d O)q@5EJ S}J=Xs䕔ҋS fPq =N6{>|~TEWÁMe_~=R62[R6;-5%pUkXh0*knnfP"ɸr5(ALHzHߥew(O] U^c ƕF}5S%䇾#;@IDAT,ѩ'KRV4#Ֆҥ2U}ؽ?y)ЭG~QYT桓+doQKkpʷ@%שTTW2e{K%`ZK UdJ0<ژ`GZ偙ؐ_T4*@YuEV-JpXX=L^Ptv5|w@= /tlUk'_l<+!FРJc1`S3Xo(+Sm?Ըp*vev9v6=uw)SpN&[Ùd>LOp|d* v]Y ++U9{ek<b;]3jXfS˭F0} :62dyTuߢkH ~.NN=t 4|^BzD>~ *U`}D Er# GSgCq\(z]S& S)0|*qa)ܽ/"l(āwŖehBDqlr}v~r%9P>>9r#=m98k5IB\ )p5S6):l R/!\!{їbq?e}70i=9.]1rp〻(¡gh 6hée^*"|? 3 !(.m+Džsp2UT }ew$CFbWN?// pQ.eWHvasyܻi89܏LܯIJe_!2,tdIil` O_"XqQ# ۹#-*\]z耉$b|TSƣ_xƄ<#$f>"3'J߫ ],{ ?dҼbJ> 'PmX>}Ty\-`g*M Vv]}I_4v!GNms{mܺmc{{5TF>t1υ\=G 2IA3=A.dЉp"t#ڊWC: ?CB֌?l$`% s87/7qY LW¾'CHzxy{GG^A%V݀Wm$dÞgL4qNB!qwnu} ":Us\)/_CEKdO?A^׹3~ܸdeKqo~Ԧ⏡my 9ژ(xP\Q.Zp6XU̷ꆼa5{6,y̚{duWBT ^JJOLvlrƀ{6@!bbU( 2G7RZrrP USN+1GէPfxY.0'z٦-hW$3Gd =yBL8tx.Ο7Gv; Mz Y.رuDƯ*F D&۵A~v'JdSS ӛ,%0\LZ1to׆$f7ܹ?ko3[i9%[iSeJy6Z~p"\^Z|,X%> DYD>C**^^&#*ց|nZuo%O݂+<&.P\B ,YD R9I{GUB)'_صf m>yG^q< .mZX5.9r# GoIiW3\Um=in1AZbT U=܄;=6F?ZbiH|c IdC}c]طk|J7^n޺IpVR})J4 ̇mrdz*9rB(@o.azM#~V}?}v!i9֦^OTb,LFjL'-Gw(U5j]埠 .}t 5ȴ#3NJ2%EԮ 2ŗ GQЦvc.G.}-,]IqԦG\Xd$ڡR:֜E9U4KjDߦ猨/ DҎdeio }1T\(`{LҴy+zUS܏>YK??0~|Mh >*SXYD6%;xPٜg<\PMQ_q:{(jJv*Z`Ҍٍ݉t9< s]<`Z BP6&:1ط;T>a߫~5􌊊"+R~px6hPsFνj,b%=Hhܵ&Ĥҙ{Hl`&)/5$ߗa$%+[l޴ƏkB OܜސLxHIE*NHC,#ׂވۋ{;{4g+s!ؽ{ƺ'~-j*ᕹoݵ3Jk`g9JwR)|cbҤR[ h!*9u?Nd` jpX(Sag^|VcCӥQ#a eX-,>](lCƲ/_Nvi-}O!'GNrm~3b1ж[ͷAXc3S3}qQ6 F n$ϏEzv)H]V :x _.R2cL_f&S,b4+oMFްiU/oxM 6 >V\(4pA\ XM!}#π@3ۻ38tx?O{^V+)I^V|. c1=y'{=MfSԩÈ錜<Zelݬ2 9PQӆ =`u=̝RυEGIԻxiL? (Lq* Iy /nZ2\L/CF~ :#7 w+`)pF|{uheUؚ2QȀ1A` \~iэ! ?PGeGxuɵ9t:cOPMUzg }kI~o:Ty_;97޿3`)|Ⱦ.?mU? MzI))hwa]5cfʵ+̘rlL6b-\$v0;,"b)Lh(J)ďT3'{9{=+3'ҩ4k)MxO04n8'W4~L;OH>%u* ѿKr#rGJlw3E~ n|qv;L43R6!**4r`,1lX=y~.ֻmGw`ڳoVb\A_,9r(d]+'Y(e6 찋dd̓ ZYSVlǎrJp*"5-˿]w/ȷb'ʀ^b_\*vA( ~ *;F 0YH&k'䒅p5>)}~Iݷc)A?[9zzɥ(`]x7$7$詳Ԧa'EUSϷ}XҔNhi *֋OsLO+ Ы!O/zNb*l ֊ٰёM7k6oF63ffsZ\v^1( ? vx WKR5D +̃X_Fزi=U;PRB>A%S=edVG.QƑ%{U^Id GbKsP[YDY G64uM. ]~!ظ#z92sq'=VfXf]#̱plӮ}T)'v–/@7Yw9D:z>s׋&(=*Xzyn! ,4O=` ƌ K ko?R9-o;Ey__o^âf{2gPWطq~8WU#N*}?#6 :yza J [5Ve 8Af e#m׎Hs(/oΟ kbf !xntEahlLTgg$vXƥXSJze_>zr>j*001Euh1STAnvFJj ;JD"&4*w;B0|@CK\XZ01#ڐ(_Ic`Ȟ,([cee>]F֠>['NĈ߽'(ڲ_8K9@|oXmԖe z&@O) l#ઘnЏfj&({ ߯1'զ!o}&<%uQ^K==7'{Zgј8~L!hK>e!c&!;)@(i9g ?AFJjKU͸雷c$`-]30e<d<^ev?WG:ޝK+**RczA ;yh>}D{jWO.]9̸/oo~4Y UѸ@+C{َ_JZ*zpW.Ā@c0dﵺKќjrصrң) A~&}͝Oq.ظa3ϡj"?j| l߸/KlO,-q_RV`G@V[<lYOÕ"8󚱖>wC{w#P LPze! Ū?+3}b0eK :ڳ reqM} Z|`6ՉC=|Re45 //pd6ٗIr]{wkß̿d  =Tǎ 庺rJTo&At|cL/j&R &!3w^+( ;n.Xr>zv+1xvlJww\T܄Imo2ܷ)"XqKi+X|5{ ][H2.FP oTPҗ7fP69uQ$cVݻGVp-L5V((,DyI4 ֟:]&I$54uZu*ojq 2ak#XZ|#4Mc x_ALTӅ"±Q_ro l|&;;Iӧ~az[ܼ *+̅ ]XnI%&&Ҵ߉)L0B'b͟'Հ xo11# ]P~<`d ՚縈LOǶm6~\wW&iDof~Ø@;xKFƮ= ª`>w8A:x::"/%c[!U&8<$wxhois#%&՛ cNv:E4:۹uEq}C{/bA{$hbM4$&1&$[,Qk%AA  |ͺHF{ ;;ٙw9?Gq9EtG+E3+/'1t#)>U=!7mކ  ʶȞf%9EH.[+Mt3!CLxo Kl.2EbN)*U$jQ6"GVe_6 d@gJ@ݳٖt+X9Rl܊ݗsS"3 OO{%wnVFbÃ`N௙AO\ܬ ʫDOi6S A X}f͌;ύ,*%Sj,~skHLMr)rik jJd&ęPOooS.5c$xz5]DĤLBJ96_C?kϝnz5=;aJXYd:Kj*V`)bmчɢz@ VsLoՉv؅ I#{Yʹ0F;۸CpSYEdݺ zu"0>q;)&M#<x!AQa Q7YPuUKNDȱ>2dL/]N p{~\c*= XXh= c"R=^qS?e3 (2Ȁ" d?"<5Ox-kOhxyhs'޽wYF󂍋rxӓ@)\ue2k j!.ށr}")Sr FsIc€Vp gD94DbJed$`?1O$J~~>jI~[^:!rId At,",1ބ! ( 580Uy;~  ,"97jC(,̭fd@ƒ>Wp;2oL= N3)s|x,ȤO˶5v"@ֹ G6Oѷ%89-S[A.]p#TK0J4qrR ֖pt/aaht{W:y?A;# {>| oۛRd\y~Rc`h@ߗ|%u5qgGOxO>;FEXrt(}0Ыc{I˥?|O ~5[Գ4D 3A.  1 ?G%=7 | Pуҭ"5"9;ĩShgϞGn]mf-8NŐwǡ(+ hhkp1VCQ~:l{mբHrzl} ~;$̙ K4nOVl0ϓhJb6 (é5 NN><^mz o8uo"c6 B @/fa%hoFHz$~lѼ C/vMiݺ5X.HLr4a[y&ЂS WTV.YNO3Ķ O_S{h%u4av7i:Ӷ f͒qt M( ȿmHE^[]ёi '_F峔lS}`lZ&;%ٛX2o#J X܇U…4]9D~aQ~_$6RI;q Lz.ρ.\(3ڶFs~-4Җ; V(IDԴ0iX((.f ` KFb[O\?Eˋ,yN҄+V!tm\nWE>ev~ QGwaB-'6OQ>]j\޶ Aٰ5W56?澾Hydg 4C_e~^"Rb9p1ie,Aia96ۅ gczb~Ԉ>_\Շ;uui֊~ua΍XPn&칳,Ԥ[>?%6S  []^O*:Ud@E@U-Ԩm']Utq]ZZ6QM zwKLAQ~f6i̽)RhyOv-wӿ3,(Q\s˜+5!/TD( פ4(Po%2 NBQL"تqF_Bl]֖QYadYl=;; 4@v\:y 'TT쏍PQR5 8S⼧iS;`Zq4mJ!v`?}{8#Syz,ԣ?$C},ݠߜ5eR,U:zK+K2|#hJCc&:0AZB9死A28D0Ď2z]5f"J ҪHTQ#= ŏdJuhAz9wXw] +"#jkNjVIYg)CidG p5#`֌ٔt,,") d%% s/j^yoc߼00% (^G(_*#J x[8AM)h2p8s)IUVl;* :rh 2)yZ[XgaնNGېAԶ^,@f ;c{$/צ6<%%={RʡF@5sD́KKR~=IJƩ Ζ>뺦'X pR|dAQr8?Q2'#WnD|<'~GaG{6˯|-Ѧ?+Իxo?[-pEl碣cc4'sNh ;ְsy&k(٪Ukcď`V`OŋSo[)5:بFdQbJX >7 fPӇcάn- GgRZdp{{{{i:qbQ4#aN f.EwTm`yCT,عknĤPֶbSyތF6Al4(g %~G|ZdjJ r*7.\ Ĝ#0gh‚sJ:M}[ӷTU5;c'}Z3d| >}6u@ME2t.X>mڳmk<;ݷŖdYz`6m k?_ ȱd(G)o4Hc}0w)*$߽6*  FF)7oL@ڍ8_PBd7 KU w?JԙI;:<&;n`qVA(햆_+ A#+yѺk-]_=3ظs-TӍ=)2Ȫ2rU ;ymBF ;#bhd ?O!kյ$A7cT9pLGݣ *_)Og'GK]mi24Y/-1315E QC櫭il c,}aW_~1(3&!ƦfUWTP? lӦmv\}ht> mJЪx9*:KKK5qm">0"J.%WH_F4Cl%(uukF  (Vuw&te9 PJ:%%^hcD@R7D*2 Gbb"m}W;2*o— HeUAhh5LNɋdu'1 ;pts UHQSvyFF6Hxiyܼ='V@x<qPtJ]L~N?L //222解] !q+[ I%2i-_ɽr-΃%o }avVt.R͛˻|d%FȖIq|`oXXbҢ*wʂf!44#$7fiݏ@ oHWX1}ǔZ!rsobm|;{|4CUop{tlۙO::u6(ǿʕg|}#Uْ9ؾ{;0o<)֡ "Ḥxs6\IhײVΆ#s $(aFjJHF]=[du0Z zp76Wv lm#ϧWH6,C^!b1VT @MO+M6;;fLVyچl`oWٚF<&"j?d6jmz$ 繜7#xiOGGYJyr; Bcynvh#ֱ`eS?-3'4 D'e6J޸lBzEbz.\ݽϬdwJhgQKy鉨sJzMC];NKoţx9Lf=<yd3"8 bJs:P/;@Ym(y{x@VѦW*V6^^TJPv?]z~X:=v:&n^(ϫ?$4TjM`'֬M5#L^0a'UĂKbHIJnK j G^ zfR湍Osf}Nu-pj}o=Y`#=S4i{؄fd}2 gU'-ـs~W `;viTh%}]rފ"JIb~XTo9Dy]|6{vA]G[QISrWb jٝ,P3 AMn?8R<↦氠oK^<\qJ JofLM[A@~ÆHhs,L&F umc`(%>z:PbIt4rRٕP3nȂ D_BHiY`K`۽f~e"|6lՓ4[a-O6o\lߺrmc-^ޢi&!F,?VzwtvnbnSq.Z穌{&L2f%@aM-cԯo 3* #.G/CvP[)WݺC}(+vępxV=O2,B1|xg)gA֊3 #+2Lj:0b"^|~]._ֿ)Ȁ" JC=]ԗ) 0V,oS1l8Y{%dsrG*,FBbn$E%ťhbhĢwE<{FMVWoS~qһ iF[t]8h^]8_M4L x|֔dOLŇ<)O#=Ue) Mu3` ?-ҏo_R,C*X&V:UxLVVNxVU2؂B&? `]b HTJ-Lz{O6Us~PCRҗ(U5VM*Ξ9W(G#L,$0&X#zl;LlCʜOWX'є H/?7C&Up>(!qf* bqO9ݒRdӘ\fXrO7s7O9C@Uvx*VdaAeU,Zi4xT.d.BUVW1}׹GZDEX'YkCC,a#ύ'B\1hCV ))޵c{J2F9d%Q ;n+U9OOOέXr)GX+ғprZSlxRb<"îS:m4l `w?bMWˠZ{ضs/-&!<hYY@倢ROQJxnuAܹSt%_bQQJJkQM TRB?3YY?m {c0.9I7&M|@lMm۷ eK!܌>u63pțkŁAR_ߌKW.+rVZ*WGVb[oxvcG.\оs׬ɯBN\>}91XXN}++fn/wzV!!k!3 B+2tz;r"ƾ;a˟"!׮b/b ESEx $AL[VC#%{HZ`:!I"#q\}86  :jՅ!ztv}轰b2gY1ʓ4yۇ==._ IaE(2_ʀ+U2 NBQ 2X2J)Z@IDATm};!H{(SЄjϼۅUd O>~-(f3JӊI62Y/\έEDfƢc#(”ΚPKԀ=(IY#}9R=%3xp2'g#! crai[@SR6d&w յt'B0;'pG|qa;>1'E]ۈ0g|dFOZAִZ%&ôWrޫJڞRfW[V=xo$yy5kjW+) JsV9<>~)&),2j'^1a GUھe tth-y@W8v$~^NM@C&pÎ56=zڈzZPբbpj2 +45楑f7"(3Æ|q>YZW4<qދ7Gصpb9s?FIa61qT܈/µ hHa7fg>ۧ+zxK>+U0Xt My.dl^hck_iV-[jjS{'yXNAII1<%TX U$2kk6~Rs1qD+N}7UKbkƘE)%"ܺs7غ7$܊NrKnuyr| zݠM Sc'țWK66rz-+ˑy&oD)kdJzcs>Ve͚4@T\PBlݣV=0¼R\\=j?uqdh^1EC׉j3`ElE %s4)zPd@Z3p/Ã{rA&ނzjmIfy˔p `һ{{lc-yCD]-)߁*d}$~Zx&n^*x )KV/d_qA>uy?[1! Ÿb\&ޮzw7xQ~3oⅾ (@֗n^T~.ێ](Ud@ Iq;:d|P``emhd%O}69ML;߅9Y~oQ gK $[L]ۈv)@̄;[wp>"R Gl0#5w{gac&J d;r ҋ,B^Nn%ߔ@ֲr%.pCڊ wԈ҆7&;+V(I# x`RZx<6$-̙ ;|6 ,A#SSj"1:>_OyFy|8}z UKEћסtq+$H+br{|G:8h4d|WÇ+2xxgL,g`8D! ]p!93u5@xx8%u3"99媪p!\č30| o[8ohu`מXe%XVH{a`ŨO6??Sױsݾ݄z \D_d  H/IkSc>|-(? J>6vq-Zw:Yaaذu% Ơކ?==ݐ3dv.f8G.وu$yW ǽ sk ʔ:lۦҚ4o9lzI[ﺹ`=gn<#./vȺﯭbJO 8g!MA[K^ı ߏ5s@HxPTO۞~RS_fgf<[7Gk>T9fUuS.\L+ָXлs[srw^Okk+Kқ؈^DݡD;)W)uWWVR#E9]@hd2蟬/F+" V9yEرs?膾=K,ߓ0OgrUjrw_SBeKǵ| iW"}|3몕Yեshp3[*Ţ>C6# _Kɮg_+^˫ S3jW/@=Pƺon~pڭB_U,EgD\PV86qlNsNn>R9lSFLz{.7$VZiZ" } :=VÁYN Jp.,(kV΀R!Qң`ID=S>Tѣg/z¹O)mZCr |޻U)vªcw 쪺*Щ[0$ӧ'Ss+\xk.W?CUY'n2Ps.ҪۈMǦͫG6Nͪ<BFT]x*1R]ǍK E+o_!no6@y}h Ok}FLʻ~)gNC'J/h>~*""L&X>2r<A}Xa@7,#JW/"lTetڸ!Yy%P_`_lGU ĸb|>Si, :|yqaucS lY瓧ҥk^WӽJ Ռnqa-壄?=AOkiݻο9 MZ(u= ~ )R[?/٧ı ^$@M;V>!!^#PX=voYȗ^^O_`mcMպɈ=w^'=O=7K9ovzR޽WVGϞcm ּǥsPLs8[=cJ07nkx2^D 7ѡCGAUC66Tk0@DmC禒wA%`܈25Q__Gj:eBQÂoz?+d43w.Ο[K@262 :i]-#-37sQrx*mOz6D39|{]4'L1!VLO'W4/S(͇>WR ӠLA, 98f V/[cG!*9Eז<_nq.6֟~j~@8A6у;*)fxu"PdeE]fwCTt,REeN{nܸ*xR۹/TΒ= ?'|D`if[Ч);ϳM~%1{LuH֯5YԐ]C:^YMHbݶMņ]K1"+s vk1֊ (_\n=+2xl9K|  t1+ECX\RZ=d ccȧd(oI=gkB|h L uդoely2zPW^:+5]pL4IOµ,Ӄ[]$G?ЌLJEN!Q01ŝB2HcaRYlgi+.WYэxҕp%o{ 4+dV!i+b -zԙ~Y3=^LtLuPfy=p.+ѹ{*iQm k<լES๼SkzrzXW7ϣ,[04榦V0aNt_|ɥn΄񰤏02`SyhBᾃT 8o7Zn_eURJ*TcKpisR7f"=XIBxdڷ UOšM\ftN^wBBL5Tpr6%%uWS5!N )yiE6%lD2zvP=F^gzQ:!qgEuXa^.Iu/]CslGж]7Jv@VUd O~p 㽘RyEmU=>?"Z1QgDI s{+cA8!o+^Zл&l,Cc dx؍\zI32eߧ%ʝ&ZVfEIz Kus޽ bcЉRBڬ+i 7`:d$}]xaÆMKOV,;{Ȍ{<V. 5^=.OSwFK_b'AmNѱ oE5kdNw*̎.NNCztM̽>S:whH{u'$ ٟ^,*d:{#1wLQ} d[ܑXfU".&M}.[SNIÖ_g}vF,\d 5-5}("E^عK‹"5Ǥ/fy (͚{}wn)3aq)#,Vn",(/&Vi Ide9wܪEKmd YsOPMThdKc*ozCO[R,_5O3OJ[s-M5>^vն?.-XE^VTl"Pdg@+/8)0uHOJ{nض*/VdCGjNlx2 $}!Y`7ȪřEgXѿ" (2Sg`cMj`"GZC`}a'Ou ߞ5',a C](1r~ :2d قfm*}IMz\ 8>-]潨 mZ@=Zߒ@IS~Jx9Ծǹ-_;ai=1yg>].^#;]׊{~u J H?7JPފq OBf^JM7A4v>I9ڄ9tIVboo< _TUgcPhҾ=ths_x=#SQ&}s$i^T2vyK %, ȦsU$ƦGR2RN "FhEpuJԛV)G z6%8[KF_#-%V+(ALn+>dGҿ(z|~g1jdrMxIu $ܽ{ښ-d oao֞sxc@ Əz{7#ZVd⸱R? }tdD$Giw FX@r'f-:BRc6bx.gz U%?`\be̞1 Kyc߳31ZVcu'NC.Suc_KΟPWBn c_GIr 6lG2%ջuB "x/#&LPY-]0lp07l)Ю};DE";\Vߍ4<]ܦ *Pˑ1ش~->5>ѯWZ;XMܥ81e%;wz<۱Vb4sj]mAGE̚a\- - w#:͕' !Q. @zLi GG??.")5vB8{ W*7߾q|WU水4O /W37ƏDln4XPF]3zyfEX> UBO@Sq!k՚7ƍIv0ZxQ;τKMؙhTb^ݺ.GφE5>W"pz>Ag,PSQqIog԰: z*̀T(ج{*U{GGEgt v1R9ٛh#.5k뙥0ђU1X' JH.Ο=kVN:)W~m,-@V'#A<ݒR<>HHLFaQ>s蝶FZ߄5?~ ܡc-P'72 }Ⱦ5ʳ:[`KE KOMy}`Щ.-欈}Ԝ!tf.5 d ZkBFL=>zZtGiJ}_ũS%aia:`u]<~Tj̳U֔:%%}]Ȏ@RRzUڋ'i&I3el RUb!2AZįa'gI)k>H.xàG0d+K{pPaưD' 0;VZFqedϙCބ|oZѪ}@OKCVT&Mf5.J9hB&]ރ=1&MCSSΰ z*ZLbefa#pvrDLtT 5'ޝ!PI01a5#bСaMgǯZ*_DIʾ@u>*||Cyy,dGZfdbJin G¬JVSgIEG|vQAN)zrԼ8A#sO0sظn#ychب!<=ԏ*!!bNEn:{/؟#Gܺk7h$ٵv:vV 眄DRWnM]>q-_ \<(k}lO&v`3ޔZ :wc#)Blwi 򳡭GRS|XO8 3?NF3dT(Cc ؟Y"aOɜk՝.8ga}:r^d^L6ߵr~lR'FFx-b-nh`Pj瞃ص BPAN|:u  ZCR]gAKF8y$E66Vi]5cs1S3pf-ĨA=%뤑b'ÒI 33.VˑE7> !/&GNOSnT?ƅd$L吚9a.ʝoݽ(_9 йcʋOF0]=],W؊Pd@hdd7nͩ{wT7i8?FE0x]X[6>&4rCmM2sZ/uj)+|,oP]-d`)_ =bׅ^Wxu (@;8nEPd΀9_lQZ+*^k)@IYΤ+j,>k-] p;.wC#t >[`| ; tnEWu}#Mܚ 9G$E^0ԟ=%MΞ&[c"{y*EB\!xJm/̆F9\y uCKJ|$ygCAԿ!:E=} -d^hpF o1gW̅R<f-;Cn^r9K 7}o-b{Nz,((x~B-d7_1Y_}uʪxs[3U¦g )>k 7եM֯__ZYINp-!@X/8kGATU8KҀwqOe[ZYƵغU*bH!XDe@2;ӧNb*{1v:ujMVzQEѪ]'I9N_Vӿ J)W +m9r } 4ؾm *oyjoת%x{yc4v3wG^=q;;Vشy;f},_n ;,ưk㧐&HMĎnSz5µ>{ۊcɓ[ptypf(c:8APKG) {=ލFMO1)XbL4{]AzW HR{G 7owggfg۷owΜs 0uTܼxwF 1c4^xiL]&=NM[/ 1Ћb11'jkRH>ӤXlhAO`vt\œE||غ/=qB@~y+͟ ҒV+ױwٙ|yh~ܻw$0KtS6Ab}IH60o0tUp-\4ѷ@8;ׂk[8H Z7[/Dӱ;pkZ_ [2ua8W.]q8{|d%cT2$e5ըvFB_.k 0sJ$8/k|Ѣ8ƾ Ǥ}VodM'VoXMr;>˜QA_=mOǸL'kjl;>[Zp \$KP5n)S jKWh* ޽m";t!tMLjL_1~͈D # gⰍ?vnXn?oܐ`ŏCrf.y?S_&\> wW_MWO|=o">xLqž+]p߰dEtdKq+_9X]Ū*3@uVD;)5P5J\7z3 p5~HY# e)竏IQáA2ܒ$PK,tvhlanXh ל絆8U{#6E>Uua B߻ٳ!(2 {cjPh"<}F e^nn{JaWY;={1zg6oxpx8I 'G$b 1vT~4`s ZSQjffI7wYo&kvz2?jێcީ/ dgYqQ8|20b)yaY$:2=C'kv(|8:xd&ATʋ EcݳHO[O`tw2'U+Hf |ڤ Űֿ:W/`?9IPM61kMe!¤.?:D2 `0b:X&ٱcd⃁X7/B{e-k"  un">$,Ɛ|T7#{}3AU3jg.yV8z#hJl^vۼr96)枥e~W^f&څQcIU < wL9t$&d /|i#~8{ j5?bub1S$ I1g3]؉#O"I2JZZZ\[#sXpKzU!98퓈vj-&n$H=?3I)S&ת&\صߗn#Ic%; `eՒ7hf܀UFCixO_ Y}*&nuXRm7oن6lى.e*_t*hW=f%8@5$%R\cBDEqd\8֥;jc+s$T`b̈_لWd_<%AR+d0_7UsL$NJI!߲ У tR{[g#eZ"|FxZtsuwg1f(bxϞ;6m݀żSPH&X$zڔa;j9cDA"VEs%yC+nY|,Ԭ$ك#ժA0P$b$e%Mݨ1| |xxg}&unhPv@o= -ߧV֦(VsD=NҊDOIMÕ{h׿ G^=(v\}W,6];SQDҲK^FWEary${x.4';5Uh`MIzgO<Т<23R J*L5^Q V=bZPj{)bEģXxE@=f峍'\ `|ke&Gmac br;|D$@YV2"Ȉ|殭z=< X ڴ7!{_qw.&fWE1mow"eWl;qIe.] u8 #YѬ5y }6Ҫr9Fѭ&MY]<+6mIJN}j?Fl]q|n'ٙHgZЋ$]L'c+%r:2(M.1\Hբ|2"mHB./XvX1Hy ضe]Inf*;c>rqAG[^K)kH cEoJr>#B5*dosÆbJۏgAOF=|$uMkŢKx4qH+M1q=O1DFMCm5\Ŭ|xM'1+ee/{_xNtre>Cq2r/ܵЅ)0 ,Ue.BCj*CʕXl[5mH.@Bst'<3g"0M.?r"\p͉_:uLL=kS-<&?ᶋ+zUhn.ӹ&,& !LcT=\> K^l3ywlܼ)<Ι #8/F; ;3t`u耿;̣' miZ<U_ Vؽ4˽ hgLbamsTdxT.G2B 3cf4MQp={d׿xK-[.÷=Vj 5TdYLAd|rKq8l=n; bGMLH26:+nMb^h)P-"IY eD1^5*1)uU"@qi$>i{tu0_ڐ@.KV_TCzmXӰfUU#ZHտnAN$@' eAL‚"wo_Z;#;~ ́>MksZb@,M:b4Sq9H槡,FB+t|2AJJ<^b?`F,X$gV^*? }''9ioĐw de֬k+# 9h i!~;w׾=;C௲7u~alP<@C{@xkCo-<-ZZBFF\'6lِ=kBrGTz2m@IDATefggDXD@'A?`kU0WiJߕ.l«0\3<GCC#WR YQ0sD$ِmmȷVw)a5NMCSyL|vGBrާIGѱ+lK*H(@FVQT@ޕPlJ^$2)L"|FCNN1fFEb_f2()u]af1X^$[KYnTX,[iTRM F r󐣥WH'̴%I @Fca2!)\aҬL=䧝9 }H浬([y4L]637 nx*}rE\\ 5*#C"Ze!E~UԆ޾BS$Sc:?)haGҙMc OПXLzW=~/Е$9~IU҅Xc 0qRmy_},F#@0!C[GO vFӓ␑ \Qd5"eԨХ:yxr0n<nOt7Et}YXrRPTADD$ b$QAk]U?FgpujA2MH>۶ Jt/Tiv.Z]ꅳغu bpq um_PڐTYtL,{4Qj7}t$bАh$ SNd?$} tp(f~~~$i[3S3s ? ʒ4Y$gmL2 :`׮УX)(L CRAKwcװUp2 QhMbrJCUh˶3f*sRB>k[2? 滵xt YYg֐A8ޖk!sĞ}WyGRܽ '`~4ɖmweOS'vٕwQ,t0)'& _z-|GSm ORml&MTT™s7ؽ1f(sMo/`].-W0ֳv")10/TqŊZiG-2v G`YMGN$H<Ťvq\ r҈K,.62SsiQsGvH:\hfZû!yhkl2-Xh@]U$/&b/^8 ZRGx#KģR `~Q_}%\+pyݻv_.o?Ac]_Լ)yn ;¼~!lI:W:PezVt9W. ts4%x(А@QUv7;g\Je78ȸJ/pyqS@JO5o{}U2KB$%k7RZf *xk`Y}c==3Y?o?$oiBju2==䑚/ mG@r BKKjjJ VMu5hPm#9Vs,kq_Jľ郻pr $`dQ DƼ"dL3/bU; Fj3t<)ARIlvЬ2dk7CňXǘExڵӅN;Ct0  Ğ[ѥ[OY t }oYT1UXc Z+ݮR9H"K$ V)H򹪪ugkoXQ[Y>@=wIm0kbEVO+|&('^xnVź#$M2ݻw %AXު+B,kuarM:vvv|mmA$Uֿty1W_?> )`]D<1cQ,?¾Q2OhFAv[Ќn{TFVFwQobeC]Q\V--:&DE)^uƒBVΞĤW8o'? ö/ ?@IA>14;™'&bc⡤ ދqL""CS/W@[^9W ӵcŝN40CGb܅0'F1eߥw~sm_a캊cVّZ:ujyk[{;q1 I2ԙT-[)b|aƦj7X_6.ӢUYF$g(:g YDWWBtj߄'b@0 R֪#d,R2I(q~xw0[pR-ZC;x= WKySzk8c)-- ĤRP,>r*:r +W?t}BpU H VV>62H.Q2d,䒼c`l-i0]Y GHbաk7̘7h8@Wh& /y4%D 0RɐTS%#1sɴ(D2T=ĵ34u#5.[CN=JL-YCcHP엊1/85/&QgXz[Y⏪}0ؓf4U ѓaVa$<#s^g-(;[ն߂@%F#&X+el2f41 4 2ߔ˹lCI}199`+ܺnVO3{gAAYm H*HS9MYZ‹&7aʤ9HH|B<3Wߍ442I]&.ֺ: ` F]!-ՔYY>XVՉZ6YGvgD=@4Bѭ,̄*4lG'vL6bw7͡*?a*K4.#M3x={Wy>D0p"#8(HA1rKW:= v@X+*OC:&Q زw94mL*.HƗ)[LEכ&l[ݡJ8U:m'UM6"ms6X>ox)I tap!.2ն[-:*;۷W} k+bцa}.¨C:$;G}~~ ];VVnر$ۙ1Oщb%W4ǩ\cRirƄ7ؐ);*NzSP!VȉsSQ`e4 5ߣHDs\{Nz6$` )oi0kCkn}aE%9?K(.BqQߧdU`dj bƷ|_')JNN*֊Uu.BEl!4IEp<jUab{ENeFC`2Fu$ڵ&h EroVVW~Olm$"J`NLU3Cǽ[nPGXD$N:4acS@8_35@u0w1~EU(dj. g7t^ڕhҘcgRRD(: U\HKzY%u>Omu*aZU3*EjqVv`?Q|ӹcg$#7/ڡ:u۞DZӧJSH*m_{ٮ&ν>m`Pux_={}i͐!'`q=Squ$͜]0!~*#*4>c>XPYLDhd:\m}*ܙE쫜W)pypzP#/{dȀ9H ~}\]ܒeKB۳`ʕ'yӛpS(,j3sR26kgPP*>VXӧp8i4lȭy < ]4ƬsI>t4n:;#3'Ot] y"Îc`JޟwY?> zl,:lP8?|jbwc(Ǒc[0$Ձ$KYb~V=[g 0F23` iťfb݆-ڬmowg4Ql 0#&7?ڍDjd)63\V6rCn(n6_m$f4$eZaE3)"<lނ7I[Sצ)!=cqa,L&",&ς#H7kDT,\Ya%tj~~u!4OtSxƥ%FIڽWq6L̟=kv֜8ue1g͙ϖ/ir&<~ &!,#hYZxcpXIR2-@nA!d$ O乺 vc` ֪Xc IiA]EDF텻eV-)urx|0` > ͛5?˯Vӳ9 1! \HUM<=]2k$H 69Ym}-S±z+\?K 3$, ?2d;v˾zn_ӧpn4Dί[1i=:d}Ky={@Es=(f}56m r(=ْO?g ?g1V)cd fR^b  RGT1|< }vj;}o/ :d h3_e`@9{x1GϚA2DjZS҈H>cb@Tl c4a/ivaq}Veant꼏CJՙM70c{KlgU\=I/ C zFP+{% pi >X YkCcҽ¥5~"Zw}wܣ%YHKOF!ErroM1N5k=\"@V0,%l{<b^'kqƖk+_aɗ`\?Z˵q}',VrEJJ MeQЄ$_~ 5ͪ׶N87ܩS݆(BV7,f (TsEr-ʇ6M] -ѿ@04~Pl3dR[ˈ '&֓cZAv֘9{ob̞99!be '9@R{7߆qǶ6|<Cn"@_d`Pߚzs6:ε[4;{aja^Ff͸ݱB£q1\}O=@[68Pj|l˱XYU +o``+.7}?xY-,xNr-Ld%Q SqB3]$HI@In:^FZ3(7K76mށ{wo'QW=uNq Xtj%22d1v HSi L,-б"$% +## <9swoS'saJ3{wn$}e-!Hg9x '%9 )#oHI I/(05/=LOۓdYHoݹz  _͎UT%F Z6ᤒ5f!/nm d)K QD1:-:Y6MtuŽ߷$$I'I5Z?|XwCzZ^FMsaOU-lQ:޲'Ʃ okQQ/0y]&lK7SKw\o]m%Řq% dX:tFXbo W77 <XSl|=Ѻ6maKE<޻$We Ԅ&q{@>Ex={@X]o߃EhB9!ٺ-%g#M'gDF ;_}"=wC:ȃhBdءrJqHE]P$Fp?'aj Y5c\]aҡL$VcŚj\&մBߪ>w$R\A*Xkm_K d=v|ibΏh<q 8{fΜA$tFWeu{&0:$gbđѱijn;y-_?81bwZ|F<}GcY oSfa%$cAIkID=A@0[yoCR҅<G#X٢Z4liY},<:&8C-1{\,*gN%(ƎG71f hb 9 _bڸ1~^2g5&o]Fl }#i醻5ړwaaG{1'\%5 d,kAדkjk`@1t7oZnߥGaddCJ]t9uIz ii!ho`'A!@1aŧ"Φhе?M9~cP!(J+˗l*f2mELyX;G.\/BfܦtfDz-NЪW|%u,]3hyf;Аk}TUٽTb;XO:G`ȊU8 @VYtzwX{u'h׃py&J#6kS?u$nr-7:N]aeґb\4H[nɩ\OF'ortCWhaca mFdP_D{4ٲYPX0xU5|4+-PwY݉ry{>n\laߓ^$@VMeWDq>H^̃gc[]r\.LJj7B^3 ݮ:驉DkO[5'=i5bbBb9AdssR`lC~]Vl ի*>b|X Zo"#?U_İ\7/jPNEq[).cx)V?D#(ⴲ>%'c 唠I['Ig e|юR꿫V&+KLdZM-m^ҋG`ni$Sنd"_:yTb~A97j""2Ő9YuYil$ᤣ˥u_hS|j hu=~}߻LΕp2VMD2h$]z}jc\}V/E2ڣEljQ TFFSTew\} Wn#%/~= L}:ZӃ$+L 9`K1%Ri F: }1?ϓ0_+>+$Ab.5zFv%6&od&b@@ٷ1JJбk@zݿoE7TenJC#mD,] 6jbŗ^_j}3$P_bIbۯ `[BfГV+ɮ9 ;X_+5/fX;`eݜ:e:K1vlP;ckY>xxbxp"B r-8V!d$ñ[?,#JXXؖmOmi!Cf暘0i WNqf::ڕ[WX&q~]YPVl : յe˷4a&c`jWy~Mu+ӧi͙ =<([6c4ZPBRxUU$ɴTfǃ'v2`KN3pk e@tA \у{k&acLU㒰NuKt1*Wc^pEE7g*`t c$)^JSbaq܄m2*Xٶ` V/]6leUmzFZz ^W&iJlN9yʹOޝu5,b|6jh °ۍAŃ<Uo Vkۀչ@{}2˞w*0Y]y\Lt9 re45@SSnbe!<*ۇn@E-JxDqwuttp%.mrk*saRtl---b.C^É{Æ /5c>j?5$]wC+&X]"W(WA]v@1`HFYns߷͈n#:~bkWGC̝3n>~Ėh3F OcФ*U-7} DGRF9φ) zr?j&P33FIYnB1Re dեeAV z(b嗼x=az+\ )˳0TŅ xϗ7OJIEGځΞA8ZGvPIVXLL:г2.=I*h=~߅sR~R 1KzF/zd2.x"~ڵk@!y#s!^eaM$)f?:3's۶?&1W9ižRiC[-?_0,@'b|fie aE ;z\ӽ!\oɣP]t47$uibM:NR2vhg wæ?cg#08?.o[/[F#(n˝ÀV&M W:`yŅhJhOӺK?Vl]uqx={qzaT_@V_iu~\hB,p ׷N'| L6N?I)`Ӝ(BC7׌6ӳ1 0BA-QPC[8C"&?nSűCnÏ߯+5eg6kJ,6&z^nq~>b_7'm~ & WlΤS2:~\wK[.ς_ß" ڠ={c6oR7S,~J~}W| hJ֝[W!xLSZ`qHH@'R/99 ČC ſAO&[Y*<`ef<_Rz[sM28 8X-'E䁅$V a,WE\1)1Z)Pl~(`d'CezY1}VT/O`Ъԭ'N9M]LgAB;_,2ۗE nÒ}V~DzEz?F$\֔dyzʕ `NZӒZ*i-l6$'SCXWceg]⬐&^Cܽ OI<E3dęaGkhZFMeuw2 ;ở~ *_|9ijeJ3 }r,VV̙aQ*KH|7mǤɓfuLTI̪ؑ&GffLZwzΞ:.W!ÑH3\cV$cӷС%MQ`%hKqjMiE{ 4:bm`A }I="l%RY+{D[#1k~_={ RV!5dzUիX]OҾѭENǽѺUK&'CkvÕ5 mHc-dH)^%AGCEt1qX88WrDš ;;@W+u!f# ._ ZkŇc0k ! w\`a^L}PW+Ş=\z4K0TDĂzhVW 5)iE_!Yb õڷ7ϳ` ;3,~ùc]w}stgQOnt|OCƥϡԦ-MtdKftAHLex4 4Fx={RuK2+}#3b[6,* ?HK7G[|I@nΎyAضv ҳrɶ~/#^ڵ7/ |OjrFTl,99ӿ֗FM ܊O}7Iӵ* {6x-TT9!P`@R'wVdz "e>_;a$c:[ k|<|̬L,7P;B&7wzlsHJf:>@W3nMu n؍;Ù4ùbZY'7(5MM"ߗq8SxqhӺlaٸ=l.^xx*]paɏ####P;}bY N,MnbGW5/3z? +]{Z\+܊={wjB.X Ҁ+BL TxΛs?7s,㨛GNvM GQ 8:wGm6_dɔ1u)sWԨ(Nhq(Pn}grZ+ca_%YȲ::VyF8es]u -IX78X_ٹ[([$m@XSS?b|yrU{}6;!^$< ҕ%ǔ5@=;)Fs],,,Rib\HQE +;Gаa#DGU@z=jU`a-˸R#cc۷-{,":uA}QS%%ey 4De1fMFRQ`عm3UQa?emoPRT J"YGfDtsz.O˲h^j 7%b=p)fcrl.英r Μ8=IZ7"\H.|qP_Sdb њڴB{ cM?+;b s9jLɝ13,_.$~R62K)?d2ɪ4i. Ʌ}Mٹx:J`Ϲk5Gjz:,nHǻCzFe@Ou-&012(Orr_#"*g.Aγ].3[ 'qIH!Ek}}^m[`L #D:wE&z8p:뀘8ls}#y:PpOR95x0&OGY56I f %0%42JT /s&gW/Q0pXbe֫[W-X& -G hʽ7*V2!7 h)35W낥ޞkbM$j8n-b"a%k>POpw O"p<]1kRaE\Dܺ%֡ fG|ѳx/rAJv֮ ޼ŻEo ":]m2vQ#[aF+`Umo t?XV K% beIQڟ'E!#q]CILC%:E[ ]tEKE6o~<<@TϷبRnڈ6nJիYWCԢʇ<#Gr3N.8Xh\ԡ!,X2uUx9phE=}Cz`ǜ3K|ޢO80$~*He߾ë/L⢩+:e.p_S,W&̺lV./Э/CѴ!tYmj7KBa֜GFviO Vrc jZʼȒϚUvxfr i#óMĄ>kGYV&bie]Hs -DݍdȊ{w օJ=Mm&t1FJ up\"3K-[`ApvñcG`5UL DCOWvh@۸9cHa Vnx"M y¿$==D -YEJVҞ$pss!׵ϰ&xkqS\⇽'/*7wr; _YdJn{. .8j=`$~c#v,NTTT*UeL5yعs?[)_|CyclH>rn@BB8Wp89r( s3?NEMm(?`v߆dž&h)jW3'K$SX4+80ѦCp'!tt 7uQUY`G&> \]p'V=C=sb\Ab]"i J0$ bwgwtnw"xԴu`FVpd9HɃGi># s7: w?q DVuWƽ;' u%X\ۻuFW -FXK \bm߾[b)S'bYb,Ŝ3U朑N={q뱭`C.^-I’g\q],܄;hc+:X҉\jba?VlƨH=&O1Rݱ`ؐ۵w*zh3/s>t; "g7o|3~őf}/ *V7sVg!&C1׳k_O֠w/`gc%m؂:Zs0Ǝm.4KNNXj-ƌO!Wg9hJ&/#YJ6)VU_t) Ӧ-kh'[:~<FA=޷a!2M {OW05h{GG Y?mJqwd*{>U9E#4U}DQ +FZKu;MytlakVc  pS/B7/wo":;.^ )pm&:Ϥ={GE\ C@=GGG"-Vcن-puwInmqhRx8VxrC^jHҊ.NpMk+:P ퟕ[f}<Z&2<*=7ln^ 2_% 7 1b}3<0ڽ vvQ`Y&>k++0?z\*\WAF ReDo~,"s nIGHz  B0ohK>Y$~d8l|-b 3rDp/.K)RW\#X;Äxp~([2oo& J4a$2o/ҚV;B؂.ٯߠ^ .#",;)qeRSAha}V{y@}^{ ȝ!(8{+f(sX =Ua_vj{%Kb#`$kxH8&ޙSF # 1$*,{.̉ޣڏS\ `DkKCؑ|-<<<<)c̰QH&9p9,Lp?:@ȈV+&@BWV,[pUYcV8 #Yl؏&!I"Ku%u9`|[DQ'\+0_ 2\CSls g Y`cH!G#F_!}-;|&S.\]"CWIq23+͇ICm*].6>/ $'Wq˹3GKOxx)_U3?*@uD`?ptu kz\T&+[[0rEV23ĵ %`xtc -tStmWd!lєh6U1tED ֋WVC,D;w ,1IM厲d=OK {bVZ҄Yn G*PVFfVqs_/=fΜJnM.0"W/ pJIDǩUTփb$:phK9Q9Hɉwq\zzx3wW0n WT 59(.|bP|ޥA]C:D񉏐&@6o%w䞲oGTȝ7ɗ=zCWWF8ü(3a,?|;V.D^Y݇5992j4cɫ@]x*v&ޅkW $%%gsps 7&HMʔt0g.ɂ擋p=ɋ}:F~Y-) zZS߻.zE1}::KBd4ۑhX`,{S Wn_b\q v.h(ft=uxsQ1HM{h )gH_ q=~}͐;; ˖P2(4'^ܲkX>####P\&e+>ֻh;P-;"ԉtMVܾUKӭOqX)m^}qt^]?DpfEVabbACQ)˞3΂,hR=d ٳ0f:~֎b]:آLDnӥWvūWx"jjg[BƹʹjcweL==$8+x5k(g.(-@qk/% aT%z9GïGGGL0II2 ^ƌ`:\ߵ=kfsF$/@+zL]UU Y٧oOڌ0mz é󗡦xFx]W jq՛&-=/hlU0Ҝ,TemH*>ЀEW䇀@?&,Eh DmX&Hn7l(ׯe7`Kx7)g7 )p& om=ÿb$z;l:4AW~E%M"4F'{Im?de#,,\u 6X 5v~we=&"?K0)1q#Y˻:Am`(1̎KѺ]7"_%ɢeˠwWg8>y̛a;w& `pn [Rʻ}MIA^LC0#ߘGGGG )B;{ 箅^nުâ.KT. b2Wډ2Zҟu_hG"%ֳl@D$l00{zE$F`7ߔܹ kު^fQ[O}=R0; U"V2rOO##Pn)|G#Wʮɪ GFŃ.̂,k<'Q0I6i `?sZfujA8q2 "3m`UE_KB|l)py<+nX*ݲ Aek -&L5Y73qtr)Brzh+WV5hF{,=<9C$rnha 1]&HzDBOɘدcSoSN_|% naإ"+kˬXra hL%ڱ/WwGlLr7|.U Vk["+6++SPT5"+۾zG'or`em"~A:eRb[G{`-!GGG#G,1ٰa )ɗ@n0@#:6/%SĄc <$Ri?7x"544?yHk&2iz&450tH2 " ƏH dzH}BZtD@<&y6 W:aј?,OE!W!y5|+ܜEK\##P$kˏ##PHL|PV["CzuXDnrʼnVraRu>Ec4q%0l F!EUuix c,2FqI.)1X;faZVܘ`⪊'!PqI+:U\zZEFWUˇM6>R,tATes%O,`[Uo8#Z'=X42咝Kkt*,s+PlEPڽCUY9?[}'Yz #3U[[ F W;8Yؾ _ [I컖7||*;LNs;Ek ͹={sWE&88]] ,Gnc垎u,\4_ٌIS{V`*"oH`ةeŝ|L0+fჸ⚉=S,Պ)"wBٶ0\b53<<<<EX -* (ڻG[wr.77E}u(w7L2PnYE@:r*K56pU<'J0\,z(Ch޾]Z5<)45(p3):7d$x a!g<$ė|!,X:$XޓXz]yxxʁ.]xxj`ݹc~iV*7^ue$+zU4;p%d۱nKE]!F}eS{ PWS;zA@0T60Y/_CSY\knV/[fK,G@,6UqY|z뱣,UF&+ٔU d+6P"tW$,F4wZJhԁ *OS'p[KփXbyS'Lp yzؔaZjGnQTn#Eڴ űxMqʒ>GuE=.^X~+TUp̚#GD~vK~0\tQ)eCqܑ c]pXӫ)c9XLkKlM)xECⵢc43g|O Ƅ>>F.<1i S팕 3h]z޼ W|3e&Wm6D`$)8 cGCr6 'K!?Ȟ&##ZY XFaD\[! *ua<<<< Y:X<4n ]#{Q}Th?L@b8r }1gڹ%o9tqXSɊ[N\E/ZsTP"xq.~fΥς*N9fM╚L{Ln؇1>:>##3/_AmD 2LjT De#Ѫ nA1!>diU<穉P3+i/)^ǪRԂAQI,UX6Aer\i3 *[,Dn]M'@4+ `۞u ^ OҢф̗'0ROU4hԠ;▤7pdwGƯ)oA ׂ3/,_ Thiadh[/΂M⮙GIۿSZɴ)QV;k1nU"ltsg97v0[ش˪)WMU6~^eGb &Łd$;!==5d564KNШc#kARӇ܂&odˎ-0d`Қ@ "*^=N#:L7G}-ŗ<>2lV._^ڴi~-ōպ2>tڵk ڀZpRp2dg? qE@k7Wʪ{FL5Ap\" ♲_)Tg#)9eV/iعl{=?Tx:r򈈎GJj& u؈[>L6܋SC _Mp3Ӂ$N"AA])=͓ät?"P-h![NNT(E6-8nֈk./Jru,STݧh'|[UYbg #toVu3H9nl.J[#ۡ-JT%kaɏ6ɳ}q8M*vBZPP N{Z&L7`d]!>x_TPlbÒܶ #> z`XvLNr #Y!M2(<"cogߑ'y9I?C#}ԟ0n,RLR?mlVlX40n[A%\akLߎE KT_GqsX}5ߏmRh2d⮳_/ 6mm7vu) a&f&W8xndzm}7x͆RFEF;5V._ &ݻزq -,_JQ7n@-D !lk?7{|\DM`e[a͐Wì¶0 oM7Chŵ'ӕkVam%*}×T: _ fBKW xxxxʄ8ɺv^K)h3QVP({{Kgh,)vE@P V~E2ڴH7ϔ;1z" ,Y5Hx5M^n{P_rmdKD>]ZsC6zhApy8T8N%w[P*,{9@%#[V2pBo"'GK\AU5@MG`Pnzظuj[KZe#IP^.d hkbc)i#C=0K۸ʪc&7//YaQxE|LcVYY֯Ņs'0z(1ĪMkq@?LU5LufM5rYk` %99._ꭇ ;((I&`\6lE0,T(6,3p>m6~x_T҃re0 Vf:'GY~SպDUѢdp6%1YYOԥ¡(g}QOvk,JC]S(OVں Ê+^]v:"QPy7Yk7{ΚǐlɥCɲZaÆ ORQMp$ VG.RA^R ?#Cq\B=Mqn4D=-UYݣ[Dy>)?5jڐW=+g;5)@@=/]#uhG^Q׻UGV5.E}o4@SK XC"{EFZ#08F>cF Ŕ\ާX(OR9x3g!$nHaXzqJf3s~xy }~ʤe~w"9|#фgl΋x5.cس{76lt45lخ"ۀ_iH|>###!o~]~_}K\"H늹e]yhzF2:L1z L3`}"{\Fm[`\ۊlnFċtfϝG.u@T/tdo/`eY *}YZӮCKΣK0k=o(TkrX<w^vT7x&qthQ*Z{xIv*GG$kE@ˊvԳ8oц| X B8F]f}ٔ6N:]֠{^\F~,L͇+*|3 ~;n訩b%O7{;de+KBYu CoG>*,³;yU*r;{hhe`uq(>c525>>gϟЁ82Vx6=_Q} dFd=V#`ily5:]3+5f*$Zy"++#gm`K1 Iê:xbS*ZU$X:e="FX{v庻lFgJVĪa}=$`'EؙnËW! thnM1w\㩑uڶi.;HƟ vG~[[mFJբ֢Te4,3S`T0uҬ1v ɽ DwbBiɴq&|GnUunh5h`HE? Ef^ Mx dNxÓF6Rhaf|kp\~ sѯG栴ud=5Uӣ{z+3 iPlyt|4kEDz,2Rsq.]s }`uX#B࿁&uΘ/M&ȓ|EnU }1W+ݡ;;*pbx ǩ(m>/ڹBP.maԤprs+iyǤ&%]_`Νk+KӳպN|4L7hnf+F[S@'"Q>.#Bʕ66IDATB'w#PTnveF"U&~@¹\ɓ'04K_X(u,źY *fZV+V#f(®:Òq#Ye zTXQ/0{ L3+$?swlL~gb֯Ֆ#K01Ǣj$ tM0rhx'OpCo䰘Y35v/U~ܹ#VNبL'HKz';mi믬=qUYUqN; ĺoZ%qΟ|\& BVc6r/-[`o}54quu%RU@¢YC : GF%^*$WΟEpP@:ۈ\zB51&oS1f_d,. xkǷϿO26n\ 2b0X= vl8m;zQ1w7֯[+w(U YFESև(ԄD####_ҳ_PE0aD֞em.s; ?TYr5ٓyX~hzVB)eg_o|=yl^#2MbSr{+SC0_Q.[ͤ(*XgRwO"X!69v|%@c7FlLߎ\ j~?)"xcEȭʘ1S^ A #5)t+ 5Sk`Ū%عm?nEVT">LW Jޢ`9?R=g"`Sox[>####P6~f>]b (<ʶz۞y8ih@!Nod\jxs#aLVvaH=>GwPyHzr;8v j:Dq˵{k~}&k'|jUg^]wQȆ+J4|0Yrfrt0zrDZ V 2`=tL?/`ݲsD|Up- "凐۷>;1u9n dm ^o^Hdz^qk˗XsF}7 7n\Ƣ%6}* (2~L ׈=%} bqazr}^枥W@@/@ ? "6~aS"gYz xbĽ(mh4}P?q-訩pW>UiѢX `DDäT=9u`.YWUat8P77Qs4h q\ӻȐ(=wKNn;|,\lV{lCJ+-<%X٘W^w:L}%XņkK*ɋXX.ia1h(/ ];ċ'J"+lF^: ).XbbV7Y߲T^0/E# ޒU:.|i9`VFL@#Pع$VZ\L |fzZR{b݌Ȣ٤vŅfqWתfrþp R2Nn>vцנZoqaR1u' r Oww̘>Ek.~#KzVO<4AbuA!px"eZCnf ̚:TL`?:W>=j0L4%eZGum,=YiOɁT%-k\]bO"dQD[ϐ; _C3\ylj z !lR+֬c¤ɵz> #KOڜ8lĢnw Yw⢖GCpv4qذn֯߈UAKS u7-[xQZ:gt~噊ìT1_qlWcYwx/M1~hQgϸF=>V>###PEy(_0_HępкԙZXcaټd ĔqJ]+kP%k]H\L>9o9%}Ue3epsvZ_ $rKjbڨإQV=㴧\zE26LH _##P^xK"@@<>VP!U{*GړXesE~ +ħ;j<|>y yJ )@=ȹqu<#W+ VVnem9IA#3avbk/Iۿ tѢ]{Z*N"loI2` 5N]:OFSPl&ݲc܈{ ̉_8X>x(2CBtml rS(/{y죤ղ o;ha CJUA!%Xw?#1&#### F(J<jksAH%+B9L̒%qakn~%r>/5yp)+ӗ!66sq˸ uUf3ܽ' GS'%ʅ',題f<! WU؅cqr Y'Buvhܸ Yڱ -qxRoj:qǑjK ľ[&*ВMWuMg8`Ԑ]j {uR=MKnK@J׈Jle *$^'.":>\vʈ[qlKV00kfg!=h^iM@lz<1s[+[ޞqXoL=icLb(*{׵{YKwok؂bT$g@KE*7726 3< Ρ7)?$ABBF'1󰑣8׿b'}}#xzxJߋ36//`si}l\]XQ1шVDw΄EDC w"0ֶ}쬬0wve=aW'8;qc>N,cb1]Kj#+deUh2r",X)/l}v֔l$*mٍP;L%y Ѩ$ĨN *JXT%+ʕ+`Ѵ1?ga{wa#W#P!xw`bv*@1C&i v7bX/$H*XR!Ў+qcˆVYIf.X%NEzEݮةTFK&+\28ŭֹE7{>86\+"~+ #9>zu˗#ONC-JLӧX=U94mnV$O$󇞁1t+?$92VYDV8<<18rlɻEhެ,׭ǃ{wП6tmȥ4 0/С]"Շē,L0ETwNBn/O3eyQ]y2d Ͽbm,p8e;Wzt?~V5G޺9k?J~>uw., mqH<@!"s^@_=V@F 80z?4Ք*؃*D eʷC 9ݼn=9֍ !ٺKv@ɨqjI+IKŨa?5=Ujܚ#0A ѽG'Z5/S4L04񞷄5kkY4.4ŢEmj ɚֽ03gQ=ʄlaҭ|NNID@t-%+WHV#=ŲҾ;]BK[[[ 4-i *kfs X"52[,s+;/6Z07|xOm5֪rUe  WzkNLnbAN{iB~F ٜgKKEI!Q2AMSjf6ۄĄGMNjA|*.c:Aj VF6=?|n ڍk1qo%;H_LIcC,&Sԙu֌#5kŞ}"-#BrP۠I(]_ !Q+zSL;  w/Ӧ_aq1hg6gQ|b+横'S"Z-ajB Z&`1v31HMSOI{QV/( ;bǷ;qֈ𦨣oRvOŖGe##lŪ9E>ЄpRT4S8?_oCCж7,g` XE H_IWSs\zzV#Gkst,,<#Pg*d9Ũz(¼Wzug dثuO?%/sU7spE U')bL; M@/{׭?LMU]C 9= _ $_^Y '')4),sb)8w9WnCxu'ďÃyv_',Xي\0#:v6b!o٩xɓjL put Xۺ wn4E׬يUcagDI7㚍]! #<n)`xC1t( ߾Z^v6Ç[>WahԵ'BODTF*Eb{{"kez\"Wh3,Db.M4ڵ U]t9uUL.ABAʺ4L"X@.]_ Î;S蒘Oeߛܣ ^.=7$R)YaA#Iw蹬~oZ[]0,l*.1~h]Zn5'j* O$bxơ$kk#1#H,IOr S#n! vOj(Nz0GkH,zeT>Rz^q[ַU۩VFý/^}m!{J.-O|c;oJ~;#|8l L-`J'V_'rKŰяBXš,dAZ$rSFS#;Dp"{A_Õ%p !έs"q] Ї=#Yz!rUDfBB;;,Ktї6Um >0x`leEdyjSa+Vu"Uek>9Yx8¬GÁV_0"tR+._-[oǶTfF`=MqlvKؼy&<|"1-%ўno %g/#ߍΆCt^t2ظdK==ͫ8QG`ҍǞIukL8]G7zei\;=&Z[񥒙Ѵ<#0@XzDza  Rg݊ƒ{Aj3+(A"6t10ҋ+^Dw S|K,i3U.|Y{wa?$2 *sM;E+ڼm|; *SbӑغE| 4b Uќdd1Nb $քÿ7%&MD0@oj |X' !axLd}  P?}0 V|lzmѪJ@ԗ甲rUMkߣH H$'; {VT .!>Ri͂9O>!ꭅ[S`F}">k&XQ%5C0kTxq'T{KJMH.sfʈd.IݭೃqC#caD<---p@^^D Eמw~e;%+WTWb9Ӳ%kˣ3#8R''>]׮!,1hn\2qx,1E !]Xi#Β5GL!qD.ml; }TVAaUMkj]'RO'@O[Y1(arz&f<2#tn!' 4" xs7!WO݌zp/ȵSʱtD~1ewڸ{Lȥ9Y w9|NKޝeziim5Ǩ"Js$ŠUH ŐWXyx71}-Ȣ\)r_;lHX*#jɏNح2+VUmT rVRW)v|UXs5 (ECp>qg=4Y:O !il=)+g/_WMņ錯<|\Z8yŭ¬Yp) >lyYa(~rmHuX*S ?)OmݠΖb$_F>Y( 6a{Z<˩3ۭI1&Y;ҫka W`eedT`=E1% ;*'%%7Zhkڰ[#oV)(`ɢ̛=޾B:RPU2$"?,%&e dlſ0q܃HLLMb̧/; 0MƫYnfG(Y=$X<\UFAIYT$dlHjGRRI2ןL*0n홫gVA:-#sΩ 鿶 YgΜf{HҒR`rq֖n9Pf\! #3>!Q=|-.DVQOZYx&C]\Ǻ/^IBgF`:"7hQ=:\ɓ'O0B꒑{}Tv߰n5b nz}{δ?32eEGt"y27OSHϝmW7xGHNLƚMk80#z< ~^wԓt( b>[n͊ tzWٿ.ս7瓹rQÂ}=wVT!ZY4Ygc2_GD5) ڙf #$bV8eW e-xif)9>8=yg052f$:ls+_C+F͟YSKŸ}GQǣ>L(mrܹ?Ǯߚg|dgˮ?'gڱ#4,QWLP2QG}}63B}뚐|_\'>1k7UЍM%XVE"XEbmEIJŦou{*oo|9B(kn/jwߑVJU/b D{CŘ=wtϿF@sRS!\!XEU$l$&?yLΓ=Fnխu?ʿVIŹ%%~V&j"jqy-VE F@d^J69jseD_S V1G``>pȲЊ`*k7)^kVaW;g,lCZjQGL*IVp!#0Yz7vf0bHw0DjI i{ Y̝k@Ŧvk_EY; 5~r*쯹ؗ5_ymtqĄIi~\",X|>۲ڒuG!R@p`u=gszRYWcǒOjViO^)AV]w43v}&XλTo8عWޜiÝxΞOO.}i!~ܵ]jfonwU[ǟҶ[l5ֺ%*Ff "E}ϮD PA"',EsEO m[ ,- nyyF`F@)z:l-s!#+MJ5֏1hH$ ;3^Gj`Un0iDns F"wh we u߃?^y9yҫ X=KJLW9~<^^Rx;c|̘cAR]d6N[a#sjM̚4|ćWc蠈겦d}1||t:N)AʻEɼ,z2\v mRORv6k18t 21˜`ei!%emeVVؾyOA~X[ I֍=oOȒ4͗6`0qP4ϟNj.P}={"^kcӪ453jh 1fG՟wVA$cC" K*ߤGwWƠpܺX"Z7 w Gi"NA_tN}5ە&Ru(Sgٵ F`:yan]T U.v9>ٶ ځ*j7: PuvRx+9 YN\/`FhjګgVckZuV\GX.uиY=Mzsb`gDzjT]΋Z|0ݡ#R`>.\LCWR AfF:,%& IH|,յD +֥-EZzT'XJ*b:rf9d.d/ID=6FJuuN!cj&n%+9 1DbaF`E@imA$erɥlbR"<=ʚq"{n\i&1ztt)Bŧ ̙%n"֌#0@dUߵc4BVRXx׮]E^>w[Lx%v3nuv-t̏`gk N~}r} >nF'[!‚Esѷo_|f zPow| R}brݥ  ^uk`na!%1)]t0'a#Gh4v9juc͚F (LַزsJ/b`rs9jF:F7ah`)LA]-zwӦO?Yۑ:qip =_^{bU1#0 !p\busPB>Ų2)kO-\mQ\xgKwE+8{6|:™u¶]r:ՙ,^0!2Ifqdtv zGqrPȍ{5P9F@gȤxMgKuFgVTsjhd#Cjf4QQ[呤dعvU&?{N.p$Op EݔHX.Zӟx|}.\l[ ~Zm;l:|p$=DJsSGyfQ*IV|J묤hXٻJi/?!r*g snN귿gj&$$"88HeChrU&ʬKTM{A—VV6,%mr{F`F)TqAFfETٝTl޺Cxrt2ٯ_g]>`d?F`j `M(ޖt<ȪK뾃{Qz,ڿK’ҋ4]YX`%oёkCL-, N+LxeiQ\]]^5 ||ae8Uף"0 !?߽~&fpWz\ -._'0s_`ep{Ytp7on߮Ľ{wLrI$ H #ڟ>c)ޕ(ޫC:8*,XmgѰڛkF`F-`U=]P_7~d̝5~%=?/عݕ8A=x\0t"4C~LOIENDB`colmap-3.10/doc/index.rst000077500000000000000000000064511464745566500153550ustar00rootroot00000000000000COLMAP ====== .. figure:: images/sparse.png :alt: Sparse reconstruction of central Rome. :figclass: align-center Sparse model of central Rome using 21K photos produced by COLMAP's SfM pipeline. .. figure:: images/dense.png :alt: Dense reconstruction of landmarks. :figclass: align-center Dense models of several landmarks produced by COLMAP's MVS pipeline. About ----- COLMAP is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface. It offers a wide range of features for reconstruction of ordered and unordered image collections. The software is licensed under the new BSD license. If you use this project for your research, please cite:: @inproceedings{schoenberger2016sfm, author={Sch\"{o}nberger, Johannes Lutz and Frahm, Jan-Michael}, title={Structure-from-Motion Revisited}, booktitle={Conference on Computer Vision and Pattern Recognition (CVPR)}, year={2016}, } @inproceedings{schoenberger2016mvs, author={Sch\"{o}nberger, Johannes Lutz and Zheng, Enliang and Pollefeys, Marc and Frahm, Jan-Michael}, title={Pixelwise View Selection for Unstructured Multi-View Stereo}, booktitle={European Conference on Computer Vision (ECCV)}, year={2016}, } If you use the image retrieval / vocabulary tree engine, please also cite:: @inproceedings{schoenberger2016vote, author={Sch\"{o}nberger, Johannes Lutz and Price, True and Sattler, Torsten and Frahm, Jan-Michael and Pollefeys, Marc}, title={A Vote-and-Verify Strategy for Fast Spatial Verification in Image Retrieval}, booktitle={Asian Conference on Computer Vision (ACCV)}, year={2016}, } The latest source code is available at `GitHub `_. COLMAP builds on top of existing works and when using specific algorithms within COLMAP, please also cite the original authors, as specified in the source code. Download -------- Executables and other resources can be downloaded from https://demuc.de/colmap/. Getting Started --------------- 1. Download the `pre-built binaries `_ or build the library manually from `source `_ (see :ref:`Installation `). 2. Download one of the provided datasets (see :ref:`Datasets `) or use your own images. 3. Use the **automatic reconstruction** to easily build models with a single click (see :ref:`Quickstart `). Support ------- Please, use `GitHub Discussions `_ for questions and the `GitHub issue tracker `_ for bug reports, feature requests/additions, etc. Acknowledgments --------------- The library was originally written by `Johannes L. Schönberger `_ with funding provided by his PhD advisors Jan-Michael Frahm and Marc Pollefeys. Since then the project has benefited from countless community contributions, including bug fixes, improvements, new features, third-party tooling, and community support. .. toctree:: :hidden: :maxdepth: 2 install tutorial database cameras format datasets gui cli faq changelog contribution license bibliography colmap-3.10/doc/install.rst000077500000000000000000000233571464745566500157200ustar00rootroot00000000000000.. _installation: Installation ============ You can either download one of the pre-built binaries or build the source code manually. Executables for Windows and Mac and other resources can be downloaded from https://demuc.de/colmap/. Executables for Linux/Unix/BSD are available at https://repology.org/metapackage/colmap/versions. Note that the COLMAP packages in the default repositories for Linux/Unix/BSD do not come with CUDA support, which requires manual compilation but is relatively easy on these platforms. COLMAP can be used as an independent application through the command-line or graphical user interface. Alternatively, COLMAP is also built as a reusable library, i.e., you can include and link COLMAP against your own source code, as described further below. ------------------ Pre-built Binaries ------------------ Windows ------- For convenience, the pre-built binaries for Windows contain both the graphical and command-line interface executables. To start the COLMAP GUI, you can simply double-click the ``COLMAP.bat`` batch script or alternatively run it from the Windows command shell or Powershell. The command-line interface is also accessible through this batch script, which automatically sets the necessary library paths. To list the available COLMAP commands, run ``COLMAP.bat -h`` in the command shell ``cmd.exe`` or in Powershell. Mac --- The pre-built application package for Mac contains both the GUI and command-line version of COLMAP. To open the GUI, simply open the application and note that COLMAP is shipped as an unsigned application, i.e., when your first open the application, you have to right-click the application and select *Open* and then accept to trust the application. In the future, you can then simply double-click the application to open COLMAP. The command-line interface is accessible by running the packaged binary ``COLMAP.app/Contents/MacOS/colmap``. To list the available COLMAP commands, run ``COLMAP.app/Contents/MacOS/colmap -h``. ----------------- Build from Source ----------------- COLMAP builds on all major platforms (Linux, Mac, Windows) with little effort. First, checkout the latest source code:: git clone https://github.com/colmap/colmap On Linux and Mac it is generally recommended to follow the installation instructions below, which use the system package managers to install the required dependencies. Alternatively, there is a Python build script that builds COLMAP and its dependencies locally. This script is useful under Windows and on a (cluster) system if you do not have root access under Linux or Mac. Linux ----- *Recommended dependencies:* CUDA (at least version 7.X) Dependencies from the default Ubuntu repositories:: sudo apt-get install \ git \ cmake \ ninja-build \ build-essential \ libboost-program-options-dev \ libboost-filesystem-dev \ libboost-graph-dev \ libboost-system-dev \ libeigen3-dev \ libflann-dev \ libfreeimage-dev \ libmetis-dev \ libgoogle-glog-dev \ libgtest-dev \ libsqlite3-dev \ libglew-dev \ qtbase5-dev \ libqt5opengl5-dev \ libcgal-dev \ libceres-dev Configure and compile COLMAP:: git clone https://github.com/colmap/colmap.git cd colmap mkdir build cd build cmake .. -GNinja ninja sudo ninja install Run COLMAP:: colmap -h colmap gui To compile with **CUDA support**, also install Ubuntu's default CUDA package:: sudo apt-get install -y \ nvidia-cuda-toolkit \ nvidia-cuda-toolkit-gcc Or, manually install the latest CUDA from NVIDIA's homepage. During CMake configuration specify `CMAKE_CUDA_ARCHITECTURES` as "native", if you want to run COLMAP on your current machine only (default), "all"/"all-major" to be able to distribute to other machines, or a specific CUDA architecture like "75", etc. Under **Ubuntu 18.04**, the CMake configuration scripts of CGAL are broken and you must also install the CGAL Qt5 package:: sudo apt-get install libcgal-qt5-dev Under **Ubuntu 22.04**, there is a problem when compiling with Ubuntu's default CUDA package and GCC, and you must compile against GCC 10:: sudo apt-get install gcc-10 g++-10 export CC=/usr/bin/gcc-10 export CXX=/usr/bin/g++-10 export CUDAHOSTCXX=/usr/bin/g++-10 # ... and then run CMake against COLMAP's sources. Mac --- Dependencies from `Homebrew `_:: brew install \ cmake \ ninja \ boost \ eigen \ flann \ freeimage \ metis \ glog \ googletest \ ceres-solver \ qt5 \ glew \ cgal \ sqlite3 Configure and compile COLMAP:: git clone https://github.com/colmap/colmap.git cd colmap export PATH="/usr/local/opt/qt@5/bin:$PATH" mkdir build cd build cmake .. -GNinja -DQt5_DIR=/usr/local/opt/qt/lib/cmake/Qt5 ninja sudo ninja install On Macs with ARM the brew paths are different so you need this cmake .. -GNinja -DCMAKE_PREFIX_PATH="/opt/homebrew/opt/flann;/opt/homebrew/opt/metis;/opt/homebrew/opt/suite-sparse;/opt/homebrew/opt/qt@5;/opt/homebrew/opt/freeimage" If you have Qt 6 installed on your system as well, you might have to temporarily link your Qt 5 installation while configuring CMake:: brew link qt5 cmake configuration (from previous code block) brew unlink qt5 Run COLMAP:: colmap -h colmap gui Windows ------- *Recommended dependencies:* CUDA (at least version 7.X), Visual Studio 2019 On Windows, the recommended way is to build COLMAP using vcpkg:: git clone https://github.com/microsoft/vcpkg cd vcpkg .\bootstrap-vcpkg.bat .\vcpkg install colmap[cuda,tests]:x64-windows To compile CUDA for multiple compute architectures, please use:: .\vcpkg install colmap[cuda-redist]:x64-windows Please refer to the next section for more details. VCPKG ----- COLMAP ships as part of the vcpkg distribution. This enables to conveniently build COLMAP and all of its dependencies from scratch under different platforms. Note that VCPKG requires you to install CUDA manually in the standard way on your platform. To compile COLMAP using VCPKG, you run:: git clone https://github.com/microsoft/vcpkg cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg install colmap:x64-linux VCPKG ships with support for various other platforms (e.g., x64-osx, x64-windows, etc.). To compile with CUDA support and to build all tests:: ./vcpkg install colmap[cuda,tests]:x64-linux The above commands will build the latest release version of COLMAP. To compile the latest commit in the dev branch, you can use the following options:: ./vcpkg install colmap:x64-linux --head To modify the source code, you can further add ``--editable --no-downloads``. Or, if you want to build from another folder and use the dependencies from vcpkg, first run `./vcpkg integrate install` (under Windows use pwsh and `./scripts/shell/enter_vs_dev_shell.ps1`) and then configure COLMAP as:: cd path/to/colmap mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release cmake --build . --config release --target colmap --parallel 24 .. _installation-library: ------- Library ------- If you want to include and link COLMAP against your own library, the easiest way is to use CMake as a build configuration tool. After configuring the COLMAP build and running `ninja/make install`, COLMAP automatically installs all headers to ``${CMAKE_INSTALL_PREFIX}/include/colmap``, all libraries to ``${CMAKE_INSTALL_PREFIX}/lib/colmap``, and the CMake configuration to ``${CMAKE_INSTALL_PREFIX}/share/colmap``. For example, compiling your own source code against COLMAP is as simple as using the following ``CMakeLists.txt``:: cmake_minimum_required(VERSION 3.10) project(SampleProject) find_package(colmap REQUIRED) # or to require a specific version: find_package(colmap 3.4 REQUIRED) add_executable(hello_world hello_world.cc) target_link_libraries(hello_world colmap::colmap) with the source code ``hello_world.cc``:: #include #include #include #include int main(int argc, char** argv) { colmap::InitializeGlog(argv); std::string message; colmap::OptionManager options; options.AddRequiredOption("message", &message); options.Parse(argc, argv); std::cout << colmap::StringPrintf("Hello %s!", message.c_str()) << std::endl; return EXIT_SUCCESS; } Then compile and run your code as:: mkdir build cd build export colmap_DIR=${CMAKE_INSTALL_PREFIX}/share/colmap cmake .. -GNinja ninja ./hello_world --message "world" The sources of this example are stored under ``doc/sample-project``. ---------------- AddressSanitizer ---------------- If you want to build COLMAP with address sanitizer flags enabled, you need to use a recent compiler with ASan support. For example, you can manually install a recent clang version on your Ubuntu machine and invoke CMake as follows:: CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake .. \ -DASAN_ENABLED=ON \ -DTESTS_ENABLED=ON \ -DCMAKE_BUILD_TYPE=RelWithDebInfo Note that it is generally useful to combine ASan with debug symbols to get meaningful traces for reported issues. ------------- Documentation ------------- You need Python and Sphinx to build the HTML documentation:: cd path/to/colmap/doc sudo apt-get install python pip install sphinx make html open _build/html/index.html Alternatively, you can build the documentation as PDF, EPUB, etc.:: make latexpdf open _build/pdf/COLMAP.pdf colmap-3.10/doc/license.rst000066400000000000000000000036541464745566500156670ustar00rootroot00000000000000License ======= The COLMAP library is licensed under the new BSD license. Note that this text refers only to the license for COLMAP itself, independent of its thirdparty dependencies, which are separately licensed. Building COLMAP with these dependencies may affect the resulting COLMAP license. .. code-block:: text Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. colmap-3.10/doc/make.bat000077500000000000000000000144731464745566500151240ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\COLMAP.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\COLMAP.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end colmap-3.10/doc/sample-project/000077500000000000000000000000001464745566500164305ustar00rootroot00000000000000colmap-3.10/doc/sample-project/CMakeLists.txt000066400000000000000000000004001464745566500211620ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.10) project(SampleProject) find_package(colmap REQUIRED) # or to require a specific version: find_package(colmap 3.4 REQUIRED) add_executable(hello_world hello_world.cc) target_link_libraries(hello_world colmap::colmap) colmap-3.10/doc/sample-project/hello_world.cc000066400000000000000000000006551464745566500212570ustar00rootroot00000000000000#include #include #include #include int main(int argc, char** argv) { colmap::InitializeGlog(argv); std::string message; colmap::OptionManager options; options.AddRequiredOption("message", &message); options.Parse(argc, argv); std::cout << colmap::StringPrintf("Hello %s!", message.c_str()) << std::endl; return EXIT_SUCCESS; } colmap-3.10/doc/tutorial.rst000077500000000000000000000637471464745566500161240ustar00rootroot00000000000000.. _tutorial: Tutorial ======== This tutorial covers the topic of image-based 3D reconstruction by demonstrating the individual processing steps in COLMAP. If you are interested in a more general and mathematical introduction to the topic of image-based 3D reconstruction, please also refer to the `CVPR 2017 Tutorial on Large-scale 3D Modeling from Crowdsourced Data `_ and [schoenberger_thesis]_. Image-based 3D reconstruction from images traditionally first recovers a sparse representation of the scene and the camera poses of the input images using Structure-from-Motion. This output then serves as the input to Multi-View Stereo to recover a dense representation of the scene. .. _quick-start: Quickstart ---------- First, start the graphical user interface of COLMAP, as described :ref:`here `. COLMAP provides an automatic reconstruction tool that simply takes a folder of input images and produces a sparse and dense reconstruction in a workspace folder. Click ``Reconstruction > Automatic Reconstruction`` in the GUI and specify the relevant options. The output is written to the workspace folder. For example, if your images are located in ``path/to/project/images``, you could select ``path/to/project`` as a workspace folder and after running the automatic reconstruction tool, the folder would look similar to this:: +── images │   +── image1.jpg │   +── image2.jpg │   +── ... +── sparse │   +── 0 │   │ +── cameras.bin │   │ +── images.bin │   │ +── points3D.bin │ +── ... +── dense │   +── 0 │   │ +── images │   │ +── sparse │   │ +── stereo │   │ +── fused.ply │   │ +── meshed-poisson.ply │   │ +── meshed-delaunay.ply │ +── ... +── database.db Here, the ``path/to/project/sparse`` contains the sparse models for all reconstructed components, while ``path/to/project/dense`` contains their corresponding dense models. The dense point cloud ``fused.ply`` can be imported in COLMAP using ``File > Import model from ...``, while the dense mesh must be visualized with an external viewer such as Meshlab. The following sections give general recommendations and describe the reconstruction process in more detail, if you need more control over the reconstruction process/parameters or if you are interested in the underlying technology in COLMAP. Structure-from-Motion --------------------- .. figure:: images/incremental-sfm.png :alt: Incremental Structure-from-Motion pipeline :figclass: align-center COLMAP's incremental Structure-from-Motion pipeline. Structure-from-Motion (SfM) is the process of reconstructing 3D structure from its projections into a series of images. The input is a set of overlapping images of the same object, taken from different viewpoints. The output is a 3-D reconstruction of the object, and the reconstructed intrinsic and extrinsic camera parameters of all images. Typically, Structure-from-Motion systems divide this process into three stages: 1) Feature detection and extraction 2) Feature matching and geometric verification 3) Structure and motion reconstruction COLMAP reflects these stages in different modules, that can be combined depending on the application. More information on Structure-from-Motion in general and the algorithms in COLMAP can be found in [schoenberger16sfm]_ and [schoenberger16mvs]_. If you have control over the picture capture process, please follow these guidelines for optimal reconstruction results: - Capture images with **good texture**. Avoid completely texture-less images (e.g., a white wall or empty desk). If the scene does not contain enough texture itself, you could place additional background objects, such as posters, etc. - Capture images at **similar illumination** conditions. Avoid high dynamic range scenes (e.g., pictures against the sun with shadows or pictures through doors/windows). Avoid specularities on shiny surfaces. - Capture images with **high visual overlap**. Make sure that each object is seen in at least 3 images -- the more images the better. - Capture images from **different viewpoints**. Do not take images from the same location by only rotating the camera, e.g., make a few steps after each shot. At the same time, try to have enough images from a relatively similar viewpoint. Note that more images is not necessarily better and might lead to a slow reconstruction process. If you use a video as input, consider down-sampling the frame rate. Multi-View Stereo ----------------- Multi-View Stereo (MVS) takes the output of SfM to compute depth and/or normal information for every pixel in an image. Fusion of the depth and normal maps of multiple images in 3D then produces a dense point cloud of the scene. Using the depth and normal information of the fused point cloud, algorithms such as the (screened) Poisson surface reconstruction [kazhdan2013]_ can then recover the 3D surface geometry of the scene. More information on Multi-View Stereo in general and the algorithms in COLMAP can be found in [schoenberger16mvs]_. Preface ------- COLMAP requires only few steps to do a standard reconstruction for a general user. For more experienced users, the program exposes many different parameters, only some of which are intuitive to a beginner. The program should usually work without the need to modify any parameters. The defaults are chosen as a trade- off between reconstruction robustness/quality and speed. You can set "optimal" options for different reconstruction scenarios by choosing ``Extras > Set options for ... data``. If in doubt what settings to choose, stick to the defaults. The source code contains more documentation about all parameters. COLMAP is research software and in rare cases it may exit ungracefully if some constraints are not fulfilled. In this case, the program prints a traceback to stdout. To see this traceback or more debug information, it is recommended to run the executables (including the GUI) from the command-line, where you can define various levels of logging verbosity. Terminology ----------- The term **camera** is associated with the physical object of a camera using the same zoom-factor and lens. A camera defines the intrinsic projection model in COLMAP. A single camera can take multiple images with the same resolution, intrinsic parameters, and distortion characteristics. The term **image** is associated with a bitmap file, e.g., a JPEG or PNG file on disk. COLMAP detects **keypoints** in each image whose appearance is described by numerical **descriptors**. Pure appearance-based correspondences between keypoints/descriptors are defined by **matches**, while **inlier matches** are geometrically verified and used for the reconstruction procedure. Data Structure -------------- COLMAP assumes that all input images are in one input directory with potentially nested sub-directories. It recursively considers all images stored in this directory, and it supports various different image formats (see `FreeImage `_). Other files are automatically ignored. If high performance is a requirement, then you should separate any files that are not images. Images are identified uniquely by their relative file path. For later processing, such as image undistortion or dense reconstruction, the relative folder structure should be preserved. COLMAP does not modify the input images or directory and all extracted data is stored in a single, self-contained SQLite database file (see :doc:`database`). The first step is to start the graphical user interface of COLMAP by running the pre-built binaries (Windows: `COLMAP.bat`, Mac: `COLMAP.app`) or by executing ``./src/colmap/exe/colmap gui`` from the CMake build folder. Next, create a new project by choosing ``File > New project``. In this dialog, you must select where to store the database and the folder that contains the input images. For convenience, you can save the entire project settings to a configuration file by choosing ``File > Save project``. The project configuration stores the absolute path information of the database and image folder in addition to any other parameter settings. If you decide to move the database or image folder, you must change the paths accordingly by creating a new project. Alternatively, the resulting `.ini` configuration file can be directly modified in a text editor of your choice. To reopen an existing project, you can simply open the configuration file by choosing ``File > Open project`` and all parameter settings should be recovered. Note that all COLMAP executables can be started from the command-line by either specifying individual settings as command-line arguments or by providing the path to the project configuration file (see :ref:`Interface `). An example folder structure could look like this:: /path/to/project/... +── images │   +── image1.jpg │   +── image2.jpg │   +── ... │   +── imageN.jpg +── database.db +── project.ini In this example, you would select `/path/to/project/images` as the image folder path, `/path/to/project/database.db` as the database file path, and save the project configuration to `/path/to/project/project.ini`. Feature Detection and Extraction -------------------------------- In the first step, feature detection/extraction finds sparse feature points in the image and describes their appearance using a numerical descriptor. COLMAP imports images and performs feature detection/extraction in one step in order to only load images from disk once. Next, choose ``Processing > Extract features``. In this dialog, you must first decide on the employed intrinsic camera model. You can either automatically extract focal length information from the embedded EXIF information or manually specify intrinsic parameters, e.g., as obtained in a lab calibration. If an image has partial EXIF information, COLMAP tries to find the missing camera specifications in a large database of camera models automatically. If all your images were captured by the same physical camera with identical zoom factor, it is recommended to share intrinsics between all images. Note that the program will exit ungracefully if the same camera model is shared among all images but not all images have the same size or EXIF focal length. If you have several groups of images that share the same intrinsic camera parameters, you can easily modify the camera models at a later point as well (see :ref:`Database Management `). If in doubt what to choose in this step, simply stick to the default parameters. You can either detect and extract new features from the images or import existing features from text files. COLMAP extracts SIFT [lowe04]_ features either on the GPU or the CPU. The GPU version requires an attached display, while the CPU version is recommended for use on a server. In general, the GPU version is favorable as it has a customized feature detection mode that often produces higher quality features in the case of high contrast images. If you import existing features, every image must have a text file next to it (e.g., `/path/to/image1.jpg` and `/path/to/image1.jpg.txt`) in the following format:: NUM_FEATURES 128 X Y SCALE ORIENTATION D_1 D_2 D_3 ... D_128 ... X Y SCALE ORIENTATION D_1 D_2 D_3 ... D_128 where `X, Y, SCALE, ORIENTATION` are floating point numbers and `D_1...D_128` values in the range `0...255`. The file should have `NUM_FEATURES` lines with one line per feature. For example, if an image has 4 features, then the text file should look something like this:: 4 128 1.2 2.3 0.1 0.3 1 2 3 4 ... 21 2.2 3.3 1.1 0.3 3 2 3 2 ... 32 0.2 1.3 1.1 0.3 3 2 3 2 ... 2 1.2 2.3 1.1 0.3 3 2 3 2 ... 3 Note that by convention the upper left corner of an image has coordinate `(0, 0)` and the center of the upper left most pixel has coordinate `(0.5, 0.5)`. If you must import features for large image collections, it is much more efficient to directly access the database with your favorite scripting language (see :ref:`Database Format `). If you are done setting all options, choose ``Extract`` and wait for the extraction to finish or cancel. If you cancel during the extraction process, the next time you start extracting images for the same project, COLMAP automatically continues where it left off. This also allows you to add images to an existing project/reconstruction. In this case, be sure to verify the camera parameters when using shared intrinsics. All extracted data will be stored in the database file and can be reviewed/managed in the database management tool (see :ref:`Database Management `) or, for experts, directly modified using SQLite (see :ref:`Database Format `). Feature Matching and Geometric Verification ------------------------------------------- In the second step, feature matching and geometric verification finds correspondences between the feature points in different images. Please, choose ``Processing > Match features`` and select one of the provided matching modes, that are intended for different input scenarios: - **Exhaustive Matching**: If the number of images in your dataset is relatively low (up to several hundreds), this matching mode should be fast enough and leads to the best reconstruction results. Here, every image is matched against every other image, while the block size determines how many images are loaded from disk into memory at the same time. - **Sequential Matching**: This mode is useful if the images are acquired in sequential order, e.g., by a video camera. In this case, consecutive frames have visual overlap and there is no need to match all image pairs exhaustively. Instead, consecutively captured images are matched against each other. This matching mode has built-in loop detection based on a vocabulary tree, where every N-th image (`loop_detection_period`) is matched against its visually most similar images (`loop_detection_num_images`). Note that image file names must be ordered sequentially (e.g., `image0001.jpg`, `image0002.jpg`, etc.). The order in the database is not relevant, since the images are explicitly ordered according to their file names. Note that loop detection requires a pre-trained vocabulary tree, that can be downloaded from https://demuc.de/colmap/. - **Vocabulary Tree Matching**: In this matching mode [schoenberger16vote]_, every image is matched against its visual nearest neighbors using a vocabulary tree with spatial re-ranking. This is the recommended matching mode for large image collections (several thousands). This requires a pre-trained vocabulary tree, that can be downloaded from https://demuc.de/colmap/. - **Spatial Matching**: This matching mode matches every image against its spatial nearest neighbors. Spatial locations can be manually set in the database management. By default, COLMAP also extracts GPS information from EXIF and uses it for spatial nearest neighbor search. If accurate prior location information is available, this is the recommended matching mode. - **Transitive Matching**: This matching mode uses the transitive relations of already existing feature matches to produce a more complete matching graph. If an image A matches to an image B and B matches to C, then this matcher attempts to match A to C directly. - **Custom Matching**: This mode allows to specify individual image pairs for matching or to import individual feature matches. To specify image pairs, you have to provide a text file with one image pair per line:: image1.jpg image2.jpg image1.jpg image3.jpg ... where `image1.jpg` is the relative path in the image folder. You have two options to import individual feature matches. Either raw feature matches, which are not geometrically verified or already geometrically verified feature matches. In both cases, the expected format is:: image1.jpg image2.jpg 0 1 1 2 3 4 image1.jpg image3.jpg 0 1 1 2 3 4 4 5 ... where `image1.jpg` is the relative path in the image folder and the pairs of numbers are zero-based feature indices in the respective images. If you must import many matches for large image collections, it is more efficient to directly access the database with a scripting language of your choice. If you are done setting all options, choose ``Match`` and wait for the matching to finish or cancel in between. Note that this step can take a significant amount of time depending on the number of images, the number of features per image, and the chosen matching mode. Expected times for exhaustive matching are from a few minutes for tens of images to a few hours for hundreds of images to days or weeks for thousands of images. If you cancel the matching process or import new images after matching, COLMAP only matches image pairs that have not been matched previously. The overhead of skipping already matched image pairs is low. This also enables to match additional images imported after an initial matching and it enables to combine different matching modes for the same dataset. All extracted data will be stored in the database file and can be reviewed/managed in the database management tool (see :ref:`Database Management `) or, for experts, directly modified using SQLite (see :ref:`Database Format `). Note that feature matching requires a GPU and that the display performance of your computer might degrade significantly during the matching process. If your system has multiple CUDA-enabled GPUs, you can select specific GPUs with the `gpu_index` option. Sparse Reconstruction --------------------- After producing the scene graph in the previous two steps, you can start the incremental reconstruction process by choosing ``Reconstruction > Start``. COLMAP first loads all extracted data from the database into memory and seeds the reconstruction from an initial image pair. Then, the scene is incrementally extended by registering new images and triangulating new points. The results are visualized in "real-time" during this reconstruction process. Refer to the :ref:`Graphical User Interface ` section for more details about the available controls. COLMAP attempts to reconstruct multiple models if not all images are registered into the same model. The different models can be selected from the drop-down menu in the toolbar. If the different models have common registered images, you can use the ``model_converter`` executable to merge them into a single reconstruction (see :ref:`FAQ ` for details). Ideally, the reconstruction works fine and all images are registered. If this is not the case, it is recommended to: - Perform additional matching. For best results, use exhaustive matching, enable guided matching, increase the number of nearest neighbors in vocabulary tree matching, or increase the overlap in sequential matching, etc. - Manually choose an initial image pair, if COLMAP fails to initialize. Choose ``Reconstruction > Reconstruction options > Init`` and set images from the database management tool that have enough matches from different viewpoints. Importing and Exporting ----------------------- COLMAP provides several export options for further processing. For full flexibility, it is recommended to export the reconstruction in COLMAP's data format by choosing ``File > Export`` to export the currently viewed model or ``File > Export all`` to export all reconstructed models. The model is exported in the selected folder using separate text files for the reconstructed cameras, images, and points. When exporting in COLMAP's data format, you can re- import the reconstruction for later visualization, image undistortion, or to continue an existing reconstruction from where it left off (e.g., after importing and matching new images). To import a model, choose ``File > Import`` and select the export folder path. Alternatively, you can also export the model in various other formats, such as Bundler, VisualSfM [#f1]_, PLY, or VRML by choosing ``File > Export as...``. COLMAP can visualize plain PLY point cloud files with RGB information by choosing ``File > Import From...``. Further information about the format of the exported models can be found :ref:`here `. .. _dense-reconstruction: Dense Reconstruction -------------------- After reconstructing a sparse representation of the scene and the camera poses of the input images, MVS can now recover denser scene geometry. COLMAP has an integrated dense reconstruction pipeline to produce depth and normal maps for all registered images, to fuse the depth and normal maps into a dense point cloud with normal information, and to finally estimate a dense surface from the fused point cloud using Poisson [kazhdan2013]_ or Delaunay reconstruction. To get started, import your sparse 3D model into COLMAP (or select the reconstructed model after finishing the previous sparse reconstruction steps). Then, choose ``Reconstruction > Multi-view stereo`` and select an empty or existing workspace folder, which is used for the output and of all dense reconstruction results. The first step is to ``undistort`` the images, second to compute the depth and normal maps using ``stereo``, third to ``fuse`` the depth and normals maps to a point cloud, followed by a final, optional point cloud ``meshing`` step. During the stereo reconstruction process, the display might freeze due to heavy compute load and, if your GPU does not have enough memory, the reconstruction process might ungracefully crash. Please, refer to the FAQ (:ref:`freeze ` and :ref:`memory `) for information on how to avoid these problems. Note that the reconstructed normals of the point cloud cannot be directly visualized in COLMAP, but e.g. in Meshlab by enabling ``Render > Show Normal/Curvature``. Similarly, the reconstructed dense surface mesh model must be visualized with external software. In addition to the internal dense reconstruction functionality, COLMAP exports to several other dense reconstruction libraries, such as CMVS/PMVS [furukawa10]_ or CMP-MVS [jancosek11]_. Please choose ``Extras > Undistort images`` and select the appropriate format. The output folders contain the reconstruction and the undistorted images. In addition, the folders contain sample shell scripts to perform the dense reconstruction. To run PMVS2, execute the following commands: ./path/to/pmvs2 /path/to/undistortion/folder/pmvs/ option-all where `/path/to/undistortion/folder` is the folder selected in the undistortion dialog. Make sure not to forget the trailing slash in `/path/to/undistortion/folder/pmvs/` in the above command-line arguments. For large datasets, you probably want to first run CMVS to cluster the scene into more manageable parts and then run COLMAP or PMVS2. Please, refer to the sample shell scripts in the undistortion output folder on how to run CMVS in combination with COLMAP or PMVS2. Moreover, there are a number of external libraries that support COLMAP's output: - `CMVS/PMVS `_ [furukawa10]_ - `CMP-MVS `_ [jancosek11]_ - `Line3D++ `_ [hofer16]_. .. _database-management: Database Management ------------------- You can review and manage the imported cameras, images, and feature matches in the database management tool. Choose ``Processing > Manage database``. In the opening dialog, you can see the list of imported images and cameras. You can view the features and matches for each image by clicking ``Show image`` and ``Overlapping images``. Individual entries in the database tables can be modified by double clicking specific cells. Note that any changes to the database are only effective after clicking ``Save``. To share intrinsic camera parameters between arbitrary groups of images, select a single or multiple images, choose ``Set camera`` and set the `camera_id`, which corresponds to the unique `camera_id` column in the cameras table. You can also add new cameras with specific parameters. By setting the `prior_focal_length` flag to 0 or 1, you can give a hint whether the reconstruction algorithm should trust the focal length value. In case of a prior lab calibration, you want to set this value to 1. Without prior knowledge about the focal length, it is recommended to set this value to `1.25 * max(width_in_px, height_in_px)`. The database management tool has only limited functionality and, for full control over the data, you must directly modify the SQLite database (see :ref:`Database Format `). By accessing the database directly, you can use COLMAP only for feature extraction and matching or you can import your own features and matches to only use COLMAP's incremental reconstruction algorithm. .. _interface: Graphical and Command-line Interface ------------------------------------ Most of COLMAP's features are accessible from both the graphical and the command-line interface, which are both embedded in the same executable. You can provide the options directly as command-line arguments or you can provide a `.ini` project configuration file containing the options using the ``--project_path path/to/project.ini`` argument. To start the GUI application, please execute ``colmap gui`` or directly specify a project configuration as ``colmap gui --project_path path/to/project.ini`` to avoid tedious selection in the GUI. To list the different commands available from the command-line, execute ``colmap help``. For example, to run feature extraction from the command-line, you must execute ``colmap feature_extractor``. The :ref:`graphical user interface ` and :ref:`command-line Interface ` sections provide more details about the available commands. .. rubric:: Footnotes .. [#f1] VisualSfM's [wu13]_ projection model applies the distortion to the measurements and COLMAP to the projection, hence the exported NVM file is not fully compatible with VisualSfM. colmap-3.10/docker/000077500000000000000000000000001464745566500142055ustar00rootroot00000000000000colmap-3.10/docker/Dockerfile000066400000000000000000000047741464745566500162130ustar00rootroot00000000000000ARG UBUNTU_VERSION=22.04 ARG NVIDIA_CUDA_VERSION=12.3.1 # # Docker builder stage. # FROM nvidia/cuda:${NVIDIA_CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} as builder ARG COLMAP_GIT_COMMIT=main ARG CUDA_ARCHITECTURES=native ENV QT_XCB_GL_INTEGRATION=xcb_egl # Prevent stop building ubuntu at time zone selection. ENV DEBIAN_FRONTEND=noninteractive # Prepare and empty machine for building. RUN apt-get update && \ apt-get install -y --no-install-recommends --no-install-suggests \ git \ cmake \ ninja-build \ build-essential \ libboost-program-options-dev \ libboost-filesystem-dev \ libboost-graph-dev \ libboost-system-dev \ libeigen3-dev \ libflann-dev \ libfreeimage-dev \ libmetis-dev \ libgoogle-glog-dev \ libgtest-dev \ libsqlite3-dev \ libglew-dev \ qtbase5-dev \ libqt5opengl5-dev \ libcgal-dev \ libceres-dev # Build and install COLMAP. RUN git clone https://github.com/colmap/colmap.git RUN cd colmap && \ git fetch https://github.com/colmap/colmap.git ${COLMAP_GIT_COMMIT} && \ git checkout FETCH_HEAD && \ mkdir build && \ cd build && \ cmake .. -GNinja -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHITECTURES} \ -DCMAKE_INSTALL_PREFIX=/colmap_installed && \ ninja install # # Docker runtime stage. # FROM nvidia/cuda:${NVIDIA_CUDA_VERSION}-runtime-ubuntu${UBUNTU_VERSION} as runtime # Minimal dependencies to run COLMAP binary compiled in the builder stage. # Note: this reduces the size of the final image considerably, since all the # build dependencies are not needed. RUN apt-get update && \ apt-get install -y --no-install-recommends --no-install-suggests \ libboost-filesystem1.74.0 \ libboost-program-options1.74.0 \ libc6 \ libceres2 \ libfreeimage3 \ libgcc-s1 \ libgl1 \ libglew2.2 \ libgoogle-glog0v5 \ libqt5core5a \ libqt5gui5 \ libqt5widgets5 # Copy all files from /colmap_installed/ in the builder stage to /usr/local/ in # the runtime stage. This simulates installing COLMAP in the default location # (/usr/local/), which simplifies environment variables. It also allows the user # of this Docker image to use it as a base image for compiling against COLMAP as # a library. For instance, CMake will be able to find COLMAP easily with the # command: find_package(COLMAP REQUIRED). COPY --from=builder /colmap_installed/ /usr/local/ colmap-3.10/docker/README.md000066400000000000000000000031431464745566500154650ustar00rootroot00000000000000# How to build COLMAP using Docker ## Requirements - Host machine with at least one NVIDIA GPU/CUDA support and installed drivers (to support dense reconstruction). - Docker (for CUDA support 19.03+). ## Quick Start 1. Check that Docker >=19.03 installed on your host machine: ``` docker --version ``` 2. Check that you have an NVIDIA driver installed on your host machine: ``` nvidia-smi ``` 3. Setup the nvidia-toolkit on your host machine: For Ubuntu host machines: `./setup-ubuntu.sh` For CentOS host machines: `./setup-centos.sh` 4. Run the *run* script, using the *full local path* to your preferred local working directory (a folder with your input files/images, etc.): ``` ./run.sh /path/where/your/working/folder/is ``` This will put you in a directory (inside the Docker container) mounted to the local path you specified. Now you can run COLMAP binaries on your own inputs like this: ``` colmap automatic_reconstructor --image_path ./images --workspace_path . ``` ## Build from Scratch After completing steps 1-3, you can alternatively build the docker image from scratch based on the **Dockerfile** (e.g., with your own modifications) using: ``` ./build.sh ./run.sh /path/where/your/working/folder/is ``` ## Troubleshooting Install an NVIDIA driver and NVIDIA container runtime: ``` sudo apt install ubuntu-drivers-common sudo ubuntu-drivers autoinstall ``` If you failed to install the above, check the appropriate NVIDIA driver by yourself and install it: ``` ubuntu-drivers devices e.g. sudo apt install nvidia-driver-455 ``` colmap-3.10/docker/build.sh000077500000000000000000000002701464745566500156420ustar00rootroot00000000000000docker build -t="colmap:latest" . # In some cases, you may have to explicitly specify the compute architecture: # docker build -t="colmap:latest" --build-arg CUDA_ARCHITECTURES=75 . colmap-3.10/docker/run-gui.sh000077500000000000000000000003421464745566500161310ustar00rootroot00000000000000docker pull colmap/colmap:latest docker run \ -e QT_XCB_GL_INTEGRATION=xcb_egl \ -e DISPLAY=:0 \ -v /tmp/.X11-unix:/tmp/.X11-unix \ --gpus all \ --privileged \ -it colmap/colmap:latest \ colmap gui colmap-3.10/docker/run.sh000077500000000000000000000001531464745566500153470ustar00rootroot00000000000000docker pull colmap/colmap:latest docker run --gpus all -w /working -v $1:/working -it colmap/colmap:latest colmap-3.10/docker/setup-centos.sh000077500000000000000000000006261464745566500172010ustar00rootroot00000000000000# Add the package repositories distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo # Install nvidia-container-toolkit sudo yum install -y nvidia-container-toolkit sudo systemctl restart docker # Check that it worked! docker run --gpus all nvidia/cuda:10.2-base nvidia-smi colmap-3.10/docker/setup-ubuntu.sh000077500000000000000000000010061464745566500172210ustar00rootroot00000000000000# Add the package repositories distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list # Install nvidia-container-toolkit sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit sudo systemctl restart docker # Check that it worked! docker run --gpus all nvidia/cuda:10.2-base nvidia-smi colmap-3.10/pycolmap/000077500000000000000000000000001464745566500145625ustar00rootroot00000000000000colmap-3.10/pycolmap/.gitignore000066400000000000000000000000341464745566500165470ustar00rootroot00000000000000*.egg-info/ build/ example/ colmap-3.10/pycolmap/CMakeLists.txt000066400000000000000000000023471464745566500173300ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.10) project(${SKBUILD_PROJECT_NAME} VERSION ${SKBUILD_PROJECT_VERSION}) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CUDA_STANDARD 14) set(CMAKE_CUDA_STANDARD_REQUIRED ON) if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Some fixes for the Glog library. add_definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") add_definitions("-DGL_GLEXT_PROTOTYPES") add_definitions("-DNOMINMAX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") # Enable object level parallel builds in Visual Studio. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() find_package(colmap REQUIRED) find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) find_package(pybind11 2.12.0 REQUIRED) file(GLOB_RECURSE SOURCE_FILES "${PROJECT_SOURCE_DIR}/../src/pycolmap/*.cc") pybind11_add_module(pycolmap ${SOURCE_FILES}) target_include_directories(pycolmap PRIVATE ${PROJECT_SOURCE_DIR}/../src/) target_link_libraries(pycolmap PRIVATE colmap::colmap glog::glog Ceres::ceres) target_compile_definitions(pycolmap PRIVATE VERSION_INFO="${PROJECT_VERSION}") install(TARGETS pycolmap LIBRARY DESTINATION .) colmap-3.10/pycolmap/README.md000066400000000000000000000240171464745566500160450ustar00rootroot00000000000000# Python bindings for COLMAP PyCOLMAP exposes to Python most capabilities of [COLMAP](https://colmap.github.io/) for Structure-from-Motion and Multiview-stereo, such as reconstruction pipelines & objects and geometric estimators. ## Installation Pre-built wheels for Python 3.8/3.9/3.10 on Linux, macOS 10/11/12 (both Intel and Apple Silicon), and Windows can be installed using pip: ```bash pip install pycolmap ``` The wheels are automatically built and pushed to [PyPI](https://pypi.org/project/pycolmap/) at each release. They are currently not built with CUDA support, which requires building from source.

[Building PyCOLMAP from source - click to expand] 1. Install COLMAP from source following [the official guide](https://colmap.github.io/install.html). 3. Build PyCOLMAP: - On Linux and macOS: ```bash python -m pip install . ``` - On Windows, after installing COLMAP [via VCPKG](https://colmap.github.io/install.html#id3), run in powershell: ```powershell python -m pip install . ` --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` --cmake.define.VCPKG_TARGET_TRIPLET="x64-windows" ```
## Reconstruction pipeline PyCOLMAP provides bindings for multiple steps of the standard reconstruction pipeline: - extracting and matching SIFT features - importing an image folder into a COLMAP database - inferring the camera parameters from the EXIF metadata of an image file - running two-view geometric verification of matches on a COLMAP database - triangulating points into an existing COLMAP model - running incremental reconstruction from a COLMAP database - dense reconstruction with multi-view stereo Sparse & Dense reconstruction from a folder of images can be performed with: ```python output_path: pathlib.Path image_dir: pathlib.Path output_path.mkdir() mvs_path = output_path / "mvs" database_path = output_path / "database.db" pycolmap.extract_features(database_path, image_dir) pycolmap.match_exhaustive(database_path) maps = pycolmap.incremental_mapping(database_path, image_dir, output_path) maps[0].write(output_path) # dense reconstruction pycolmap.undistort_images(mvs_path, output_path, image_dir) pycolmap.patch_match_stereo(mvs_path) # requires compilation with CUDA pycolmap.stereo_fusion(mvs_path / "dense.ply", mvs_path) ``` PyCOLMAP can leverage the GPU for feature extraction, matching, and multi-view stereo if COLMAP was compiled with CUDA support. Similarly, PyCOLMAP can run Delaunay Triangulation if COLMAP was compiled with CGAL support. This requires to build the package from source and is not available with the PyPI wheels. All of the above steps are easily configurable with python dicts which are recursively merged into their respective defaults, for example: ```python pycolmap.extract_features(database_path, image_dir, sift_options={"max_num_features": 512}) # equivalent to ops = pycolmap.SiftExtractionOptions() ops.max_num_features = 512 pycolmap.extract_features(database_path, image_dir, sift_options=ops) ``` To list available options and their default parameters: ```python help(pycolmap.SiftExtractionOptions) ``` For another example of usage, see [`example.py`](./example.py) or [`hloc/reconstruction.py`](https://github.com/cvg/Hierarchical-Localization/blob/master/hloc/reconstruction.py). ## Reconstruction object We can load and manipulate an existing COLMAP 3D reconstruction: ```python import pycolmap reconstruction = pycolmap.Reconstruction("path/to/reconstruction/dir") print(reconstruction.summary()) for image_id, image in reconstruction.images.items(): print(image_id, image) for point3D_id, point3D in reconstruction.points3D.items(): print(point3D_id, point3D) for camera_id, camera in reconstruction.cameras.items(): print(camera_id, camera) reconstruction.write("path/to/reconstruction/dir/") ``` The object API mirrors the COLMAP C++ library. The bindings support many other operations, for example: - projecting a 3D point into an image with arbitrary camera model: ```python uv = camera.img_from_cam(image.cam_from_world * point3D.xyz) ``` - aligning two 3D reconstructions by their camera poses: ```python rec2_from_rec1 = pycolmap.align_reconstructions_via_reprojections(reconstruction1, reconstrution2) reconstruction1.transform(rec2_from_rec1) print(rec2_from_rec1.scale, rec2_from_rec1.rotation, rec2_from_rec1.translation) ``` - exporting reconstructions to text, PLY, or other formats: ```python reconstruction.write_text("path/to/new/reconstruction/dir/") # text format reconstruction.export_PLY("rec.ply") # PLY format ``` ## Estimators We provide robust RANSAC-based estimators for absolute camera pose (single-camera and multi-camera-rig), essential matrix, fundamental matrix, homography, and two-view relative pose for calibrated cameras. All RANSAC and estimation parameters are exposed as objects that behave similarly as Python dataclasses. The RANSAC options are described in [`colmap/optim/ransac.h`](https://github.com/colmap/colmap/blob/main/src/colmap/optim/ransac.h#L43-L72) and their default values are: ```python ransac_options = pycolmap.RANSACOptions( max_error=4.0, # for example the reprojection error in pixels min_inlier_ratio=0.01, confidence=0.9999, min_num_trials=1000, max_num_trials=100000, ) ``` ### Absolute pose estimation For instance, to estimate the absolute pose of a query camera given 2D-3D correspondences: ```python # Parameters: # - points2D: Nx2 array; pixel coordinates # - points3D: Nx3 array; world coordinates # - camera: pycolmap.Camera # Optional parameters: # - estimation_options: dict or pycolmap.AbsolutePoseEstimationOptions # - refinement_options: dict or pycolmap.AbsolutePoseRefinementOptions answer = pycolmap.absolute_pose_estimation(points2D, points3D, camera) # Returns: dictionary of estimation outputs or None if failure ``` 2D and 3D points are passed as Numpy arrays or lists. The options are defined in [`estimators/absolute_pose.cc`](./pycolmap/estimators/absolute_pose.h#L100-L122) and can be passed as regular (nested) Python dictionaries: ```python pycolmap.absolute_pose_estimation( points2D, points3D, camera, estimation_options=dict(ransac=dict(max_error=12.0)), refinement_options=dict(refine_focal_length=True), ) ``` ### Absolute Pose Refinement ```python # Parameters: # - cam_from_world: pycolmap.Rigid3d, initial pose # - points2D: Nx2 array; pixel coordinates # - points3D: Nx3 array; world coordinates # - inlier_mask: array of N bool; inlier_mask[i] is true if correpondence i is an inlier # - camera: pycolmap.Camera # Optional parameters: # - refinement_options: dict or pycolmap.AbsolutePoseRefinementOptions answer = pycolmap.pose_refinement(cam_from_world, points2D, points3D, inlier_mask, camera) # Returns: dictionary of refinement outputs or None if failure ``` ### Essential matrix estimation ```python # Parameters: # - points1: Nx2 array; 2D pixel coordinates in image 1 # - points2: Nx2 array; 2D pixel coordinates in image 2 # - camera1: pycolmap.Camera of image 1 # - camera2: pycolmap.Camera of image 2 # Optional parameters: # - options: dict or pycolmap.RANSACOptions (default inlier threshold is 4px) answer = pycolmap.essential_matrix_estimation(points1, points2, camera1, camera2) # Returns: dictionary of estimation outputs or None if failure ``` ### Fundamental matrix estimation ```python answer = pycolmap.fundamental_matrix_estimation( points1, points2, [options], # optional dict or pycolmap.RANSACOptions ) ``` ### Homography estimation ```python answer = pycolmap.homography_matrix_estimation( points1, points2, [options], # optional dict or pycolmap.RANSACOptions ) ``` ### Two-view geometry estimation COLMAP can also estimate a relative pose between two calibrated cameras by estimating both E and H and accounting for the degeneracies of each model. ```python # Parameters: # - camera1: pycolmap.Camera of image 1 # - points1: Nx2 array; 2D pixel coordinates in image 1 # - camera2: pycolmap.Camera of image 2 # - points2: Nx2 array; 2D pixel coordinates in image 2 # Optional parameters: # - matches: Nx2 integer array; correspondences across images # - options: dict or pycolmap.TwoViewGeometryOptions answer = pycolmap.estimate_calibrated_two_view_geometry(camera1, points1, camera2, points2) # Returns: pycolmap.TwoViewGeometry ``` The `TwoViewGeometryOptions` control how each model is selected. The output structure contains the geometric model, inlier matches, the relative pose (if `options.compute_relative_pose=True`), and the type of camera configuration, which is an instance of the enum `pycolmap.TwoViewGeometryConfiguration`. ### Camera argument Some estimators expect a COLMAP camera object, which can be created as follows: ```python camera = pycolmap.Camera( model=camera_model_name_or_id, width=width, height=height, params=params, ) ``` The different camera models and their extra parameters are defined in [`colmap/src/colmap/sensor/models.h`](https://github.com/colmap/colmap/blob/main/src/colmap/sensor/models.h). For example for a pinhole camera: ```python camera = pycolmap.Camera( model='SIMPLE_PINHOLE', width=width, height=height, params=[focal_length, cx, cy], ) ``` Alternatively, we can also pass a camera dictionary: ```python camera_dict = { 'model': COLMAP_CAMERA_MODEL_NAME_OR_ID, 'width': IMAGE_WIDTH, 'height': IMAGE_HEIGHT, 'params': EXTRA_CAMERA_PARAMETERS_LIST } ``` ## SIFT feature extraction ```python import numpy as np import pycolmap from PIL import Image, ImageOps # Input should be grayscale image with range [0, 1]. img = Image.open('image.jpg').convert('RGB') img = ImageOps.grayscale(img) img = np.array(img).astype(np.float) / 255. # Optional parameters: # - options: dict or pycolmap.SiftExtractionOptions # - device: default pycolmap.Device.auto uses the GPU if available sift = pycolmap.Sift() # Parameters: # - image: HxW float array keypoints, descriptors = sift.extract(img) # Returns: # - keypoints: Nx4 array; format: x (j), y (i), scale, orientation # - descriptors: Nx128 array; L2-normalized descriptors ``` colmap-3.10/pycolmap/ci/000077500000000000000000000000001464745566500151555ustar00rootroot00000000000000colmap-3.10/pycolmap/ci/install-colmap-centos.sh000077500000000000000000000027211464745566500217260ustar00rootroot00000000000000#!/bin/bash set -e -x uname -a CURRDIR=$(pwd) export PATH="/usr/bin" # Install toolchain under AlmaLinux 8, # see https://almalinux.pkgs.org/8/almalinux-appstream-x86_64/ yum install -y \ gcc \ gcc-c++ \ gcc-gfortran \ git \ cmake3 \ ninja-build \ curl \ zip \ unzip \ tar # ccache shipped by CentOS is too old so we download and cache it. COMPILER_TOOLS_DIR="${CONTAINER_COMPILER_CACHE_DIR}/bin" mkdir -p ${COMPILER_TOOLS_DIR} if [ ! -f "${COMPILER_TOOLS_DIR}/ccache" ]; then FILE="ccache-4.10.1-linux-x86_64" curl -sSLO https://github.com/ccache/ccache/releases/download/v4.10.1/${FILE}.tar.xz tar -xf ${FILE}.tar.xz cp ${FILE}/ccache ${COMPILER_TOOLS_DIR} fi export PATH="${COMPILER_TOOLS_DIR}:${PATH}" # Setup vcpkg git clone https://github.com/microsoft/vcpkg ${VCPKG_INSTALLATION_ROOT} cd ${VCPKG_INSTALLATION_ROOT} git checkout ${VCPKG_COMMIT_ID} ./bootstrap-vcpkg.sh ./vcpkg integrate install # Build COLMAP cd ${CURRDIR} mkdir build && cd build cmake3 .. -GNinja \ -DCUDA_ENABLED=OFF \ -DGUI_ENABLED=OFF \ -DCGAL_ENABLED=OFF \ -DLSD_ENABLED=OFF \ -DCCACHE_ENABLED=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \ -DCMAKE_TOOLCHAIN_FILE="${CMAKE_TOOLCHAIN_FILE}" \ -DVCPKG_TARGET_TRIPLET="${VCPKG_TARGET_TRIPLET}" \ -DCMAKE_EXE_LINKER_FLAGS_INIT="-ldl" ninja install ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose colmap-3.10/pycolmap/ci/install-colmap-macos.sh000077500000000000000000000024251464745566500215360ustar00rootroot00000000000000#!/bin/bash set -x -e CURRDIR=$(pwd) # Fix `brew link` error. find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete brew update brew install git cmake ninja gfortran ccache sudo xcode-select --reset export ARCHFLAGS="-arch ${CMAKE_OSX_ARCHITECTURES}" # When building lapack-reference, vcpkg/cmake looks for gfortran. ln -sf $(which gfortran-14) "$(dirname $(which gfortran-14))/gfortran" # Setup vcpkg git clone https://github.com/microsoft/vcpkg ${VCPKG_INSTALLATION_ROOT} cd ${VCPKG_INSTALLATION_ROOT} git checkout ${VCPKG_COMMIT_ID} ./bootstrap-vcpkg.sh ./vcpkg integrate install # Build COLMAP cd ${CURRDIR} mkdir build && cd build "$(brew --prefix cmake)/bin/cmake" .. -GNinja \ -DCUDA_ENABLED=OFF \ -DGUI_ENABLED=OFF \ -DCGAL_ENABLED=OFF \ -DLSD_ENABLED=OFF \ -DCCACHE_ENABLED=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_MAKE_PROGRAM="$(brew --prefix ninja)/bin/ninja" \ -DCMAKE_TOOLCHAIN_FILE="${CMAKE_TOOLCHAIN_FILE}" \ -DVCPKG_TARGET_TRIPLET="${VCPKG_TARGET_TRIPLET}" \ -DCMAKE_OSX_ARCHITECTURES="${CMAKE_OSX_ARCHITECTURES}" \ `if [[ ${CIBW_ARCHS_MACOS} == "arm64" ]]; then echo "-DSIMD_ENABLED=OFF"; fi` ninja sudo ninja install ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose colmap-3.10/pycolmap/ci/install-colmap-windows.ps1000077500000000000000000000021351464745566500222150ustar00rootroot00000000000000$CURRDIR = $PWD $COMPILER_TOOLS_DIR = "${env:COMPILER_CACHE_DIR}/bin" New-Item -ItemType Directory -Force -Path ${COMPILER_TOOLS_DIR} $env:Path = "${COMPILER_TOOLS_DIR};" + $env:Path If (!(Test-Path -path "${COMPILER_TOOLS_DIR}/ccache.exe" -PathType Leaf)) { .github/workflows/install-ccache.ps1 -Destination "${COMPILER_TOOLS_DIR}" } # Setup vcpkg cd ${CURRDIR} git clone https://github.com/microsoft/vcpkg ${env:VCPKG_INSTALLATION_ROOT} cd ${env:VCPKG_INSTALLATION_ROOT} git checkout "${env:VCPKG_COMMIT_ID}" ./bootstrap-vcpkg.bat cd ${CURRDIR} & "./scripts/shell/enter_vs_dev_shell.ps1" & "${env:VCPKG_INSTALLATION_ROOT}/vcpkg.exe" integrate install # Build COLMAP mkdir build cd build cmake .. ` -GNinja ` -DCMAKE_MAKE_PROGRAM=ninja ` -DCUDA_ENABLED="OFF" ` -DGUI_ENABLED="OFF" ` -DCGAL_ENABLED="OFF" ` -DLSD_ENABLED="OFF" ` -DCMAKE_BUILD_TYPE="Release" ` -DCMAKE_TOOLCHAIN_FILE="${env:CMAKE_TOOLCHAIN_FILE}" ` -DVCPKG_TARGET_TRIPLET="${env:VCPKG_TARGET_TRIPLET}" ninja install ccache --show-stats --verbose ccache --evict-older-than 1d ccache --show-stats --verbose colmap-3.10/pycolmap/ci/test-colmap-windows.ps1000066400000000000000000000002461464745566500215240ustar00rootroot00000000000000& "./scripts/shell/enter_vs_dev_shell.ps1" & "${env:VCPKG_INSTALLATION_ROOT}/vcpkg.exe" integrate install & python -c "import pycolmap; print(pycolmap.__version__)" colmap-3.10/pycolmap/custom_bundle_adjustment.py000066400000000000000000000425571464745566500222520ustar00rootroot00000000000000""" Python reimplementation of the bundle adjustment for the incremental mapper of C++ with equivalent logic. As a result, one can add customized residuals on top of the exposed ceres problem from conventional bundle adjustment. pyceres is needed as a dependency for this file. """ import pyceres import pycolmap from pycolmap import logging import copy class PyBundleAdjuster(object): # Python implementation of COLMAP bundle adjuster with pyceres def __init__( self, options: pycolmap.BundleAdjustmentOptions, config: pycolmap.BundleAdjustmentConfig, ): self.options = options self.config = config self.problem = pyceres.Problem() self.summary = pyceres.SolverSummary() self.camera_ids = set() self.point3D_num_observations = dict() def solve(self, reconstruction: pycolmap.Reconstruction): loss = self.options.create_loss_function() self.set_up_problem(reconstruction, loss) if self.problem.num_residuals() == 0: return False solver_options = self.set_up_solver_options( self.problem, self.options.solver_options ) pyceres.solve(solver_options, self.problem, self.summary) return True def set_up_problem( self, reconstruction: pycolmap.Reconstruction, loss: pyceres.LossFunction, ): assert reconstruction is not None self.problem = pyceres.Problem() for image_id in self.config.image_ids: self.add_image_to_problem(image_id, reconstruction, loss) for point3D_id in self.config.variable_point3D_ids: self.add_point_to_problem(point3D_id, reconstruction, loss) for point3D_id in self.config.constant_point3D_ids: self.add_point_to_problem(point3D_id, reconstruction, loss) self.parameterize_cameras(reconstruction) self.parameterize_points(reconstruction) return self.problem def set_up_solver_options( self, problem: pyceres.Problem, solver_options: pyceres.SolverOptions ): bundle_adjuster = pycolmap.BundleAdjuster(self.options, self.config) return bundle_adjuster.set_up_solver_options(problem, solver_options) def add_image_to_problem( self, image_id: int, reconstruction: pycolmap.Reconstruction, loss: pyceres.LossFunction, ): image = reconstruction.images[image_id] pose = image.cam_from_world camera = reconstruction.cameras[image.camera_id] constant_cam_pose = ( not self.options.refine_extrinsics ) or self.config.has_constant_cam_pose(image.image_id) num_observations = 0 for point2D in image.points2D: if not point2D.has_point3D(): continue num_observations += 1 if point2D.point3D_id not in self.point3D_num_observations: self.point3D_num_observations[point2D.point3D_id] = 0 self.point3D_num_observations[point2D.point3D_id] += 1 point3D = reconstruction.points3D[point2D.point3D_id] assert point3D.track.length() > 1 if constant_cam_pose: cost = pycolmap.cost_functions.ReprojErrorCost( camera.model, pose, point2D.xy ) self.problem.add_residual_block( cost, loss, [point3D.xyz, camera.params] ) else: cost = pycolmap.cost_functions.ReprojErrorCost( camera.model, point2D.xy ) self.problem.add_residual_block( cost, loss, [ pose.rotation.quat, pose.translation, point3D.xyz, camera.params, ], ) if num_observations > 0: self.camera_ids.add(image.camera_id) # Set pose parameterization if not constant_cam_pose: self.problem.set_manifold( pose.rotation.quat, pyceres.QuaternionManifold() ) if self.config.has_constant_cam_positions(image_id): constant_position_idxs = self.config.constant_cam_positions( image_id ) self.problem.set_manifold( pose.translation, pyceres.SubsetManifold(3, constant_position_idxs), ) def add_point_to_problem( self, point3D_id: int, reconstruction: pycolmap.Reconstruction, loss: pyceres.LossFunction, ): point3D = reconstruction.points3D[point3D_id] if point3D_id in self.point3D_num_observations: if ( self.point3D_num_observations[point3D_id] == point3D.track.length() ): return else: self.point3D_num_observations[point3D_id] = 0 for track_el in point3D.track.elements: if self.config.has_image(track_el.image_id): continue self.point3D_num_observations[point3D_id] += 1 image = reconstruction.images[track_el.image_id] camera = reconstruction.cameras[image.camera_id] point2D = image.point2D(track_el.point2D_idx) if image.camera_id not in self.camera_ids: self.camera_ids.add(image.camera_id) self.config.set_constant_cam_intrinsics(image.camera_id) cost = pycolmap.cost_functions.ReprojErrorCost( camera.model, image.cam_from_world, point2D.xy ) self.problem.add_residual_block( cost, loss, [point3D.xyz, camera.params] ) def parameterize_cameras(self, reconstruction: pycolmap.Reconstruction): constant_camera = ( (not self.options.refine_focal_length) and (not self.options.refine_principal_point) and (not options.refine_extra_params) ) for camera_id in self.camera_ids: camera = reconstruction.cameras[camera_id] if constant_camera or self.config.has_constant_cam_intrinsics( camera_id ): self.problem.set_parameter_block_constant(camera.params) continue const_camera_params = [] if not self.options.refine_focal_length: const_camera_params.extend(camera.focal_length_idxs()) if not self.options.refine_principal_point: const_camera_params.extend(camera.principal_point_idxs()) if not self.options.refine_extra_params: const_camera_params.extend(camera.extra_point_idxs()) if len(const_camera_params) > 0: self.problem.set_manifold( camera.params, pyceres.SubsetManifold( len(camera.params), const_camera_params ), ) def parameterize_points(self, reconstruction: pycolmap.Reconstruction): for ( point3D_id, num_observations, ) in self.point3D_num_observations.items(): point3D = reconstruction.points3D[point3D_id] if point3D.track.length() > num_observations: self.problem.set_parameter_block_constant(point3D.xyz) for point3D_id in self.config.constant_point3D_ids: point3D = reconstruction.points3D[point3D_id] self.problem.set_parameter_block_constant(point3D.xyz) def solve_bundle_adjustment(reconstruction, ba_options, ba_config): bundle_adjuster = pycolmap.BundleAdjuster(ba_options, ba_config) # alternative equivalent python-based bundle adjustment (slower): # bundle_adjuster = PyBundleAdjuster(ba_options, ba_config) bundle_adjuster.set_up_problem( reconstruction, ba_options.create_loss_function() ) solver_options = bundle_adjuster.set_up_solver_options( bundle_adjuster.problem, ba_options.solver_options ) summary = pyceres.SolverSummary() pyceres.solve(solver_options, bundle_adjuster.problem, summary) return summary def adjust_global_bundle(mapper, mapper_options, ba_options): """Equivalent to mapper.adjust_global_bundle(...)""" reconstruction = mapper.reconstruction assert reconstruction is not None reg_image_ids = reconstruction.reg_image_ids() if len(reg_image_ids) < 2: logging.fatal( "At least two images must be registered for global bundle-adjustment" ) ba_options_tmp = copy.deepcopy(ba_options) # Use stricter convergence criteria for first registered images if len(reg_image_ids) < 10: # kMinNumRegImagesForFastBA = 10 ba_options_tmp.solver_options.function_tolerance /= 10 ba_options_tmp.solver_options.gradient_tolerance /= 10 ba_options_tmp.solver_options.parameter_tolerance /= 10 ba_options_tmp.solver_options.max_num_iterations *= 2 ba_options_tmp.solver_options.max_linear_solver_iterations = 200 # Avoid degeneracies in bundle adjustment mapper.observation_manager.filter_observations_with_negative_depth() # Configure bundle adjustment ba_config = pycolmap.BundleAdjustmentConfig() for image_id in reg_image_ids: ba_config.add_image(image_id) # Fix the existing images, if option specified if mapper_options.fix_existing_images: for image_id in reg_image_ids: if image_id in mapper.existing_image_ids: ba_config.set_constant_cam_pose(image_id) # Fix 7-DOFs of the bundle adjustment problem ba_config.set_constant_cam_pose(reg_image_ids[0]) if (not mapper_options.fix_existing_images) or ( reg_image_ids[1] not in mapper.existing_image_ids ): ba_config.set_constant_cam_positions(reg_image_ids[1], [0]) # Run bundle adjustment summary = solve_bundle_adjustment(reconstruction, ba_options_tmp, ba_config) logging.info("Global Bundle Adjustment") logging.info(summary.BriefReport()) def iterative_global_refinement( mapper, max_num_refinements, max_refinement_change, mapper_options, ba_options, tri_options, normalize_reconstruction=True, ): """Equivalent to mapper.iterative_global_refinement(...)""" reconstruction = mapper.reconstruction mapper.complete_and_merge_tracks(tri_options) num_retriangulated_observations = mapper.retriangulate(tri_options) logging.verbose( 1, f"=> Retriangulated observations: {num_retriangulated_observations}" ) for i in range(max_num_refinements): num_observations = reconstruction.compute_num_observations() # mapper.adjust_global_bundle(mapper_options, ba_options) adjust_global_bundle(mapper, mapper_options, ba_options) if normalize_reconstruction: reconstruction.normalize() num_changed_observations = mapper.complete_and_merge_tracks(tri_options) num_changed_observations += mapper.filter_points(mapper_options) changed = ( num_changed_observations / num_observations if num_observations > 0 else 0 ) logging.verbose(1, f"=> Changed observations: {changed:.6f}") if changed < max_refinement_change: break def adjust_local_bundle( mapper, mapper_options, ba_options, tri_options, image_id, point3D_ids ): """Equivalent to mapper.adjust_local_bundle(...)""" reconstruction = mapper.reconstruction assert reconstruction is not None report = pycolmap.LocalBundleAdjustmentReport() # Find images that have most 3D points with given image in common local_bundle = mapper.find_local_bundle(mapper_options, image_id) # Do the bundle adjustment only if there is any connected images if local_bundle: ba_config = pycolmap.BundleAdjustmentConfig() ba_config.add_image(image_id) for local_image_id in local_bundle: ba_config.add_image(local_image_id) # Fix the existing images, if options specified if mapper_options.fix_existing_images: for local_image_id in local_bundle: if local_image_id in mapper.existing_image_ids: ba_config.set_constant_cam_pose(local_image_id) # Determine which cameras to fix, when not all the registered images are within the current local bundle. num_images_per_camera = {} for image_id in ba_config.image_ids: image = reconstruction.images[image_id] if image.camera_id not in num_images_per_camera: num_images_per_camera[image.camera_id] = 0 num_images_per_camera[image.camera_id] += 1 for camera_id, num_images_local in num_images_per_camera.items(): if num_images_local < mapper.num_reg_images_per_camera[camera_id]: ba_config.set_constant_cam_intrinsics(camera_id) # Fix 7 DOF to avoid scale/rotation/translation drift in bundle adjustment if len(local_bundle) == 1: ba_config.set_constant_cam_pose(local_bundle[0]) ba_config.set_constant_cam_positions(image_id, [0]) elif len(local_bundle) > 1: image_id1, image_id2 = local_bundle[-1], local_bundle[-2] ba_config.set_constant_cam_pose(image_id1) if (not mapper_options.fix_existing_images) or ( image_id2 not in mapper.existing_image_ids ): ba_config.set_constant_cam_positions(image_id2, [0]) # Make sure, we refine all new and short-track 3D points, no matter if # they are fully contained in the local image set or not. Do not include # long track 3D points as they are usually already very stable and adding # to them to bundle adjustment and track merging/completion would slow # down the local bundle adjustment significantly. variable_point3D_ids = set() for point3D_id in list(point3D_ids): point3D = reconstruction.point3D(point3D_id) kMaxTrackLength = 15 if ( point3D.error == -1.0 ) or point3D.track.length() <= kMaxTrackLength: ba_config.add_variable_point(point3D_id) variable_point3D_ids.add(point3D_id) # Adjust the local bundle summary = solve_bundle_adjustment( mapper.reconstruction, ba_options, ba_config ) logging.info("Local Bundle Adjustment") logging.info(summary.BriefReport()) report.num_adjusted_observations = int(summary.num_residuals / 2) # Merge refined tracks with other existing points report.num_merged_observations = mapper.triangulator.merge_tracks( tri_options, variable_point3D_ids ) # Complete tracks that may have failed to triangulate before refinement # of camera pose and calibration in bundle adjustment. This may avoid that # some points are filtered and it helps for subsequent image registrations report.num_completed_observations = mapper.triangulator.complete_tracks( tri_options, variable_point3D_ids ) report.num_completed_observations += mapper.triangulator.complete_image( tri_options, image_id ) filter_image_ids = {image_id, *local_bundle} report.num_filtered_observations = ( mapper.observation_manager.filter_points3D_in_images( mapper_options.filter_max_reproj_error, mapper_options.filter_min_tri_angle, filter_image_ids, ) ) report.num_filtered_observations += ( mapper.observation_manager.filter_points3D( mapper_options.filter_max_reproj_error, mapper_options.filter_min_tri_angle, point3D_ids, ) ) return report def iterative_local_refinement( mapper, max_num_refinements, max_refinement_change, mapper_options, ba_options, tri_options, image_id, ): """Equivalent to mapper.iterative_local_refinement(...)""" ba_options_tmp = copy.deepcopy(ba_options) for i in range(max_num_refinements): # report = mapper.adjust_local_bundle(mapper_options, ba_options_tmp, tri_options, image_id, mapper.get_modified_points3D()) report = adjust_local_bundle( mapper, mapper_options, ba_options_tmp, tri_options, image_id, mapper.get_modified_points3D(), ) logging.verbose( 1, f"=> Merged observations: {report.num_merged_observations}" ) logging.verbose( 1, f"=> Completed observations: {report.num_completed_observations}" ) logging.verbose( 1, f"=> Filtered observations: {report.num_filtered_observations}" ) changed = 0 if report.num_adjusted_observations > 0: changed = ( report.num_merged_observations + report.num_completed_observations + report.num_filtered_observations ) / report.num_adjusted_observations logging.verbose(1, f"=> Changed observations: {changed:.6f}") if changed < max_refinement_change: break # Only use robust cost function for first iteration ba_options_tmp.loss_function_type = pycolmap.LossFunctionType.TRIVIAL mapper.clear_modified_points3D() colmap-3.10/pycolmap/custom_incremental_mapping.py000066400000000000000000000313511464745566500225450ustar00rootroot00000000000000""" Python reimplementation of the C++ incremental mapper with equivalent logic. """ import shutil import time import urllib.request import zipfile from pathlib import Path import enlighten import pycolmap from pycolmap import logging import custom_bundle_adjustment def extract_colors(image_path, image_id, reconstruction): if not reconstruction.extract_colors_for_image(image_id, image_path): logging.warning(f"Could not read image {image_id} at path {image_path}") def write_snapshot(reconstruction, snapshot_path): logging.info("Creating snapshot") timestamp = time.time() * 1000 path = snapshot_path / f"{timestamp:010d}" path.mkdir(exist_ok=True, parents=True) logging.verbose(1, f"=> Writing to {path}") reconstruction.write(path) def iterative_global_refinement(options, mapper_options, mapper): logging.info("Retriangulation and Global bundle adjustment") # The following is equivalent to mapper.iterative_global_refinement(...) custom_bundle_adjustment.iterative_global_refinement( mapper, options.ba_global_max_refinements, options.ba_global_max_refinement_change, mapper_options, options.get_global_bundle_adjustment(), options.get_triangulation(), ) mapper.filter_images(mapper_options) def initialize_reconstruction( controller, mapper, mapper_options, reconstruction ): """Equivalent to IncrementalMapperController.initialize_reconstruction(...)""" options = controller.options init_pair = (options.init_image_id1, options.init_image_id2) # Try to find good initial pair if not options.is_initial_pair_provided(): logging.info("Finding good initial image pair") ret = mapper.find_initial_image_pair(mapper_options, *init_pair) if ret is None: logging.info("No good initial image pair found.") return pycolmap.IncrementalMapperStatus.NO_INITIAL_PAIR init_pair, two_view_geometry = ret else: if not all(reconstruction.exists_image(i) for i in init_pair): logging.info(f"=> Initial image pair {init_pair} does not exist.") return pycolmap.IncrementalMapperStatus.BAD_INITIAL_PAIR two_view_geometry = mapper.estimate_initial_two_view_geometry( mapper_options, *init_pair ) if two_view_geometry is None: logging.info("Provided pair is insuitable for initialization") return pycolmap.IncrementalMapperStatus.BAD_INITIAL_PAIR logging.info(f"Initializing with image pair {init_pair}") mapper.register_initial_image_pair( mapper_options, two_view_geometry, *init_pair ) logging.info("Global bundle adjustment") # The following is equivalent to: mapper.adjust_global_bundle(...) custom_bundle_adjustment.adjust_global_bundle( mapper, mapper_options, options.get_global_bundle_adjustment() ) reconstruction.normalize() mapper.filter_points(mapper_options) mapper.filter_images(mapper_options) # Initial image pair failed to register if ( reconstruction.num_reg_images() == 0 or reconstruction.num_points3D() == 0 ): return pycolmap.IncrementalMapperStatus.BAD_INITIAL_PAIR if options.extract_colors: extract_colors(controller.image_path, init_pair[0], reconstruction) return pycolmap.IncrementalMapperStatus.SUCCESS def reconstruct_sub_model(controller, mapper, mapper_options, reconstruction): """Equivalent to IncrementalMapperController.reconstruct_sub_model(...)""" # register initial pair mapper.begin_reconstruction(reconstruction) if reconstruction.num_reg_images() == 0: init_status = initialize_reconstruction( controller, mapper, mapper_options, reconstruction ) if init_status != pycolmap.IncrementalMapperStatus.SUCCESS: return init_status controller.callback( pycolmap.IncrementalMapperCallback.INITIAL_IMAGE_PAIR_REG_CALLBACK ) # incremental mapping options = controller.options snapshot_prev_num_reg_images = reconstruction.num_reg_images() ba_prev_num_reg_images = reconstruction.num_reg_images() ba_prev_num_points = reconstruction.num_points3D() reg_next_success, prev_reg_next_success = True, True while True: if not (reg_next_success or prev_reg_next_success): break prev_reg_next_success = reg_next_success reg_next_success = False next_images = mapper.find_next_images(mapper_options) if len(next_images) == 0: break for reg_trial in range(len(next_images)): next_image_id = next_images[reg_trial] logging.info( f"Registering image #{next_image_id} " f"({reconstruction.num_reg_images() + 1})" ) num_vis = mapper.observation_manager.num_visible_points3D( next_image_id ) num_obs = mapper.observation_manager.num_observations(next_image_id) logging.info(f"=> Image sees {num_vis} / {num_obs} points") reg_next_success = mapper.register_next_image( mapper_options, next_image_id ) if reg_next_success: break else: logging.info("=> Could not register, trying another image.") # If initial pair fails to continue for some time, # abort and try different initial pair. kMinNumInitialRegTrials = 30 if ( reg_trial >= kMinNumInitialRegTrials and reconstruction.num_reg_images() < options.min_model_size ): break if reg_next_success: mapper.triangulate_image(options.get_triangulation(), next_image_id) # The following is equivalent to mapper.iterative_local_refinement(...) custom_bundle_adjustment.iterative_local_refinement( mapper, options.ba_local_max_refinements, options.ba_local_max_refinement_change, mapper_options, options.get_local_bundle_adjustment(), options.get_triangulation(), next_image_id, ) if controller.check_run_global_refinement( reconstruction, ba_prev_num_reg_images, ba_prev_num_points ): iterative_global_refinement(options, mapper_options, mapper) ba_prev_num_points = reconstruction.num_points3D() ba_prev_num_reg_images = reconstruction.num_reg_images() if options.extract_colors: extract_colors( controller.image_path, next_image_id, reconstruction ) if ( options.snapshot_images_freq > 0 and reconstruction.num_reg_images() >= options.snapshot_images_freq + snapshot_prev_num_reg_images ): snapshot_prev_num_reg_images = reconstruction.num_reg_images() write_snapshot(reconstruction, Path(options.snapshot_path)) controller.callback( pycolmap.IncrementalMapperCallback.NEXT_IMAGE_REG_CALLBACK ) if mapper.num_shared_reg_images() >= int(options.max_model_overlap): break if (not reg_next_success) and prev_reg_next_success: iterative_global_refinement(options, mapper_options, mapper) if ( reconstruction.num_reg_images() >= 2 and reconstruction.num_reg_images() != ba_prev_num_reg_images and reconstruction.num_points3D != ba_prev_num_points ): iterative_global_refinement(options, mapper_options, mapper) return pycolmap.IncrementalMapperStatus.SUCCESS def reconstruct(controller, mapper_options): """Equivalent to IncrementalMapperController.reconstruct(...)""" options = controller.options reconstruction_manager = controller.reconstruction_manager database_cache = controller.database_cache mapper = pycolmap.IncrementalMapper(database_cache) initial_reconstruction_given = reconstruction_manager.size() > 0 if reconstruction_manager.size() > 1: logging.fatal( "Can only resume from a single reconstruction, but multiple are given" ) for num_trials in range(options.init_num_trials): if (not initial_reconstruction_given) or num_trials > 0: reconstruction_idx = reconstruction_manager.add() else: reconstruction_idx = 0 reconstruction = reconstruction_manager.get(reconstruction_idx) status = reconstruct_sub_model( controller, mapper, mapper_options, reconstruction ) if status == pycolmap.IncrementalMapperStatus.INTERRUPTED: mapper.end_reconstruction(False) elif status in ( pycolmap.IncrementalMapperStatus.NO_INITIAL_PAIR, pycolmap.IncrementalMapperStatus.BAD_INITIAL_PAIR, ): mapper.end_reconstruction(True) reconstruction_manager.delete(reconstruction_idx) if options.is_initial_pair_provided(): return elif status == pycolmap.IncrementalMapperStatus.SUCCESS: total_num_reg_images = mapper.num_total_reg_images() min_model_size = min( 0.8 * database_cache.num_images(), options.min_model_size ) if ( options.multiple_models and reconstruction_manager.size() > 1 and ( reconstruction.num_reg_images() < min_model_size or reconstruction.num_reg_images() == 0 ) ): mapper.end_reconstruction(True) reconstruction_manager.delete(reconstruction_idx) else: mapper.end_reconstruction(False) controller.callback( pycolmap.IncrementalMapperCallback.LAST_IMAGE_REG_CALLBACK ) if ( initial_reconstruction_given or (not options.multiple_models) or reconstruction_manager.size() >= options.max_num_models or total_num_reg_images >= database_cache.num_images() - 1 ): return else: logging.fatal(f"Unknown reconstruction status: {status}") def main_incremental_mapper(controller): """Equivalent to IncrementalMapperController.run()""" timer = pycolmap.Timer() timer.start() if not controller.load_database(): return init_mapper_options = controller.options.get_mapper() reconstruct(controller, init_mapper_options) for i in range(2): # number of relaxations if controller.reconstruction_manager.size() > 0: break logging.info("=> Relaxing the initialization constraints") init_mapper_options.init_min_num_inliers = int( init_mapper_options.init_min_num_inliers / 2 ) reconstruct(controller, init_mapper_options) if controller.reconstruction_manager.size() > 0: break logging.info("=> Relaxing the initialization constraints") init_mapper_options.init_min_tri_angle /= 2 reconstruct(controller, init_mapper_options) timer.print_minutes() def main( database_path, image_path, output_path, options=pycolmap.IncrementalPipelineOptions(), input_path=None, ): if not database_path.exists(): logging.fatal(f"Database path does not exist: {database_path}") if not image_path.exists(): logging.fatal(f"Image path does not exist: {image_path}") output_path.mkdir(exist_ok=True, parents=True) reconstruction_manager = pycolmap.ReconstructionManager() if input_path is not None and input_path != "": reconstruction_manager.read(input_path) mapper = pycolmap.IncrementalMapperController( options, image_path, database_path, reconstruction_manager ) # main runner num_images = pycolmap.Database(database_path).num_images with enlighten.Manager() as manager: with manager.counter( total=num_images, desc="Images registered:" ) as pbar: pbar.update(0, force=True) mapper.add_callback( pycolmap.IncrementalMapperCallback.INITIAL_IMAGE_PAIR_REG_CALLBACK, lambda: pbar.update(2), ) mapper.add_callback( pycolmap.IncrementalMapperCallback.NEXT_IMAGE_REG_CALLBACK, lambda: pbar.update(1), ) main_incremental_mapper(mapper) # write and output reconstruction_manager.write(output_path) reconstructions = {} for i in range(reconstruction_manager.size()): reconstructions[i] = reconstruction_manager.get(i) return reconstructions colmap-3.10/pycolmap/example.py000066400000000000000000000043731464745566500165760ustar00rootroot00000000000000""" An example for running incremental SfM on a set of images with pycolmap interfaces. """ import shutil import urllib.request import zipfile from pathlib import Path import enlighten import pycolmap from pycolmap import logging def incremental_mapping_with_pbar(database_path, image_path, sfm_path): num_images = pycolmap.Database(database_path).num_images with enlighten.Manager() as manager: with manager.counter( total=num_images, desc="Images registered:" ) as pbar: pbar.update(0, force=True) reconstructions = pycolmap.incremental_mapping( database_path, image_path, sfm_path, initial_image_pair_callback=lambda: pbar.update(2), next_image_callback=lambda: pbar.update(1), ) return reconstructions def run(): output_path = Path("example/") image_path = output_path / "Fountain/images" database_path = output_path / "database.db" sfm_path = output_path / "sfm" output_path.mkdir(exist_ok=True) # The log filename is postfixed with the execution timestamp. logging.set_log_destination(logging.INFO, output_path / "INFO.log.") data_url = "https://cvg-data.inf.ethz.ch/local-feature-evaluation-schoenberger2017/Strecha-Fountain.zip" if not image_path.exists(): logging.info("Downloading the data.") zip_path = output_path / "data.zip" urllib.request.urlretrieve(data_url, zip_path) with zipfile.ZipFile(zip_path, "r") as fid: fid.extractall(output_path) logging.info(f"Data extracted to {output_path}.") if database_path.exists(): database_path.unlink() pycolmap.set_random_seed(0) pycolmap.extract_features(database_path, image_path) pycolmap.match_exhaustive(database_path) if sfm_path.exists(): shutil.rmtree(sfm_path) sfm_path.mkdir(exist_ok=True) recs = incremental_mapping_with_pbar(database_path, image_path, sfm_path) # alternatively, use: # import custom_incremental_mapping # recs = custom_incremental_mapping.main(database_path, image_path, sfm_path) for idx, rec in recs.items(): logging.info(f"#{idx} {rec.summary()}") if __name__ == "__main__": run() colmap-3.10/pycolmap/pyproject.toml000066400000000000000000000026571464745566500175100ustar00rootroot00000000000000[build-system] requires = ["scikit-build-core>=0.3.3", "pybind11==2.12.0"] build-backend = "scikit_build_core.build" [project] name = "pycolmap" version = "3.10-dev" description="COLMAP bindings" readme = "README.md" authors = [ { name = "Mihai Dusmanu", email = "mihai.dusmanu@gmail.com" }, { name = "Paul-Edouard Sarlin", email = "psarlin@ethz.ch" }, { name = "Philipp Lindenberger", email = "plindenbe@ethz.ch" }, ] license = {text = "BSD-3-Clause"} urls = {Repository = "https://github.com/colmap/pycolmap"} requires-python = ">=3.7" dependencies = ["numpy"] classifiers = [ "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3 :: Only", ] [tool.scikit-build] wheel.expand-macos-universal-tags = true [tool.cibuildwheel] build = "cp3{8,9,10,11,12}-{macosx,manylinux,win}*" archs = ["auto64"] [tool.cibuildwheel.environment] VCPKG_COMMIT_ID = "e01906b2ba7e645a76ee021a19de616edc98d29f" [tool.cibuildwheel.linux] before-all = "{package}/ci/install-colmap-centos.sh" test-command = "python -c \"import pycolmap; print(pycolmap.__version__)\"" [tool.cibuildwheel.macos] before-all = "{package}/ci/install-colmap-macos.sh" test-command = "python -c \"import pycolmap; print(pycolmap.__version__)\"" [tool.cibuildwheel.windows] before-all = "powershell -File {package}/ci/install-colmap-windows.ps1" before-build = "pip install delvewheel" test-command = "powershell -File {package}/ci/test-colmap-windows.ps1" colmap-3.10/scripts/000077500000000000000000000000001464745566500144255ustar00rootroot00000000000000colmap-3.10/scripts/format/000077500000000000000000000000001464745566500157155ustar00rootroot00000000000000colmap-3.10/scripts/format/black.sh000077500000000000000000000015001464745566500173240ustar00rootroot00000000000000#!/usr/bin/env bash # This script runs the black Python formatter on the whole repository. # Check version version_string=$(black --version | sed -E 's/^.*(\d+\.\d+-.*).*$/\1/') expected_version_string='21.12' if [[ "$version_string" =~ "$expected_version_string" ]]; then echo "black version '$version_string' matches '$expected_version_string'" else echo "black version '$version_string' doesn't match '$expected_version_string'" exit 1 fi # Get all C++ files checked into the repo, excluding submodules root_folder=$(git rev-parse --show-toplevel) all_files=$( \ git ls-tree --full-tree -r --name-only HEAD . \ | grep "^.*\(\.py\)$" \ | sed "s~^~$root_folder/~") num_files=$(echo $all_files | wc -w) echo "Formatting ${num_files} files" # shellcheck disable=SC2086 black --line-length 80 ${all_files} colmap-3.10/scripts/format/clang_format.sh000077500000000000000000000023111464745566500207050ustar00rootroot00000000000000#!/usr/bin/env bash # This script applies clang-format to the whole repository. # Find clang-format tools=' clang-format-8 clang-format ' clang_format='' for tool in ${tools}; do if type -p "${tool}" > /dev/null; then clang_format=$tool break fi done if [ -z "$clang_format" ]; then echo "Could not locate clang-format" exit 1 fi echo "Found clang-format: $(which ${clang_format})" # Check version version_string=$($clang_format --version | sed -E 's/^.*(\d+\.\d+\.\d+-.*).*$/\1/') expected_version_string='14.0.0' if [[ "$version_string" =~ "$expected_version_string" ]]; then echo "clang-format version '$version_string' matches '$expected_version_string'" else echo "clang-format version '$version_string' doesn't match '$expected_version_string'" exit 1 fi # Get all C++ files checked into the repo, excluding submodules root_folder=$(git rev-parse --show-toplevel) all_files=$( \ git ls-tree --full-tree -r --name-only HEAD . \ | grep "^src/\(colmap\|pycolmap\).*\(\.cc\|\.h\|\.hpp\|\.cpp\|\.cu\)$" \ | sed "s~^~$root_folder/~") num_files=$(echo $all_files | wc -w) echo "Formatting ${num_files} files" # Run clang-format ${clang_format} -i $all_files colmap-3.10/scripts/matlab/000077500000000000000000000000001464745566500156655ustar00rootroot00000000000000colmap-3.10/scripts/matlab/cmap2rgb.m000066400000000000000000000036371464745566500175510ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function rgb = cmap2rgb(image, cmap, varargin) if length(varargin) == 1 clim = varargin{1}; image(image <= clim(1)) = clim(1); image(image > clim(2)) = clim(2); end image_min = min(image(:)); image_max = max(image(:)); image = (image - image_min) / (image_max - image_min) * size(cmap, 1); rgb = ind2rgb(uint32(image), cmap); end colmap-3.10/scripts/matlab/plot_model.m000077500000000000000000000045761464745566500202200ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function plot_model(cameras, images, points) % Visualize COLMAP model. keys = images.keys; camera_centers = zeros(images.length, 3); view_dirs = zeros(3 * images.length, 3); for i = 1:images.length image_id = keys{i}; image = images(image_id); camera_centers(i,:) = -image.R' * image.t; view_dirs(3 * i - 2,:) = camera_centers(i,:); view_dirs(3 * i - 1,:) = camera_centers(i,:)' + image.R' * [0; 0; 0.3]; view_dirs(3 * i,:) = nan; end keys = points.keys; xyz = zeros(points.length, 3); for i = 1:points.length point_id = keys{i}; point = points(point_id); xyz(i,:) = point.xyz; end hold on; plot3(camera_centers(:,1), camera_centers(:,2), camera_centers(:,3), 'xr'); plot3(view_dirs(:,1), view_dirs(:,2), view_dirs(:,3), '-b'); plot3(xyz(:,1), xyz(:,2), xyz(:,3), '.k'); hold off; end colmap-3.10/scripts/matlab/quat2rotmat.m000077500000000000000000000041651464745566500203370ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function rotmat = quat2rotmat(qvec) rotmat = [1 - 2 * qvec(3).^2 - 2 * qvec(4).^2, ... 2 * qvec(2) * qvec(3) - 2 * qvec(1) * qvec(4), ... 2 * qvec(4) * qvec(2) + 2 * qvec(1) * qvec(3); ... 2 * qvec(2) * qvec(3) + 2 * qvec(1) * qvec(4), ... 1 - 2 * qvec(2).^2 - 2 * qvec(4).^2, ... 2 * qvec(3) * qvec(4) - 2 * qvec(1) * qvec(2); ... 2 * qvec(4) * qvec(2) - 2 * qvec(1) * qvec(3), ... 2 * qvec(3) * qvec(4) + 2 * qvec(1) * qvec(2), ... 1 - 2 * qvec(2).^2 - 2 * qvec(3).^2]; end colmap-3.10/scripts/matlab/read_array.m000066400000000000000000000037761464745566500201710ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function array = read_array(path, varargin) if length(varargin) == 1 dtype = varargin{1}; else dtype = 'single'; end fid = fopen(path); line = fscanf(fid, '%d&%d&%d&', [1, 3]); width = line(1); height = line(2); channels = line(3); num = width * height * channels; array = fread(fid, num, dtype); array = reshape(array, [width, height, channels]); array = permute(array, [2 1 3]); array = cast(array, dtype); fclose(fid); end colmap-3.10/scripts/matlab/read_depth_map.m000066400000000000000000000035101464745566500207760ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function [depth_map, depth_map_rgb] = read_depth_map(path) depth_map = read_array(path); depth_range = prctile(depth_map(depth_map(:) > 0), [2, 98]); depth_map(depth_map<=0) = nan; depth_map_rgb = cmap2rgb(depth_map, [0 0 0; jet(2^15)], depth_range); end colmap-3.10/scripts/matlab/read_model.m000077500000000000000000000111611464745566500201410ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function [cameras, images, points3D] = read_model(path) % Read COLMAP model from folder, which contains a % cameras.txt, images.txt, and points3D.txt. if numel(path) > 0 && path(end) ~= '/' path = [path '/']; end cameras = read_cameras([path 'cameras.txt']); images = read_images([path 'images.txt']); points3D = read_points3D([path 'points3D.txt']); end function cameras = read_cameras(path) cameras = containers.Map('KeyType', 'int64', 'ValueType', 'any'); fid = fopen(path); tline = fgets(fid); while ischar(tline) elems = strsplit(tline); if numel(elems) < 4 || strcmp(elems(1), '#') tline = fgets(fid); continue end if mod(cameras.Count, 10) == 0 fprintf('Reading camera %d\n', cameras.length); end camera = struct; camera.camera_id = str2num(elems{1}); camera.model = elems{2}; camera.width = str2num(elems{3}); camera.height = str2num(elems{4}); camera.params = zeros(numel(elems) - 5, 1); for i = 5:numel(elems) - 1 camera.params(i - 4) = str2double(elems{i}); end cameras(camera.camera_id) = camera; tline = fgets(fid); end fclose(fid); end function images = read_images(path) images = containers.Map('KeyType', 'int64', 'ValueType', 'any'); fid = fopen(path); tline = fgets(fid); while ischar(tline) elems = strsplit(tline); if numel(elems) < 4 || strcmp(elems(1), '#') tline = fgets(fid); continue end if mod(images.Count, 10) == 0 fprintf('Reading image %d\n', images.length); end image = struct; image.image_id = str2num(elems{1}); qw = str2double(elems{2}); qx = str2double(elems{3}); qy = str2double(elems{4}); qz = str2double(elems{5}); image.R = quat2rotmat([qw, qx, qy, qz]); tx = str2double(elems{6}); ty = str2double(elems{7}); tz = str2double(elems{8}); image.t = [tx; ty; tz]; image.camera_id = str2num(elems{9}); image.name = elems{10}; tline = fgets(fid); elems = sscanf(tline, '%f'); elems = reshape(elems, [3, numel(elems) / 3]); image.xys = elems(1:2,:)'; image.point3D_ids = elems(3,:)'; images(image.image_id) = image; tline = fgets(fid); end fclose(fid); end function points3D = read_points3D(path) points3D = containers.Map('KeyType', 'int64', 'ValueType', 'any'); fid = fopen(path); tline = fgets(fid); while ischar(tline) if numel(tline) == 0 || strcmp(tline(1), '#') tline = fgets(fid); continue; end elems = sscanf(tline, '%f'); if numel(elems) == 0 tline = fgets(fid); continue; end if mod(points3D.Count, 1000) == 0 fprintf('Reading point %d\n', points3D.length); end point = struct; point.point3D_id = int64(elems(1)); point.xyz = elems(2:4); point.rgb = uint8(elems(5:7)); point.error = elems(8); point.track = int64(elems(9:end)); point.track = reshape(point.track, [2, numel(point.track) / 2])'; point.track(:,2) = point.track(:,2) + 1; points3D(point.point3D_id) = point; tline = fgets(fid); end fclose(fid); end colmap-3.10/scripts/matlab/read_normal_map.m000066400000000000000000000041031464745566500211610ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function [normal_map, normal_map_rgb] = read_normal_map(path, varargin) normal_map = read_array(path); normal_map_rgb = -[normal_map(:,:,1) normal_map(:,:,2) ... 2 * normal_map(:,:,3) + 1]; normal_map_rgb = reshape(normal_map_rgb, ... size(normal_map,1), size(normal_map,2), 3); normal_map_rgb = uint8(((normal_map_rgb + 1) ./ 2) .* 255); if length(varargin) == 1 depth_map = varargin{1}; normal_map_rgb(repmat(isnan(depth_map), [1, 1, 3])) = 0; end end colmap-3.10/scripts/matlab/read_ply.m000077500000000000000000000044231464745566500176500ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function [xyz, normals, rgb] = read_ply(path) % Read point cloud from PLY text file. file = fopen(path, 'r'); type = fscanf(file, '%s', 1); format = fscanf(file, '%s', 3); data = fscanf(file, '%s', 2); num_points = fscanf(file, '%d', 1); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 3); fscanf(file, '%s', 1); points_data = textscan(file, '%f %f %f %f %f %f %f %f %f', num_points); xyz = [points_data{1}, points_data{2}, points_data{3}]; rgb = [points_data{7}, points_data{8}, points_data{9}]; normals = [points_data{4}, points_data{5}, points_data{6}]; end colmap-3.10/scripts/matlab/write_array.m000066400000000000000000000034401464745566500203740ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function write_array(path, array) fid = fopen(path, 'w'); fprintf(fid, '%d&%d&%d&', size(array, 2), size(array, 1), size(array, 3)); array = permute(array, [2 1 3]); fwrite(fid, array, class(array)); fclose(fid); end colmap-3.10/scripts/matlab/write_ply.m000077500000000000000000000046461464745566500200760ustar00rootroot00000000000000% Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. % All rights reserved. % % Redistribution and use in source and binary forms, with or without % modification, are permitted provided that the following conditions are met: % % * Redistributions of source code must retain the above copyright % notice, this list of conditions and the following disclaimer. % % * Redistributions in binary form must reproduce the above copyright % notice, this list of conditions and the following disclaimer in the % documentation and/or other materials provided with the distribution. % % * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of % its contributors may be used to endorse or promote products derived % from this software without specific prior written permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % POSSIBILITY OF SUCH DAMAGE. function write_ply(path, xyz, normals, rgb) % Write point cloud to PLY text file. file = fopen(path, 'W'); fprintf(file,'ply\n'); fprintf(file,'format ascii 1.0\n'); fprintf(file,'element vertex %d\n',size(xyz,1)); fprintf(file,'property float x\n'); fprintf(file,'property float y\n'); fprintf(file,'property float z\n'); fprintf(file,'property float nx\n'); fprintf(file,'property float ny\n'); fprintf(file,'property float nz\n'); fprintf(file,'property uchar diffuse_red\n'); fprintf(file,'property uchar diffuse_green\n'); fprintf(file,'property uchar diffuse_blue\n'); fprintf(file,'end_header\n'); for i = 1:size(xyz, 1) fprintf(file, '%f %f %f %f %f %f %d %d %d\n', ... xyz(i,1), xyz(i,2), xyz(i,3), ... normals(i,1), normals(i,2), normals(i,3), ... uint8(rgb(i,1)), uint8(rgb(i,2)), uint8(rgb(i,3))); end fclose(file); end colmap-3.10/scripts/python/000077500000000000000000000000001464745566500157465ustar00rootroot00000000000000colmap-3.10/scripts/python/benchmark_eth3d.py000066400000000000000000000126561464745566500213530ustar00rootroot00000000000000import os import sys import argparse import urllib.request import subprocess def download_file(url, file_path, max_retries=3): if os.path.exists(file_path): return print(f"Downloading {url} to {file_path}") for retry in range(max_retries): try: urllib.request.urlretrieve(url, file_path) return except Exception as exc: print( f"Failed to download {url} (trial={retry+1}) to {file_path} due to {exc}" ) def check_small_errors_or_exit( dataset_name, max_rotation_error, max_proj_center_error, expected_num_images, errors_csv_path, ): print(f"Evaluating errors for {dataset_name}") error = False with open(errors_csv_path, "r") as fid: num_images = 0 for line in fid: line = line.strip() if len(line) == 0 or line.startswith("#"): continue rotation_error, proj_center_error = map(float, line.split(",")) num_images += 1 if rotation_error > max_rotation_error: print("Exceeded rotation error threshold:", rotation_error) error = True if proj_center_error > max_proj_center_error: print( "Exceeded projection center error threshold:", proj_center_error, ) error = True if num_images != expected_num_images: print("Unexpected number of images:", num_images) error = True if error: sys.exit(1) def process_dataset(args, dataset_name): print("Processing dataset:", dataset_name) workspace_path = os.path.join( os.path.realpath(args.workspace_path), dataset_name ) os.makedirs(workspace_path, exist_ok=True) dataset_archive_path = os.path.join(workspace_path, f"{dataset_name}.7z") download_file( f"https://www.eth3d.net/data/{dataset_name}_dslr_undistorted.7z", dataset_archive_path, ) subprocess.check_call( ["7zz", "x", "-y", f"{dataset_name}.7z"], cwd=workspace_path ) # Find undistorted parameters of first camera and initialize all images with it. with open( os.path.join( workspace_path, f"{dataset_name}/dslr_calibration_undistorted/cameras.txt", ), "r", ) as fid: for line in fid: if not line.startswith("#"): first_camera_data = line.split() camera_model = first_camera_data[1] assert camera_model == "PINHOLE" camera_params = first_camera_data[4:] assert len(camera_params) == 4 break # Count the number of expected images in the GT. expected_num_images = 0 with open( os.path.join( workspace_path, f"{dataset_name}/dslr_calibration_undistorted/images.txt", ), "r", ) as fid: for line in fid: if not line.startswith("#") and line.strip(): expected_num_images += 1 # Each image uses two consecutive lines. assert expected_num_images % 2 == 0 expected_num_images /= 2 # Run automatic reconstruction pipeline. subprocess.check_call( [ os.path.realpath(args.colmap_path), "automatic_reconstructor", "--image_path", f"{dataset_name}/images/", "--workspace_path", workspace_path, "--use_gpu", "1" if args.use_gpu else "0", "--num_threads", str(args.num_threads), "--quality", "low", "--camera_model", "PINHOLE", "--camera_params", ",".join(camera_params), ], cwd=workspace_path, ) # Compare reconstructed model to GT model. subprocess.check_call( [ os.path.realpath(args.colmap_path), "model_comparer", "--input_path1", "sparse/0", "--input_path2", f"{dataset_name}/dslr_calibration_undistorted/", "--output_path", ".", "--alignment_error", "proj_center", "--max_proj_center_error", str(args.max_proj_center_error), ], cwd=workspace_path, ) # Ensure discrepancy between reconstructed model and GT is small. check_small_errors_or_exit( dataset_name, args.max_rotation_error, args.max_proj_center_error, expected_num_images, os.path.join(workspace_path, "errors.csv"), ) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--dataset_names", required=True) parser.add_argument("--workspace_path", required=True) parser.add_argument("--colmap_path", required=True) parser.add_argument("--use_gpu", default=True, action="store_true") parser.add_argument("--use_cpu", dest="use_gpu", action="store_false") parser.add_argument("--num_threads", type=int, default=-1) parser.add_argument("--quality", default="medium") parser.add_argument("--max_rotation_error", type=float, default=1.0) parser.add_argument("--max_proj_center_error", type=float, default=0.1) return parser.parse_args() def main(): args = parse_args() for dataset_name in args.dataset_names.split(","): process_dataset(args, dataset_name.strip()) if __name__ == "__main__": main() colmap-3.10/scripts/python/build_windows_app.py000077500000000000000000000071341464745566500220410ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import glob import shutil import argparse def parse_args(): parser = argparse.ArgumentParser() parser.add_argument( "--install_path", required=True, help="The installation prefix, e.g., build/__install__", ) parser.add_argument( "--app_path", required=True, help="The application path, e.g., " "build/COLMAP-dev-windows", ) args = parser.parse_args() return args def mkdir_if_not_exists(path): assert os.path.exists(os.path.dirname(os.path.abspath(path))) if not os.path.exists(path): os.makedirs(path) def main(): args = parse_args() mkdir_if_not_exists(args.app_path) mkdir_if_not_exists(os.path.join(args.app_path, "bin")) mkdir_if_not_exists(os.path.join(args.app_path, "lib")) mkdir_if_not_exists(os.path.join(args.app_path, "lib/platforms")) # Copy batch scripts to app directory. shutil.copyfile( os.path.join(args.install_path, "COLMAP.bat"), os.path.join(args.app_path, "COLMAP.bat"), ) shutil.copyfile( os.path.join(args.install_path, "RUN_TESTS.bat"), os.path.join(args.app_path, "RUN_TESTS.bat"), ) # Copy executables to app directory. exe_files = glob.glob(os.path.join(args.install_path, "bin/*.exe")) for exe_file in exe_files: shutil.copyfile( exe_file, os.path.join(args.app_path, "bin", os.path.basename(exe_file)), ) # Copy shared libraries to app directory. dll_files = glob.glob(os.path.join(args.install_path, "lib/*.dll")) for dll_file in dll_files: shutil.copyfile( dll_file, os.path.join(args.app_path, "lib", os.path.basename(dll_file)), ) shutil.copyfile( os.path.join(args.install_path, "lib/platforms/qwindows.dll"), os.path.join(args.app_path, "lib/platforms/qwindows.dll"), ) # Create zip archive for deployment. shutil.make_archive(args.app_path, "zip", root_dir=args.app_path) if __name__ == "__main__": main() colmap-3.10/scripts/python/bundler_to_ply.py000077500000000000000000000113131464745566500213430ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script converts a Bundler reconstruction file to a PLY point cloud. import argparse import numpy as np def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--bundler_path", required=True) parser.add_argument("--ply_path", required=True) parser.add_argument("--normalize", type=bool, default=True) parser.add_argument("--normalize_p0", type=float, default=0.2) parser.add_argument("--normalize_p1", type=float, default=0.8) parser.add_argument("--min_track_length", type=int, default=3) args = parser.parse_args() return args def main(): args = parse_args() with open(args.bundler_path, "r") as fid: line = fid.readline() line = fid.readline() num_images, num_points = map(int, line.split()) for i in range(5 * num_images): fid.readline() xyz = np.zeros((num_points, 3), dtype=np.float64) rgb = np.zeros((num_points, 3), dtype=np.uint16) track_lengths = np.zeros((num_points,), dtype=np.uint32) for i in range(num_points): if i % 1000 == 0: print("Reading point", i, "/", num_points) xyz[i] = map(float, fid.readline().split()) rgb[i] = map(int, fid.readline().split()) track_lengths[i] = int(fid.readline().split()[0]) mask = track_lengths >= args.min_track_length xyz = xyz[mask] rgb = rgb[mask] if args.normalize: sorted_x = np.sort(xyz[:, 0]) sorted_y = np.sort(xyz[:, 1]) sorted_z = np.sort(xyz[:, 2]) num_coords = sorted_x.size min_coord = int(args.normalize_p0 * num_coords) max_coord = int(args.normalize_p1 * num_coords) mean_coords = xyz.mean(0) bbox_min = np.array( [sorted_x[min_coord], sorted_y[min_coord], sorted_z[min_coord]] ) bbox_max = np.array( [sorted_x[max_coord], sorted_y[max_coord], sorted_z[max_coord]] ) extent = np.linalg.norm(bbox_max - bbox_min) scale = 10.0 / extent xyz -= mean_coords xyz *= scale xyz[:, 2] *= -1 with open(args.ply_path, "w") as fid: fid.write("ply\n") fid.write("format ascii 1.0\n") fid.write("element vertex %d\n" % xyz.shape[0]) fid.write("property float x\n") fid.write("property float y\n") fid.write("property float z\n") fid.write("property float nx\n") fid.write("property float ny\n") fid.write("property float nz\n") fid.write("property uchar diffuse_red\n") fid.write("property uchar diffuse_green\n") fid.write("property uchar diffuse_blue\n") fid.write("end_header\n") for i in range(xyz.shape[0]): if i % 1000 == 0: print("Writing point", i, "/", xyz.shape[0]) fid.write( "%f %f %f 0 0 0 %d %d %d\n" % ( xyz[i, 0], xyz[i, 1], xyz[i, 2], rgb[i, 0], rgb[i, 1], rgb[i, 2], ) ) if __name__ == "__main__": main() colmap-3.10/scripts/python/clang_format_code.py000077500000000000000000000050031464745566500217470ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import string import argparse import subprocess def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--path", required=True) parser.add_argument("--exts", default=".h,.cc") parser.add_argument("--style", default="File") args = parser.parse_args() return args def main(): args = parse_args() exts = map(string.lower, args.exts.split(",")) for root, subdirs, files in os.walk(args.path): for f in files: name, ext = os.path.splitext(f) if ext.lower() in exts: file_path = os.path.join(root, f) proc = subprocess.Popen( ["clang-format", "--style", args.style, file_path], stdout=subprocess.PIPE, ) text = "".join(proc.stdout) with open(file_path, "w") as fd: fd.write(text) if __name__ == "__main__": main() colmap-3.10/scripts/python/crawl_camera_specs.py000077500000000000000000000130041464745566500221360ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import re import argparse import requests from lxml.html import soupparser MAX_REQUEST_TRIALS = 10 def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--lib_path", required=True) args = parser.parse_args() return args def request_trial(func, *args, **kwargs): for i in range(MAX_REQUEST_TRIALS): try: response = func(*args, **kwargs) except: continue else: return response raise SystemError def main(): args = parse_args() ########################################################################## # Header file ########################################################################## with open(args.lib_path + ".h", "w") as f: f.write("#include \n") f.write("#include \n") f.write("#include \n\n") f.write("// { make1 : ({ model1 : sensor-width in mm }, ...), ... }\n") f.write( "typedef std::vector> make_specs_t;\n" ) f.write( "typedef std::unordered_map camera_specs_t;;\n\n" ) f.write("camera_specs_t InitializeCameraSpecs();\n\n") ########################################################################## # Source file ########################################################################## makes_response = requests.get("http://www.digicamdb.com") makes_tree = soupparser.fromstring(makes_response.text) makes_node = makes_tree.find('.//select[@id="select_brand"]') makes = [b.attrib["value"] for b in makes_node.iter("option")] with open(args.lib_path + ".cc", "w") as f: f.write("camera_specs_t InitializeCameraSpecs() {\n") f.write(" camera_specs_t specs;\n\n") for make in makes: f.write(" {\n") f.write( ' auto& make_specs = specs["%s"];\n' % make.lower().replace(" ", "") ) models_response = request_trial( requests.post, "http://www.digicamdb.com/inc/ajax.php", data={"b": make, "role": "header_search"}, ) models_tree = soupparser.fromstring(models_response.text) models_code = "" num_models = 0 for model_node in models_tree.iter("option"): model = model_node.attrib.get("value") model_name = model_node.text if model is None: continue url = "http://www.digicamdb.com/specs/{0}_{1}".format( make, model ) specs_response = request_trial(requests.get, url) specs_tree = soupparser.fromstring(specs_response.text) for spec in specs_tree.findall('.//td[@class="info_key"]'): if spec.text.strip() == "Sensor:": sensor_text = spec.find("..").find( './td[@class="bold"]' ) sensor_text = sensor_text.text.strip() m = re.match(".*?([\d.]+) x ([\d.]+).*?", sensor_text) sensor_width = m.group(1) data = ( model_name.lower().replace(" ", ""), float(sensor_width.replace(" ", "")), ) models_code += ( ' make_specs.emplace_back("%s", %.4ff);\n' % data ) print(make, model_name) print(" ", sensor_text) num_models += 1 f.write(" make_specs.reserve(%d);\n" % num_models) f.write(models_code) f.write(" }\n\n") f.write(" return specs;\n") f.write("}\n") if __name__ == "__main__": main() colmap-3.10/scripts/python/database.py000077500000000000000000000326771464745566500201060ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script is based on an original implementation by True Price. import sys import sqlite3 import numpy as np IS_PYTHON3 = sys.version_info[0] >= 3 MAX_IMAGE_ID = 2 ** 31 - 1 CREATE_CAMERAS_TABLE = """CREATE TABLE IF NOT EXISTS cameras ( camera_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, model INTEGER NOT NULL, width INTEGER NOT NULL, height INTEGER NOT NULL, params BLOB, prior_focal_length INTEGER NOT NULL)""" CREATE_DESCRIPTORS_TABLE = """CREATE TABLE IF NOT EXISTS descriptors ( image_id INTEGER PRIMARY KEY NOT NULL, rows INTEGER NOT NULL, cols INTEGER NOT NULL, data BLOB, FOREIGN KEY(image_id) REFERENCES images(image_id) ON DELETE CASCADE)""" CREATE_IMAGES_TABLE = """CREATE TABLE IF NOT EXISTS images ( image_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL UNIQUE, camera_id INTEGER NOT NULL, CONSTRAINT image_id_check CHECK(image_id >= 0 and image_id < {}), FOREIGN KEY(camera_id) REFERENCES cameras(camera_id)) """.format( MAX_IMAGE_ID ) CREATE_POSE_PRIORS_TABLE = """CREATE TABLE IF NOT EXISTS pose_priors ( image_id INTEGER PRIMARY KEY NOT NULL, position BLOB, coordinate_system INTEGER NOT NULL, FOREIGN KEY(image_id) REFERENCES images(image_id) ON DELETE CASCADE)""" CREATE_TWO_VIEW_GEOMETRIES_TABLE = """ CREATE TABLE IF NOT EXISTS two_view_geometries ( pair_id INTEGER PRIMARY KEY NOT NULL, rows INTEGER NOT NULL, cols INTEGER NOT NULL, data BLOB, config INTEGER NOT NULL, F BLOB, E BLOB, H BLOB, qvec BLOB, tvec BLOB) """ CREATE_KEYPOINTS_TABLE = """CREATE TABLE IF NOT EXISTS keypoints ( image_id INTEGER PRIMARY KEY NOT NULL, rows INTEGER NOT NULL, cols INTEGER NOT NULL, data BLOB, FOREIGN KEY(image_id) REFERENCES images(image_id) ON DELETE CASCADE) """ CREATE_MATCHES_TABLE = """CREATE TABLE IF NOT EXISTS matches ( pair_id INTEGER PRIMARY KEY NOT NULL, rows INTEGER NOT NULL, cols INTEGER NOT NULL, data BLOB)""" CREATE_NAME_INDEX = ( "CREATE UNIQUE INDEX IF NOT EXISTS index_name ON images(name)" ) CREATE_ALL = "; ".join( [ CREATE_CAMERAS_TABLE, CREATE_IMAGES_TABLE, CREATE_POSE_PRIORS_TABLE, CREATE_KEYPOINTS_TABLE, CREATE_DESCRIPTORS_TABLE, CREATE_MATCHES_TABLE, CREATE_TWO_VIEW_GEOMETRIES_TABLE, CREATE_NAME_INDEX, ] ) def image_ids_to_pair_id(image_id1, image_id2): if image_id1 > image_id2: image_id1, image_id2 = image_id2, image_id1 return image_id1 * MAX_IMAGE_ID + image_id2 def pair_id_to_image_ids(pair_id): image_id2 = pair_id % MAX_IMAGE_ID image_id1 = (pair_id - image_id2) / MAX_IMAGE_ID return image_id1, image_id2 def array_to_blob(array): if IS_PYTHON3: return array.tostring() else: return np.getbuffer(array) def blob_to_array(blob, dtype, shape=(-1,)): if IS_PYTHON3: return np.fromstring(blob, dtype=dtype).reshape(*shape) else: return np.frombuffer(blob, dtype=dtype).reshape(*shape) class COLMAPDatabase(sqlite3.Connection): @staticmethod def connect(database_path): return sqlite3.connect(database_path, factory=COLMAPDatabase) def __init__(self, *args, **kwargs): super(COLMAPDatabase, self).__init__(*args, **kwargs) self.create_tables = lambda: self.executescript(CREATE_ALL) self.create_cameras_table = lambda: self.executescript( CREATE_CAMERAS_TABLE ) self.create_descriptors_table = lambda: self.executescript( CREATE_DESCRIPTORS_TABLE ) self.create_images_table = lambda: self.executescript( CREATE_IMAGES_TABLE ) self.create_pose_priors_table = lambda: self.executescript( CREATE_POSE_PRIORS_TABLE ) self.create_two_view_geometries_table = lambda: self.executescript( CREATE_TWO_VIEW_GEOMETRIES_TABLE ) self.create_keypoints_table = lambda: self.executescript( CREATE_KEYPOINTS_TABLE ) self.create_matches_table = lambda: self.executescript( CREATE_MATCHES_TABLE ) self.create_name_index = lambda: self.executescript(CREATE_NAME_INDEX) def add_camera( self, model, width, height, params, prior_focal_length=False, camera_id=None, ): params = np.asarray(params, np.float64) cursor = self.execute( "INSERT INTO cameras VALUES (?, ?, ?, ?, ?, ?)", ( camera_id, model, width, height, array_to_blob(params), prior_focal_length, ), ) return cursor.lastrowid def add_image( self, name, camera_id, prior_q=np.full(4, np.NaN), prior_t=np.full(3, np.NaN), image_id=None, ): cursor = self.execute( "INSERT INTO images VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", ( image_id, name, camera_id, prior_q[0], prior_q[1], prior_q[2], prior_q[3], prior_t[0], prior_t[1], prior_t[2], ), ) return cursor.lastrowid def add_pose_prior(self, image_id, position, coordinate_system=-1): position = np.asarray(position, dtype=np.float64) self.execute( "INSERT INTO pose_priors VALUES (?, ?, ?)", (image_id, array_to_blob(position), coordinate_system), ) def add_keypoints(self, image_id, keypoints): assert len(keypoints.shape) == 2 assert keypoints.shape[1] in [2, 4, 6] keypoints = np.asarray(keypoints, np.float32) self.execute( "INSERT INTO keypoints VALUES (?, ?, ?, ?)", (image_id,) + keypoints.shape + (array_to_blob(keypoints),), ) def add_descriptors(self, image_id, descriptors): descriptors = np.ascontiguousarray(descriptors, np.uint8) self.execute( "INSERT INTO descriptors VALUES (?, ?, ?, ?)", (image_id,) + descriptors.shape + (array_to_blob(descriptors),), ) def add_matches(self, image_id1, image_id2, matches): assert len(matches.shape) == 2 assert matches.shape[1] == 2 if image_id1 > image_id2: matches = matches[:, ::-1] pair_id = image_ids_to_pair_id(image_id1, image_id2) matches = np.asarray(matches, np.uint32) self.execute( "INSERT INTO matches VALUES (?, ?, ?, ?)", (pair_id,) + matches.shape + (array_to_blob(matches),), ) def add_two_view_geometry( self, image_id1, image_id2, matches, F=np.eye(3), E=np.eye(3), H=np.eye(3), qvec=np.array([1.0, 0.0, 0.0, 0.0]), tvec=np.zeros(3), config=2, ): assert len(matches.shape) == 2 assert matches.shape[1] == 2 if image_id1 > image_id2: matches = matches[:, ::-1] pair_id = image_ids_to_pair_id(image_id1, image_id2) matches = np.asarray(matches, np.uint32) F = np.asarray(F, dtype=np.float64) E = np.asarray(E, dtype=np.float64) H = np.asarray(H, dtype=np.float64) qvec = np.asarray(qvec, dtype=np.float64) tvec = np.asarray(tvec, dtype=np.float64) self.execute( "INSERT INTO two_view_geometries VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (pair_id,) + matches.shape + ( array_to_blob(matches), config, array_to_blob(F), array_to_blob(E), array_to_blob(H), array_to_blob(qvec), array_to_blob(tvec), ), ) def example_usage(): import os import argparse parser = argparse.ArgumentParser() parser.add_argument("--database_path", default="database.db") args = parser.parse_args() if os.path.exists(args.database_path): print("ERROR: database path already exists -- will not modify it.") return # Open the database. db = COLMAPDatabase.connect(args.database_path) # For convenience, try creating all the tables upfront. db.create_tables() # Create dummy cameras. model1, width1, height1, params1 = ( 0, 1024, 768, np.array((1024.0, 512.0, 384.0)), ) model2, width2, height2, params2 = ( 2, 1024, 768, np.array((1024.0, 512.0, 384.0, 0.1)), ) camera_id1 = db.add_camera(model1, width1, height1, params1) camera_id2 = db.add_camera(model2, width2, height2, params2) # Create dummy images. image_id1 = db.add_image("image1.png", camera_id1) image_id2 = db.add_image("image2.png", camera_id1) image_id3 = db.add_image("image3.png", camera_id2) image_id4 = db.add_image("image4.png", camera_id2) # Create dummy keypoints. # # Note that COLMAP supports: # - 2D keypoints: (x, y) # - 4D keypoints: (x, y, theta, scale) # - 6D affine keypoints: (x, y, a_11, a_12, a_21, a_22) num_keypoints = 1000 keypoints1 = np.random.rand(num_keypoints, 2) * (width1, height1) keypoints2 = np.random.rand(num_keypoints, 2) * (width1, height1) keypoints3 = np.random.rand(num_keypoints, 2) * (width2, height2) keypoints4 = np.random.rand(num_keypoints, 2) * (width2, height2) db.add_keypoints(image_id1, keypoints1) db.add_keypoints(image_id2, keypoints2) db.add_keypoints(image_id3, keypoints3) db.add_keypoints(image_id4, keypoints4) # Create dummy matches. M = 50 matches12 = np.random.randint(num_keypoints, size=(M, 2)) matches23 = np.random.randint(num_keypoints, size=(M, 2)) matches34 = np.random.randint(num_keypoints, size=(M, 2)) db.add_matches(image_id1, image_id2, matches12) db.add_matches(image_id2, image_id3, matches23) db.add_matches(image_id3, image_id4, matches34) # Commit the data to the file. db.commit() # Read and check cameras. rows = db.execute("SELECT * FROM cameras") camera_id, model, width, height, params, prior = next(rows) params = blob_to_array(params, np.float64) assert camera_id == camera_id1 assert model == model1 and width == width1 and height == height1 assert np.allclose(params, params1) camera_id, model, width, height, params, prior = next(rows) params = blob_to_array(params, np.float64) assert camera_id == camera_id2 assert model == model2 and width == width2 and height == height2 assert np.allclose(params, params2) # Read and check keypoints. keypoints = dict( (image_id, blob_to_array(data, np.float32, (-1, 2))) for image_id, data in db.execute("SELECT image_id, data FROM keypoints") ) assert np.allclose(keypoints[image_id1], keypoints1) assert np.allclose(keypoints[image_id2], keypoints2) assert np.allclose(keypoints[image_id3], keypoints3) assert np.allclose(keypoints[image_id4], keypoints4) # Read and check matches. pair_ids = [ image_ids_to_pair_id(*pair) for pair in ( (image_id1, image_id2), (image_id2, image_id3), (image_id3, image_id4), ) ] matches = dict( (pair_id_to_image_ids(pair_id), blob_to_array(data, np.uint32, (-1, 2))) for pair_id, data in db.execute("SELECT pair_id, data FROM matches") ) assert np.all(matches[(image_id1, image_id2)] == matches12) assert np.all(matches[(image_id2, image_id3)] == matches23) assert np.all(matches[(image_id3, image_id4)] == matches34) # Clean up. db.close() if os.path.exists(args.database_path): os.remove(args.database_path) if __name__ == "__main__": example_usage() colmap-3.10/scripts/python/export_inlier_matches.py000077500000000000000000000064601464745566500227200ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script exports inlier matches from a COLMAP database to a text file. import os import argparse import sqlite3 import numpy as np def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--database_path", required=True) parser.add_argument("--output_path", required=True) parser.add_argument("--min_num_matches", type=int, default=15) args = parser.parse_args() return args def pair_id_to_image_ids(pair_id): image_id2 = pair_id % 2147483647 image_id1 = (pair_id - image_id2) / 2147483647 return image_id1, image_id2 def main(): args = parse_args() connection = sqlite3.connect(args.database_path) cursor = connection.cursor() images = {} cursor.execute("SELECT image_id, camera_id, name FROM images;") for row in cursor: image_id = row[0] image_name = row[2] images[image_id] = image_name with open(os.path.join(args.output_path), "w") as fid: cursor.execute( "SELECT pair_id, data FROM two_view_geometries WHERE rows>=?;", (args.min_num_matches,), ) for row in cursor: pair_id = row[0] inlier_matches = np.fromstring(row[1], dtype=np.uint32).reshape( -1, 2 ) image_id1, image_id2 = pair_id_to_image_ids(pair_id) image_name1 = images[image_id1] image_name2 = images[image_id2] fid.write( "%s %s %d\n" % (image_name1, image_name2, inlier_matches.shape[0]) ) for i in range(inlier_matches.shape[0]): fid.write("%d %d\n" % tuple(inlier_matches[i])) cursor.close() connection.close() if __name__ == "__main__": main() colmap-3.10/scripts/python/export_inlier_pairs.py000077500000000000000000000061521464745566500224100ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script exports inlier image pairs from a COLMAP database to a text file. import sqlite3 import argparse def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--database_path", required=True) parser.add_argument("--match_list_path", required=True) parser.add_argument("--min_num_matches", type=int, default=15) args = parser.parse_args() return args def pair_id_to_image_ids(pair_id): image_id2 = pair_id % 2147483647 image_id1 = (pair_id - image_id2) / 2147483647 return image_id1, image_id2 def main(): args = parse_args() connection = sqlite3.connect(args.database_path) cursor = connection.cursor() # Get a mapping between image ids and image names image_id_to_name = dict() cursor.execute("SELECT image_id, name FROM images;") for row in cursor: image_id = row[0] name = row[1] image_id_to_name[image_id] = name # Iterate over entries in the two_view_geometries table output = open(args.match_list_path, "w") cursor.execute("SELECT pair_id, rows FROM two_view_geometries;") for row in cursor: pair_id = row[0] rows = row[1] if rows < args.min_num_matches: continue image_id1, image_id2 = pair_id_to_image_ids(pair_id) image_name1 = image_id_to_name[image_id1] image_name2 = image_id_to_name[image_id2] output.write("%s %s\n" % (image_name1, image_name2)) output.close() cursor.close() connection.close() if __name__ == "__main__": main() colmap-3.10/scripts/python/export_to_bundler.py000077500000000000000000000152271464745566500220700ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script exports a COLMAP database to the file structure to run Bundler. import os import argparse import sqlite3 import shutil import gzip import numpy as np def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--database_path", required=True) parser.add_argument("--image_path", required=True) parser.add_argument("--output_path", required=True) parser.add_argument("--min_num_matches", type=int, default=15) args = parser.parse_args() return args def pair_id_to_image_ids(pair_id): image_id2 = pair_id % 2147483647 image_id1 = (pair_id - image_id2) / 2147483647 return image_id1, image_id2 def main(): args = parse_args() connection = sqlite3.connect(args.database_path) cursor = connection.cursor() try: os.makedirs(args.output_path) except: pass cameras = {} cursor.execute("SELECT camera_id, params FROM cameras;") for row in cursor: camera_id = row[0] params = np.fromstring(row[1], dtype=np.double) cameras[camera_id] = params images = {} with open(os.path.join(args.output_path, "list.txt"), "w") as fid: cursor.execute("SELECT image_id, camera_id, name FROM images;") for row in cursor: image_id = row[0] camera_id = row[1] image_name = row[2] print("Copying image", image_name) images[image_id] = (len(images), image_name) fid.write("./%s 0 %f\n" % (image_name, cameras[camera_id][0])) if not os.path.exists(os.path.join(args.output_path, image_name)): shutil.copyfile( os.path.join(args.image_path, image_name), os.path.join(args.output_path, image_name), ) for image_id, (image_idx, image_name) in images.iteritems(): print("Exporting key file for", image_name) base_name, ext = os.path.splitext(image_name) key_file_name = os.path.join(args.output_path, base_name + ".key") key_file_name_gz = key_file_name + ".gz" if os.path.exists(key_file_name_gz): continue cursor.execute( "SELECT data FROM keypoints WHERE image_id=?;", (image_id,) ) row = next(cursor) if row[0] is None: keypoints = np.zeros((0, 6), dtype=np.float32) descriptors = np.zeros((0, 128), dtype=np.uint8) else: keypoints = np.fromstring(row[0], dtype=np.float32).reshape(-1, 6) cursor.execute( "SELECT data FROM descriptors WHERE image_id=?;", (image_id,) ) row = next(cursor) descriptors = np.fromstring(row[0], dtype=np.uint8).reshape(-1, 128) with open(key_file_name, "w") as fid: fid.write("%d %d\n" % (keypoints.shape[0], descriptors.shape[1])) for r in range(keypoints.shape[0]): fid.write( "%f %f %f %f\n" % ( keypoints[r, 1], keypoints[r, 0], keypoints[r, 2], keypoints[r, 3], ) ) for i in range(0, 128, 20): desc_block = descriptors[r, i : i + 20] fid.write(" ".join(map(str, desc_block.ravel().tolist()))) fid.write("\n") with open(key_file_name, "rb") as fid_in: with gzip.open(key_file_name + ".gz", "wb") as fid_out: fid_out.writelines(fid_in) os.remove(key_file_name) with open(os.path.join(args.output_path, "matches.init.txt"), "w") as fid: cursor.execute( "SELECT pair_id, data FROM two_view_geometries " "WHERE rows>=?;", (args.min_num_matches,), ) for row in cursor: pair_id = row[0] inlier_matches = np.fromstring(row[1], dtype=np.uint32).reshape( -1, 2 ) image_id1, image_id2 = pair_id_to_image_ids(pair_id) image_idx1 = images[image_id1][0] image_idx2 = images[image_id2][0] fid.write( "%d %d\n%d\n" % (image_idx1, image_idx2, inlier_matches.shape[0]) ) for i in range(inlier_matches.shape[0]): fid.write( "%d %d\n" % (inlier_matches[i, 0], inlier_matches[i, 1]) ) with open(os.path.join(args.output_path, "run_bundler.sh"), "w") as fid: fid.write("bin/Bundler list.txt \\\n") fid.write("--run_bundle \\\n") fid.write("--use_focal_estimate \\\n") fid.write("--output_all bundle_ \\\n") fid.write("--constrain_focal \\\n") fid.write("--estimate_distortion \\\n") fid.write("--match_table matches.init.txt \\\n") fid.write("--variable_focal_length \\\n") fid.write("--output_dir bundle \\\n") fid.write("--output bundle.out \\\n") fid.write("--constrain_focal_weight 0.0001 \\\n") cursor.close() connection.close() if __name__ == "__main__": main() colmap-3.10/scripts/python/export_to_visualsfm.py000077500000000000000000000145371464745566500224510ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script exports a COLMAP database to the file structure to run VisualSfM. import os import sys import argparse import sqlite3 import shutil import gzip import numpy as np def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--database_path", required=True) parser.add_argument("--image_path", required=True) parser.add_argument("--output_path", required=True) parser.add_argument("--min_num_matches", type=int, default=15) parser.add_argument("--binary_feature_files", type=bool, default=True) args = parser.parse_args() return args def pair_id_to_image_ids(pair_id): image_id2 = pair_id % 2147483647 image_id1 = (pair_id - image_id2) / 2147483647 return image_id1, image_id2 def main(): args = parse_args() connection = sqlite3.connect(args.database_path) cursor = connection.cursor() try: os.makedirs(args.output_path) except: pass cameras = {} cursor.execute("SELECT camera_id, params FROM cameras;") for row in cursor: camera_id = row[0] params = np.fromstring(row[1], dtype=np.double) cameras[camera_id] = params images = {} cursor.execute("SELECT image_id, camera_id, name FROM images;") for row in cursor: image_id = row[0] camera_id = row[1] image_name = row[2] print("Copying image", image_name) images[image_id] = (len(images), image_name) if not os.path.exists(os.path.join(args.output_path, image_name)): shutil.copyfile( os.path.join(args.image_path, image_name), os.path.join(args.output_path, image_name), ) # The magic numbers used in VisualSfM's binary file format for storing the # feature descriptors. sift_name = 1413892435 sift_version_v4 = 808334422 sift_eof_marker = 1179600383 for image_id, (image_idx, image_name) in images.iteritems(): print("Exporting key file for", image_name) base_name, ext = os.path.splitext(image_name) key_file_name = os.path.join(args.output_path, base_name + ".sift") if os.path.exists(key_file_name): continue cursor.execute( "SELECT data FROM keypoints WHERE image_id=?;", (image_id,) ) row = next(cursor) if row[0] is None: keypoints = np.zeros((0, 6), dtype=np.float32) descriptors = np.zeros((0, 128), dtype=np.uint8) else: keypoints = np.fromstring(row[0], dtype=np.float32).reshape(-1, 6) cursor.execute( "SELECT data FROM descriptors WHERE image_id=?;", (image_id,) ) row = next(cursor) descriptors = np.fromstring(row[0], dtype=np.uint8).reshape(-1, 128) if args.binary_feature_files: with open(key_file_name, "wb") as fid: fid.write(struct.pack("i", sift_name)) fid.write(struct.pack("i", sift_version_v4)) fid.write(struct.pack("i", keypoints.shape[0])) fid.write(struct.pack("i", 4)) fid.write(struct.pack("i", 128)) keypoints[:, :4].astype(np.float32).tofile(fid) descriptors.astype(np.uint8).tofile(fid) fid.write(struct.pack("i", sift_eof_marker)) else: with open(key_file_name, "w") as fid: fid.write( "%d %d\n" % (keypoints.shape[0], descriptors.shape[1]) ) for r in range(keypoints.shape[0]): fid.write("%f %f 0 0 " % (keypoints[r, 0], keypoints[r, 1])) fid.write( " ".join(map(str, descriptors[r].ravel().tolist())) ) fid.write("\n") with open(os.path.join(args.output_path, "matches.txt"), "w") as fid: cursor.execute( "SELECT pair_id, data FROM two_view_geometries " "WHERE rows>=?;", (args.min_num_matches,), ) for row in cursor: pair_id = row[0] inlier_matches = np.fromstring(row[1], dtype=np.uint32).reshape( -1, 2 ) image_id1, image_id2 = pair_id_to_image_ids(pair_id) image_name1 = images[image_id1][1] image_name2 = images[image_id2][1] fid.write( "%s %s %d\n" % (image_name1, image_name2, inlier_matches.shape[0]) ) line1 = "" line2 = "" for i in range(inlier_matches.shape[0]): line1 += "%d " % inlier_matches[i, 0] line2 += "%d " % inlier_matches[i, 1] fid.write(line1 + "\n") fid.write(line2 + "\n") cursor.close() connection.close() if __name__ == "__main__": main() colmap-3.10/scripts/python/flickr_downloader.py000077500000000000000000000143301464745566500220140ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import time import datetime import urllib import urllib2 import urlparse import socket import argparse import multiprocessing import xml.etree.ElementTree as ElementTree PER_PAGE = 500 SORT = "date-posted-desc" URL = ( "https://api.flickr.com/services/rest/?method=flickr.photos.search&" "api_key=%s&text=%s&sort=%s&per_page=%d&page=%d&min_upload_date=%s&" "max_upload_date=%s&format=rest&extras=url_o,url_l,url_c,url_z,url_n" ) MAX_PAGE_REQUESTS = 5 MAX_PAGE_TIMEOUT = 20 MAX_IMAGE_REQUESTS = 3 TIME_SKIP = 24 * 60 * 60 MAX_DATE = time.time() MIN_DATE = MAX_DATE - TIME_SKIP def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--search_text", required=True) parser.add_argument("--api_key", required=True) parser.add_argument("--image_path", required=True) parser.add_argument("--num_procs", type=int, default=10) parser.add_argument("--max_days_without_image", type=int, default=365) args = parser.parse_args() return args def compose_url(page, api_key, text, min_date, max_date): return URL % ( api_key, text, SORT, PER_PAGE, page, str(min_date), str(max_date), ) def parse_page(page, api_key, text, min_date, max_date): f = None for _ in range(MAX_PAGE_REQUESTS): try: f = urllib2.urlopen( compose_url(page, api_key, text, min_date, max_date), timeout=MAX_PAGE_TIMEOUT, ) except socket.timeout: continue else: break if f is None: return { "pages": "0", "total": "0", "page": "0", "perpage": "0", }, tuple() response = f.read() root = ElementTree.fromstring(response) if root.attrib["stat"] != "ok": raise IOError photos = [] for photo in root.iter("photo"): photos.append(photo.attrib) return root.find("photos").attrib, photos class PhotoDownloader(object): def __init__(self, image_path): self.image_path = image_path def __call__(self, photo): # Find the URL corresponding to the highest image resolution. We will # need this URL here to determine the image extension (typically .jpg, # but could be .png, .gif, etc). url = None for url_suffix in ("o", "l", "k", "h", "b", "c", "z"): url_attr = "url_%s" % url_suffix if photo.get(url_attr) is not None: url = photo.get(url_attr) break if url is not None: # Note that the following statement may fail in Python 3. urlparse # may need to be replaced with urllib.parse. url_filename = urlparse.urlparse(url).path image_ext = os.path.splitext(url_filename)[1] image_name = "%s_%s%s" % (photo["id"], photo["secret"], image_ext) path = os.path.join(self.image_path, image_name) if not os.path.exists(path): print(url) for _ in range(MAX_IMAGE_REQUESTS): try: urllib.urlretrieve(url, path) except urllib.ContentTooShortError: continue else: break def main(): args = parse_args() downloader = PhotoDownloader(args.image_path) pool = multiprocessing.Pool(processes=args.num_procs) num_pages = float("inf") page = 0 min_date = MIN_DATE max_date = MAX_DATE days_in_row = 0 search_text = args.search_text.replace(" ", "-") while num_pages > page: page += 1 metadata, photos = parse_page( page, args.api_key, search_text, min_date, max_date ) num_pages = int(metadata["pages"]) print(78 * "=") print("Page:\t\t", page, "of", num_pages) print("Min-Date:\t", datetime.datetime.fromtimestamp(min_date)) print("Max-Date:\t", datetime.datetime.fromtimestamp(max_date)) print("Num-Photos:\t", len(photos)) print(78 * "=") try: pool.map_async(downloader, photos).get(1e10) except KeyboardInterrupt: pool.wait() break if page >= num_pages: max_date -= TIME_SKIP min_date -= TIME_SKIP page = 0 if num_pages == 0: days_in_row = days_in_row + 1 num_pages = float("inf") print(" No images in", days_in_row, "days in a row") if days_in_row == args.max_days_without_image: break else: days_in_row = 0 if __name__ == "__main__": main() colmap-3.10/scripts/python/merge_ply_files.py000077500000000000000000000051111464745566500214660ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script merges multiple homogeneous PLY files into a single PLY file. import os import glob import argparse import numpy as np import plyfile def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--folder_path", required=True) parser.add_argument("--merged_path", required=True) args = parser.parse_args() return args def main(): args = parse_args() files = [] for file_name in os.listdir(args.folder_path): if len(file_name) < 4 or file_name[-4:].lower() != ".ply": continue print("Reading file", file_name) file = plyfile.PlyData.read(os.path.join(args.folder_path, file_name)) for element in file.elements: files.append(element.data) print("Merging files") merged_file = np.concatenate(files, -1) merged_el = plyfile.PlyElement.describe(merged_file, "vertex") print("Writing merged file") plyfile.PlyData([merged_el]).write(args.merged_path) if __name__ == "__main__": main() colmap-3.10/scripts/python/migrate_database_pose_prior.py000077500000000000000000000065531464745566500240510ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import numpy as np import argparse from database import COLMAPDatabase if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--database_path", type=str, required=True) parser.add_argument("--is_cartesian", action="store_true") parser.add_argument("--cleanup", action="store_true") args = parser.parse_args() db = COLMAPDatabase.connect(args.database_path) pose_priors = {} rows = db.execute("SELECT * FROM images") for image_id, _, _, *cam_from_world_prior in rows: if not cam_from_world_prior: # newer format database continue qvec = np.array(cam_from_world_prior[:4], dtype=float) tvec = np.array(cam_from_world_prior[4:], dtype=float) if np.isfinite(qvec).any(): print( f"Warning: rotation prior for image {image_id} " "will be lost during migration." ) if np.isfinite(tvec).any(): pose_priors[image_id] = tvec print(f"Found location priors for {len(pose_priors)} images.") coordinate_systems = {"UNKNOWN": -1, "WGS84": 0, "CARTESIAN": 1} coordinate_system = coordinate_systems[ "CARTESIAN" if args.is_cartesian else "WGS84" ] db.create_pose_priors_table() for image_id, position in pose_priors.items(): (exists,) = db.execute( "SELECT COUNT(*) FROM pose_priors WHERE image_id = ?", (image_id,), ).fetchone() if exists: print(f"Location prior for {image_id} already exists, skipping.") continue db.add_pose_prior(image_id, position, coordinate_system) if args.cleanup: for col in ["qw", "qx", "qy", "qz", "tx", "ty", "tz"]: db.execute(f"ALTER TABLE images DROP COLUMN prior_{col}") db.commit() colmap-3.10/scripts/python/nvm_to_ply.py000077500000000000000000000113271464745566500205150ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script converts a VisualSfM reconstruction file to a PLY point cloud. import os import argparse import numpy as np def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--nvm_path", required=True) parser.add_argument("--ply_path", required=True) parser.add_argument("--normalize", type=bool, default=True) parser.add_argument("--normalize_p0", type=float, default=0.2) parser.add_argument("--normalize_p1", type=float, default=0.8) parser.add_argument("--min_track_length", type=int, default=3) args = parser.parse_args() return args def main(): args = parse_args() with open(args.nvm_path, "r") as fid: line = fid.readline() line = fid.readline() num_images = int(fid.readline()) for i in range(num_images + 1): fid.readline() num_points = int(fid.readline()) xyz = np.zeros((num_points, 3), dtype=np.float64) rgb = np.zeros((num_points, 3), dtype=np.uint16) track_lengths = np.zeros((num_points,), dtype=np.uint32) for i in range(num_points): if i % 1000 == 0: print("Reading point", i, "/", num_points) elems = fid.readline().split() xyz[i] = map(float, elems[0:3]) rgb[i] = map(int, elems[3:6]) track_lengths[i] = int(elems[6]) mask = track_lengths >= args.min_track_length xyz = xyz[mask] rgb = rgb[mask] if args.normalize: sorted_x = np.sort(xyz[:, 0]) sorted_y = np.sort(xyz[:, 1]) sorted_z = np.sort(xyz[:, 2]) num_coords = sorted_x.size min_coord = int(args.normalize_p0 * num_coords) max_coord = int(args.normalize_p1 * num_coords) mean_coords = xyz.mean(0) bbox_min = np.array( [sorted_x[min_coord], sorted_y[min_coord], sorted_z[min_coord]] ) bbox_max = np.array( [sorted_x[max_coord], sorted_y[max_coord], sorted_z[max_coord]] ) extent = np.linalg.norm(bbox_max - bbox_min) scale = 10.0 / extent xyz -= mean_coords xyz *= scale with open(args.ply_path, "w") as fid: fid.write("ply\n") fid.write("format ascii 1.0\n") fid.write("element vertex %d\n" % xyz.shape[0]) fid.write("property float x\n") fid.write("property float y\n") fid.write("property float z\n") fid.write("property float nx\n") fid.write("property float ny\n") fid.write("property float nz\n") fid.write("property uchar diffuse_red\n") fid.write("property uchar diffuse_green\n") fid.write("property uchar diffuse_blue\n") fid.write("end_header\n") for i in range(xyz.shape[0]): if i % 1000 == 0: print("Writing point", i, "/", xyz.shape[0]) fid.write( "%f %f %f 0 0 0 %d %d %d\n" % ( xyz[i, 0], xyz[i, 1], xyz[i, 2], rgb[i, 0], rgb[i, 1], rgb[i, 2], ) ) if __name__ == "__main__": main() colmap-3.10/scripts/python/plyfile.py000077500000000000000000000624471464745566500200040ustar00rootroot00000000000000# Copyright 2014 Darsh Ranjan # # This file is part of python-plyfile. # # python-plyfile is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # python-plyfile is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with python-plyfile. If not, see # . from itertools import islice as _islice import numpy as _np from sys import byteorder as _byteorder try: _range = xrange except NameError: _range = range # Many-many relation _data_type_relation = [ ("int8", "i1"), ("char", "i1"), ("uint8", "u1"), ("uchar", "b1"), ("uchar", "u1"), ("int16", "i2"), ("short", "i2"), ("uint16", "u2"), ("ushort", "u2"), ("int32", "i4"), ("int", "i4"), ("uint32", "u4"), ("uint", "u4"), ("float32", "f4"), ("float", "f4"), ("float64", "f8"), ("double", "f8"), ] _data_types = dict(_data_type_relation) _data_type_reverse = dict((b, a) for (a, b) in _data_type_relation) _types_list = [] _types_set = set() for (_a, _b) in _data_type_relation: if _a not in _types_set: _types_list.append(_a) _types_set.add(_a) if _b not in _types_set: _types_list.append(_b) _types_set.add(_b) _byte_order_map = { "ascii": "=", "binary_little_endian": "<", "binary_big_endian": ">", } _byte_order_reverse = {"<": "binary_little_endian", ">": "binary_big_endian"} _native_byte_order = {"little": "<", "big": ">"}[_byteorder] def _lookup_type(type_str): if type_str not in _data_type_reverse: try: type_str = _data_types[type_str] except KeyError: raise ValueError( "field type %r not in %r" % (type_str, _types_list) ) return _data_type_reverse[type_str] def _split_line(line, n): fields = line.split(None, n) if len(fields) == n: fields.append("") assert len(fields) == n + 1 return fields def make2d(array, cols=None, dtype=None): """ Make a 2D array from an array of arrays. The `cols' and `dtype' arguments can be omitted if the array is not empty. """ if (cols is None or dtype is None) and not len(array): raise RuntimeError( "cols and dtype must be specified for empty " "array" ) if cols is None: cols = len(array[0]) if dtype is None: dtype = array[0].dtype return _np.fromiter(array, [("_", dtype, (cols,))], count=len(array))["_"] class PlyParseError(Exception): """ Raised when a PLY file cannot be parsed. The attributes `element', `row', `property', and `message' give additional information. """ def __init__(self, message, element=None, row=None, prop=None): self.message = message self.element = element self.row = row self.prop = prop s = "" if self.element: s += "element %r: " % self.element.name if self.row is not None: s += "row %d: " % self.row if self.prop: s += "property %r: " % self.prop.name s += self.message Exception.__init__(self, s) def __repr__(self): return ( "PlyParseError(%r, element=%r, row=%r, prop=%r)" % self.message, self.element, self.row, self.prop, ) class PlyData(object): """ PLY file header and data. A PlyData instance is created in one of two ways: by the static method PlyData.read (to read a PLY file), or directly from __init__ given a sequence of elements (which can then be written to a PLY file). """ def __init__( self, elements=[], text=False, byte_order="=", comments=[], obj_info=[] ): """ elements: sequence of PlyElement instances. text: whether the resulting PLY file will be text (True) or binary (False). byte_order: '<' for little-endian, '>' for big-endian, or '=' for native. This is only relevant if `text' is False. comments: sequence of strings that will be placed in the header between the 'ply' and 'format ...' lines. obj_info: like comments, but will be placed in the header with "obj_info ..." instead of "comment ...". """ if byte_order == "=" and not text: byte_order = _native_byte_order self.byte_order = byte_order self.text = text self.comments = list(comments) self.obj_info = list(obj_info) self.elements = elements def _get_elements(self): return self._elements def _set_elements(self, elements): self._elements = tuple(elements) self._index() elements = property(_get_elements, _set_elements) def _get_byte_order(self): return self._byte_order def _set_byte_order(self, byte_order): if byte_order not in ["<", ">", "="]: raise ValueError("byte order must be '<', '>', or '='") self._byte_order = byte_order byte_order = property(_get_byte_order, _set_byte_order) def _index(self): self._element_lookup = dict((elt.name, elt) for elt in self._elements) if len(self._element_lookup) != len(self._elements): raise ValueError("two elements with same name") @staticmethod def _parse_header(stream): """ Parse a PLY header from a readable file-like stream. """ lines = [] comments = {"comment": [], "obj_info": []} while True: line = stream.readline().decode("ascii").strip() fields = _split_line(line, 1) if fields[0] == "end_header": break elif fields[0] in comments.keys(): lines.append(fields) else: lines.append(line.split()) a = 0 if lines[a] != ["ply"]: raise PlyParseError("expected 'ply'") a += 1 while lines[a][0] in comments.keys(): comments[lines[a][0]].append(lines[a][1]) a += 1 if lines[a][0] != "format": raise PlyParseError("expected 'format'") if lines[a][2] != "1.0": raise PlyParseError("expected version '1.0'") if len(lines[a]) != 3: raise PlyParseError("too many fields after 'format'") fmt = lines[a][1] if fmt not in _byte_order_map: raise PlyParseError("don't understand format %r" % fmt) byte_order = _byte_order_map[fmt] text = fmt == "ascii" a += 1 while a < len(lines) and lines[a][0] in comments.keys(): comments[lines[a][0]].append(lines[a][1]) a += 1 return PlyData( PlyElement._parse_multi(lines[a:]), text, byte_order, comments["comment"], comments["obj_info"], ) @staticmethod def read(stream): """ Read PLY data from a readable file-like object or filename. """ must_close = False try: if isinstance(stream, str): stream = open(stream, "rb") must_close = True data = PlyData._parse_header(stream) for elt in data: elt._read(stream, data.text, data.byte_order) finally: if must_close: stream.close() return data def write(self, stream): """ Write PLY data to a writeable file-like object or filename. """ must_close = False try: if isinstance(stream, str): stream = open(stream, "wb") must_close = True stream.write(self.header.encode("ascii")) stream.write(b"\r\n") for elt in self: elt._write(stream, self.text, self.byte_order) finally: if must_close: stream.close() @property def header(self): """ Provide PLY-formatted metadata for the instance. """ lines = ["ply"] if self.text: lines.append("format ascii 1.0") else: lines.append( "format " + _byte_order_reverse[self.byte_order] + " 1.0" ) # Some information is lost here, since all comments are placed # between the 'format' line and the first element. for c in self.comments: lines.append("comment " + c) for c in self.obj_info: lines.append("obj_info " + c) lines.extend(elt.header for elt in self.elements) lines.append("end_header") return "\r\n".join(lines) def __iter__(self): return iter(self.elements) def __len__(self): return len(self.elements) def __contains__(self, name): return name in self._element_lookup def __getitem__(self, name): return self._element_lookup[name] def __str__(self): return self.header def __repr__(self): return ( "PlyData(%r, text=%r, byte_order=%r, " "comments=%r, obj_info=%r)" % ( self.elements, self.text, self.byte_order, self.comments, self.obj_info, ) ) class PlyElement(object): """ PLY file element. A client of this library doesn't normally need to instantiate this directly, so the following is only for the sake of documenting the internals. Creating a PlyElement instance is generally done in one of two ways: as a byproduct of PlyData.read (when reading a PLY file) and by PlyElement.describe (before writing a PLY file). """ def __init__(self, name, properties, count, comments=[]): """ This is not part of the public interface. The preferred methods of obtaining PlyElement instances are PlyData.read (to read from a file) and PlyElement.describe (to construct from a numpy array). """ self._name = str(name) self._check_name() self._count = count self._properties = tuple(properties) self._index() self.comments = list(comments) self._have_list = any( isinstance(p, PlyListProperty) for p in self.properties ) @property def count(self): return self._count def _get_data(self): return self._data def _set_data(self, data): self._data = data self._count = len(data) self._check_sanity() data = property(_get_data, _set_data) def _check_sanity(self): for prop in self.properties: if prop.name not in self._data.dtype.fields: raise ValueError("dangling property %r" % prop.name) def _get_properties(self): return self._properties def _set_properties(self, properties): self._properties = tuple(properties) self._check_sanity() self._index() properties = property(_get_properties, _set_properties) def _index(self): self._property_lookup = dict( (prop.name, prop) for prop in self._properties ) if len(self._property_lookup) != len(self._properties): raise ValueError("two properties with same name") def ply_property(self, name): return self._property_lookup[name] @property def name(self): return self._name def _check_name(self): if any(c.isspace() for c in self._name): msg = "element name %r contains spaces" % self._name raise ValueError(msg) def dtype(self, byte_order="="): """ Return the numpy dtype of the in-memory representation of the data. (If there are no list properties, and the PLY format is binary, then this also accurately describes the on-disk representation of the element.) """ return [(prop.name, prop.dtype(byte_order)) for prop in self.properties] @staticmethod def _parse_multi(header_lines): """ Parse a list of PLY element definitions. """ elements = [] while header_lines: (elt, header_lines) = PlyElement._parse_one(header_lines) elements.append(elt) return elements @staticmethod def _parse_one(lines): """ Consume one element definition. The unconsumed input is returned along with a PlyElement instance. """ a = 0 line = lines[a] if line[0] != "element": raise PlyParseError("expected 'element'") if len(line) > 3: raise PlyParseError("too many fields after 'element'") if len(line) < 3: raise PlyParseError("too few fields after 'element'") (name, count) = (line[1], int(line[2])) comments = [] properties = [] while True: a += 1 if a >= len(lines): break if lines[a][0] == "comment": comments.append(lines[a][1]) elif lines[a][0] == "property": properties.append(PlyProperty._parse_one(lines[a])) else: break return (PlyElement(name, properties, count, comments), lines[a:]) @staticmethod def describe(data, name, len_types={}, val_types={}, comments=[]): """ Construct a PlyElement from an array's metadata. len_types and val_types can be given as mappings from list property names to type strings (like 'u1', 'f4', etc., or 'int8', 'float32', etc.). These can be used to define the length and value types of list properties. List property lengths always default to type 'u1' (8-bit unsigned integer), and value types default to 'i4' (32-bit integer). """ if not isinstance(data, _np.ndarray): raise TypeError("only numpy arrays are supported") if len(data.shape) != 1: raise ValueError("only one-dimensional arrays are " "supported") count = len(data) properties = [] descr = data.dtype.descr for t in descr: if not isinstance(t[1], str): raise ValueError("nested records not supported") if not t[0]: raise ValueError("field with empty name") if len(t) != 2 or t[1][1] == "O": # non-scalar field, which corresponds to a list # property in PLY. if t[1][1] == "O": if len(t) != 2: raise ValueError( "non-scalar object fields not " "supported" ) len_str = _data_type_reverse[len_types.get(t[0], "u1")] if t[1][1] == "O": val_type = val_types.get(t[0], "i4") val_str = _lookup_type(val_type) else: val_str = _lookup_type(t[1][1:]) prop = PlyListProperty(t[0], len_str, val_str) else: val_str = _lookup_type(t[1][1:]) prop = PlyProperty(t[0], val_str) properties.append(prop) elt = PlyElement(name, properties, count, comments) elt.data = data return elt def _read(self, stream, text, byte_order): """ Read the actual data from a PLY file. """ if text: self._read_txt(stream) else: if self._have_list: # There are list properties, so a simple load is # impossible. self._read_bin(stream, byte_order) else: # There are no list properties, so loading the data is # much more straightforward. self._data = _np.fromfile( stream, self.dtype(byte_order), self.count ) if len(self._data) < self.count: k = len(self._data) del self._data raise PlyParseError("early end-of-file", self, k) self._check_sanity() def _write(self, stream, text, byte_order): """ Write the data to a PLY file. """ if text: self._write_txt(stream) else: if self._have_list: # There are list properties, so serialization is # slightly complicated. self._write_bin(stream, byte_order) else: # no list properties, so serialization is # straightforward. self.data.astype(self.dtype(byte_order), copy=False).tofile( stream ) def _read_txt(self, stream): """ Load a PLY element from an ASCII-format PLY file. The element may contain list properties. """ self._data = _np.empty(self.count, dtype=self.dtype()) k = 0 for line in _islice(iter(stream.readline, b""), self.count): fields = iter(line.strip().split()) for prop in self.properties: try: self._data[prop.name][k] = prop._from_fields(fields) except StopIteration: raise PlyParseError("early end-of-line", self, k, prop) except ValueError: raise PlyParseError("malformed input", self, k, prop) try: next(fields) except StopIteration: pass else: raise PlyParseError("expected end-of-line", self, k) k += 1 if k < self.count: del self._data raise PlyParseError("early end-of-file", self, k) def _write_txt(self, stream): """ Save a PLY element to an ASCII-format PLY file. The element may contain list properties. """ for rec in self.data: fields = [] for prop in self.properties: fields.extend(prop._to_fields(rec[prop.name])) _np.savetxt(stream, [fields], "%.18g", newline="\r\n") def _read_bin(self, stream, byte_order): """ Load a PLY element from a binary PLY file. The element may contain list properties. """ self._data = _np.empty(self.count, dtype=self.dtype(byte_order)) for k in _range(self.count): for prop in self.properties: try: self._data[prop.name][k] = prop._read_bin( stream, byte_order ) except StopIteration: raise PlyParseError("early end-of-file", self, k, prop) def _write_bin(self, stream, byte_order): """ Save a PLY element to a binary PLY file. The element may contain list properties. """ for rec in self.data: for prop in self.properties: prop._write_bin(rec[prop.name], stream, byte_order) @property def header(self): """ Format this element's metadata as it would appear in a PLY header. """ lines = ["element %s %d" % (self.name, self.count)] # Some information is lost here, since all comments are placed # between the 'element' line and the first property definition. for c in self.comments: lines.append("comment " + c) lines.extend(list(map(str, self.properties))) return "\r\n".join(lines) def __getitem__(self, key): return self.data[key] def __setitem__(self, key, value): self.data[key] = value def __str__(self): return self.header def __repr__(self): return "PlyElement(%r, %r, count=%d, comments=%r)" % ( self.name, self.properties, self.count, self.comments, ) class PlyProperty(object): """ PLY property description. This class is pure metadata; the data itself is contained in PlyElement instances. """ def __init__(self, name, val_dtype): self._name = str(name) self._check_name() self.val_dtype = val_dtype def _get_val_dtype(self): return self._val_dtype def _set_val_dtype(self, val_dtype): self._val_dtype = _data_types[_lookup_type(val_dtype)] val_dtype = property(_get_val_dtype, _set_val_dtype) @property def name(self): return self._name def _check_name(self): if any(c.isspace() for c in self._name): msg = "Error: property name %r contains spaces" % self._name raise RuntimeError(msg) @staticmethod def _parse_one(line): assert line[0] == "property" if line[1] == "list": if len(line) > 5: raise PlyParseError("too many fields after " "'property list'") if len(line) < 5: raise PlyParseError("too few fields after " "'property list'") return PlyListProperty(line[4], line[2], line[3]) else: if len(line) > 3: raise PlyParseError("too many fields after " "'property'") if len(line) < 3: raise PlyParseError("too few fields after " "'property'") return PlyProperty(line[2], line[1]) def dtype(self, byte_order="="): """ Return the numpy dtype description for this property (as a tuple of strings). """ return byte_order + self.val_dtype def _from_fields(self, fields): """ Parse from generator. Raise StopIteration if the property could not be read. """ return _np.dtype(self.dtype()).type(next(fields)) def _to_fields(self, data): """ Return generator over one item. """ yield _np.dtype(self.dtype()).type(data) def _read_bin(self, stream, byte_order): """ Read data from a binary stream. Raise StopIteration if the property could not be read. """ try: return _np.fromfile(stream, self.dtype(byte_order), 1)[0] except IndexError: raise StopIteration def _write_bin(self, data, stream, byte_order): """ Write data to a binary stream. """ _np.dtype(self.dtype(byte_order)).type(data).tofile(stream) def __str__(self): val_str = _data_type_reverse[self.val_dtype] return "property %s %s" % (val_str, self.name) def __repr__(self): return "PlyProperty(%r, %r)" % (self.name, _lookup_type(self.val_dtype)) class PlyListProperty(PlyProperty): """ PLY list property description. """ def __init__(self, name, len_dtype, val_dtype): PlyProperty.__init__(self, name, val_dtype) self.len_dtype = len_dtype def _get_len_dtype(self): return self._len_dtype def _set_len_dtype(self, len_dtype): self._len_dtype = _data_types[_lookup_type(len_dtype)] len_dtype = property(_get_len_dtype, _set_len_dtype) def dtype(self, byte_order="="): """ List properties always have a numpy dtype of "object". """ return "|O" def list_dtype(self, byte_order="="): """ Return the pair (len_dtype, val_dtype) (both numpy-friendly strings). """ return (byte_order + self.len_dtype, byte_order + self.val_dtype) def _from_fields(self, fields): (len_t, val_t) = self.list_dtype() n = int(_np.dtype(len_t).type(next(fields))) data = _np.loadtxt(list(_islice(fields, n)), val_t, ndmin=1) if len(data) < n: raise StopIteration return data def _to_fields(self, data): """ Return generator over the (numerical) PLY representation of the list data (length followed by actual data). """ (len_t, val_t) = self.list_dtype() data = _np.asarray(data, dtype=val_t).ravel() yield _np.dtype(len_t).type(data.size) for x in data: yield x def _read_bin(self, stream, byte_order): (len_t, val_t) = self.list_dtype(byte_order) try: n = _np.fromfile(stream, len_t, 1)[0] except IndexError: raise StopIteration data = _np.fromfile(stream, val_t, n) if len(data) < n: raise StopIteration return data def _write_bin(self, data, stream, byte_order): """ Write data to a binary stream. """ (len_t, val_t) = self.list_dtype(byte_order) data = _np.asarray(data, dtype=val_t).ravel() _np.array(data.size, dtype=len_t).tofile(stream) data.tofile(stream) def __str__(self): len_str = _data_type_reverse[self.len_dtype] val_str = _data_type_reverse[self.val_dtype] return "property list %s %s %s" % (len_str, val_str, self.name) def __repr__(self): return "PlyListProperty(%r, %r, %r)" % ( self.name, _lookup_type(self.len_dtype), _lookup_type(self.val_dtype), ) colmap-3.10/scripts/python/read_write_dense.py000077500000000000000000000120161464745566500216260ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import argparse import numpy as np import os import struct def read_array(path): with open(path, "rb") as fid: width, height, channels = np.genfromtxt( fid, delimiter="&", max_rows=1, usecols=(0, 1, 2), dtype=int ) fid.seek(0) num_delimiter = 0 byte = fid.read(1) while True: if byte == b"&": num_delimiter += 1 if num_delimiter >= 3: break byte = fid.read(1) array = np.fromfile(fid, np.float32) array = array.reshape((width, height, channels), order="F") return np.transpose(array, (1, 0, 2)).squeeze() def write_array(array, path): """ see: src/mvs/mat.h void Mat::Write(const std::string& path) """ assert array.dtype == np.float32 if len(array.shape) == 2: height, width = array.shape channels = 1 elif len(array.shape) == 3: height, width, channels = array.shape else: assert False with open(path, "w") as fid: fid.write(str(width) + "&" + str(height) + "&" + str(channels) + "&") with open(path, "ab") as fid: if len(array.shape) == 2: array_trans = np.transpose(array, (1, 0)) elif len(array.shape) == 3: array_trans = np.transpose(array, (1, 0, 2)) else: assert False data_1d = array_trans.reshape(-1, order="F") data_list = data_1d.tolist() endian_character = "<" format_char_sequence = "".join(["f"] * len(data_list)) byte_data = struct.pack( endian_character + format_char_sequence, *data_list ) fid.write(byte_data) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument( "-d", "--depth_map", help="path to depth map", type=str, required=True ) parser.add_argument( "-n", "--normal_map", help="path to normal map", type=str, required=True ) parser.add_argument( "--min_depth_percentile", help="minimum visualization depth percentile", type=float, default=5, ) parser.add_argument( "--max_depth_percentile", help="maximum visualization depth percentile", type=float, default=95, ) args = parser.parse_args() return args def main(): args = parse_args() if args.min_depth_percentile > args.max_depth_percentile: raise ValueError( "min_depth_percentile should be less than or equal " "to the max_depth_percentile." ) # Read depth and normal maps corresponding to the same image. if not os.path.exists(args.depth_map): raise FileNotFoundError("File not found: {}".format(args.depth_map)) if not os.path.exists(args.normal_map): raise FileNotFoundError("File not found: {}".format(args.normal_map)) depth_map = read_array(args.depth_map) normal_map = read_array(args.normal_map) min_depth, max_depth = np.percentile( depth_map, [args.min_depth_percentile, args.max_depth_percentile] ) depth_map[depth_map < min_depth] = min_depth depth_map[depth_map > max_depth] = max_depth import pylab as plt # Visualize the depth map. plt.figure() plt.imshow(depth_map) plt.title("depth map") # Visualize the normal map. plt.figure() plt.imshow(normal_map) plt.title("normal map") plt.show() if __name__ == "__main__": main() colmap-3.10/scripts/python/read_write_fused_vis.py000077500000000000000000000121211464745566500225140ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import collections import numpy as np import pandas as pd from pyntcloud import PyntCloud from read_write_model import read_next_bytes, write_next_bytes MeshPoint = collections.namedtuple( "MeshingPoint", ["position", "color", "normal", "num_visible_images", "visible_image_idxs"], ) def read_fused(path_to_fused_ply, path_to_fused_ply_vis): """ see: src/mvs/meshing.cc void ReadDenseReconstruction(const std::string& path """ assert os.path.isfile(path_to_fused_ply) assert os.path.isfile(path_to_fused_ply_vis) point_cloud = PyntCloud.from_file(path_to_fused_ply) xyz_arr = point_cloud.points.loc[:, ["x", "y", "z"]].to_numpy() normal_arr = point_cloud.points.loc[:, ["nx", "ny", "nz"]].to_numpy() color_arr = point_cloud.points.loc[:, ["red", "green", "blue"]].to_numpy() with open(path_to_fused_ply_vis, "rb") as fid: num_points = read_next_bytes(fid, 8, "Q")[0] mesh_points = [0] * num_points for i in range(num_points): num_visible_images = read_next_bytes(fid, 4, "I")[0] visible_image_idxs = read_next_bytes( fid, num_bytes=4 * num_visible_images, format_char_sequence="I" * num_visible_images, ) visible_image_idxs = np.array(tuple(map(int, visible_image_idxs))) mesh_point = MeshPoint( position=xyz_arr[i], color=color_arr[i], normal=normal_arr[i], num_visible_images=num_visible_images, visible_image_idxs=visible_image_idxs, ) mesh_points[i] = mesh_point return mesh_points def write_fused_ply(mesh_points, path_to_fused_ply): columns = ["x", "y", "z", "nx", "ny", "nz", "red", "green", "blue"] points_data_frame = pd.DataFrame( np.zeros((len(mesh_points), len(columns))), columns=columns ) positions = np.asarray([point.position for point in mesh_points]) normals = np.asarray([point.normal for point in mesh_points]) colors = np.asarray([point.color for point in mesh_points]) points_data_frame.loc[:, ["x", "y", "z"]] = positions points_data_frame.loc[:, ["nx", "ny", "nz"]] = normals points_data_frame.loc[:, ["red", "green", "blue"]] = colors points_data_frame = points_data_frame.astype( { "x": positions.dtype, "y": positions.dtype, "z": positions.dtype, "red": colors.dtype, "green": colors.dtype, "blue": colors.dtype, "nx": normals.dtype, "ny": normals.dtype, "nz": normals.dtype, } ) point_cloud = PyntCloud(points_data_frame) point_cloud.to_file(path_to_fused_ply) def write_fused_ply_vis(mesh_points, path_to_fused_ply_vis): """ see: src/mvs/fusion.cc void WritePointsVisibility(const std::string& path, const std::vector>& points_visibility) """ with open(path_to_fused_ply_vis, "wb") as fid: write_next_bytes(fid, len(mesh_points), "Q") for point in mesh_points: write_next_bytes(fid, point.num_visible_images, "I") format_char_sequence = "I" * point.num_visible_images write_next_bytes( fid, [*point.visible_image_idxs], format_char_sequence ) def write_fused(points, path_to_fused_ply, path_to_fused_ply_vis): write_fused_ply(points, path_to_fused_ply) write_fused_ply_vis(points, path_to_fused_ply_vis) colmap-3.10/scripts/python/read_write_model.py000077500000000000000000000540131464745566500216330ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import collections import numpy as np import struct import argparse CameraModel = collections.namedtuple( "CameraModel", ["model_id", "model_name", "num_params"] ) Camera = collections.namedtuple( "Camera", ["id", "model", "width", "height", "params"] ) BaseImage = collections.namedtuple( "Image", ["id", "qvec", "tvec", "camera_id", "name", "xys", "point3D_ids"] ) Point3D = collections.namedtuple( "Point3D", ["id", "xyz", "rgb", "error", "image_ids", "point2D_idxs"] ) class Image(BaseImage): def qvec2rotmat(self): return qvec2rotmat(self.qvec) CAMERA_MODELS = { CameraModel(model_id=0, model_name="SIMPLE_PINHOLE", num_params=3), CameraModel(model_id=1, model_name="PINHOLE", num_params=4), CameraModel(model_id=2, model_name="SIMPLE_RADIAL", num_params=4), CameraModel(model_id=3, model_name="RADIAL", num_params=5), CameraModel(model_id=4, model_name="OPENCV", num_params=8), CameraModel(model_id=5, model_name="OPENCV_FISHEYE", num_params=8), CameraModel(model_id=6, model_name="FULL_OPENCV", num_params=12), CameraModel(model_id=7, model_name="FOV", num_params=5), CameraModel(model_id=8, model_name="SIMPLE_RADIAL_FISHEYE", num_params=4), CameraModel(model_id=9, model_name="RADIAL_FISHEYE", num_params=5), CameraModel(model_id=10, model_name="THIN_PRISM_FISHEYE", num_params=12), } CAMERA_MODEL_IDS = dict( [(camera_model.model_id, camera_model) for camera_model in CAMERA_MODELS] ) CAMERA_MODEL_NAMES = dict( [(camera_model.model_name, camera_model) for camera_model in CAMERA_MODELS] ) def read_next_bytes(fid, num_bytes, format_char_sequence, endian_character="<"): """Read and unpack the next bytes from a binary file. :param fid: :param num_bytes: Sum of combination of {2, 4, 8}, e.g. 2, 6, 16, 30, etc. :param format_char_sequence: List of {c, e, f, d, h, H, i, I, l, L, q, Q}. :param endian_character: Any of {@, =, <, >, !} :return: Tuple of read and unpacked values. """ data = fid.read(num_bytes) return struct.unpack(endian_character + format_char_sequence, data) def write_next_bytes(fid, data, format_char_sequence, endian_character="<"): """pack and write to a binary file. :param fid: :param data: data to send, if multiple elements are sent at the same time, they should be encapsuled either in a list or a tuple :param format_char_sequence: List of {c, e, f, d, h, H, i, I, l, L, q, Q}. should be the same length as the data list or tuple :param endian_character: Any of {@, =, <, >, !} """ if isinstance(data, (list, tuple)): bytes = struct.pack(endian_character + format_char_sequence, *data) else: bytes = struct.pack(endian_character + format_char_sequence, data) fid.write(bytes) def read_cameras_text(path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::WriteCamerasText(const std::string& path) void Reconstruction::ReadCamerasText(const std::string& path) """ cameras = {} with open(path, "r") as fid: while True: line = fid.readline() if not line: break line = line.strip() if len(line) > 0 and line[0] != "#": elems = line.split() camera_id = int(elems[0]) model = elems[1] width = int(elems[2]) height = int(elems[3]) params = np.array(tuple(map(float, elems[4:]))) cameras[camera_id] = Camera( id=camera_id, model=model, width=width, height=height, params=params, ) return cameras def read_cameras_binary(path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::WriteCamerasBinary(const std::string& path) void Reconstruction::ReadCamerasBinary(const std::string& path) """ cameras = {} with open(path_to_model_file, "rb") as fid: num_cameras = read_next_bytes(fid, 8, "Q")[0] for _ in range(num_cameras): camera_properties = read_next_bytes( fid, num_bytes=24, format_char_sequence="iiQQ" ) camera_id = camera_properties[0] model_id = camera_properties[1] model_name = CAMERA_MODEL_IDS[camera_properties[1]].model_name width = camera_properties[2] height = camera_properties[3] num_params = CAMERA_MODEL_IDS[model_id].num_params params = read_next_bytes( fid, num_bytes=8 * num_params, format_char_sequence="d" * num_params, ) cameras[camera_id] = Camera( id=camera_id, model=model_name, width=width, height=height, params=np.array(params), ) assert len(cameras) == num_cameras return cameras def write_cameras_text(cameras, path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::WriteCamerasText(const std::string& path) void Reconstruction::ReadCamerasText(const std::string& path) """ HEADER = ( "# Camera list with one line of data per camera:\n" + "# CAMERA_ID, MODEL, WIDTH, HEIGHT, PARAMS[]\n" + "# Number of cameras: {}\n".format(len(cameras)) ) with open(path, "w") as fid: fid.write(HEADER) for _, cam in cameras.items(): to_write = [cam.id, cam.model, cam.width, cam.height, *cam.params] line = " ".join([str(elem) for elem in to_write]) fid.write(line + "\n") def write_cameras_binary(cameras, path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::WriteCamerasBinary(const std::string& path) void Reconstruction::ReadCamerasBinary(const std::string& path) """ with open(path_to_model_file, "wb") as fid: write_next_bytes(fid, len(cameras), "Q") for _, cam in cameras.items(): model_id = CAMERA_MODEL_NAMES[cam.model].model_id camera_properties = [cam.id, model_id, cam.width, cam.height] write_next_bytes(fid, camera_properties, "iiQQ") for p in cam.params: write_next_bytes(fid, float(p), "d") return cameras def read_images_text(path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadImagesText(const std::string& path) void Reconstruction::WriteImagesText(const std::string& path) """ images = {} with open(path, "r") as fid: while True: line = fid.readline() if not line: break line = line.strip() if len(line) > 0 and line[0] != "#": elems = line.split() image_id = int(elems[0]) qvec = np.array(tuple(map(float, elems[1:5]))) tvec = np.array(tuple(map(float, elems[5:8]))) camera_id = int(elems[8]) image_name = elems[9] elems = fid.readline().split() xys = np.column_stack( [ tuple(map(float, elems[0::3])), tuple(map(float, elems[1::3])), ] ) point3D_ids = np.array(tuple(map(int, elems[2::3]))) images[image_id] = Image( id=image_id, qvec=qvec, tvec=tvec, camera_id=camera_id, name=image_name, xys=xys, point3D_ids=point3D_ids, ) return images def read_images_binary(path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadImagesBinary(const std::string& path) void Reconstruction::WriteImagesBinary(const std::string& path) """ images = {} with open(path_to_model_file, "rb") as fid: num_reg_images = read_next_bytes(fid, 8, "Q")[0] for _ in range(num_reg_images): binary_image_properties = read_next_bytes( fid, num_bytes=64, format_char_sequence="idddddddi" ) image_id = binary_image_properties[0] qvec = np.array(binary_image_properties[1:5]) tvec = np.array(binary_image_properties[5:8]) camera_id = binary_image_properties[8] binary_image_name = b"" current_char = read_next_bytes(fid, 1, "c")[0] while current_char != b"\x00": # look for the ASCII 0 entry binary_image_name += current_char current_char = read_next_bytes(fid, 1, "c")[0] image_name = binary_image_name.decode("utf-8") num_points2D = read_next_bytes( fid, num_bytes=8, format_char_sequence="Q" )[0] x_y_id_s = read_next_bytes( fid, num_bytes=24 * num_points2D, format_char_sequence="ddq" * num_points2D, ) xys = np.column_stack( [ tuple(map(float, x_y_id_s[0::3])), tuple(map(float, x_y_id_s[1::3])), ] ) point3D_ids = np.array(tuple(map(int, x_y_id_s[2::3]))) images[image_id] = Image( id=image_id, qvec=qvec, tvec=tvec, camera_id=camera_id, name=image_name, xys=xys, point3D_ids=point3D_ids, ) return images def write_images_text(images, path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadImagesText(const std::string& path) void Reconstruction::WriteImagesText(const std::string& path) """ if len(images) == 0: mean_observations = 0 else: mean_observations = sum( (len(img.point3D_ids) for _, img in images.items()) ) / len(images) HEADER = ( "# Image list with two lines of data per image:\n" + "# IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, NAME\n" + "# POINTS2D[] as (X, Y, POINT3D_ID)\n" + "# Number of images: {}, mean observations per image: {}\n".format( len(images), mean_observations ) ) with open(path, "w") as fid: fid.write(HEADER) for _, img in images.items(): image_header = [ img.id, *img.qvec, *img.tvec, img.camera_id, img.name, ] first_line = " ".join(map(str, image_header)) fid.write(first_line + "\n") points_strings = [] for xy, point3D_id in zip(img.xys, img.point3D_ids): points_strings.append(" ".join(map(str, [*xy, point3D_id]))) fid.write(" ".join(points_strings) + "\n") def write_images_binary(images, path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadImagesBinary(const std::string& path) void Reconstruction::WriteImagesBinary(const std::string& path) """ with open(path_to_model_file, "wb") as fid: write_next_bytes(fid, len(images), "Q") for _, img in images.items(): write_next_bytes(fid, img.id, "i") write_next_bytes(fid, img.qvec.tolist(), "dddd") write_next_bytes(fid, img.tvec.tolist(), "ddd") write_next_bytes(fid, img.camera_id, "i") for char in img.name: write_next_bytes(fid, char.encode("utf-8"), "c") write_next_bytes(fid, b"\x00", "c") write_next_bytes(fid, len(img.point3D_ids), "Q") for xy, p3d_id in zip(img.xys, img.point3D_ids): write_next_bytes(fid, [*xy, p3d_id], "ddq") def read_points3D_text(path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadPoints3DText(const std::string& path) void Reconstruction::WritePoints3DText(const std::string& path) """ points3D = {} with open(path, "r") as fid: while True: line = fid.readline() if not line: break line = line.strip() if len(line) > 0 and line[0] != "#": elems = line.split() point3D_id = int(elems[0]) xyz = np.array(tuple(map(float, elems[1:4]))) rgb = np.array(tuple(map(int, elems[4:7]))) error = float(elems[7]) image_ids = np.array(tuple(map(int, elems[8::2]))) point2D_idxs = np.array(tuple(map(int, elems[9::2]))) points3D[point3D_id] = Point3D( id=point3D_id, xyz=xyz, rgb=rgb, error=error, image_ids=image_ids, point2D_idxs=point2D_idxs, ) return points3D def read_points3D_binary(path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadPoints3DBinary(const std::string& path) void Reconstruction::WritePoints3DBinary(const std::string& path) """ points3D = {} with open(path_to_model_file, "rb") as fid: num_points = read_next_bytes(fid, 8, "Q")[0] for _ in range(num_points): binary_point_line_properties = read_next_bytes( fid, num_bytes=43, format_char_sequence="QdddBBBd" ) point3D_id = binary_point_line_properties[0] xyz = np.array(binary_point_line_properties[1:4]) rgb = np.array(binary_point_line_properties[4:7]) error = np.array(binary_point_line_properties[7]) track_length = read_next_bytes( fid, num_bytes=8, format_char_sequence="Q" )[0] track_elems = read_next_bytes( fid, num_bytes=8 * track_length, format_char_sequence="ii" * track_length, ) image_ids = np.array(tuple(map(int, track_elems[0::2]))) point2D_idxs = np.array(tuple(map(int, track_elems[1::2]))) points3D[point3D_id] = Point3D( id=point3D_id, xyz=xyz, rgb=rgb, error=error, image_ids=image_ids, point2D_idxs=point2D_idxs, ) return points3D def write_points3D_text(points3D, path): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadPoints3DText(const std::string& path) void Reconstruction::WritePoints3DText(const std::string& path) """ if len(points3D) == 0: mean_track_length = 0 else: mean_track_length = sum( (len(pt.image_ids) for _, pt in points3D.items()) ) / len(points3D) HEADER = ( "# 3D point list with one line of data per point:\n" + "# POINT3D_ID, X, Y, Z, R, G, B, ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX)\n" + "# Number of points: {}, mean track length: {}\n".format( len(points3D), mean_track_length ) ) with open(path, "w") as fid: fid.write(HEADER) for _, pt in points3D.items(): point_header = [pt.id, *pt.xyz, *pt.rgb, pt.error] fid.write(" ".join(map(str, point_header)) + " ") track_strings = [] for image_id, point2D in zip(pt.image_ids, pt.point2D_idxs): track_strings.append(" ".join(map(str, [image_id, point2D]))) fid.write(" ".join(track_strings) + "\n") def write_points3D_binary(points3D, path_to_model_file): """ see: src/colmap/scene/reconstruction.cc void Reconstruction::ReadPoints3DBinary(const std::string& path) void Reconstruction::WritePoints3DBinary(const std::string& path) """ with open(path_to_model_file, "wb") as fid: write_next_bytes(fid, len(points3D), "Q") for _, pt in points3D.items(): write_next_bytes(fid, pt.id, "Q") write_next_bytes(fid, pt.xyz.tolist(), "ddd") write_next_bytes(fid, pt.rgb.tolist(), "BBB") write_next_bytes(fid, pt.error, "d") track_length = pt.image_ids.shape[0] write_next_bytes(fid, track_length, "Q") for image_id, point2D_id in zip(pt.image_ids, pt.point2D_idxs): write_next_bytes(fid, [image_id, point2D_id], "ii") def detect_model_format(path, ext): if ( os.path.isfile(os.path.join(path, "cameras" + ext)) and os.path.isfile(os.path.join(path, "images" + ext)) and os.path.isfile(os.path.join(path, "points3D" + ext)) ): print("Detected model format: '" + ext + "'") return True return False def read_model(path, ext=""): # try to detect the extension automatically if ext == "": if detect_model_format(path, ".bin"): ext = ".bin" elif detect_model_format(path, ".txt"): ext = ".txt" else: print("Provide model format: '.bin' or '.txt'") return if ext == ".txt": cameras = read_cameras_text(os.path.join(path, "cameras" + ext)) images = read_images_text(os.path.join(path, "images" + ext)) points3D = read_points3D_text(os.path.join(path, "points3D") + ext) else: cameras = read_cameras_binary(os.path.join(path, "cameras" + ext)) images = read_images_binary(os.path.join(path, "images" + ext)) points3D = read_points3D_binary(os.path.join(path, "points3D") + ext) return cameras, images, points3D def write_model(cameras, images, points3D, path, ext=".bin"): if ext == ".txt": write_cameras_text(cameras, os.path.join(path, "cameras" + ext)) write_images_text(images, os.path.join(path, "images" + ext)) write_points3D_text(points3D, os.path.join(path, "points3D") + ext) else: write_cameras_binary(cameras, os.path.join(path, "cameras" + ext)) write_images_binary(images, os.path.join(path, "images" + ext)) write_points3D_binary(points3D, os.path.join(path, "points3D") + ext) return cameras, images, points3D def qvec2rotmat(qvec): return np.array( [ [ 1 - 2 * qvec[2] ** 2 - 2 * qvec[3] ** 2, 2 * qvec[1] * qvec[2] - 2 * qvec[0] * qvec[3], 2 * qvec[3] * qvec[1] + 2 * qvec[0] * qvec[2], ], [ 2 * qvec[1] * qvec[2] + 2 * qvec[0] * qvec[3], 1 - 2 * qvec[1] ** 2 - 2 * qvec[3] ** 2, 2 * qvec[2] * qvec[3] - 2 * qvec[0] * qvec[1], ], [ 2 * qvec[3] * qvec[1] - 2 * qvec[0] * qvec[2], 2 * qvec[2] * qvec[3] + 2 * qvec[0] * qvec[1], 1 - 2 * qvec[1] ** 2 - 2 * qvec[2] ** 2, ], ] ) def rotmat2qvec(R): Rxx, Ryx, Rzx, Rxy, Ryy, Rzy, Rxz, Ryz, Rzz = R.flat K = ( np.array( [ [Rxx - Ryy - Rzz, 0, 0, 0], [Ryx + Rxy, Ryy - Rxx - Rzz, 0, 0], [Rzx + Rxz, Rzy + Ryz, Rzz - Rxx - Ryy, 0], [Ryz - Rzy, Rzx - Rxz, Rxy - Ryx, Rxx + Ryy + Rzz], ] ) / 3.0 ) eigvals, eigvecs = np.linalg.eigh(K) qvec = eigvecs[[3, 0, 1, 2], np.argmax(eigvals)] if qvec[0] < 0: qvec *= -1 return qvec def main(): parser = argparse.ArgumentParser( description="Read and write COLMAP binary and text models" ) parser.add_argument("--input_model", help="path to input model folder") parser.add_argument( "--input_format", choices=[".bin", ".txt"], help="input model format", default="", ) parser.add_argument("--output_model", help="path to output model folder") parser.add_argument( "--output_format", choices=[".bin", ".txt"], help="output model format", default=".txt", ) args = parser.parse_args() cameras, images, points3D = read_model( path=args.input_model, ext=args.input_format ) print("num_cameras:", len(cameras)) print("num_images:", len(images)) print("num_points3D:", len(points3D)) if args.output_model is not None: write_model( cameras, images, points3D, path=args.output_model, ext=args.output_format, ) if __name__ == "__main__": main() colmap-3.10/scripts/python/test_read_write_dense.py000077500000000000000000000046211464745566500226700ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import numpy as np from read_write_dense import read_array, write_array def main(): import sys if len(sys.argv) != 3: print( "Usage: python test_read_write_dense.py " "path/to/dense/input.bin path/to/dense/output.bin" ) return print( "Checking consistency of reading and writing dense arrays " + "(depth maps / normal maps) ..." ) path_to_dense_input = sys.argv[1] path_to_dense_output = sys.argv[2] dense_input = read_array(path_to_dense_input) print("Input shape: " + str(dense_input.shape)) write_array(dense_input, path_to_dense_output) dense_output = read_array(path_to_dense_output) np.testing.assert_array_equal(dense_input, dense_output) print("... dense arrays are equal.") if __name__ == "__main__": main() colmap-3.10/scripts/python/test_read_write_fused_vis.py000077500000000000000000000052151464745566500235610ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import filecmp from read_write_fused_vis import read_fused, write_fused def main(): import sys if len(sys.argv) != 5: print( "Usage: python test_read_write_fused_vis.py " "path/to/input_fused.ply path/to/input_fused.ply.vis " "path/to/output_fused.ply path/to/output_fused.ply.vis" ) return print( "Checking consistency of reading and writing fused.ply and fused.ply.vis files ..." ) path_to_fused_ply_input = sys.argv[1] path_to_fused_ply_vis_input = sys.argv[2] path_to_fused_ply_output = sys.argv[3] path_to_fused_ply_vis_output = sys.argv[4] mesh_points = read_fused( path_to_fused_ply_input, path_to_fused_ply_vis_input ) write_fused( mesh_points, path_to_fused_ply_output, path_to_fused_ply_vis_output ) assert filecmp.cmp(path_to_fused_ply_input, path_to_fused_ply_output) assert filecmp.cmp( path_to_fused_ply_vis_input, path_to_fused_ply_vis_output ) print("... Results are equal.") if __name__ == "__main__": main() colmap-3.10/scripts/python/test_read_write_model.py000077500000000000000000000112321464745566500226660ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import numpy as np from read_write_model import read_model, write_model from tempfile import mkdtemp def compare_cameras(cameras1, cameras2): assert len(cameras1) == len(cameras2) for camera_id1 in cameras1: camera1 = cameras1[camera_id1] camera2 = cameras2[camera_id1] assert camera1.id == camera2.id assert camera1.width == camera2.width assert camera1.height == camera2.height assert np.allclose(camera1.params, camera2.params) def compare_images(images1, images2): assert len(images1) == len(images2) for image_id1 in images1: image1 = images1[image_id1] image2 = images2[image_id1] assert image1.id == image2.id assert np.allclose(image1.qvec, image2.qvec) assert np.allclose(image1.tvec, image2.tvec) assert image1.camera_id == image2.camera_id assert image1.name == image2.name assert np.allclose(image1.xys, image2.xys) assert np.array_equal(image1.point3D_ids, image2.point3D_ids) def compare_points(points3D1, points3D2): for point3D_id1 in points3D1: point3D1 = points3D1[point3D_id1] point3D2 = points3D2[point3D_id1] assert point3D1.id == point3D2.id assert np.allclose(point3D1.xyz, point3D2.xyz) assert np.array_equal(point3D1.rgb, point3D2.rgb) assert np.allclose(point3D1.error, point3D2.error) assert np.array_equal(point3D1.image_ids, point3D2.image_ids) assert np.array_equal(point3D1.point2D_idxs, point3D2.point2D_idxs) def main(): import sys if len(sys.argv) != 3: print( "Usage: python read_model.py " "path/to/model/folder/txt path/to/model/folder/bin" ) return print("Comparing text and binary models ...") path_to_model_txt_folder = sys.argv[1] path_to_model_bin_folder = sys.argv[2] cameras_txt, images_txt, points3D_txt = read_model( path_to_model_txt_folder, ext=".txt" ) cameras_bin, images_bin, points3D_bin = read_model( path_to_model_bin_folder, ext=".bin" ) compare_cameras(cameras_txt, cameras_bin) compare_images(images_txt, images_bin) compare_points(points3D_txt, points3D_bin) print("... text and binary models are equal.") print("Saving text model and reloading it ...") tmpdir = mkdtemp() write_model(cameras_bin, images_bin, points3D_bin, tmpdir, ext=".txt") cameras_txt, images_txt, points3D_txt = read_model(tmpdir, ext=".txt") compare_cameras(cameras_txt, cameras_bin) compare_images(images_txt, images_bin) compare_points(points3D_txt, points3D_bin) print("... saved text and loaded models are equal.") print("Saving binary model and reloading it ...") write_model(cameras_bin, images_bin, points3D_bin, tmpdir, ext=".bin") cameras_bin, images_bin, points3D_bin = read_model(tmpdir, ext=".bin") compare_cameras(cameras_txt, cameras_bin) compare_images(images_txt, images_bin) compare_points(points3D_txt, points3D_bin) print("... saved binary and loaded models are equal.") if __name__ == "__main__": main() colmap-3.10/scripts/python/visualize_model.py000077500000000000000000000160301464745566500215160ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import argparse import numpy as np import open3d from read_write_model import read_model, write_model, qvec2rotmat, rotmat2qvec class Model: def __init__(self): self.cameras = [] self.images = [] self.points3D = [] self.__vis = None def read_model(self, path, ext=""): self.cameras, self.images, self.points3D = read_model(path, ext) def add_points(self, min_track_len=3, remove_statistical_outlier=True): pcd = open3d.geometry.PointCloud() xyz = [] rgb = [] for point3D in self.points3D.values(): track_len = len(point3D.point2D_idxs) if track_len < min_track_len: continue xyz.append(point3D.xyz) rgb.append(point3D.rgb / 255) pcd.points = open3d.utility.Vector3dVector(xyz) pcd.colors = open3d.utility.Vector3dVector(rgb) # remove obvious outliers if remove_statistical_outlier: [pcd, _] = pcd.remove_statistical_outlier( nb_neighbors=20, std_ratio=2.0 ) # open3d.visualization.draw_geometries([pcd]) self.__vis.add_geometry(pcd) self.__vis.poll_events() self.__vis.update_renderer() def add_cameras(self, scale=1): frames = [] for img in self.images.values(): # rotation R = qvec2rotmat(img.qvec) # translation t = img.tvec # invert t = -R.T @ t R = R.T # intrinsics cam = self.cameras[img.camera_id] if cam.model in ("SIMPLE_PINHOLE", "SIMPLE_RADIAL", "RADIAL"): fx = fy = cam.params[0] cx = cam.params[1] cy = cam.params[2] elif cam.model in ( "PINHOLE", "OPENCV", "OPENCV_FISHEYE", "FULL_OPENCV", ): fx = cam.params[0] fy = cam.params[1] cx = cam.params[2] cy = cam.params[3] else: raise Exception("Camera model not supported") # intrinsics K = np.identity(3) K[0, 0] = fx K[1, 1] = fy K[0, 2] = cx K[1, 2] = cy # create axis, plane and pyramed geometries that will be drawn cam_model = draw_camera(K, R, t, cam.width, cam.height, scale) frames.extend(cam_model) # add geometries to visualizer for i in frames: self.__vis.add_geometry(i) def create_window(self): self.__vis = open3d.visualization.Visualizer() self.__vis.create_window() def show(self): self.__vis.poll_events() self.__vis.update_renderer() self.__vis.run() self.__vis.destroy_window() def draw_camera(K, R, t, w, h, scale=1, color=[0.8, 0.2, 0.8]): """Create axis, plane and pyramed geometries in Open3D format. :param K: calibration matrix (camera intrinsics) :param R: rotation matrix :param t: translation :param w: image width :param h: image height :param scale: camera model scale :param color: color of the image plane and pyramid lines :return: camera model geometries (axis, plane and pyramid) """ # intrinsics K = K.copy() / scale Kinv = np.linalg.inv(K) # 4x4 transformation T = np.column_stack((R, t)) T = np.vstack((T, (0, 0, 0, 1))) # axis axis = open3d.geometry.TriangleMesh.create_coordinate_frame( size=0.5 * scale ) axis.transform(T) # points in pixel points_pixel = [ [0, 0, 0], [0, 0, 1], [w, 0, 1], [0, h, 1], [w, h, 1], ] # pixel to camera coordinate system points = [Kinv @ p for p in points_pixel] # image plane width = abs(points[1][0]) + abs(points[3][0]) height = abs(points[1][1]) + abs(points[3][1]) plane = open3d.geometry.TriangleMesh.create_box(width, height, depth=1e-6) plane.paint_uniform_color(color) plane.translate([points[1][0], points[1][1], scale]) plane.transform(T) # pyramid points_in_world = [(R @ p + t) for p in points] lines = [ [0, 1], [0, 2], [0, 3], [0, 4], ] colors = [color for i in range(len(lines))] line_set = open3d.geometry.LineSet( points=open3d.utility.Vector3dVector(points_in_world), lines=open3d.utility.Vector2iVector(lines), ) line_set.colors = open3d.utility.Vector3dVector(colors) # return as list in Open3D format return [axis, plane, line_set] def parse_args(): parser = argparse.ArgumentParser( description="Visualize COLMAP binary and text models" ) parser.add_argument( "--input_model", required=True, help="path to input model folder" ) parser.add_argument( "--input_format", choices=[".bin", ".txt"], help="input model format", default="", ) args = parser.parse_args() return args def main(): args = parse_args() # read COLMAP model model = Model() model.read_model(args.input_model, ext=args.input_format) print("num_cameras:", len(model.cameras)) print("num_images:", len(model.images)) print("num_points3D:", len(model.points3D)) # display using Open3D visualization tools model.create_window() model.add_points() model.add_cameras(scale=0.25) model.show() if __name__ == "__main__": main() colmap-3.10/scripts/shell/000077500000000000000000000000001464745566500155345ustar00rootroot00000000000000colmap-3.10/scripts/shell/build_mac_app.sh000077500000000000000000000064231464745566500206570ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This script creates a deployable package of COLMAP for Mac OS X. BASE_PATH=$(dirname $1) echo "Creating bundle directory" mkdir -p "$BASE_PATH/COLMAP.app/Contents/MacOS" echo "Copying binary" cp "$BASE_PATH/colmap" "$BASE_PATH/COLMAP.app/Contents/MacOS/colmap" echo "Writing Info.plist" cat <"$BASE_PATH/COLMAP.app/Contents/Info.plist" CFBundlePackageType APPL CFBundleExecutable colmap CFBundleIdentifier COLMAP CFBundleName COLMAP CFBundleDisplayName COLMAP NSHighResolutionCapable NSAppSleepDisabled EOM install_name_tool -change @rpath/libtbb.dylib /usr/local/lib/libtbb.dylib $BASE_PATH/COLMAP.app/Contents/MacOS/COLMAP install_name_tool -change @rpath/libtbbmalloc.dylib /usr/local/lib/libtbbmalloc.dylib $BASE_PATH/COLMAP.app/Contents/MacOS/COLMAP echo "Linking dynamic libraries" /usr/local/opt/qt5/bin/macdeployqt "$BASE_PATH/COLMAP.app" echo "Wrapping binary" cat <"$BASE_PATH/COLMAP.app/Contents/MacOS/colmap_gui.sh" #!/bin/bash script_path="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)" \$script_path/colmap gui EOM chmod +x $BASE_PATH/COLMAP.app/Contents/MacOS/colmap_gui.sh sed -i '' 's#colmap#colmap_gui.sh#g' $BASE_PATH/COLMAP.app/Contents/Info.plist echo "Compressing application" cd "$BASE_PATH" zip -r "COLMAP-mac.zip" "COLMAP.app" colmap-3.10/scripts/shell/colmap.bat000077500000000000000000000035331464745566500175060ustar00rootroot00000000000000@echo off rem Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. rem All rights reserved. rem rem Redistribution and use in source and binary forms, with or without rem modification, are permitted provided that the following conditions are met: rem rem * Redistributions of source code must retain the above copyright rem notice, this list of conditions and the following disclaimer. rem rem * Redistributions in binary form must reproduce the above copyright rem notice, this list of conditions and the following disclaimer in the rem documentation and/or other materials provided with the distribution. rem rem * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of rem its contributors may be used to endorse or promote products derived rem from this software without specific prior written permission. rem rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" rem AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE rem IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE rem ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE rem LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR rem CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF rem SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS rem INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN rem CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) rem ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE rem POSSIBILITY OF SUCH DAMAGE. set SCRIPT_PATH=%~dp0 set PATH=%SCRIPT_PATH%\bin;%PATH% set QT_PLUGIN_PATH=%SCRIPT_PATH%\plugins;%QT_PLUGIN_PATH% set ARGUMENTS=%* if "%ARGUMENTS%"=="" set ARGUMENTS=gui "%SCRIPT_PATH%\bin\colmap" %ARGUMENTS% colmap-3.10/scripts/shell/enter_vs_dev_shell.ps1000066400000000000000000000015031464745566500220320ustar00rootroot00000000000000if (!$env:VisualStudioDevShell) { $vswhere = "${Env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe" if (!(Test-Path $vswhere)) { throw "Failed to find vswhere.exe" } & $vswhere -latest -format json $vsInstance = & $vswhere -latest -format json | ConvertFrom-Json if ($LASTEXITCODE) { throw "vswhere.exe returned exit code $LASTEXITCODE" } Import-Module "$($vsInstance.installationPath)/Common7/Tools/Microsoft.VisualStudio.DevShell.dll" $prevCwd = Get-Location try { Enter-VsDevShell $vsInstance.instanceId -DevCmdArguments "-no_logo -host_arch=amd64 -arch=amd64" } catch { Write-Host $_ Write-Error "Failed to enter Visual Studio Dev Shell" exit 1 } Set-Location $prevCwd $env:VisualStudioDevShell = $true } colmap-3.10/scripts/shell/images_to_video.sh000077500000000000000000000033161464745566500212330ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Command to produce video from images produced by COLMAP movie grabber tool. ffmpeg -i frame%06d.png -r 30 -vf scale=1680:1050 out.mp4 colmap-3.10/scripts/shell/profile_binary.sh000077500000000000000000000050021464745566500210740ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Script to perform profiling on a command. For example: # ./profile_binary.sh ./src/colmap/exe/colmap automatic_reconstructor ... perf_bin=$(find /usr/lib/linux-tools -name perf | head -1) if [[ -z $perf_bin ]]; then echo "Error: Perf tool not found. Under ubuntu, install as:" echo " sudo apt-get install linux-tools-generic" exit 1 fi "$perf_bin" record -e cycles:u -g "$@" binary_filename=$(basename -- "${binary_path}") profile_path="$binary_filename.perf.data" mv perf.data "$profile_path" echo "#####################################################################" echo "###### Profiling finished. Inspect results using the commands: ######" echo "#####################################################################" echo "If the perf output contains unknown list items, recompile with RelWithDebInfo" echo "$perf_bin report -i $profile_path" echo "$perf_bin report --stdio -g graph,0.5,caller -i $profile_path" colmap-3.10/scripts/shell/restore_git_submodules.sh000077500000000000000000000035261464745566500226710ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. set -e git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | while read path_key path do url_key=$(echo $path_key | sed 's/\.path/.url/') url=$(git config -f .gitmodules --get "$url_key") git submodule add -f $url $path done colmap-3.10/scripts/shell/run_tests.bat000077500000000000000000000035561464745566500202660ustar00rootroot00000000000000@echo off rem Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. rem All rights reserved. rem rem Redistribution and use in source and binary forms, with or without rem modification, are permitted provided that the following conditions are met: rem rem * Redistributions of source code must retain the above copyright rem notice, this list of conditions and the following disclaimer. rem rem * Redistributions in binary form must reproduce the above copyright rem notice, this list of conditions and the following disclaimer in the rem documentation and/or other materials provided with the distribution. rem rem * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of rem its contributors may be used to endorse or promote products derived rem from this software without specific prior written permission. rem rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" rem AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE rem IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE rem ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE rem LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR rem CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF rem SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS rem INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN rem CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) rem ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE rem POSSIBILITY OF SUCH DAMAGE. set SCRIPT_PATH=%~dp0 set PATH=%SCRIPT_PATH%\bin;%PATH% set QT_PLUGIN_PATH=%SCRIPT_PATH%\plugins;%QT_PLUGIN_PATH% @echo on for %%i in (%SCRIPT_PATH%\bin\*_test.exe) do ( %%i if %errorlevel% neq 0 goto end ) :end pause colmap-3.10/src/000077500000000000000000000000001464745566500135255ustar00rootroot00000000000000colmap-3.10/src/colmap/000077500000000000000000000000001464745566500150005ustar00rootroot00000000000000colmap-3.10/src/colmap/CMakeLists.txt000066400000000000000000000054761464745566500175540ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. if(IS_MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3") # Avoid pulling in too many header files through add_definitions("-DWIN32_LEAN_AND_MEAN") elseif(IS_GNU OR IS_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif() if(CUDA_ENABLED) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --use_fast_math") # Use a separate stream per thread to allow for concurrent kernel execution # between multiple threads on the same device. set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --default-stream per-thread") # Suppress warnings: # ptxas warning : Stack size for entry function X cannot be statically determined. set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xptxas=-suppress-stack-size-warning") endif() add_subdirectory(controllers) add_subdirectory(estimators) add_subdirectory(exe) add_subdirectory(feature) add_subdirectory(geometry) add_subdirectory(image) add_subdirectory(math) add_subdirectory(mvs) add_subdirectory(optim) add_subdirectory(retrieval) add_subdirectory(scene) add_subdirectory(sensor) add_subdirectory(sfm) add_subdirectory(tools) add_subdirectory(util) if (GUI_ENABLED) add_subdirectory(ui) endif() colmap-3.10/src/colmap/controllers/000077500000000000000000000000001464745566500173465ustar00rootroot00000000000000colmap-3.10/src/colmap/controllers/CMakeLists.txt000066400000000000000000000053011464745566500221050ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. set(FOLDER_NAME "controllers") COLMAP_ADD_LIBRARY( NAME colmap_controllers SRCS automatic_reconstruction.h automatic_reconstruction.cc bundle_adjustment.h bundle_adjustment.cc hierarchical_mapper.h hierarchical_mapper.cc feature_extraction.h feature_extraction.cc feature_matching.h feature_matching.cc feature_matching_utils.h feature_matching_utils.cc image_reader.h image_reader.cc incremental_mapper.h incremental_mapper.cc option_manager.h option_manager.cc PUBLIC_LINK_LIBS colmap_estimators colmap_feature colmap_geometry colmap_scene colmap_util Eigen3::Eigen Boost::program_options PRIVATE_LINK_LIBS colmap_image colmap_math colmap_mvs colmap_sfm Ceres::ceres Boost::filesystem Boost::boost ) COLMAP_ADD_TEST( NAME hierarchical_mapper_test SRCS hierarchical_mapper_test.cc LINK_LIBS colmap_controllers ) COLMAP_ADD_TEST( NAME incremental_mapper_test SRCS incremental_mapper_test.cc LINK_LIBS colmap_controllers ) colmap-3.10/src/colmap/controllers/automatic_reconstruction.cc000066400000000000000000000277241464745566500250200ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/automatic_reconstruction.h" #include "colmap/controllers/feature_extraction.h" #include "colmap/controllers/feature_matching.h" #include "colmap/controllers/incremental_mapper.h" #include "colmap/controllers/option_manager.h" #include "colmap/image/undistortion.h" #include "colmap/mvs/fusion.h" #include "colmap/mvs/meshing.h" #include "colmap/mvs/patch_match.h" #include "colmap/util/logging.h" #include "colmap/util/misc.h" namespace colmap { AutomaticReconstructionController::AutomaticReconstructionController( const Options& options, std::shared_ptr reconstruction_manager) : options_(options), reconstruction_manager_(std::move(reconstruction_manager)), active_thread_(nullptr) { THROW_CHECK_DIR_EXISTS(options_.workspace_path); THROW_CHECK_DIR_EXISTS(options_.image_path); THROW_CHECK_NOTNULL(reconstruction_manager_); option_manager_.AddAllOptions(); *option_manager_.image_path = options_.image_path; *option_manager_.database_path = JoinPaths(options_.workspace_path, "database.db"); if (options_.data_type == DataType::VIDEO) { option_manager_.ModifyForVideoData(); } else if (options_.data_type == DataType::INDIVIDUAL) { option_manager_.ModifyForIndividualData(); } else if (options_.data_type == DataType::INTERNET) { option_manager_.ModifyForInternetData(); } else { LOG(FATAL_THROW) << "Data type not supported"; } THROW_CHECK(ExistsCameraModelWithName(options_.camera_model)); if (options_.quality == Quality::LOW) { option_manager_.ModifyForLowQuality(); } else if (options_.quality == Quality::MEDIUM) { option_manager_.ModifyForMediumQuality(); } else if (options_.quality == Quality::HIGH) { option_manager_.ModifyForHighQuality(); } else if (options_.quality == Quality::EXTREME) { option_manager_.ModifyForExtremeQuality(); } option_manager_.sift_extraction->num_threads = options_.num_threads; option_manager_.sift_matching->num_threads = options_.num_threads; option_manager_.mapper->num_threads = options_.num_threads; option_manager_.poisson_meshing->num_threads = options_.num_threads; ImageReaderOptions& reader_options = *option_manager_.image_reader; reader_options.database_path = *option_manager_.database_path; reader_options.image_path = *option_manager_.image_path; if (!options_.mask_path.empty()) { reader_options.mask_path = options_.mask_path; option_manager_.image_reader->mask_path = options_.mask_path; option_manager_.stereo_fusion->mask_path = options_.mask_path; } reader_options.single_camera = options_.single_camera; reader_options.single_camera_per_folder = options_.single_camera_per_folder; reader_options.camera_model = options_.camera_model; reader_options.camera_params = options_.camera_params; option_manager_.sift_extraction->use_gpu = options_.use_gpu; option_manager_.sift_matching->use_gpu = options_.use_gpu; option_manager_.sift_extraction->gpu_index = options_.gpu_index; option_manager_.sift_matching->gpu_index = options_.gpu_index; option_manager_.patch_match_stereo->gpu_index = options_.gpu_index; feature_extractor_ = CreateFeatureExtractorController( reader_options, *option_manager_.sift_extraction); exhaustive_matcher_ = CreateExhaustiveFeatureMatcher(*option_manager_.exhaustive_matching, *option_manager_.sift_matching, *option_manager_.two_view_geometry, *option_manager_.database_path); if (!options_.vocab_tree_path.empty()) { option_manager_.sequential_matching->loop_detection = true; option_manager_.sequential_matching->vocab_tree_path = options_.vocab_tree_path; } sequential_matcher_ = CreateSequentialFeatureMatcher(*option_manager_.sequential_matching, *option_manager_.sift_matching, *option_manager_.two_view_geometry, *option_manager_.database_path); if (!options_.vocab_tree_path.empty()) { option_manager_.vocab_tree_matching->vocab_tree_path = options_.vocab_tree_path; vocab_tree_matcher_ = CreateVocabTreeFeatureMatcher(*option_manager_.vocab_tree_matching, *option_manager_.sift_matching, *option_manager_.two_view_geometry, *option_manager_.database_path); } } void AutomaticReconstructionController::Stop() { if (active_thread_ != nullptr) { active_thread_->Stop(); } Thread::Stop(); } void AutomaticReconstructionController::Run() { if (IsStopped()) { return; } RunFeatureExtraction(); if (IsStopped()) { return; } RunFeatureMatching(); if (IsStopped()) { return; } if (options_.sparse) { RunSparseMapper(); } if (IsStopped()) { return; } if (options_.dense) { RunDenseMapper(); } } void AutomaticReconstructionController::RunFeatureExtraction() { THROW_CHECK_NOTNULL(feature_extractor_); active_thread_ = feature_extractor_.get(); feature_extractor_->Start(); feature_extractor_->Wait(); feature_extractor_.reset(); active_thread_ = nullptr; } void AutomaticReconstructionController::RunFeatureMatching() { Thread* matcher = nullptr; if (options_.data_type == DataType::VIDEO) { matcher = sequential_matcher_.get(); } else if (options_.data_type == DataType::INDIVIDUAL || options_.data_type == DataType::INTERNET) { Database database(*option_manager_.database_path); const size_t num_images = database.NumImages(); if (options_.vocab_tree_path.empty() || num_images < 200) { matcher = exhaustive_matcher_.get(); } else { matcher = vocab_tree_matcher_.get(); } } THROW_CHECK_NOTNULL(matcher); active_thread_ = matcher; matcher->Start(); matcher->Wait(); exhaustive_matcher_.reset(); sequential_matcher_.reset(); vocab_tree_matcher_.reset(); active_thread_ = nullptr; } void AutomaticReconstructionController::RunSparseMapper() { const auto sparse_path = JoinPaths(options_.workspace_path, "sparse"); if (ExistsDir(sparse_path)) { auto dir_list = GetDirList(sparse_path); std::sort(dir_list.begin(), dir_list.end()); if (dir_list.size() > 0) { LOG(WARNING) << "Skipping sparse reconstruction because it is already computed"; for (const auto& dir : dir_list) { reconstruction_manager_->Read(dir); } return; } } IncrementalMapperController mapper(option_manager_.mapper, *option_manager_.image_path, *option_manager_.database_path, reconstruction_manager_); mapper.SetCheckIfStoppedFunc([&]() { return IsStopped(); }); mapper.Run(); CreateDirIfNotExists(sparse_path); reconstruction_manager_->Write(sparse_path); option_manager_.Write(JoinPaths(sparse_path, "project.ini")); } void AutomaticReconstructionController::RunDenseMapper() { CreateDirIfNotExists(JoinPaths(options_.workspace_path, "dense")); for (size_t i = 0; i < reconstruction_manager_->Size(); ++i) { if (IsStopped()) { return; } const std::string dense_path = JoinPaths(options_.workspace_path, "dense", std::to_string(i)); const std::string fused_path = JoinPaths(dense_path, "fused.ply"); std::string meshing_path; if (options_.mesher == Mesher::POISSON) { meshing_path = JoinPaths(dense_path, "meshed-poisson.ply"); } else if (options_.mesher == Mesher::DELAUNAY) { meshing_path = JoinPaths(dense_path, "meshed-delaunay.ply"); } if (ExistsFile(fused_path) && ExistsFile(meshing_path)) { continue; } // Image undistortion. if (!ExistsDir(dense_path)) { CreateDirIfNotExists(dense_path); UndistortCameraOptions undistortion_options; undistortion_options.max_image_size = option_manager_.patch_match_stereo->max_image_size; COLMAPUndistorter undistorter(undistortion_options, *reconstruction_manager_->Get(i), *option_manager_.image_path, dense_path); undistorter.SetCheckIfStoppedFunc([&]() { return IsStopped(); }); undistorter.Run(); } if (IsStopped()) { return; } // Patch match stereo. #if defined(COLMAP_CUDA_ENABLED) { mvs::PatchMatchController patch_match_controller( *option_manager_.patch_match_stereo, dense_path, "COLMAP", ""); patch_match_controller.SetCheckIfStoppedFunc( [&]() { return IsStopped(); }); patch_match_controller.Run(); } #else // COLMAP_CUDA_ENABLED LOG(WARNING) << "Skipping patch match stereo because CUDA is not available"; return; #endif // COLMAP_CUDA_ENABLED if (IsStopped()) { return; } // Stereo fusion. if (!ExistsFile(fused_path)) { auto fusion_options = *option_manager_.stereo_fusion; const int num_reg_images = reconstruction_manager_->Get(i)->NumRegImages(); fusion_options.min_num_pixels = std::min(num_reg_images + 1, fusion_options.min_num_pixels); mvs::StereoFusion fuser( fusion_options, dense_path, "COLMAP", "", options_.quality == Quality::HIGH ? "geometric" : "photometric"); fuser.SetCheckIfStoppedFunc([&]() { return IsStopped(); }); fuser.Run(); LOG(INFO) << "Writing output: " << fused_path; WriteBinaryPlyPoints(fused_path, fuser.GetFusedPoints()); mvs::WritePointsVisibility(fused_path + ".vis", fuser.GetFusedPointsVisibility()); } if (IsStopped()) { return; } // Surface meshing. if (!ExistsFile(meshing_path)) { if (options_.mesher == Mesher::POISSON) { mvs::PoissonMeshing( *option_manager_.poisson_meshing, fused_path, meshing_path); } else if (options_.mesher == Mesher::DELAUNAY) { #if defined(COLMAP_CGAL_ENABLED) mvs::DenseDelaunayMeshing( *option_manager_.delaunay_meshing, dense_path, meshing_path); #else // COLMAP_CGAL_ENABLED LOG(WARNING) << "Skipping Delaunay meshing because CGAL is not available"; return; #endif // COLMAP_CGAL_ENABLED } } } } } // namespace colmap colmap-3.10/src/colmap/controllers/automatic_reconstruction.h000066400000000000000000000105071464745566500246510ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/controllers/option_manager.h" #include "colmap/scene/reconstruction_manager.h" #include "colmap/util/threading.h" #include #include namespace colmap { class AutomaticReconstructionController : public Thread { public: enum class DataType { INDIVIDUAL, VIDEO, INTERNET }; enum class Quality { LOW, MEDIUM, HIGH, EXTREME }; enum class Mesher { POISSON, DELAUNAY }; struct Options { // The path to the workspace folder in which all results are stored. std::string workspace_path; // The path to the image folder which are used as input. std::string image_path; // The path to the mask folder which are used as input. std::string mask_path; // The path to the vocabulary tree for feature matching. std::string vocab_tree_path; // The type of input data used to choose optimal mapper settings. DataType data_type = DataType::INDIVIDUAL; // Whether to perform low- or high-quality reconstruction. Quality quality = Quality::HIGH; // Whether to use shared intrinsics or not. bool single_camera = false; // Whether to use shared intrinsics or not for all images in the same // sub-folder. bool single_camera_per_folder = false; // Which camera model to use for images. std::string camera_model = "SIMPLE_RADIAL"; // Initial camera params for all images. std::string camera_params; // Whether to perform sparse mapping. bool sparse = true; // Whether to perform dense mapping. #if defined(COLMAP_CUDA_ENABLED) bool dense = true; #else bool dense = false; #endif // The meshing algorithm to be used. Mesher mesher = Mesher::POISSON; // The number of threads to use in all stages. int num_threads = -1; // Whether to use the GPU in feature extraction and matching. bool use_gpu = true; // Index of the GPU used for GPU stages. For multi-GPU computation, // you should separate multiple GPU indices by comma, e.g., "0,1,2,3". // By default, all GPUs will be used in all stages. std::string gpu_index = "-1"; }; AutomaticReconstructionController( const Options& options, std::shared_ptr reconstruction_manager); void Stop() override; private: void Run() override; void RunFeatureExtraction(); void RunFeatureMatching(); void RunSparseMapper(); void RunDenseMapper(); const Options options_; OptionManager option_manager_; std::shared_ptr reconstruction_manager_; Thread* active_thread_; std::unique_ptr feature_extractor_; std::unique_ptr exhaustive_matcher_; std::unique_ptr sequential_matcher_; std::unique_ptr vocab_tree_matcher_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/bundle_adjustment.cc000066400000000000000000000074071464745566500233740ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/bundle_adjustment.h" #include "colmap/estimators/bundle_adjustment.h" #include "colmap/sfm/observation_manager.h" #include "colmap/util/misc.h" #include "colmap/util/timer.h" #include namespace colmap { namespace { // Callback functor called after each bundle adjustment iteration. class BundleAdjustmentIterationCallback : public ceres::IterationCallback { public: explicit BundleAdjustmentIterationCallback(BaseController* controller) : controller_(controller) {} virtual ceres::CallbackReturnType operator()( const ceres::IterationSummary& summary) { THROW_CHECK_NOTNULL(controller_); if (controller_->CheckIfStopped()) { return ceres::SOLVER_TERMINATE_SUCCESSFULLY; } else { return ceres::SOLVER_CONTINUE; } } private: BaseController* controller_; }; } // namespace BundleAdjustmentController::BundleAdjustmentController( const OptionManager& options, std::shared_ptr reconstruction) : options_(options), reconstruction_(std::move(reconstruction)) {} void BundleAdjustmentController::Run() { THROW_CHECK_NOTNULL(reconstruction_); PrintHeading1("Global bundle adjustment"); Timer run_timer; run_timer.Start(); const std::vector& reg_image_ids = reconstruction_->RegImageIds(); if (reg_image_ids.size() < 2) { LOG(ERROR) << "Need at least two views."; return; } // Avoid degeneracies in bundle adjustment. ObservationManager(*reconstruction_).FilterObservationsWithNegativeDepth(); BundleAdjustmentOptions ba_options = *options_.bundle_adjustment; BundleAdjustmentIterationCallback iteration_callback(this); ba_options.solver_options.callbacks.push_back(&iteration_callback); // Configure bundle adjustment. BundleAdjustmentConfig ba_config; for (const image_t image_id : reg_image_ids) { ba_config.AddImage(image_id); } ba_config.SetConstantCamPose(reg_image_ids[0]); ba_config.SetConstantCamPositions(reg_image_ids[1], {0}); // Run bundle adjustment. BundleAdjuster bundle_adjuster(ba_options, ba_config); bundle_adjuster.Solve(reconstruction_.get()); run_timer.PrintMinutes(); } } // namespace colmap colmap-3.10/src/colmap/controllers/bundle_adjustment.h000066400000000000000000000042301464745566500232250ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/controllers/option_manager.h" #include "colmap/scene/reconstruction.h" #include "colmap/util/base_controller.h" namespace colmap { // Class that controls the global bundle adjustment procedure. class BundleAdjustmentController : public BaseController { public: BundleAdjustmentController(const OptionManager& options, std::shared_ptr reconstruction); void Run(); private: const OptionManager options_; std::shared_ptr reconstruction_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/feature_extraction.cc000066400000000000000000000513501464745566500235540ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/feature_extraction.h" #include "colmap/feature/sift.h" #include "colmap/geometry/gps.h" #include "colmap/scene/database.h" #include "colmap/util/cuda.h" #include "colmap/util/misc.h" #include "colmap/util/opengl_utils.h" #include "colmap/util/timer.h" #include namespace colmap { namespace { void ScaleKeypoints(const Bitmap& bitmap, const Camera& camera, FeatureKeypoints* keypoints) { if (static_cast(bitmap.Width()) != camera.width || static_cast(bitmap.Height()) != camera.height) { const float scale_x = static_cast(camera.width) / bitmap.Width(); const float scale_y = static_cast(camera.height) / bitmap.Height(); for (auto& keypoint : *keypoints) { keypoint.Rescale(scale_x, scale_y); } } } void MaskKeypoints(const Bitmap& mask, FeatureKeypoints* keypoints, FeatureDescriptors* descriptors) { size_t out_index = 0; BitmapColor color; for (size_t i = 0; i < keypoints->size(); ++i) { if (!mask.GetPixel(static_cast(keypoints->at(i).x), static_cast(keypoints->at(i).y), &color) || color.r == 0) { // Delete this keypoint by not copying it to the output. } else { // Retain this keypoint by copying it to the output index (in case this // index differs from its current position). if (out_index != i) { keypoints->at(out_index) = keypoints->at(i); for (int col = 0; col < descriptors->cols(); ++col) { (*descriptors)(out_index, col) = (*descriptors)(i, col); } } out_index += 1; } } keypoints->resize(out_index); descriptors->conservativeResize(out_index, descriptors->cols()); } struct ImageData { ImageReader::Status status = ImageReader::Status::FAILURE; Camera camera; Image image; PosePrior pose_prior; Bitmap bitmap; Bitmap mask; FeatureKeypoints keypoints; FeatureDescriptors descriptors; }; class ImageResizerThread : public Thread { public: ImageResizerThread(int max_image_size, JobQueue* input_queue, JobQueue* output_queue) : max_image_size_(max_image_size), input_queue_(input_queue), output_queue_(output_queue) {} private: void Run() override { while (true) { if (IsStopped()) { break; } auto input_job = input_queue_->Pop(); if (input_job.IsValid()) { auto& image_data = input_job.Data(); if (image_data.status == ImageReader::Status::SUCCESS) { if (static_cast(image_data.bitmap.Width()) > max_image_size_ || static_cast(image_data.bitmap.Height()) > max_image_size_) { // Fit the down-sampled version exactly into the max dimensions. const double scale = static_cast(max_image_size_) / std::max(image_data.bitmap.Width(), image_data.bitmap.Height()); const int new_width = static_cast(image_data.bitmap.Width() * scale); const int new_height = static_cast(image_data.bitmap.Height() * scale); image_data.bitmap.Rescale(new_width, new_height); } } output_queue_->Push(std::move(image_data)); } else { break; } } } const int max_image_size_; JobQueue* input_queue_; JobQueue* output_queue_; }; class SiftFeatureExtractorThread : public Thread { public: SiftFeatureExtractorThread(const SiftExtractionOptions& sift_options, const std::shared_ptr& camera_mask, JobQueue* input_queue, JobQueue* output_queue) : sift_options_(sift_options), camera_mask_(camera_mask), input_queue_(input_queue), output_queue_(output_queue) { THROW_CHECK(sift_options_.Check()); #if !defined(COLMAP_CUDA_ENABLED) if (sift_options_.use_gpu) { opengl_context_ = std::make_unique(); } #endif } private: void Run() override { if (sift_options_.use_gpu) { #if !defined(COLMAP_CUDA_ENABLED) THROW_CHECK_NOTNULL(opengl_context_); THROW_CHECK(opengl_context_->MakeCurrent()); #endif } std::unique_ptr extractor = CreateSiftFeatureExtractor(sift_options_); if (extractor == nullptr) { LOG(ERROR) << "Failed to create feature extractor."; SignalInvalidSetup(); return; } SignalValidSetup(); while (true) { if (IsStopped()) { break; } auto input_job = input_queue_->Pop(); if (input_job.IsValid()) { auto& image_data = input_job.Data(); if (image_data.status == ImageReader::Status::SUCCESS) { if (extractor->Extract(image_data.bitmap, &image_data.keypoints, &image_data.descriptors)) { ScaleKeypoints( image_data.bitmap, image_data.camera, &image_data.keypoints); if (camera_mask_) { MaskKeypoints(*camera_mask_, &image_data.keypoints, &image_data.descriptors); } if (image_data.mask.Data()) { MaskKeypoints(image_data.mask, &image_data.keypoints, &image_data.descriptors); } } else { image_data.status = ImageReader::Status::FAILURE; } } image_data.bitmap.Deallocate(); output_queue_->Push(std::move(image_data)); } else { break; } } } const SiftExtractionOptions sift_options_; std::shared_ptr camera_mask_; std::unique_ptr opengl_context_; JobQueue* input_queue_; JobQueue* output_queue_; }; class FeatureWriterThread : public Thread { public: FeatureWriterThread(size_t num_images, Database* database, JobQueue* input_queue) : num_images_(num_images), database_(database), input_queue_(input_queue) {} private: void Run() override { size_t image_index = 0; while (true) { if (IsStopped()) { break; } auto input_job = input_queue_->Pop(); if (input_job.IsValid()) { auto& image_data = input_job.Data(); image_index += 1; LOG(INFO) << StringPrintf( "Processed file [%d/%d]", image_index, num_images_); LOG(INFO) << StringPrintf(" Name: %s", image_data.image.Name().c_str()); if (image_data.status == ImageReader::Status::IMAGE_EXISTS) { LOG(INFO) << " SKIP: Features for image already extracted."; } else if (image_data.status == ImageReader::Status::BITMAP_ERROR) { LOG(ERROR) << "Failed to read image file format."; } else if (image_data.status == ImageReader::Status::CAMERA_SINGLE_DIM_ERROR) { LOG(ERROR) << "Single camera specified, " "but images have different dimensions."; } else if (image_data.status == ImageReader::Status::CAMERA_EXIST_DIM_ERROR) { LOG(ERROR) << "Image previously processed, but current image " "has different dimensions."; } else if (image_data.status == ImageReader::Status::CAMERA_PARAM_ERROR) { LOG(ERROR) << "Camera has invalid parameters."; } else if (image_data.status == ImageReader::Status::FAILURE) { LOG(ERROR) << "Failed to extract features."; } if (image_data.status != ImageReader::Status::SUCCESS) { continue; } LOG(INFO) << StringPrintf(" Dimensions: %d x %d", image_data.camera.width, image_data.camera.height); LOG(INFO) << StringPrintf(" Camera: #%d - %s", image_data.camera.camera_id, image_data.camera.ModelName().c_str()); LOG(INFO) << StringPrintf( " Focal Length: %.2fpx%s", image_data.camera.MeanFocalLength(), image_data.camera.has_prior_focal_length ? " (Prior)" : ""); LOG(INFO) << StringPrintf(" Features: %d", image_data.keypoints.size()); DatabaseTransaction database_transaction(database_); if (image_data.image.ImageId() == kInvalidImageId) { image_data.image.SetImageId(database_->WriteImage(image_data.image)); if (image_data.pose_prior.IsValid()) { LOG(INFO) << StringPrintf( " GPS: LAT=%.3f, LON=%.3f, ALT=%.3f", image_data.pose_prior.position.x(), image_data.pose_prior.position.y(), image_data.pose_prior.position.z()); database_->WritePosePrior(image_data.image.ImageId(), image_data.pose_prior); } } if (!database_->ExistsKeypoints(image_data.image.ImageId())) { database_->WriteKeypoints(image_data.image.ImageId(), image_data.keypoints); } if (!database_->ExistsDescriptors(image_data.image.ImageId())) { database_->WriteDescriptors(image_data.image.ImageId(), image_data.descriptors); } } else { break; } } } const size_t num_images_; Database* database_; JobQueue* input_queue_; }; // Feature extraction class to extract features for all images in a directory. class FeatureExtractorController : public Thread { public: FeatureExtractorController(const ImageReaderOptions& reader_options, const SiftExtractionOptions& sift_options) : reader_options_(reader_options), sift_options_(sift_options), database_(reader_options_.database_path), image_reader_(reader_options_, &database_) { THROW_CHECK(reader_options_.Check()); THROW_CHECK(sift_options_.Check()); std::shared_ptr camera_mask; if (!reader_options_.camera_mask_path.empty()) { camera_mask = std::make_shared(); if (!camera_mask->Read(reader_options_.camera_mask_path, /*as_rgb*/ false)) { LOG(ERROR) << "Cannot read camera mask file: " << reader_options_.camera_mask_path << ". No mask is going to be used."; camera_mask.reset(); } } const int num_threads = GetEffectiveNumThreads(sift_options_.num_threads); THROW_CHECK_GT(num_threads, 0); // Make sure that we only have limited number of objects in the queue to // avoid excess in memory usage since images and features take lots of // memory. const int kQueueSize = 1; resizer_queue_ = std::make_unique>(kQueueSize); extractor_queue_ = std::make_unique>(kQueueSize); writer_queue_ = std::make_unique>(kQueueSize); if (sift_options_.max_image_size > 0) { for (int i = 0; i < num_threads; ++i) { resizers_.emplace_back( std::make_unique(sift_options_.max_image_size, resizer_queue_.get(), extractor_queue_.get())); } } if (!sift_options_.domain_size_pooling && !sift_options_.estimate_affine_shape && sift_options_.use_gpu) { std::vector gpu_indices = CSVToVector(sift_options_.gpu_index); THROW_CHECK_GT(gpu_indices.size(), 0); #if defined(COLMAP_CUDA_ENABLED) if (gpu_indices.size() == 1 && gpu_indices[0] == -1) { const int num_cuda_devices = GetNumCudaDevices(); THROW_CHECK_GT(num_cuda_devices, 0); gpu_indices.resize(num_cuda_devices); std::iota(gpu_indices.begin(), gpu_indices.end(), 0); } #endif // COLMAP_CUDA_ENABLED auto sift_gpu_options = sift_options_; for (const auto& gpu_index : gpu_indices) { sift_gpu_options.gpu_index = std::to_string(gpu_index); extractors_.emplace_back( std::make_unique(sift_gpu_options, camera_mask, extractor_queue_.get(), writer_queue_.get())); } } else { if (sift_options_.num_threads == -1 && sift_options_.max_image_size == SiftExtractionOptions().max_image_size && sift_options_.first_octave == SiftExtractionOptions().first_octave) { LOG(WARNING) << "Your current options use the maximum number of " "threads on the machine to extract features. Extracting SIFT " "features on the CPU can consume a lot of RAM per thread for " "large images. Consider reducing the maximum image size and/or " "the first octave or manually limit the number of extraction " "threads. Ignore this warning, if your machine has sufficient " "memory for the current settings."; } auto custom_sift_options = sift_options_; custom_sift_options.use_gpu = false; for (int i = 0; i < num_threads; ++i) { extractors_.emplace_back( std::make_unique(custom_sift_options, camera_mask, extractor_queue_.get(), writer_queue_.get())); } } writer_ = std::make_unique( image_reader_.NumImages(), &database_, writer_queue_.get()); } private: void Run() override { PrintHeading1("Feature extraction"); Timer run_timer; run_timer.Start(); for (auto& resizer : resizers_) { resizer->Start(); } for (auto& extractor : extractors_) { extractor->Start(); } writer_->Start(); for (auto& extractor : extractors_) { if (!extractor->CheckValidSetup()) { return; } } while (image_reader_.NextIndex() < image_reader_.NumImages()) { if (IsStopped()) { resizer_queue_->Stop(); extractor_queue_->Stop(); resizer_queue_->Clear(); extractor_queue_->Clear(); break; } ImageData image_data; image_data.status = image_reader_.Next(&image_data.camera, &image_data.image, &image_data.pose_prior, &image_data.bitmap, &image_data.mask); if (image_data.status != ImageReader::Status::SUCCESS) { image_data.bitmap.Deallocate(); } if (sift_options_.max_image_size > 0) { THROW_CHECK(resizer_queue_->Push(std::move(image_data))); } else { THROW_CHECK(extractor_queue_->Push(std::move(image_data))); } } resizer_queue_->Wait(); resizer_queue_->Stop(); for (auto& resizer : resizers_) { resizer->Wait(); } extractor_queue_->Wait(); extractor_queue_->Stop(); for (auto& extractor : extractors_) { extractor->Wait(); } writer_queue_->Wait(); writer_queue_->Stop(); writer_->Wait(); run_timer.PrintMinutes(); } const ImageReaderOptions reader_options_; const SiftExtractionOptions sift_options_; Database database_; ImageReader image_reader_; std::vector> resizers_; std::vector> extractors_; std::unique_ptr writer_; std::unique_ptr> resizer_queue_; std::unique_ptr> extractor_queue_; std::unique_ptr> writer_queue_; }; // Import features from text files. Each image must have a corresponding text // file with the same name and an additional ".txt" suffix. class FeatureImporterController : public Thread { public: FeatureImporterController(const ImageReaderOptions& reader_options, const std::string& import_path) : reader_options_(reader_options), import_path_(import_path) {} private: void Run() override { PrintHeading1("Feature import"); Timer run_timer; run_timer.Start(); if (!ExistsDir(import_path_)) { LOG(ERROR) << "Import directory does not exist."; return; } Database database(reader_options_.database_path); ImageReader image_reader(reader_options_, &database); while (image_reader.NextIndex() < image_reader.NumImages()) { if (IsStopped()) { break; } LOG(INFO) << StringPrintf("Processing file [%d/%d]", image_reader.NextIndex() + 1, image_reader.NumImages()); // Load image data and possibly save camera to database. Camera camera; Image image; PosePrior pose_prior; Bitmap bitmap; if (image_reader.Next(&camera, &image, &pose_prior, &bitmap, nullptr) != ImageReader::Status::SUCCESS) { continue; } const std::string path = JoinPaths(import_path_, image.Name() + ".txt"); if (ExistsFile(path)) { FeatureKeypoints keypoints; FeatureDescriptors descriptors; LoadSiftFeaturesFromTextFile(path, &keypoints, &descriptors); LOG(INFO) << "Features: " << keypoints.size(); DatabaseTransaction database_transaction(&database); if (image.ImageId() == kInvalidImageId) { image.SetImageId(database.WriteImage(image)); if (pose_prior.IsValid()) { database.WritePosePrior(image.ImageId(), pose_prior); } } if (!database.ExistsKeypoints(image.ImageId())) { database.WriteKeypoints(image.ImageId(), keypoints); } if (!database.ExistsDescriptors(image.ImageId())) { database.WriteDescriptors(image.ImageId(), descriptors); } } else { LOG(INFO) << "SKIP: No features found at " << path; } } run_timer.PrintMinutes(); } const ImageReaderOptions reader_options_; const std::string import_path_; }; } // namespace std::unique_ptr CreateFeatureExtractorController( const ImageReaderOptions& reader_options, const SiftExtractionOptions& sift_options) { return std::make_unique(reader_options, sift_options); } std::unique_ptr CreateFeatureImporterController( const ImageReaderOptions& reader_options, const std::string& import_path) { return std::make_unique(reader_options, import_path); } } // namespace colmap colmap-3.10/src/colmap/controllers/feature_extraction.h000066400000000000000000000044061464745566500234160ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/controllers/image_reader.h" #include "colmap/feature/sift.h" #include "colmap/util/threading.h" namespace colmap { // Reads images from a folder, extracts features, and writes them to database. std::unique_ptr CreateFeatureExtractorController( const ImageReaderOptions& reader_options, const SiftExtractionOptions& sift_options); // Import features from text files. Each image must have a corresponding text // file with the same name and an additional ".txt" suffix. std::unique_ptr CreateFeatureImporterController( const ImageReaderOptions& reader_options, const std::string& import_path); } // namespace colmap colmap-3.10/src/colmap/controllers/feature_matching.cc000066400000000000000000000357401464745566500231730ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/feature_matching.h" #include "colmap/controllers/feature_matching_utils.h" #include "colmap/estimators/two_view_geometry.h" #include "colmap/feature/matcher.h" #include "colmap/feature/utils.h" #include "colmap/util/misc.h" #include "colmap/util/timer.h" #include #include namespace colmap { namespace { void PrintElapsedTime(const Timer& timer) { LOG(INFO) << StringPrintf(" in %.3fs", timer.ElapsedSeconds()); } template class GenericFeatureMatcher : public Thread { public: GenericFeatureMatcher( const typename DerivedPairGenerator::PairOptions& pair_options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) : pair_options_(pair_options), database_(std::make_shared(database_path)), cache_(std::make_shared( DerivedPairGenerator::CacheSize(pair_options_), database_)), matcher_( matching_options, geometry_options, database_.get(), cache_.get()) { THROW_CHECK(matching_options.Check()); THROW_CHECK(geometry_options.Check()); } private: void Run() override { PrintHeading1("Feature matching"); Timer run_timer; run_timer.Start(); if (!matcher_.Setup()) { return; } cache_->Setup(); DerivedPairGenerator pair_generator(pair_options_, cache_); while (!pair_generator.HasFinished()) { if (IsStopped()) { run_timer.PrintMinutes(); return; } Timer timer; timer.Start(); const std::vector> image_pairs = pair_generator.Next(); DatabaseTransaction database_transaction(database_.get()); matcher_.Match(image_pairs); PrintElapsedTime(timer); } run_timer.PrintMinutes(); } const typename DerivedPairGenerator::PairOptions pair_options_; const std::shared_ptr database_; const std::shared_ptr cache_; FeatureMatcherController matcher_; }; } // namespace std::unique_ptr CreateExhaustiveFeatureMatcher( const ExhaustiveMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique>( options, matching_options, geometry_options, database_path); } std::unique_ptr CreateVocabTreeFeatureMatcher( const VocabTreeMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique>( options, matching_options, geometry_options, database_path); } std::unique_ptr CreateSequentialFeatureMatcher( const SequentialMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique>( options, matching_options, geometry_options, database_path); } std::unique_ptr CreateSpatialFeatureMatcher( const SpatialMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique>( options, matching_options, geometry_options, database_path); } namespace { class TransitiveFeatureMatcher : public Thread { public: TransitiveFeatureMatcher(const TransitiveMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) : options_(options), matching_options_(matching_options), database_(std::make_shared(database_path)), cache_(std::make_shared(options_.batch_size, database_)), matcher_( matching_options, geometry_options, database_.get(), cache_.get()) { THROW_CHECK(options.Check()); THROW_CHECK(matching_options.Check()); THROW_CHECK(geometry_options.Check()); } private: void Run() override { PrintHeading1("Transitive feature matching"); Timer run_timer; run_timer.Start(); if (!matcher_.Setup()) { return; } cache_->Setup(); const std::vector image_ids = cache_->GetImageIds(); std::vector> image_pairs; std::unordered_set image_pair_ids; for (int iteration = 0; iteration < options_.num_iterations; ++iteration) { if (IsStopped()) { run_timer.PrintMinutes(); return; } Timer timer; timer.Start(); LOG(INFO) << StringPrintf( "Iteration [%d/%d]", iteration + 1, options_.num_iterations); std::vector> existing_image_pairs; std::vector existing_num_inliers; database_->ReadTwoViewGeometryNumInliers(&existing_image_pairs, &existing_num_inliers); THROW_CHECK_EQ(existing_image_pairs.size(), existing_num_inliers.size()); std::unordered_map> adjacency; for (const auto& image_pair : existing_image_pairs) { adjacency[image_pair.first].push_back(image_pair.second); adjacency[image_pair.second].push_back(image_pair.first); } const size_t batch_size = static_cast(options_.batch_size); size_t num_batches = 0; image_pairs.clear(); image_pair_ids.clear(); for (const auto& image : adjacency) { const auto image_id1 = image.first; for (const auto& image_id2 : image.second) { if (adjacency.count(image_id2) > 0) { for (const auto& image_id3 : adjacency.at(image_id2)) { const auto image_pair_id = Database::ImagePairToPairId(image_id1, image_id3); if (image_pair_ids.count(image_pair_id) == 0) { image_pairs.emplace_back(image_id1, image_id3); image_pair_ids.insert(image_pair_id); if (image_pairs.size() >= batch_size) { num_batches += 1; LOG(INFO) << StringPrintf(" Batch %d", num_batches); DatabaseTransaction database_transaction(database_.get()); matcher_.Match(image_pairs); image_pairs.clear(); PrintElapsedTime(timer); timer.Restart(); if (IsStopped()) { run_timer.PrintMinutes(); return; } } } } } } } num_batches += 1; LOG(INFO) << StringPrintf(" Batch %d", num_batches); DatabaseTransaction database_transaction(database_.get()); matcher_.Match(image_pairs); PrintElapsedTime(timer); } run_timer.PrintMinutes(); } const TransitiveMatchingOptions options_; const SiftMatchingOptions matching_options_; const std::shared_ptr database_; const std::shared_ptr cache_; FeatureMatcherController matcher_; }; } // namespace std::unique_ptr CreateTransitiveFeatureMatcher( const TransitiveMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique( options, matching_options, geometry_options, database_path); } std::unique_ptr CreateImagePairsFeatureMatcher( const ImagePairsMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique>( options, matching_options, geometry_options, database_path); } namespace { class FeaturePairsFeatureMatcher : public Thread { public: FeaturePairsFeatureMatcher(const FeaturePairsMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) : options_(options), matching_options_(matching_options), geometry_options_(geometry_options), database_(std::make_shared(database_path)), cache_(std::make_shared(/*cache_size=*/100, database_)) { THROW_CHECK(options.Check()); THROW_CHECK(matching_options.Check()); THROW_CHECK(geometry_options.Check()); } private: void Run() override { PrintHeading1("Importing matches"); Timer run_timer; run_timer.Start(); cache_->Setup(); std::unordered_map image_name_to_image; image_name_to_image.reserve(cache_->GetImageIds().size()); for (const auto image_id : cache_->GetImageIds()) { const auto& image = cache_->GetImage(image_id); image_name_to_image.emplace(image.Name(), &image); } std::ifstream file(options_.match_list_path); THROW_CHECK_FILE_OPEN(file, options_.match_list_path); std::string line; while (std::getline(file, line)) { if (IsStopped()) { run_timer.PrintMinutes(); return; } StringTrim(&line); if (line.empty()) { continue; } std::istringstream line_stream(line); std::string image_name1, image_name2; try { line_stream >> image_name1 >> image_name2; } catch (...) { LOG(ERROR) << "Could not read image pair."; break; } LOG(INFO) << StringPrintf( "%s - %s", image_name1.c_str(), image_name2.c_str()); if (image_name_to_image.count(image_name1) == 0) { LOG(INFO) << StringPrintf("SKIP: Image %s not found in database.", image_name1.c_str()); break; } if (image_name_to_image.count(image_name2) == 0) { LOG(INFO) << StringPrintf("SKIP: Image %s not found in database.", image_name2.c_str()); break; } const Image& image1 = *image_name_to_image[image_name1]; const Image& image2 = *image_name_to_image[image_name2]; bool skip_pair = false; if (database_->ExistsInlierMatches(image1.ImageId(), image2.ImageId())) { LOG(INFO) << "SKIP: Matches for image pair already exist in database."; skip_pair = true; } FeatureMatches matches; while (std::getline(file, line)) { StringTrim(&line); if (line.empty()) { break; } std::istringstream line_stream(line); FeatureMatch match; try { line_stream >> match.point2D_idx1 >> match.point2D_idx2; } catch (...) { LOG(ERROR) << "Cannot read feature matches."; break; } matches.push_back(match); } if (skip_pair) { continue; } const Camera& camera1 = cache_->GetCamera(image1.CameraId()); const Camera& camera2 = cache_->GetCamera(image2.CameraId()); if (options_.verify_matches) { database_->WriteMatches(image1.ImageId(), image2.ImageId(), matches); const auto keypoints1 = cache_->GetKeypoints(image1.ImageId()); const auto keypoints2 = cache_->GetKeypoints(image2.ImageId()); TwoViewGeometry two_view_geometry = EstimateTwoViewGeometry(camera1, FeatureKeypointsToPointsVector(*keypoints1), camera2, FeatureKeypointsToPointsVector(*keypoints2), matches, geometry_options_); database_->WriteTwoViewGeometry( image1.ImageId(), image2.ImageId(), two_view_geometry); } else { TwoViewGeometry two_view_geometry; if (camera1.has_prior_focal_length && camera2.has_prior_focal_length) { two_view_geometry.config = TwoViewGeometry::CALIBRATED; } else { two_view_geometry.config = TwoViewGeometry::UNCALIBRATED; } two_view_geometry.inlier_matches = matches; database_->WriteTwoViewGeometry( image1.ImageId(), image2.ImageId(), two_view_geometry); } } run_timer.PrintMinutes(); } const FeaturePairsMatchingOptions options_; const SiftMatchingOptions matching_options_; const TwoViewGeometryOptions geometry_options_; const std::shared_ptr database_; const std::shared_ptr cache_; }; } // namespace std::unique_ptr CreateFeaturePairsFeatureMatcher( const FeaturePairsMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path) { return std::make_unique( options, matching_options, geometry_options, database_path); } } // namespace colmap colmap-3.10/src/colmap/controllers/feature_matching.h000066400000000000000000000147751464745566500230420ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/estimators/two_view_geometry.h" #include "colmap/feature/pairing.h" #include "colmap/feature/sift.h" #include "colmap/util/threading.h" #include #include namespace colmap { // Exhaustively match images by processing each block in the exhaustive match // matrix in one batch: // // +----+----+-----------------> images[i] // |#000|0000| // |1#00|1000| <- Above the main diagonal, the block diagonal is not matched // |11#0|1100| ^ // |111#|1110| | // +----+----+ | // |1000|#000|\ | // |1100|1#00| \ One block | // |1110|11#0| / of image pairs | // |1111|111#|/ | // +----+----+ | // | ^ | // | | | // | Below the main diagonal, the block diagonal is matched <--------------+ // | // v // images[i] // // Pairs will only be matched if 1, to avoid duplicate pairs. Pairs with # // are on the main diagonal and denote pairs of the same image. std::unique_ptr CreateExhaustiveFeatureMatcher( const ExhaustiveMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Match each image against its nearest neighbors using a vocabulary tree. std::unique_ptr CreateVocabTreeFeatureMatcher( const VocabTreeMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Sequentially match images within neighborhood: // // +-------------------------------+-----------------------> images[i] // ^ | ^ // | Current image[i] | // | | | // +----------+-----------+ // | // Match image_i against // // image_[i - o, i + o] with o = [1 .. overlap] // image_[i - 2^o, i + 2^o] (for quadratic overlap) // // Sequential order is determined based on the image names in ascending order. // // Invoke loop detection if `(i mod loop_detection_period) == 0`, retrieve // most similar `loop_detection_num_images` images from vocabulary tree, // and perform matching and verification. std::unique_ptr CreateSequentialFeatureMatcher( const SequentialMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Match images against spatial nearest neighbors using prior location // information, e.g. provided manually or extracted from EXIF. std::unique_ptr CreateSpatialFeatureMatcher( const SpatialMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Match transitive image pairs in a database with existing feature matches. // This matcher transitively closes loops. For example, if image pairs A-B and // B-C match but A-C has not been matched, then this matcher attempts to match // A-C. This procedure is performed for multiple iterations. std::unique_ptr CreateTransitiveFeatureMatcher( const TransitiveMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Match images manually specified in a list of image pairs. // // Read matches file with the following format: // // image_name1 image_name2 // image_name1 image_name3 // image_name2 image_name3 // ... // std::unique_ptr CreateImagePairsFeatureMatcher( const ImagePairsMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); // Import feature matches from a text file. // // Read matches file with the following format: // // image_name1 image_name2 // 0 1 // 1 2 // 2 3 // // image_name1 image_name3 // 0 1 // 1 2 // 2 3 // ... // std::unique_ptr CreateFeaturePairsFeatureMatcher( const FeaturePairsMatchingOptions& options, const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, const std::string& database_path); } // namespace colmap colmap-3.10/src/colmap/controllers/feature_matching_utils.cc000066400000000000000000000370161464745566500244110ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/feature_matching_utils.h" #include "colmap/estimators/two_view_geometry.h" #include "colmap/feature/utils.h" #include "colmap/util/cuda.h" #include "colmap/util/misc.h" #include #include #include namespace colmap { FeatureMatcherWorker::FeatureMatcherWorker( const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, FeatureMatcherCache* cache, JobQueue* input_queue, JobQueue* output_queue) : matching_options_(matching_options), geometry_options_(geometry_options), cache_(cache), input_queue_(input_queue), output_queue_(output_queue) { THROW_CHECK(matching_options_.Check()); prev_keypoints_image_ids_[0] = kInvalidImageId; prev_keypoints_image_ids_[1] = kInvalidImageId; prev_descriptors_image_ids_[0] = kInvalidImageId; prev_descriptors_image_ids_[1] = kInvalidImageId; if (matching_options_.use_gpu) { #if !defined(COLMAP_CUDA_ENABLED) opengl_context_ = std::make_unique(); #endif } } void FeatureMatcherWorker::SetMaxNumMatches(int max_num_matches) { matching_options_.max_num_matches = max_num_matches; } void FeatureMatcherWorker::Run() { if (matching_options_.use_gpu) { #if !defined(COLMAP_CUDA_ENABLED) THROW_CHECK_NOTNULL(opengl_context_); THROW_CHECK(opengl_context_->MakeCurrent()); #endif } std::unique_ptr matcher = CreateSiftFeatureMatcher(matching_options_); if (matcher == nullptr) { LOG(ERROR) << "Failed to create feature matcher."; SignalInvalidSetup(); return; } SignalValidSetup(); while (true) { if (IsStopped()) { break; } auto input_job = input_queue_->Pop(); if (input_job.IsValid()) { auto& data = input_job.Data(); if (!cache_->ExistsDescriptors(data.image_id1) || !cache_->ExistsDescriptors(data.image_id2)) { THROW_CHECK(output_queue_->Push(std::move(data))); continue; } if (matching_options_.guided_matching) { matcher->MatchGuided(geometry_options_.ransac_options.max_error, GetKeypointsPtr(0, data.image_id1), GetKeypointsPtr(1, data.image_id2), GetDescriptorsPtr(0, data.image_id1), GetDescriptorsPtr(1, data.image_id2), &data.two_view_geometry); } else { matcher->Match(GetDescriptorsPtr(0, data.image_id1), GetDescriptorsPtr(1, data.image_id2), &data.matches); } THROW_CHECK(output_queue_->Push(std::move(data))); } } } std::shared_ptr FeatureMatcherWorker::GetKeypointsPtr( const int index, const image_t image_id) { THROW_CHECK_GE(index, 0); THROW_CHECK_LE(index, 1); if (prev_keypoints_image_ids_[index] == image_id) { return nullptr; } else { prev_keypoints_image_ids_[index] = image_id; prev_keypoints_[index] = cache_->GetKeypoints(image_id); return prev_keypoints_[index]; } } std::shared_ptr FeatureMatcherWorker::GetDescriptorsPtr( const int index, const image_t image_id) { THROW_CHECK_GE(index, 0); THROW_CHECK_LE(index, 1); if (prev_descriptors_image_ids_[index] == image_id) { return nullptr; } else { prev_descriptors_image_ids_[index] = image_id; prev_descriptors_[index] = cache_->GetDescriptors(image_id); return prev_descriptors_[index]; } } namespace { class VerifierWorker : public Thread { public: typedef FeatureMatcherData Input; typedef FeatureMatcherData Output; VerifierWorker(const TwoViewGeometryOptions& options, FeatureMatcherCache* cache, JobQueue* input_queue, JobQueue* output_queue) : options_(options), cache_(cache), input_queue_(input_queue), output_queue_(output_queue) { THROW_CHECK(options_.Check()); } protected: void Run() override { while (true) { if (IsStopped()) { break; } auto input_job = input_queue_->Pop(); if (input_job.IsValid()) { auto& data = input_job.Data(); if (data.matches.size() < static_cast(options_.min_num_inliers)) { THROW_CHECK(output_queue_->Push(std::move(data))); continue; } const auto& camera1 = cache_->GetCamera(cache_->GetImage(data.image_id1).CameraId()); const auto& camera2 = cache_->GetCamera(cache_->GetImage(data.image_id2).CameraId()); const auto keypoints1 = cache_->GetKeypoints(data.image_id1); const auto keypoints2 = cache_->GetKeypoints(data.image_id2); const std::vector points1 = FeatureKeypointsToPointsVector(*keypoints1); const std::vector points2 = FeatureKeypointsToPointsVector(*keypoints2); data.two_view_geometry = EstimateTwoViewGeometry( camera1, points1, camera2, points2, data.matches, options_); THROW_CHECK(output_queue_->Push(std::move(data))); } } } private: const TwoViewGeometryOptions options_; FeatureMatcherCache* cache_; JobQueue* input_queue_; JobQueue* output_queue_; }; } // namespace FeatureMatcherController::FeatureMatcherController( const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, Database* database, FeatureMatcherCache* cache) : matching_options_(matching_options), geometry_options_(geometry_options), database_(database), cache_(cache), is_setup_(false) { THROW_CHECK(matching_options_.Check()); THROW_CHECK(geometry_options_.Check()); const int num_threads = GetEffectiveNumThreads(matching_options_.num_threads); THROW_CHECK_GT(num_threads, 0); std::vector gpu_indices = CSVToVector(matching_options_.gpu_index); THROW_CHECK_GT(gpu_indices.size(), 0); #if defined(COLMAP_CUDA_ENABLED) if (matching_options_.use_gpu && gpu_indices.size() == 1 && gpu_indices[0] == -1) { const int num_cuda_devices = GetNumCudaDevices(); THROW_CHECK_GT(num_cuda_devices, 0); gpu_indices.resize(num_cuda_devices); std::iota(gpu_indices.begin(), gpu_indices.end(), 0); } #endif // COLMAP_CUDA_ENABLED if (matching_options_.use_gpu) { auto matching_options_copy = matching_options_; // The first matching is always without guided matching. matching_options_copy.guided_matching = false; matchers_.reserve(gpu_indices.size()); for (const auto& gpu_index : gpu_indices) { matching_options_copy.gpu_index = std::to_string(gpu_index); matchers_.emplace_back( std::make_unique(matching_options_copy, geometry_options_, cache, &matcher_queue_, &verifier_queue_)); } } else { auto matching_options_copy = matching_options_; // The first matching is always without guided matching. matching_options_copy.guided_matching = false; matchers_.reserve(num_threads); for (int i = 0; i < num_threads; ++i) { matchers_.emplace_back( std::make_unique(matching_options_copy, geometry_options_, cache, &matcher_queue_, &verifier_queue_)); } } verifiers_.reserve(num_threads); if (matching_options_.guided_matching) { // Redirect the verification output to final round of guided matching. for (int i = 0; i < num_threads; ++i) { verifiers_.emplace_back(std::make_unique( geometry_options_, cache, &verifier_queue_, &guided_matcher_queue_)); } if (matching_options_.use_gpu) { auto matching_options_copy = matching_options_; guided_matchers_.reserve(gpu_indices.size()); for (const auto& gpu_index : gpu_indices) { matching_options_copy.gpu_index = std::to_string(gpu_index); guided_matchers_.emplace_back( std::make_unique(matching_options_copy, geometry_options_, cache, &guided_matcher_queue_, &output_queue_)); } } else { guided_matchers_.reserve(num_threads); for (int i = 0; i < num_threads; ++i) { guided_matchers_.emplace_back( std::make_unique(matching_options_, geometry_options_, cache, &guided_matcher_queue_, &output_queue_)); } } } else { for (int i = 0; i < num_threads; ++i) { verifiers_.emplace_back(std::make_unique( geometry_options_, cache, &verifier_queue_, &output_queue_)); } } } FeatureMatcherController::~FeatureMatcherController() { matcher_queue_.Wait(); verifier_queue_.Wait(); guided_matcher_queue_.Wait(); output_queue_.Wait(); for (auto& matcher : matchers_) { matcher->Stop(); } for (auto& verifier : verifiers_) { verifier->Stop(); } for (auto& guided_matcher : guided_matchers_) { guided_matcher->Stop(); } matcher_queue_.Stop(); verifier_queue_.Stop(); guided_matcher_queue_.Stop(); output_queue_.Stop(); for (auto& matcher : matchers_) { matcher->Wait(); } for (auto& verifier : verifiers_) { verifier->Wait(); } for (auto& guided_matcher : guided_matchers_) { guided_matcher->Wait(); } } bool FeatureMatcherController::Setup() { // Minimize the amount of allocated GPU memory by computing the maximum number // of descriptors for any image over the whole database. const int max_num_features = THROW_CHECK_NOTNULL(database_)->MaxNumKeypoints(); matching_options_.max_num_matches = std::min(matching_options_.max_num_matches, max_num_features); for (auto& matcher : matchers_) { matcher->SetMaxNumMatches(matching_options_.max_num_matches); matcher->Start(); } for (auto& verifier : verifiers_) { verifier->Start(); } for (auto& guided_matcher : guided_matchers_) { guided_matcher->SetMaxNumMatches(matching_options_.max_num_matches); guided_matcher->Start(); } for (auto& matcher : matchers_) { if (!matcher->CheckValidSetup()) { return false; } } for (auto& guided_matcher : guided_matchers_) { if (!guided_matcher->CheckValidSetup()) { return false; } } is_setup_ = true; return true; } void FeatureMatcherController::Match( const std::vector>& image_pairs) { THROW_CHECK_NOTNULL(database_); THROW_CHECK_NOTNULL(cache_); THROW_CHECK(is_setup_); if (image_pairs.empty()) { return; } ////////////////////////////////////////////////////////////////////////////// // Match the image pairs ////////////////////////////////////////////////////////////////////////////// std::unordered_set image_pair_ids; image_pair_ids.reserve(image_pairs.size()); size_t num_outputs = 0; for (const auto& image_pair : image_pairs) { // Avoid self-matches. if (image_pair.first == image_pair.second) { continue; } // Avoid duplicate image pairs. const image_pair_t pair_id = Database::ImagePairToPairId(image_pair.first, image_pair.second); if (image_pair_ids.count(pair_id) > 0) { continue; } image_pair_ids.insert(pair_id); const bool exists_matches = cache_->ExistsMatches(image_pair.first, image_pair.second); const bool exists_inlier_matches = cache_->ExistsInlierMatches(image_pair.first, image_pair.second); if (exists_matches && exists_inlier_matches) { continue; } num_outputs += 1; // If only one of the matches or inlier matches exist, we recompute them // from scratch and delete the existing results. This must be done before // pushing the jobs to the queue, otherwise database constraints might fail // when writing an existing result into the database. if (exists_inlier_matches) { cache_->DeleteInlierMatches(image_pair.first, image_pair.second); } FeatureMatcherData data; data.image_id1 = image_pair.first; data.image_id2 = image_pair.second; if (exists_matches) { data.matches = cache_->GetMatches(image_pair.first, image_pair.second); cache_->DeleteMatches(image_pair.first, image_pair.second); THROW_CHECK(verifier_queue_.Push(std::move(data))); } else { THROW_CHECK(matcher_queue_.Push(std::move(data))); } } ////////////////////////////////////////////////////////////////////////////// // Write results to database ////////////////////////////////////////////////////////////////////////////// for (size_t i = 0; i < num_outputs; ++i) { auto output_job = output_queue_.Pop(); THROW_CHECK(output_job.IsValid()); auto& output = output_job.Data(); if (output.matches.size() < static_cast(geometry_options_.min_num_inliers)) { output.matches = {}; } if (output.two_view_geometry.inlier_matches.size() < static_cast(geometry_options_.min_num_inliers)) { output.two_view_geometry = TwoViewGeometry(); } cache_->WriteMatches(output.image_id1, output.image_id2, output.matches); cache_->WriteTwoViewGeometry( output.image_id1, output.image_id2, output.two_view_geometry); } THROW_CHECK_EQ(output_queue_.Size(), 0); } } // namespace colmap colmap-3.10/src/colmap/controllers/feature_matching_utils.h000066400000000000000000000114251464745566500242470ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/estimators/two_view_geometry.h" #include "colmap/feature/matcher.h" #include "colmap/feature/sift.h" #include "colmap/scene/database.h" #include "colmap/util/opengl_utils.h" #include "colmap/util/threading.h" #include #include #include #include namespace colmap { struct FeatureMatcherData { image_t image_id1 = kInvalidImageId; image_t image_id2 = kInvalidImageId; FeatureMatches matches; TwoViewGeometry two_view_geometry; }; class FeatureMatcherWorker : public Thread { public: typedef FeatureMatcherData Input; typedef FeatureMatcherData Output; FeatureMatcherWorker(const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& geometry_options, FeatureMatcherCache* cache, JobQueue* input_queue, JobQueue* output_queue); void SetMaxNumMatches(int max_num_matches); private: void Run() override; std::shared_ptr GetKeypointsPtr(int index, image_t image_id); std::shared_ptr GetDescriptorsPtr(int index, image_t image_id); SiftMatchingOptions matching_options_; TwoViewGeometryOptions geometry_options_; FeatureMatcherCache* cache_; JobQueue* input_queue_; JobQueue* output_queue_; std::unique_ptr opengl_context_; std::array prev_keypoints_image_ids_; std::array, 2> prev_keypoints_; std::array prev_descriptors_image_ids_; std::array, 2> prev_descriptors_; }; // Multi-threaded and multi-GPU SIFT feature matcher, which writes the computed // results to the database and skips already matched image pairs. To improve // performance of the matching by taking advantage of caching and database // transactions, pass multiple images to the `Match` function. Note that the // database should be in an active transaction while calling `Match`. class FeatureMatcherController { public: FeatureMatcherController( const SiftMatchingOptions& matching_options, const TwoViewGeometryOptions& two_view_geometry_options, Database* database, FeatureMatcherCache* cache); ~FeatureMatcherController(); // Setup the matchers and return if successful. bool Setup(); // Match one batch of multiple image pairs. void Match(const std::vector>& image_pairs); private: SiftMatchingOptions matching_options_; TwoViewGeometryOptions geometry_options_; Database* database_; FeatureMatcherCache* cache_; bool is_setup_; std::vector> matchers_; std::vector> guided_matchers_; std::vector> verifiers_; std::unique_ptr thread_pool_; JobQueue matcher_queue_; JobQueue verifier_queue_; JobQueue guided_matcher_queue_; JobQueue output_queue_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/hierarchical_mapper.cc000066400000000000000000000224351464745566500236450ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/hierarchical_mapper.h" #include "colmap/estimators/alignment.h" #include "colmap/scene/scene_clustering.h" #include "colmap/sfm/observation_manager.h" #include "colmap/util/misc.h" #include "colmap/util/threading.h" namespace colmap { namespace { void MergeClusters(const SceneClustering::Cluster& cluster, std::unordered_map>* reconstruction_managers) { // Extract all reconstructions from all child clusters. std::vector> reconstructions; for (const auto& child_cluster : cluster.child_clusters) { if (!child_cluster.child_clusters.empty()) { MergeClusters(child_cluster, reconstruction_managers); } auto& reconstruction_manager = reconstruction_managers->at(&child_cluster); for (size_t i = 0; i < reconstruction_manager->Size(); ++i) { reconstructions.push_back(reconstruction_manager->Get(i)); } } // Try to merge all child cluster reconstruction. while (reconstructions.size() > 1) { bool merge_success = false; for (size_t i = 0; i < reconstructions.size(); ++i) { const int num_reg_images_i = reconstructions[i]->NumRegImages(); for (size_t j = 0; j < i; ++j) { const double kMaxReprojError = 8.0; const int num_reg_images_j = reconstructions[j]->NumRegImages(); if (MergeAndFilterReconstructions( kMaxReprojError, *reconstructions[j], *reconstructions[i])) { LOG(INFO) << StringPrintf( "=> Merged clusters with %d and %d images into %d images", num_reg_images_i, num_reg_images_j, reconstructions[i]->NumRegImages()); reconstructions.erase(reconstructions.begin() + j); merge_success = true; break; } } if (merge_success) { break; } } if (!merge_success) { break; } } // Insert a new reconstruction manager for merged cluster. auto& reconstruction_manager = (*reconstruction_managers)[&cluster]; reconstruction_manager = std::make_shared(); for (const auto& reconstruction : reconstructions) { reconstruction_manager->Get(reconstruction_manager->Add()) = reconstruction; } // Delete all merged child cluster reconstruction managers. for (const auto& child_cluster : cluster.child_clusters) { reconstruction_managers->erase(&child_cluster); } } } // namespace bool HierarchicalMapperController::Options::Check() const { CHECK_OPTION_GT(init_num_trials, -1); CHECK_OPTION_GE(num_workers, -1); clustering_options.Check(); THROW_CHECK_EQ(clustering_options.branching, 2); incremental_options.Check(); return true; } HierarchicalMapperController::HierarchicalMapperController( const Options& options, std::shared_ptr reconstruction_manager) : options_(options), reconstruction_manager_(std::move(reconstruction_manager)) { THROW_CHECK(options_.Check()); } void HierarchicalMapperController::Run() { PrintHeading1("Partitioning scene"); Timer run_timer; run_timer.Start(); ////////////////////////////////////////////////////////////////////////////// // Cluster scene graph ////////////////////////////////////////////////////////////////////////////// const Database database(options_.database_path); LOG(INFO) << "Reading images..."; const auto images = database.ReadAllImages(); std::unordered_map image_id_to_name; image_id_to_name.reserve(images.size()); for (const auto& image : images) { image_id_to_name.emplace(image.ImageId(), image.Name()); } SceneClustering scene_clustering = SceneClustering::Create(options_.clustering_options, database); auto leaf_clusters = scene_clustering.GetLeafClusters(); size_t total_num_images = 0; for (size_t i = 0; i < leaf_clusters.size(); ++i) { total_num_images += leaf_clusters[i]->image_ids.size(); LOG(INFO) << StringPrintf(" Cluster %d with %d images", i + 1, leaf_clusters[i]->image_ids.size()); } LOG(INFO) << StringPrintf("Clusters have %d images", total_num_images); ////////////////////////////////////////////////////////////////////////////// // Reconstruct clusters ////////////////////////////////////////////////////////////////////////////// PrintHeading1("Reconstructing clusters"); // Determine the number of workers and threads per worker. const int kMaxNumThreads = -1; const int num_eff_threads = GetEffectiveNumThreads(kMaxNumThreads); const int kDefaultNumWorkers = 8; const int num_eff_workers = options_.num_workers < 1 ? std::min(static_cast(leaf_clusters.size()), std::min(kDefaultNumWorkers, num_eff_threads)) : options_.num_workers; const int num_threads_per_worker = std::max(1, num_eff_threads / num_eff_workers); // Function to reconstruct one cluster using incremental mapping. auto ReconstructCluster = [&, this](const SceneClustering::Cluster& cluster, std::shared_ptr reconstruction_manager) { if (cluster.image_ids.empty()) { return; } auto incremental_options = std::make_shared( options_.incremental_options); incremental_options->max_model_overlap = 3; incremental_options->init_num_trials = options_.init_num_trials; if (incremental_options->num_threads < 0) { incremental_options->num_threads = num_threads_per_worker; } for (const auto image_id : cluster.image_ids) { incremental_options->image_names.insert( image_id_to_name.at(image_id)); } IncrementalMapperController mapper(std::move(incremental_options), options_.image_path, options_.database_path, std::move(reconstruction_manager)); mapper.Run(); }; // Start reconstructing the bigger clusters first for better resource usage. std::sort(leaf_clusters.begin(), leaf_clusters.end(), [](const SceneClustering::Cluster* cluster1, const SceneClustering::Cluster* cluster2) { return cluster1->image_ids.size() > cluster2->image_ids.size(); }); // Start the reconstruction workers. Use a separate reconstruction manager per // thread to avoid race conditions. std::unordered_map> reconstruction_managers; reconstruction_managers.reserve(leaf_clusters.size()); ThreadPool thread_pool(num_eff_workers); for (const auto& cluster : leaf_clusters) { reconstruction_managers[cluster] = std::make_shared(); thread_pool.AddTask( ReconstructCluster, *cluster, reconstruction_managers[cluster]); } thread_pool.Wait(); ////////////////////////////////////////////////////////////////////////////// // Merge clusters ////////////////////////////////////////////////////////////////////////////// if (leaf_clusters.size() > 1) { PrintHeading1("Merging clusters"); MergeClusters(*scene_clustering.GetRootCluster(), &reconstruction_managers); } THROW_CHECK_EQ(reconstruction_managers.size(), 1); THROW_CHECK_GT( reconstruction_managers.begin()->second->Get(0)->NumRegImages(), 0); *reconstruction_manager_ = *reconstruction_managers.begin()->second; run_timer.PrintMinutes(); } } // namespace colmap colmap-3.10/src/colmap/controllers/hierarchical_mapper.h000066400000000000000000000062421464745566500235050ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/controllers/incremental_mapper.h" #include "colmap/scene/reconstruction_manager.h" #include "colmap/scene/scene_clustering.h" #include "colmap/util/base_controller.h" #include namespace colmap { // Hierarchical mapping first hierarchically partitions the scene into multiple // overlapping clusters, then reconstructs them separately using incremental // mapping, and finally merges them all into a globally consistent // reconstruction. This is especially useful for larger-scale scenes, since // incremental mapping becomes slow with an increasing number of images. class HierarchicalMapperController : public BaseController { public: struct Options { // The path to the image folder which are used as input. std::string image_path; // The path to the database file which is used as input. std::string database_path; // The maximum number of trials to initialize a cluster. int init_num_trials = 10; // The number of workers used to reconstruct clusters in parallel. int num_workers = -1; // Options for clustering the scene graph. SceneClustering::Options clustering_options; // Options used to reconstruction each cluster individually. IncrementalMapperOptions incremental_options; bool Check() const; }; HierarchicalMapperController( const Options& options, std::shared_ptr reconstruction_manager); void Run() override; private: const Options options_; std::shared_ptr reconstruction_manager_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/hierarchical_mapper_test.cc000066400000000000000000000144641464745566500247070ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/hierarchical_mapper.h" #include "colmap/estimators/alignment.h" #include "colmap/scene/synthetic.h" #include "colmap/util/testing.h" #include namespace colmap { namespace { void ExpectEqualReconstructions(const Reconstruction& gt, const Reconstruction& computed, const double max_rotation_error_deg, const double max_proj_center_error, const double num_obs_tolerance) { EXPECT_EQ(computed.NumCameras(), gt.NumCameras()); EXPECT_EQ(computed.NumImages(), gt.NumImages()); EXPECT_EQ(computed.NumRegImages(), gt.NumRegImages()); EXPECT_GE(computed.ComputeNumObservations(), (1 - num_obs_tolerance) * gt.ComputeNumObservations()); Sim3d gtFromComputed; AlignReconstructionsViaProjCenters(computed, gt, /*max_proj_center_error=*/0.1, >FromComputed); const std::vector errors = ComputeImageAlignmentError(computed, gt, gtFromComputed); EXPECT_EQ(errors.size(), gt.NumImages()); for (const auto& error : errors) { EXPECT_LT(error.rotation_error_deg, max_rotation_error_deg); EXPECT_LT(error.proj_center_error, max_proj_center_error); } } TEST(HierarchicalMapperController, WithoutNoise) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 2; synthetic_dataset_options.num_images = 20; synthetic_dataset_options.num_points3D = 50; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, >_reconstruction, &database); auto reconstruction_manager = std::make_shared(); HierarchicalMapperController::Options mapper_options; mapper_options.database_path = database_path; mapper_options.clustering_options.leaf_max_num_images = 5; mapper_options.clustering_options.image_overlap = 3; HierarchicalMapperController mapper(mapper_options, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 1); ExpectEqualReconstructions(gt_reconstruction, *reconstruction_manager->Get(0), /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); } TEST(HierarchicalMapperController, MultiReconstruction) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction1; Reconstruction gt_reconstruction2; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 1; synthetic_dataset_options.num_images = 5; synthetic_dataset_options.num_points3D = 50; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, >_reconstruction1, &database); synthetic_dataset_options.num_images = 4; SynthesizeDataset(synthetic_dataset_options, >_reconstruction2, &database); auto reconstruction_manager = std::make_shared(); HierarchicalMapperController::Options mapper_options; mapper_options.database_path = database_path; mapper_options.clustering_options.leaf_max_num_images = 5; mapper_options.clustering_options.image_overlap = 3; HierarchicalMapperController mapper(mapper_options, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 2); Reconstruction* computed_reconstruction1 = nullptr; Reconstruction* computed_reconstruction2 = nullptr; if (reconstruction_manager->Get(0)->NumRegImages() == 5) { computed_reconstruction1 = reconstruction_manager->Get(0).get(); computed_reconstruction2 = reconstruction_manager->Get(1).get(); } else { computed_reconstruction1 = reconstruction_manager->Get(1).get(); computed_reconstruction2 = reconstruction_manager->Get(0).get(); } ExpectEqualReconstructions(gt_reconstruction1, *computed_reconstruction1, /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); ExpectEqualReconstructions(gt_reconstruction2, *computed_reconstruction2, /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); } } // namespace } // namespace colmap colmap-3.10/src/colmap/controllers/image_reader.cc000066400000000000000000000257041464745566500222710ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/image_reader.h" #include "colmap/sensor/models.h" #include "colmap/util/misc.h" namespace colmap { bool ImageReaderOptions::Check() const { CHECK_OPTION_GT(default_focal_length_factor, 0.0); CHECK_OPTION(ExistsCameraModelWithName(camera_model)); const CameraModelId model_id = CameraModelNameToId(camera_model); if (!camera_params.empty()) { CHECK_OPTION( CameraModelVerifyParams(model_id, CSVToVector(camera_params))); } return true; } ImageReader::ImageReader(const ImageReaderOptions& options, Database* database) : options_(options), database_(database), image_index_(0) { THROW_CHECK(options_.Check()); // Ensure trailing slash, so that we can build the correct image name. options_.image_path = EnsureTrailingSlash(StringReplace(options_.image_path, "\\", "/")); options_.mask_path = EnsureTrailingSlash(StringReplace(options_.mask_path, "\\", "/")); // Get a list of all files in the image path, sorted by image name. if (options_.image_list.empty()) { options_.image_list = GetRecursiveFileList(options_.image_path); std::sort(options_.image_list.begin(), options_.image_list.end()); } else { if (!std::is_sorted(options_.image_list.begin(), options_.image_list.end())) { std::sort(options_.image_list.begin(), options_.image_list.end()); } for (auto& image_name : options_.image_list) { image_name = JoinPaths(options_.image_path, image_name); } } if (static_cast(options_.existing_camera_id) != kInvalidCameraId) { THROW_CHECK(database->ExistsCamera(options_.existing_camera_id)); prev_camera_ = database->ReadCamera(options_.existing_camera_id); } else { // Set the manually specified camera parameters. prev_camera_.camera_id = kInvalidCameraId; THROW_CHECK(ExistsCameraModelWithName(options_.camera_model)); prev_camera_.model_id = CameraModelNameToId(options_.camera_model); prev_camera_.params.resize(CameraModelNumParams(prev_camera_.model_id), 0.); if (!options_.camera_params.empty()) { THROW_CHECK(prev_camera_.SetParamsFromString(options_.camera_params)); prev_camera_.has_prior_focal_length = true; } } } ImageReader::Status ImageReader::Next(Camera* camera, Image* image, PosePrior* pose_prior, Bitmap* bitmap, Bitmap* mask) { THROW_CHECK_NOTNULL(camera); THROW_CHECK_NOTNULL(image); THROW_CHECK_NOTNULL(bitmap); image_index_ += 1; THROW_CHECK_LE(image_index_, options_.image_list.size()); const std::string image_path = options_.image_list.at(image_index_ - 1); DatabaseTransaction database_transaction(database_); ////////////////////////////////////////////////////////////////////////////// // Set the image name. ////////////////////////////////////////////////////////////////////////////// image->SetName(image_path); image->SetName(StringReplace(image->Name(), "\\", "/")); image->SetName( image->Name().substr(options_.image_path.size(), image->Name().size() - options_.image_path.size())); const std::string image_folder = GetParentDir(image->Name()); ////////////////////////////////////////////////////////////////////////////// // Check if image already read. ////////////////////////////////////////////////////////////////////////////// const bool exists_image = database_->ExistsImageWithName(image->Name()); if (exists_image) { *image = database_->ReadImageWithName(image->Name()); const bool exists_keypoints = database_->ExistsKeypoints(image->ImageId()); const bool exists_descriptors = database_->ExistsDescriptors(image->ImageId()); if (exists_keypoints && exists_descriptors) { return Status::IMAGE_EXISTS; } } ////////////////////////////////////////////////////////////////////////////// // Read image. ////////////////////////////////////////////////////////////////////////////// if (!bitmap->Read(image_path, false)) { return Status::BITMAP_ERROR; } ////////////////////////////////////////////////////////////////////////////// // Read mask. ////////////////////////////////////////////////////////////////////////////// if (mask && !options_.mask_path.empty()) { const std::string mask_path = JoinPaths(options_.mask_path, image->Name() + ".png"); if (ExistsFile(mask_path) && !mask->Read(mask_path, false)) { // NOTE: Maybe introduce a separate error type MASK_ERROR? return Status::BITMAP_ERROR; } } ////////////////////////////////////////////////////////////////////////////// // Check for well-formed data. ////////////////////////////////////////////////////////////////////////////// if (exists_image) { Camera current_camera = database_->ReadCamera(image->CameraId()); if (options_.single_camera && prev_camera_.camera_id != kInvalidCameraId && (current_camera.width != prev_camera_.width || current_camera.height != prev_camera_.height)) { return Status::CAMERA_SINGLE_DIM_ERROR; } if (static_cast(bitmap->Width()) != current_camera.width || static_cast(bitmap->Height()) != current_camera.height) { return Status::CAMERA_EXIST_DIM_ERROR; } prev_camera_ = std::move(current_camera); } else { ////////////////////////////////////////////////////////////////////////////// // Check image dimensions. ////////////////////////////////////////////////////////////////////////////// if (prev_camera_.camera_id != kInvalidCameraId && ((options_.single_camera && !options_.single_camera_per_folder) || (options_.single_camera_per_folder && image_folder == prev_image_folder_)) && (prev_camera_.width != static_cast(bitmap->Width()) || prev_camera_.height != static_cast(bitmap->Height()))) { return Status::CAMERA_SINGLE_DIM_ERROR; } ////////////////////////////////////////////////////////////////////////////// // Read camera model and check for consistency if it exists ////////////////////////////////////////////////////////////////////////////// std::string camera_model; const bool valid_camera_model = bitmap->ExifCameraModel(&camera_model); if (camera_model_to_id_.count(camera_model) > 0) { Camera camera = database_->ReadCamera(camera_model_to_id_.at(camera_model)); if (camera.width != static_cast(bitmap->Width()) || camera.height != static_cast(bitmap->Height())) { return Status::CAMERA_EXIST_DIM_ERROR; } prev_camera_ = std::move(camera); } ////////////////////////////////////////////////////////////////////////////// // Extract camera model and focal length ////////////////////////////////////////////////////////////////////////////// if (prev_camera_.camera_id == kInvalidCameraId || options_.single_camera_per_image || (!options_.single_camera && !options_.single_camera_per_folder && static_cast(options_.existing_camera_id) == kInvalidCameraId && camera_model_to_id_.count(camera_model) == 0) || (options_.single_camera_per_folder && image_folders_.count(image_folder) == 0)) { if (options_.camera_params.empty()) { // Extract focal length. double focal_length = 0.0; bool has_focal_length = false; if (bitmap->ExifFocalLength(&focal_length)) { has_focal_length = true; } else { focal_length = options_.default_focal_length_factor * std::max(bitmap->Width(), bitmap->Height()); } prev_camera_ = Camera::CreateFromModelId(prev_camera_.camera_id, prev_camera_.model_id, focal_length, bitmap->Width(), bitmap->Height()); prev_camera_.has_prior_focal_length = has_focal_length; } prev_camera_.width = static_cast(bitmap->Width()); prev_camera_.height = static_cast(bitmap->Height()); if (!prev_camera_.VerifyParams()) { return Status::CAMERA_PARAM_ERROR; } prev_camera_.camera_id = database_->WriteCamera(prev_camera_); if (valid_camera_model) { camera_model_to_id_[camera_model] = prev_camera_.camera_id; } } image->SetCameraId(prev_camera_.camera_id); ////////////////////////////////////////////////////////////////////////////// // Extract GPS data. ////////////////////////////////////////////////////////////////////////////// Eigen::Vector3d position_prior; if (bitmap->ExifLatitude(&position_prior.x()) && bitmap->ExifLongitude(&position_prior.y()) && bitmap->ExifAltitude(&position_prior.z())) { pose_prior->position = position_prior; pose_prior->coordinate_system = PosePrior::CoordinateSystem::WGS84; } } *camera = prev_camera_; image_folders_.insert(image_folder); prev_image_folder_ = image_folder; return Status::SUCCESS; } size_t ImageReader::NextIndex() const { return image_index_; } size_t ImageReader::NumImages() const { return options_.image_list.size(); } } // namespace colmap colmap-3.10/src/colmap/controllers/image_reader.h000066400000000000000000000117401464745566500221260ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/geometry/gps.h" #include "colmap/scene/database.h" #include "colmap/sensor/bitmap.h" #include "colmap/util/threading.h" #include namespace colmap { struct ImageReaderOptions { // Path to database in which to store the extracted data. std::string database_path = ""; // Root path to folder which contains the images. std::string image_path = ""; // Optional root path to folder which contains image masks. For a given image, // the corresponding mask must have the same sub-path below this root as the // image has below image_path. The filename must be equal, aside from the // added extension .png. For example, for an image image_path/abc/012.jpg, the // mask would be mask_path/abc/012.jpg.png. No features will be extracted in // regions where the mask image is black (pixel intensity value 0 in // grayscale). std::string mask_path = ""; // Optional list of images to read. The list must contain the relative path // of the images with respect to the image_path. std::vector image_list; // Name of the camera model. std::string camera_model = "SIMPLE_RADIAL"; // Whether to use the same camera for all images. bool single_camera = false; // Whether to use the same camera for all images in the same sub-folder. bool single_camera_per_folder = false; // Whether to use a different camera for each image. bool single_camera_per_image = false; // Whether to explicitly use an existing camera for all images. Note that in // this case the specified camera model and parameters are ignored. int existing_camera_id = kInvalidCameraId; // Manual specification of camera parameters. If empty, camera parameters // will be extracted from EXIF, i.e. principal point and focal length. std::string camera_params = ""; // If camera parameters are not specified manually and the image does not // have focal length EXIF information, the focal length is set to the // value `default_focal_length_factor * max(width, height)`. double default_focal_length_factor = 1.2; // Optional path to an image file specifying a mask for all images. No // features will be extracted in regions where the mask is black (pixel // intensity value 0 in grayscale). std::string camera_mask_path = ""; bool Check() const; }; // Recursively iterate over the images in a directory. Skips an image if it // already exists in the database. Extracts the camera intrinsics from EXIF and // writes the camera information to the database. class ImageReader { public: enum class Status { FAILURE, SUCCESS, IMAGE_EXISTS, BITMAP_ERROR, CAMERA_SINGLE_DIM_ERROR, CAMERA_EXIST_DIM_ERROR, CAMERA_PARAM_ERROR }; ImageReader(const ImageReaderOptions& options, Database* database); Status Next(Camera* camera, Image* image, PosePrior* pose_prior, Bitmap* bitmap, Bitmap* mask); size_t NextIndex() const; size_t NumImages() const; private: // Image reader options. ImageReaderOptions options_; Database* database_; // Index of previously processed image. size_t image_index_; // Previously processed camera. Camera prev_camera_; std::unordered_map camera_model_to_id_; // Names of image sub-folders. std::string prev_image_folder_; std::unordered_set image_folders_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/incremental_mapper.cc000066400000000000000000000542271464745566500235340ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/incremental_mapper.h" #include "colmap/util/misc.h" #include "colmap/util/timer.h" namespace colmap { namespace { void IterativeGlobalRefinement(const IncrementalMapperOptions& options, const IncrementalMapper::Options& mapper_options, IncrementalMapper& mapper) { LOG(INFO) << "Retriangulation and Global bundle adjustment"; mapper.IterativeGlobalRefinement(options.ba_global_max_refinements, options.ba_global_max_refinement_change, mapper_options, options.GlobalBundleAdjustment(), options.Triangulation()); mapper.FilterImages(mapper_options); } void ExtractColors(const std::string& image_path, const image_t image_id, Reconstruction& reconstruction) { if (!reconstruction.ExtractColorsForImage(image_id, image_path)) { LOG(WARNING) << StringPrintf("Could not read image %s at path %s.", reconstruction.Image(image_id).Name().c_str(), image_path.c_str()); } } void WriteSnapshot(const Reconstruction& reconstruction, const std::string& snapshot_path) { LOG(INFO) << "Creating snapshot"; // Get the current timestamp in milliseconds. const size_t timestamp = std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); // Write reconstruction to unique path with current timestamp. const std::string path = JoinPaths(snapshot_path, StringPrintf("%010d", timestamp)); CreateDirIfNotExists(path); VLOG(1) << "=> Writing to " << path; reconstruction.Write(path); } } // namespace IncrementalMapper::Options IncrementalMapperOptions::Mapper() const { IncrementalMapper::Options options = mapper; options.abs_pose_refine_focal_length = ba_refine_focal_length; options.abs_pose_refine_extra_params = ba_refine_extra_params; options.min_focal_length_ratio = min_focal_length_ratio; options.max_focal_length_ratio = max_focal_length_ratio; options.max_extra_param = max_extra_param; options.num_threads = num_threads; options.local_ba_num_images = ba_local_num_images; options.fix_existing_images = fix_existing_images; return options; } IncrementalTriangulator::Options IncrementalMapperOptions::Triangulation() const { IncrementalTriangulator::Options options = triangulation; options.min_focal_length_ratio = min_focal_length_ratio; options.max_focal_length_ratio = max_focal_length_ratio; options.max_extra_param = max_extra_param; return options; } BundleAdjustmentOptions IncrementalMapperOptions::LocalBundleAdjustment() const { BundleAdjustmentOptions options; options.solver_options.function_tolerance = ba_local_function_tolerance; options.solver_options.gradient_tolerance = 10.0; options.solver_options.parameter_tolerance = 0.0; options.solver_options.max_num_iterations = ba_local_max_num_iterations; options.solver_options.max_linear_solver_iterations = 100; options.solver_options.logging_type = ceres::LoggingType::SILENT; options.solver_options.num_threads = num_threads; #if CERES_VERSION_MAJOR < 2 options.solver_options.num_linear_solver_threads = num_threads; #endif // CERES_VERSION_MAJOR options.print_summary = false; options.refine_focal_length = ba_refine_focal_length; options.refine_principal_point = ba_refine_principal_point; options.refine_extra_params = ba_refine_extra_params; options.min_num_residuals_for_multi_threading = ba_min_num_residuals_for_multi_threading; options.loss_function_scale = 1.0; options.loss_function_type = BundleAdjustmentOptions::LossFunctionType::SOFT_L1; return options; } BundleAdjustmentOptions IncrementalMapperOptions::GlobalBundleAdjustment() const { BundleAdjustmentOptions options; options.solver_options.function_tolerance = ba_global_function_tolerance; options.solver_options.gradient_tolerance = 1.0; options.solver_options.parameter_tolerance = 0.0; options.solver_options.max_num_iterations = ba_global_max_num_iterations; options.solver_options.max_linear_solver_iterations = 100; options.solver_options.logging_type = ceres::LoggingType::PER_MINIMIZER_ITERATION; options.solver_options.minimizer_progress_to_stdout = false; options.solver_options.num_threads = num_threads; #if CERES_VERSION_MAJOR < 2 options.solver_options.num_linear_solver_threads = num_threads; #endif // CERES_VERSION_MAJOR options.print_summary = false; options.refine_focal_length = ba_refine_focal_length; options.refine_principal_point = ba_refine_principal_point; options.refine_extra_params = ba_refine_extra_params; options.min_num_residuals_for_multi_threading = ba_min_num_residuals_for_multi_threading; options.loss_function_type = BundleAdjustmentOptions::LossFunctionType::TRIVIAL; return options; } bool IncrementalMapperOptions::Check() const { CHECK_OPTION_GT(min_num_matches, 0); CHECK_OPTION_GT(max_num_models, 0); CHECK_OPTION_GT(max_model_overlap, 0); CHECK_OPTION_GE(min_model_size, 0); CHECK_OPTION_GT(init_num_trials, 0); CHECK_OPTION_GT(min_focal_length_ratio, 0); CHECK_OPTION_GT(max_focal_length_ratio, 0); CHECK_OPTION_GE(max_extra_param, 0); CHECK_OPTION_GE(ba_local_num_images, 2); CHECK_OPTION_GE(ba_local_max_num_iterations, 0); CHECK_OPTION_GT(ba_global_images_ratio, 1.0); CHECK_OPTION_GT(ba_global_points_ratio, 1.0); CHECK_OPTION_GT(ba_global_images_freq, 0); CHECK_OPTION_GT(ba_global_points_freq, 0); CHECK_OPTION_GT(ba_global_max_num_iterations, 0); CHECK_OPTION_GT(ba_local_max_refinements, 0); CHECK_OPTION_GE(ba_local_max_refinement_change, 0); CHECK_OPTION_GT(ba_global_max_refinements, 0); CHECK_OPTION_GE(ba_global_max_refinement_change, 0); CHECK_OPTION_GE(snapshot_images_freq, 0); CHECK_OPTION(Mapper().Check()); CHECK_OPTION(Triangulation().Check()); return true; } IncrementalMapperController::IncrementalMapperController( std::shared_ptr options, const std::string& image_path, const std::string& database_path, std::shared_ptr reconstruction_manager) : options_(std::move(options)), image_path_(image_path), database_path_(database_path), reconstruction_manager_(std::move(reconstruction_manager)) { THROW_CHECK(options_->Check()); RegisterCallback(INITIAL_IMAGE_PAIR_REG_CALLBACK); RegisterCallback(NEXT_IMAGE_REG_CALLBACK); RegisterCallback(LAST_IMAGE_REG_CALLBACK); } void IncrementalMapperController::Run() { Timer run_timer; run_timer.Start(); if (!LoadDatabase()) { return; } IncrementalMapper::Options init_mapper_options = options_->Mapper(); Reconstruct(init_mapper_options); const size_t kNumInitRelaxations = 2; for (size_t i = 0; i < kNumInitRelaxations; ++i) { if (reconstruction_manager_->Size() > 0 || CheckIfStopped()) { break; } LOG(INFO) << "=> Relaxing the initialization constraints."; init_mapper_options.init_min_num_inliers /= 2; Reconstruct(init_mapper_options); if (reconstruction_manager_->Size() > 0 || CheckIfStopped()) { break; } LOG(INFO) << "=> Relaxing the initialization constraints."; init_mapper_options.init_min_tri_angle /= 2; Reconstruct(init_mapper_options); } run_timer.PrintMinutes(); } bool IncrementalMapperController::LoadDatabase() { LOG(INFO) << "Loading database"; // Make sure images of the given reconstruction are also included when // manually specifying images for the reconstruction procedure. std::unordered_set image_names = options_->image_names; if (reconstruction_manager_->Size() == 1 && !options_->image_names.empty()) { const auto& reconstruction = reconstruction_manager_->Get(0); for (const image_t image_id : reconstruction->RegImageIds()) { const auto& image = reconstruction->Image(image_id); image_names.insert(image.Name()); } } Database database(database_path_); Timer timer; timer.Start(); const size_t min_num_matches = static_cast(options_->min_num_matches); database_cache_ = DatabaseCache::Create( database, min_num_matches, options_->ignore_watermarks, image_names); timer.PrintMinutes(); if (database_cache_->NumImages() == 0) { LOG(WARNING) << "No images with matches found in the database"; return false; } return true; } IncrementalMapperController::Status IncrementalMapperController::InitializeReconstruction( IncrementalMapper& mapper, const IncrementalMapper::Options& mapper_options, Reconstruction& reconstruction) { image_t image_id1 = static_cast(options_->init_image_id1); image_t image_id2 = static_cast(options_->init_image_id2); // Try to find good initial pair. TwoViewGeometry two_view_geometry; if (!options_->IsInitialPairProvided()) { LOG(INFO) << "Finding good initial image pair"; const bool find_init_success = mapper.FindInitialImagePair( mapper_options, two_view_geometry, image_id1, image_id2); if (!find_init_success) { LOG(INFO) << "=> No good initial image pair found."; return Status::NO_INITIAL_PAIR; } } else { if (!reconstruction.ExistsImage(image_id1) || !reconstruction.ExistsImage(image_id2)) { LOG(INFO) << StringPrintf( "=> Initial image pair #%d and #%d do not exist.", image_id1, image_id2); return Status::BAD_INITIAL_PAIR; } const bool provided_init_success = mapper.EstimateInitialTwoViewGeometry( mapper_options, two_view_geometry, image_id1, image_id2); if (!provided_init_success) { LOG(INFO) << "Provided pair is insuitable for intialization."; return Status::BAD_INITIAL_PAIR; } } LOG(INFO) << StringPrintf( "Initializing with image pair #%d and #%d", image_id1, image_id2); mapper.RegisterInitialImagePair( mapper_options, two_view_geometry, image_id1, image_id2); LOG(INFO) << "Global bundle adjustment"; mapper.AdjustGlobalBundle(mapper_options, options_->GlobalBundleAdjustment()); reconstruction.Normalize(); mapper.FilterPoints(mapper_options); mapper.FilterImages(mapper_options); // Initial image pair failed to register. if (reconstruction.NumRegImages() == 0 || reconstruction.NumPoints3D() == 0) { return Status::BAD_INITIAL_PAIR; } if (options_->extract_colors) { ExtractColors(image_path_, image_id1, reconstruction); } return Status::SUCCESS; } bool IncrementalMapperController::CheckRunGlobalRefinement( const Reconstruction& reconstruction, const size_t ba_prev_num_reg_images, const size_t ba_prev_num_points) { return reconstruction.NumRegImages() >= options_->ba_global_images_ratio * ba_prev_num_reg_images || reconstruction.NumRegImages() >= options_->ba_global_images_freq + ba_prev_num_reg_images || reconstruction.NumPoints3D() >= options_->ba_global_points_ratio * ba_prev_num_points || reconstruction.NumPoints3D() >= options_->ba_global_points_freq + ba_prev_num_points; } IncrementalMapperController::Status IncrementalMapperController::ReconstructSubModel( IncrementalMapper& mapper, const IncrementalMapper::Options& mapper_options, const std::shared_ptr& reconstruction) { mapper.BeginReconstruction(reconstruction); //////////////////////////////////////////////////////////////////////////// // Register initial pair //////////////////////////////////////////////////////////////////////////// if (reconstruction->NumRegImages() == 0) { const Status init_status = IncrementalMapperController::InitializeReconstruction( mapper, mapper_options, *reconstruction); if (init_status != Status::SUCCESS) { return init_status; } } Callback(INITIAL_IMAGE_PAIR_REG_CALLBACK); //////////////////////////////////////////////////////////////////////////// // Incremental mapping //////////////////////////////////////////////////////////////////////////// size_t snapshot_prev_num_reg_images = reconstruction->NumRegImages(); size_t ba_prev_num_reg_images = reconstruction->NumRegImages(); size_t ba_prev_num_points = reconstruction->NumPoints3D(); bool reg_next_success = true; bool prev_reg_next_success = true; do { if (CheckIfStopped()) { break; } prev_reg_next_success = reg_next_success; reg_next_success = false; const std::vector next_images = mapper.FindNextImages(mapper_options); if (next_images.empty()) { break; } image_t next_image_id; for (size_t reg_trial = 0; reg_trial < next_images.size(); ++reg_trial) { next_image_id = next_images[reg_trial]; LOG(INFO) << StringPrintf("Registering image #%d (%d)", next_image_id, reconstruction->NumRegImages() + 1); LOG(INFO) << StringPrintf( "=> Image sees %d / %d points", mapper.ObservationManager().NumVisiblePoints3D(next_image_id), mapper.ObservationManager().NumObservations(next_image_id)); reg_next_success = mapper.RegisterNextImage(mapper_options, next_image_id); if (reg_next_success) { break; } else { LOG(INFO) << "=> Could not register, trying another image."; // If initial pair fails to continue for some time, // abort and try different initial pair. const size_t kMinNumInitialRegTrials = 30; if (reg_trial >= kMinNumInitialRegTrials && reconstruction->NumRegImages() < static_cast(options_->min_model_size)) { break; } } } if (reg_next_success) { mapper.TriangulateImage(options_->Triangulation(), next_image_id); mapper.IterativeLocalRefinement(options_->ba_local_max_refinements, options_->ba_local_max_refinement_change, mapper_options, options_->LocalBundleAdjustment(), options_->Triangulation(), next_image_id); if (CheckRunGlobalRefinement( *reconstruction, ba_prev_num_reg_images, ba_prev_num_points)) { IterativeGlobalRefinement(*options_, mapper_options, mapper); ba_prev_num_points = reconstruction->NumPoints3D(); ba_prev_num_reg_images = reconstruction->NumRegImages(); } if (options_->extract_colors) { ExtractColors(image_path_, next_image_id, *reconstruction); } if (options_->snapshot_images_freq > 0 && reconstruction->NumRegImages() >= options_->snapshot_images_freq + snapshot_prev_num_reg_images) { snapshot_prev_num_reg_images = reconstruction->NumRegImages(); WriteSnapshot(*reconstruction, options_->snapshot_path); } Callback(NEXT_IMAGE_REG_CALLBACK); } const size_t max_model_overlap = static_cast(options_->max_model_overlap); if (mapper.NumSharedRegImages() >= max_model_overlap) { break; } // If no image could be registered, try a single final global iterative // bundle adjustment and try again to register one image. If this fails // once, then exit the incremental mapping. if (!reg_next_success && prev_reg_next_success) { IterativeGlobalRefinement(*options_, mapper_options, mapper); } } while (reg_next_success || prev_reg_next_success); if (CheckIfStopped()) { return Status::INTERRUPTED; } // Only run final global BA, if last incremental BA was not global. if (reconstruction->NumRegImages() >= 2 && reconstruction->NumRegImages() != ba_prev_num_reg_images && reconstruction->NumPoints3D() != ba_prev_num_points) { IterativeGlobalRefinement(*options_, mapper_options, mapper); } return Status::SUCCESS; } void IncrementalMapperController::Reconstruct( const IncrementalMapper::Options& mapper_options) { IncrementalMapper mapper(database_cache_); // Is there a sub-model before we start the reconstruction? I.e. the user // has imported an existing reconstruction. const bool initial_reconstruction_given = reconstruction_manager_->Size() > 0; THROW_CHECK_LE(reconstruction_manager_->Size(), 1) << "Can only resume from a " "single reconstruction, but " "multiple are given."; for (int num_trials = 0; num_trials < options_->init_num_trials; ++num_trials) { if (CheckIfStopped()) { break; } size_t reconstruction_idx; if (!initial_reconstruction_given || num_trials > 0) { reconstruction_idx = reconstruction_manager_->Add(); } else { reconstruction_idx = 0; } std::shared_ptr reconstruction = reconstruction_manager_->Get(reconstruction_idx); const Status status = ReconstructSubModel(mapper, mapper_options, reconstruction); switch (status) { case Status::INTERRUPTED: mapper.EndReconstruction(/*discard=*/false); return; case Status::NO_INITIAL_PAIR: case Status::BAD_INITIAL_PAIR: mapper.EndReconstruction(/*discard=*/true); reconstruction_manager_->Delete(reconstruction_idx); // If both initial images are manually specified, there is no need for // further initialization trials. if (options_->IsInitialPairProvided()) { return; } break; case Status::SUCCESS: { // Remember the total number of registered images before potentially // discarding it below due to small size, so we can out of the main // loop, if all images were registered. const size_t total_num_reg_images = mapper.NumTotalRegImages(); // If the total number of images is small then do not enforce the // minimum model size so that we can reconstruct small image // collections. Always keep the first reconstruction, independent of // size. const size_t min_model_size = std::min( 0.8 * database_cache_->NumImages(), options_->min_model_size); if ((options_->multiple_models && reconstruction_manager_->Size() > 1 && reconstruction->NumRegImages() < min_model_size) || reconstruction->NumRegImages() == 0) { mapper.EndReconstruction(/*discard=*/true); reconstruction_manager_->Delete(reconstruction_idx); } else { mapper.EndReconstruction(/*discard=*/false); } Callback(LAST_IMAGE_REG_CALLBACK); if (initial_reconstruction_given || !options_->multiple_models || reconstruction_manager_->Size() >= static_cast(options_->max_num_models) || total_num_reg_images >= database_cache_->NumImages() - 1) { return; } } break; default: LOG(FATAL_THROW) << "Unknown reconstruction status."; } } } void IncrementalMapperController::TriangulateReconstruction( const std::shared_ptr& reconstruction) { THROW_CHECK(LoadDatabase()); IncrementalMapper mapper(database_cache_); mapper.BeginReconstruction(reconstruction); LOG(INFO) << "Iterative triangulation"; const std::vector& reg_image_ids = reconstruction->RegImageIds(); for (size_t i = 0; i < reg_image_ids.size(); ++i) { const image_t image_id = reg_image_ids[i]; const auto& image = reconstruction->Image(image_id); LOG(INFO) << StringPrintf("Triangulating image #%d (%d)", image_id, i); const size_t num_existing_points3D = image.NumPoints3D(); LOG(INFO) << "=> Image sees " << num_existing_points3D << " / " << mapper.ObservationManager().NumObservations(image_id) << " points"; mapper.TriangulateImage(options_->Triangulation(), image_id); VLOG(1) << "=> Triangulated " << (image.NumPoints3D() - num_existing_points3D) << " points"; } LOG(INFO) << "Retriangulation and Global bundle adjustment"; mapper.IterativeGlobalRefinement(options_->ba_global_max_refinements, options_->ba_global_max_refinement_change, options_->Mapper(), options_->GlobalBundleAdjustment(), options_->Triangulation(), /*normalize_reconstruction=*/false); mapper.EndReconstruction(/*discard=*/false); LOG(INFO) << "Extracting colors"; reconstruction->ExtractColorsForAllImages(image_path_); } } // namespace colmap colmap-3.10/src/colmap/controllers/incremental_mapper.h000066400000000000000000000172621464745566500233740ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/scene/reconstruction_manager.h" #include "colmap/sfm/incremental_mapper.h" #include "colmap/util/base_controller.h" namespace colmap { struct IncrementalMapperOptions { // The minimum number of matches for inlier matches to be considered. int min_num_matches = 15; // Whether to ignore the inlier matches of watermark image pairs. bool ignore_watermarks = false; // Whether to reconstruct multiple sub-models. bool multiple_models = true; // The number of sub-models to reconstruct. int max_num_models = 50; // The maximum number of overlapping images between sub-models. If the // current sub-models shares more than this number of images with another // model, then the reconstruction is stopped. int max_model_overlap = 20; // The minimum number of registered images of a sub-model, otherwise the // sub-model is discarded. Note that the first sub-model is always kept // independent of size. int min_model_size = 10; // The image identifiers used to initialize the reconstruction. Note that // only one or both image identifiers can be specified. In the former case, // the second image is automatically determined. int init_image_id1 = -1; int init_image_id2 = -1; // The number of trials to initialize the reconstruction. int init_num_trials = 200; // Whether to extract colors for reconstructed points. bool extract_colors = true; // The number of threads to use during reconstruction. int num_threads = -1; // Thresholds for filtering images with degenerate intrinsics. double min_focal_length_ratio = 0.1; double max_focal_length_ratio = 10.0; double max_extra_param = 1.0; // Which intrinsic parameters to optimize during the reconstruction. bool ba_refine_focal_length = true; bool ba_refine_principal_point = false; bool ba_refine_extra_params = true; // The minimum number of residuals per bundle adjustment problem to // enable multi-threading solving of the problems. int ba_min_num_residuals_for_multi_threading = 50000; // The number of images to optimize in local bundle adjustment. int ba_local_num_images = 6; // Ceres solver function tolerance for local bundle adjustment double ba_local_function_tolerance = 0.0; // The maximum number of local bundle adjustment iterations. int ba_local_max_num_iterations = 25; // The growth rates after which to perform global bundle adjustment. double ba_global_images_ratio = 1.1; double ba_global_points_ratio = 1.1; int ba_global_images_freq = 500; int ba_global_points_freq = 250000; // Ceres solver function tolerance for global bundle adjustment double ba_global_function_tolerance = 0.0; // The maximum number of global bundle adjustment iterations. int ba_global_max_num_iterations = 50; // The thresholds for iterative bundle adjustment refinements. int ba_local_max_refinements = 2; double ba_local_max_refinement_change = 0.001; int ba_global_max_refinements = 5; double ba_global_max_refinement_change = 0.0005; // Path to a folder with reconstruction snapshots during incremental // reconstruction. Snapshots will be saved according to the specified // frequency of registered images. std::string snapshot_path = ""; int snapshot_images_freq = 0; // Which images to reconstruct. If no images are specified, all images will // be reconstructed by default. std::unordered_set image_names; // If reconstruction is provided as input, fix the existing image poses. bool fix_existing_images = false; IncrementalMapper::Options mapper; IncrementalTriangulator::Options triangulation; IncrementalMapper::Options Mapper() const; IncrementalTriangulator::Options Triangulation() const; BundleAdjustmentOptions LocalBundleAdjustment() const; BundleAdjustmentOptions GlobalBundleAdjustment() const; inline bool IsInitialPairProvided() const { return init_image_id1 != -1 && init_image_id2 != -1; } bool Check() const; }; // Class that controls the incremental mapping procedure by iteratively // initializing reconstructions from the same scene graph. class IncrementalMapperController : public BaseController { public: enum CallbackType { INITIAL_IMAGE_PAIR_REG_CALLBACK, NEXT_IMAGE_REG_CALLBACK, LAST_IMAGE_REG_CALLBACK, }; enum class Status { NO_INITIAL_PAIR, BAD_INITIAL_PAIR, SUCCESS, INTERRUPTED }; IncrementalMapperController( std::shared_ptr options, const std::string& image_path, const std::string& database_path, std::shared_ptr reconstruction_manager); void Run(); void TriangulateReconstruction( const std::shared_ptr& reconstruction); bool LoadDatabase(); // getter functions for python pipelines const std::string& ImagePath() const { return image_path_; } const std::string& DatabasePath() const { return database_path_; } const std::shared_ptr& Options() const { return options_; } const std::shared_ptr& ReconstructionManager() const { return reconstruction_manager_; } const std::shared_ptr& DatabaseCache() const { return database_cache_; } void Reconstruct(const IncrementalMapper::Options& init_mapper_options); Status ReconstructSubModel( IncrementalMapper& mapper, const IncrementalMapper::Options& mapper_options, const std::shared_ptr& reconstruction); Status InitializeReconstruction( IncrementalMapper& mapper, const IncrementalMapper::Options& mapper_options, Reconstruction& reconstruction); bool CheckRunGlobalRefinement(const Reconstruction& reconstruction, size_t ba_prev_num_reg_images, size_t ba_prev_num_points); private: const std::shared_ptr options_; const std::string image_path_; const std::string database_path_; std::shared_ptr reconstruction_manager_; std::shared_ptr database_cache_; }; } // namespace colmap colmap-3.10/src/colmap/controllers/incremental_mapper_test.cc000066400000000000000000000207321464745566500245650ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/incremental_mapper.h" #include "colmap/estimators/alignment.h" #include "colmap/scene/synthetic.h" #include "colmap/util/testing.h" #include namespace colmap { namespace { void ExpectEqualReconstructions(const Reconstruction& gt, const Reconstruction& computed, const double max_rotation_error_deg, const double max_proj_center_error, const double num_obs_tolerance) { EXPECT_EQ(computed.NumCameras(), gt.NumCameras()); EXPECT_EQ(computed.NumImages(), gt.NumImages()); EXPECT_EQ(computed.NumRegImages(), gt.NumRegImages()); EXPECT_GE(computed.ComputeNumObservations(), (1 - num_obs_tolerance) * gt.ComputeNumObservations()); Sim3d gtFromComputed; AlignReconstructionsViaProjCenters(computed, gt, /*max_proj_center_error=*/0.1, >FromComputed); const std::vector errors = ComputeImageAlignmentError(computed, gt, gtFromComputed); EXPECT_EQ(errors.size(), gt.NumImages()); for (const auto& error : errors) { EXPECT_LT(error.rotation_error_deg, max_rotation_error_deg); EXPECT_LT(error.proj_center_error, max_proj_center_error); } } TEST(IncrementalMapperController, WithoutNoise) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 2; synthetic_dataset_options.num_images = 7; synthetic_dataset_options.num_points3D = 50; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, >_reconstruction, &database); auto reconstruction_manager = std::make_shared(); IncrementalMapperController mapper( std::make_shared(), /*image_path=*/"", database_path, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 1); ExpectEqualReconstructions(gt_reconstruction, *reconstruction_manager->Get(0), /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); } TEST(IncrementalMapperController, WithNoise) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 2; synthetic_dataset_options.num_images = 7; synthetic_dataset_options.num_points3D = 100; synthetic_dataset_options.point2D_stddev = 0.5; SynthesizeDataset(synthetic_dataset_options, >_reconstruction, &database); auto reconstruction_manager = std::make_shared(); IncrementalMapperController mapper( std::make_shared(), /*image_path=*/"", database_path, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 1); ExpectEqualReconstructions(gt_reconstruction, *reconstruction_manager->Get(0), /*max_rotation_error_deg=*/1e-1, /*max_proj_center_error=*/1e-1, /*num_obs_tolerance=*/0.02); } TEST(IncrementalMapperController, MultiReconstruction) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction1; Reconstruction gt_reconstruction2; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 1; synthetic_dataset_options.num_images = 5; synthetic_dataset_options.num_points3D = 50; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, >_reconstruction1, &database); synthetic_dataset_options.num_images = 4; SynthesizeDataset(synthetic_dataset_options, >_reconstruction2, &database); auto reconstruction_manager = std::make_shared(); auto mapper_options = std::make_shared(); mapper_options->min_model_size = 4; IncrementalMapperController mapper(mapper_options, /*image_path=*/"", database_path, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 2); Reconstruction* computed_reconstruction1 = nullptr; Reconstruction* computed_reconstruction2 = nullptr; if (reconstruction_manager->Get(0)->NumRegImages() == 5) { computed_reconstruction1 = reconstruction_manager->Get(0).get(); computed_reconstruction2 = reconstruction_manager->Get(1).get(); } else { computed_reconstruction1 = reconstruction_manager->Get(1).get(); computed_reconstruction2 = reconstruction_manager->Get(0).get(); } ExpectEqualReconstructions(gt_reconstruction1, *computed_reconstruction1, /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); ExpectEqualReconstructions(gt_reconstruction2, *computed_reconstruction2, /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); } TEST(IncrementalMapperController, ChainedMatches) { const std::string database_path = CreateTestDir() + "/database.db"; Database database(database_path); Reconstruction gt_reconstruction; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.match_config = SyntheticDatasetOptions::MatchConfig::CHAINED; synthetic_dataset_options.num_cameras = 1; synthetic_dataset_options.num_images = 4; synthetic_dataset_options.num_points3D = 100; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, >_reconstruction, &database); auto reconstruction_manager = std::make_shared(); IncrementalMapperController mapper( std::make_shared(), /*image_path=*/"", database_path, reconstruction_manager); mapper.Run(); ASSERT_EQ(reconstruction_manager->Size(), 1); ExpectEqualReconstructions(gt_reconstruction, *reconstruction_manager->Get(0), /*max_rotation_error_deg=*/1e-2, /*max_proj_center_error=*/1e-4, /*num_obs_tolerance=*/0); } } // namespace } // namespace colmap colmap-3.10/src/colmap/controllers/option_manager.cc000066400000000000000000001216001464745566500226570ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/controllers/option_manager.h" #include "colmap/controllers/feature_extraction.h" #include "colmap/controllers/image_reader.h" #include "colmap/controllers/incremental_mapper.h" #include "colmap/estimators/bundle_adjustment.h" #include "colmap/estimators/two_view_geometry.h" #include "colmap/feature/pairing.h" #include "colmap/feature/sift.h" #include "colmap/math/random.h" #include "colmap/mvs/fusion.h" #include "colmap/mvs/meshing.h" #include "colmap/mvs/patch_match.h" #include "colmap/ui/render_options.h" #include "colmap/util/misc.h" #include "colmap/util/version.h" #include #include namespace config = boost::program_options; namespace colmap { OptionManager::OptionManager(bool add_project_options) { project_path = std::make_shared(); database_path = std::make_shared(); image_path = std::make_shared(); image_reader = std::make_shared(); sift_extraction = std::make_shared(); sift_matching = std::make_shared(); two_view_geometry = std::make_shared(); exhaustive_matching = std::make_shared(); sequential_matching = std::make_shared(); vocab_tree_matching = std::make_shared(); spatial_matching = std::make_shared(); transitive_matching = std::make_shared(); image_pairs_matching = std::make_shared(); bundle_adjustment = std::make_shared(); mapper = std::make_shared(); patch_match_stereo = std::make_shared(); stereo_fusion = std::make_shared(); poisson_meshing = std::make_shared(); delaunay_meshing = std::make_shared(); render = std::make_shared(); Reset(); desc_->add_options()("help,h", ""); AddRandomOptions(); AddLogOptions(); if (add_project_options) { desc_->add_options()("project_path", config::value()); } } void OptionManager::ModifyForIndividualData() { mapper->min_focal_length_ratio = 0.1; mapper->max_focal_length_ratio = 10; mapper->max_extra_param = std::numeric_limits::max(); } void OptionManager::ModifyForVideoData() { const bool kResetPaths = false; ResetOptions(kResetPaths); mapper->mapper.init_min_tri_angle /= 2; mapper->ba_global_images_ratio = 1.4; mapper->ba_global_points_ratio = 1.4; mapper->min_focal_length_ratio = 0.1; mapper->max_focal_length_ratio = 10; mapper->max_extra_param = std::numeric_limits::max(); stereo_fusion->min_num_pixels = 15; } void OptionManager::ModifyForInternetData() { stereo_fusion->min_num_pixels = 10; } void OptionManager::ModifyForLowQuality() { sift_extraction->max_image_size = 1000; sift_extraction->max_num_features = 2048; sequential_matching->loop_detection_num_images /= 2; vocab_tree_matching->num_images /= 2; mapper->ba_local_max_num_iterations /= 2; mapper->ba_global_max_num_iterations /= 2; mapper->ba_global_images_ratio *= 1.2; mapper->ba_global_points_ratio *= 1.2; mapper->ba_global_max_refinements = 2; patch_match_stereo->max_image_size = 1000; patch_match_stereo->window_radius = 4; patch_match_stereo->window_step = 2; patch_match_stereo->num_samples /= 2; patch_match_stereo->num_iterations = 3; patch_match_stereo->geom_consistency = false; stereo_fusion->check_num_images /= 2; stereo_fusion->max_image_size = 1000; } void OptionManager::ModifyForMediumQuality() { sift_extraction->max_image_size = 1600; sift_extraction->max_num_features = 4096; sequential_matching->loop_detection_num_images /= 1.5; vocab_tree_matching->num_images /= 1.5; mapper->ba_local_max_num_iterations /= 1.5; mapper->ba_global_max_num_iterations /= 1.5; mapper->ba_global_images_ratio *= 1.1; mapper->ba_global_points_ratio *= 1.1; mapper->ba_global_max_refinements = 2; patch_match_stereo->max_image_size = 1600; patch_match_stereo->window_radius = 4; patch_match_stereo->window_step = 2; patch_match_stereo->num_samples /= 1.5; patch_match_stereo->num_iterations = 5; patch_match_stereo->geom_consistency = false; stereo_fusion->check_num_images /= 1.5; stereo_fusion->max_image_size = 1600; } void OptionManager::ModifyForHighQuality() { sift_extraction->estimate_affine_shape = true; sift_extraction->max_image_size = 2400; sift_extraction->max_num_features = 8192; sift_matching->guided_matching = true; mapper->ba_local_max_num_iterations = 30; mapper->ba_local_max_refinements = 3; mapper->ba_global_max_num_iterations = 75; patch_match_stereo->max_image_size = 2400; stereo_fusion->max_image_size = 2400; } void OptionManager::ModifyForExtremeQuality() { // Most of the options are set to extreme quality by default. sift_extraction->estimate_affine_shape = true; sift_extraction->domain_size_pooling = true; sift_matching->guided_matching = true; mapper->ba_local_max_num_iterations = 40; mapper->ba_local_max_refinements = 3; mapper->ba_global_max_num_iterations = 100; } void OptionManager::AddAllOptions() { AddLogOptions(); AddRandomOptions(); AddDatabaseOptions(); AddImageOptions(); AddExtractionOptions(); AddMatchingOptions(); AddExhaustiveMatchingOptions(); AddSequentialMatchingOptions(); AddVocabTreeMatchingOptions(); AddSpatialMatchingOptions(); AddTransitiveMatchingOptions(); AddImagePairsMatchingOptions(); AddBundleAdjustmentOptions(); AddMapperOptions(); AddPatchMatchStereoOptions(); AddStereoFusionOptions(); AddPoissonMeshingOptions(); AddDelaunayMeshingOptions(); AddRenderOptions(); } void OptionManager::AddLogOptions() { if (added_log_options_) { return; } added_log_options_ = true; AddAndRegisterDefaultOption("log_to_stderr", &FLAGS_logtostderr); AddAndRegisterDefaultOption("log_level", &FLAGS_v); } void OptionManager::AddRandomOptions() { if (added_random_options_) { return; } added_random_options_ = true; AddAndRegisterDefaultOption("random_seed", &kDefaultPRNGSeed); } void OptionManager::AddDatabaseOptions() { if (added_database_options_) { return; } added_database_options_ = true; AddAndRegisterRequiredOption("database_path", database_path.get()); } void OptionManager::AddImageOptions() { if (added_image_options_) { return; } added_image_options_ = true; AddAndRegisterRequiredOption("image_path", image_path.get()); } void OptionManager::AddExtractionOptions() { if (added_extraction_options_) { return; } added_extraction_options_ = true; AddAndRegisterDefaultOption("ImageReader.mask_path", &image_reader->mask_path); AddAndRegisterDefaultOption("ImageReader.camera_model", &image_reader->camera_model); AddAndRegisterDefaultOption("ImageReader.single_camera", &image_reader->single_camera); AddAndRegisterDefaultOption("ImageReader.single_camera_per_folder", &image_reader->single_camera_per_folder); AddAndRegisterDefaultOption("ImageReader.single_camera_per_image", &image_reader->single_camera_per_image); AddAndRegisterDefaultOption("ImageReader.existing_camera_id", &image_reader->existing_camera_id); AddAndRegisterDefaultOption("ImageReader.camera_params", &image_reader->camera_params); AddAndRegisterDefaultOption("ImageReader.default_focal_length_factor", &image_reader->default_focal_length_factor); AddAndRegisterDefaultOption("ImageReader.camera_mask_path", &image_reader->camera_mask_path); AddAndRegisterDefaultOption("SiftExtraction.num_threads", &sift_extraction->num_threads); AddAndRegisterDefaultOption("SiftExtraction.use_gpu", &sift_extraction->use_gpu); AddAndRegisterDefaultOption("SiftExtraction.gpu_index", &sift_extraction->gpu_index); AddAndRegisterDefaultOption("SiftExtraction.max_image_size", &sift_extraction->max_image_size); AddAndRegisterDefaultOption("SiftExtraction.max_num_features", &sift_extraction->max_num_features); AddAndRegisterDefaultOption("SiftExtraction.first_octave", &sift_extraction->first_octave); AddAndRegisterDefaultOption("SiftExtraction.num_octaves", &sift_extraction->num_octaves); AddAndRegisterDefaultOption("SiftExtraction.octave_resolution", &sift_extraction->octave_resolution); AddAndRegisterDefaultOption("SiftExtraction.peak_threshold", &sift_extraction->peak_threshold); AddAndRegisterDefaultOption("SiftExtraction.edge_threshold", &sift_extraction->edge_threshold); AddAndRegisterDefaultOption("SiftExtraction.estimate_affine_shape", &sift_extraction->estimate_affine_shape); AddAndRegisterDefaultOption("SiftExtraction.max_num_orientations", &sift_extraction->max_num_orientations); AddAndRegisterDefaultOption("SiftExtraction.upright", &sift_extraction->upright); AddAndRegisterDefaultOption("SiftExtraction.domain_size_pooling", &sift_extraction->domain_size_pooling); AddAndRegisterDefaultOption("SiftExtraction.dsp_min_scale", &sift_extraction->dsp_min_scale); AddAndRegisterDefaultOption("SiftExtraction.dsp_max_scale", &sift_extraction->dsp_max_scale); AddAndRegisterDefaultOption("SiftExtraction.dsp_num_scales", &sift_extraction->dsp_num_scales); } void OptionManager::AddMatchingOptions() { if (added_match_options_) { return; } added_match_options_ = true; AddAndRegisterDefaultOption("SiftMatching.num_threads", &sift_matching->num_threads); AddAndRegisterDefaultOption("SiftMatching.use_gpu", &sift_matching->use_gpu); AddAndRegisterDefaultOption("SiftMatching.gpu_index", &sift_matching->gpu_index); AddAndRegisterDefaultOption("SiftMatching.max_ratio", &sift_matching->max_ratio); AddAndRegisterDefaultOption("SiftMatching.max_distance", &sift_matching->max_distance); AddAndRegisterDefaultOption("SiftMatching.cross_check", &sift_matching->cross_check); AddAndRegisterDefaultOption("SiftMatching.guided_matching", &sift_matching->guided_matching); AddAndRegisterDefaultOption("SiftMatching.max_num_matches", &sift_matching->max_num_matches); AddAndRegisterDefaultOption("TwoViewGeometry.min_num_inliers", &two_view_geometry->min_num_inliers); AddAndRegisterDefaultOption("TwoViewGeometry.multiple_models", &two_view_geometry->multiple_models); AddAndRegisterDefaultOption("TwoViewGeometry.compute_relative_pose", &two_view_geometry->compute_relative_pose); AddAndRegisterDefaultOption("TwoViewGeometry.max_error", &two_view_geometry->ransac_options.max_error); AddAndRegisterDefaultOption("TwoViewGeometry.confidence", &two_view_geometry->ransac_options.confidence); AddAndRegisterDefaultOption( "TwoViewGeometry.max_num_trials", &two_view_geometry->ransac_options.max_num_trials); AddAndRegisterDefaultOption( "TwoViewGeometry.min_inlier_ratio", &two_view_geometry->ransac_options.min_inlier_ratio); } void OptionManager::AddExhaustiveMatchingOptions() { if (added_exhaustive_match_options_) { return; } added_exhaustive_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("ExhaustiveMatching.block_size", &exhaustive_matching->block_size); } void OptionManager::AddSequentialMatchingOptions() { if (added_sequential_match_options_) { return; } added_sequential_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("SequentialMatching.overlap", &sequential_matching->overlap); AddAndRegisterDefaultOption("SequentialMatching.quadratic_overlap", &sequential_matching->quadratic_overlap); AddAndRegisterDefaultOption("SequentialMatching.loop_detection", &sequential_matching->loop_detection); AddAndRegisterDefaultOption("SequentialMatching.loop_detection_period", &sequential_matching->loop_detection_period); AddAndRegisterDefaultOption("SequentialMatching.loop_detection_num_images", &sequential_matching->loop_detection_num_images); AddAndRegisterDefaultOption( "SequentialMatching.loop_detection_num_nearest_neighbors", &sequential_matching->loop_detection_num_nearest_neighbors); AddAndRegisterDefaultOption("SequentialMatching.loop_detection_num_checks", &sequential_matching->loop_detection_num_checks); AddAndRegisterDefaultOption( "SequentialMatching.loop_detection_num_images_after_verification", &sequential_matching->loop_detection_num_images_after_verification); AddAndRegisterDefaultOption( "SequentialMatching.loop_detection_max_num_features", &sequential_matching->loop_detection_max_num_features); AddAndRegisterDefaultOption("SequentialMatching.vocab_tree_path", &sequential_matching->vocab_tree_path); } void OptionManager::AddVocabTreeMatchingOptions() { if (added_vocab_tree_match_options_) { return; } added_vocab_tree_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("VocabTreeMatching.num_images", &vocab_tree_matching->num_images); AddAndRegisterDefaultOption("VocabTreeMatching.num_nearest_neighbors", &vocab_tree_matching->num_nearest_neighbors); AddAndRegisterDefaultOption("VocabTreeMatching.num_checks", &vocab_tree_matching->num_checks); AddAndRegisterDefaultOption( "VocabTreeMatching.num_images_after_verification", &vocab_tree_matching->num_images_after_verification); AddAndRegisterDefaultOption("VocabTreeMatching.max_num_features", &vocab_tree_matching->max_num_features); AddAndRegisterDefaultOption("VocabTreeMatching.vocab_tree_path", &vocab_tree_matching->vocab_tree_path); AddAndRegisterDefaultOption("VocabTreeMatching.match_list_path", &vocab_tree_matching->match_list_path); } void OptionManager::AddSpatialMatchingOptions() { if (added_spatial_match_options_) { return; } added_spatial_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("SpatialMatching.ignore_z", &spatial_matching->ignore_z); AddAndRegisterDefaultOption("SpatialMatching.max_num_neighbors", &spatial_matching->max_num_neighbors); AddAndRegisterDefaultOption("SpatialMatching.max_distance", &spatial_matching->max_distance); } void OptionManager::AddTransitiveMatchingOptions() { if (added_transitive_match_options_) { return; } added_transitive_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("TransitiveMatching.batch_size", &transitive_matching->batch_size); AddAndRegisterDefaultOption("TransitiveMatching.num_iterations", &transitive_matching->num_iterations); } void OptionManager::AddImagePairsMatchingOptions() { if (added_image_pairs_match_options_) { return; } added_image_pairs_match_options_ = true; AddMatchingOptions(); AddAndRegisterDefaultOption("ImagePairsMatching.block_size", &image_pairs_matching->block_size); } void OptionManager::AddBundleAdjustmentOptions() { if (added_ba_options_) { return; } added_ba_options_ = true; AddAndRegisterDefaultOption( "BundleAdjustment.max_num_iterations", &bundle_adjustment->solver_options.max_num_iterations); AddAndRegisterDefaultOption( "BundleAdjustment.max_linear_solver_iterations", &bundle_adjustment->solver_options.max_linear_solver_iterations); AddAndRegisterDefaultOption( "BundleAdjustment.function_tolerance", &bundle_adjustment->solver_options.function_tolerance); AddAndRegisterDefaultOption( "BundleAdjustment.gradient_tolerance", &bundle_adjustment->solver_options.gradient_tolerance); AddAndRegisterDefaultOption( "BundleAdjustment.parameter_tolerance", &bundle_adjustment->solver_options.parameter_tolerance); AddAndRegisterDefaultOption("BundleAdjustment.refine_focal_length", &bundle_adjustment->refine_focal_length); AddAndRegisterDefaultOption("BundleAdjustment.refine_principal_point", &bundle_adjustment->refine_principal_point); AddAndRegisterDefaultOption("BundleAdjustment.refine_extra_params", &bundle_adjustment->refine_extra_params); AddAndRegisterDefaultOption("BundleAdjustment.refine_extrinsics", &bundle_adjustment->refine_extrinsics); } void OptionManager::AddMapperOptions() { if (added_mapper_options_) { return; } added_mapper_options_ = true; AddAndRegisterDefaultOption("Mapper.min_num_matches", &mapper->min_num_matches); AddAndRegisterDefaultOption("Mapper.ignore_watermarks", &mapper->ignore_watermarks); AddAndRegisterDefaultOption("Mapper.multiple_models", &mapper->multiple_models); AddAndRegisterDefaultOption("Mapper.max_num_models", &mapper->max_num_models); AddAndRegisterDefaultOption("Mapper.max_model_overlap", &mapper->max_model_overlap); AddAndRegisterDefaultOption("Mapper.min_model_size", &mapper->min_model_size); AddAndRegisterDefaultOption("Mapper.init_image_id1", &mapper->init_image_id1); AddAndRegisterDefaultOption("Mapper.init_image_id2", &mapper->init_image_id2); AddAndRegisterDefaultOption("Mapper.init_num_trials", &mapper->init_num_trials); AddAndRegisterDefaultOption("Mapper.extract_colors", &mapper->extract_colors); AddAndRegisterDefaultOption("Mapper.num_threads", &mapper->num_threads); AddAndRegisterDefaultOption("Mapper.min_focal_length_ratio", &mapper->min_focal_length_ratio); AddAndRegisterDefaultOption("Mapper.max_focal_length_ratio", &mapper->max_focal_length_ratio); AddAndRegisterDefaultOption("Mapper.max_extra_param", &mapper->max_extra_param); AddAndRegisterDefaultOption("Mapper.ba_refine_focal_length", &mapper->ba_refine_focal_length); AddAndRegisterDefaultOption("Mapper.ba_refine_principal_point", &mapper->ba_refine_principal_point); AddAndRegisterDefaultOption("Mapper.ba_refine_extra_params", &mapper->ba_refine_extra_params); AddAndRegisterDefaultOption( "Mapper.ba_min_num_residuals_for_multi_threading", &mapper->ba_min_num_residuals_for_multi_threading); AddAndRegisterDefaultOption("Mapper.ba_local_num_images", &mapper->ba_local_num_images); AddAndRegisterDefaultOption("Mapper.ba_local_function_tolerance", &mapper->ba_local_function_tolerance); AddAndRegisterDefaultOption("Mapper.ba_local_max_num_iterations", &mapper->ba_local_max_num_iterations); AddAndRegisterDefaultOption("Mapper.ba_global_images_ratio", &mapper->ba_global_images_ratio); AddAndRegisterDefaultOption("Mapper.ba_global_points_ratio", &mapper->ba_global_points_ratio); AddAndRegisterDefaultOption("Mapper.ba_global_images_freq", &mapper->ba_global_images_freq); AddAndRegisterDefaultOption("Mapper.ba_global_points_freq", &mapper->ba_global_points_freq); AddAndRegisterDefaultOption("Mapper.ba_global_function_tolerance", &mapper->ba_global_function_tolerance); AddAndRegisterDefaultOption("Mapper.ba_global_max_num_iterations", &mapper->ba_global_max_num_iterations); AddAndRegisterDefaultOption("Mapper.ba_global_max_refinements", &mapper->ba_global_max_refinements); AddAndRegisterDefaultOption("Mapper.ba_global_max_refinement_change", &mapper->ba_global_max_refinement_change); AddAndRegisterDefaultOption("Mapper.ba_local_max_refinements", &mapper->ba_local_max_refinements); AddAndRegisterDefaultOption("Mapper.ba_local_max_refinement_change", &mapper->ba_local_max_refinement_change); AddAndRegisterDefaultOption("Mapper.snapshot_path", &mapper->snapshot_path); AddAndRegisterDefaultOption("Mapper.snapshot_images_freq", &mapper->snapshot_images_freq); AddAndRegisterDefaultOption("Mapper.fix_existing_images", &mapper->fix_existing_images); // IncrementalMapper. AddAndRegisterDefaultOption("Mapper.init_min_num_inliers", &mapper->mapper.init_min_num_inliers); AddAndRegisterDefaultOption("Mapper.init_max_error", &mapper->mapper.init_max_error); AddAndRegisterDefaultOption("Mapper.init_max_forward_motion", &mapper->mapper.init_max_forward_motion); AddAndRegisterDefaultOption("Mapper.init_min_tri_angle", &mapper->mapper.init_min_tri_angle); AddAndRegisterDefaultOption("Mapper.init_max_reg_trials", &mapper->mapper.init_max_reg_trials); AddAndRegisterDefaultOption("Mapper.abs_pose_max_error", &mapper->mapper.abs_pose_max_error); AddAndRegisterDefaultOption("Mapper.abs_pose_min_num_inliers", &mapper->mapper.abs_pose_min_num_inliers); AddAndRegisterDefaultOption("Mapper.abs_pose_min_inlier_ratio", &mapper->mapper.abs_pose_min_inlier_ratio); AddAndRegisterDefaultOption("Mapper.filter_max_reproj_error", &mapper->mapper.filter_max_reproj_error); AddAndRegisterDefaultOption("Mapper.filter_min_tri_angle", &mapper->mapper.filter_min_tri_angle); AddAndRegisterDefaultOption("Mapper.max_reg_trials", &mapper->mapper.max_reg_trials); AddAndRegisterDefaultOption("Mapper.local_ba_min_tri_angle", &mapper->mapper.local_ba_min_tri_angle); // IncrementalTriangulator. AddAndRegisterDefaultOption("Mapper.tri_max_transitivity", &mapper->triangulation.max_transitivity); AddAndRegisterDefaultOption("Mapper.tri_create_max_angle_error", &mapper->triangulation.create_max_angle_error); AddAndRegisterDefaultOption("Mapper.tri_continue_max_angle_error", &mapper->triangulation.continue_max_angle_error); AddAndRegisterDefaultOption("Mapper.tri_merge_max_reproj_error", &mapper->triangulation.merge_max_reproj_error); AddAndRegisterDefaultOption("Mapper.tri_complete_max_reproj_error", &mapper->triangulation.complete_max_reproj_error); AddAndRegisterDefaultOption("Mapper.tri_complete_max_transitivity", &mapper->triangulation.complete_max_transitivity); AddAndRegisterDefaultOption("Mapper.tri_re_max_angle_error", &mapper->triangulation.re_max_angle_error); AddAndRegisterDefaultOption("Mapper.tri_re_min_ratio", &mapper->triangulation.re_min_ratio); AddAndRegisterDefaultOption("Mapper.tri_re_max_trials", &mapper->triangulation.re_max_trials); AddAndRegisterDefaultOption("Mapper.tri_min_angle", &mapper->triangulation.min_angle); AddAndRegisterDefaultOption("Mapper.tri_ignore_two_view_tracks", &mapper->triangulation.ignore_two_view_tracks); } void OptionManager::AddPatchMatchStereoOptions() { if (added_patch_match_stereo_options_) { return; } added_patch_match_stereo_options_ = true; AddAndRegisterDefaultOption("PatchMatchStereo.max_image_size", &patch_match_stereo->max_image_size); AddAndRegisterDefaultOption("PatchMatchStereo.gpu_index", &patch_match_stereo->gpu_index); AddAndRegisterDefaultOption("PatchMatchStereo.depth_min", &patch_match_stereo->depth_min); AddAndRegisterDefaultOption("PatchMatchStereo.depth_max", &patch_match_stereo->depth_max); AddAndRegisterDefaultOption("PatchMatchStereo.window_radius", &patch_match_stereo->window_radius); AddAndRegisterDefaultOption("PatchMatchStereo.window_step", &patch_match_stereo->window_step); AddAndRegisterDefaultOption("PatchMatchStereo.sigma_spatial", &patch_match_stereo->sigma_spatial); AddAndRegisterDefaultOption("PatchMatchStereo.sigma_color", &patch_match_stereo->sigma_color); AddAndRegisterDefaultOption("PatchMatchStereo.num_samples", &patch_match_stereo->num_samples); AddAndRegisterDefaultOption("PatchMatchStereo.ncc_sigma", &patch_match_stereo->ncc_sigma); AddAndRegisterDefaultOption("PatchMatchStereo.min_triangulation_angle", &patch_match_stereo->min_triangulation_angle); AddAndRegisterDefaultOption("PatchMatchStereo.incident_angle_sigma", &patch_match_stereo->incident_angle_sigma); AddAndRegisterDefaultOption("PatchMatchStereo.num_iterations", &patch_match_stereo->num_iterations); AddAndRegisterDefaultOption("PatchMatchStereo.geom_consistency", &patch_match_stereo->geom_consistency); AddAndRegisterDefaultOption( "PatchMatchStereo.geom_consistency_regularizer", &patch_match_stereo->geom_consistency_regularizer); AddAndRegisterDefaultOption("PatchMatchStereo.geom_consistency_max_cost", &patch_match_stereo->geom_consistency_max_cost); AddAndRegisterDefaultOption("PatchMatchStereo.filter", &patch_match_stereo->filter); AddAndRegisterDefaultOption("PatchMatchStereo.filter_min_ncc", &patch_match_stereo->filter_min_ncc); AddAndRegisterDefaultOption( "PatchMatchStereo.filter_min_triangulation_angle", &patch_match_stereo->filter_min_triangulation_angle); AddAndRegisterDefaultOption("PatchMatchStereo.filter_min_num_consistent", &patch_match_stereo->filter_min_num_consistent); AddAndRegisterDefaultOption( "PatchMatchStereo.filter_geom_consistency_max_cost", &patch_match_stereo->filter_geom_consistency_max_cost); AddAndRegisterDefaultOption("PatchMatchStereo.cache_size", &patch_match_stereo->cache_size); AddAndRegisterDefaultOption("PatchMatchStereo.allow_missing_files", &patch_match_stereo->allow_missing_files); AddAndRegisterDefaultOption("PatchMatchStereo.write_consistency_graph", &patch_match_stereo->write_consistency_graph); } void OptionManager::AddStereoFusionOptions() { if (added_stereo_fusion_options_) { return; } added_stereo_fusion_options_ = true; AddAndRegisterDefaultOption("StereoFusion.mask_path", &stereo_fusion->mask_path); AddAndRegisterDefaultOption("StereoFusion.num_threads", &stereo_fusion->num_threads); AddAndRegisterDefaultOption("StereoFusion.max_image_size", &stereo_fusion->max_image_size); AddAndRegisterDefaultOption("StereoFusion.min_num_pixels", &stereo_fusion->min_num_pixels); AddAndRegisterDefaultOption("StereoFusion.max_num_pixels", &stereo_fusion->max_num_pixels); AddAndRegisterDefaultOption("StereoFusion.max_traversal_depth", &stereo_fusion->max_traversal_depth); AddAndRegisterDefaultOption("StereoFusion.max_reproj_error", &stereo_fusion->max_reproj_error); AddAndRegisterDefaultOption("StereoFusion.max_depth_error", &stereo_fusion->max_depth_error); AddAndRegisterDefaultOption("StereoFusion.max_normal_error", &stereo_fusion->max_normal_error); AddAndRegisterDefaultOption("StereoFusion.check_num_images", &stereo_fusion->check_num_images); AddAndRegisterDefaultOption("StereoFusion.cache_size", &stereo_fusion->cache_size); AddAndRegisterDefaultOption("StereoFusion.use_cache", &stereo_fusion->use_cache); } void OptionManager::AddPoissonMeshingOptions() { if (added_poisson_meshing_options_) { return; } added_poisson_meshing_options_ = true; AddAndRegisterDefaultOption("PoissonMeshing.point_weight", &poisson_meshing->point_weight); AddAndRegisterDefaultOption("PoissonMeshing.depth", &poisson_meshing->depth); AddAndRegisterDefaultOption("PoissonMeshing.color", &poisson_meshing->color); AddAndRegisterDefaultOption("PoissonMeshing.trim", &poisson_meshing->trim); AddAndRegisterDefaultOption("PoissonMeshing.num_threads", &poisson_meshing->num_threads); } void OptionManager::AddDelaunayMeshingOptions() { if (added_delaunay_meshing_options_) { return; } added_delaunay_meshing_options_ = true; AddAndRegisterDefaultOption("DelaunayMeshing.max_proj_dist", &delaunay_meshing->max_proj_dist); AddAndRegisterDefaultOption("DelaunayMeshing.max_depth_dist", &delaunay_meshing->max_depth_dist); AddAndRegisterDefaultOption("DelaunayMeshing.visibility_sigma", &delaunay_meshing->visibility_sigma); AddAndRegisterDefaultOption("DelaunayMeshing.distance_sigma_factor", &delaunay_meshing->distance_sigma_factor); AddAndRegisterDefaultOption("DelaunayMeshing.quality_regularization", &delaunay_meshing->quality_regularization); AddAndRegisterDefaultOption("DelaunayMeshing.max_side_length_factor", &delaunay_meshing->max_side_length_factor); AddAndRegisterDefaultOption("DelaunayMeshing.max_side_length_percentile", &delaunay_meshing->max_side_length_percentile); AddAndRegisterDefaultOption("DelaunayMeshing.num_threads", &delaunay_meshing->num_threads); } void OptionManager::AddRenderOptions() { if (added_render_options_) { return; } added_render_options_ = true; AddAndRegisterDefaultOption("Render.min_track_len", &render->min_track_len); AddAndRegisterDefaultOption("Render.max_error", &render->max_error); AddAndRegisterDefaultOption("Render.refresh_rate", &render->refresh_rate); AddAndRegisterDefaultOption("Render.adapt_refresh_rate", &render->adapt_refresh_rate); AddAndRegisterDefaultOption("Render.image_connections", &render->image_connections); AddAndRegisterDefaultOption("Render.projection_type", &render->projection_type); } void OptionManager::Reset() { FLAGS_logtostderr = true; const bool kResetPaths = true; ResetOptions(kResetPaths); desc_ = std::make_shared(); options_bool_.clear(); options_int_.clear(); options_double_.clear(); options_string_.clear(); added_log_options_ = false; added_random_options_ = false; added_database_options_ = false; added_image_options_ = false; added_extraction_options_ = false; added_match_options_ = false; added_exhaustive_match_options_ = false; added_sequential_match_options_ = false; added_vocab_tree_match_options_ = false; added_spatial_match_options_ = false; added_transitive_match_options_ = false; added_image_pairs_match_options_ = false; added_ba_options_ = false; added_mapper_options_ = false; added_patch_match_stereo_options_ = false; added_stereo_fusion_options_ = false; added_poisson_meshing_options_ = false; added_delaunay_meshing_options_ = false; added_render_options_ = false; } void OptionManager::ResetOptions(const bool reset_paths) { if (reset_paths) { *project_path = ""; *database_path = ""; *image_path = ""; } *image_reader = ImageReaderOptions(); *sift_extraction = SiftExtractionOptions(); *sift_matching = SiftMatchingOptions(); *exhaustive_matching = ExhaustiveMatchingOptions(); *sequential_matching = SequentialMatchingOptions(); *vocab_tree_matching = VocabTreeMatchingOptions(); *spatial_matching = SpatialMatchingOptions(); *transitive_matching = TransitiveMatchingOptions(); *image_pairs_matching = ImagePairsMatchingOptions(); *bundle_adjustment = BundleAdjustmentOptions(); *mapper = IncrementalMapperOptions(); *patch_match_stereo = mvs::PatchMatchOptions(); *stereo_fusion = mvs::StereoFusionOptions(); *poisson_meshing = mvs::PoissonMeshingOptions(); *delaunay_meshing = mvs::DelaunayMeshingOptions(); *render = RenderOptions(); } bool OptionManager::Check() { bool success = true; if (added_database_options_) { const auto database_parent_path = GetParentDir(*database_path); success = success && CHECK_OPTION_IMPL(!ExistsDir(*database_path)) && CHECK_OPTION_IMPL(database_parent_path == "" || ExistsDir(database_parent_path)); } if (added_image_options_) success = success && CHECK_OPTION_IMPL(ExistsDir(*image_path)); if (image_reader) success = success && image_reader->Check(); if (sift_extraction) success = success && sift_extraction->Check(); if (sift_matching) success = success && sift_matching->Check(); if (two_view_geometry) success = success && two_view_geometry->Check(); if (exhaustive_matching) success = success && exhaustive_matching->Check(); if (sequential_matching) success = success && sequential_matching->Check(); if (vocab_tree_matching) success = success && vocab_tree_matching->Check(); if (spatial_matching) success = success && spatial_matching->Check(); if (transitive_matching) success = success && transitive_matching->Check(); if (image_pairs_matching) success = success && image_pairs_matching->Check(); if (bundle_adjustment) success = success && bundle_adjustment->Check(); if (mapper) success = success && mapper->Check(); if (patch_match_stereo) success = success && patch_match_stereo->Check(); if (stereo_fusion) success = success && stereo_fusion->Check(); if (poisson_meshing) success = success && poisson_meshing->Check(); if (delaunay_meshing) success = success && delaunay_meshing->Check(); #if defined(COLMAP_GUI_ENABLED) if (render) success = success && render->Check(); #endif return success; } void OptionManager::Parse(const int argc, char** argv) { config::variables_map vmap; try { config::store(config::parse_command_line(argc, argv, *desc_), vmap); if (vmap.count("help")) { LOG(INFO) << StringPrintf( "%s (%s)", GetVersionInfo().c_str(), GetBuildInfo().c_str()); LOG(INFO) << "Options can either be specified via command-line or by defining " "them in a .ini project file passed to `--project_path`.\n" << *desc_; // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(EXIT_SUCCESS); } if (vmap.count("project_path")) { *project_path = vmap["project_path"].as(); if (!Read(*project_path)) { // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(EXIT_FAILURE); } } else { vmap.notify(); } } catch (std::exception& exc) { LOG(ERROR) << "Failed to parse options - " << exc.what() << "."; // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(EXIT_FAILURE); } catch (...) { LOG(ERROR) << "Failed to parse options for unknown reason."; // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(EXIT_FAILURE); } if (!Check()) { LOG(ERROR) << "Invalid options provided."; // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(EXIT_FAILURE); } } bool OptionManager::Read(const std::string& path) { config::variables_map vmap; if (!ExistsFile(path)) { LOG(ERROR) << "Configuration file does not exist."; return false; } try { std::ifstream file(path); THROW_CHECK_FILE_OPEN(file, path); config::store(config::parse_config_file(file, *desc_), vmap); vmap.notify(); } catch (std::exception& e) { LOG(ERROR) << "Failed to parse options " << e.what() << "."; return false; } catch (...) { LOG(ERROR) << "Failed to parse options for unknown reason."; return false; } return Check(); } bool OptionManager::ReRead(const std::string& path) { Reset(); AddAllOptions(); return Read(path); } void OptionManager::Write(const std::string& path) const { boost::property_tree::ptree pt; // First, put all options without a section and then those with a section. // This is necessary as otherwise older Boost versions will write the // options without a section in between other sections and therefore // the errors will be assigned to the wrong section if read later. for (const auto& option : options_bool_) { if (!StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_int_) { if (!StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_double_) { if (!StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_string_) { if (!StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_bool_) { if (StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_int_) { if (StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_double_) { if (StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } for (const auto& option : options_string_) { if (StringContains(option.first, ".")) { pt.put(option.first, *option.second); } } boost::property_tree::write_ini(path, pt); } } // namespace colmap colmap-3.10/src/colmap/controllers/option_manager.h000066400000000000000000000222741464745566500225300ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/util/logging.h" #include #include namespace colmap { struct ImageReaderOptions; struct SiftExtractionOptions; struct SiftMatchingOptions; struct TwoViewGeometryOptions; struct ExhaustiveMatchingOptions; struct SequentialMatchingOptions; struct VocabTreeMatchingOptions; struct SpatialMatchingOptions; struct TransitiveMatchingOptions; struct ImagePairsMatchingOptions; struct BundleAdjustmentOptions; struct IncrementalMapperOptions; struct RenderOptions; namespace mvs { struct PatchMatchOptions; struct StereoFusionOptions; struct PoissonMeshingOptions; struct DelaunayMeshingOptions; } // namespace mvs class OptionManager { public: explicit OptionManager(bool add_project_options = true); // Create "optimal" set of options for different reconstruction scenarios. // Note that the existing options are modified, so if your parameters are // already low quality, they will be further modified. void ModifyForIndividualData(); void ModifyForVideoData(); void ModifyForInternetData(); // Create "optimal" set of options for different quality settings. // Note that the existing options are modified, so if your parameters are // already low quality, they will be further degraded. void ModifyForLowQuality(); void ModifyForMediumQuality(); void ModifyForHighQuality(); void ModifyForExtremeQuality(); void AddAllOptions(); void AddLogOptions(); void AddRandomOptions(); void AddDatabaseOptions(); void AddImageOptions(); void AddExtractionOptions(); void AddMatchingOptions(); void AddExhaustiveMatchingOptions(); void AddSequentialMatchingOptions(); void AddVocabTreeMatchingOptions(); void AddSpatialMatchingOptions(); void AddTransitiveMatchingOptions(); void AddImagePairsMatchingOptions(); void AddBundleAdjustmentOptions(); void AddMapperOptions(); void AddPatchMatchStereoOptions(); void AddStereoFusionOptions(); void AddPoissonMeshingOptions(); void AddDelaunayMeshingOptions(); void AddRenderOptions(); template void AddRequiredOption(const std::string& name, T* option, const std::string& help_text = ""); template void AddDefaultOption(const std::string& name, T* option, const std::string& help_text = ""); void Reset(); void ResetOptions(bool reset_paths); bool Check(); void Parse(int argc, char** argv); bool Read(const std::string& path); bool ReRead(const std::string& path); void Write(const std::string& path) const; std::shared_ptr project_path; std::shared_ptr database_path; std::shared_ptr image_path; std::shared_ptr image_reader; std::shared_ptr sift_extraction; std::shared_ptr sift_matching; std::shared_ptr two_view_geometry; std::shared_ptr exhaustive_matching; std::shared_ptr sequential_matching; std::shared_ptr vocab_tree_matching; std::shared_ptr spatial_matching; std::shared_ptr transitive_matching; std::shared_ptr image_pairs_matching; std::shared_ptr bundle_adjustment; std::shared_ptr mapper; std::shared_ptr patch_match_stereo; std::shared_ptr stereo_fusion; std::shared_ptr poisson_meshing; std::shared_ptr delaunay_meshing; std::shared_ptr render; private: template void AddAndRegisterRequiredOption(const std::string& name, T* option, const std::string& help_text = ""); template void AddAndRegisterDefaultOption(const std::string& name, T* option, const std::string& help_text = ""); template void RegisterOption(const std::string& name, const T* option); std::shared_ptr desc_; std::vector> options_bool_; std::vector> options_int_; std::vector> options_double_; std::vector> options_string_; bool added_log_options_; bool added_random_options_; bool added_database_options_; bool added_image_options_; bool added_extraction_options_; bool added_match_options_; bool added_exhaustive_match_options_; bool added_sequential_match_options_; bool added_vocab_tree_match_options_; bool added_spatial_match_options_; bool added_transitive_match_options_; bool added_image_pairs_match_options_; bool added_ba_options_; bool added_mapper_options_; bool added_patch_match_stereo_options_; bool added_stereo_fusion_options_; bool added_poisson_meshing_options_; bool added_delaunay_meshing_options_; bool added_render_options_; }; //////////////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////////////// template void OptionManager::AddRequiredOption(const std::string& name, T* option, const std::string& help_text) { desc_->add_options()(name.c_str(), boost::program_options::value(option)->required(), help_text.c_str()); } template void OptionManager::AddDefaultOption(const std::string& name, T* option, const std::string& help_text) { desc_->add_options()( name.c_str(), boost::program_options::value(option)->default_value(*option), help_text.c_str()); } template void OptionManager::AddAndRegisterRequiredOption(const std::string& name, T* option, const std::string& help_text) { desc_->add_options()(name.c_str(), boost::program_options::value(option)->required(), help_text.c_str()); RegisterOption(name, option); } template void OptionManager::AddAndRegisterDefaultOption(const std::string& name, T* option, const std::string& help_text) { desc_->add_options()( name.c_str(), boost::program_options::value(option)->default_value(*option), help_text.c_str()); RegisterOption(name, option); } template void OptionManager::RegisterOption(const std::string& name, const T* option) { if (std::is_same::value) { options_bool_.emplace_back(name, reinterpret_cast(option)); } else if (std::is_same::value) { options_int_.emplace_back(name, reinterpret_cast(option)); } else if (std::is_same::value) { options_double_.emplace_back(name, reinterpret_cast(option)); } else if (std::is_same::value) { options_string_.emplace_back(name, reinterpret_cast(option)); } else { LOG(FATAL_THROW) << "Unsupported option type"; } } } // namespace colmap colmap-3.10/src/colmap/estimators/000077500000000000000000000000001464745566500171725ustar00rootroot00000000000000colmap-3.10/src/colmap/estimators/CMakeLists.txt000066400000000000000000000113131464745566500217310ustar00rootroot00000000000000# Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of # its contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. set(FOLDER_NAME "estimators") COLMAP_ADD_LIBRARY( NAME colmap_estimators SRCS absolute_pose.h absolute_pose.cc affine_transform.h affine_transform.cc alignment.h alignment.cc bundle_adjustment.h bundle_adjustment.cc coordinate_frame.h coordinate_frame.cc cost_functions.h covariance.h covariance.cc essential_matrix.h essential_matrix.cc euclidean_transform.h fundamental_matrix.h fundamental_matrix.cc generalized_absolute_pose.h generalized_absolute_pose.cc generalized_absolute_pose_coeffs.h generalized_absolute_pose_coeffs.cc generalized_relative_pose.h generalized_relative_pose.cc homography_matrix.h homography_matrix.cc pose.h pose.cc generalized_pose.h generalized_pose.cc similarity_transform.h translation_transform.h triangulation.h triangulation.cc two_view_geometry.h two_view_geometry.cc utils.h utils.cc PUBLIC_LINK_LIBS colmap_util colmap_math colmap_feature_types colmap_geometry colmap_sensor colmap_image colmap_scene colmap_optim Eigen3::Eigen Ceres::ceres ) COLMAP_ADD_TEST( NAME absolute_pose_test SRCS absolute_pose_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME affine_transform_test SRCS affine_transform_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME alignment_test SRCS alignment_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME bundle_adjustment_test SRCS bundle_adjustment_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME coordinate_frame_test SRCS coordinate_frame_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME covariance_test SRCS covariance_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME cost_functions_test SRCS cost_functions_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME essential_matrix_test SRCS essential_matrix_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME estimators_utils_test SRCS utils_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME fundamental_matrix_test SRCS fundamental_matrix_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME generalized_absolute_pose_test SRCS generalized_absolute_pose_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME generalized_pose_test SRCS generalized_pose_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME generalized_relative_pose_test SRCS generalized_relative_pose_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME homography_matrix_test SRCS homography_matrix_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME pose_test SRCS pose_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME similarity_transform_test SRCS similarity_transform_test.cc LINK_LIBS colmap_estimators ) COLMAP_ADD_TEST( NAME translation_transform_test SRCS translation_transform_test.cc LINK_LIBS colmap_estimators ) colmap-3.10/src/colmap/estimators/absolute_pose.cc000066400000000000000000000510241464745566500223470ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/absolute_pose.h" #include "colmap/estimators/utils.h" #include "colmap/math/polynomial.h" #include "colmap/util/eigen_alignment.h" #include "colmap/util/logging.h" #include namespace colmap { void P3PEstimator::Estimate(const std::vector& points2D, const std::vector& points3D, std::vector* models) { THROW_CHECK_EQ(points2D.size(), 3); THROW_CHECK_EQ(points3D.size(), 3); THROW_CHECK(models != nullptr); models->clear(); Eigen::Matrix3d points3D_world; points3D_world.col(0) = points3D[0]; points3D_world.col(1) = points3D[1]; points3D_world.col(2) = points3D[2]; const Eigen::Vector3d u = points2D[0].homogeneous().normalized(); const Eigen::Vector3d v = points2D[1].homogeneous().normalized(); const Eigen::Vector3d w = points2D[2].homogeneous().normalized(); // Angles between 2D points. const double cos_uv = u.transpose() * v; const double cos_uw = u.transpose() * w; const double cos_vw = v.transpose() * w; // Distances between 2D points. const double dist_AB_2 = (points3D[0] - points3D[1]).squaredNorm(); const double dist_AC_2 = (points3D[0] - points3D[2]).squaredNorm(); const double dist_BC_2 = (points3D[1] - points3D[2]).squaredNorm(); const double dist_AB = std::sqrt(dist_AB_2); const double a = dist_BC_2 / dist_AB_2; const double b = dist_AC_2 / dist_AB_2; // Helper variables for calculation of coefficients. const double a2 = a * a; const double b2 = b * b; const double p = 2 * cos_vw; const double q = 2 * cos_uw; const double r = 2 * cos_uv; const double p2 = p * p; const double p3 = p2 * p; const double q2 = q * q; const double r2 = r * r; const double r3 = r2 * r; const double r4 = r3 * r; const double r5 = r4 * r; // Build polynomial coefficients: a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0 = 0. Eigen::Matrix coeffs; coeffs(0) = -2 * b + b2 + a2 + 1 + a * b * (2 - r2) - 2 * a; coeffs(1) = -2 * q * a2 - r * p * b2 + 4 * q * a + (2 * q + p * r) * b + (r2 * q - 2 * q + r * p) * a * b - 2 * q; coeffs(2) = (2 + q2) * a2 + (p2 + r2 - 2) * b2 - (4 + 2 * q2) * a - (p * q * r + p2) * b - (p * q * r + r2) * a * b + q2 + 2; coeffs(3) = -2 * q * a2 - r * p * b2 + 4 * q * a + (p * r + q * p2 - 2 * q) * b + (r * p + 2 * q) * a * b - 2 * q; coeffs(4) = a2 + b2 - 2 * a + (2 - p2) * b - 2 * a * b + 1; Eigen::VectorXd roots_real; Eigen::VectorXd roots_imag; if (!FindPolynomialRootsCompanionMatrix(coeffs, &roots_real, &roots_imag)) { return; } models->reserve(roots_real.size()); for (Eigen::VectorXd::Index i = 0; i < roots_real.size(); ++i) { const double kMaxRootImag = 1e-10; if (std::abs(roots_imag(i)) > kMaxRootImag) { continue; } const double x = roots_real(i); if (x < 0) { continue; } const double x2 = x * x; const double x3 = x2 * x; // Build polynomial coefficients: b1*y + b0 = 0. const double bb1 = (p2 - p * q * r + r2) * a + (p2 - r2) * b - p2 + p * q * r - r2; const double b1 = b * bb1 * bb1; const double b0 = ((1 - a - b) * x2 + (a - 1) * q * x - a + b + 1) * (r3 * (a2 + b2 - 2 * a - 2 * b + (2 - r2) * a * b + 1) * x3 + r2 * (p + p * a2 - 2 * r * q * a * b + 2 * r * q * b - 2 * r * q - 2 * p * a - 2 * p * b + p * r2 * b + 4 * r * q * a + q * r3 * a * b - 2 * r * q * a2 + 2 * p * a * b + p * b2 - r2 * p * b2) * x2 + (r5 * (b2 - a * b) - r4 * p * q * b + r3 * (q2 - 4 * a - 2 * q2 * a + q2 * a2 + 2 * a2 - 2 * b2 + 2) + r2 * (4 * p * q * a - 2 * p * q * a * b + 2 * p * q * b - 2 * p * q - 2 * p * q * a2) + r * (p2 * b2 - 2 * p2 * b + 2 * p2 * a * b - 2 * p2 * a + p2 + p2 * a2)) * x + (2 * p * r2 - 2 * r3 * q + p3 - 2 * p2 * q * r + p * q2 * r2) * a2 + (p3 - 2 * p * r2) * b2 + (4 * q * r3 - 4 * p * r2 - 2 * p3 + 4 * p2 * q * r - 2 * p * q2 * r2) * a + (-2 * q * r3 + p * r4 + 2 * p2 * q * r - 2 * p3) * b + (2 * p3 + 2 * q * r3 - 2 * p2 * q * r) * a * b + p * q2 * r2 - 2 * p2 * q * r + 2 * p * r2 + p3 - 2 * r3 * q); // Solve for y. const double y = b0 / b1; const double y2 = y * y; const double nu = x2 + y2 - 2 * x * y * cos_uv; const double dist_PC = dist_AB / std::sqrt(nu); const double dist_PB = y * dist_PC; const double dist_PA = x * dist_PC; Eigen::Matrix3d points3D_camera; points3D_camera.col(0) = u * dist_PA; // A' points3D_camera.col(1) = v * dist_PB; // B' points3D_camera.col(2) = w * dist_PC; // C' // Find transformation from the world to the camera system. const Eigen::Matrix4d transform = Eigen::umeyama(points3D_world, points3D_camera, false); models->push_back(transform.topLeftCorner<3, 4>()); } } void P3PEstimator::Residuals(const std::vector& points2D, const std::vector& points3D, const M_t& proj_matrix, std::vector* residuals) { ComputeSquaredReprojectionError(points2D, points3D, proj_matrix, residuals); } void EPNPEstimator::Estimate(const std::vector& points2D, const std::vector& points3D, std::vector* models) { THROW_CHECK_GE(points2D.size(), 4); THROW_CHECK_EQ(points2D.size(), points3D.size()); THROW_CHECK(models != nullptr); models->clear(); EPNPEstimator epnp; M_t proj_matrix; if (!epnp.ComputePose(points2D, points3D, &proj_matrix)) { return; } models->resize(1); (*models)[0] = proj_matrix; } void EPNPEstimator::Residuals(const std::vector& points2D, const std::vector& points3D, const M_t& proj_matrix, std::vector* residuals) { ComputeSquaredReprojectionError(points2D, points3D, proj_matrix, residuals); } bool EPNPEstimator::ComputePose(const std::vector& points2D, const std::vector& points3D, Eigen::Matrix3x4d* proj_matrix) { points2D_ = &points2D; points3D_ = &points3D; ChooseControlPoints(); if (!ComputeBarycentricCoordinates()) { return false; } const Eigen::Matrix M = ComputeM(); const Eigen::Matrix MtM = M.transpose() * M; Eigen::JacobiSVD> svd( MtM, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix Ut = svd.matrixU().transpose(); const Eigen::Matrix L6x10 = ComputeL6x10(Ut); const Eigen::Matrix rho = ComputeRho(); Eigen::Vector4d betas[4]; std::array reproj_errors; std::array Rs; std::array ts; FindBetasApprox1(L6x10, rho, &betas[1]); RunGaussNewton(L6x10, rho, &betas[1]); reproj_errors[1] = ComputeRT(Ut, betas[1], &Rs[1], &ts[1]); FindBetasApprox2(L6x10, rho, &betas[2]); RunGaussNewton(L6x10, rho, &betas[2]); reproj_errors[2] = ComputeRT(Ut, betas[2], &Rs[2], &ts[2]); FindBetasApprox3(L6x10, rho, &betas[3]); RunGaussNewton(L6x10, rho, &betas[3]); reproj_errors[3] = ComputeRT(Ut, betas[3], &Rs[3], &ts[3]); int best_idx = 1; if (reproj_errors[2] < reproj_errors[1]) { best_idx = 2; } if (reproj_errors[3] < reproj_errors[best_idx]) { best_idx = 3; } proj_matrix->leftCols<3>() = Rs[best_idx]; proj_matrix->rightCols<1>() = ts[best_idx]; return true; } void EPNPEstimator::ChooseControlPoints() { // Take C0 as the reference points centroid: cws_[0].setZero(); for (size_t i = 0; i < points3D_->size(); ++i) { cws_[0] += (*points3D_)[i]; } cws_[0] /= points3D_->size(); Eigen::Matrix PW0(points3D_->size(), 3); for (size_t i = 0; i < points3D_->size(); ++i) { PW0.row(i) = (*points3D_)[i] - cws_[0]; } const Eigen::Matrix3d PW0tPW0 = PW0.transpose() * PW0; Eigen::JacobiSVD svd( PW0tPW0, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Vector3d& D = svd.singularValues(); const Eigen::Matrix3d Ut = svd.matrixU().transpose(); for (int i = 1; i < 4; ++i) { const double k = std::sqrt(D(i - 1) / points3D_->size()); cws_[i] = cws_[0] + k * Ut.row(i - 1).transpose(); } } bool EPNPEstimator::ComputeBarycentricCoordinates() { Eigen::Matrix3d CC; for (int i = 0; i < 3; ++i) { for (int j = 1; j < 4; ++j) { CC(i, j - 1) = cws_[j][i] - cws_[0][i]; } } if (CC.colPivHouseholderQr().rank() < 3) { return false; } const Eigen::Matrix3d CC_inv = CC.inverse(); alphas_.resize(points2D_->size()); for (size_t i = 0; i < points3D_->size(); ++i) { for (int j = 0; j < 3; ++j) { alphas_[i][1 + j] = CC_inv(j, 0) * ((*points3D_)[i][0] - cws_[0][0]) + CC_inv(j, 1) * ((*points3D_)[i][1] - cws_[0][1]) + CC_inv(j, 2) * ((*points3D_)[i][2] - cws_[0][2]); } alphas_[i][0] = 1.0 - alphas_[i][1] - alphas_[i][2] - alphas_[i][3]; } return true; } Eigen::Matrix EPNPEstimator::ComputeM() { Eigen::Matrix M(2 * points2D_->size(), 12); for (size_t i = 0; i < points3D_->size(); ++i) { for (size_t j = 0; j < 4; ++j) { M(2 * i, 3 * j) = alphas_[i][j]; M(2 * i, 3 * j + 1) = 0.0; M(2 * i, 3 * j + 2) = -alphas_[i][j] * (*points2D_)[i].x(); M(2 * i + 1, 3 * j) = 0.0; M(2 * i + 1, 3 * j + 1) = alphas_[i][j]; M(2 * i + 1, 3 * j + 2) = -alphas_[i][j] * (*points2D_)[i].y(); } } return M; } Eigen::Matrix EPNPEstimator::ComputeL6x10( const Eigen::Matrix& Ut) { Eigen::Matrix L6x10; std::array, 4> dv; for (int i = 0; i < 4; ++i) { int a = 0, b = 1; for (int j = 0; j < 6; ++j) { dv[i][j][0] = Ut(11 - i, 3 * a) - Ut(11 - i, 3 * b); dv[i][j][1] = Ut(11 - i, 3 * a + 1) - Ut(11 - i, 3 * b + 1); dv[i][j][2] = Ut(11 - i, 3 * a + 2) - Ut(11 - i, 3 * b + 2); b += 1; if (b > 3) { a += 1; b = a + 1; } } } for (int i = 0; i < 6; ++i) { L6x10(i, 0) = dv[0][i].transpose() * dv[0][i]; L6x10(i, 1) = 2.0 * dv[0][i].transpose() * dv[1][i]; L6x10(i, 2) = dv[1][i].transpose() * dv[1][i]; L6x10(i, 3) = 2.0 * dv[0][i].transpose() * dv[2][i]; L6x10(i, 4) = 2.0 * dv[1][i].transpose() * dv[2][i]; L6x10(i, 5) = dv[2][i].transpose() * dv[2][i]; L6x10(i, 6) = 2.0 * dv[0][i].transpose() * dv[3][i]; L6x10(i, 7) = 2.0 * dv[1][i].transpose() * dv[3][i]; L6x10(i, 8) = 2.0 * dv[2][i].transpose() * dv[3][i]; L6x10(i, 9) = dv[3][i].transpose() * dv[3][i]; } return L6x10; } Eigen::Matrix EPNPEstimator::ComputeRho() { Eigen::Matrix rho; rho[0] = (cws_[0] - cws_[1]).squaredNorm(); rho[1] = (cws_[0] - cws_[2]).squaredNorm(); rho[2] = (cws_[0] - cws_[3]).squaredNorm(); rho[3] = (cws_[1] - cws_[2]).squaredNorm(); rho[4] = (cws_[1] - cws_[3]).squaredNorm(); rho[5] = (cws_[2] - cws_[3]).squaredNorm(); return rho; } // betas10 = [B11 B12 B22 B13 B23 B33 B14 B24 B34 B44] // betas_approx_1 = [B11 B12 B13 B14] void EPNPEstimator::FindBetasApprox1(const Eigen::Matrix& L6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas) { Eigen::Matrix L_6x4; for (int i = 0; i < 6; ++i) { L_6x4(i, 0) = L6x10(i, 0); L_6x4(i, 1) = L6x10(i, 1); L_6x4(i, 2) = L6x10(i, 3); L_6x4(i, 3) = L6x10(i, 6); } Eigen::JacobiSVD> svd( L_6x4, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix b4 = svd.solve(rho); if (b4[0] < 0) { (*betas)[0] = std::sqrt(-b4[0]); (*betas)[1] = -b4[1] / (*betas)[0]; (*betas)[2] = -b4[2] / (*betas)[0]; (*betas)[3] = -b4[3] / (*betas)[0]; } else { (*betas)[0] = std::sqrt(b4[0]); (*betas)[1] = b4[1] / (*betas)[0]; (*betas)[2] = b4[2] / (*betas)[0]; (*betas)[3] = b4[3] / (*betas)[0]; } } // betas10 = [B11 B12 B22 B13 B23 B33 B14 B24 B34 B44] // betas_approx_2 = [B11 B12 B22 ] void EPNPEstimator::FindBetasApprox2(const Eigen::Matrix& L6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas) { Eigen::Matrix L_6x3(6, 3); for (int i = 0; i < 6; ++i) { L_6x3(i, 0) = L6x10(i, 0); L_6x3(i, 1) = L6x10(i, 1); L_6x3(i, 2) = L6x10(i, 2); } Eigen::JacobiSVD> svd( L_6x3, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix b3 = svd.solve(rho); if (b3[0] < 0) { (*betas)[0] = std::sqrt(-b3[0]); (*betas)[1] = (b3[2] < 0) ? std::sqrt(-b3[2]) : 0.0; } else { (*betas)[0] = std::sqrt(b3[0]); (*betas)[1] = (b3[2] > 0) ? std::sqrt(b3[2]) : 0.0; } if (b3[1] < 0) { (*betas)[0] = -(*betas)[0]; } (*betas)[2] = 0.0; (*betas)[3] = 0.0; } // betas10 = [B11 B12 B22 B13 B23 B33 B14 B24 B34 B44] // betas_approx_3 = [B11 B12 B22 B13 B23 ] void EPNPEstimator::FindBetasApprox3(const Eigen::Matrix& L6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas) { Eigen::JacobiSVD> svd( L6x10.leftCols<5>(), Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix b5 = svd.solve(rho); if (b5[0] < 0) { (*betas)[0] = std::sqrt(-b5[0]); (*betas)[1] = (b5[2] < 0) ? std::sqrt(-b5[2]) : 0.0; } else { (*betas)[0] = std::sqrt(b5[0]); (*betas)[1] = (b5[2] > 0) ? std::sqrt(b5[2]) : 0.0; } if (b5[1] < 0) { (*betas)[0] = -(*betas)[0]; } (*betas)[2] = b5[3] / (*betas)[0]; (*betas)[3] = 0.0; } void EPNPEstimator::RunGaussNewton(const Eigen::Matrix& L6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas) { Eigen::Matrix A; Eigen::Matrix b; const int kNumIterations = 5; for (int k = 0; k < kNumIterations; ++k) { for (int i = 0; i < 6; ++i) { A(i, 0) = 2 * L6x10(i, 0) * (*betas)[0] + L6x10(i, 1) * (*betas)[1] + L6x10(i, 3) * (*betas)[2] + L6x10(i, 6) * (*betas)[3]; A(i, 1) = L6x10(i, 1) * (*betas)[0] + 2 * L6x10(i, 2) * (*betas)[1] + L6x10(i, 4) * (*betas)[2] + L6x10(i, 7) * (*betas)[3]; A(i, 2) = L6x10(i, 3) * (*betas)[0] + L6x10(i, 4) * (*betas)[1] + 2 * L6x10(i, 5) * (*betas)[2] + L6x10(i, 8) * (*betas)[3]; A(i, 3) = L6x10(i, 6) * (*betas)[0] + L6x10(i, 7) * (*betas)[1] + L6x10(i, 8) * (*betas)[2] + 2 * L6x10(i, 9) * (*betas)[3]; b(i) = rho[i] - (L6x10(i, 0) * (*betas)[0] * (*betas)[0] + L6x10(i, 1) * (*betas)[0] * (*betas)[1] + L6x10(i, 2) * (*betas)[1] * (*betas)[1] + L6x10(i, 3) * (*betas)[0] * (*betas)[2] + L6x10(i, 4) * (*betas)[1] * (*betas)[2] + L6x10(i, 5) * (*betas)[2] * (*betas)[2] + L6x10(i, 6) * (*betas)[0] * (*betas)[3] + L6x10(i, 7) * (*betas)[1] * (*betas)[3] + L6x10(i, 8) * (*betas)[2] * (*betas)[3] + L6x10(i, 9) * (*betas)[3] * (*betas)[3]); } const Eigen::Vector4d x = A.colPivHouseholderQr().solve(b); (*betas) += x; } } double EPNPEstimator::ComputeRT(const Eigen::Matrix& Ut, const Eigen::Vector4d& betas, Eigen::Matrix3d* R, Eigen::Vector3d* t) { ComputeCcs(betas, Ut); ComputePcs(); SolveForSign(); EstimateRT(R, t); return ComputeTotalReprojectionError(*R, *t); } void EPNPEstimator::ComputeCcs(const Eigen::Vector4d& betas, const Eigen::Matrix& Ut) { for (int i = 0; i < 4; ++i) { ccs_[i][0] = ccs_[i][1] = ccs_[i][2] = 0.0; } for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { for (int k = 0; k < 3; ++k) { ccs_[j][k] += betas[i] * Ut(11 - i, 3 * j + k); } } } } void EPNPEstimator::ComputePcs() { pcs_.resize(points2D_->size()); for (size_t i = 0; i < points3D_->size(); ++i) { for (int j = 0; j < 3; ++j) { pcs_[i][j] = alphas_[i][0] * ccs_[0][j] + alphas_[i][1] * ccs_[1][j] + alphas_[i][2] * ccs_[2][j] + alphas_[i][3] * ccs_[3][j]; } } } void EPNPEstimator::SolveForSign() { if (pcs_[0][2] < 0.0) { for (int i = 0; i < 4; ++i) { ccs_[i] = -ccs_[i]; } for (size_t i = 0; i < points3D_->size(); ++i) { pcs_[i] = -pcs_[i]; } } } void EPNPEstimator::EstimateRT(Eigen::Matrix3d* R, Eigen::Vector3d* t) { Eigen::Vector3d pc0 = Eigen::Vector3d::Zero(); Eigen::Vector3d pw0 = Eigen::Vector3d::Zero(); for (size_t i = 0; i < points3D_->size(); ++i) { pc0 += pcs_[i]; pw0 += (*points3D_)[i]; } pc0 /= points3D_->size(); pw0 /= points3D_->size(); Eigen::Matrix3d abt = Eigen::Matrix3d::Zero(); for (size_t i = 0; i < points3D_->size(); ++i) { for (int j = 0; j < 3; ++j) { abt(j, 0) += (pcs_[i][j] - pc0[j]) * ((*points3D_)[i][0] - pw0[0]); abt(j, 1) += (pcs_[i][j] - pc0[j]) * ((*points3D_)[i][1] - pw0[1]); abt(j, 2) += (pcs_[i][j] - pc0[j]) * ((*points3D_)[i][2] - pw0[2]); } } Eigen::JacobiSVD svd( abt, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix3d& abt_U = svd.matrixU(); const Eigen::Matrix3d& abt_V = svd.matrixV(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { (*R)(i, j) = abt_U.row(i) * abt_V.row(j).transpose(); } } if (R->determinant() < 0) { Eigen::Matrix3d Abt_v_prime = abt_V; Abt_v_prime.col(2) = -abt_V.col(2); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { (*R)(i, j) = abt_U.row(i) * Abt_v_prime.row(j).transpose(); } } } *t = pc0 - *R * pw0; } double EPNPEstimator::ComputeTotalReprojectionError(const Eigen::Matrix3d& R, const Eigen::Vector3d& t) { Eigen::Matrix3x4d proj_matrix; proj_matrix.leftCols<3>() = R; proj_matrix.rightCols<1>() = t; std::vector residuals; ComputeSquaredReprojectionError( *points2D_, *points3D_, proj_matrix, &residuals); double reproj_error = 0.0; for (const double residual : residuals) { reproj_error += std::sqrt(residual); } return reproj_error; } } // namespace colmap colmap-3.10/src/colmap/estimators/absolute_pose.h000066400000000000000000000165301464745566500222140ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/util/eigen_alignment.h" #include "colmap/util/types.h" #include #include #include namespace colmap { // Analytic solver for the P3P (Perspective-Three-Point) problem. // // The algorithm is based on the following paper: // // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang. Complete Solution // Classification for the Perspective-Three-Point Problem. // http://www.mmrc.iss.ac.cn/~xgao/paper/ieee.pdf class P3PEstimator { public: // The 2D image feature observations. typedef Eigen::Vector2d X_t; // The observed 3D features in the world frame. typedef Eigen::Vector3d Y_t; // The transformation from the world to the camera frame. typedef Eigen::Matrix3x4d M_t; // The minimum number of samples needed to estimate a model. static const int kMinNumSamples = 3; // Estimate the most probable solution of the P3P problem from a set of // three 2D-3D point correspondences. // // @param points2D Normalized 2D image points as 3x2 matrix. // @param points3D 3D world points as 3x3 matrix. // // @return Most probable pose as length-1 vector of a 3x4 matrix. static void Estimate(const std::vector& points2D, const std::vector& points3D, std::vector* models); // Calculate the squared reprojection error given a set of 2D-3D point // correspondences and a projection matrix. // // @param points2D Normalized 2D image points as Nx2 matrix. // @param points3D 3D world points as Nx3 matrix. // @param proj_matrix 3x4 projection matrix. // @param residuals Output vector of residuals. static void Residuals(const std::vector& points2D, const std::vector& points3D, const M_t& proj_matrix, std::vector* residuals); }; // EPNP solver for the PNP (Perspective-N-Point) problem. The solver needs a // minimum of 4 2D-3D correspondences. // // The algorithm is based on the following paper: // // Lepetit, Vincent, Francesc Moreno-Noguer, and Pascal Fua. // "Epnp: An accurate o (n) solution to the pnp problem." // International journal of computer vision 81.2 (2009): 155-166. // // The implementation is based on their original open-source release, but is // ported to Eigen and contains several improvements over the original code. class EPNPEstimator { public: // The 2D image feature observations. typedef Eigen::Vector2d X_t; // The observed 3D features in the world frame. typedef Eigen::Vector3d Y_t; // The transformation from the world to the camera frame. typedef Eigen::Matrix3x4d M_t; // The minimum number of samples needed to estimate a model. static const int kMinNumSamples = 4; // Estimate the most probable solution of the P3P problem from a set of // three 2D-3D point correspondences. // // @param points2D Normalized 2D image points as 3x2 matrix. // @param points3D 3D world points as 3x3 matrix. // // @return Most probable pose as length-1 vector of a 3x4 matrix. static void Estimate(const std::vector& points2D, const std::vector& points3D, std::vector* models); // Calculate the squared reprojection error given a set of 2D-3D point // correspondences and a projection matrix. // // @param points2D Normalized 2D image points as Nx2 matrix. // @param points3D 3D world points as Nx3 matrix. // @param proj_matrix 3x4 projection matrix. // @param residuals Output vector of residuals. static void Residuals(const std::vector& points2D, const std::vector& points3D, const M_t& proj_matrix, std::vector* residuals); private: bool ComputePose(const std::vector& points2D, const std::vector& points3D, Eigen::Matrix3x4d* proj_matrix); void ChooseControlPoints(); bool ComputeBarycentricCoordinates(); Eigen::Matrix ComputeM(); Eigen::Matrix ComputeL6x10( const Eigen::Matrix& Ut); Eigen::Matrix ComputeRho(); void FindBetasApprox1(const Eigen::Matrix& L_6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas); void FindBetasApprox2(const Eigen::Matrix& L_6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas); void FindBetasApprox3(const Eigen::Matrix& L_6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas); void RunGaussNewton(const Eigen::Matrix& L_6x10, const Eigen::Matrix& rho, Eigen::Vector4d* betas); double ComputeRT(const Eigen::Matrix& Ut, const Eigen::Vector4d& betas, Eigen::Matrix3d* R, Eigen::Vector3d* t); void ComputeCcs(const Eigen::Vector4d& betas, const Eigen::Matrix& Ut); void ComputePcs(); void SolveForSign(); void EstimateRT(Eigen::Matrix3d* R, Eigen::Vector3d* t); double ComputeTotalReprojectionError(const Eigen::Matrix3d& R, const Eigen::Vector3d& t); const std::vector* points2D_ = nullptr; const std::vector* points3D_ = nullptr; std::vector pcs_; std::vector alphas_; std::array cws_; std::array ccs_; }; } // namespace colmap colmap-3.10/src/colmap/estimators/absolute_pose_test.cc000066400000000000000000000204161464745566500234070ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/absolute_pose.h" #include "colmap/estimators/essential_matrix.h" #include "colmap/geometry/pose.h" #include "colmap/geometry/rigid3.h" #include "colmap/math/random.h" #include "colmap/optim/ransac.h" #include "colmap/util/eigen_alignment.h" #include #include namespace colmap { namespace { TEST(AbsolutePose, P3P) { const std::vector points3D = { Eigen::Vector3d(1, 1, 1), Eigen::Vector3d(0, 1, 1), Eigen::Vector3d(3, 1.0, 4), Eigen::Vector3d(3, 1.1, 4), Eigen::Vector3d(3, 1.2, 4), Eigen::Vector3d(3, 1.3, 4), Eigen::Vector3d(3, 1.4, 4), Eigen::Vector3d(2, 1, 7), }; auto points3D_faulty = points3D; for (size_t i = 0; i < points3D.size(); ++i) { points3D_faulty[i](0) = 20; } // NOLINTNEXTLINE(clang-analyzer-security.FloatLoopCounter) for (double qx = 0; qx < 1; qx += 0.2) { // NOLINTNEXTLINE(clang-analyzer-security.FloatLoopCounter) for (double tx = 0; tx < 1; tx += 0.1) { const Rigid3d expected_cam_from_world( Eigen::Quaterniond(1, qx, 0, 0).normalized(), Eigen::Vector3d(tx, 0, 0)); // Project points to camera coordinate system. std::vector points2D; for (size_t i = 0; i < points3D.size(); ++i) { points2D.push_back( (expected_cam_from_world * points3D[i]).hnormalized()); } RANSACOptions options; options.max_error = 1e-5; RANSAC ransac(options); const auto report = ransac.Estimate(points2D, points3D); EXPECT_TRUE(report.success); EXPECT_LT((expected_cam_from_world.ToMatrix() - report.model).norm(), 1e-2); // Test residuals of exact points. std::vector residuals; P3PEstimator::Residuals(points2D, points3D, report.model, &residuals); for (size_t i = 0; i < residuals.size(); ++i) { EXPECT_TRUE(residuals[i] < 1e-3); } // Test residuals of faulty points. P3PEstimator::Residuals( points2D, points3D_faulty, report.model, &residuals); for (size_t i = 0; i < residuals.size(); ++i) { EXPECT_TRUE(residuals[i] > 0.1); } } } } TEST(AbsolutePose, EPNP) { const std::vector points3D = { Eigen::Vector3d(1, 1, 1), Eigen::Vector3d(0, 1, 1), Eigen::Vector3d(3, 1.0, 4), Eigen::Vector3d(3, 1.1, 4), Eigen::Vector3d(3, 1.2, 4), Eigen::Vector3d(3, 1.3, 4), Eigen::Vector3d(3, 1.4, 4), Eigen::Vector3d(2, 1, 7), }; auto points3D_faulty = points3D; for (size_t i = 0; i < points3D.size(); ++i) { points3D_faulty[i](0) = 20; } // NOLINTNEXTLINE(clang-analyzer-security.FloatLoopCounter) for (double qx = 0; qx < 1; qx += 0.2) { // NOLINTNEXTLINE(clang-analyzer-security.FloatLoopCounter) for (double tx = 0; tx < 1; tx += 0.1) { const Rigid3d expected_cam_from_world( Eigen::Quaterniond(1, qx, 0, 0).normalized(), Eigen::Vector3d(tx, 0, 0)); // Project points to camera coordinate system. std::vector points2D; for (size_t i = 0; i < points3D.size(); ++i) { points2D.push_back( (expected_cam_from_world * points3D[i]).hnormalized()); } RANSACOptions options; options.max_error = 1e-5; RANSAC ransac(options); const auto report = ransac.Estimate(points2D, points3D); EXPECT_TRUE(report.success); EXPECT_LT((expected_cam_from_world.ToMatrix() - report.model).norm(), 1e-4); // Test residuals of exact points. std::vector residuals; EPNPEstimator::Residuals(points2D, points3D, report.model, &residuals); for (size_t i = 0; i < residuals.size(); ++i) { EXPECT_TRUE(residuals[i] < 1e-3); } // Test residuals of faulty points. EPNPEstimator::Residuals( points2D, points3D_faulty, report.model, &residuals); for (size_t i = 0; i < residuals.size(); ++i) { EXPECT_TRUE(residuals[i] > 0.1); } } } } TEST(AbsolutePose, EPNP_BrokenSolveSignCase) { std::vector points2D; points2D.emplace_back(-2.6783007931074532e-01, 5.3457197430746251e-01); points2D.emplace_back(-4.2629907287470264e-01, 7.5623350319519789e-01); points2D.emplace_back(-1.6767413005963930e-01, -1.3387172544910089e-01); points2D.emplace_back(-5.6616329720373559e-02, 2.3621156497739373e-01); points2D.emplace_back(-1.7721225948969935e-01, 2.3395366792735982e-02); points2D.emplace_back(-5.1836259886632222e-02, -4.4380694271927049e-02); points2D.emplace_back(-3.5897765845560037e-01, 1.6252721078589397e-01); points2D.emplace_back(2.7057324473684058e-01, -1.4067450104631887e-01); points2D.emplace_back(-2.5811166424334520e-01, 8.0167171300227366e-02); points2D.emplace_back(2.0239567448222310e-02, -3.2845953375344145e-01); points2D.emplace_back(4.2571014715170657e-01, -2.8321173570154773e-01); points2D.emplace_back(-5.4597596412987237e-01, 9.1431935871671977e-02); std::vector points3D; points3D.emplace_back( 4.4276865308679305e+00, -1.3384364366019632e+00, -3.5997423085253892e+00); points3D.emplace_back( 2.7278555252512309e+00, -3.8152996187231392e-01, -2.6558518399902824e+00); points3D.emplace_back( 4.8548566083054894e+00, -1.4756197433631739e+00, -6.8274946022490501e-01); points3D.emplace_back( 3.1523013527998449e+00, -1.3377020437938025e+00, -1.6443269301929087e+00); points3D.emplace_back( 3.8551679771512073e+00, -1.0557700545885551e+00, -1.1695994508851486e+00); points3D.emplace_back( 5.9571373150353812e+00, -2.6120646101684555e+00, -1.0841441206050342e+00); points3D.emplace_back( 6.3287088499358894e+00, -1.1761274755817175e+00, -2.5951879774151583e+00); points3D.emplace_back( 2.3005305990121250e+00, -1.4019796626800123e+00, -4.4485464455072321e-01); points3D.emplace_back( 5.9816859934587354e+00, -1.4211814511691452e+00, -2.0285923889293449e+00); points3D.emplace_back( 5.2543344690665457e+00, -2.3389255564264144e+00, 4.3708173185524052e-01); points3D.emplace_back( 3.2181599245991688e+00, -2.8906671988445098e+00, 2.6825718150064348e-01); points3D.emplace_back( 4.4592895306946758e+00, -9.1235241641579902e-03, -1.6555237117970871e+00); std::vector models; EPNPEstimator::Estimate(points2D, points3D, &models); ASSERT_EQ(models.size(), 1); double reproj = 0.0; for (size_t i = 0; i < points3D.size(); ++i) { reproj += ((models[0] * points3D[i].homogeneous()).hnormalized() - points2D[i]) .norm(); } EXPECT_TRUE(reproj < 0.2); } } // namespace } // namespace colmap colmap-3.10/src/colmap/estimators/affine_transform.cc000066400000000000000000000100121464745566500230160ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/affine_transform.h" #include "colmap/util/eigen_alignment.h" #include "colmap/util/logging.h" #include namespace colmap { void AffineTransformEstimator::Estimate(const std::vector& points1, const std::vector& points2, std::vector* models) { THROW_CHECK_EQ(points1.size(), points2.size()); THROW_CHECK_GE(points1.size(), 3); THROW_CHECK(models != nullptr); models->clear(); // Sets up the linear system that we solve to obtain a least squared solution // for the affine transformation. Eigen::MatrixXd C(2 * points1.size(), 6); C.setZero(); Eigen::VectorXd b(2 * points1.size(), 1); for (size_t i = 0; i < points1.size(); ++i) { const Eigen::Vector2d& x1 = points1[i]; const Eigen::Vector2d& x2 = points2[i]; C(2 * i, 0) = x1(0); C(2 * i, 1) = x1(1); C(2 * i, 2) = 1.0f; b(2 * i) = x2(0); C(2 * i + 1, 3) = x1(0); C(2 * i + 1, 4) = x1(1); C(2 * i + 1, 5) = 1.0f; b(2 * i + 1) = x2(1); } const Eigen::VectorXd nullspace = C.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b); Eigen::Map> A_t(nullspace.data()); models->resize(1); (*models)[0] = A_t.transpose(); } void AffineTransformEstimator::Residuals(const std::vector& points1, const std::vector& points2, const M_t& A, std::vector* residuals) { THROW_CHECK_EQ(points1.size(), points2.size()); residuals->resize(points1.size()); // Note that this code might not be as nice as Eigen expressions, // but it is significantly faster in various tests. const double A_00 = A(0, 0); const double A_01 = A(0, 1); const double A_02 = A(0, 2); const double A_10 = A(1, 0); const double A_11 = A(1, 1); const double A_12 = A(1, 2); for (size_t i = 0; i < points1.size(); ++i) { const double s_0 = points1[i](0); const double s_1 = points1[i](1); const double d_0 = points2[i](0); const double d_1 = points2[i](1); const double pd_0 = A_00 * s_0 + A_01 * s_1 + A_02; const double pd_1 = A_10 * s_0 + A_11 * s_1 + A_12; const double dd_0 = d_0 - pd_0; const double dd_1 = d_1 - pd_1; (*residuals)[i] = dd_0 * dd_0 + dd_1 * dd_1; } } } // namespace colmap colmap-3.10/src/colmap/estimators/affine_transform.h000066400000000000000000000047671464745566500227040ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/util/eigen_alignment.h" #include "colmap/util/types.h" #include #include namespace colmap { class AffineTransformEstimator { public: typedef Eigen::Vector2d X_t; typedef Eigen::Vector2d Y_t; typedef Eigen::Matrix M_t; // The minimum number of samples needed to estimate a model. static const int kMinNumSamples = 3; // Estimate the affine transformation from at least 3 correspondences. static void Estimate(const std::vector& points1, const std::vector& points2, std::vector* models); // Compute the squared transformation error. static void Residuals(const std::vector& points1, const std::vector& points2, const M_t& E, std::vector* residuals); }; } // namespace colmap colmap-3.10/src/colmap/estimators/affine_transform_test.cc000066400000000000000000000051101464745566500240600ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/affine_transform.h" #include "colmap/util/eigen_alignment.h" #include #include namespace colmap { namespace { TEST(AffineTransform, Nominal) { for (int x = 0; x < 10; ++x) { Eigen::Matrix A; A << x / 10.0, 0.2, 0.3, 30, 0.2, 0.1; std::vector src; src.emplace_back(x, 0); src.emplace_back(1, 0); src.emplace_back(2, 1); std::vector dst; for (size_t i = 0; i < 3; ++i) { dst.push_back(A * src[i].homogeneous()); } AffineTransformEstimator estimator; std::vector> models; estimator.Estimate(src, dst, &models); ASSERT_EQ(models.size(), 1); std::vector residuals; estimator.Residuals(src, dst, models[0], &residuals); EXPECT_EQ(residuals.size(), 3); for (size_t i = 0; i < 3; ++i) { EXPECT_LT(residuals[i], 1e-6); } } } } // namespace } // namespace colmap colmap-3.10/src/colmap/estimators/alignment.cc000066400000000000000000000450411464745566500214630ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/alignment.h" #include "colmap/estimators/similarity_transform.h" #include "colmap/geometry/pose.h" #include "colmap/optim/loransac.h" #include "colmap/scene/projection.h" #include "colmap/util/logging.h" #include namespace colmap { namespace { struct ReconstructionAlignmentEstimator { static const int kMinNumSamples = 3; typedef const Image* X_t; typedef const Image* Y_t; typedef Sim3d M_t; void SetMaxReprojError(const double max_reproj_error) { max_squared_reproj_error_ = max_reproj_error * max_reproj_error; } void SetReconstructions(const Reconstruction* src_reconstruction, const Reconstruction* tgt_reconstruction) { THROW_CHECK_NOTNULL(src_reconstruction); THROW_CHECK_NOTNULL(tgt_reconstruction); src_reconstruction_ = src_reconstruction; tgt_reconstruction_ = tgt_reconstruction; } // Estimate 3D similarity transform from corresponding projection centers. void Estimate(const std::vector& src_images, const std::vector& tgt_images, std::vector* models) const { THROW_CHECK_GE(src_images.size(), 3); THROW_CHECK_GE(tgt_images.size(), 3); THROW_CHECK_EQ(src_images.size(), tgt_images.size()); THROW_CHECK(models != nullptr); models->clear(); std::vector proj_centers1(src_images.size()); std::vector proj_centers2(tgt_images.size()); for (size_t i = 0; i < src_images.size(); ++i) { THROW_CHECK_EQ(src_images[i]->ImageId(), tgt_images[i]->ImageId()); proj_centers1[i] = src_images[i]->ProjectionCenter(); proj_centers2[i] = tgt_images[i]->ProjectionCenter(); } Sim3d tgt_from_src; if (!EstimateSim3d(proj_centers1, proj_centers2, tgt_from_src)) { return; } models->resize(1); (*models)[0] = tgt_from_src; } // For each image, determine the ratio of 3D points that correctly project // from one image to the other image and vice versa for the given // tgt_from_src. The residual is then defined as 1 minus this ratio, i.e., an // error threshold of 0.3 means that 70% of the points for that image must // reproject within the given maximum reprojection error threshold. void Residuals(const std::vector& src_images, const std::vector& tgt_images, const M_t& tgt_from_src, std::vector* residuals) const { THROW_CHECK_EQ(src_images.size(), tgt_images.size()); THROW_CHECK_NOTNULL(src_reconstruction_); THROW_CHECK_NOTNULL(tgt_reconstruction_); const Sim3d srcFromTgt = Inverse(tgt_from_src); residuals->resize(src_images.size()); for (size_t i = 0; i < src_images.size(); ++i) { const auto& src_image = *src_images[i]; const auto& tgt_image = *tgt_images[i]; THROW_CHECK_EQ(src_image.ImageId(), tgt_image.ImageId()); const auto& src_camera = src_reconstruction_->Camera(src_image.CameraId()); const auto& tgt_camera = tgt_reconstruction_->Camera(tgt_image.CameraId()); const Eigen::Matrix3x4d src_cam_from_world = src_image.CamFromWorld().ToMatrix(); const Eigen::Matrix3x4d tgt_cam_from_world = tgt_image.CamFromWorld().ToMatrix(); THROW_CHECK_EQ(src_image.NumPoints2D(), tgt_image.NumPoints2D()); size_t num_inliers = 0; size_t num_common_points = 0; for (point2D_t point2D_idx = 0; point2D_idx < src_image.NumPoints2D(); ++point2D_idx) { // Check if both images have a 3D point. const auto& src_point2D = src_image.Point2D(point2D_idx); if (!src_point2D.HasPoint3D()) { continue; } const auto& tgt_point2D = tgt_image.Point2D(point2D_idx); if (!tgt_point2D.HasPoint3D()) { continue; } num_common_points += 1; const Eigen::Vector3d src_point_in_tgt = tgt_from_src * src_reconstruction_->Point3D(src_point2D.point3D_id).xyz; if (CalculateSquaredReprojectionError(tgt_point2D.xy, src_point_in_tgt, tgt_cam_from_world, tgt_camera) > max_squared_reproj_error_) { continue; } const Eigen::Vector3d tgt_point_in_src = srcFromTgt * tgt_reconstruction_->Point3D(tgt_point2D.point3D_id).xyz; if (CalculateSquaredReprojectionError(src_point2D.xy, tgt_point_in_src, src_cam_from_world, src_camera) > max_squared_reproj_error_) { continue; } num_inliers += 1; } if (num_common_points == 0) { (*residuals)[i] = 1.0; } else { const double negative_inlier_ratio = 1.0 - static_cast(num_inliers) / static_cast(num_common_points); (*residuals)[i] = negative_inlier_ratio * negative_inlier_ratio; } } } private: double max_squared_reproj_error_ = 0.0; const Reconstruction* src_reconstruction_ = nullptr; const Reconstruction* tgt_reconstruction_ = nullptr; }; } // namespace bool AlignReconstructionToLocations( const Reconstruction& src_reconstruction, const std::vector& tgt_image_names, const std::vector& tgt_image_locations, const int min_common_images, const RANSACOptions& ransac_options, Sim3d* tgt_from_src) { THROW_CHECK_GE(min_common_images, 3); THROW_CHECK_EQ(tgt_image_names.size(), tgt_image_locations.size()); // Find out which images are contained in the reconstruction and get the // positions of their camera centers. std::unordered_set common_image_ids; std::vector src; std::vector dst; for (size_t i = 0; i < tgt_image_names.size(); ++i) { const class Image* src_image = src_reconstruction.FindImageWithName(tgt_image_names[i]); if (src_image == nullptr) { continue; } if (!src_reconstruction.IsImageRegistered(src_image->ImageId())) { continue; } // Ignore duplicate images. if (common_image_ids.count(src_image->ImageId()) > 0) { continue; } common_image_ids.insert(src_image->ImageId()); src.push_back(src_image->ProjectionCenter()); dst.push_back(tgt_image_locations[i]); } // Only compute the alignment if there are enough correspondences. if (common_image_ids.size() < static_cast(min_common_images)) { return false; } LORANSAC, SimilarityTransformEstimator<3, true>> ransac(ransac_options); const auto report = ransac.Estimate(src, dst); if (report.support.num_inliers < static_cast(min_common_images)) { return false; } if (tgt_from_src != nullptr) { *tgt_from_src = Sim3d::FromMatrix(report.model); } return true; } bool AlignReconstructionsViaReprojections( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, const double min_inlier_observations, const double max_reproj_error, Sim3d* tgt_from_src) { THROW_CHECK_GE(min_inlier_observations, 0.0); THROW_CHECK_LE(min_inlier_observations, 1.0); RANSACOptions ransac_options; ransac_options.max_error = 1.0 - min_inlier_observations; ransac_options.min_inlier_ratio = 0.2; LORANSAC ransac(ransac_options); ransac.estimator.SetMaxReprojError(max_reproj_error); ransac.estimator.SetReconstructions(&src_reconstruction, &tgt_reconstruction); ransac.local_estimator.SetMaxReprojError(max_reproj_error); ransac.local_estimator.SetReconstructions(&src_reconstruction, &tgt_reconstruction); const std::vector> common_image_ids = src_reconstruction.FindCommonRegImageIds(tgt_reconstruction); if (common_image_ids.size() < 3) { return false; } std::vector src_images(common_image_ids.size()); std::vector tgt_images(common_image_ids.size()); for (size_t i = 0; i < common_image_ids.size(); ++i) { src_images[i] = &src_reconstruction.Image(common_image_ids[i].first); tgt_images[i] = &tgt_reconstruction.Image(common_image_ids[i].second); } const auto report = ransac.Estimate(src_images, tgt_images); if (report.success) { *tgt_from_src = report.model; } return report.success; } bool AlignReconstructionsViaProjCenters( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, const double max_proj_center_error, Sim3d* tgt_from_src) { THROW_CHECK_GT(max_proj_center_error, 0); std::vector ref_image_names; std::vector ref_proj_centers; for (const auto& image : tgt_reconstruction.Images()) { if (image.second.IsRegistered()) { ref_image_names.push_back(image.second.Name()); ref_proj_centers.push_back(image.second.ProjectionCenter()); } } Sim3d tform; RANSACOptions ransac_options; ransac_options.max_error = max_proj_center_error; return AlignReconstructionToLocations(src_reconstruction, ref_image_names, ref_proj_centers, /*min_common_images=*/3, ransac_options, tgt_from_src); } std::vector ComputeImageAlignmentError( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, const Sim3d& tgt_from_src) { const std::vector> common_image_ids = src_reconstruction.FindCommonRegImageIds(tgt_reconstruction); const int num_common_images = common_image_ids.size(); std::vector errors; errors.reserve(num_common_images); for (const auto& image_ids : common_image_ids) { const auto& src_image = src_reconstruction.Image(image_ids.first); const Rigid3d tgt_world_from_src_cam = Inverse(TransformCameraWorld(tgt_from_src, src_image.CamFromWorld())); const Rigid3d tgt_world_from_tgt_cam = Inverse(tgt_reconstruction.Image(image_ids.second).CamFromWorld()); ImageAlignmentError error; error.image_name = src_image.Name(); error.rotation_error_deg = RadToDeg(tgt_world_from_src_cam.rotation.angularDistance( tgt_world_from_tgt_cam.rotation)); error.proj_center_error = (tgt_world_from_src_cam.translation - tgt_world_from_tgt_cam.translation) .norm(); errors.push_back(error); } return errors; } bool AlignReconstructionsViaPoints(const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, const size_t min_common_observations, const double max_error, const double min_inlier_ratio, Sim3d* tgt_from_src) { THROW_CHECK_GT(min_common_observations, 0); THROW_CHECK_GT(max_error, 0.0); THROW_CHECK_GE(min_inlier_ratio, 0.0); THROW_CHECK_LE(min_inlier_ratio, 1.0); std::vector src_xyz; std::vector tgt_xyz; std::unordered_map counts; // Associate 3D points using point2D_idx for (const auto& src_point3D : src_reconstruction.Points3D()) { counts.clear(); // Count how often a 3D point in tgt is associated to this 3D point. for (const auto& track_el : src_point3D.second.track.Elements()) { if (!tgt_reconstruction.IsImageRegistered(track_el.image_id)) { continue; } const Point2D& tgt_point2D = tgt_reconstruction.Image(track_el.image_id) .Point2D(track_el.point2D_idx); if (tgt_point2D.HasPoint3D()) { if (counts.find(tgt_point2D.point3D_id) != counts.end()) { counts[tgt_point2D.point3D_id]++; } else { counts[tgt_point2D.point3D_id] = 0; } } } if (counts.empty()) { continue; } // The 3D point in tgt who is associated the most is selected auto best_p3D = std::max_element(counts.begin(), counts.end(), [](const std::pair& p1, const std::pair& p2) { return p1.second < p2.second; }); if (best_p3D->second >= min_common_observations) { src_xyz.push_back(src_point3D.second.xyz); tgt_xyz.push_back(tgt_reconstruction.Point3D(best_p3D->first).xyz); } } THROW_CHECK_EQ(src_xyz.size(), tgt_xyz.size()); LOG(INFO) << "Found " << src_xyz.size() << " / " << src_reconstruction.NumPoints3D() << " valid correspondences."; RANSACOptions ransac_options; ransac_options.max_error = max_error; ransac_options.min_inlier_ratio = min_inlier_ratio; LORANSAC, SimilarityTransformEstimator<3, true>> ransac(ransac_options); const auto report = ransac.Estimate(src_xyz, tgt_xyz); if (report.success) { *tgt_from_src = Sim3d::FromMatrix(report.model); } return report.success; } bool MergeReconstructions(const double max_reproj_error, const Reconstruction& src_reconstruction, Reconstruction& tgt_reconstruction) { Sim3d tgt_from_src; if (!AlignReconstructionsViaReprojections(src_reconstruction, tgt_reconstruction, /*min_inlier_observations=*/0.3, max_reproj_error, &tgt_from_src)) { return false; } // Find common and missing images in the two reconstructions. std::unordered_set common_image_ids; common_image_ids.reserve(src_reconstruction.NumRegImages()); std::unordered_set missing_image_ids; missing_image_ids.reserve(src_reconstruction.NumRegImages()); for (const auto& image_id : src_reconstruction.RegImageIds()) { if (tgt_reconstruction.ExistsImage(image_id)) { common_image_ids.insert(image_id); } else { missing_image_ids.insert(image_id); } } // Register the missing images in this src_reconstruction. for (const auto image_id : missing_image_ids) { auto src_image = src_reconstruction.Image(image_id); src_image.SetRegistered(false); src_image.CamFromWorld() = TransformCameraWorld(tgt_from_src, src_image.CamFromWorld()); tgt_reconstruction.AddImage(src_image); tgt_reconstruction.RegisterImage(image_id); if (!tgt_reconstruction.ExistsCamera(src_image.CameraId())) { tgt_reconstruction.AddCamera( src_reconstruction.Camera(src_image.CameraId())); } } // Merge the two point clouds using the following two rules: // - copy points to this src_reconstruction with non-conflicting tracks, // i.e. points that do not have an already triangulated observation // in this src_reconstruction. // - merge tracks that are unambiguous, i.e. only merge points in the two // reconstructions if they have a one-to-one mapping. // Note that in both cases no cheirality or reprojection test is performed. for (const auto& point3D : src_reconstruction.Points3D()) { Track new_track; Track old_track; std::unordered_set old_point3D_ids; for (const auto& track_el : point3D.second.track.Elements()) { if (common_image_ids.count(track_el.image_id) > 0) { const auto& point2D = tgt_reconstruction.Image(track_el.image_id) .Point2D(track_el.point2D_idx); if (point2D.HasPoint3D()) { old_track.AddElement(track_el); old_point3D_ids.insert(point2D.point3D_id); } else { new_track.AddElement(track_el); } } else if (missing_image_ids.count(track_el.image_id) > 0) { tgt_reconstruction.Image(track_el.image_id) .ResetPoint3DForPoint2D(track_el.point2D_idx); new_track.AddElement(track_el); } } const bool create_new_point = new_track.Length() >= 2; const bool merge_new_and_old_point = (new_track.Length() + old_track.Length()) >= 2 && old_point3D_ids.size() == 1; if (create_new_point || merge_new_and_old_point) { const Eigen::Vector3d xyz = tgt_from_src * point3D.second.xyz; const auto point3D_id = tgt_reconstruction.AddPoint3D(xyz, new_track, point3D.second.color); if (old_point3D_ids.size() == 1) { tgt_reconstruction.MergePoints3D(point3D_id, *old_point3D_ids.begin()); } } } return true; } } // namespace colmap colmap-3.10/src/colmap/estimators/alignment.h000066400000000000000000000106031464745566500213210ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/geometry/sim3.h" #include "colmap/optim/ransac.h" #include "colmap/scene/reconstruction.h" namespace colmap { bool AlignReconstructionToLocations( const Reconstruction& reconstruction, const std::vector& image_names, const std::vector& locations, int min_common_images, const RANSACOptions& ransac_options, Sim3d* tform); // Robustly compute alignment between reconstructions by finding images that // are registered in both reconstructions. The alignment is then estimated // robustly inside RANSAC from corresponding projection centers. An alignment // is verified by reprojecting common 3D point observations. // The min_inlier_observations threshold determines how many observations // in a common image must reproject within the given threshold. bool AlignReconstructionsViaReprojections( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, double min_inlier_observations, double max_reproj_error, Sim3d* tgt_from_src); // Robustly compute alignment between reconstructions by finding images that // are registered in both reconstructions. The alignment is then estimated // robustly inside RANSAC from corresponding projection centers and by // minimizing the Euclidean distance between them in world space. bool AlignReconstructionsViaProjCenters( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, double max_proj_center_error, Sim3d* tgt_from_src); // Robustly compute the alignment between reconstructions that share the // same 2D points. It is estimated by minimizing the 3D distance between // corresponding 3D points. bool AlignReconstructionsViaPoints(const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, size_t min_common_observations, double max_error, double min_inlier_ratio, Sim3d* tgt_from_src); // Compute image alignment errors in the target coordinate frame. struct ImageAlignmentError { std::string image_name; double rotation_error_deg = -1; double proj_center_error = -1; }; std::vector ComputeImageAlignmentError( const Reconstruction& src_reconstruction, const Reconstruction& tgt_reconstruction, const Sim3d& tgt_from_src); // Aligns the source to the target reconstruction and merges cameras, images, // points3D into the target using the alignment. Returns false on failure. bool MergeReconstructions(double max_reproj_error, const Reconstruction& src_reconstruction, Reconstruction& tgt_reconstruction); } // namespace colmap colmap-3.10/src/colmap/estimators/alignment_test.cc000066400000000000000000000117231464745566500225220ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/alignment.h" #include "colmap/geometry/sim3.h" #include "colmap/math/random.h" #include "colmap/scene/database.h" #include "colmap/scene/reconstruction.h" #include "colmap/scene/synthetic.h" #include "colmap/util/testing.h" #include namespace colmap { Sim3d TestSim3d() { return Sim3d(RandomUniformReal(0.5, 2), Eigen::Quaterniond::UnitRandom(), Eigen::Vector3d::Random()); } void ExpectEqualSim3d(const Sim3d& gt_tgt_from_src, const Sim3d& tgt_from_src) { EXPECT_NEAR(gt_tgt_from_src.scale, tgt_from_src.scale, 1e-6); EXPECT_LT(gt_tgt_from_src.rotation.angularDistance(tgt_from_src.rotation), 1e-6); EXPECT_LT((gt_tgt_from_src.translation - tgt_from_src.translation).norm(), 1e-6); } Reconstruction GenerateReconstructionForAlignment() { // const std::string database_path = CreateTestDir() + "/database.db"; // Database database(database_path); Reconstruction reconstruction; SyntheticDatasetOptions synthetic_dataset_options; synthetic_dataset_options.num_cameras = 2; synthetic_dataset_options.num_images = 20; synthetic_dataset_options.num_points3D = 50; synthetic_dataset_options.point2D_stddev = 0; SynthesizeDataset(synthetic_dataset_options, &reconstruction); return reconstruction; } TEST(Alignment, AlignReconstructionsViaReprojections) { Reconstruction src_reconstruction = GenerateReconstructionForAlignment(); Reconstruction tgt_reconstruction = src_reconstruction; Sim3d gt_tgt_from_src = TestSim3d(); tgt_reconstruction.Transform(gt_tgt_from_src); Sim3d tgt_from_src; THROW_CHECK( AlignReconstructionsViaReprojections(src_reconstruction, tgt_reconstruction, /*min_inlier_observations=*/0.9, /*max_reproj_error=*/2, &tgt_from_src)); ExpectEqualSim3d(gt_tgt_from_src, tgt_from_src); } TEST(Alignment, AlignReconstructionsViaProjCenters) { Reconstruction src_reconstruction = GenerateReconstructionForAlignment(); Reconstruction tgt_reconstruction = src_reconstruction; Sim3d gt_tgt_from_src = TestSim3d(); tgt_reconstruction.Transform(gt_tgt_from_src); Sim3d tgt_from_src; THROW_CHECK(AlignReconstructionsViaProjCenters(src_reconstruction, tgt_reconstruction, /*max_proj_center_error=*/0.1, &tgt_from_src)); ExpectEqualSim3d(gt_tgt_from_src, tgt_from_src); } TEST(Alignment, AlignReconstructionsViaPoints) { Reconstruction src_reconstruction = GenerateReconstructionForAlignment(); Reconstruction tgt_reconstruction = src_reconstruction; Sim3d gt_tgt_from_src = TestSim3d(); tgt_reconstruction.Transform(gt_tgt_from_src); Sim3d tgt_from_src; THROW_CHECK(AlignReconstructionsViaPoints(src_reconstruction, tgt_reconstruction, /*min_common_observations=*/3, /*max_error=*/0.01, /*min_inlier_ratio=*/0.9, &tgt_from_src)); ExpectEqualSim3d(gt_tgt_from_src, tgt_from_src); } } // namespace colmap colmap-3.10/src/colmap/estimators/bundle_adjustment.cc000066400000000000000000000761571464745566500232300ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/bundle_adjustment.h" #include "colmap/estimators/cost_functions.h" #include "colmap/scene/projection.h" #include "colmap/sensor/models.h" #include "colmap/util/misc.h" #include "colmap/util/threading.h" #include "colmap/util/timer.h" #include namespace colmap { //////////////////////////////////////////////////////////////////////////////// // BundleAdjustmentOptions //////////////////////////////////////////////////////////////////////////////// ceres::LossFunction* BundleAdjustmentOptions::CreateLossFunction() const { ceres::LossFunction* loss_function = nullptr; switch (loss_function_type) { case LossFunctionType::TRIVIAL: loss_function = new ceres::TrivialLoss(); break; case LossFunctionType::SOFT_L1: loss_function = new ceres::SoftLOneLoss(loss_function_scale); break; case LossFunctionType::CAUCHY: loss_function = new ceres::CauchyLoss(loss_function_scale); break; } THROW_CHECK_NOTNULL(loss_function); return loss_function; } bool BundleAdjustmentOptions::Check() const { CHECK_OPTION_GE(loss_function_scale, 0); return true; } //////////////////////////////////////////////////////////////////////////////// // BundleAdjustmentConfig //////////////////////////////////////////////////////////////////////////////// BundleAdjustmentConfig::BundleAdjustmentConfig() {} size_t BundleAdjustmentConfig::NumImages() const { return image_ids_.size(); } size_t BundleAdjustmentConfig::NumPoints() const { return variable_point3D_ids_.size() + constant_point3D_ids_.size(); } size_t BundleAdjustmentConfig::NumConstantCamIntrinsics() const { return constant_intrinsics_.size(); } size_t BundleAdjustmentConfig::NumConstantCamPoses() const { return constant_cam_poses_.size(); } size_t BundleAdjustmentConfig::NumConstantCamPositions() const { return constant_cam_positions_.size(); } size_t BundleAdjustmentConfig::NumVariablePoints() const { return variable_point3D_ids_.size(); } size_t BundleAdjustmentConfig::NumConstantPoints() const { return constant_point3D_ids_.size(); } size_t BundleAdjustmentConfig::NumResiduals( const Reconstruction& reconstruction) const { // Count the number of observations for all added images. size_t num_observations = 0; for (const image_t image_id : image_ids_) { num_observations += reconstruction.Image(image_id).NumPoints3D(); } // Count the number of observations for all added 3D points that are not // already added as part of the images above. auto NumObservationsForPoint = [this, &reconstruction](const point3D_t point3D_id) { size_t num_observations_for_point = 0; const auto& point3D = reconstruction.Point3D(point3D_id); for (const auto& track_el : point3D.track.Elements()) { if (image_ids_.count(track_el.image_id) == 0) { num_observations_for_point += 1; } } return num_observations_for_point; }; for (const auto point3D_id : variable_point3D_ids_) { num_observations += NumObservationsForPoint(point3D_id); } for (const auto point3D_id : constant_point3D_ids_) { num_observations += NumObservationsForPoint(point3D_id); } return 2 * num_observations; } void BundleAdjustmentConfig::AddImage(const image_t image_id) { image_ids_.insert(image_id); } bool BundleAdjustmentConfig::HasImage(const image_t image_id) const { return image_ids_.find(image_id) != image_ids_.end(); } void BundleAdjustmentConfig::RemoveImage(const image_t image_id) { image_ids_.erase(image_id); } void BundleAdjustmentConfig::SetConstantCamIntrinsics( const camera_t camera_id) { constant_intrinsics_.insert(camera_id); } void BundleAdjustmentConfig::SetVariableCamIntrinsics( const camera_t camera_id) { constant_intrinsics_.erase(camera_id); } bool BundleAdjustmentConfig::HasConstantCamIntrinsics( const camera_t camera_id) const { return constant_intrinsics_.find(camera_id) != constant_intrinsics_.end(); } void BundleAdjustmentConfig::SetConstantCamPose(const image_t image_id) { THROW_CHECK(HasImage(image_id)); THROW_CHECK(!HasConstantCamPositions(image_id)); constant_cam_poses_.insert(image_id); } void BundleAdjustmentConfig::SetVariableCamPose(const image_t image_id) { constant_cam_poses_.erase(image_id); } bool BundleAdjustmentConfig::HasConstantCamPose(const image_t image_id) const { return constant_cam_poses_.find(image_id) != constant_cam_poses_.end(); } void BundleAdjustmentConfig::SetConstantCamPositions( const image_t image_id, const std::vector& idxs) { THROW_CHECK_GT(idxs.size(), 0); THROW_CHECK_LE(idxs.size(), 3); THROW_CHECK(HasImage(image_id)); THROW_CHECK(!HasConstantCamPose(image_id)); THROW_CHECK(!VectorContainsDuplicateValues(idxs)) << "Tvec indices must not contain duplicates"; constant_cam_positions_.emplace(image_id, idxs); } void BundleAdjustmentConfig::RemoveConstantCamPositions( const image_t image_id) { constant_cam_positions_.erase(image_id); } bool BundleAdjustmentConfig::HasConstantCamPositions( const image_t image_id) const { return constant_cam_positions_.find(image_id) != constant_cam_positions_.end(); } const std::unordered_set BundleAdjustmentConfig::ConstantIntrinsics() const { return constant_intrinsics_; } const std::unordered_set& BundleAdjustmentConfig::Images() const { return image_ids_; } const std::unordered_set& BundleAdjustmentConfig::VariablePoints() const { return variable_point3D_ids_; } const std::unordered_set& BundleAdjustmentConfig::ConstantPoints() const { return constant_point3D_ids_; } const std::unordered_set& BundleAdjustmentConfig::ConstantCamPoses() const { return constant_cam_poses_; } const std::vector& BundleAdjustmentConfig::ConstantCamPositions( const image_t image_id) const { return constant_cam_positions_.at(image_id); } void BundleAdjustmentConfig::AddVariablePoint(const point3D_t point3D_id) { THROW_CHECK(!HasConstantPoint(point3D_id)); variable_point3D_ids_.insert(point3D_id); } void BundleAdjustmentConfig::AddConstantPoint(const point3D_t point3D_id) { THROW_CHECK(!HasVariablePoint(point3D_id)); constant_point3D_ids_.insert(point3D_id); } bool BundleAdjustmentConfig::HasPoint(const point3D_t point3D_id) const { return HasVariablePoint(point3D_id) || HasConstantPoint(point3D_id); } bool BundleAdjustmentConfig::HasVariablePoint( const point3D_t point3D_id) const { return variable_point3D_ids_.find(point3D_id) != variable_point3D_ids_.end(); } bool BundleAdjustmentConfig::HasConstantPoint( const point3D_t point3D_id) const { return constant_point3D_ids_.find(point3D_id) != constant_point3D_ids_.end(); } void BundleAdjustmentConfig::RemoveVariablePoint(const point3D_t point3D_id) { variable_point3D_ids_.erase(point3D_id); } void BundleAdjustmentConfig::RemoveConstantPoint(const point3D_t point3D_id) { constant_point3D_ids_.erase(point3D_id); } //////////////////////////////////////////////////////////////////////////////// // BundleAdjuster //////////////////////////////////////////////////////////////////////////////// BundleAdjuster::BundleAdjuster(const BundleAdjustmentOptions& options, const BundleAdjustmentConfig& config) : options_(options), config_(config) { THROW_CHECK(options_.Check()); } bool BundleAdjuster::Solve(Reconstruction* reconstruction) { loss_function_ = std::unique_ptr(options_.CreateLossFunction()); SetUpProblem(reconstruction, loss_function_.get()); if (problem_->NumResiduals() == 0) { return false; } ceres::Solver::Options solver_options = SetUpSolverOptions(*problem_, options_.solver_options); ceres::Solve(solver_options, problem_.get(), &summary_); if (options_.print_summary || VLOG_IS_ON(1)) { PrintSolverSummary(summary_, "Bundle adjustment report"); } return true; } const BundleAdjustmentOptions& BundleAdjuster::Options() const { return options_; } const BundleAdjustmentConfig& BundleAdjuster::Config() const { return config_; } std::shared_ptr BundleAdjuster::Problem() { return problem_; } const ceres::Solver::Summary& BundleAdjuster::Summary() const { return summary_; } void BundleAdjuster::SetUpProblem(Reconstruction* reconstruction, ceres::LossFunction* loss_function) { THROW_CHECK_NOTNULL(reconstruction); // Initialize an empty problem ceres::Problem::Options problem_options; problem_options.loss_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; problem_ = std::make_shared(problem_options); // Set up problem // Warning: AddPointsToProblem assumes that AddImageToProblem is called first. // Do not change order of instructions! for (const image_t image_id : config_.Images()) { AddImageToProblem(image_id, reconstruction, loss_function); } for (const auto point3D_id : config_.VariablePoints()) { AddPointToProblem(point3D_id, reconstruction, loss_function); } for (const auto point3D_id : config_.ConstantPoints()) { AddPointToProblem(point3D_id, reconstruction, loss_function); } ParameterizeCameras(reconstruction); ParameterizePoints(reconstruction); } ceres::Solver::Options BundleAdjuster::SetUpSolverOptions( const ceres::Problem& problem, const ceres::Solver::Options& input_solver_options) const { ceres::Solver::Options solver_options = input_solver_options; const bool has_sparse = solver_options.sparse_linear_algebra_library_type != ceres::NO_SPARSE; // Empirical choice. const size_t kMaxNumImagesDirectDenseSolver = 50; const size_t kMaxNumImagesDirectSparseSolver = 1000; const size_t num_images = config_.NumImages(); if (num_images <= kMaxNumImagesDirectDenseSolver) { solver_options.linear_solver_type = ceres::DENSE_SCHUR; } else if (num_images <= kMaxNumImagesDirectSparseSolver && has_sparse) { solver_options.linear_solver_type = ceres::SPARSE_SCHUR; } else { // Indirect sparse (preconditioned CG) solver. solver_options.linear_solver_type = ceres::ITERATIVE_SCHUR; solver_options.preconditioner_type = ceres::SCHUR_JACOBI; } if (problem.NumResiduals() < options_.min_num_residuals_for_multi_threading) { solver_options.num_threads = 1; #if CERES_VERSION_MAJOR < 2 solver_options.num_linear_solver_threads = 1; #endif // CERES_VERSION_MAJOR } else { solver_options.num_threads = GetEffectiveNumThreads(solver_options.num_threads); #if CERES_VERSION_MAJOR < 2 solver_options.num_linear_solver_threads = GetEffectiveNumThreads(solver_options.num_linear_solver_threads); #endif // CERES_VERSION_MAJOR } std::string solver_error; THROW_CHECK(solver_options.IsValid(&solver_error)) << solver_error; return solver_options; } void BundleAdjuster::AddImageToProblem(const image_t image_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function) { Image& image = reconstruction->Image(image_id); Camera& camera = reconstruction->Camera(image.CameraId()); // CostFunction assumes unit quaternions. image.CamFromWorld().rotation.normalize(); double* cam_from_world_rotation = image.CamFromWorld().rotation.coeffs().data(); double* cam_from_world_translation = image.CamFromWorld().translation.data(); double* camera_params = camera.params.data(); const bool constant_cam_pose = !options_.refine_extrinsics || config_.HasConstantCamPose(image_id); // Add residuals to bundle adjustment problem. size_t num_observations = 0; for (const Point2D& point2D : image.Points2D()) { if (!point2D.HasPoint3D()) { continue; } num_observations += 1; point3D_num_observations_[point2D.point3D_id] += 1; Point3D& point3D = reconstruction->Point3D(point2D.point3D_id); assert(point3D.track.Length() > 1); if (constant_cam_pose) { problem_->AddResidualBlock( CameraCostFunction( camera.model_id, image.CamFromWorld(), point2D.xy), loss_function, point3D.xyz.data(), camera_params); } else { problem_->AddResidualBlock(CameraCostFunction( camera.model_id, point2D.xy), loss_function, cam_from_world_rotation, cam_from_world_translation, point3D.xyz.data(), camera_params); } } if (num_observations > 0) { camera_ids_.insert(image.CameraId()); // Set pose parameterization. if (!constant_cam_pose) { SetQuaternionManifold(problem_.get(), cam_from_world_rotation); if (config_.HasConstantCamPositions(image_id)) { const std::vector& constant_position_idxs = config_.ConstantCamPositions(image_id); SetSubsetManifold(3, constant_position_idxs, problem_.get(), cam_from_world_translation); } } } } void BundleAdjuster::AddPointToProblem(const point3D_t point3D_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function) { Point3D& point3D = reconstruction->Point3D(point3D_id); // Is 3D point already fully contained in the problem? I.e. its entire track // is contained in `variable_image_ids`, `constant_image_ids`, // `constant_x_image_ids`. if (point3D_num_observations_[point3D_id] == point3D.track.Length()) { return; } for (const auto& track_el : point3D.track.Elements()) { // Skip observations that were already added in `FillImages`. if (config_.HasImage(track_el.image_id)) { continue; } point3D_num_observations_[point3D_id] += 1; Image& image = reconstruction->Image(track_el.image_id); Camera& camera = reconstruction->Camera(image.CameraId()); const Point2D& point2D = image.Point2D(track_el.point2D_idx); // CostFunction assumes unit quaternions. image.CamFromWorld().rotation.normalize(); // We do not want to refine the camera of images that are not // part of `constant_image_ids_`, `constant_image_ids_`, // `constant_x_image_ids_`. if (camera_ids_.count(image.CameraId()) == 0) { camera_ids_.insert(image.CameraId()); config_.SetConstantCamIntrinsics(image.CameraId()); } problem_->AddResidualBlock( CameraCostFunction( camera.model_id, image.CamFromWorld(), point2D.xy), loss_function, point3D.xyz.data(), camera.params.data()); } } void BundleAdjuster::ParameterizeCameras(Reconstruction* reconstruction) { const bool constant_camera = !options_.refine_focal_length && !options_.refine_principal_point && !options_.refine_extra_params; for (const camera_t camera_id : camera_ids_) { Camera& camera = reconstruction->Camera(camera_id); if (constant_camera || config_.HasConstantCamIntrinsics(camera_id)) { problem_->SetParameterBlockConstant(camera.params.data()); continue; } else { std::vector const_camera_params; if (!options_.refine_focal_length) { const span params_idxs = camera.FocalLengthIdxs(); const_camera_params.insert( const_camera_params.end(), params_idxs.begin(), params_idxs.end()); } if (!options_.refine_principal_point) { const span params_idxs = camera.PrincipalPointIdxs(); const_camera_params.insert( const_camera_params.end(), params_idxs.begin(), params_idxs.end()); } if (!options_.refine_extra_params) { const span params_idxs = camera.ExtraParamsIdxs(); const_camera_params.insert( const_camera_params.end(), params_idxs.begin(), params_idxs.end()); } if (const_camera_params.size() > 0) { SetSubsetManifold(static_cast(camera.params.size()), const_camera_params, problem_.get(), camera.params.data()); } } } } void BundleAdjuster::ParameterizePoints(Reconstruction* reconstruction) { for (const auto elem : point3D_num_observations_) { Point3D& point3D = reconstruction->Point3D(elem.first); if (point3D.track.Length() > elem.second) { problem_->SetParameterBlockConstant(point3D.xyz.data()); } } for (const point3D_t point3D_id : config_.ConstantPoints()) { Point3D& point3D = reconstruction->Point3D(point3D_id); problem_->SetParameterBlockConstant(point3D.xyz.data()); } } //////////////////////////////////////////////////////////////////////////////// // RigBundleAdjuster //////////////////////////////////////////////////////////////////////////////// RigBundleAdjuster::RigBundleAdjuster(const BundleAdjustmentOptions& options, const Options& rig_options, const BundleAdjustmentConfig& config) : BundleAdjuster(options, config), rig_options_(rig_options) {} bool RigBundleAdjuster::Solve(Reconstruction* reconstruction, std::vector* camera_rigs) { loss_function_ = std::unique_ptr(options_.CreateLossFunction()); SetUpProblem(reconstruction, camera_rigs, loss_function_.get()); if (problem_->NumResiduals() == 0) { return false; } ceres::Solver::Options solver_options = SetUpSolverOptions(*problem_, options_.solver_options); ceres::Solve(solver_options, problem_.get(), &summary_); if (options_.print_summary || VLOG_IS_ON(1)) { PrintSolverSummary(summary_, "Rig Bundle adjustment report"); } TearDown(reconstruction, *camera_rigs); return true; } void RigBundleAdjuster::SetUpProblem(Reconstruction* reconstruction, std::vector* camera_rigs, ceres::LossFunction* loss_function) { THROW_CHECK_NOTNULL(reconstruction); THROW_CHECK_NOTNULL(camera_rigs); THROW_CHECK(!problem_) << "Cannot set up problem from the same BundleAdjuster multiple times"; // Check the validity of the provided camera rigs. std::unordered_set rig_camera_ids; for (auto& camera_rig : *camera_rigs) { camera_rig.Check(*reconstruction); for (const auto& camera_id : camera_rig.GetCameraIds()) { THROW_CHECK_EQ(rig_camera_ids.count(camera_id), 0) << "Camera must not be part of multiple camera rigs"; rig_camera_ids.insert(camera_id); } for (const auto& snapshot : camera_rig.Snapshots()) { for (const auto& image_id : snapshot) { THROW_CHECK_EQ(image_id_to_camera_rig_.count(image_id), 0) << "Image must not be part of multiple camera rigs"; image_id_to_camera_rig_.emplace(image_id, &camera_rig); } } } // Initialize an empty problem ceres::Problem::Options problem_options; problem_options.loss_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; problem_ = std::make_shared(problem_options); // Set up problem ComputeCameraRigPoses(*reconstruction, *camera_rigs); for (const image_t image_id : config_.Images()) { AddImageToProblem(image_id, reconstruction, camera_rigs, loss_function); } for (const auto point3D_id : config_.VariablePoints()) { AddPointToProblem(point3D_id, reconstruction, loss_function); } for (const auto point3D_id : config_.ConstantPoints()) { AddPointToProblem(point3D_id, reconstruction, loss_function); } ParameterizeCameras(reconstruction); ParameterizePoints(reconstruction); ParameterizeCameraRigs(reconstruction); } void RigBundleAdjuster::TearDown(Reconstruction* reconstruction, const std::vector& camera_rigs) { for (const auto& elem : image_id_to_camera_rig_) { const auto image_id = elem.first; const auto& camera_rig = *elem.second; auto& image = reconstruction->Image(image_id); image.CamFromWorld() = camera_rig.CamFromRig(image.CameraId()) * (*image_id_to_rig_from_world_.at(image_id)); } } void RigBundleAdjuster::AddImageToProblem(const image_t image_id, Reconstruction* reconstruction, std::vector* camera_rigs, ceres::LossFunction* loss_function) { const double max_squared_reproj_error = rig_options_.max_reproj_error * rig_options_.max_reproj_error; Image& image = reconstruction->Image(image_id); Camera& camera = reconstruction->Camera(image.CameraId()); const bool constant_cam_pose = config_.HasConstantCamPose(image_id); const bool constant_cam_position = config_.HasConstantCamPositions(image_id); double* camera_params = camera.params.data(); double* cam_from_rig_rotation = nullptr; double* cam_from_rig_translation = nullptr; double* rig_from_world_rotation = nullptr; double* rig_from_world_translation = nullptr; CameraRig* camera_rig = nullptr; Eigen::Matrix3x4d cam_from_world_mat = Eigen::Matrix3x4d::Zero(); if (image_id_to_camera_rig_.count(image_id) > 0) { THROW_CHECK(!constant_cam_pose) << "Images contained in a camera rig must not have constant pose"; THROW_CHECK(!constant_cam_position) << "Images contained in a camera rig must not have constant tvec"; camera_rig = image_id_to_camera_rig_.at(image_id); Rigid3d& rig_from_world = *image_id_to_rig_from_world_.at(image_id); rig_from_world_rotation = rig_from_world.rotation.coeffs().data(); rig_from_world_translation = rig_from_world.translation.data(); Rigid3d& cam_from_rig = camera_rig->CamFromRig(image.CameraId()); cam_from_rig_rotation = cam_from_rig.rotation.coeffs().data(); cam_from_rig_translation = cam_from_rig.translation.data(); cam_from_world_mat = (cam_from_rig * rig_from_world).ToMatrix(); } else { // CostFunction assumes unit quaternions. image.CamFromWorld().rotation.normalize(); cam_from_rig_rotation = image.CamFromWorld().rotation.coeffs().data(); cam_from_rig_translation = image.CamFromWorld().translation.data(); } // Collect cameras for final parameterization. THROW_CHECK(image.HasCamera()); camera_ids_.insert(image.CameraId()); // The number of added observations for the current image. size_t num_observations = 0; // Add residuals to bundle adjustment problem. for (const Point2D& point2D : image.Points2D()) { if (!point2D.HasPoint3D()) { continue; } Point3D& point3D = reconstruction->Point3D(point2D.point3D_id); assert(point3D.track.Length() > 1); if (camera_rig != nullptr && CalculateSquaredReprojectionError( point2D.xy, point3D.xyz, cam_from_world_mat, camera) > max_squared_reproj_error) { continue; } num_observations += 1; point3D_num_observations_[point2D.point3D_id] += 1; if (camera_rig == nullptr) { if (constant_cam_pose) { problem_->AddResidualBlock( CameraCostFunction( camera.model_id, image.CamFromWorld(), point2D.xy), loss_function, point3D.xyz.data(), camera_params); } else { problem_->AddResidualBlock(CameraCostFunction( camera.model_id, point2D.xy), loss_function, cam_from_rig_rotation, // rig == world cam_from_rig_translation, // rig == world point3D.xyz.data(), camera_params); } } else { problem_->AddResidualBlock(CameraCostFunction( camera.model_id, point2D.xy), loss_function, cam_from_rig_rotation, cam_from_rig_translation, rig_from_world_rotation, rig_from_world_translation, point3D.xyz.data(), camera_params); } } if (num_observations > 0) { parameterized_quats_.insert(cam_from_rig_rotation); if (camera_rig != nullptr) { parameterized_quats_.insert(rig_from_world_rotation); // Set the relative pose of the camera constant if relative pose // refinement is disabled or if it is the reference camera to avoid over- // parameterization of the camera pose. if (!rig_options_.refine_relative_poses || image.CameraId() == camera_rig->RefCameraId()) { problem_->SetParameterBlockConstant(cam_from_rig_rotation); problem_->SetParameterBlockConstant(cam_from_rig_translation); } } // Set pose parameterization. if (!constant_cam_pose && constant_cam_position) { const std::vector& constant_position_idxs = config_.ConstantCamPositions(image_id); SetSubsetManifold( 3, constant_position_idxs, problem_.get(), cam_from_rig_translation); } } } void RigBundleAdjuster::AddPointToProblem(const point3D_t point3D_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function) { Point3D& point3D = reconstruction->Point3D(point3D_id); // Is 3D point already fully contained in the problem? I.e. its entire track // is contained in `variable_image_ids`, `constant_image_ids`, // `constant_x_image_ids`. if (point3D_num_observations_[point3D_id] == point3D.track.Length()) { return; } for (const auto& track_el : point3D.track.Elements()) { // Skip observations that were already added in `AddImageToProblem`. if (config_.HasImage(track_el.image_id)) { continue; } point3D_num_observations_[point3D_id] += 1; Image& image = reconstruction->Image(track_el.image_id); Camera& camera = reconstruction->Camera(image.CameraId()); const Point2D& point2D = image.Point2D(track_el.point2D_idx); // We do not want to refine the camera of images that are not // part of `constant_image_ids_`, `constant_image_ids_`, // `constant_x_image_ids_`. if (camera_ids_.count(image.CameraId()) == 0) { camera_ids_.insert(image.CameraId()); config_.SetConstantCamIntrinsics(image.CameraId()); } problem_->AddResidualBlock( CameraCostFunction( camera.model_id, image.CamFromWorld(), point2D.xy), loss_function, point3D.xyz.data(), camera.params.data()); } } void RigBundleAdjuster::ComputeCameraRigPoses( const Reconstruction& reconstruction, const std::vector& camera_rigs) { rigs_from_world_.reserve(camera_rigs.size()); for (const auto& camera_rig : camera_rigs) { rigs_from_world_.emplace_back(); auto& rig_from_world = rigs_from_world_.back(); const size_t num_snapshots = camera_rig.NumSnapshots(); rig_from_world.resize(num_snapshots); for (size_t snapshot_idx = 0; snapshot_idx < num_snapshots; ++snapshot_idx) { rig_from_world[snapshot_idx] = camera_rig.ComputeRigFromWorld(snapshot_idx, reconstruction); for (const auto image_id : camera_rig.Snapshots()[snapshot_idx]) { image_id_to_rig_from_world_.emplace(image_id, &rig_from_world[snapshot_idx]); } } } } void RigBundleAdjuster::ParameterizeCameraRigs(Reconstruction* reconstruction) { for (double* cam_from_rig_rotation : parameterized_quats_) { SetQuaternionManifold(problem_.get(), cam_from_rig_rotation); } } void PrintSolverSummary(const ceres::Solver::Summary& summary, const std::string& header) { std::ostringstream log; log << "\n" << header << ":\n"; log << std::right << std::setw(16) << "Residuals : "; log << std::left << summary.num_residuals_reduced << "\n"; log << std::right << std::setw(16) << "Parameters : "; log << std::left << summary.num_effective_parameters_reduced << "\n"; log << std::right << std::setw(16) << "Iterations : "; log << std::left << summary.num_successful_steps + summary.num_unsuccessful_steps << "\n"; log << std::right << std::setw(16) << "Time : "; log << std::left << summary.total_time_in_seconds << " [s]\n"; log << std::right << std::setw(16) << "Initial cost : "; log << std::right << std::setprecision(6) << std::sqrt(summary.initial_cost / summary.num_residuals_reduced) << " [px]\n"; log << std::right << std::setw(16) << "Final cost : "; log << std::right << std::setprecision(6) << std::sqrt(summary.final_cost / summary.num_residuals_reduced) << " [px]\n"; log << std::right << std::setw(16) << "Termination : "; std::string termination = ""; switch (summary.termination_type) { case ceres::CONVERGENCE: termination = "Convergence"; break; case ceres::NO_CONVERGENCE: termination = "No convergence"; break; case ceres::FAILURE: termination = "Failure"; break; case ceres::USER_SUCCESS: termination = "User success"; break; case ceres::USER_FAILURE: termination = "User failure"; break; default: termination = "Unknown"; break; } log << std::right << termination << "\n\n"; LOG(INFO) << log.str(); } } // namespace colmap colmap-3.10/src/colmap/estimators/bundle_adjustment.h000066400000000000000000000254351464745566500230630ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/scene/camera_rig.h" #include "colmap/scene/reconstruction.h" #include "colmap/util/eigen_alignment.h" #include #include #include #include namespace colmap { struct BundleAdjustmentOptions { // Loss function types: Trivial (non-robust) and Cauchy (robust) loss. enum class LossFunctionType { TRIVIAL, SOFT_L1, CAUCHY }; LossFunctionType loss_function_type = LossFunctionType::TRIVIAL; // Scaling factor determines residual at which robustification takes place. double loss_function_scale = 1.0; // Whether to refine the focal length parameter group. bool refine_focal_length = true; // Whether to refine the principal point parameter group. bool refine_principal_point = false; // Whether to refine the extra parameter group. bool refine_extra_params = true; // Whether to refine the extrinsic parameter group. bool refine_extrinsics = true; // Whether to print a final summary. bool print_summary = true; // Minimum number of residuals to enable multi-threading. Note that // single-threaded is typically better for small bundle adjustment problems // due to the overhead of threading. int min_num_residuals_for_multi_threading = 50000; // Ceres-Solver options. ceres::Solver::Options solver_options; BundleAdjustmentOptions() { solver_options.function_tolerance = 0.0; solver_options.gradient_tolerance = 0.0; solver_options.parameter_tolerance = 0.0; solver_options.logging_type = ceres::LoggingType::SILENT; solver_options.max_num_iterations = 100; solver_options.max_linear_solver_iterations = 200; solver_options.max_num_consecutive_invalid_steps = 10; solver_options.max_consecutive_nonmonotonic_steps = 10; solver_options.num_threads = -1; #if CERES_VERSION_MAJOR < 2 solver_options.num_linear_solver_threads = -1; #endif // CERES_VERSION_MAJOR } // Create a new loss function based on the specified options. The caller // takes ownership of the loss function. ceres::LossFunction* CreateLossFunction() const; bool Check() const; }; // Configuration container to setup bundle adjustment problems. class BundleAdjustmentConfig { public: BundleAdjustmentConfig(); size_t NumImages() const; size_t NumPoints() const; size_t NumConstantCamIntrinsics() const; size_t NumConstantCamPoses() const; size_t NumConstantCamPositions() const; size_t NumVariablePoints() const; size_t NumConstantPoints() const; // Determine the number of residuals for the given reconstruction. The number // of residuals equals the number of observations times two. size_t NumResiduals(const Reconstruction& reconstruction) const; // Add / remove images from the configuration. void AddImage(image_t image_id); bool HasImage(image_t image_id) const; void RemoveImage(image_t image_id); // Set cameras of added images as constant or variable. By default all // cameras of added images are variable. Note that the corresponding images // have to be added prior to calling these methods. void SetConstantCamIntrinsics(camera_t camera_id); void SetVariableCamIntrinsics(camera_t camera_id); bool HasConstantCamIntrinsics(camera_t camera_id) const; // Set the pose of added images as constant. The pose is defined as the // rotational and translational part of the projection matrix. void SetConstantCamPose(image_t image_id); void SetVariableCamPose(image_t image_id); bool HasConstantCamPose(image_t image_id) const; // Set the translational part of the pose, hence the constant pose // indices may be in [0, 1, 2] and must be unique. Note that the // corresponding images have to be added prior to calling these methods. void SetConstantCamPositions(image_t image_id, const std::vector& idxs); void RemoveConstantCamPositions(image_t image_id); bool HasConstantCamPositions(image_t image_id) const; // Add / remove points from the configuration. Note that points can either // be variable or constant but not both at the same time. void AddVariablePoint(point3D_t point3D_id); void AddConstantPoint(point3D_t point3D_id); bool HasPoint(point3D_t point3D_id) const; bool HasVariablePoint(point3D_t point3D_id) const; bool HasConstantPoint(point3D_t point3D_id) const; void RemoveVariablePoint(point3D_t point3D_id); void RemoveConstantPoint(point3D_t point3D_id); // Access configuration data. const std::unordered_set ConstantIntrinsics() const; const std::unordered_set& Images() const; const std::unordered_set& VariablePoints() const; const std::unordered_set& ConstantPoints() const; const std::unordered_set& ConstantCamPoses() const; const std::vector& ConstantCamPositions(image_t image_id) const; private: std::unordered_set constant_intrinsics_; std::unordered_set image_ids_; std::unordered_set variable_point3D_ids_; std::unordered_set constant_point3D_ids_; std::unordered_set constant_cam_poses_; std::unordered_map> constant_cam_positions_; }; // Bundle adjustment based on Ceres-Solver. Enables most flexible configurations // and provides best solution quality. class BundleAdjuster { public: BundleAdjuster(const BundleAdjustmentOptions& options, const BundleAdjustmentConfig& config); bool Solve(Reconstruction* reconstruction); // Set up the problem void SetUpProblem(Reconstruction* reconstruction, ceres::LossFunction* loss_function); ceres::Solver::Options SetUpSolverOptions( const ceres::Problem& problem, const ceres::Solver::Options& input_solver_options) const; // Getter functions below const BundleAdjustmentOptions& Options() const; const BundleAdjustmentConfig& Config() const; // Get the Ceres problem after the last call to "set_up" std::shared_ptr Problem(); // Get the Ceres solver summary after the last call to `Solve`. const ceres::Solver::Summary& Summary() const; private: void AddImageToProblem(image_t image_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function); void AddPointToProblem(point3D_t point3D_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function); protected: void ParameterizeCameras(Reconstruction* reconstruction); void ParameterizePoints(Reconstruction* reconstruction); const BundleAdjustmentOptions options_; BundleAdjustmentConfig config_; std::shared_ptr problem_; ceres::Solver::Summary summary_; std::unordered_set camera_ids_; std::unordered_map point3D_num_observations_; // Hold the life of loss function for Solve() std::unique_ptr loss_function_; }; class RigBundleAdjuster : public BundleAdjuster { public: struct Options { // Whether to optimize the relative poses of the camera rigs. bool refine_relative_poses = true; // The maximum allowed reprojection error for an observation to be // considered in the bundle adjustment. Some observations might have large // reprojection errors due to the concatenation of the absolute and relative // rig poses, which might be different from the absolute pose of the image // in the reconstruction. double max_reproj_error = 1000.0; }; RigBundleAdjuster(const BundleAdjustmentOptions& options, const Options& rig_options, const BundleAdjustmentConfig& config); bool Solve(Reconstruction* reconstruction, std::vector* camera_rigs); void SetUpProblem(Reconstruction* reconstruction, std::vector* camera_rigs, ceres::LossFunction* loss_function); void TearDown(Reconstruction* reconstruction, const std::vector& camera_rigs); private: void AddImageToProblem(image_t image_id, Reconstruction* reconstruction, std::vector* camera_rigs, ceres::LossFunction* loss_function); void AddPointToProblem(point3D_t point3D_id, Reconstruction* reconstruction, ceres::LossFunction* loss_function); void ComputeCameraRigPoses(const Reconstruction& reconstruction, const std::vector& camera_rigs); void ParameterizeCameraRigs(Reconstruction* reconstruction); const Options rig_options_; // Mapping from images to camera rigs. std::unordered_map image_id_to_camera_rig_; // Mapping from images to the absolute camera rig poses. std::unordered_map image_id_to_rig_from_world_; // For each camera rig, the absolute camera rig poses for all snapshots. std::vector> rigs_from_world_; // The Quaternions added to the problem, used to set the local // parameterization once after setting up the problem. std::unordered_set parameterized_quats_; }; void PrintSolverSummary(const ceres::Solver::Summary& summary, const std::string& header); } // namespace colmap colmap-3.10/src/colmap/estimators/bundle_adjustment_test.cc000066400000000000000000001000121464745566500242410ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/bundle_adjustment.h" #include "colmap/math/random.h" #include "colmap/scene/correspondence_graph.h" #include "colmap/scene/projection.h" #include "colmap/sensor/models.h" #include #define CheckVariableCamera(camera, orig_camera) \ { \ const size_t focal_length_idx = \ SimpleRadialCameraModel::focal_length_idxs[0]; \ const size_t extra_param_idx = \ SimpleRadialCameraModel::extra_params_idxs[0]; \ EXPECT_NE((camera).params[focal_length_idx], \ (orig_camera).params[focal_length_idx]); \ EXPECT_NE((camera).params[extra_param_idx], \ (orig_camera).params[extra_param_idx]); \ } #define CheckConstantCamera(camera, orig_camera) \ { \ const size_t focal_length_idx = \ SimpleRadialCameraModel::focal_length_idxs[0]; \ const size_t extra_param_idx = \ SimpleRadialCameraModel::extra_params_idxs[0]; \ EXPECT_EQ((camera).params[focal_length_idx], \ (orig_camera).params[focal_length_idx]); \ EXPECT_EQ((camera).params[extra_param_idx], \ (orig_camera).params[extra_param_idx]); \ } #define CheckVariableImage(image, orig_image) \ { \ EXPECT_NE((image).CamFromWorld().rotation.coeffs(), \ (orig_image).CamFromWorld().rotation.coeffs()); \ EXPECT_NE((image).CamFromWorld().translation, \ (orig_image).CamFromWorld().translation); \ } #define CheckConstantImage(image, orig_image) \ { \ EXPECT_EQ((image).CamFromWorld().rotation.coeffs(), \ (orig_image).CamFromWorld().rotation.coeffs()); \ EXPECT_EQ((image).CamFromWorld().translation, \ (orig_image).CamFromWorld().translation); \ } #define CheckConstantXImage(image, orig_image) \ { \ CheckVariableImage(image, orig_image); \ EXPECT_EQ((image).CamFromWorld().translation.x(), \ (orig_image).CamFromWorld().translation.x()); \ } #define CheckConstantCameraRig(camera_rig, orig_camera_rig, camera_id) \ { \ EXPECT_EQ((camera_rig).CamFromRig(camera_id).rotation.coeffs(), \ (orig_camera_rig).CamFromRig(camera_id).rotation.coeffs()); \ EXPECT_EQ((camera_rig).CamFromRig(camera_id).translation, \ (orig_camera_rig).CamFromRig(camera_id).translation); \ } #define CheckVariableCameraRig(camera_rig, orig_camera_rig, camera_id) \ { \ if ((camera_rig).RefCameraId() == (camera_id)) { \ CheckConstantCameraRig(camera_rig, orig_camera_rig, camera_id); \ } else { \ EXPECT_NE((camera_rig).CamFromRig(camera_id).rotation.coeffs(), \ (orig_camera_rig).CamFromRig(camera_id).rotation.coeffs()); \ EXPECT_NE((camera_rig).CamFromRig(camera_id).translation, \ (orig_camera_rig).CamFromRig(camera_id).translation); \ } \ } #define CheckVariablePoint(point, orig_point) \ { EXPECT_NE((point).xyz, (orig_point).xyz); } #define CheckConstantPoint(point, orig_point) \ { EXPECT_EQ((point).xyz, (orig_point).xyz); } namespace colmap { namespace { void GeneratePointCloud(const size_t num_points, const Eigen::Vector3d& min, const Eigen::Vector3d& max, Reconstruction* reconstruction) { for (size_t i = 0; i < num_points; ++i) { Eigen::Vector3d xyz; xyz.x() = RandomUniformReal(min.x(), max.x()); xyz.y() = RandomUniformReal(min.y(), max.y()); xyz.z() = RandomUniformReal(min.z(), max.z()); reconstruction->AddPoint3D(xyz, Track()); } } void GenerateReconstruction(const size_t num_images, const size_t num_points, Reconstruction* reconstruction) { SetPRNGSeed(0); GeneratePointCloud(num_points, Eigen::Vector3d(-1, -1, -1), Eigen::Vector3d(1, 1, 1), reconstruction); const double kFocalLengthFactor = 1.2; const size_t kImageSize = 1000; for (size_t i = 0; i < num_images; ++i) { const camera_t camera_id = static_cast(i); const image_t image_id = static_cast(i); const Camera camera = Camera::CreateFromModelId(camera_id, SimpleRadialCameraModel::model_id, kFocalLengthFactor * kImageSize, kImageSize, kImageSize); reconstruction->AddCamera(camera); Image image; image.SetImageId(image_id); image.SetCameraId(camera_id); image.SetName(std::to_string(i)); image.CamFromWorld() = Rigid3d( Eigen::Quaterniond::Identity(), Eigen::Vector3d( RandomUniformReal(-1.0, 1.0), RandomUniformReal(-1.0, 1.0), 10)); image.SetRegistered(true); reconstruction->AddImage(image); const Eigen::Matrix3x4d cam_from_world_matrix = image.CamFromWorld().ToMatrix(); std::vector points2D; for (const auto& point3D : reconstruction->Points3D()) { EXPECT_TRUE( HasPointPositiveDepth(cam_from_world_matrix, point3D.second.xyz)); // Get exact projection of 3D point. Eigen::Vector2d point2D = camera.ImgFromCam( (image.CamFromWorld() * point3D.second.xyz).hnormalized()); // Add some uniform noise. point2D += Eigen::Vector2d(RandomUniformReal(-2.0, 2.0), RandomUniformReal(-2.0, 2.0)); points2D.push_back(point2D); } reconstruction->Image(image_id).SetPoints2D(points2D); } for (size_t i = 0; i < num_images; ++i) { const image_t image_id = static_cast(i); TrackElement track_el; track_el.image_id = image_id; track_el.point2D_idx = 0; for (const auto& point3D : reconstruction->Points3D()) { reconstruction->AddObservation(point3D.first, track_el); track_el.point2D_idx += 1; } } } TEST(BundleAdjustment, ConfigNumObservations) { Reconstruction reconstruction; GenerateReconstruction(4, 100, &reconstruction); BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); EXPECT_EQ(config.NumResiduals(reconstruction), 400); config.AddVariablePoint(1); EXPECT_EQ(config.NumResiduals(reconstruction), 404); config.AddConstantPoint(2); EXPECT_EQ(config.NumResiduals(reconstruction), 408); config.AddImage(2); EXPECT_EQ(config.NumResiduals(reconstruction), 604); config.AddImage(3); EXPECT_EQ(config.NumResiduals(reconstruction), 800); } TEST(BundleAdjustment, TwoView) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPositions(1, {0}); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 5 image parameters (pose of second image) // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 309); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1)); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, TwoViewConstantCamera) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPose(1); config.SetConstantCamIntrinsics(0); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 302); CheckConstantCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1)); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, PartiallyContainedTracks) { Reconstruction reconstruction; GenerateReconstruction(3, 100, &reconstruction); const auto variable_point3D_id = reconstruction.Image(2).Point2D(0).point3D_id; reconstruction.DeleteObservation(2, 0); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPose(1); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 1 x 3 point parameters // 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 7); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckConstantCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2)); CheckConstantImage(reconstruction.Image(2), orig_reconstruction.Image(2)); for (const auto& point3D : reconstruction.Points3D()) { if (point3D.first == variable_point3D_id) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } else { CheckConstantPoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } } TEST(BundleAdjustment, PartiallyContainedTracksForceToOptimizePoint) { Reconstruction reconstruction; GenerateReconstruction(3, 100, &reconstruction); const point3D_t variable_point3D_id = reconstruction.Image(2).Point2D(0).point3D_id; const point3D_t add_variable_point3D_id = reconstruction.Image(2).Point2D(1).point3D_id; const point3D_t add_constant_point3D_id = reconstruction.Image(2).Point2D(2).point3D_id; reconstruction.DeleteObservation(2, 0); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPose(1); config.AddVariablePoint(add_variable_point3D_id); config.AddConstantPoint(add_constant_point3D_id); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image // + 2 residuals in 3rd image for added variable 3D point // (added constant point does not add residuals since the image/camera // is also constant). EXPECT_EQ(summary.num_residuals_reduced, 402); // 2 x 3 point parameters // 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 10); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckConstantCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2)); CheckConstantImage(reconstruction.Image(2), orig_reconstruction.Image(2)); for (const auto& point3D : reconstruction.Points3D()) { if (point3D.first == variable_point3D_id || point3D.first == add_variable_point3D_id) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } else { CheckConstantPoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } } TEST(BundleAdjustment, ConstantPoints) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; const point3D_t constant_point3D_id1 = 1; const point3D_t constant_point3D_id2 = 2; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPose(1); config.AddConstantPoint(constant_point3D_id1); config.AddConstantPoint(constant_point3D_id2); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 98 x 3 point parameters // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 298); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1)); for (const auto& point3D : reconstruction.Points3D()) { if (point3D.first == constant_point3D_id1 || point3D.first == constant_point3D_id2) { CheckConstantPoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } else { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } } TEST(BundleAdjustment, VariableImage) { Reconstruction reconstruction; GenerateReconstruction(3, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.AddImage(2); config.SetConstantCamPose(0); config.SetConstantCamPositions(1, {0}); BundleAdjustmentOptions options; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 3 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 600); // 100 x 3 point parameters // + 5 image parameters (pose of second image) // + 6 image parameters (pose of third image) // + 3 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 317); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckVariableCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2)); CheckVariableImage(reconstruction.Image(2), orig_reconstruction.Image(2)); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, ConstantFocalLength) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPositions(1, {0}); BundleAdjustmentOptions options; options.refine_focal_length = false; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 3 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 5 image parameters (pose of second image) // + 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 307); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1)); const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0]; const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0]; const auto& camera0 = reconstruction.Camera(0); const auto& orig_camera0 = orig_reconstruction.Camera(0); EXPECT_TRUE(camera0.params[focal_length_idx] == orig_camera0.params[focal_length_idx]); EXPECT_TRUE(camera0.params[extra_param_idx] != orig_camera0.params[extra_param_idx]); const auto& camera1 = reconstruction.Camera(1); const auto& orig_camera1 = orig_reconstruction.Camera(1); EXPECT_TRUE(camera1.params[focal_length_idx] == orig_camera1.params[focal_length_idx]); EXPECT_TRUE(camera1.params[extra_param_idx] != orig_camera1.params[extra_param_idx]); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, VariablePrincipalPoint) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPositions(1, {0}); BundleAdjustmentOptions options; options.refine_principal_point = true; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 3 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 5 image parameters (pose of second image) // + 8 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 313); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1)); const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0]; const size_t principal_point_idx_x = SimpleRadialCameraModel::principal_point_idxs[0]; const size_t principal_point_idx_y = SimpleRadialCameraModel::principal_point_idxs[0]; const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0]; const auto& camera0 = reconstruction.Camera(0); const auto& orig_camera0 = orig_reconstruction.Camera(0); EXPECT_TRUE(camera0.params[focal_length_idx] != orig_camera0.params[focal_length_idx]); EXPECT_TRUE(camera0.params[principal_point_idx_x] != orig_camera0.params[principal_point_idx_x]); EXPECT_TRUE(camera0.params[principal_point_idx_y] != orig_camera0.params[principal_point_idx_y]); EXPECT_TRUE(camera0.params[extra_param_idx] != orig_camera0.params[extra_param_idx]); const auto& camera1 = reconstruction.Camera(1); const auto& orig_camera1 = orig_reconstruction.Camera(1); EXPECT_TRUE(camera1.params[focal_length_idx] != orig_camera1.params[focal_length_idx]); EXPECT_TRUE(camera1.params[principal_point_idx_x] != orig_camera1.params[principal_point_idx_x]); EXPECT_TRUE(camera1.params[principal_point_idx_y] != orig_camera1.params[principal_point_idx_y]); EXPECT_TRUE(camera1.params[extra_param_idx] != orig_camera1.params[extra_param_idx]); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, ConstantExtraParam) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.SetConstantCamPose(0); config.SetConstantCamPositions(1, {0}); BundleAdjustmentOptions options; options.refine_extra_params = false; BundleAdjuster bundle_adjuster(options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction)); const auto summary = bundle_adjuster.Summary(); // 100 points, 3 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 5 image parameters (pose of second image) // + 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 307); CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1)); const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0]; const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0]; const auto& camera0 = reconstruction.Camera(0); const auto& orig_camera0 = orig_reconstruction.Camera(0); EXPECT_TRUE(camera0.params[focal_length_idx] != orig_camera0.params[focal_length_idx]); EXPECT_TRUE(camera0.params[extra_param_idx] == orig_camera0.params[extra_param_idx]); const auto& camera1 = reconstruction.Camera(1); const auto& orig_camera1 = orig_reconstruction.Camera(1); EXPECT_TRUE(camera1.params[focal_length_idx] != orig_camera1.params[focal_length_idx]); EXPECT_TRUE(camera1.params[extra_param_idx] == orig_camera1.params[extra_param_idx]); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, RigTwoView) { Reconstruction reconstruction; GenerateReconstruction(2, 100, &reconstruction); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); std::vector camera_rigs; camera_rigs.emplace_back(); camera_rigs[0].AddCamera(0, Rigid3d()); camera_rigs[0].AddCamera(1, Rigid3d()); camera_rigs[0].AddSnapshot({0, 1}); camera_rigs[0].SetRefCameraId(0); const auto orig_camera_rigs = camera_rigs; BundleAdjustmentOptions options; RigBundleAdjuster::Options rig_options; RigBundleAdjuster bundle_adjuster(options, rig_options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction, &camera_rigs)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 400); // 100 x 3 point parameters // + 6 pose parameters for camera rig // + 1 x 6 relative pose parameters for camera rig // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 316); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, RigFourView) { Reconstruction reconstruction; GenerateReconstruction(4, 100, &reconstruction); reconstruction.Image(2).SetCameraId(0); reconstruction.Image(3).SetCameraId(1); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.AddImage(2); config.AddImage(3); std::vector camera_rigs; camera_rigs.emplace_back(); camera_rigs[0].AddCamera(0, Rigid3d()); camera_rigs[0].AddCamera(1, Rigid3d()); camera_rigs[0].AddSnapshot({0, 1}); camera_rigs[0].AddSnapshot({2, 3}); camera_rigs[0].SetRefCameraId(0); const auto orig_camera_rigs = camera_rigs; BundleAdjustmentOptions options; RigBundleAdjuster::Options rig_options; RigBundleAdjuster bundle_adjuster(options, rig_options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction, &camera_rigs)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 800); // 100 x 3 point parameters // + 2 x 6 pose parameters for camera rig // + 1 x 6 relative pose parameters for camera rig // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 322); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, ConstantRigFourView) { Reconstruction reconstruction; GenerateReconstruction(4, 100, &reconstruction); reconstruction.Image(2).SetCameraId(0); reconstruction.Image(3).SetCameraId(1); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.AddImage(2); config.AddImage(3); std::vector camera_rigs; camera_rigs.emplace_back(); camera_rigs[0].AddCamera(0, Rigid3d()); camera_rigs[0].AddCamera(1, Rigid3d()); camera_rigs[0].AddSnapshot({0, 1}); camera_rigs[0].AddSnapshot({2, 3}); camera_rigs[0].SetRefCameraId(0); const auto orig_camera_rigs = camera_rigs; BundleAdjustmentOptions options; RigBundleAdjuster::Options rig_options; rig_options.refine_relative_poses = false; RigBundleAdjuster bundle_adjuster(options, rig_options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction, &camera_rigs)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 800); // 100 x 3 point parameters // + 2 x 6 pose parameters for camera rig // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 316); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckConstantCameraRig(camera_rigs[0], orig_camera_rigs[0], 0); CheckConstantCameraRig(camera_rigs[0], orig_camera_rigs[0], 1); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } TEST(BundleAdjustment, RigFourViewPartial) { Reconstruction reconstruction; GenerateReconstruction(4, 100, &reconstruction); reconstruction.Image(2).SetCameraId(0); reconstruction.Image(3).SetCameraId(1); const auto orig_reconstruction = reconstruction; BundleAdjustmentConfig config; config.AddImage(0); config.AddImage(1); config.AddImage(2); config.AddImage(3); std::vector camera_rigs; camera_rigs.emplace_back(); camera_rigs[0].AddCamera(0, Rigid3d()); camera_rigs[0].AddCamera(1, Rigid3d()); camera_rigs[0].AddSnapshot({0, 1}); camera_rigs[0].AddSnapshot({2}); camera_rigs[0].SetRefCameraId(0); const auto orig_camera_rigs = camera_rigs; BundleAdjustmentOptions options; RigBundleAdjuster::Options rig_options; RigBundleAdjuster bundle_adjuster(options, rig_options, config); ASSERT_TRUE(bundle_adjuster.Solve(&reconstruction, &camera_rigs)); const auto summary = bundle_adjuster.Summary(); // 100 points, 2 images, 2 residuals per point per image EXPECT_EQ(summary.num_residuals_reduced, 800); // 100 x 3 point parameters // + 2 x 6 pose parameters for camera rig // + 1 x 6 relative pose parameters for camera rig // + 1 x 6 pose parameters for individual image // + 2 x 2 camera parameters EXPECT_EQ(summary.num_effective_parameters_reduced, 328); CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0)); CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0)); CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1)); CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1)); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0); CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1); for (const auto& point3D : reconstruction.Points3D()) { CheckVariablePoint(point3D.second, orig_reconstruction.Point3D(point3D.first)); } } } // namespace } // namespace colmap colmap-3.10/src/colmap/estimators/coordinate_frame.cc000066400000000000000000000333631464745566500230120ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/coordinate_frame.h" #include "colmap/estimators/utils.h" #include "colmap/geometry/gps.h" #include "colmap/geometry/pose.h" #include "colmap/image/line.h" #include "colmap/image/undistortion.h" #include "colmap/optim/ransac.h" #include "colmap/util/logging.h" #include "colmap/util/misc.h" namespace colmap { namespace { Eigen::Vector3d FindBestConsensusAxis(const std::vector& axes, const double max_distance) { if (axes.empty()) { return Eigen::Vector3d::Zero(); } std::vector inlier_idxs; inlier_idxs.reserve(axes.size()); std::vector best_inlier_idxs; best_inlier_idxs.reserve(axes.size()); double best_inlier_distance_sum = std::numeric_limits::max(); for (size_t i = 0; i < axes.size(); ++i) { const Eigen::Vector3d& ref_axis = axes[i]; double inlier_distance_sum = 0; inlier_idxs.clear(); for (size_t j = 0; j < axes.size(); ++j) { if (i == j) { inlier_idxs.push_back(j); } else { const double distance = 1 - ref_axis.dot(axes[j]); if (distance <= max_distance) { inlier_distance_sum += distance; inlier_idxs.push_back(j); } } } if (inlier_idxs.size() > best_inlier_idxs.size() || (inlier_idxs.size() == best_inlier_idxs.size() && inlier_distance_sum < best_inlier_distance_sum)) { best_inlier_distance_sum = inlier_distance_sum; best_inlier_idxs = inlier_idxs; } } if (best_inlier_idxs.empty()) { return Eigen::Vector3d::Zero(); } Eigen::Vector3d best_axis(0, 0, 0); for (const auto idx : best_inlier_idxs) { best_axis += axes[idx]; } best_axis /= best_inlier_idxs.size(); return best_axis; } } // namespace Eigen::Vector3d EstimateGravityVectorFromImageOrientation( const Reconstruction& reconstruction, const double max_axis_distance) { std::vector downward_axes; downward_axes.reserve(reconstruction.NumRegImages()); for (const auto image_id : reconstruction.RegImageIds()) { const auto& image = reconstruction.Image(image_id); downward_axes.push_back( image.CamFromWorld().rotation.toRotationMatrix().row(1)); } return FindBestConsensusAxis(downward_axes, max_axis_distance); } #ifdef COLMAP_LSD_ENABLED struct VanishingPointEstimator { // The line segments. typedef LineSegment X_t; // The line representation of the segments. typedef Eigen::Vector3d Y_t; // The vanishing point. typedef Eigen::Vector3d M_t; // The minimum number of samples needed to estimate a model. static const int kMinNumSamples = 2; // Estimate the vanishing point from at least two line segments. static void Estimate(const std::vector& line_segments, const std::vector& lines, std::vector* models) { THROW_CHECK_EQ(line_segments.size(), 2); THROW_CHECK_EQ(lines.size(), 2); THROW_CHECK(models != nullptr); models->resize(1); (*models)[0] = lines[0].cross(lines[1]); } // Calculate the squared distance of each line segment's end point to the line // connecting the vanishing point and the midpoint of the line segment. static void Residuals(const std::vector& line_segments, const std::vector& lines, const M_t& vanishing_point, std::vector* residuals) { residuals->resize(line_segments.size()); // Check if vanishing point is at infinity. if (vanishing_point[2] == 0) { std::fill(residuals->begin(), residuals->end(), std::numeric_limits::max()); return; } for (size_t i = 0; i < lines.size(); ++i) { const Eigen::Vector3d midpoint = (0.5 * (line_segments[i].start + line_segments[i].end)).homogeneous(); const Eigen::Vector3d connecting_line = midpoint.cross(vanishing_point); const double signed_distance = connecting_line.dot(line_segments[i].end.homogeneous()) / connecting_line.head<2>().norm(); (*residuals)[i] = signed_distance * signed_distance; } } }; Eigen::Matrix3d EstimateManhattanWorldFrame( const ManhattanWorldFrameEstimationOptions& options, const Reconstruction& reconstruction, const std::string& image_path) { std::vector rightward_axes; std::vector downward_axes; for (size_t i = 0; i < reconstruction.NumRegImages(); ++i) { const auto image_id = reconstruction.RegImageIds()[i]; const auto& image = reconstruction.Image(image_id); const auto& camera = reconstruction.Camera(image.CameraId()); PrintHeading1(StringPrintf("Processing image %s (%d / %d)", image.Name().c_str(), i + 1, reconstruction.NumRegImages())); LOG(INFO) << "Reading image..."; colmap::Bitmap bitmap; THROW_CHECK(bitmap.Read(colmap::JoinPaths(image_path, image.Name()))); LOG(INFO) << "Undistorting image..."; UndistortCameraOptions undistortion_options; undistortion_options.max_image_size = options.max_image_size; Bitmap undistorted_bitmap; Camera undistorted_camera; UndistortImage(undistortion_options, bitmap, camera, &undistorted_bitmap, &undistorted_camera); LOG(INFO) << "Detecting lines..."; const std::vector line_segments = DetectLineSegments(undistorted_bitmap, options.min_line_length); const std::vector line_orientations = ClassifyLineSegmentOrientations(line_segments, options.line_orientation_tolerance); LOG(INFO) << StringPrintf(" %d", line_segments.size()); std::vector horizontal_line_segments; std::vector vertical_line_segments; std::vector horizontal_lines; std::vector vertical_lines; for (size_t i = 0; i < line_segments.size(); ++i) { const auto& line_segment = line_segments[i]; const Eigen::Vector3d line_segment_start = line_segment.start.homogeneous(); const Eigen::Vector3d line_segment_end = line_segment.end.homogeneous(); const Eigen::Vector3d line = line_segment_start.cross(line_segment_end); if (line_orientations[i] == LineSegmentOrientation::HORIZONTAL) { horizontal_line_segments.push_back(line_segment); horizontal_lines.push_back(line); } else if (line_orientations[i] == LineSegmentOrientation::VERTICAL) { vertical_line_segments.push_back(line_segment); vertical_lines.push_back(line); } } LOG(INFO) << StringPrintf(" (%d horizontal, %d vertical)", horizontal_lines.size(), vertical_lines.size()); LOG(INFO) << "Estimating vanishing points..."; RANSACOptions ransac_options; ransac_options.max_error = options.max_line_vp_distance; RANSAC ransac(ransac_options); const auto horizontal_report = ransac.Estimate(horizontal_line_segments, horizontal_lines); const auto vertical_report = ransac.Estimate(vertical_line_segments, vertical_lines); LOG(INFO) << StringPrintf(" (%d horizontal inliers, %d vertical inliers)", horizontal_report.support.num_inliers, vertical_report.support.num_inliers); LOG(INFO) << "Composing coordinate axes..."; const Eigen::Matrix3d inv_calib_matrix = undistorted_camera.CalibrationMatrix().inverse(); const Eigen::Quaterniond world_from_cam_rotation = image.CamFromWorld().rotation.inverse(); if (horizontal_report.success) { Eigen::Vector3d horizontal_axis_in_world = world_from_cam_rotation * (inv_calib_matrix * horizontal_report.model).normalized(); // Make sure all axes point into the same direction. if (rightward_axes.size() > 0 && rightward_axes[0].dot(horizontal_axis_in_world) < 0) { horizontal_axis_in_world = -horizontal_axis_in_world; } rightward_axes.push_back(horizontal_axis_in_world); LOG(INFO) << "Horizontal: " << horizontal_axis_in_world.transpose(); } if (vertical_report.success) { const Eigen::Vector3d vertical_axis_in_cam = (inv_calib_matrix * vertical_report.model).normalized(); Eigen::Vector3d vertical_axis_in_world = (world_from_cam_rotation * vertical_axis_in_cam).normalized(); // Make sure axis points downwards in the image, assuming that the image // was taken in upright orientation. if (vertical_axis_in_world.dot(Eigen::Vector3d(0, 1, 0)) < 0) { vertical_axis_in_world = -vertical_axis_in_world; } downward_axes.push_back(vertical_axis_in_world); LOG(INFO) << "Vertical: " << vertical_axis_in_world.transpose(); } } PrintHeading1("Computing coordinate frame"); Eigen::Matrix3d frame = Eigen::Matrix3d::Zero(); if (rightward_axes.size() > 0) { frame.col(0) = FindBestConsensusAxis(rightward_axes, options.max_axis_distance); } LOG(INFO) << "Found rightward axis: " << frame.col(0).transpose(); if (downward_axes.size() > 0) { frame.col(1) = FindBestConsensusAxis(downward_axes, options.max_axis_distance); } LOG(INFO) << "Found downward axis: " << frame.col(1).transpose(); if (rightward_axes.size() > 0 && downward_axes.size() > 0) { frame.col(2) = frame.col(0).cross(frame.col(1)); Eigen::JacobiSVD svd( frame, Eigen::ComputeFullV | Eigen::ComputeFullU); const Eigen::Matrix3d orthonormal_frame = svd.matrixU() * Eigen::Matrix3d::Identity() * svd.matrixV().transpose(); frame = orthonormal_frame; } LOG(INFO) << "Found orthonormal frame:\n" << frame; return frame; } #endif void AlignToPrincipalPlane(Reconstruction* reconstruction, Sim3d* tform) { // Perform SVD on the 3D points to estimate the ground plane basis const Eigen::Vector3d centroid = reconstruction->ComputeCentroid(0.0, 1.0); Eigen::MatrixXd normalized_points3D(3, reconstruction->NumPoints3D()); int pidx = 0; for (const auto& point : reconstruction->Points3D()) { normalized_points3D.col(pidx++) = point.second.xyz - centroid; } const Eigen::Matrix3d basis = normalized_points3D.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV) .matrixU(); Eigen::Matrix3d rot_mat; rot_mat << basis.col(0), basis.col(1), basis.col(0).cross(basis.col(1)); rot_mat.transposeInPlace(); *tform = Sim3d(1.0, Eigen::Quaterniond(rot_mat), -rot_mat * centroid); // If camera plane ends up below ground then flip basis vectors. const Rigid3d cam0_from_aligned_world = TransformCameraWorld( *tform, reconstruction->Image(reconstruction->RegImageIds()[0]).CamFromWorld()); if (Inverse(cam0_from_aligned_world).translation.z() < 0.0) { rot_mat << basis.col(0), -basis.col(1), basis.col(0).cross(-basis.col(1)); rot_mat.transposeInPlace(); *tform = Sim3d(1.0, Eigen::Quaterniond(rot_mat), -rot_mat * centroid); } reconstruction->Transform(*tform); } void AlignToENUPlane(Reconstruction* reconstruction, Sim3d* tform, bool unscaled) { const Eigen::Vector3d centroid = reconstruction->ComputeCentroid(0.0, 1.0); GPSTransform gps_tform; const Eigen::Vector3d ell_centroid = gps_tform.XYZToEll({centroid}).at(0); // Create rotation matrix from ECEF to ENU coordinates const double sin_lat = std::sin(DegToRad(ell_centroid(0))); const double sin_lon = std::sin(DegToRad(ell_centroid(1))); const double cos_lat = std::cos(DegToRad(ell_centroid(0))); const double cos_lon = std::cos(DegToRad(ell_centroid(1))); // Create ECEF to ENU rotation matrix Eigen::Matrix3d rot_mat; rot_mat << -sin_lon, cos_lon, 0, -cos_lon * sin_lat, -sin_lon * sin_lat, cos_lat, cos_lon * cos_lat, sin_lon * cos_lat, sin_lat; const double scale = unscaled ? 1.0 / tform->scale : 1.0; *tform = Sim3d(scale, Eigen::Quaterniond(rot_mat), -scale * rot_mat * centroid); reconstruction->Transform(*tform); } } // namespace colmap colmap-3.10/src/colmap/estimators/coordinate_frame.h000066400000000000000000000100461464745566500226450ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/scene/reconstruction.h" #include "colmap/util/eigen_alignment.h" #include namespace colmap { struct ManhattanWorldFrameEstimationOptions { // The maximum image size for line detection. int max_image_size = 1024; // The minimum length of line segments in pixels. double min_line_length = 3; // The tolerance for classifying lines into horizontal/vertical. double line_orientation_tolerance = 0.2; // The maximum distance in pixels between lines and the vanishing points. double max_line_vp_distance = 0.5; // The maximum cosine distance between estimated axes to be inliers. double max_axis_distance = 0.05; }; // Estimate gravity vector by assuming gravity-aligned image orientation, i.e. // the majority of images is assumed to have the gravity vector aligned with an // upright image plane. Eigen::Vector3d EstimateGravityVectorFromImageOrientation( const Reconstruction& reconstruction, double max_axis_distance = 0.05); // Estimate the coordinate frame of the reconstruction assuming a Manhattan // world by finding the major vanishing points in each image. This function // assumes that the majority of images is taken in upright direction, i.e. // people are standing upright in the image. The orthonormal axes of the // estimated coordinate frame will be given in the columns of the returned // matrix. If one axis could not be determined, the respective column will be // zero. The axes are specified in the world coordinate system in the order // rightward, downward, forward. #ifdef COLMAP_LSD_ENABLED Eigen::Matrix3d EstimateManhattanWorldFrame( const ManhattanWorldFrameEstimationOptions& options, const Reconstruction& reconstruction, const std::string& image_path); #endif // Aligns the reconstruction to the plane defined by running PCA on the 3D // points. The model centroid is at the origin of the new coordinate system // and the X axis is the first principal component with the Y axis being the // second principal component void AlignToPrincipalPlane(Reconstruction* recon, Sim3d* tform); // Aligns the reconstruction to the local ENU plane orientation. Rotates the // reconstruction such that the x-y plane aligns with the ENU tangent plane at // the point cloud centroid and translates the origin to the centroid. // If unscaled == true, then the original scale of the model remains unchanged. void AlignToENUPlane(Reconstruction* recon, Sim3d* tform, bool unscaled); } // namespace colmap colmap-3.10/src/colmap/estimators/coordinate_frame_test.cc000066400000000000000000000146471464745566500240550ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include "colmap/estimators/coordinate_frame.h" #include "colmap/geometry/gps.h" #include namespace colmap { namespace { TEST(CoordinateFrame, EstimateGravityVectorFromImageOrientation) { Reconstruction reconstruction; EXPECT_EQ(EstimateGravityVectorFromImageOrientation(reconstruction), Eigen::Vector3d::Zero()); } TEST(CoordinateFrame, EstimateManhattanWorldFrame) { Reconstruction reconstruction; std::string image_path; EXPECT_EQ( EstimateManhattanWorldFrame( ManhattanWorldFrameEstimationOptions(), reconstruction, image_path), Eigen::Matrix3d::Zero()); } TEST(CoordinateFrame, AlignToPrincipalPlane) { // Start with reconstruction containing points on the Y-Z plane and cameras // "above" the plane on the positive X axis. After alignment the points should // be on the X-Y plane and the cameras "above" the plane on the positive Z // axis. Sim3d tform; Reconstruction reconstruction; // Setup image with projection center at (1, 0, 0) Image image; image.SetImageId(1); image.SetRegistered(true); image.CamFromWorld() = Rigid3d(Eigen::Quaterniond::Identity(), Eigen::Vector3d(-1, 0, 0)); reconstruction.AddImage(image); // Setup 4 points on the Y-Z plane const point3D_t p1 = reconstruction.AddPoint3D(Eigen::Vector3d(0, -1, 0), Track()); const point3D_t p2 = reconstruction.AddPoint3D(Eigen::Vector3d(0, 1, 0), Track()); const point3D_t p3 = reconstruction.AddPoint3D(Eigen::Vector3d(0, 0, -1), Track()); const point3D_t p4 = reconstruction.AddPoint3D(Eigen::Vector3d(0, 0, 1), Track()); AlignToPrincipalPlane(&reconstruction, &tform); // Note that the final X and Y axes may be inverted after alignment, so we // need to account for both cases when checking for correctness const bool inverted = tform.rotation.y() < 0; // Verify that points lie on the correct locations of the X-Y plane EXPECT_LE((reconstruction.Point3D(p1).xyz - Eigen::Vector3d(inverted ? 1 : -1, 0, 0)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(p2).xyz - Eigen::Vector3d(inverted ? -1 : 1, 0, 0)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(p3).xyz - Eigen::Vector3d(0, inverted ? 1 : -1, 0)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(p4).xyz - Eigen::Vector3d(0, inverted ? -1 : 1, 0)) .norm(), 1e-6); // Verify that projection center is at (0, 0, 1) EXPECT_LE( (reconstruction.Image(1).ProjectionCenter() - Eigen::Vector3d(0, 0, 1)) .norm(), 1e-6); // Verify that transform matrix does shuffling of axes Eigen::Matrix3x4d expected; if (inverted) { expected << 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0; } else { expected << 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0; } EXPECT_LT((tform.ToMatrix() - expected).norm(), 1e-6); } TEST(CoordinateFrame, AlignToENUPlane) { // Create reconstruction with 4 points with known LLA coordinates. After the // ENU transform all 4 points should land approximately on the X-Y plane. GPSTransform gps; auto points = gps.EllToXYZ({Eigen::Vector3d(50, 10.1, 100), Eigen::Vector3d(50.1, 10, 100), Eigen::Vector3d(50.1, 10.1, 100), Eigen::Vector3d(50, 10, 100)}); Sim3d tform; Reconstruction reconstruction; std::vector point_ids; for (size_t i = 0; i < points.size(); ++i) { point_ids.push_back(reconstruction.AddPoint3D(points[i], Track())); LOG(INFO) << points[i].transpose(); } AlignToENUPlane(&reconstruction, &tform, false); // Verify final locations of points EXPECT_LE((reconstruction.Point3D(point_ids[0]).xyz - Eigen::Vector3d(3584.8565215, -5561.5336506, 0.0742643)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(point_ids[1]).xyz - Eigen::Vector3d(-3577.3888622, 5561.6397107, 0.0783761)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(point_ids[2]).xyz - Eigen::Vector3d(3577.4152111, 5561.6397283, 0.0783613)) .norm(), 1e-6); EXPECT_LE((reconstruction.Point3D(point_ids[3]).xyz - Eigen::Vector3d(-3584.8301178, -5561.5336683, 0.0742791)) .norm(), 1e-6); // Verify that straight line distance between points is preserved for (size_t i = 1; i < points.size(); ++i) { const double dist_orig = (points[i] - points[i - 1]).norm(); const double dist_tform = (reconstruction.Point3D(point_ids[i]).xyz - reconstruction.Point3D(point_ids[i - 1]).xyz) .norm(); EXPECT_LE(std::abs(dist_orig - dist_tform), 1e-6); } } } // namespace } // namespace colmap colmap-3.10/src/colmap/estimators/cost_functions.h000066400000000000000000000533711464745566500224140ustar00rootroot00000000000000// Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #pragma once #include "colmap/geometry/rigid3.h" #include "colmap/sensor/models.h" #include "colmap/util/eigen_alignment.h" #include "colmap/util/logging.h" #include #include #include #include namespace colmap { template using EigenVector3Map = Eigen::Map>; template using EigenQuaternionMap = Eigen::Map>; using EigenMatrix6d = Eigen::Matrix; inline Eigen::MatrixXd SqrtInformation(const Eigen::MatrixXd& covariance) { return covariance.inverse().llt().matrixL().transpose(); } // Standard bundle adjustment cost function for variable // camera pose, calibration, and point parameters. template class ReprojErrorCostFunction { public: explicit ReprojErrorCostFunction(const Eigen::Vector2d& point2D) : observed_x_(point2D(0)), observed_y_(point2D(1)) {} static ceres::CostFunction* Create(const Eigen::Vector2d& point2D) { return ( new ceres::AutoDiffCostFunction, 2, 4, 3, 3, CameraModel::num_params>( new ReprojErrorCostFunction(point2D))); } template bool operator()(const T* const cam_from_world_rotation, const T* const cam_from_world_translation, const T* const point3D, const T* const camera_params, T* residuals) const { const Eigen::Matrix point3D_in_cam = EigenQuaternionMap(cam_from_world_rotation) * EigenVector3Map(point3D) + EigenVector3Map(cam_from_world_translation); CameraModel::ImgFromCam(camera_params, point3D_in_cam[0], point3D_in_cam[1], point3D_in_cam[2], &residuals[0], &residuals[1]); residuals[0] -= T(observed_x_); residuals[1] -= T(observed_y_); return true; } private: const double observed_x_; const double observed_y_; }; // Bundle adjustment cost function for variable // camera calibration and point parameters, and fixed camera pose. template class ReprojErrorConstantPoseCostFunction : public ReprojErrorCostFunction { using Parent = ReprojErrorCostFunction; public: ReprojErrorConstantPoseCostFunction(const Rigid3d& cam_from_world, const Eigen::Vector2d& point2D) : Parent(point2D), cam_from_world_(cam_from_world) {} static ceres::CostFunction* Create(const Rigid3d& cam_from_world, const Eigen::Vector2d& point2D) { return (new ceres::AutoDiffCostFunction< ReprojErrorConstantPoseCostFunction, 2, 3, CameraModel::num_params>( new ReprojErrorConstantPoseCostFunction(cam_from_world, point2D))); } template bool operator()(const T* const point3D, const T* const camera_params, T* residuals) const { const Eigen::Quaternion cam_from_world_rotation = cam_from_world_.rotation.cast(); const Eigen::Matrix cam_from_world_translation = cam_from_world_.translation.cast(); return Parent::operator()(cam_from_world_rotation.coeffs().data(), cam_from_world_translation.data(), point3D, camera_params, residuals); } private: const Rigid3d& cam_from_world_; }; // Bundle adjustment cost function for variable // camera pose and calibration parameters, and fixed point. template class ReprojErrorConstantPoint3DCostFunction : public ReprojErrorCostFunction { using Parent = ReprojErrorCostFunction; public: ReprojErrorConstantPoint3DCostFunction(const Eigen::Vector2d& point2D, const Eigen::Vector3d& point3D) : Parent(point2D), point3D_x_(point3D(0)), point3D_y_(point3D(1)), point3D_z_(point3D(2)) {} static ceres::CostFunction* Create(const Eigen::Vector2d& point2D, const Eigen::Vector3d& point3D) { return (new ceres::AutoDiffCostFunction< ReprojErrorConstantPoint3DCostFunction, 2, 4, 3, CameraModel::num_params>( new ReprojErrorConstantPoint3DCostFunction(point2D, point3D))); } template bool operator()(const T* const cam_from_world_rotation, const T* const cam_from_world_translation, const T* const camera_params, T* residuals) const { const T point3D[3] = {T(point3D_x_), T(point3D_y_), T(point3D_z_)}; return Parent::operator()(cam_from_world_rotation, cam_from_world_translation, point3D, camera_params, residuals); } private: const double point3D_x_; const double point3D_y_; const double point3D_z_; }; // Rig bundle adjustment cost function for variable camera pose and calibration // and point parameters. Different from the standard bundle adjustment function, // this cost function is suitable for camera rigs with consistent relative poses // of the cameras within the rig. The cost function first projects points into // the local system of the camera rig and then into the local system of the // camera within the rig. template class RigReprojErrorCostFunction { public: explicit RigReprojErrorCostFunction(const Eigen::Vector2d& point2D) : observed_x_(point2D(0)), observed_y_(point2D(1)) {} static ceres::CostFunction* Create(const Eigen::Vector2d& point2D) { return ( new ceres::AutoDiffCostFunction, 2, 4, 3, 4, 3, 3, CameraModel::num_params>( new RigReprojErrorCostFunction(point2D))); } template bool operator()(const T* const cam_from_rig_rotation, const T* const cam_from_rig_translation, const T* const rig_from_world_rotation, const T* const rig_from_world_translation, const T* const point3D, const T* const camera_params, T* residuals) const { const Eigen::Matrix point3D_in_cam = EigenQuaternionMap(cam_from_rig_rotation) * (EigenQuaternionMap(rig_from_world_rotation) * EigenVector3Map(point3D) + EigenVector3Map(rig_from_world_translation)) + EigenVector3Map(cam_from_rig_translation); CameraModel::ImgFromCam(camera_params, point3D_in_cam[0], point3D_in_cam[1], point3D_in_cam[2], &residuals[0], &residuals[1]); residuals[0] -= T(observed_x_); residuals[1] -= T(observed_y_); return true; } private: const double observed_x_; const double observed_y_; }; // Rig bundle adjustment cost function for variable camera pose and camera // calibration and point parameters but fixed rig extrinsic poses. template class RigReprojErrorConstantRigCostFunction : public RigReprojErrorCostFunction { using Parent = RigReprojErrorCostFunction; public: explicit RigReprojErrorConstantRigCostFunction(const Rigid3d& cam_from_rig, const Eigen::Vector2d& point2D) : Parent(point2D), cam_from_rig_(cam_from_rig) {} static ceres::CostFunction* Create(const Rigid3d& cam_from_rig, const Eigen::Vector2d& point2D) { return (new ceres::AutoDiffCostFunction< RigReprojErrorConstantRigCostFunction, 2, 4, 3, 3, CameraModel::num_params>( new RigReprojErrorConstantRigCostFunction(cam_from_rig, point2D))); } template bool operator()(const T* const rig_from_world_rotation, const T* const rig_from_world_translation, const T* const point3D, const T* const camera_params, T* residuals) const { const Eigen::Quaternion cam_from_rig_rotation = cam_from_rig_.rotation.cast(); const Eigen::Matrix cam_from_rig_translation = cam_from_rig_.translation.cast(); return Parent::operator()(cam_from_rig_rotation.coeffs().data(), cam_from_rig_translation.data(), rig_from_world_rotation, rig_from_world_translation, point3D, camera_params, residuals); } private: const Rigid3d& cam_from_rig_; }; // Cost function for refining two-view geometry based on the Sampson-Error. // // First pose is assumed to be located at the origin with 0 rotation. Second // pose is assumed to be on the unit sphere around the first pose, i.e. the // pose of the second camera is parameterized by a 3D rotation and a // 3D translation with unit norm. `tvec` is therefore over-parameterized as is // and should be down-projected using `SphereManifold`. class SampsonErrorCostFunction { public: SampsonErrorCostFunction(const Eigen::Vector2d& x1, const Eigen::Vector2d& x2) : x1_(x1(0)), y1_(x1(1)), x2_(x2(0)), y2_(x2(1)) {} static ceres::CostFunction* Create(const Eigen::Vector2d& x1, const Eigen::Vector2d& x2) { return (new ceres::AutoDiffCostFunction( new SampsonErrorCostFunction(x1, x2))); } template bool operator()(const T* const cam2_from_cam1_rotation, const T* const cam2_from_cam1_translation, T* residuals) const { const Eigen::Matrix R = EigenQuaternionMap(cam2_from_cam1_rotation).toRotationMatrix(); // Matrix representation of the cross product t x R. Eigen::Matrix t_x; t_x << T(0), -cam2_from_cam1_translation[2], cam2_from_cam1_translation[1], cam2_from_cam1_translation[2], T(0), -cam2_from_cam1_translation[0], -cam2_from_cam1_translation[1], cam2_from_cam1_translation[0], T(0); // Essential matrix. const Eigen::Matrix E = t_x * R; // Homogeneous image coordinates. const Eigen::Matrix x1_h(T(x1_), T(y1_), T(1)); const Eigen::Matrix x2_h(T(x2_), T(y2_), T(1)); // Squared sampson error. const Eigen::Matrix Ex1 = E * x1_h; const Eigen::Matrix Etx2 = E.transpose() * x2_h; const T x2tEx1 = x2_h.transpose() * Ex1; residuals[0] = x2tEx1 * x2tEx1 / (Ex1(0) * Ex1(0) + Ex1(1) * Ex1(1) + Etx2(0) * Etx2(0) + Etx2(1) * Etx2(1)); return true; } private: const double x1_; const double y1_; const double x2_; const double y2_; }; template inline void EigenQuaternionToAngleAxis(const T* eigen_quaternion, T* angle_axis) { const T quaternion[4] = {eigen_quaternion[3], eigen_quaternion[0], eigen_quaternion[1], eigen_quaternion[2]}; ceres::QuaternionToAngleAxis(quaternion, angle_axis); } // 6-DoF error on the absolute pose. The residual is the log of the error pose, // splitting SE(3) into SO(3) x R^3. The 6x6 covariance matrix is defined in the // reference frame of the camera. Its first and last three components correspond // to the rotation and translation errors, respectively. struct AbsolutePoseErrorCostFunction { public: AbsolutePoseErrorCostFunction(const Rigid3d& cam_from_world, const EigenMatrix6d& covariance_cam) : world_from_cam_(Inverse(cam_from_world)), sqrt_information_cam_(SqrtInformation(covariance_cam)) {} static ceres::CostFunction* Create(const Rigid3d& cam_from_world, const EigenMatrix6d& covariance_cam) { return ( new ceres::AutoDiffCostFunction( new AbsolutePoseErrorCostFunction(cam_from_world, covariance_cam))); } template bool operator()(const T* const cam_from_world_q, const T* const cam_from_world_t, T* residuals_ptr) const { const Eigen::Quaternion param_from_measured_q = EigenQuaternionMap(cam_from_world_q) * world_from_cam_.rotation.cast(); EigenQuaternionToAngleAxis(param_from_measured_q.coeffs().data(), residuals_ptr); Eigen::Map> param_from_measured_t(residuals_ptr + 3); param_from_measured_t = EigenVector3Map(cam_from_world_t) + EigenQuaternionMap(cam_from_world_q) * world_from_cam_.translation.cast(); Eigen::Map> residuals(residuals_ptr); residuals.applyOnTheLeft(sqrt_information_cam_.template cast()); return true; } private: const Rigid3d world_from_cam_; const EigenMatrix6d sqrt_information_cam_; }; // 6-DoF error between two absolute poses based on a measurement that is their // relative pose, with identical scale for the translation. The covariance is // defined in the reference frame of the camera j. // Its first and last three components correspond to the rotation and // translation errors, respectively. // // Derivation: // j_T_w = ΔT_j·j_T_i·i_T_w // where ΔT_j = exp(η_j) is the residual in SE(3) and η_j in tangent space. // Thus η_j = log(j_T_w·i_T_w⁻¹·i_T_j) // Rotation term: ΔR = log(j_R_w·i_R_w⁻¹·i_R_j) // Translation term: Δt = j_t_w + j_R_w·i_R_w⁻¹·(i_t_j -i_t_w) struct MetricRelativePoseErrorCostFunction { public: MetricRelativePoseErrorCostFunction(const Rigid3d& i_from_j, const EigenMatrix6d& covariance_j) : i_from_j_(i_from_j), sqrt_information_j_(SqrtInformation(covariance_j)) {} static ceres::CostFunction* Create(const Rigid3d& i_from_j, const EigenMatrix6d& covariance_j) { return (new ceres::AutoDiffCostFunction( new MetricRelativePoseErrorCostFunction(i_from_j, covariance_j))); } template bool operator()(const T* const i_from_world_q, const T* const i_from_world_t, const T* const j_from_world_q, const T* const j_from_world_t, T* residuals_ptr) const { const Eigen::Quaternion j_from_i_q = EigenQuaternionMap(j_from_world_q) * EigenQuaternionMap(i_from_world_q).inverse(); const Eigen::Quaternion param_from_measured_q = j_from_i_q * i_from_j_.rotation.cast(); EigenQuaternionToAngleAxis(param_from_measured_q.coeffs().data(), residuals_ptr); Eigen::Matrix i_from_jw_t = i_from_j_.translation.cast() - EigenVector3Map(i_from_world_t); Eigen::Map> param_from_measured_t(residuals_ptr + 3); param_from_measured_t = EigenVector3Map(j_from_world_t) + j_from_i_q * i_from_jw_t; Eigen::Map> residuals(residuals_ptr); residuals.applyOnTheLeft(sqrt_information_j_.template cast()); return true; } private: const Rigid3d& i_from_j_; const EigenMatrix6d sqrt_information_j_; }; // A cost function that wraps another one and whiten its residuals with an // isotropic covariance, i.e. assuming that the variance is identical in and // independent between each dimension of the residual. template class IsotropicNoiseCostFunctionWrapper { class LinearCostFunction : public ceres::CostFunction { public: explicit LinearCostFunction(const double s) : s_(s) { set_num_residuals(1); mutable_parameter_block_sizes()->push_back(1); } bool Evaluate(double const* const* parameters, double* residuals, double** jacobians) const final { *residuals = **parameters * s_; if (jacobians && *jacobians) { **jacobians = s_; } return true; } private: const double s_; }; public: template static ceres::CostFunction* Create(const double stddev, Args&&... args) { THROW_CHECK_GT(stddev, 0.0); ceres::CostFunction* cost_function = CostFunction::Create(std::forward(args)...); const double scale = 1.0 / stddev; std::vector conditioners( #if CERES_VERSION_MAJOR < 2 cost_function->num_residuals()); // Ceres <2.0 does not allow reusing the same conditioner multiple times. for (size_t i = 0; i < conditioners.size(); ++i) { conditioners[i] = new LinearCostFunction(scale); } #else cost_function->num_residuals(), new LinearCostFunction(scale)); #endif return new ceres::ConditionedCostFunction( cost_function, conditioners, ceres::TAKE_OWNERSHIP); } }; template

B[F7C(@<g  7 l$(BPKATt4 "UX2C.a槜>8 X \κ8\r,Z* _Cl`-9(/clˎ4ʛK>kPJ̙SD%HeK*y?Lλ24;͂V3.ϗK`? 96<";=ǎ_zJ~g`)FE߱nZ@Z:e/?^(+,4λl w`ݲe2l$ОlԜ92=}* l @/=B[sa+bD,c/ p1;.d)kP~l1dEѯN8>OZy\dBJHhαı(LApm1_3x =0hi[/[7Ȇ:mR^6BƎBٹ{cR_vR5~*z%L(D nʮ%^{zǕPJ@ (%p\{e=( 0`G?Tj<@:Ll()X%<`;0(Gtlz )@U!5J%6 q.H׬' ?_Xɠfk\vEuI `:, #*?F:ʉ\n:]jٰl_h&lntv?h~lF\B ]nxB`GA"_y$>JRi%c8=17\ (pW3GכBX&0SeߞҶ]"xҤ pyqGn.*'&&OҲQIv5m7m zpi ˫^Gksz#|"t(%$>># eqV|xC ( {^_Ϩ{@;mcJXBڟ}jY2͘OGt?5}#esܹY;vΝ ܉W^)[kj6o6&F-=FΘ!+K/5mq%׈,\YGy%6%i(Gh -b&:gTtEFQBye;G9*AC' >6b!PdcI ti*6 4;D5M ot~5V.$z-c-\ה )pД~:vqlc|(g=I&kzQ,'vG?(v\(Ӧ͔m ҾI<.P 4C7l\u(%04 >z^ݟG@.-QG~ezD%04ģ] %Źy 7/Gv% ^?חHf*1et /H[czMBkI\  \<u|KFqNH2nbX,S}<\\.o2T:X:=[Quoqo'> VҿMY׽7ˁZDk}ȑ{ 8zro-KyD&wq&~V[cvgKNAh@g՟9'OEl^-G?[HBaKVX)$e 5Yfu IJF`Ŷ;%{FdR7_)BcbhU60g .w6"V}jsBXcgGGD"T0M0~p6S3AsA@Vׁ}-(MtAD` va$"!(a D"թpmq@3*{v# kؾ様:;ө8}LYw@ _7uBL 7k׸!p9s幅':?4ػE;U?ȝWIWBMOKɯWMGZhhm߰Q9V]Unx+'(,.6%}Tҥ2M?k۱7ٲG1H"u5̉pQYBa=a qQ<`m̓S_U~)=CmcYV~WyNXFkbB\`0ށ͈[SI,r<B%RTj& ~k6(;X36P3Ғ֔ADs׃MdPbI/QtFKBǺykGiC8Ǭ #C!d! 7|j>F|6 KEyTl&(p-Pjs3 t ژ*۱/?]* Πlvy mEl\ro#ҶZӧnzt59B 5mxnZQU(9;}^M;rzG%z'ѣuDB68aґ}]A}:#rm>얳xaa \S.lB*Gic0wd6mݏ+)nY/x”֎ӱhmyz(.然 pLNU֮{ߔe:\ne?)L;*{VpH.:\15”%Wh0 wY%xPHeMҨ2bǤSh7T;qfD)+Cv5@Gt8n㎃X)))<_T)cFK</2ab!]~|n4ŠIϜ4avYއob(Snm ;ρ%'f:ٓtuxM֑{nR^6nb6 5=ߓNI]ѱOCd @Λs1~]h> _v,h :w~C (n^|u_K^OvC)8ko5"[Ŝ9tG9/)U&l P~5>~_6?*0q %l4^R3a t6=֭\{y&UGSDQ t,\1JAicI5_LA@cO5qL)( MS?!3}t@hgCYf 4=ݮ,!FDIX!90! *uIŘr"rCK` jxB> eZ[> PcN:1W{|?F4!{3f?=v]`[SWam][%r kZGn`[}'t-2{PJwe%r]r虑#GʯyX?kez ]O%"PQQ!?yGIh5M.H/Jqeeg]\Y,2bKEE9%'d3 9T.\(cȔy Mm.0kk? miIƨN\1hO)Qr8\Xt6ԓSP`, X)As"0STc5G5!@ZpqpAhb)zXVs`=w~_W]ζdkZG9_w}Uzcs]L +_r̿\xKM<翘R6 ѡ Yt/I<u[0q G#KCb)ci 3,}rtg[PA~u}L]YD^}_w9*1q#q4pK H&]x!2bbV:SLԶYUz8 v"BS9HFˍepQ̈Q!t?At=c(QW'¹(R9!^9\G&wgh{;Z0 X.ʴ% KY)s"dBט)?H}pű=pQ wY˂sTXBm:C q.L ud1k60Gy<Ztdߘ;弳>///~^֭_S]mY)A"c|lZ.:HaZ:9dsV$5w~UP* |R1jLXُxHp7ɍ7\/k֮-["lx.[ .Dʱ2}'.? p/m}YCڵK(PX9VE6vbK@g_}u-[fyC qyԨs>tˑ6Ks}>O$p !.XsXi be0l?P`UfWOjӉu0 ͠TTY2sROR8c(W 6C3.jpA ̜cN4sc8߰N&FAlPtݱ4RS ]\:9$pQ !;Ka8u(ӌV#f@:P"`).nzWh23\xӡM3>S=;% &G c}yI;6;Dﲖޓ|&O,#!Y3;w,GAJ 匯}-OML(=Һ}!m^[ŁpCbU\צ\/Y6YuJaI>݂P_6ZPJGKI1 E\(/miVO[k,لX E8t1Z,"]L7|o<K2*x !-I,;t@ -fViÄ$`9XK^mX|JI, e+Scv(u׮ƕzL3~싂Q>,/]r:]2e#FEgVJ@ (%PJ@ (AF|UU{dx?g6ɑX!vh^uOe[oI WFeSh=Ǥck6֗RP5kH$ҩؗp{55IҺmXZ D4%KK M>*{4T^sM_ mtsY\eKAڊRr@X ,-2MSJ Xg(+wFôgf\jmtŃ! Jٶ/pk9ֺ} p%q1B,(Z./`t0bsZO*pPb(K)cyP]fo=2#MFלB'q?(jR͎@VϹ)%}jsPPL':qqx)&!0!退g5W%PJ@ (%PJoZׯ}k֘zV8 C[sI-LbK)Rm%Gn+r8 tpdm\XN^F k>'h&:No Ck.q-%8q7 H^kG JRx)h[qIMYk~?k}PJ@ (%PJ@ (%'Ґ9K 8Y_!}_h?s+#Re^y%]Zxb6G "[}ݟU? }PJ@ (%PJ@ (%)QW\!7K>DHsid'Z_{<O?ǯ('QwJ ˳PnK"--{X9s|G~Ux*#+B#<2TWשPJ@ (%PJ@ Yd~ Ƣ@u]w;WqW\j|;曻IAc_J|Rdőߵɜ@fūϯ{(%PJ@ (%PJ@ d/CiAoEO }c֏~$_s`Oy>i7ߔаp\T֓~3U]PJ@ (%PJ@ (%pp6!EW9G\)%H,:d~a-O?-vτ@m,woEf>\gtd mᨳ(%PJ@ (%PJ˥ o =NA9'pmw#3!ĭFH‹sHѬYoHm}GeAUh;_]=7%PJ@ (%PJ `XLŅ@VTkWi{MҶa\jLG :O@3PJ@ (%PJ@ (%pTm6v/Y"@@@<#Qʺf%uxPJ@ (%PJ@ (@{Eٵt\e56_B=%PJ@ (%PJ@ @g }tPh`IPJ@ (%PJ@ (%7h;^A:`0(:PJk<&kSJ@ (%r@ݖ9"]8|v/R(t(߾E~eSF (%@`˶FL:PJ@ (%>/BW@@KGQPJ@ (%PJ@ (%P*πPJ@ (%PJ@ (%K #=O 5 Izu(%PJ@ (%JTJ5 m*%PJ@ (%PJ@ (%p`PJ@ (%PJ@ (%@ otPJ@ (%PJ@ (%8@?CIENDB`colmap-3.10/doc/images/sparse.png000077500000000000000000040755471464745566500170040ustar00rootroot00000000000000PNG  IHDRY5C$sRGB pHYs  YiTXtXML:com.adobe.xmp 1 L'Y@IDATx|\ll6HiQ*Z.p{{.ťTh)uwMٸsβF6&y̙3lJKD /st=sA~} ḼhUk藟+kky#w+TUU&tm(MAȞϰ[> b,}ɀȉspuvC_M^47:B#v/^FеKx/UUUpv&o۵\ʟjhv˕%0 dfLd]]P- DH -Pe27Te :,oXNMlj{ NCھ:U"@ E@DV!4"@M|.N&@-u0p/^u\!3%?wpuV 'EbE]:"+=u'}=^hA*27*ym?nZ j*izLuA{cs}C2 #v30 D"@&l~";V"kCM>?@J!"@ D`d yN & Ue2JK%Co $vN}s ~C\=q ex(5ոv ~ep0==|]~fZ#o;8h#h?+)9#SVv돻~'RŹ p|9v6=k> SԺSceD ,:j"@PN(']Y31>X18qVE&;D"@F,04 D<Cln:1UX>GC'@503pg,V#`"-oVeAۨmLݛ FMeoD@ca*L=[N`G8[ػx")z` `BLl~y/Z;v3͏?Bv/'-0[);O->w YB7"2r+V4̛uX?{XuB s{xL8,-'x&ˆ D`\vNu ujpSZ4Z@@V˒"@P&.Xͅ"0 KXM#PZڰp]!5!}xPª < 3!@lsf•"Rjb,Zx+lp"빠kȋNogώx`#=k.ï} lݦ iv,zYԨ=St?ڊbԲ0Qq8a,[43D|UMKg-BSm)=b '۽{t?)soj^K='mƠBLC"@ D`t ^=ttgI"@ %@K"@&ƆZ@]  H׶W&4`a〫BosW˯Sa}K =ow)L[;{Lٗ0mrdfł}#3Gv߮]c:*&ry<&#X9B#3=sx?zBaªWS588 _/vV{N`rl$\VTXVRix{e+͏"@:JQ_t C D O3$ DqO*jPWBBl8+kMO {.l_u/zzc L|2#P܆|7S[S^@8?ZJP~#@#00ABz6jذ~Spq,?]# nuv,fV3ҡhifa_/5ܩ#H$k#ı]_u(Xv5,Xn^0 OAYw'gW^s0Jan&P]^WD!-!֛9#R1 ;pkХKȈ ëwMr #VrϝfG D7:͗"0kW?hp*hvg@Md[ӲsQQY  N(qYs;PTP ohhiW_~}!|!y{*(4+T[ T,+ݏU9f8ft oLvݡ[줶$/ EV*:"0Bjkk! G:8{ ȍ*Iniб#^_dhID"@'@ 'PUVaC]IM tSoYqLζhilA|dx7pbZ"`Ru}xeHMn[`LLOz6imT40%RMBgV.qk8u/?i4\TQ.S" 펏zGS`}ꙗ勳 H% ,g*Z?:+FRW_'zm4+UuLI`M4 DIJ@m&iDIE 8t:Zwm"  ՟N`}tmx7dUˣ]((.SPY^ 63PO 'aώ 00…בw~-L7{:JsR0sў27fVPԁ z 4Ń뤤OΞ#qμlNoEn(aaIa"kpV?ŴY{%˔ D`|,˒@VwBȘe7bSPЏ1 K+7(D yNH D(@Nr, L``J^NJ;,^9ٙxS9TVW"*2,HPUW -gwO4U@K Bkd&c㦇 ~m> $P[%$'N޷$5ͅPAMwpԔ̸i&#o|wNh}b4wYX^fypIq&!.D`B =-_z{B38W_x?utgG)#IAĖ85M85̄{웚) DnHd톃N s3m> D^T|̥{e:h|ԡjUW\߁KoAoB|yOq|"RjDDC3>}&^?r[UhcqYspB@ǐ O0VUzz|^huiX횢RDzN!||<5RI.Tl3~77V-t@aO>@d(@ou3lҿ@Bk7$t455B]]j#X>|d?a,=2⠢maRXWq>l(d"@nI5 DOL\՚ kΰϝCzF&gӬ+n3ric]dd0o~̅ acBE@]EEYe~zy!]R KPBۏduYV7DŽtz?LD1F˦4+Lؿc#V֕壅髩38O̫ZYRIZ8 klcJZ:z0YAMmbK:=S:N٤t\q `"pPfQt:C[y41 UUU>2Ln ZU"H7T}Sf[$ikhd~ 5έe:"@!@VB }(//l"]!cO`Ro+߷%l౧ř"3dg!!&_9 )q2<:X.D {qyc~\3–Xcl(=ҵ[ K{\uB'D$h "@@fR< md:HP7BUKqp"k{Y ]6 dR/vMTAy*鍡i"@F@L*(qIDqyhD"0QT&D"󉲤qNd0m_a3t@ء3ϙ8]:v4eb r됓OOhI s/ܺrhj}r%r_"+'?-PhC7 GKl$>> .^ǐmtX u!PqE|ʴX66`V 6(.*t4s%i ![;R[Y8^Κ>щ @ue9l0Xb U"@@lv {L6l.t(% &E{1m\͜33V.:z78?LKKWf| qQX_p~e^EyiLڲa(r@3ݝSU(jVea &{=f%CGf!c7#'&' \!m.?yCW= 5h1r.$uoDSwϻ |tBpB•YHTA D"@ yNJ"D @d5XXvBu2#c{A]Q *Qyn%Z-(h{ :wb}Iۏ>R;Ȳ-`uY1MK C5tɣcLZ^I=f~G{W4TL@? khأ"/= :won$po*lhb {1 L DjK9uKVԀ"@jJ @LBYl+}Wȋ6 핹n^sa gQ 7ZL|3k.m?mՅ;:yg L<.]$/W̋ci-b--)7/;GU @Mq68֮)&6;wtYsy+^PDFF{3sR~rLW}2^zm> aX)"0OEO\E~nZ"N ؘ"@ DHd5#jA$$ceJD`PGkGsO ǟظae-PmGNz"Ԅƨkl!8R=X__BaeTr,\?2+ʍ>~?]|]Ld^y1 1WAC/̦ ^|~~n:شqZk07/?lދt=^+YhhH:y7̘9D }Li|VqB4p D"hOVG4C"@@mU!ln;Vti8=L'ơ^P;gJRpYR#/{N:zT "6>Ά0-NDF|7?KUTcUpUq0'(f_z܊;zEhoiElT`{ >sVAl;qm,Nk_X.]VdyHzMxg0cHS'rhk<3Y\P.¼tp"못=ҜD@ _$pz@K5\7X΋&D"@z '!DLz%/򄖎K"\/3B3B=W5qM+ }-T <.O8:< ʄhƩ_Eq1ʋ%YYBSӨORǏWQvogUC;y\)]&>N`͎?>/ Êkbl<}m7qҰ^wzkKuCE@CCYGg`1FAOLDl trd~M1xwp|^"'$Xp'$\=Uxd"@&65 '-4 /V"._D- %VW[5&>y96YKw\ [p!1ܾi1 yd'~%.yߩ,DbzAڷIL223ygy[$HKw}BYz8*KQA~ SC`JJ.sny*J`=e<p*DQM /K-T\(?L::l)=ǘ?o51F_G ˔ D y#D"XG-!]:UI$ȍ[ײu{5 Wo^ʊz~(j_;#THr9ҵwŽݖfoᏃq600ۄmS`}MPkjyb/S"+!o!琝*xM!>./uV).;6 v}&b8qa-$/1󼝜y %Ym- w'#݁=Run58#i3٬iD;JႻs3"@D!P[3 _ԉ4Z 7w OGL"@d!PSSc\U5A E!ge.z-k\xX`|4TW{ߙDPCSC$qwT]7hU7^Of7_7z7OE)έY_v}mPU\Hl۾Yh`_\1|cD#/zzrkxe7DOf Y͏NhTpK)xdW\GϹBTXU҉xv~41"0܃8z7RԆ"0> %DQI<>WA&DV-!R^pK[5D@fI DqH .1ť0 yZZex{y,?P& |wU!b'42E:F-m IZ<ZQS^ <3dH`{Λ?c{Ww}w@V!-< * h7ևGb" l2pA]eUƒ5=,V6;hd"8:N5,f#*&B] S6UkCi&lll~:046Ayy /jj/} "nKYWOG7-,m'n~+׭OUWW"@d)r^ڂgO||YA -&"k1\251gΜ֯tA[ZY^9¹lN=8Ds]ǻcO=![g.өb ܀#$Ζig^LdeѦߪ}EjZKg(D`LOa{-.ײs_才}&nY"  XCs^Ö 6e&g8>C ֮r{xХBTWYNLL*-}{ d)P[ڀ>JXN\咡qwI/ی۹Rd wT1[vj?B4VCS GIj24Q]SAomFFZ<\8ID3 \=*>OXkbTUSæk'5D89o&IIR"S3'n݄B|G  t71a]|`膦6ADT:%,vϷ181b;ԋ1:SH_ f i TϢ7/lΉ5f!ra9c22k]5ΎV6qA <Y@@ዏUvt?aȳ8;䁨`=? [Cޟ4%MP14ٸަL"koT"@x*#3 I`{,X ukw^HscS3e`?anOSfRSpitTY=Zja]p!>zu6KC%,g/EAEU T;|ǃ:8:`V@ճ;W{mmPS+] -2r8y2`=hm,YdRV n1Fpf6m~Ggjj‹ʥ O=#7ޱFVR}8cw-OjSקts0vC:tՠ!**63f_{f'c <մyY;KE `Ű)<݇!b^\hgJA@`bM`ͪ/UvQSKܵD P78$?N糶owk"&`YT kdYك%z0 )"0 i:/-mhE^4<3}%~ !ڍ0TA?1I"0Q#"@  Һ{gFF lZXXhDئ*v3FT|4ݻGѨhkB[s54F.LP#t@:T;]в Xv; gC u-0f;P7/{x̅ox-5HAy fa׭_{Pvk0eN\+ǩjZSUڀLI=|x " FzXam Chhgk0\^8 6*b)MVUmT[m=#>'3.s`ϩ\*$3v 2 "2b"Qw17ElM -]35g^B>wmϕKr4=끝?")6 n[ѯ* \*,(wl,[<Z&^pdd7板U+Uё"@FpVbmkpx]Q' qaqnurQU]V: D`@*Zz~7.(2uz$vAe"@ $S!߇w_=Ko1[Ov},~3-MhlQPgto569iJôQh'E :uUphe ?+"cX̨ X3&h裠O@mE!~t]*b']up񇵃+Q[YIJ%LbFT!'BCl1XϝG)L@yqJ %SVÄX{O>jK-B۔:"aQ&Uĉ7u%ġ74ʉ%?`>|3'yquִ݃: K+&Zo2*緑y kqzKU`xM{˔_ٖ%6oFXXR6,[sn&^zK{qm4'"0pM`c{U9uS<=_l.*5e}M[5DIM`c +Ryl74=#/N Mŋz}8"p3,pYYUǤ $ɯ߹n=_~2Ց/v^dV8yہrs̼=o""'a&.l,ƣ 3Ev:'Z)"0'xL`>P9 p\_3 rΚfEb/h$0/֞/DK \D i*SY6*5ő'"0y <Ð h哉@aJ SSk}/acG`^غ{pe Bcw>Ubia+ s6|p|s"2:s̑ sˣP:ʷ-'>Gz~ʋklJ8y_nj+a FjV.Zs n~b\t6"%Wڹ3p>,=XػwVY]>|s ϣfhj`qIw8O҃BWBx/V*R@: Iv vwлS箆!-tŶ^0,[v̤\3kz:B|~~>7k_z$k/DT5V\l,!ޣk[w>X{b#"tKD'%`lɼ޹L"@N?_ft `dMv|/]l޹PXS.}P[3*Kss-s!ُuH 5F}]Kota/Da#$D`زe /N^FnLT}QAWĝ6|`me_sƺ@(lش#w|c'bu[mFPG=-Nܞe%vYY7&$,=n36CijݽRY v?v%&٥7Dzkpy(e⪡Ȏm  ~ j#:"}~z4*+ S\WBrV!|v<{0*Z+W+ s+QXcs.9WmeYg/`@X.n>w^Bdp\=ghB0-Gv7o[&rōR=VPV|߾z02/`bҺk$g 39fVҗ5C D"PZ^y3jxY}c"S X߹[355M~[H"@&. u}~hD"0Lwo؀W}BRJj̚%Xʠ^`MdMMdJ2!†ƦZXX[+'rǁz43tX1Bn = ʧtV>OJCMy1ٹ:ξ~cR\$``䎊Z8zOE+sjd+W}=,ZB EsS M=N`lEFF"`,PSIV,rsnhhׅ#ħ8#aE0049Zf]ss3l]f! PWJz5e}7ߛ&z;6r\A!܆,3!xƂ0 LMDYqQ7=?ènc@(21=wBL(DQ~&WrG\d7B]ML""@P(g[Ɩ._3+@ $O ͙J`-qyO??1ŢҘ΀CAv0"@GTc`=wo&;ww"ڷ <_?c#%9?uu'v}KL@h4䯁Po8 OBWSO{w|_ڜpĦV'- |~L@AB? x'wocx9Ⱦ VT?W('֔Cϴ61X+k-Yx*5?.!7ї i34uybHɋ d墭 \ ;uڌ@GTBl)X|[S%wg #PSRGDC~k8 ۋP j;;1ϻv|H9g^7E 2#:D602A۳u?r`kga{v9y9g8~>7?B#cö#='D"@ D"@;fuU;‰=bJ:F'ð}Hapڈhi)pC 2ﰵN{+.^:`depK̓ {P Wgascud],++fפ"L!33%uLJ7ZKH8w,m`i]|U 5I!7`#>?o~ӑ{I^`:/B]cR`ge VTT'`cˇVyXXNꁚyM 5IAp`jp5IJˠV-mZL`)(glY!Oiϡ -+)};GPKEe,L&D,..\ 5f^*x9V.GQ%fW 51 ᵘ:ou&\ĩb }RM"S&=UkXxrwm-XxRHgߙ%%/res[Gy{jxpcZ1/~KKȝS"D"@ D"@G=#|&SQc?o&w*i'X8mJo4>Ԑ"0V~7$Ƅ"&:yYܹwQ&7' gYj*P[U ;YdCGWy5+XR鿋YXo* ^S뷟oD;֯?{@KN?~9ĬE="1Db{QT 5c6~׃w1VqN*l߷thhB``6&]=ńcE&Gt砱B#BM{U{HJpez3_N\ݒrwQ8lp||"!% p2 qS[v߅<[{hC8t:1d$9&vx/#9 !,P %q.yxÞ+KE 0w/#/;wo[U>ɏ7?^<<\uC)DE"&*nykhဘkǽ/imo+OÇ0a`oPxQ"@O? "Ѝ@ow; \n*JD"@ @EkuT ^ǽwNh' Q μ:=|cVsم0#Ѭ ?// w3N=5 ]d@IDATq|'+QR׊Yxի33-=&*l{6"@%VůLEM]&-" 'hWW4md(p^n10de%p)2vEFXS P9OyGo","1QK_n݉,,fo1!Z55zkEyhµs;yMXWm]&_NR_3 ƍ ze~6T~Zd샱x`x]Ώ25S1W~>ZYuta"A5lyiXo,ĝi&^8i\85Dߟę;7s NHE1C]}; ]9VK] ׮^AuuTSgamܵp/<>V΃uo AFlٖuAfVPW[0 xKACW =6= |  31{9VAsl>NO^99/y,WgHǴ{زu&r핵%}vo?'4tNٟgfh[ W/IJU69—gߦ7Esr2Js4%ci &`>*a3XDn&`Bw 4H'uCjA! si>"ShFK RQ_[[מ[ 5%&p!,vv 5/ QY;!ڌK}7;{NDL@W) \VJ'~gaaWc-L`2ܧ@OvsƼ[- pϟ!1 3 ,iVF& wgr֊bO$1Gu= 3n?ʻue_Myso'|~]][Gǧ=b{&Da? \-k/s/k )<w8r8^?q΀/^nXc]+l5S L8ŋfc<\0wv-'Q^+6`6=.# =4*I؞aaAX~K0s6?_|9m#Dd"+45 $r{t =p;쥇$vrWbX ;7 ƛd޺;v"**K:c7>lek /6l@_lGWg>o~ekgxi#ŧ :J{É7I<M"@>.#sʾJ$N g6Cuh㾵 _ SW@58t_Z/|Sf-FIE,\u6<Eb[YA]:\|ѫv8 S\]u!tin__7ݼnSj8/!kI-wVHr 6xyzs:TTV͏_(˓ B?!b̌ X^oBB\40^ Fԍk^{k[ ; B}| Mz%+VAlnv(`(2Q5Q.Z {wPY^+J^_m߆O;&`uU9UR! %[sк:#pPa}u -&Զ3PtDiq1.]m,e1A˫Zl%z9,Z ihgqyXD8,P>!b/$7L3p4c#z>~ wb3rahc8t.{}_sSsq~Y+֮AЬ2#oơ=7/~u浞^$Vnb,\>;[+E@u,߳؛0b_UXv޾X,֙LBC`rvqez^>WںBhI#qILwls"T]2 D( kw*A|msU nM(N`=wx{wr 06lU4&yR 5mfDM e"~/0}Y9z2qUӘQY{yr+,.Md9{I+@]y& +`bFÊ;ֆ#fjaӞ^~ /zxX:]Ķ 3o==,G3R]scKa^y{T5:S[o!g}{X}ތgK*k0pR+-^evomF"9&yNCcm6}L,`l>UO<*|}n\=ZǨKs '>\xU?.cŎuGUl?nzW $7AE)ݧ{CłDEy4@ i$!!el)^MS{ww9y}>9OBMw/o[ZHW{ $'g )Jr6ELV=Y +?-WܪcB{}:Ѧ6(<uOL q9DLd1$ŜiRőB WN1rUo6~yrTp@16ơk gHe䳏TTciBBB;67Cn[+s? XMH>{.~3C!̈lf V*g*KL51 Q605/4D;Ap8LmV6W W( & G`-Nh#'`LXڻ`$]NDIq1m8-P8<9P"6! z^XmՄӭzQqa9ՉL;yssچxr3Iq"v9ٙE.$Ģt5}7ril"~ykj=;w!묌geÐ"]43G~"zz% vn'"E4M÷HEBf3N&ʋ~ ,(N.\܆NyenECMԵnI}wT[V"-*+A&5&ɥxqgFQWU\,{erUzqdfeb֬Bѯ{‡\ֵ~kurՙ`#+ȳwƺ0=7soT\7<gkGHDsݫꆷ&v1u$8`8#X]"b͞=?ϱ3Uz!RN>.$C%VD~-"#Xk)wTRxP^VTDօjhin@-Db5 ̲$YY:55 1 /ŲT$^8yH""qxBcYoBdK&PT -.*2`F֒Z*wz*,}+nkVRm"$V@KOLjJ"t,Zz0u; +DeBB<)榆-ڄQy }񐿠L3+(>lFϽyEz$kjV@HkDӄ6roT"S?*+Mj[XAO Iu 5U()ļ ؈76~"s=}hwWio(}O=#?@SGK71,/ ;ih鄊yeE%Y ?' BwԤt(7{ځo݊!3'եsd?}NFvF2q!KU0YDzٴ %Y$DO_GUXBs8Gc53z#PG)q0ycP7] d9m""1My2 ֮k6=/Ea^<ǯG|-G#,,k)ۈ7Ҥ&mJFv%c`exsuwop`ݶm3-[GUNvǚ,1Xs%J ֊4ִdu:DXydAMq4ui#͓G~Ù3D.ꢩaXu>]M5{d ɬ;TlxXtuDyS`b޻efĹsɁezo@Y =N^.Fd^^ |U͑lrO͞9 cxi8M:(hFxZBVUp75ZxƥPǿކzptƹ7Cw͸݌܆+p xw;8ug}U_Xt=AxZ!!"xVbscM?l\Frj1Mf]F5aO8}w_u7ގrE]դCvfzݳE ]"l"O>~ L*{LyydUj!ce-GUSAEK 2byR}ۻ[aw{RxQ(4uҰs+qœw܀5ol$~ bU[~S[#+Jq=rPPZ _/dȒٙt7F0 p&'/:g<~jJ"a;cKQֿ 73hKV^`31suXڛBY25rZ[ϰ%IQ^Q˶,y9"RJd3e`ݲu6?h0~05,ip8M~.L.I<~uew(`}U5ZL. eYWQYV )ĕ>+*: <0߯~88h",YK?Z_ݩ=*4(EB5h.#Y;1cUtHbw)G#0$&&ظ6 CoAuQĞt#5f}p%BSЃɪcL5?+Z<"}{W޽(.ʁl)|C5+4VWɉ37Y ]5ɑ!%Ȋ U*R"]ӧC-H4Tߏ6ASIțY݆kɽ5)ֺË,A6u u1X*F&32%B.W4F͑v[KeXVF*ړ$_gͽhDq^&J7U``.^VTQ5=|fZZňe7ZJq[^{"+; Df&:Ydj+D6;FT E;A062FYA>۰ wyoW3MtU(NlAbѪkhJj*fڌ~K,XXjSW}@"p|uyRnoE]ܹ My55Bb.spFSϮ%1K5X‰u@djb>21,^# ܼ| Wa%eKe}BF/Y>__vNҢQOk. IR%CzXyGߋJƦ!+pnmDNFjJD Ǿ"$XpzAසGV.Cq1:zPSds@xBc('q=NecOˆTĎL>/ht{CTuujϘ۞?O%XT8G[on:ģ7ƂVN?r٭a= 쯨̀1%`0dٺF$yJ//"\1mj ")";!b)25J<-JN4ɽpl|^ VURZؠ(=܍@ȎU3#ϡegeKճKeO0ͻo}u>+sd['^P^Jr%҃%=XXc#*8)nЪBMd$'bڍ0 V-he}4 M\ad)&YJޔʚV5@+$U˯.F^vY߆h(-MCK]%dLq q+O%2_LS&f8{* sEzKniDnu02Ё)h#W;w@6†K~O*dJJʚPR!s\7߀G3ƺUUą#ʋEuc?skxB /7 UU~]e>(ǦQP,1֣:DyU0ŗ M1(/VqQϯu%ӮVWR.qEl@Aq1|<&$̆#P5wj(J3OXWRg֨kRɌz-xG^Ui/)X*dV(+PgY>1$x8ɆNTzhl t98Nӧ -xMn\&Ь/"7mP5EBb"t.d:ғb%7 S"Uf̞VA>o'G1FnBeLo?n?c/@K_L֗ >/dĄQ _0k2()Mr8-;ň Ɗ{6]Uɤbq~ܼp$kLu)ޮ޵$hUUp[s5`Pw]#de.OLLſM5PRUGUy>g*ps r!")jZdXBHdž74PN!f́%ŝU_#?5JpߞS,)Iƴ7Թxܴl%45PTP&z;OIokq3 !yōZ@.i9*2 ~`}AZ;[\{\튓&U 괵Ԣ&jߔz6VCQY]w1 %G#0Zq39 S}~7tNmz=FQ^b"áJIp gCOBnf&T L8{!SÔ,~-h ||'\N^@Ld$+pFL4{ Ykp&du'q?y3p8G`,!g\4[9-Um ?]aU]uoJeA, &!D Tܒx1G#0q` />0!y}n2d\*+VYHkZcu.eQ@0y8o>aO_٘Dj0v|@S5qU>^xrꅆ]Mn'R65 :ʬX,`%bfܬLXْAيuPllma e}s<w1*PV|jXnl* Wrs[n[dx?o(.*52ek'r]+V_bZBxix6={ YY+ /c[_̙AYl7[pܦEjN%`osz0*}JQ\ jػ qV[?>+RN'4/]‡`7n{O7mg0rAT6B/ͻpFF%@~ymArb <ٳ>r#P"XQ/T>S ^)D-ɓϿe%u(qŃރc,,e' pOfKQl]-m a5aύQRSQ &J@@0Pz^x UHa&V`)#%Wם'zf4\r)={>[Yi7x6ٰ/\X(π5ZT#n+*6EuoDF x̸UPs۝wwJʪJL@nm}L_aF?0C5%}+2G1sU +p8G#H*yMA*4D۸^4흧;y3htR}0%F֒"kUdHC|Vk;>+kA~y1nLq؟g"93;WxNogtf]WNW`廭x/ڳY~3r+oIeڪUSTPQׁ1QA͏nGrά(Y#C0}&J`<75)9#Z+l1O<[P ~njn38:Xdy =CVVFJb"dsQH87q'‰FaQa;dUIW{,X9_x=@ ,MVa*K̋DD X>dJݎ<&k7HxG#p:ؿ{xxvdt9HK! ĻLPxKn.E8EUe9+o_vVNZH_{<9ChAt{{]Y8xeA fo=D؏a+K '{bɚdF@ L$XYY P[G$$y:`ʾIM+ Uz..c.'N|.#ްnhrez52n[Tz wz^[&WZeM&d p8@AAA`/Qccp_pq÷sti'X% 05p3p+a Z(:!Xٙ\cv5=)!h̽$} 7ļyTe?mǾ]p 5.r!ֺ,jIX9Z:́3ݢt̹G0MEo,َb~`މ1X Xssue8[N__6[OW^$-HVW/9d;1Gkhj,xd%_thL$"hYP VqKhjj I&p8A PRPde {̂u",1\m|ա'А.@7Q'Lfg}S.]]n\Wߎܜv+;RAQY99򊖞Uykkshʏ@ht:~'țѪ^~ZA3x:{FX0y3 z$X=9@`׮HIϔ-N 9[d5WROKq|a?Z:FPUׂȢ,_Hލqx' Bc9+ɓʍ;kZ-ԋ;;NG-/쎀&нS#W~S`=k3Iٽo.bxb6T+j?k*JRŌ,Xi񄉝zk#YsUkJIq.GZIYHUX"%XYV5׃%y$:BF6c)Y`scfE0GGuCax }ϼ#YlYu*4)Qq!sSOAh/E}EP!'G\KInE2` G# pq4E<^9ͺ.OO*,|(Lyq@IDAT8XaܪNOo"KwzhkOO8_zG{;-4U$()L"`*4c>y/X~TCaq|2qvcl&WUa<iByCɋQERU) ~8/bc";m86ݕZYWUko"%״pI)&qSp[4D&MQ0q髪P^ZX@%1]y L.$X**ʈgGgIqs,H$}Ӫkr=.qiWLb2n o(s&,YuIhϘ;!bMOr!PU] FPha֌]o2p|AYn:/G]=w#y<G` d ^pFJǟ{yt찘dݹc <}(FxonBEy>ųx*--Dmm9k28z5G阫{6o3YKBiWw#X{ %_-`*5UXij}5W^xwqKim3M6TFϺu=?_Bgڄw }UV\,^55qoV=U&INnڄ7{gC jM W鷨Q.bꔎBEG%~6=z3/Tsp&&qdibe :j ŋApF ċBߎȊ;b57DTQ|μ} j4[ 1( u%UlOϊG#0w#{^*X0LOGt-ֽ9FY( }gw,.X(<#$FϏ bіj!0 ++sDtj»vT崱 Tj"py5W/cL}iI!CC90qBym%˪$5{iTV6R"=-U5`m+q*j\Cˡ~o&-zdo'_h-9xjmMH师Qh.E%J[IT3`e;VJBp;'qL*gI0'*RxT֦a쁫dą#g:`el?u}i8:7&5TW>C =3aa2O`!}}<.rVRՀ>ر?u-Tar58yz 5PSt/>e>RjPI EZn~8,Z쪄zw+'alԵhTu 2HNKT7wһVK HLL* V?6O:D2q]k_="/̔$(is w_IܾgΆh`ؾg4 p\K" 3;\17@y\c=)~zX4DfBd1ŵx(4U@v@0{x Iށ&DŽY%w۴h6豜pzCqqVq8À@#=5_Ƙ5 *G 焞L6F^u+c$kqnܦV33MWA3;c:_$#;3 I?:KIJ;88CYVkIIqvr8B-`颅RD+'Y6#X{}|{8)sq2Uede0psz GvCf(΅Ο ÙW'6OO?>.RnNJ[V~Ale^n'Wê{E046CSbxݯThkizSPRp5h.׀uՆ!Y;Vpj`UG#00u{w?(&~W/#5%\4ۏ+b)Ul] ,U݉ 7gE76o |-[qR`mgx9[ۍo}-̠8|G\m[w`=mNJIt\nyG#L<q8D<Udu2x7ʈ6:BO V~Ԃ1TWFCy&LZocL{M- 9H8}PE suM`pm?aN66=mz,̐|::t|oowԨGc`s+RHc;E!3V61ۖYё6QNJ .5UP1{#Ǟqbmayw!gdy+Npd4"N)/إ%ńS1\&%)_KoX˥eFuG 1<  O6 ,eVX`2)*fοo r>R05AP7qAVz ,3Ko\;_FFjj0{ܵy,~@uUD"t#p=d!G#0O` mE+ ҡ3Ɋν('`nݽܱ\t@v03Zl?F2QS\GM(;U"]AYp0.n£|/"ڈ|t)!n>ӰEo$&`o.I X& I/BuM9s 6qFA^N!5M]hji#J &&zZ@L@]M54t[elyŮu?G-fkV6j(h iLMfTHGx ϟ?s8C@CS~ՠBi sXgǰ404wkbbn#ϵv7]glmЕWz"Yma dVl*ja!~liUDPσb KEn 3KhҚ+ :hܴr'wh G#L,E&' 24 >G`"nÔ)2j{*K``՝ۿeK-4[:֙yǾ]:v\dG%k^< x" # մtfwf 5"hjJ`ek3f;VG͜9_}+o)4PR,ɏ^s(@MU#2:KЦ\[$[S^ZtZMT KssI PZ6Z ʚhk yHʂ~EsD. ƁgDn:*/F`QĄ@CUmD;>/'ʐx"YwY曯QT\ww13tFDA`]p*bk$RЂ =5vUokkBϞ@m}EG&֨EcC=T4ĔZSĆ.z('p8B`dV'f|68Elu`͋G xsc>= bevK'gW:8a%ydh`~%SY+q8 4NP7sGEM , T%4{fY]==.n_-83Ү\&W9J#ZeInz*XMy?*~Iŵ+yaNPIqy. }=DFn|bff7o ,X}gH֯nE_~Nc… KqϨ+EScuTtF֢-xaW& $x7'G#ȏ@U%T^0Yr)d&׽ubݛâ)}pU2Ȉa?/ߩ:.l!Xu*x{J1q_B󈌺&zOZ̜\|G"X7Hngt:5Η#0`@7e v>[O 1(KV溂[Gq8Å`2c}vK* FVdq׳ūTqt)6RVUEȁ #3/o' 52X7ٹX;`:%RI%ݰ\Ђ\rb6gtX3qA--WX飦TmзSR7G>_H&,%+w)mQ]W.nMiY=Κ\Y)J:K߻spp\4sMuTҟS!: QW1oAO4|iKqݲ[5wûW,j&F"k!,dSP}jX IN%5t="TSզTu.DÇ&hQsgOE N ,9cRT*הydQr~1k2G*3ߩڻ n.{XR6h'Q0$ħBNB4%W[ߏb*OJseIt e&KU-DlIYisP4PRRԈ< (-{qb^ J[[W1sz1NJ=W%*~|榖nF+ߕ$4qkrV !g zo_46` X}\OD\Bpe=sbk[w`ʴk) #+_~AE[Fii=Q<]N 'ړGjla7z̅uɫ !sl׽fz~KG|| m$#+# #`LKeWw-|2fCPƖ~ƾ=1k/$Á[AI@su"|e焱NkWcKO h" *6xWZ=@r:zpqhM1w⹔ΐMrLlhoYK3:&/uxٚuuMr5> #CGT X;odKX|xIM!^+o6+dualツVGޭq;j*L5Sse&rЦm9f }s8BGSϾf"HLml_X"Zh+,u#⏣>VE9mVVעf۬ɬCOBaz#dLxCw!6>qzl0'oG>U}Upglx G#w#,,nQ>4zQs6|^/kO5[>ۄi=o}e}e2+@{p!,?Y&zX|u*}LvwqW` b^%u!̉,*1r7 oCYw/e7{G'hkjCM7|ePi6a*vV߮RDkTDRe?u^# \Plh8v~ eWaIqw5Dp9.ZثY/' nn.W]Ym JڼDǢR<ف%1PԅĮ_b .Lb.G#p8qÏx䱇qw>MG~/hUwJo0\v;2ru8ֆB+ iB\+@VND1zմiBeYjĠp7 ֽ1nV6QFjkμG`!Ī[/54UϤ G#p8C@G*rI\NI(>2 `ͯ(И/l ʥt&XY+FD&0,%%¬LeJfb)Xld\(I"W ^# ;;k \@:74FSSs`jf*Aͧ@sKt[P_S&aLPY002C]<I[Zڹ?ڌ MI$l5CW:(,ɊTb\M?9UҬףRb|x{+Yu;ܑkGO2CT`{nXf8Hr>s LL(kxEeky4e'5,F> pG]U5*[ʒL4S@uL ,,))tȶ<ꠇRdŞS5:[ZX4S}=#1pvHgr9ZJh:\BEQ̦O%aa!ojvhѣѱ+`$.c_2N~HK U$YMe .p EU!I G#4y:%& &z;WM- 0J 0œ͜b[>B%`Y[YI z(4`ۖ M "6X?eSkeZ82"wVE*Z{]x/ #dL!NquL}|0Ƀ{ {+O#MJHV.#/wBGGR-Fv{Rg#?a7G!>m gC Y|;By\LJGEG^n.,%={riPY[ 'gOD ؋p"eEy00$MJ7?cw.wl_@ RԵPR\Np[m>@ue#70駝_~',3Y`eRQ궵5DF>}E|/BkvqCm5/DG (j yFFF-k5p٩У ?/Xzxbkh% xbF~1ΑES'M]jj21mZp!!!XzuGvmPGI/8u͍5Ґ(x|l+ foqdpm@K :6:űK G ai۶@pP =zmgk ;Ϊnǂ q۠k`*NC@xe9XtJU55iCΘ+>yFu)|/)\[( X-I}xTg;d"w7x H)*ۖ.vn]~Bmۭ"HMd?ߝN <7ΕOν3=AVw,92LL ]=0Q<&EjjꂗDiߎ n|F۷Di05&碁[ 9K,(3_M<\ops;Y%w! gLGe~2s1mF0,lQWXOށ L: :*8wg[,bkm]v9,()-F_֮dP*)LDA~6VCֹy˃c7jGЌpr+tt QVVoFz `)`eן9~ =V޳S."PQcTC>w5gw'h5jGKH GΝr5  XIj2Y45B惻& lMY/NW?t(;5?={`y@ Ԃ@@ lm`*[(Iks:B &#_ʒRК~1~+$_9 R*+-w=߼JX{p׍OEAR-h>SJ̬Frmu#yϗz[u  : Z5xp yY4NF@֌{!T)ܿd%(Zǁ߮Y/ջBwz@+X_}}t^E x6l؀BL 򆝵=T(pO2@,V ;_9|k")6:׬?aTHIǹn45!l5aca'ϣ QYA83R[h(&%MQK Jˠ!O̶J$+7 5E8 yɸw+zopB5ba|mV]ƥ톼eMx3 $,6~|YQ. A4Eqf,MIP҇¡ڻ]ˊrq* 5CO0$Jr<\`> -(+.-MI,"-+)x&,,,->mQt_,Kς <b:L}ZmRf~X4/- U%:s~pH.h?5Eca%HB qԵ$=+CHhZ 6ZA7iO455jd6= Z׍p&vtCZK:L!H{k={Dak}U9iz@ RwwW Rl~Ǟx/# 'N]ew\Ƥʥρa>4һכ8جqQ9U`a6! Hѝ1w&! d7|l$i>Ij7 %;(U(`zw1֥Za~y#R30*m54#_W*8qD$[} 9p6z RD~&C_؈#'3kbB?FPN<|'{X6FQU%ʚNyq(Ix-MzKbL{S 2R{VKy@`B}mCw{.R/ b)Ĉ~M ce\9Vsal ^fP_LOGHcn>`1z[Wa~Ν!0jDz]=N a]C3LnYʬ_4R 7"%^yz=f?cw|i+AffdϷi02!`]Ul}?𛵘l8}:IvTêUQ_$7 `UMO#=%s*g$}'9о$e97j]G߃zwstww932 |Z(LnSMcI$4Ķ9|x=pG{@D`q@xD#ñf]褱cu ޾uNm Ѐ v%0vbc ͊' E"BVUb h$aAAla*x `e˵L.oNpǻw2 mEò '͛ b,`G9Аm[\wdK3:%ba=LN1eikhWdw~=0q<5FC3X}۾0K|Ӈ@ma:DzFDyqT$>}h+Pt+WcAKw'{1sk ÿ_D [*KTW7=Ca=TfpVKVv#ˠeJhr뚰1oNyQRe+Gv D"!kL =Dr9ȕɱYJФr\O2E2U t Tvd;M0qGDj6>+X:C^SlQ~OGvϚaCyTGco"]?Wd$km}hZAjm8+] ЦABx9nS|(N }շ`*D^< +{iX[ 6 1t7}>^x+`CТm9Kh' .' TR Wm8H?g.DV":{7İ '{Î킌ڸ`(=}$8l\}l'/_m_m|k['|(FvZ4w)eLm].Ƀt$&+ˇ\Yy:Gj_9@] asއFLA~n<NI"Iiwo_/6cr 6 UMJ% 5RH39:)1 Ot5#)6Iq wt;ܱc;˳ r ^v+k/Gعcq9K)i&W[F[m9bRdp M/&B5h{ N.(+- 'ҭ ;g;?|],]_.䩗Gb֬y:d"'TSW a{bb jESm%K(h'deuV!n meFUxMq=CY˖uy``g+$Ęe K(ʸr^ )H{>GD[g@ZIXbN񟆤S[Hfvb*XRrR+[{6])L(04UMF 9AsO$G˗ՂPnjrjWPQV],,;(g+/1GgOj+ut_8@fjc PC@ 4{\)W:tήWwr eгseEwфhfdA@v5 =RM*&F ykр1[yA:.KC ` 9a>SGW{ TƘ.@g셦H DWA2c }l`[gQ`+޺{pjV>Y7N=0%pxux?Gy(=p *5 a&5(9qT:X޽*MUR+c*ٷ{2_N/1wֺ ފjZj\i\?qH44g  *c B wv jJWp#GXtYÖ-[8uܹCm$o~Dzv~t*`x 5- /\sJ<:in%PE%P.SNƹqKl通 ,Yr:ox` `QQRMXb 'eV$1 a0nވ hCKU$ut! *5!< Rp=xn100,A/s/嘬xij,*3#߿TԉfACaZ+Qi_5HGQ68z>T<'v Ʈʨ@% OլAw{ȒPDy?ʋ_Ѐ*Tv3ZPՍbTQ'[j9 %()/~;3Y0$.C=(H;_dJ7"YK Hi8}`44)oOA\6#J,Ng'ӧQXc "q100sAyA]&ԀW =`U٠+Îm۱{w(ɸDbڊbhk^~_6p K5 :=JSYTv1036X v(*,& %P% (1/89a@ʻ8UVj:76cAIb)KGNIj8&64if=_ȷ@֛`m-Ek]u k%U}Vv c+]MS_Qc `U_teRM?kpuqR;i=աo@;i7h:`7o-@m}]WNhh{*{y +-]&MODmu tئovc= *'aVgj-='Fjzq((GII JilFj)1E"~)z^75 \җ*ߞ.fd@UUe> `^=0½<J' ߠ갡 P Hj\V )^^z\;u $3%X3pIG+?cӫ#`u91oCB Iˑؽ'kW==}b/# x8q$k+@6?TenRb ;Kߐs pp6a]8e3=,f`B -f5SEjf!FK)o$N C.› l|fb}'T;؜X˅hVSAgm=ϝC~2 gCIT ?'S$$UK mfHkAtVP!Ё'#R`MyV[QZӎKgoB:@"#@Z}{4ukņF5a;ݦ3NEɑ0555#0IL߄D󖮆3SŇoaѲjLWLwGqJ$^~QQ a9VB+m fUR#Y'<6ϡ4/A~d]>l0gcc]PNI89@?2pfyho%_(Cϟ®_~Bb _>{vvYkH('Fuy WKbWD_C7Z+Hstk76Fk+W//wb[אǛҎ$M=pCnP+fx=< ?][VMdPkFt2σY'؃7聘H*|El4}\W{Tn@IDATjjf.O h'h|?JizMi.XS X)*QTbT k1+-&&`Tp*Y,-pU/Rbxe8v/ADnZw") HUIʊ=[bϸKYU^Bb9$ Sf&xghg6aǹkڛ(o|ICp1őxC@:Dhښ(Iπ5IWT"#=rIi<ΜfbkAaIeH˯DI*8XL#|p=DptM$^W)159E5 J`߉vY svmSH^ k#ockW|ݗhE+ `cڍ+ #b #[M=LJi>~$!<^6K `Uֿ|?/ArT vYzTc$;[we%rW^U3g-itT!*yo|CMQ@V.[䑃XKtC7I^[8<qv+Oګ⸜f'XF}Ck}1 pð"񰃿ÂC9Pzm4ǩ2AW{"w/.{!mLP\L/ĪUt\JsV4` @j*0ݖ+},X *aL7 ekh[n3̳ <\>7!"֭7xȡphohnM]OLv]^/={=LJ}&&ܢtK0{eʧ!Tqc׻wCJR:+X=7KjP,Bt\ V9'cޮ^&˄[9bH[EZ#ܞAӯJ oiNJ&Cbn d :(ǫ/-ԹيHȉÙ7?o$+ &*̛j6 ' M2zM!ܫew#I]p6WX Ye-1KmHNɇrʔdN]*dQQUC& hC'~.hd9p8}*DgNG CRrG_epBYi!4UI6QߣN+X Y;#pϽAS[ g+C%ޗ{|8ҍx@cL KKL/5ϽBU'l>k<.{m3;o6" byu!!- er9Ak# {C\{i ~XqIУ~ihPзwߩtHΞMXeUP /K0 ]Zf4]Kmu@gZ()*9ExSXմ=\A7YӜ9yi 늩hb*A)_TEt5,MNy1Roa N;·cHJWCqYo]TN۾ S:zLؘHJm4`e7!@`1 mVƁfXQn#=A&gQ>{>Hx;Z\ /,ǯ$onsh4qi!3%ul|VZI^d Z`goFp V @ͧ85MBrT+KZJuuZb&D\Vvhon{Z/vG"dfÍX|}|tb`gLFl=KȅC}W5:gN]=F4I4Y54K>^򕳰vAAY%d*16 b X܅9s=' 3j.MԔTTQ1پ}? 3.Dա l ,S@JUo7`A߿gNPfgB"1\953-91j(N=k{> nx^ߌ^>b/Z&\+$AzɼݟL,e,VyqȚ}lO?`000 ^S|<:-#!6+̸TR 9v,kui1hyET)!fFc0_Ra뱘<\Ǯ(]aFjq,}hz{m?Qbђ:z7皮NA갠;CJQ^_:diO5kZ%\~ɮmbM\wKٴG\V>Jeu03z:\%4Fc- w>LaVv =p=)>YG1|Uy. O an$9ǭYaY0s@j*Cd!xOrn \e˱C8ul/N@'yVUM6`U89\pgUWOs 'Pf(ӣm K+[Y *e+3{gQ2k-=ظSNE+b~΄,(킵t|0j#]kv6ž;(TrwZW=?!O$_Fx#`&S3I=U?P6ZF-xOC$D쵶 jGjۻX]Je#h< X1A$p5Ui>R x$"6Rm&^u֡ [ Y}#)NHJJsboJdXBKOj!Oe;@ lWNFKAM--(--A zMiZZ2ZaKd `eNaױq Ϗ1bYY` T1u|1_6Q_LRmmk h҇%l @A}'ΝGXy  duvFъHs#Xd)]SmD:#|sO jp^Ԗ(X{ Qӆ-ă9g xlj"p sg xGG\9=z$U0û.GnJ<̉ѫ'S|\Yby\T={`~K8' Ց7 `eNhp)6V1 _/թX h ޤ puWQS]By+Xg"9,\)ZÍĒlnjEܶSq'SSNՔ+ G/Ul{،> <ȟ!gꚊ D&^sZHVj `jMg;|+w"od޵ }wڎ4J=Jl\> 8" kޚ{sUڿÆ`~SQZ!;q&)+!%Z1ef&EYA&y!xc(9;~uBʷw/յ_Fmpp@WH]l9 0s wvunUY9 (|K~S{98yp7ܼ{ XO- S * `1Mp6@aq1"ȈAny=C;הίR]sb.mKqpu&C+׭w`ie Z[9ɉ؏) @dluЌS@HTKA hsm-[ZQ,:؄46$3N,U p9'Uxo!hTL1K-$7 z~6ddb'RJAmtBrA1S\5e+1?-%bDtT(W3j* 1^qX`ݢ R1d9P9TeU$;n8 %19Y¼=veQv=fkK(!yk g^-wI,D a$ߛ P#kDuiH2 @0+nXEf-| j<_A|{c +Digs%z4q'r2+MHhX#hɉs VM`-IL+Mt5CWU6z utӏCi_X[hIB ػ}@ ypn-FZLX]FH4 ގ'Jh^-M[Wxh($"h@ԍI8&>$Mԅj u@t.Ą !ǎ\$)=eXr= \?q|[QVOҹa$[ZZ{կ/ec_95pKW>W%Ij1l톆{SyyH/E{S=ISbp)w '->#TJ.zyro^\WSc~+`h7u3,_;#"/3jh#QVDWdXȝ&T:b|r`U7ZUy`sO")3NiDp:4*%lro y,<:г^,.hՒJ[ |^di=zXk{%)VV2xH>S3hU\Mʂb16Sv[؄ T壩bP#ZGwr ԡD9iv-_koR\B㩄Ig*MMKXg`eׅG\ds{E%T3z+OeDy=]ȋUkLͭPЊHDJ{vcƜcfuQC~I|(,twv"! "sqȥ]գW+5ƅ"X9ylrϺ7YYQm{z:/@*cY9Iؿᙇfo)nN9Wtw0O섋#\0M>4.4okiwJԋ1Гި".b䪢bUo%1=N=SUXrW0N CJϭڪ0CSc3j!rVwI(m3Bm8$aC]OYl `5^$&S8N4cHVe=wBWk< Ϥ`1g΅ `Bd< pX:C#:b[s7C2vqp l Ϊ<!JwM?bLư(cbqf XSԒ )o9~+kG{=Y{z#/Wy=Ipr3X\7:meT˪LkZZ)cYBFʣ(! 1hoc[^L6X hvYM韩 ɀ^xeN;p96@h#f.DbYΡ5+)$|oq 33vз {w|5a+:1Gp2a|$f/YsdexMXt#LMɀ,JKI߶#!/υX,yNCNv.*̞7/.TdΉ9 :kC7&` )1D*cXe obUBXdlb%zy˛Z,6I/UVW#+- GK-_gJ5;D<6u#be #+ .+ C|1r*p8iг6$zcfh$VN^;#: yi2%0BGU@@׻~ 0h!J4Hjx\+nqi "CT)m&[[M(  0n/" $6Ν'cwJ}vqRS)3ѨBu̝3``(Ō=ʖ8N\Uz0' ތk7f+[z3X{_\/ YϴrG䁇MA8z|ԆQ Xn\sa~GrR>Ӡ|o Ky=٢MV뀦rr•14i[(R5#G)W9챆zdL {8 |>W>+|K̹1&a .p'x޻k7 YyE*:ںhoof`=w ܊%Cp=|Y\h!"#<<iE 5vfp;x#6%ǃϽ\K̵!''?Xt5%< |ݧ!;zx:421! `}mqWAA.ڢTAǘףvmzAUefA[~ <6Wf.ߌPtP` 4˯{{'(85%:IH  BhJh,劲wX+)NSm% Ukx"oD{:Got53<:е_ 3Yrwί/*oze·w~7g9vjs겟(j`@GֺN@NT>/[Tσ}={fx1Y8x!݆D8vyQTռ:\VZ߶fbآA~C)g gu;sz1ݞVB\^^$/K,99"@|2p`sXXY\y:(LBZl "I6(diOcisuNhi+o68cVT$#/_yM90oJ?MA/@E!7񯃋+Abd Q[Kړ4%bϞw[w[@ 㸴;\{kr;N*+ybf/ʽԜ> nj S=`u<9и`vȻk =* _U=\ #=$PN৶=s&.*,UamЎA/6DUVU2Bۊag#NFBWGfK/Hl(&J(ܭrb@<'9Q uRV;u~A>魣gHW;ZP%n\ yY4Q!%,!^|O < \.mF]}N Ea!zG#RBOlPU OvԔd|\gU[WLK8ZKTΚ{"`c*f^|:g%#]!}fwX `(+'oKJ5))|_Hڴ~ o>sN1b|i Jc*;{`r{*W=odo dM"Պ"R7<Ko5)UÐTix}=`NWkJ|֧u|.BfB80g=(HICasJ)TO've;^bۮ`ssLB1̬>û/t>T6 eY4+"s9 eLסb= ,d;3 XmA7a+`fR7zةB 6\0H[szpbt_=A.w=p# @ I?zx`fzXJȋS [Gw0u(c,֧~zX1? aee5T1~yv<4$` @jaUO5a/pzQʖQ.S he Vr=K x [k򡍈<˸B7f„̘usۺ4k:+,]`A90-B_~Уla&GtZX[XȯlĒ+QNҪ’ǟݻ(("^Osb>0tXEpGh_2ƷИt!w݋#o`\Q u:SY?{W_ű~Oݕ$hbJiKz_jTJK BpC ;mww98n 2khU,`=K8훡qrZPВXUf?uI,MmMhʃ>nyFS ϿR*/"&],"/Z U~U15ǰX|iq툌ݿcyEr#ܧ.udJ [b\1 =2.*RVR7}>/W]]2c_*`#ظqnCK6N7g-f֯d%x:VTV˼ $!()kX Ң4V `5vkkjC& Xxv;;ȞkQ,*'ɬ>yLg{&-Av$+m;ovd]Y(oeee07;~>+ 茚hNC ࣕBZ@6v hd ;liqyj9ڧY;[`- H+-U`XFYaabaibu0;p23,]VݔQ_;'MĖl534+PutuGhiN^YxL8Ʈw͒齲$AWCj*J1c 2GM6~YΗUOAd[N<,~M+g `nfҥIյ1z]0 {.X$`f`~ KU +8s&u=]vľ'ׄ|Շ*rݛDyRnbyX1vb_AV`%*ۖƒ$INn(>?zh)˃Zί>2p 1WqԗXnvR-xè PH@[K٥8}6|Al?\f ωdysD,X1@6u?Mpw\z)硤Ny%%x{ǟa0Im~$%ܢ#OJΪ( 6)% Y[KK~>NPk hԻNP[*gm# 6AZL_nd {L9T[&詷 !1攐ln̦#LHL>|]bϱX{n²[o1)N9ݫ5@AE J*n;?݄d,!hYj11t \鞍O7RmgoV^j̋:-.G`مXe(/9Bke{ܺ zfs1f#NJcurnv`#4cV֘1g-`[rgdI6e4ϼly>TׇǤ@53F?wt'jmv[?ԃC"Tx%@7ƻQXV#@+;P?1V+0qȋ>g݂E8hۏ=0qFCE!( (0_'b*c]߼x/[Цa$zu$ h5UmQP^OZ8de4Z8Ш+F=C{PMQ)qps"+WNF 4z&$ $9]V'%>)(+aG:\eN~"8\TLyh T%8Fں ks^-ptCMi:UdrGߴt9xDhL>Nl2]72XE}Z7Wq"5$(%c,7YnK؊~TisV,=!~[&z5T]LVqžhcV V$?Pq GW*gNm=A֡XM^Fnl- ~v.WbuP؃x=ءHLƴX47@lo*K1Kܐ+\P2v$ehg xĤbO1,GO0)rC'*ssycqb͚'Ц WQVk$ME?~)|ug`磼Nhxhl((@```u/X¶X;1:36NfIݺzfI9%XJ1L76qJcc'EJuF< UX,vh(k.XƆF4@;Fl f@@IDAT틌Xr`v0NϫٶeutȂX u֪NUd0$mR^-ܐp|/<l0N^;,aK:q@hL2y h[jJ6טqHNM@ S M6ŸNSNXmmڰhuE0/?(#QPI՞44u`h$سYx/ Gߵ5U WKSvE]fbJiMRze"nJ7v~i_3ۆu'Ө"3Ĉ1c%2eLK ̂F7nGv6b,S!UgX|.Kݼa_K[**7\(b_JOrB语r 4 j.Or ]oft2C# gOY]&;] vm&4@c_6o2"̚}!AO- nQ:'d&rXZ_͇. ;3AAA/ ÿ|U.K'fá!t66 5`onOo=ejۈ%sw+smWSioɓ%3!S[#z!nkT2d*}r -pI,PUQ7xjId-%!Bšš_Eo(L&}u0Ymo\Ub-.JCXV;tL6CQIQ- ej0& *6S %nϼE a˖%w´ QX\ ?ƴ32=Nݻ :Ty␯PYu)5~PqǪdg$_TM,,Lɞ: ğ&OgYF`ZDHdbYAPD"9&\_L!4!2* ^=JϦ;s/$20f=b@.q4ڊzʲ*R>""+ac 1\=(eIVR!aM&,œz`~sS=%~TwYRBwЪX̛)~ΰLtiA&&.ʭy%8@qP1"5q) [afj.>*CAFUQ jK>c6c4)1yb]rj `HXC7:VMYXeF@H'ŌÈ16k;1H.:f,ԉoa3(Ǎ7ߌ¬T8hG*s)},j,ͬSkjAqVHEJ_N9k܇ּ$ʱ*vQ6ׁ" 9ܫ `ϿȯA8]`RTG7w-pXeC71LX&HJLW -"YX^o|9saō+em9 LК톋+Q 5-?oD HZ2ٝ'aWDT-YskG01Fm6TcLEŢ<^pg ߱2YXFzH/b:L6Mg'XG:յcV j`I.[D%0hPS.F/2jYS 5Uz&Cw٪C;Mkƺ,r={;u˷/.)|2raӏ,k.+F̱#Kʏ- Xj̤w5&ZXQ"RNzꙣ`#3L9r1mej˥Ә:"Џ1jAaA+ދ3m]3Y8m0a"#0TO*zR_u {,,,ׇUnKl:-!1m~w 1in_ܻz1v8u-|@tT 7\8U%0UN=SL:_>{A`:^0ecmI9ڪRs'L(7 ޓf99uH1bl`G'g\7o~g3*IMSWZl%cOIuUejbwZ`XyL 7-A4Ai_EQREZ cE2-+nZy3(TW vۘNK&&|֑Y_Đ$a(.73Y/X`cgǎ[%.l5 o/ ?Dei҄ p2TD{m < 뒴5U;Jėfmyo|eټW{0 }KCui*45)[#DÕ>y=)YwAmϘRD=bO};#JoʶgUWv~Z<2;g1?L0*&XB@3)a{lrvt2c@5כk($+ vU 0zÝM>$5/3/ 5:P)PP8Gi k 457CGS|ɱ6?$4!36 041\\#zhljh(}%\,*JcNt  b I_!Wۗ8_*'#N|] h%Y9h:RE2|BfPIn.6 30w,4_w믇1JeHMɰX<2aZ K/@NV,ZJ2N!mjw1՜=:^2)oԚkmh[Dll;eի`:e >'`8_~y~-KMIAM%EV87s8j=8}܅LJ@gԠ =!!dېѮ `1#EHŦ[=X{C y}{̙8t83CQY- ]P-;2԰):4^fJwNAuF,ȚKnB=rOq +zo`s\TS֦za0m&)[yq,F \fE{`v773%':'JM)%3w*%*EyYjAzesl{mXx!޷}CC{;4$WAd=~x7Cims&˂XɉàGL}|Z\;EUw-0b,ĸ]0yC: (n{{1cþ'\zM>u>ʺH)Uϼ+@K=wgxmr*x ؉3i+16n*/܄h}G*Լ`/eF{$Z; _~Ĕ3nes^!e_9W?[}c`|` n}nFg_|?SLfۘtǹF'TtrBI@ z%}sqx Ux6G%ǥQՆ9d|1c:B} q~ݧCw *?VԹNSf ʋ ``b!+lP:g$TIn. `0 [~FaH.yG۩ƙD%sLKܵ~֒ˤ4X7qDT/{5 )1CtX0ՌSOS&ڵӮ'pG7sv?R70R3E K8̻-θp/>XY[ub[OG'UӎLёf.X\J4&K]0=CZtX(,βaZ>O , s'ٝ2LKgAvӳ7m4t(WH'J:IP|}=߾탳HǢ#qDzqͫ2Ⱥ`vD0X]|&I(5k4@%ţ[ ӗvV) ۪l]G!++_- Ęv!6\U{alӿgj5%jy-%J1P;O|Rb[o^y{N>cH#>X`]һXr áC"حq>dI83h+Y1\@@504_}G[S8#)1X SS4Ty9o?:77 ,̅JC)uЧ?&j;i5XUb1 _p|}{GlDfr4ȊH7 ҘQǶn[ SayV9 \qD/Gb\ŦGv`W ރӌ;(d7 S'!""NXJZ${>9 bPωG}.%M:lcv":6͡5t/Him ޔ*AcH=CvHo}#w޴^vz{5UACba::?U0iDZ 4UUhh̆JƆAbp3i?';!*;=yPZIplo]b)CRSP\oWoTUddɁaYxx#ccGdx$<8xt;~=s708`֫E(ñ48QvN]h!*5=` &{O4/sğٖИ X]&7=HwRCaq/U8.ݲQNkdC<3yk(ǐ7\_/ݺAbTmh1Ӱ]sJ]4Кa.`ޔ[wl.򩓩&}?ʪ꫼W PdXڞv퐳 Ωo"X1#JSWf߂/,]al <F$'dű]?~-Y_YQT^+$Ğ)I R Zvn*|H럚/ ,ʎ6Xy#4ƭ2dmEFa yɴkb̤GY]'L1kTD({ \=XF ;l?t6?c.&O<vdRB:5BSմK%!G73Ε.KHӍ){[X<.cF{I~ ^C3a$cghObEX4n3Wv6M@b5K*=I{tCUImǎc΍tH ^ނŋϙ L*CXsXqaۡٶuV]U{l蚠\--PrOWX`p---tO6Ey_B kWޅ 6"t Cy[`灖|a'Gock ҂,D kg5?d#S7ߦsqhjk‚|::]J7Q>eE8%eUuSgdŖsS1`@*Lf/QTR`Rc&TojtO?.=|py1w魜 0BZ缹1h(r#4Nl{\ rMY !zPUYLמDu#x veYj89R|5APimרjI:Bk{ |T0$!=0rsP}fD;C`6.Vnk`,o '+#pr3>7U85=DD!>6)LGlN"=72ܸ}[-#Ϡ~}۝oc9qo@sWs,23;@ LpW5 #3FΛ"YE:S'(CORcQP\Ƹ>H?|XXcћr2'{!:>nE hٸ('MȫNstO=l7d$'ȶ` q@VY%aA8%Fz>p\2i\fԩH7/DY~"Ф +s6~gkN'p"0t0iRv jʅ9ָ{Mcm9k:"mS,+GOj+Xٻb]JZ:SQwJEE6&&QB{MQ׬'+=ury*!ᖇk; aukEldF`'kK[BF.LXǔcjI(`}q ~T *-ذ;~hSjy31)p !)b"p}mBf=9Vi.5wuλ ,^^0WV$X*jW~"y>{y!~+BNiTP3V[iq}.^bl,Z]]߾w ұݻ!0`#'yM:~#7Čr _$Q>|ʭ[rK]E'zIglW453󷥄rtHQy+dL>sYW-pQ(/-T ey8NO7|.bI9 6CZ;#t"ݸ tBWUSr%7K5U#Pw賓,!bm= *$J+INuײg;k+ -a;BiT.2N2?#7WuHD:W2el{tV:NniL=_\?"]oұ B)N,+e 5Fo9W'>D :"I)wcXM:$U3[Y}\zʪdڟs}wy:J7q6~f5w/ߢ{`%B_$K>oV_)mw7oFu+zӿAց>SO<6$_CI.j1KrRyr -XB(jhBWӈ?G&J.22sjn]3X_C[d0g+UGoq.Э_Y#O^eߎȚ͘Hĭ*r5nppr@mm+ʊ*qPՃ3N5kfM?߉02ATX'MGn,N;BU$˳v셽#wA [B05H![*yo<NDD'/c־@Vq4ZK:IHH >7g<_+rLN/7$pzyذ TSadcs{>xtU T1~xi{Wpo~mg-ZTn9F٘ ,j@3܇>gZQ0>2 Qah(HE~A qg7(Q0Fpd<QnkRzPW@)>ZO(1[) c2Ң\yٔ^uv*_F[m1 :5RK.ﶎ^GlǞCۄrMv&-~|\PWQ̸,Xzbx&ģqir;ް J*Yj)E{]ubuȉ(CƳuN~ݸg9!^r#u#,8XjZWk[c";)gyυ_C0N|g=)k3Qغy^~s7?HV;W%iYTТi_,Z2w; yY8ܽ}%Q^>z2 !@AQCZ!]w2[ =9(߯u.?H@rJrou7z'@' <8:tT}%tzt P]>$Wu[Z@Z'yŸp<ca'v:Tvff2Z[k 4a,H/*1S/ kFHe2;[;>0eCI{Ƽ[4>)K:L3зva<=l#YOU#0U\u7Z^Dl4TÚa,5б6ʊp& *(&Cک4ᕪ?pƸ``D$W#<"E98߇twÍ7,C=|<گ:, +uLM+J ,L ێIKGyr \+h.KC}A470n o'--CJIqq73[O?ӧLCzq  : wO|ר˰bL|RIG#kꘫvM-ph Gw(Ø٥h&ftT`,Bjr<4PQ-RTT(+cVxxcQUU}N IaMƤ,.ʥi,Y1LbD+J%5-) OR*ҿsiIngbu勆xu(ll+/cV!Kmu|yPXA8s̬4ܶr1e@mN3.`1qޢ eׅ5m;<8AXv G.vl `lFϴL: Ye{'moߡYRQd˳cчdҡ)7رc|VuqĬ7EF3GbU=D]H!x;ʤv[2HIuyhD ǷXPdAZ9c'֒{g!IO;@CO^* \ʔ VxLju2 vu)-E{n;XJ`}DZPY pVJJge3J99RUs0~J@_U_Lv޿*>r/Gs sJ_π[.JsgmIz/-"UT5zV b==st353j8Isc;_k] [D͑2[@AW` cɒaky]P|z$~nq:\_1^̫peN;tH&9}K{uX@%௽u: /Z@ΩuE;ͥq"6%hiڃ{|o86Kvu^ev6 lPd &QūOQ&|n6k*B*$i@u4t?5 a`M}M(\shux-C4KPVU )9i Mՠ͈HGZ,ԊP8g|t1&p5A~vT| Ǯk lVݶӞ!gO++ a M^:$ܸr)~,[BΊY@\"o?L~᪒֑Y/7ZW*N(̓'/^0zs&kuPh1wBEIl[ *]^Z&-.RRcNE9=R3p@^N.n[u'&O9Hdi;g7qmdX>-KXyoeKutW^V{QE'w;5ιͲ`gg׵X爓'o0lj,F1EM,g$<+ | yUƵ]ݫJA[4 `u9ѯmgfzJp=7/25L8YyCÎMt*٨ 7nx)P]n)060"h<7@{=(#HX"LP\[}Uƥ„1RQG)0UJMDw hYC lLgJӑ{b抻3(lRRtЭH5λeFZxlXY%Jn݇t3 k(qPmP~M9N$# EDGyKf}t 2ULyIS1F>N݂ܔX5Tc̄9Xl W1ǥB7!9 hL6VJ)uk5fz?CFy **,Vz|Nt, U6}&`k7`Ϻm#5cS/~qGw+g!+u;&90&\0߯V,9!-i̓"U$OMMG y[@n"HZҺ(UM OO"ZLTFBqܼ6XƱ; $;3 z+bn*yB 9K`px_~ ,= 5`=9/冢%c7ʄР@N-W\+WE\qoíGAZX׎8iĄ1qP}p:P˄!F;T(NP>NӱF=Y$#h2,g$P T"+k&`+HPGNp`#41nsqVS,gm D' -5ep4oFtxlձ( B] LFϟʒt-C<-kS6X!6-t.ihAMa +j=16%UT"~uה,'#&:za{ȁ?ѦY\W[\Z@6b]a:6|_0=Ycz@bʮV,P/^*]hހGݺG=RaQ!OƑÇڊ6ELFɠ};61i/~y )o,1r2=v4Ȏsth!K>F,qv`xXc_z%%q.չ052**1065RNu (AKG MM0l(3VL[R"(VCu>vfԜa[3عxLc& &`|ƻL̠o[Ѐ/n2Usot:y|*/+7g:2&< ܁.'wĒ[Tʪ*< XD: |y[V'Ȫ>ٺZ04FY_+K?Nc>e6@{ƈ"(75'|"mhk84 xKK׼x7HF^U'.&BxG"*0R;2kPKGSXYq"~Ká,y}f2ȏh{^aP u]B * [َFrGaqj֢LJz)t )~١Ĉ8u,X6#TXh9]Gz|[z*;xnVJLqlߺ Nf|^ZӋ U" k㜪"a*;ML8t9_*̀ p&N?_>:<>Μy\bIve}x'QPP^~ >oj o6]01ǩ19:.ey-B*:#빯U"}'8i3mUŹI s#UH:IO[7|/: L]ASٗDXE*ʝpKHIaCWU^!inFAMqػyW<(?V~ZE?@u#bn \B^q?\~=CCTUW ,. { Px^XЮp3k=){h "BB.-vd ӡ°¤ItoO 'DALz6FOǰ$c2)To//$!>1qk1WVeKmֻ D@QFYfkk'j`k؂+' 4T˲0r@4ҫS-dqP-O$]Fb(0ʎ%9d||scPk-,<1t49d 5PRN&ӒgrY7Ug0E:W񫷐z {-ƪQԋ@IDAT1B_L9cEFbSoĭ ξ{[ӛvefa7_ˏly ,^G`b `Jض ]cJkgz|: "lX^cY?zGrvtdݾo%D]*ni-\)mz~p]CXL`nsNDɖ^{g\ůw L)k5䢆:t~<5ʰgw<- r \. ғwA3k*/kS  $ld>q51@F&:wM5[,zSv$u=&|-XDw!¦}2iL0טы,CTW8/rŒZFKs*ŵ jʈ F}k;CqC5cܭ'[STJtUlMGd8W#`hjFA^6dޠ'^}z#ArD8FsC(>x= Cv8QiDĆ\`9;XXhJRFT%#-i(Aˊ p2K4$`ËfqtqFfz l\ZƒpsBi|_Td,3PuI9?0etsuy>ǰN |T7Ct&9F+ωFz= 071>,̀3;*sN'f5Cξ}mo1CqPA}K`T`Q{&h,o2UERKY5sZ'3O#fml9֎j$W΢~(l< df碶F窧%f#! :uwoeD>zǗ/_NJ~W޽ku(MNz1y{P34妠筺2ULEUrVwcE67~D@6"1oRMe*c RHe$'pwѨ}ַ"v!35<Ï`߽zJX^V|BH9Ic=NL_29t<7)t_zVNIvr(^+~Ƽ$2~*I#KJ^~۰|ēxpzUS^K.xy\rɦxz0mt vUV}405dL'ό VWrv{Pwo~m,7ghADɡ]&O.x;x',zY-@VUE! ?4_ߵ5tQJ7cGT$L m=F*mE\P#U*Y:s\kٱY:C v0VBz |YUFJZ;X{B3Q Ȣ~F\͆j+J*ѕu Sd'CXJ> RՔL$Gqz`u[,ݲ !MY=R8n"Ȣ! s0@[ⲓћy9MEw{+zQWI[tĒ>:QzKĄ%p'Q1Pl"ʡP%7b]`~Ԍ MJ2dg@fL-?" rY (LԀ) egS i$^y]!_KCƿ.-)6tKz@q†a#@VkssY*]agL7mDOk3sBјl|Hݻ7!"pJ[ϻ|nn~j4 8x tiQ!p5g*Zi/{t#5U8F4wt#lf NTY 9\G޾6#DFv2U71+5#+w>ɡb?r3Rc-FpJm u%EX!%3 ٘ة&dNhlPS}B5 If3̤Zܾ<򤴭9A م8^~̍ɳyz@btd6ˊiYÉVVrD2ACO PXQ'NA>N(NC!lKGXPm`f~V55f~4$"z?5s'kyH# ~ @I?^SІ*~f8XDڡO?^d$%OIF$Z؄[~ak*MF*ESM=~"xd"c⤾QcGIQjiKƬ# E+˽W`/e+VCsKG1]T1/Z_ =prxQ9n1?֞V#. PsMAeqd~9Z:Md!}9P U+`-*gBtb#kT {cZbL+ݬlʪjͣbII ]=mR2ޯ,Mru<Tq +V▕ieӒp0l?*ZyNZvOoKk}_BNV:z9Aj؆˯>x_"9/-)GJ"eh'$dԖ3zs~^9maQ AR-u8:X2LX:cY5<0;D{6#P͈/%Vy((aa54HxxJJf O+~Ե! h置TҩOOLP֬pK›XhMhc/;q^+EfKs-23eo+7TV_EV/ *S f(-0mr9.KL3 ְ)n[ 7B̅myiG7EJz*7c\ln!s̘ s#Mh N< @hs;{>!T#7)}B^EoR*^U m\eo}{2 4xrDEF#+RԂ^F&rE;#Gpal߽u5x̂>L,m?Q1hĝʊ2GH.s(Dk*i5~`:&,>ܾ?iRU%'0;N/3$X(w`NN 52VbijBlb,6l`@kgG70VL(/*@dlcấ+hlFڬhPQ8AR7/%:+hXI6OsrĉteM3'X &&A%}>JP>';B+ÃJ,*K$y_/FVRS1HW4LlQ -*`8mK;Tu`I@؎*_c~TɸEJa+IVhojODqv_hCkQ "\Tcܧ/XϞ9b9{NMk SG.\:T', U֩cfz;M:x||E^WG9`@sH~ T&:F5H9Fu{4ԑX̜w|z9 3m-[7+Ϲ0u3*+W0avZIPjJTds;Z*AG[3??6WҼ$|˻oEdYCjwaoU =0&≧+&&CIKFlKLi-roO|5'L Q85wȴeTE@9pRIVxF  끫`osLsXuBN큋>tƒt;I^Xw 363v7**9GulR1o%`{O<+ VQZTIs 326WV&Iֵr`UʾȽsa ilk2cmrG%;{ۢ4UD+ >{ 5A|A> #ڳ#"jZut궘dm]V)n/fFn0@kި2!>_=JRK~W(()ACU#8N,]L5j/zXKgCӡcDhc , ̹`cf. u͚B?Z{#j_/}{ЧnSvقL .>f`f˗@g ftkkk13]*+C-rʚsh C1*p Ʊ@!O>Њv3"4]2;ԑlD`_{?d"ʫX5pÊթgS1?W56(˪P]KXiIUg(u/NE[M)'u8[*aL[WWggxVeSQw>W|XKX+G5ةp8ZWD+T*]I)kUT 9]0fm>AnXp dso0޵oxadCIMK+H!<+akއkp[y]&I[G`LNUvq;&:R6Uysf闇 uDdSliHUKagiը&@ZWY gOM?Vh(a ^*KUbh9QRź%Ŝāhe Gj~z4:1en|HJZ 8}ո8 "@[Ff2 ?2ZѤAN㣢TUTUT!9pte6Р6l0RFC}+lMh_L&:xh(DnEipOen-"hqJ dؔnMaG8㒱H4jI.(=mn*Ǭv8kRlMK%3+'Гv&PaeQjhIPIz?*mdNV ?'.Uک$ntҢ|c/DE YT l^lt0޻ S'tuu`c \fTTV@9-+nͷI]0ոz9z|$z"ZwY k~K/<#NZ+qz3`qIXb 7a͏[‡*[FF;p?_?|;+č7.;W$a5P srQDhpl+v@vXT W"0ً@4 ꍷo| }yݿƢ~$鑘GU!`jTH&_t7 u p6D"W{HQReA"Vї`MMMֵw=PXm^OGm0%ӛ@{v`iX\I"- U ]_Bmk!~3w0:` '凖*ڀAJM{٨o lplu ]z?V+ݢ itW:z%@N_-[H'[ؐ\mLa<sYRGI…Iet=^|@_WXOأ\(.mB Sκ=mpCi G_AM/F6@ $:~N{)aaHf] /^,t5J&zZlz5 "߁y7AZ dDQ:Zʤ^ohhjZÅQ/\XYHӂH>od Bg $՚8CUP:uSihtIeufs=FG*ʘZLւ-0wth(bakvP1`3hk/yl=Q3m545NtG X82Ebv@ie Jh/HA[@&h+O?5YػV:g=N_:MHWu".|?76Q'PجkT>qoS{.vx\HYG۰_C?KȋhJdы n#?dCij/Ԍw㏏U^ Jdn4bw\-Ul VLwȲY\J."#YaQ!bhIPGVf'm#pk9@ń_G[չ 7gTxPthLV 7d9g4z5@Z%&c޴`qrH  Q5MswEn~,]ߒnuh'aimp3~FEU ZPe}~Ͻ bN+ǟÄ֒bOS-=hw9cY[˷WxbON{.݋i K ϵ `9z(B)H4L9I+$޻=q2N C0Xh1}*ޥhD7Fڛ0wbWM~1Gbvp& 2{Iys0^{p]3+5iEmMm ]:`k9}pnvZjjMEg51/0-TCFT5!"&5jy)d?j{ cx$/ŠJ QۖBuWTŷ? Cy-AdYqd\vPQVL/#pfL{EXBw'C< {$+4z*{k =B6h;\T.*5ֆAN 0 -MhPo8ب@fdG p7ѦT_*0a!QЈ.I+4)!Z:S0wIe(Y|ʍ(Uե<U BQZ2w߉s<0︬;4<errHN# 4z1s}Qbll1!, fp7tV- _UˁR:lY&g,JGYy N`e mb<䦿K k43ZϷ7D (~'iO6ȢF6ZxLQ>َ(wdxO+>xz!lg.L^Mzn!G'^3ut ~5!!׶sÏbn pu`XF>x1zۘ߬Ee1I~21>z*u>%bqA;T\RaȃjMtB q%6y**mk3]i qBzY7>>ۙU=^]X'|]=qpNM0ūO>qZ%ǽ~#|4u P]M† 7jj*8䱓9ӡrꢛճ#2:%Z)1A Bѯ΃R/TaW7O Z-Yу"UU5gֵLso + swAM=ho(܀/i/g:K9F &}-e (P-kAi-B3ʭ̯-`D\ս)?$Ȑw=J0fJ'9f1 L|=uጧ K{$"맗硼"_GӀu¡z˥MU`f=S1a*{a8XGhQ{7 u󠋫y9uއ7K0}Rd+1w 9nR\EDI< 쿟|mROqI܁P`AAI̽ѯICFMy14[@5jIRلt+rŃm.f_=:POPŸ??wtDl!KkCOG"恪Ja^ \,ٕ#k9 ZY1>,BJd~SI> OQ}Y{y,A `)bwM |)sk><* ܽTQhi= g}[% ύ?Kc%#TPy~^&_B[G؅,*0K5w"5Yv g@OWعhoMGWG'&M$;NeOfU\M[Fk~ 4۴-ApiӦ-Lh:8XOIHĴi3}P҇͝2+2hl*27-OBo`6i1s%BLS)I"yGִD:AXua@9mr4$nfqyNؿ e´I׋ 5hQdc@vc~Xx -LΚ\+~9jċo]#3B>e- nNTDBS -0ڲ<7Mʦ(WGI~!Y9 _֠4}blNp5m]*mIPVi)nrFD~b‡VʓW.CEZ +̞:5>kG[#zWofG]17ELX6} <'Onhc{6ZΜ;CO^ w/ocq]7^T3gٗ_R\ ~?XH3#7+C0$z:|;n!UlHPB,*je"A?&ٽg; {c̅3ZsdXEN5R`0Ǽ?tf8|_ tXrp? KX;#*VWzu*Z\nϭ 0gov܈nADtN7X|ח__>XyA_)’]_ܳnې<ν]̎1)T=aX(N7ppP>r&s21c P'RIV-ZݶIq1n"U5΃8dFW۹g klD8CXr-z?y +Bqye>հ/> +F]bGDw8#,ĉk1}*f.mm S?ė߬-<~MX2h<[Zc\O1# %y8u]rY .. Fas+==<RpIio3P[H:ɡ3E=\26hXnld)L ?r+&D)q *S͚};$p-Caz@ YiXH_?:ZlytZ*Bg߸ƴ>m6ູAH*FzNJ[KE5eHL@Z㱇c_v+h Lo7RaB%F!:>aQAGS'˛\*-LT6U! P5s7"S~v;-sj;<Φ𵷂e~YV_*MtWրept(nq1'0u-\ YE+AT$&"_bfs+np4O*~9_,/G(㲨uMUii4ZrA6 ¬ ìffX-b%Hf8J@:.{ɉ!diA'g_bbP1X*ly^&ֆxQxv;˰ 1޶t7Tq9{\1u8+1"-^'?uqAKXt6$Nwc}(Fc[9ٙ'H)0MUzI0^~EX2BA{6؛C.T6S)[ԖJ\*XNtomkdgd>"!G?tk(KBkeIJTfc…P|3B'Ҋ(h^c+Kј6hTTG]oWP^(#0`*qMׅJxbEI1P,L2nx.ΰqq#:ƹ'cz~zKRl SmZZ:2}/ߤiU׎_cGPθ6dע.j C%q ~1 T+Ɍ Eb;6#.-եV+vG7U6~N\ `XM>߾r=0&ʽ{`L-rب!K39?ľAzQJ֙AmW'sCE*+zxOdeJ+62k w&Èu_nXL、9*}}(bCI.5@oՠj?\LfB وYq'A%}[6㹧GTttc[x.hDhG!d\ʞ1RE\F֜*=|/|bHI^[]qEK=km] *𢅫1I0^EDj2b)ya-p6@]^ӥFt+= !dPV@MPd`wCy1?a͖E id_"8W^^ŋ`d 2˒]/:~䕷?=OȄǶTUk'];ۈCby^&m TeMV! tv; {Qߗ Zm6E`Οׄiny VD8?c%k-iڻ|,Yv]^s='RDt-ϝ\-,gtЅ(%9w3֡l]=5t`X|xx{#!6"8yaڂ眼;wD(HDO32RZSQYf#H25ZZV Zc+2f h[JtpֹXr:YܬM$tgW;50yUP\lٲr"ڂE-NYi%K1sluJ>ڠYKq0# yQS0A|ZU`ض>X ^v*p@LY3z;yPVD}2t!9#akS:U90<*  ;Kv8~yXEZ+Nt30bJmp<\]FGRrY˛h%#Z`X,h ٲYngƲ)cSGZ(L0gb3 qw1!ێ:in}m mVSFv ZY1!g`N<$@IDATRY'8݂ >j OG-kY1C'q>݇k-ޏv"oe!w>qnY36],&ӗse"%Ajj* ; FKL]EǤ޽u3^xiĦ$獛**5O.;QR\Ki/JO+\3*D{%3HC÷mwsVhh2䁝 ;ƺ\=8弻),E;3 )Q10L $⎽AkM6^&RcQz=pupF4 }hdd7w Ek!eݚ v4Wӓ6ϢA=梉&7_{ov0$#Մ_WO,Z١ga%@N򇥿}Jp$/6,mVqߓ֢`= ]t-R9!$?5T᝗'3~ FB߈tPс!^poٵexO3Ïk머3ed1(dd5s3 ϨX>[90{# 0 20w|_ص{/44aԀ4:^C{7A,0xO?Cs,i5ke;fMSTDVW]MaNG~#wȜhv@3xUl߾Ҫ&@MKVƻe-u8OrYv P$~8(l}SF^fꡮ F^#A]y Wހ/ 72fvUm8G=ZQA6-ONeNMMexɺQOn so/~ U5t4?\1ΙzOma[f}6tqidei3AU=JsW#n43 I6ƵhUqrN)<erVgFIXdԀˎtˋb=@!%i1c{ח8華5Zyq'Y,'hO? ܊oOצ ƃ SW'#ؗ&r"r<,[&F.%w̄u2S7q(^9xSp@_qvs6m3UZ* Y(IGze=Rdn5sLRU_{e (伳1AF0uA;I@4ˍ 7NÝdmx_ρ]0l,tPOu?ȆQRE>P㓏u۰ ײx vFG4!<>:B_#@NԢ)I05`k9P,hJ(.o@vEe=֥%;2tnÙNQc&`t u=RR7#$>G8u2sKҭi 4Y۳( -(&QZGSf:h'<׍uI uuXlF#ߓ*j5im]ֲ4dX6-0@%ToUِi2ՌLcl!SCEC3Up.#VsoUhFJil?r9~qq!}`B"&Sٍ}[‚ʆS(I 22XѦaZLAGSomHkxLOFA&NpT4h8riQPR/܋߮rRbG{.9@/2_6 ]S9ڶ R OyZٺcn =>ߟ|6!T1BP\&2tlՓE\S6;'] h+42;gam^zZԤ, ZMA9)i` ʘ*T†ġ]\v;`*pM˙#e͚,֦(4sPf*NG?²7``3 j?kԓSvcQE>>6=UФ߀mܗ&rөnvafb43S%[q0qlT`A*VQu&7p@o\,khBIE.ˈ PAjv!zz ʙBLK}T`taT1Y }Mx򥷥W3-6Cse92p~3\To@VqZqy!, !GFE-8, k@̘95>XE]߮ pN}8͐VþD\B"c"`zk2/U{Zul/? &#uHnC9;F{g;eN*L0GaD?/~ON1h[ѪC|<+|G[j :~u#^WV񤫧8:.ϝz%Besh/ QStX: *ښZК3ѱUbml9*z8Ʉ30h=0so=0XZF{<- 5^/EUZDCeL '$2%! @O=:?VK/ٛ ݏ8!ԆǡH<*KDg BVo/*O!vp%iYo^m*LZ}Rq͝sPmBGov*2@SW /)Ascy.Uf4(ܼlYgoʤx].Ǵn$UO=OX~Ϝ=-͍&Z c=Uu"I5p6V{z=M R{x+s9 _A4fvEZ=aejKgCŬ#`\x-#!VFc6=mtq^^GKݒ\MEU0bT* zRAENl;~h뀦0uu Rjj>ㅘGNE1s96(q;R8@;Z`[xD F*ڷ<407UKK5]QpRD'thnne%$Ihύ1>PMt~؋trA?qьkoŴ6'dc sB1ݿꙿE513RxVAElj8/-$1fT #d 8hgM@6B9o'2u4Rlo6ެeɌQDPT&B"nwC Pn*6 :lϮ Nzq=={;Cȝ;ű-I"fg,.Ŕa+SïU rѾ4,2P[8gG[J>V+궏&Ңڈpq+Ue+AsQe1N pu`.`=N+C9*6 9@#{~HSɰ$iŨKyV![&"zJHԐ@VNϦ-aTCq4emL_߀oljQHLL~5w9&FZz<՜v;bP7ٝi3ќ3gnM ̤4ž}{n&  mˏx[ȑjض)٥Xs uwKPPL(1˘as2QQZf0Vࣨ >i'=x[^; 6vH< )݉EFڝ*ZcO?"-A3'xgܹ:of]VĴl<+qMҕUx.;҂%0s:NZ1;o!9 i3S#, Ԏ ,T倵K; jj u \}#sQ8[k l #]Y#?n, /PX,*n G~[_>osٺL1hTvHJB|AR:f F*t ]_|>vI"A<ܼj923%~Uuty.ʁ#'򦩥uZF~nAVo%>"Xv~V7pڈ<[ ,޼qvhV!mKv:)C*} ZׄEK A>d (oc` ~>PƎ8.q"@+'!-t=Z|(\ [c PTӆg_}84Ĉ:V>21DIezJo|6uwoBѥCw݅]eq_P(ԝI=D0mڦ Lf2r3W^kZtC L UT Ξ^T&2y,u02E:xNr ;9 l=Wbs/"=3|'A ^QbKX/̄|O?GZ.8b{O35%\S<yE@cLCs-0oOr{Jr$տUxd?6v܇@MJl .0-%^(5kh1T`Z_5rBՉ[P}s4<6=u{cNs3^Z `lFRc圅&ZT(׃sQ_ 5C' WygZX8h#PARϩp @ky<7U5vC}S\+lͽ"PQs֡'i4@d(q_%fxx>Mx?"6TA$ C_7&*щ6sXXih)Fۅ=1\_?yIx-D+ŭX\JV>Z|>cH8"io$UlIj,,ζܒ/_6{C*=$mPXX|/J:sv"=gW0{ t15M}ظWV"7Jizkq7iDVepK˫p<;^q4֔[O=x73bAjl CΑ>kin q[@dL>F'K+f +D *cbbNKxͫE\{kQBi?1UYK#1ɵkq*ٴ񃷱qhn*r,hc$ Tj(oˇ7mZ|B҉DcR  ف^LmPi_mB 65I[z ֹ{%{S}d1Ȓ8O;CdM+ܶV8;ЫcRN2oKP1,< Aѳ9 Z+h-#SI\ <:hSko32ѡr:1"1LV5 0Q@!/kD-jH5h ngn8X㹷,uYta+) ձ t+/ȃ2=hD>@-\@#A.bUBJr͈&ہ^ B:Tv.FAA)reUHdIjO\$ڸ$ n({PtDVB ?e|wu(v9#Y*h.-C1a|e5|O]CvкZf;s33GĞ[]G{*V@|z/2f&(kGw֎μ365ezbiFz@a{m[6 L, M*@ *}`nnKY&TegeViKaJYe ΀>KlݹE,wq 5qLT 6d{*G^2<.f('%P+j{Q*jTcç/0t݌@ECKQG GmnnB[=VFC̊8=ۚ+NƗB } iy32- ͉ fBZ=JAf& ض+˩z~o'-B) j !8by)lO?'x־1wCta}?b27Cqv ,M`>??(:FpcFf t+֘xA .vcr̔xUvfdf~YU|֚@rNg@.lۓG6fx,޺l9m6~Ch-d ">9/npe- w1'4 X*PEX#3;ܵkĂt50k -1`g ڵ,녓O0,^!ǀV8^"Hr;͘a', KW?POcR5S?3D>:^+˪cm-Ύ#N3T@78 DO'<** CDZ~]+Ӯ\KTt[Aw?3Z,nMAA&ou 7܈ȉ3k 0D^ۨbNmpwtd Y74=ѥme&l|-z˺y-nd^T\nXc?"w’Fgxn7㹮Ve@VChRf '2Y? ym>aM7sy++ Qs*wFv|b"\]Ƙ);QIbQe)"'{L Uh<y1GQPA pD ?TZ(Qʘ&ꨐqRryjgl>}gk0 wwArkiI>dM>>& k N MMZRG>Dk/U }%\S Ě  ݷ߉߷Yi-vt<ΜN#5k=ise~^y6k`Q=+_NG%l-} ص>z \5 P!ȡljKW9ucU"%NO?-+ÚmM6l5 絜W/_qaZj#}ֹfO_ݣ^ynZFK &^:F ~k4$5p3"+.U1G'BVڲş@7cr*ɺ]T([!/̓K8JKK "衶J*DSP G$ [C ?m̸ rLD]?[PD$ݎgQ0Ft:ZY %W=(7KDD2IN1-QPLn_ sHΎ. 6ۇ>>taA-8pu"#RN)I` -KUw^ jf~-cQ]-'5%R;:8mK~*5,HVaaW@Ou9!TBom' ݫV!؍R#Ҏ9R Ft޼w K$7?42B ԰ fzPmlh5lj;pۂM֩g㠖N*u<3`m M#3PDptG ʲnVnSi:$৘߼YK%9J}@buf{ l]/Bk 47`I v"l1b@@W_}w d 9QHYO&Wy)n-<<<`lG^m=u5Qn;DlUT:d@VpmTj2zWKU %U`k`N*PGr["#h|c*nd*Ir:P-Uᩉ17qoԍaGh d瑇YT HMC8f&CN\xVT` \׏E"GK8q~m4q JϢzY:e4,n}Wotf"n~¸G6;6G`U}DŞ@`8PVQ^Nf&Y{z Orn `=/xG&PIylj&Ӑ$8^|ol@BEr$"~cx^ iW,4` <=q4g`gu⹜ӝTQZY-Ite5òǝTL'# 3Sfyrzh3tCe'e\%'x hoFF-,CƉuu'R=J$Aݜ>ygUw+.$(_oחdU8S~і˄!b##KiSH (z_辝@H$޵Ob854ڟOO Iv`Y *STiIq;H35F5y1PކC"hŝaKw"IMC{QIU:=;A!$T[j s3:|?$kQ4|󸓊5H1,q'ћ+(L=gvs~NhT+1SP&bo{yl|sB/jp0 M)شq3Iy/]T_GMȖb)\TД&Gt1oT ͺ Ș9=jq(! Nt4IE:AVorFbAka*)bsz5<§CS`J~2hC֓ΖCZ$Adh ~ϛKel~ אrZ+M%Sգ VK5Kc7Y_wpxrT5+ru:HOJKTQFQ1qhoYӳFk}UȥRT[%  0ua 鎨%]_ZZ:O6pG|:ki9Yɜ־ADB@;K swb$+X xAA+~ DP&oXQo2A8sL3y"PQMWr}l%eIv22:T@_הnʐv6yTr.jhz53eHWvσ[W:Z\ fEE 5`FG2CG9QAtS-VE%zB>ϻN8}Q{kAoZy5h#7@T 30']ukN4#Z^K}jRUTC+}&Jґ>mQ1G˵nZj "3oO ޶3qPV u/U{Gwns甓UKRS*[1P۸z,*u:sc7oڄ;W߅'d^bcr.[6nUtrCCQSΆ;oưVeE'LM G{\>Z{/O?wA!V3L.sm48IG֎&xy .Vo-V $"GPS`a }Dq<Ϝ?TW Lg)S|!7Q*lip}e7bf$sx Q}T/9Jm\1}&BVr4k-?w2>ܟ[%#{f4l^.ո!TLH`H~31)u@+t!//AT嬎;h\@sdXZ[CfcJIM=q-F=KkpQlqpt8'}D<&MʉbmO.ФWǜ+ yU1񪃼f` w^|뎍?2GSO WΟvQwCv@zYL:sp'9]Շۙ[!ن}\vV)Ra gU\Z]uE`V!&EUuI-7/YժTx+8ULE mjZ:3hmaml mԳ(n5umwu;IgaIV1 IstD[hw/^eȤa}sʲG/xjT !gkk{T+9$//f9U$N)[Re+#$(lDU>}6Rqk}τ>,bE+fxq8},*Ui'HTqY8";5cxRgRHX۾$`M]gĤaƁ|{‡tDZhP*o @fCbђhyKW@7.`mD/m_kS0jDh9HXs 9<:)yҵYE5c>sXlo:hU>V~r`%R _ h+"ҏ1Cf`VdM`cecv@A׀ty}E&嬏weXT$I R"R)®T*\7aݸqtߛ:MNUu]#'Y/}?LjT=?HkU2MC=jǺzCàFAdRjj.9V ؃{ f2kp8*k*1-2c;|aBXUk(Xc95PRZn TR\Q9稦n-Dw]s7Y/bց..<.qw8Oщ@ 1ﵞO ]Lti5]ku.0g+%݌E[u*˨(W&tRO'OC&@ܶi}IERy7B"Y g0E0=r6 =y)#XU4אts!tlREϡdf Aj8f38&o$0*.6 oTz{K:~TaLfH(9-C#YFbV,=P +KF|pl 3'ٻlTHyjhZKwJjMy݇EIE jx0˖--p3z^9wt3Zs0f"cZ/1 y{""tԨWWGFFYL@X4ns/'ڐO)U /_#;ˤ*aa8}UR>z[]6t`TDT YVP鄞6ƳK 1hdYc`\ߠcvF&A =[g eUXSR251m hhaRikkN\L\Ag7'X|%~z8 'Cӳpttę18y0.Y}[hjJkRCKaomq=y%twUuQIOMKڛGpcw #Da2ٞy{Iss xC`DK8q]Evؼ[dpv%HkFq &/V)9YhjE9 x7XXj.9X6ucEm_\]R>a}G6O=~vm6($nnAeܜQ|4SǼ OTc"Y'6[‚VFp:<8p%n6\eZGtGjd2ڇ35ε:Ɖ =pr0mW3Camej=iβRtuW?}2Rc r? &,Of8#T )YɓQ*HTsGUa*|P\F`ǡV0<|Ώfص}3:p nfh-=ettT:ej8IA?}F`fّ]2',N,27\In*:cvþBb 0򃡃\LaalvɩOAFʹ٤Y3gaJ%?K6v<_%oቲ2 z++8Ȩ14 dD3F -%8 viPo_"k€kijd:Ĺ[#{Xs y7nFVWR6U{~``!WxEIZ=o1)z>;y =SSUUItd!U\7uuo5]%} LI&@mlgz*{(Pp@T  tm8/~HX2FN *]ԟ/_薓xch}V:ĝ}0J: 1#Mo$ٌ2@Ϗۇ9e"E_0gNN[b'lp; ~)͠5UU8ڶ;Bj#))n_Rl〮4ۨa8tտUz/:Xwt&ઃT7* 8G洅 ZT4"9wv'AB*gIa*Tw*M:!7ɲ3a RFd23W/9q0΁׿qrX[|$T`r[w޹V6ݿp|F%[=^l=CeLa< |ڢewqN֜X~ o;}|Ỵq޲'N@ c5!bhr^cƎlS3si+Ma;n@}yVY25CMztj5)Kds6\XlԕE`@ .]p_Ȣ}kdݨoFK\W v#3aV9pq ;9&QII '%f6.t[oCJ&_*=>)VG`t7_Re*08I᭜R2*+]hax|]{EPYUHw;ұNo '}u~qCVM;X4͝+SaN&,_&GN&3o#-xy,|Xz>} Ҳ qaӧ†Yūv9=w˲GFzG.UTBۚzͶRٯI p60~ZkGcw;9вmP#? {T,NrsC铭-2V֢Yѵ: [7|O?IY2c#mr]QSPݣI;A*9Ar2g;V#8ɼSd׊H{s>A=u&[6z<~|%-V..y8]*r,_C1ϽCeFU+_ǜq*֗^|i(0w.>RUe_,F>/B՞DRN\{4 Ӷ\/΄ e,(YΙ/̇u )^;TddǺbD '^2DMu iEe4a@W+M*Xւ63;ϟO&GKY[y=rY̝*TX k +`΢眴Jy½֓TNsO^K ܵMfS+z%OSGKg} Z$94nlIr6 0irAhl9d.E4IϨO>D̹K s%_| :w~,۱JW vIj̄C+X$9}ŵ:jX{nh\w {%uRN4 <8I#̵ԠAe`Vs7_ZͲrwNqc,DGU.XN(e\JWo;ƸZa4xOFO%= uXib+d5+)ȭ邕#:C3Kj\tkNgM7mH\?[q ,T:[R+u fZ~u[^Z8}^N$v7wOQ`=?OL C6Z{iNLsFkХWn]>TN*Ѳ̌A Rz"~3Hε#<N)Iɉ$GsYL-lO Wg`Aח?`uvH!B\ k 8(/;~8 FX "ی2.lDR &fzj|Oku71vP﨩\|f-Dqn64uHy SG&wd3z .ZZ7pr@x"&N u.}T:#m@L-χkA䤝B %2ءf&\3l}B߉_w+ۿcgZL? 1X#KqrT:O ]WR}#s=Olg8O^.lo$z;UGloypC^JNZ>iR*w;+*/C[Rw* | mX^ڦ>4-/H["d*u{Pe/v lC䄩(?LH=6mc2D3Ed[)$že,ˡF柢̰ms'x""$ė{)N&$!x$l?m2/ 9(c1Y2R]l^8`ޢ8qx?&k"_m ~#446PG%E\O5w0~VS»T??uچg$uPRKdMsZ]f~Xin$ė7m]m ur`d|JI"Šv&-%>Fzlv6b`AKɋWPI mus:~R)ȫ0Tc*:tfsiBئ26Am($[߄ ;:`S] )`K_AݽÙtf:SIJ*lиY wf<' 2 yeŒ2 Jf:3mϠZH@=HLM@&̵l`V2*F]hVI+$~~0KՑjg^wdг`.N br/嬇U72nl f. *HMM8ڪT4}C11i0VG?Mːx&T9c9gփO([<%njeB*'%U-Fە{@ZY#ZEm}E+<>(!kdZ>?{`Xe Y]xwr[nkVv~zVTJl7 %pbllz`-++Ğ? T?їaH @i;cf9ћK.;h˖"A2o_;m6s`@"+\iLڎvՉrs tk>c63P %Xt˽,\_IyI8p޽?!.7wxҪcԙںTlȚ~ZzRH r2c PL5}-O fn1`p,hK%ݽd;(^1^{+zzWhoYM.YĦ50'`5 9+VcIQkNOO -LK1tdRVW;$K.CJ)Zj ɃHk6=T`¸ flGﮓ@V-wh?mn Nmǎ%?EA!M9[K#%}狨B=H!Bf`cDkצ.̋4"'P= }2=k(M5YiO$c*X 0ԗg0؊ɳV9%50vL%ԣ&XuVg9k2Z.WH,ڏ!Aki/bm1b%2V*++9ƙ`lKnŧw \ڻmG7EY ?~.Z3.^4f3ڐ#^0pdOayv<51vР6'4&GAT:1dAX%q47OofA$XZ'nn9p*DL"LDuۏ_"L uS0=2=P :0{1\lGA~) ` d%CBx8q7e;k?lxOpQ]fؘ8fH^f j r_;8%6jfTPr q+= ?yVTpp5.9 $ R=[#|?|+i#/f6-i"Y(d m=fZ2z:8хoAZ[fdr}JkiEA}E<31yL JKʑ(ey",d%nK F27} pI8 U'wN\=$Ŝ<__I/+@_r6oM5 / XūFv"\:Ntym͔P 51 <}/LzN`~l#e X@}hӆ AlFBt`kiqx ~ L!ԝ dkBfʶ`|M!;|(_Y rq\:`\]nl}dUUbE+ zhlz6ȳ-*,){_|?'ޯ: ^18y'[%Vwk!.W_|wXtCxQUM2&݁r(x1(lK/]H83O{ #]`U.gU+ژgZ2tIzrDn]pbݣ^0Y7<1S瑧i`M:mG]Gv1I*ՋVyDTmH\L&E*w`)W%w%Y>u`ϋ[rESIu*E!/ISej2l"gUi,G<c.qfKC[qm8-lĆ-{`m(*2w @"-)&Z:e2C#.?ߔ:ATRA,mŮAzX 2ӱpio؎ӧ"9?lMnAxXVemJD~.nFǸ6 CֹƺTd nXA$'{1` nV8oY Rb"@GqGuYy9b\YƩD 'L1z-:4!+FXT&>*qj^4crIa"#=yǝȏV醢0 }t:oATD2t B{qoYu{{hD]\TFеJs8NTE2hBBa ME(/6 f,:FTZ!'1 cgՙC Ʊ>:NZ;QaBX|ms3 1hVS;^]q'"W&h^U9ڴPDi 8owf]dZ.؂Xc[gDag _$+Fg:5thI2 "o7Ŗҹ1w&0(NiMl q*Tc[Z@cveC>Me9-+=h"Yτ ;oـhN*J : k:dز~,Q8y[7RdVYZM̦Yb%¯0!zDSdW!82핛7'[hosDЄ {rT5Tx-]Inc+ࣺ򶟸L]!C;m)uvn[@Rܝ$$D|ϹaB v7εssq0Y\lĮ% @]'A?MHܩD_iOG\^1I)"l%h ESHd'&-ݰwt㽅7K)oPh,<0yB1PҀ0o4SLט{}Q@Roo2Z^]h>T2ۀl桭 ;~Uru|P^ `bMd\%5-=9/h&M' ]H*K(gz5Ja$ۈv0Zqޢ0\*-,@м|HtvFt},`u5gXD2x[AʪFK|K(*wns_ZI댶#pXž\-V?|/6<*"ކE  0{&Μx_ ]iH߷~\IJNZ-;r}AcL *> :Uz4QZ?Mp(b"Fi V 3]OB*l j hTo0|%}. QXGjbx)ڶLOԴ*/,/W#btS}xP,+_ށP[ZaA,2hM|N$ W/{cwBbByT)0HBK#8r29RW,w=,TfݮrT3ReE2j[u%5ح ά8 up [3ZxY Zq U1:M PRYA)KW/9RZa3 ̪ 08W:ꬅ\7WoDޱ Xb-ESpL&լXԎ䑈I#mZkXQb *[ UTVB;Uݰ2VxF<`]XA qV§.F3j4a+n~`.MtUJfizuX4kKoC5߉>3EkLpX C,iNqJi#㡲f޼p@q?VL6uQ ̜|{Wa-bأښsf(+(D-mn$j>e7C.5X+aww1VUz Y)c7aU+=.?0wCS[22i+mq]}ߟ҂k;|K; #4=G@Xk2GX{㔞|)iq,(L,kR:00f$,CYIi`x\hxVSM;#VmכMQ0DBr.&]<4Ү`mO=4;w;fCRͻ`ذi|m}C'o%8FRd@`hTrHų bZMMIjhj͎HBycж5-&[KKz߈ݐ8 <} \EX6:؁Z{`dy&RyP(-j<ުhBl>yx/ R=xor4A 1e\dY5(nì鳠@&߻R٫c :m-rcR1GjF3=Tecm Efy3+b4fOetnaPՒ!U)!R!}sp93V˜֡2[n.3SFj,37J(H+ׂv*jO8HKf/ K`IBmK|Zў@*ƐTy6TQ8AB?B=Ht{g͓,c|=lKTCXzz&{Cbax-M*;j0 ӧGJf 3iiuKg>&8ҼWlS>^nn y9޹ ~y5qDWt YXsvBdq0Aj)^yd FwtGch B}i>b׾p8P1Y2dYӮBEY74'zi#T楝9VA=8e|LV:ر|b-]g7uS+g޲VVVs?Jv5dٽG.@m`+F8^O34~!'$b-`US3VeCG>e. UΑ4ƥ @~XTCb-:d/pf+^smmd .Gj꘣ĂCssYcho gVq` E^"Gxaftk{F%O d~>3fqtz`_$ spb& c%gH 5<$3ﵛ}wkT(튬#7ksX[SpM8h(a*Q^S\XRvP^ Z{ߙ8^L{n?9+/>MuB>Od:Txձ~Uq*Ө$3;@٘%L:c̽ _BOPKh=?1w .$9jItsn[_"ՠrHzzF^_|S:?e {Q`e##x€cXA6k*!BW_‘,ǫ0*D{u)4GJҢC& lXXdB2U\J<--A _S?qp 'vXwp /ZI0no!RH-Pf*PE.T3O Wk"OT(?EPn 1NyXhd]bZ  XڴJi+'R X'ƍ4}GHbB*T '`Ⱦ尺r|FHJǴU0'?iT[ƟZj2$B3Ks:oG,$e쉍 g1=]-4һW n^YMQHqx"KA-CCWyBnx #ۙv֍_4V`eJ}]Œ`AVw@]D2sOMSñg Vՠ :Qك.7"%\q)-R2ZC2'߽ *MP\JuyZ%&c܏"Z!}}Gq@FL0Kf!FZ׶xMB/?%m" ?| pՏ0-w(h`Ӕ)6C'͈6:uRip<FT..nm5fP^>S9XСUtrƹ$}ӲXdSMjjHB.Skqغupq|ˆ2Y6nlJW= r\; ')))Ȃk XOփ8M1 giށ%eD9~NX g! h\XZBKVFBh}lmg\h+4ԑTlӾtе@1W 馗˞Fs7wd޼.$6KMua`5sK$K\Ⱥ`_] ɭw1 7%8zFU4ŀ֊X2);I#3WS!ո;/Yw%֦F|T#VR6fwN5)_ O݇B*<&JdQhZ$N.EBj|\AUZ2O V̆m)ai:id 8w3DU=sW|xQo@oun$zC@IDATBg@U#I,⡭Lb$^vI۱m]:q&׽[9cx*y#G"DS%P4G-^ S !a0e&8THްd^k\{b`l$9Ql}=HMJ܀FA֑ScVbw#~b2':B)1C[1}mMI~iU'PH'?`;wy떿8{p+Y+Ph#b*<z6;h`<a77Oi1~JǓhD |[:袗f7G ?m(p(MʊN!M겿pQ*1*}<T@߯wꉥlvrS}=[ {bW,;]7*>ڣ/[L}ƃVOU8tvUEM ZI̎:|:誳rJS' =F!q.t%Z€tYj y !Þ@*4&`Y8u22bNqyy-8J^wg+ԜAfQ=?h{[,6TAjqdHт]`M¦ ۏBl%գ1t/+Ha(#VVdڢk`1MUG ]ю:..~E ~:5DW2H5*D[sZ>SCLN6P! , \Dg*QDux7[(Vvws'fPefϦdt2ӕqvfQuݒxai)TcXĪ'\*2K":*o؀_[f bA;|SJptqZ(th/ҨN%Iv$nK*[-a)?5dmcg*E䠁hǔ 풡RyS1ޝvh k0TGGFޕb8s.HLH'z{ƫ Qo50u0-YMuQYL"me9;UF;kڄ?= ˀ`D++.!c&Ѕ[T]o+q_\@S[R|M}A@MXofcQRX(,zĵ{d#:?U$槪֭+7EŰtzVYO;0)+7WXvh1`*/a>B?-BX ^Z%e\|#PV$hMQ>'*Nja=쩆ttfx{n#˜Kpr qd颔5|X{Z촠Ů>V4x ć'x0!l6; q(`h0? (#3M}zyO30YlphO*փQE__rr3yeϸ)U>*.DjKfOC<-C᩿J\¾CXu8>U'-^ǟyUԵhEk_ &Y0꫟ J꒍|NuDE$!#HM $FԜc}d:\_%M|qX$%;qԙf "x g޲ %՘9V&mϊJB*8h=Qqu%|H5QQ(,*D8u!H 0 xgF7ci5, -olO@ -Nvr4rXxD-e#4qEglϬ_bUd)MIՅy(eT,ԡ>82ՑKK״3XXfkc¬0vø ١6Bin6٧@msQAPœ6Ҹ,g>õ Hxo۶M(,, ş*XBTpW߶* hlkaK2 xsH@9( sDSfA9N-XL{i h=/箐 VR Z Ih|k,A !9%v|֣vupU3jC3ϣο|Jغ9֢ vpq@Vi°lpŰ9s 8x@Q*%ammՅTP%nb7t nWF;+K2m;kQVQPEL5ڻ%F:Fe ҳp>1uH$_*&0%!2TD8me@:HίGynQD{G x1F(Ju{Ȳm,xf^s2yO/D 9!1!ޞdz3`OAIFI kIujEh'HHHSsF!OR*F\IhkPM=V Pln]Y= So߱hq`.FYrU_]`?R^l Z3 y#ӔJ =ox{#ۿҼ7QBӂŋp X~e;֟dŕ:](Xo`8ߑTHߑ[YIX<d=փ-bU?H'V$DɣL3 D$tK{N@TtW19eUm*UQD;Jfk.qbՒ ?'תg0rrQ^>nX׉?uUq*g)'m *rІEKa@aW;+Y/ JTir*o$P9p}-$mx9v's_$ ktI'߾<6 +׽mUu/^J(s??-Xt`E`Xlz#M[mڳ`]w\5wAaa]+ԞY[1ے@6օK2#,x9Z׮لXmym#M:"0*NVb]bvP4*ahc e@ZsTj7D8/M/%ݳ2*@tCҁVW٥KEnc\Pxv9$z7U되,P għ$KWEˠ'Uuu\9~-]-EFa5B]Gg c*S{YSUgBztu ݸ95 h}kB:ASsI<wd'%5Xgԧp==Iڀ$Iq/LfL$%e3 y9glS/u]7²6gŸE]+/Z`;ka"ĘK@̡~s3ӵQKj- IPl%/ g.&U=ЪO$2 d-D,Ӷ:J"gSU¹͘%=> 8x Kp@Aj8Z^5=m;ť2Y7EMXxHhR!iGko Lكq>ލHQfjJaem뭐twSq)F(Zf rsC$4]t*Ƭ3l93g&J/WjD+{tV -g464ד)狜[vmڀ]7 t^-H6%v wЁ~} .㖀E)g^G`ojnQ`V7 dݪVWSҢlXٺH Y_!\,;#F:md<JECԙo%ʴ<ݵm6FXz2њ|Zb"77z2@Tn۸k"*U@ 2jjk zuhSbN; ;8 Qd?Oi P@Z**>[ I7el@qmm-;Ҳ&I 랝[NA`##DJCAȊƇ}w&L~ X;K5k>ƌY3x{9Ǒ{ѧwW=^76D fig{cxAZ'q@'C#g4vlټ!J1(UK+rѩ!=NyM*vLHF *x7t; \4;C -C_} ,]{9OBP8ڹ`&;v#@I^=,C_ &h[ g\6ݘp;xfQLDU-,\OCT iGsd/xQw1@$Zc^5fyi1gգ.m#I]8} hFSRlm0#û<'Ed1_CgC@p+ X|mb0 F6Zs:] UE{GB%thdZ6?U+5v^'ئOFhNV2$5@c.\/ k ITϘ5 |p~-x^ mjX9x{~)n#x,CeתP瀿߃JY6z3>vZf`hH R6 }D[t(G6akD=H>}'לpBMܚż3,MN$XXΆFAVZ]{TjwG8ԢOTV27nE `agZGLd3@WRʨ6pQ`NU26fޱ.l\ IsԓOڋom@+bt6I1,gL7M7]=.Xѕ^Y~ճ=~'UXjZ~㥗_3Xؓ02N=`~x% u =YYIxvN`dVCZg 뙄kH:nf2WACM v޼ġ!#'߅H0iƜE;X?Jtp'sN9pM Ool$)P``߸F ăG_P1ҟa\ h+gZYE+DrJpðҐfʴ68)&uo42ĻgC񁟨jCZV>R?0F#Gw›6 MddT&Vm+gT3gSbU՞CN5!?BAWq?g.>oyK `^M袺U]]݌"knW~} )2t3&*l@m3!5=%ts\٪|-J$n1+4U6ubʄt)s=Շػw;d9'A*6 F3-۰7*2u06ƒ@iJy<&ZЬ=腊::IB|0.z8JA2_!Tv2z^ ndЪ1),iB@fEGW/ǵ5A?4̞*B}m=x$ I?o A~T*ؠ1̷bͦ[ iA[ڼĜL`XIel3eVK 4p'O3"9.@C9xk ]MRG{;*X26Tg-*|`onuɆo>0ʩQP. u|em ]I.-ŹtqO7K5zODGa^e+,9({ڬRu[L UpC㯭^=Z[\t$]-0S9^ÊH ףT;ϻBɡ(++ "e ?'mus(C7 ڥT~^;.=T,[ uzyÈumQ۾ޖ$az Gt9{K@V =\Q%$Bm?XX |"H.-_:6߭Xv4胯OR;trkmғ* =v\ 80jż\-l"VGjJS*c65-Vg_ 3T 4c\`γ; *:k`NjK>J01ċG.viRUZiѴ_,~E8B5xPI(_yF Wa}ydK\b4h%@!+ ߈W[Z)$=p=#yUE|;f*e>vREҼl,_ZjPԉCѧ믿@9M"_DGum}{,Y~&koY4Ф N3Dse-aٜxޘ*d;hwj S1alXhx24ca"hjY"fFvg^rh %vMȝ5ᇈEW5|k/{0n*oJhcS&`L@0Њx$z\` :taꍳwaR&;e7'᳗4\iMɧ_;og%G'N{Pe5t BwAQ4}M!k*1'ndީ> FTvKI 焢Uy4dV@G 5JO ȓc(: ]*0oyC+ZS[Y1c'΃7N%sn(mn\~TO9[ZKG/+9%בܢZ' JO>DJ656Ď-?3ͼyfcAVѶtKcSxvoD`X2z _ɇ¬Qveע m7USFm{au4](UITWgc(Ck"V?lz|C"tr+W H$LI x8qUCrDpf,+Y<mۀ Wd[Wz9BUwb}uiٸ`;_VCP;d!ʞEĹسm ɜMZZaN{Y{6mwPE:jpAکcy͜0R^Ӄs*$ @Vd5{d6Va'l'+UeyTD2ds]MJ Np9]ztzx/^UYJ [ 5Jw+>'ELT}N7A>7Av3 b*HYEw#~W}?[C'_: i!~¿b ĦPͨ@ЁOn$CJWwOޚ2~6ﱁz<*X(XEdJV# V30Xgb&*GV7;["sƔ)pdƎ>Ufz? &tߡ}w ivP6.R$ݺwϝŗo$Lm4˾1OŌ}ub Fq2:fNPF2%`m*A[/QC|F?i2Rb$U#~X2Xr$i;6DW݇^iށx )VP ^tuXV]ߪ ss}kש(Hő`Uo+SbY$\[ŭXFܵ$ln^Z8}tvb~F3Ol` {8cIgY1N6TTݬ3Mcsc)t*o釣^/Ւ 63#95s03jք$Ecql7GbjzQ WF9ޮVtAܷftʦԥ` rղVh$.UJRuc p"hD.t1*璡ψ%Cm*J%7cjNJj[Cmr +hi@Zf,LR&k5 ~ NmneC,$SS]s$v8Uld:;;"$8WѡExm1ָJ2?a;FO^y5>ѕK_Jͩ$$geRY((w|%|i͐ٺq\Ig*TՕ?/ h;`ñ.!9ѝt}{qKYcz9h:k^mTkgMWsk,l[\o'{2CZ rmhUfwc~:Ԩr6ő=`Ipvr1('X> ਲ਼SD/wiHuFv#~C1uK['$ϼr][(#;>T;8z[/;:!cL.W$m_(QM\nd6] o?}HW*ZsAu< ,W՗17`C G7qHa)KD;t>TPZNXGTf%t"^< Ga%E#t ;5΢úb\X(,Y8'7{&Ρ*{du梼_|#f!? Cm*YqHGY(Z2?2b`z\\ X1P(vލg}flU?$3-)ڼV]/ eؑ{y*g-`ȭf͛wf)`hqGɎ+Ad9zcpvĵl<~O=$XS |!)H9M+dM2%]:ڴCg1TFۣ = mEFhbJ`,}ȰNG jT)3$S\@1ӒFǘzKSPJVj n{|r2hSOjT.jFFsO{9j]6u+#}/-JJ˩q0%1=OIB0Uá !,9=t;igc%%3}zs:$;OqMH pDb.C7[|s٭Z^pw"UryX%dTz? ktC3 C%t Kg :M+.:+"P 1^̽WQB{[bN„}LOi) M6 Ȁ#Ц7*x+@Đ@l/d5NG- 2Ԁe&F!Зzzʼ3K`AWs3HB*@7?Ef0Y]9H?Ks{:c&L b|e̬ *2^TRm뫴fױjJSL hD!GZvR q &A>&"1)emk%@ORҞ=;>ynvNvhP`KF˸o7l`L#4T hNPYcH,[gG[ 3q{fZ:&NZo.&iBn}BS)8Xj#T"Uz(lԞ5}񯯡C}Pץwb1^JD\n#*!٫O"1Yħ؈}ƄX"GXt$^elܶl.EI>یԂ%^ښE0h%:=6HRٖ$0!m8ҁJ ""ЯMQDXL9͈#655>}Pw8^d-gc-*~x;Wsilz+k)0U7 x啕yNw.|Lvn䟷C[*_\I7?fŽO8⑰kZ-YGb/s `3^㏤B#0 mgb+ӡ󲠯g@uLkm;׭ą_kV}`ϫg͇$2(d"&> % I!ʂy(%H۔NiÉ#̑ kږ 4ij{xJB^ Wk$%T[>3$Ul_6.k^y 튒w_~H tӄ=U*pZSSݴW_OzOs 8{U?GlFT2䳯#+qHOOq^^ .V\$eP Vj D>Y&C3b66 fED޲ r4eGNӲY%}=$N]w9~whbR~_P`Tq ؁n/]ަ*yA;mM dfmn7:$aG^ ΞO;DK GvN^FeY0j9цw<9P`` CzՃZc+/BBӆHzDGfіj/oNjCPV \*$ PK#מGyC7f?*0}IXpN:@"@ Kf Iqe[=ߔ"1m|z75AJ\u<3I2,<9-R9H0hJ[ٔ%(g?üe嚩>Swߎ* #VCnRhs9=0rR0qKVURT$(lqְ84bO9T71 aUig O?% m–7p@Aϳ ϾqrT5jV dyÛ&sGX7~1 NTDLR*kJU-꘵SH;_e="hB2Bfr>\ -=_|)pĉSb~˴iqm~}epp:uXT"dCnLnoGuf*ala=zuЎYԃ1iAeH}i ta3H@Y7ⁿю,<|G̾=Y GL/{opؾ/}%|1FuG@iq Pa]-ObɐQmEU4IJ$=„C鐃wYOfrvBp>.syi.PvG8JSK;aJK,a@An;H30 SǑJ'm$lAʢ.c^)T T֫ EۺyeMٍIq\ C;R`mrliÖ4 bb-EJDPIoo_n+j}l71Pxlj f U~c'<{9+LG-&YW^J!zZ$u33;<;|(gqEStSVa२kw _a8=tRS >p,J|JѧL~N2 uko37MQ}ZP9Xɱ>-h;QW_I桛N[==|ETR}1[/rUif (gq7>OxH*r)thU3yM."I^ :^B.#pN< t 82z* mazql!_F`-g%{ 7OdǞx~5ÞU~~ITΖUIЩ6mFWu"c8m-,QGqD4).ƒ;nCmY,_N$7kcb#~#tβtG`,W F]*4`8R@o<Gʻq'%e_IfX+fT6ٕ\= o{3F9\Z"6W`c CMxi?%Kަ;j;``h Pz"W=5Z<Rṕw7Ng}O ݵŴnF O KmVm `[1kކy.m[)Fښ@5AueʍxN0w} c/$@.v<-~Y!8yv}\瀉x m"rKd~L~}#\cN'CM&BQQVG%  Q8yW=ݑQFG+aц̼3rZA^**Ic}m \?Px&,:5mU*U5bAu hVAХ6fHl!ml[|m쐛]Q dӎȉ`g٩nNAfyLsjuk{W/̥kʹhI:&0;6dm'Y+p-|SagGX2Dž҆c@5*v]f04 daeZ~^hߟժ kg?] X<"<:4FGd(8,qL5~*2KO"VJ.7Zpƙ OkUآ@J0a~ue5-tcg ?y3j^w^GA#S*4P؈;Ym%g/~W4‹EO'i=~9& ckShdjN+s(PSe.DÊjB*~U%zS>$ڠh h=CX{M 'NsP K)eKg$%Yw{iP^ `3R]kH kNj,-*cS+U! n1Q0+pb:o݂ U%fT额甔LfR%j&9)ఒ|hUO:B3Sa(. Ku:p$uv:iDÏ0;ﻏf3v65HYWѤ ,VC:̨ mtRB4Z|QI*3ӢHWs*pߊ;Vtd7В)PBj)P^|xxy( ջ%]IKruOU=>z}<p[ [k!bQ|`I\ &go{:@RBO U!%)*buY}[?omp 巄)8 k=2e ̩HkĪExd NIҔY p G*2D2 R㼝B$nMƔ5P `e#]51jk a˖M;w> J_Z6T3'pk6TyC=}gȲ,o`%zy4sBisR_SAc¨2>e.)w0#.gODLb-d0.Z,ˈAf45;6і8 .]x5_+U*U'f/$Vx+L[YXxGGڰNEu[zO18) P߱NND5֕ro3)r49:&t$gh!!#vCFXkhN+ >X;y` 3B \υE͍c=q1Kbt4]|s7+e1^YN*48}VWSB]icL:ł e>-9S2Yv C;homfaf8M2 #qrg-8 HwkbNDC ݬZ=LȒUzl s'VXSM,^R~ sGqAl{dSO|S{p-W噩l,\#kEIZweU22e;5":E0 F'hnpqEc7g{-AOغoзy=<~V_J+|5 wIUˌF$dTӖ՞3e,xkNP@+Ֆͅs̝ԫj̤+󐙗kӗ?H1Z41]GbWȨطKe:hr-MD07kߎ`J5?IohCPqJ A9'9޷e6Rb_%COC|n}6,Hz(J ;-dH:~nTo{|J[N3PK洎v'T; A\qּ޳0^q+-BK_ogBwߕ2B']rsnXf^tsM\S|ŧ|tL>_`Һ#H udzϿ8d qx'c֗uJǻH\Pןq4(WJ_7? 9W#nc'B){7o1NK'JڱvڎyT7鐘4qBĥQeM;P O$G!XZy Q;׭+BW<ܸ(R;U_Y4gEjj]A!cM|-C4*ӆ#Z׳Z#)X PQ+u 7-֩X g8 o [0"snA -"x0q\ܯ50>/ vw6&]IYCާb}޶cD:tHF57v/O^TLfa.N:tGGxx@e~NZ LhZ050SX6uyX;Aewz4HRU%OE|"eQ"DSFw/g'h<@]q%[5wML",k&dWTM C{v6^sh.)Ɣ9 I0'~/:,TAMۑPzZpעшϬf6nBfJ,]/R!1ݕ`q/x'?3CfHEWX[~-Jn%T$#s:O\DYejsd_@_?IuƂ)>)GGzLj&~T=&>.ׇZm*:|*t02D-JzL,LksT> n}XNhPij*K[pqhA)jbt9*Qك chv3 >4i%жW0!2!vT7@L)Ucl 06jtEu)NyE5:,mtih3ZhZz?rG`9mI.,@_]%AVtMK"ϩӴf9>^ٌ!9l6BV:̶G/ d$+ƫ/9ޣ{dEDVW%ŕ DFsycǍyzbO`>`_Jo\3KS߄8Ga>H#??=k;?ȺA1hvs7"K }ߡ޾~CU~U?{gL[{D`J#YT 8##=#Ԗ3'oT[1crZQƆN+;wx3O5_0_ӧLDya6:%A[7⨨x$_ ΐ-ذyr9!76*& ^?&iQiMRڅ;ox嗑f$7J;֛ )mm-;$@S:i$şC^q"Hس\VF[w7a֧:X9j> w`sC7Rɞ={Z}Mp7 ڸ|ZP c*â_FusV& NL CmU6!5%{ٷ.Q\g$ǓE;+'*AU0*p,lGaji~=^ywaXy]^VR9D?2R%QT]MPVQG@ 挥NP`f. Kh-H:"5-GIكeTQ,BX}$upp3}+Afb˼J*38$s;4u*!1T󹏆w}EOwԬ\$sSiGe㒰 5CjU-v^ iKlF<.0CEvTC6C֖vYDFiq:{Lafyݺy 0'XGBY,2QSZ,Њr+XTU†]g\ M*qFB\WFEwО[q"Yrsͮ#fQE%;W ຫ$Hſ3f]/h@'Ywt\QՂX*#ᢝӧ=-:T(+`O&Y'9K>oђw/Y\bpnEse~`96G7Ǒ=;i[%+VPTwDR9_RR& 3'(`.Ζ#.88c|k5\}e;7ngB2w* kv1}ɐY:\qsxɧۤe׾:}:?*|$Zb㤬d혟kf 2صo7#)F :\X< 2dz7b:l?[\lw߃>wHt523Z3_"ܑ|Sz<>ih8`( x Z5ļ(s3KFpj8nDю.+؀'ȓG ֖u/0EMaHKFmS'|gu٭Xzm̬O=l=<= Z(bni!1cהO+c(H~Uf TY #-"`=Z0%560RZjkSfXJ~ X #Tφ)c4ݐFYws=^?>-;l*͇Ut$nZ1F@}Ņ$hk~`T^߿mIWMRBu%B*@PqQ*-Lr)jߛNQ+iECyCƖzCzؾg˷yWZ׺xBo՟B#)޶3ebu0mv/h>APF^e :Z 82krN1>r.mfIjv5%SU:T9մ-9PCչ+TIkNUGNE"+HsJ59?6>JHpќ}'eAdPgT]>=&#!`g#^|` G3*8qrҹ"Hɮ@tF] `ANښ)C1E>Y+qxhR1w8T6J쯵ɯ0sgR%oiH,a;c( Y }~A"6QQ~5l5f05}];/Uz6HdeGfvP,{[fY4ŗd+~д@aV2rًZ#S ޱ K%3'xQ!F<S&# F/-KOFJ{ JYٲ:*X1\GHM*jcUyHTwJǐb)3[`}_+$ձOJdgϟ șM59{fAkm0]Ti,Cm^"T R|F5Y1ۗ.dYC*[7g~䬩aJA$LmOWj$wgw+JIPB!WORj& @7D V2@?Yv"%>rxB\,.Nl_s"<:&OG$b#^.eVp,xeƇ!z+@f6* d*n0j/ۍz8[1C[ g23uYp ]WtC4<=rly}0\6#_PINFmZ P$oF,@Y xXi-vIp6N!YڴvVJmq!0.Dʳ pgn'F2y<(lS'DdR:Ue̜m2TiCg%X}M%Y^fmjG E1ɨ%(8lKž}xRQ /M&+]<Ǝq6bsFsEP3ىߓ,mh7ܺ;i5wJ0j,} 'MsgoŌ"ڐS!Zb'& }*,#`9V!^sfnQ>YYTW$V,[fAvg<2V> >]8Fl/۶m֭W{erM[p=w=(ޘLaMG{b* 0ocX=zs.D'bvڀERXSBݚt DNgNmOL@t pFb}brЮhg~-c8x=$wkb..Or#.qP Pb0 ԥk싒Vf*mQW\iב!dACԶ⽋0UW @X|Çؿb_wE8 i5 %jdݾo/ctꢒ &x[swآ ʮ<,ISfx.\>ao**$0н-yљʐh"Ԏ3sdTus_-[1o88{QAD,1Ag-[S *FaZں}U0Z2l|0]zHIFrDr.(/\2U\JBV5Iqn vd"O&YS 6$?/m\7qfv1tuB1c1o-aܠʞPh/YW7j"~Tv~fOuNQBZ(j~Gy؏C7،9 aX;TЁ 8s>2Y񻨭y$h1-eXىB9~eΰpSP}FYA^R"ɧ`vE-??$BV1bIT`֭HnÏ#=c>qAPj'Ɇ6S$GVDBB-Ӻ-2"I\.1dq oam쿇vl` #Hx:ul@ `M f_-%7ᄍF8YYێN5uŋZ,Rm׳]UlL<X[$.E?t ɨsHYY>\ŷ_oj4cPI ˦ yȉ9LJ“گ-TCi!VNv:B2!kF hOol/}M0;;p PN}}j O|bpz);~oB'^tM'uʼnc/DY %u̙3l_r?eDz9]UQMK` "xsLjr2ˡ ƝĜEФ"h(\M w>O##5nE;ZFY NTaL؜^_͈'H%&cad :\*6A}2\gG\pfXHMp:ⓆY[D Z\ ^X2,,;&FF蝏֢I %D6, ׼m8h47%qA~$HC.wRM0QP! XDd;h vO;gp!.̰WfYv㤿v洪ٌܜ Pe'h*^,XDl*Ai42#i܊Flͧµ,ίWF\4 UY*r&1E '=3CWO^{]x8ٴ?zX ھOG -ʛBw1Oy~[7GZRT($P},8&2 B[f5*KKnm}e6PF64W>0 9ye/ٶljP cɎvg ȒiQ؇iMq::eX1DaPbk 7WC3cvs z+V'xj 9D**[3~Wx̘:k UZF37&Ui!Ӥ+3TEXFy3u 3hpǯ66F!!A;DhQatiBHPX[b$gyXrp!;(pWg3)#PFE)~Q\ >!/F1)^[4GDŽ"JxJO`rߐJl*.eK h*C YXKJ[amIկK6G/~q;n޺^NpA}$@>)UMt;PơqgUZhۇfm= u%<ua ŌκfXY2.Jө`IWeSޣRcUH6D'ގ$Ӳ_bIU!rX6SMX_$<3Z3@WEk cfب +c}֠R\tX FxrИi).[!&4LBQ|JUKв 6NtlS6j~+ɬX㩓p%x%07<-2`@ HdT45A8-u;Zgj7zdi,w"* ;v Z^*kV0;s]e=zZS6S WQ b6.+x%MQJٱ!dV@9s4PEo=mJYȢL'CSOサ =_U3lS~џ"7S ߯ ~؀:` Am^riYI^~ݱTY5`Y:8Bਜ਼vW[M˝ ֫AKCm]SڪGiA _TYSEawv$ E\`Yb|&'`FzhY,F]y&W"xqYZ*?_.'Fh,^4&OX? ݾnY.-sedXSnBۛ؄ hNJV+-Gf|tL2b&Hko|_~eKRuz =phy$:)PJ_'-w_'>NϿ,ٗd*DZ ".9^|GfXKU&Uk]i2qԖ076o^@v'N;ɬ*wͰ56@! *1Z񻵀*uVV#̹YxӾB/ٺbd|d Tc,&`&7ANIϟ5LRxAjU_Y} ߵ#+5l+ot26cW_Wal^_ -,,XW;;`Wy@0Ӗo/:*Յ)Zg29X͗8O@`9.;ѓ0E:YS>ԩST/;M̄C= IMuB`-wLڃ7Rg3G6~C~y"}ff8J(V^[bE~c-~K| O^U઒SwShJ<3X Dz3?2{ +ZŐ2p1:xPzyꆾ+KOfsY~ I 7`mA1$ѹc-}z2z'e ぷ: nKR6=,...י*tv2˹CJF?|yAp\~I'\Z~*ϊl 7_*V` iaG0wf#=*Tb!ݐI}dsYbH\k *X Qo)4lT_({۩xFLe)ʋW!p׺!P]b ~]͞yY&_a*h*۶c#nu(nv:1Kf^uj-0Ö5UIѺm>e4IQY1JP3 YR͒t[rlj;p>!b[SqΥw,]e&#dVa1$ף8wp*6W:9 6 &y; UOdN5Hs5ߠ#$JX2TWK&Ḣ B [mp>: GOXW0Pn&iv^} NêϾAφɎ@•:}dI!e\P[^M66dwH@ik2/*Qy׸!탷)Wbf`8Ӂ ]TiצTlh<3s:O$4m uj'>{$&„2&<Z]r†YW#b$+1eWe$ޛ*Zd*k!Y TaKH"niJP,>إ*"GkAxP X*@9"xI]n@29?l* J89̍ӱilE'("b xOM{y2rkIy3Λ(ϋ@z@Ӻ.+QG_t4076H+Liq9~{*"6σdPs `a O0~5b;/iy -*lLJ2b eZpD2Mγyx \ҵ3)_:o,7E-Ro:sraIasȖ++@bZ1V`6Bh,M)˄ _OndYΖg#dҺ8tՔ0eD-&J'?HJ8[W<} 7' E( JP5gjCOIli;Gf*:8=oNiAs,uɐ?سC[WA:{"/^x禵/G~M_Qg. ^6Sdo!]|%W%&[V#|85J/YVtmLm~0(g?^6*֋oEmM 6Ӓ*fa9.*EmriM*3"|'`=c)|Uw?vH+3 \H'{8D[w:Mz͢CX5*3”i!;i قU_|;هFc:4CĉØ:g>'a<110#jهTd, {|6} CQG*IR",Yub= gw6oA0c\]=pp6NXO_#(b܌J8‘62QAcl ah"K0%4y*Ű"PZ ɖ{9Q`g0Zo!.Ćsxrqi5O(ǿjeWRF/٪(KnTY !9RbN@;FKe9<@uj7?cN>d%ѭd?[x='3؆igIusMLPb lD;T޽_}).b)j~3zTZX>/5ŇXkֺͺxR$6@*b; Z`Ҧf&& (B)2}Ȩ҂ yJCjh㉌ʇ)Ia/eщot 61;Vg0i(gKYEfr,v06"FJm6!+Ri^AN&0˖1K0*Ԃ p"©:V)CM-߷2VVU3p80%i0R%*Zh|Uy1"g]zy;iuJ$䢉`6u#XNY{7$%P n|4:l ⺙Z Rb /DM'6Ѿ~ oډkv*F=H͢zJN)]|~BB}XX(a꘳ۡe^Ws6M7CM7,%*.A5z㏘?}IQbT\PVD2O mZ:1x_eF\o5j XgǟĦCa&]g<"Ubx;!#ڨI1,Cqx?.ͭ0WXo >g]1a!,?;X1ZڑI樅ei\5^'xStԈ$lt"N7[7HdQq_w:Qʬ ; }z[o/Ǧ)UIO'h7ukxas6=55,bT`dn ww q =v'ۿ_B33=iRDHwlDAA&IY\g_Ǎ(2Ӑ6RХJv5xh#߬3F(g>1~,g^ƴAD\O}-ZJ*l{zzAgP\3/XKAJ:>y"%œ6jl5*lW9%6XTM3> ru0V e ueZ7ޅ\BElR<1 u+s,uX`KFAy[;.Oxtr2w`Sw{vHK\6^ɢfSEJh%lLU5a3Rc)Ƿ%f[~Hc^vZRT*t`d]ܗ: NISpx~yyxQYVfH8u zʁeFqVn=EK~JjsyԱIɍ#mΆT:`-(,wc(7;Z6s`6A\\4xq H35Ο}pUuq3QD ]J*PWet3"(_û"O4Or;IF3@;IB5YPRj~$ mo Օ 7=G{wԦZU}x$O݋[ŠWH$,XbCKײR3Vq[PZe`7{ؼc7i X9IYaUȜ~68I_: R%bơY -CKĭbܝ>&Pf ;\HŌiKf(/(@Gw5<M$ gCwb׏+ŜYϗλQ^+T|TPMJO* Vԃⶕ "槮zCTY/j'ߪ?nWXLM/zx;Ķm`x-q[1X (h|mXߐރX^$-P2s58+jf~S<~5Vݽ3'+(wWkn(c߽ }*'u?,q`~ؚ̙Hy}˂_`0\}s6:irڠ&CM*cM)tILJ.aT b)(0,G|.L\|PCl ˺W cMi鄝횑ۤW iJ$Jfܢ^xI}O3*㣒(jȧb1 yyRV%dshL+cb*9LlTbeŌcE¾Z+բ^NLv IY06䶪`~P ɸbu&lIpqAX/ysF|Q9v2dQgQG2X6B̂-JsIu\XSPSXL#pBBDHµF .h CmMhkm3ERd̒>hjSRGO>N}.10d F,_{vFhxEUWSc8:Xc}.Fӈں S (WN%<'Lup4 x<gwf%D'T~O2 C+<i[b:Z`מ=jKC/6l ~퓞8 d'_s(6uzXffs sڱ(kBd PK zTJ-8+L]b{_ߐ PN 񜈷>f`ōUad*փ"<<`L"ucU3Z(0uh.eB nh%ލ^@+zIRY>6ETY(Zf^I1ez޴G|.*n(3ZLx;ϢPVo*?6CI-=RS=-n/-eT`o˦:XVuj[ۧB+SQ*6TW";K(B& XU%9f EdA{~d-hnl)ZDLVT /CP#';'c3lkL:w[׎!Tw ;Ty}ĈD-Gֱzysc&Zހp/ß.nX\4Qu]g|}`c(-)GHx^{U,Ai5'NƳYW:h=LFB-TX=*u319B&IzbJ0ƼiQA"T/Ze4(qKxzVI0{)W5 8h ,^L(6eU2Gw;ZT"[u獵S5ed9s\PʪK4~>NU4'?b^9Nx/bGf-'T_q[ۻʊ Wd}cse;7Gr[y O™_{XЙ(˜h|7 f՗K{S\ӒR梜1˗,ӱo~ܱtT>9AAS[KEՓLu|,^v0D3] Y繹@ed=ckGw@75Fus)( lւR:~"2u=&N@fτ:-l%ũG@b1xlbx$q>XNUf+t,]΀ڙCq@sʔ}U&LJ@?[N"'kc+I.,@ ?Ug@Av&ȉ ju u#b2Ϥ燬օ@!vT~F%m_O?ZImյM Gd }n KXW=7tlvJ .,$#o<^kfA+{*\|}(l#"A hCd.@8U_~O`jk`N&[W"|z \8yEȨ)$WQ5\no~E[ZO3U?0V1c i]'vh̑_ձ2W J˫q&Gn%Cu JTTg<','Q:ƜL=K@m|dyڬmQdv֤ ?wڸ˖.=vGgC i`bWX3*l|AKdtykEߥwm,#VN2+9/ZyT-s#x@554g|R5#;bHl sؓL LK*!|$!yz,gR? qY6 'Mٲ*t)P|^Yi̡M|QsZTiгUh@0рO mNY+ٳYC5hga(H4a*ݞ9<6Ba:Nzn^ P ݇~}-P#3bkEֆiEu qòېDASc'hMS:O!*v3p=%6.NTabލK1u,2aY0j 勍;v4/woEiA|lk?s/K9PAZTrQ81ߧd{0?K7T=<`*֏nTFzX|͈qC;G%7ފ*6!:WЂeg^mCzu0cM,r.E%tNun7aժU$ogL[;P:61}Pq:xM{`cffk #?VO$0( })xϢTY%hj2LJ1onk! .-UM9UZy;2?l'|9 ٴBBrD $#Xl  e7ރBhGwBj"EО7r&=|f-Dk:x899Vv!W2f',"OX%|b' = *,=*/wsOcE}WeU,7AEJ!!*iw[\~ _Q4*=(Xeŵ ] U~C&OS=sx+NfK=l _$/iu#ky\d%7]ص;kGs@Vy܏J+XŲ̺pƐ/eՌ1QQpGjjvُn | :sUa~lwj*OiO=]={`ufΡv|VuJLI"u'%]G:}[Bde,zͬfDjV^_\6hO $5(C74<:`{Uymģ&P)Tl*?&x+!Բ#kɱ႕_;6zNl2 NEaFDu3fG6V?b Yay1UԜU$ t9(Eit wIgWoeeCH$멽#IQQVC^k:vIÃzFBImq<ٷk-Q}\7WA\&UjW`aG6 6z;T>ɇ%זki)uKꡣUMCsk4dV&m0%:Y#&Y4֬b5 If8ξ{Gݽؼi cDfcTF%iЁ\&`y b$UDԓdHVF=E'l # 4kc&wV^3N]uG`mT9tAu5E-ڪ}x)$ >ΧGoݱʘ;iNPt&E0!Ѯ]|fĖ3gMw1ɎjBoh)ɗjTpE[AQ2=A~%Π]aib0oFsmBnvg/cjZC\-Me_H2ANKk/0Ӈ`\j3TR\ n4ꃆt0ֈvFڪhlC|̊c~'c9CŨkBZg;`j!@P+c궰FD$ر(7][$b=J8.`TVva5+i)LjZ+응ž=n)gO(&[u%"A[} ]~灆l4nc.dԕ=W\<|٫w[Tk듈)q =ն=+-)X/PX'*ZKs}k~CXT^v뤼5*McU =T)WKȞ-38w|GWX#+N\߅,AϻR\6heOYشc>ň8hO?d!8~${7_ػ^t cu:i%!h2 u9Y$~(fCKz4PExLnoPJjhVb&>NRk.Cq"st$f{|Xul{ki=96:?`@_OmĺoZm=H1Xv)۵8\˗ʬj$a!(K9"E,PQlX+d79jdu52g-oOCz% &R68v>v~@+ӘЩʿ^r?<'9q3{ ܠ+X(DM 5 iYFUlB XR[zZ)@tTcd)@4"h+5fΚ* ,`ie2hE;͌u}?s 3Y?,!C`I 9`ZΤeF=՗MrfO_ > :t3OE~my;);Ů+i)p9pB|ᱴeޕ 4Ɏ:l̩FI[ߞyLT=mḼ8Tnm1EkgGcQrYIDle|)Tfdo/¶_b0鴃6mdQW";Tb 1 ӇvG "z@o\~'9/<@ M;Qϋh-5>]W뺍d n% MHN>ɘ:|Z*$o 7\#Q?@VLCM<|^S({ u66o>=d *ߩO' ]~k6?|]LwZ*A{Z+rO 0$~~oA M CX2j$3]l~fˋ-vkG K. M3GX/YT0^j5:2RZ.4FfoȈp:sP+'ּ rrq]j.q}#wt獜+ k Xm@ O}0W FjCVKy)|6GwW<ضֳV"kjK{[H4@af6ڊ dDcs sO}Ib<aR]^dUM$<|p#]Bb:He̾F!|+SU=!)҆";X+֛c־>\T ():he]@brMwF@d Z65ucp@&)Ta?_+ t.- EQ;:;Q8$[;!9 5MTXAkR/m7;=|=M&ްu^H=[NທQCLq}STk6!42Kv' 9€٤g_U mc 8әˤ JBL zV5qt*XP*IVc_sϡxT7#"T,^FZ<ށzO h ^֤&I=" Q[w:y #҄/º=I>Lz⊕+D:]%LD_[d!=~|fW(elBP~ n <}'eܒ:RoNMǞOwM1amn'N.W +gYv;sn/Ԡ߶!TOqץ6<-U)]LHѫt mW>(S+E]CgQQW\)M 8I&z d[,/ыNF ܄~%ZUk< j(_#ȚvF?-B%_F>&LDܑ:}dpmCpGu#@4#+ TDəmBs`WHRqaBR %Fx-4Jًhs">6g93,O%⓷ޤ~1]ii\k[ ZJaABG'U̩M/QfUM .y?pgQ_QQ #V=m:`GFm|MI oWA lp5f<i|ӓ+= j>{O.-'SY4C;D/Rf"-㴼U!y&7[H26fiCA(y-Yܩ`QF;h_qP=s ۱/ɇ=mnRs"tb N̬ /peի% d3͗ C%u %@]]QH*\D,dx7mxᠴʽLbo_f:f 7&$L ]hf\mQ e߇Tq,(2YU" 2'l.I˅sn͜{'OHp`C(XXL:*/)/z*lrm Zr2g¨~5V :\-uy-TQan-=F%/ 1{?fמq\8w_mڄ(FIlFEwXNjq$j|˨DR!*2"vJ:{8jl*\7?izTEE fv0vVy4sk`V*?QL3Es~rQThen-b׳AOC4T @Hhn PB)Ee+$PT޶+2+ϙlRzL+k91 ^1*E 蕞|?*\pU<]B+J\$KulZ+ :L`]2o&z]ZSPDs{4i#w)JaT-x77Ξ%mTK Npi#'8"q%6-Ʈ$pH*mA  q ]Ҭm膧)˨'`ՏejP]E#fT`DB4{FvNH&`gj$P;\_@Xgpe'8{{nBQV*`h3i5D[jpWXmmpzY {@k +oO2r%ՌI.(gQCBҽq9J)9;:fַXAW[Z;  5+[)jB1o!Nk"A#q(huhQ]A-YҒY8j ّ(UuupsǪ5_"͒.8MJ7tWUuHfNY.?>$&KsV- KFFu'S wSZ>VZ0!֙#k>5\ZS-KkQN9L\#8P٧39E5mPSa^G:b ۰ց9[9Z@=K \B:,>#[Dc1-|0eY3g}|Az=8o &탉ax'Om=UćG:zձq\UUtTŤpoܚuUult]iY>O9vtjx/!K,Gw$'sZ)Ij&_SM쳙>=b]Q:M1\"HUqE/q}ڂ!ԸOi:iA꾭Pcڸ{ZT)&Y\R&=L~JqKvERr2-0;;U^Q8*Kp w)!GA}T YcZald]f6L$U0^~O=N%#bCk+yPqQu3??NR|ޫ9"Z1#,ۘ04;ӗ̪rpqŖj1~uv6JhD1 LYY۞MjN\~ idl1-t<"dz,>ᱚtrD-^2Ƴ< 𗿢9n\yi;m q![_~eG~ \Na"&5qE'lI;ɬZ;K]h`FFXH8"'ͺ$* Cߟ~z*iGfPEv@ cVI'9,:XqD[~RFҕO_4Wa%ZZp&(v5Gvf:ޫ$jC])eDvM ~U أTttZfUht%EA֨YÚyl8?"=3Al@9 7ah i12pUHӱ)z.|{6q.:Fř |iĢTIWg/dq?q\ `m}eIȤڻ[vsiCoSG`nSut" u,Xi[R'an@Z^6̰͑I#v>)@ݩ=d螥Uo' # ɳ瑕l&myE+(Y+䡝ؼTvwFMʲSt_]6c0UŹtܙm^y+d6S3W.EC̾n2?q׽c(šd߫I].-Ρl"#8ӥ}aHuS71%rSC_higPxj@n5☙֨Gs_~`?}>Jt`Խ""I؉^pk\TF̱ǓO=A{l߷5$;c$>G U%Y k2knJ`jp@^zyT`Y[BFkg#ߟ'5ŵX[iyF|~T"(nW7~+\dpnUۯF{yw$4^Kw֯*U|dc\*V(URzFR%.ϞXz=K^wmH#fMqM=vݷx;y*Jǟ $sg5yv(ƆdX^~r;SMScShKGn *jW<*x9LhC8AOo_YUch^Ev/a[UYi dٷ .~YE%~8/aUo GcoF%8ڋay:nZb0l2NEuUХ*BL8f⼨1Z(XeU5hp'x|dU,kn}Qu WC~df 뛑xFw?(pS.;һbҍ$ tpt.UAf#@IDATޡ᠁P kmC#M kǑYkM# x~C<f2ft`5h?K{^ف u04:g NF}TZ+0]z֖U#Iͱ-tX_0vfH4 \nt88YYI{. pe κʆ_7_?smbjH.Ds[UtI򀫷d]V L}O? ftNpcHH'ؘDnc`p ړh<жvѶʜVGd!8\*|W׍ J{iK+Iw8JX+0F o7/d3Mmwc)jZT.l!N'9 qyf&NO? _WQC+BJqtB,U]):2lŶa㊬ٻL]t1N ؉'䁳Sq20 wc8gR5loWRti&X }>-a=Ok?XϞ }F1 gknck|uPIx/G{FRPspQ Va;%8+F)\:7\_Zc[h<ՍwEf^W1RNs7|úBݺm93 :23@,2ex3*=m"bt6hsoX2|DM Rt[krxS\GyY%HM<-OG Jsx?s<8AieՋ_/:k-I|PZφqR~$!ts&v͚58tM}.'mֆl/ oO;F֛ 238Њ2wԀ{/!<,jK94c.}1L5b aӦؿ} ~63l,a'x߯gTXزN蜅5c3I CZ+fTىa=>ʕ+Zw3B rP9}A\* uaAfvv0eUJW!ĉȟ׻ہ^cWHI΢GHN6M{/,;G,JFXsY_gb|G>PI^Je@ 975":dٳ~f#1@y Xp"< 1`:ې{d$ @<ǿE71+`L,L-BI5T"t*,-{ {HFbTp ~ ]+ `fh ^,1-2n0s ,zX2':P^V"y]'kߛh,9S o<s@IYLrfʎh# ،9)ǘZYuP!@Y*X^3gP&hE J~FdSu17ߐx*m3H24Ї |~_]?c \<6q*du63 W uD u*yA[tKIἊ ᣯ &m9_gVaִXig8*Zk3\lX&8pdP}{v0GLPpo2R1SajZa]zaa7n@m~5vf&WgsaI"4(ʳzh `iA${O $/ke-ؽu;(Sk#UIy%wN5[~~>>9afFvmw%| JIp=nA)8z; ^҆E-RƪjI631d-m9*[KۄVFߴ gŠ4U܌9eNRiG'[G|0{Ge^m6{GBK;V=IwhZ“a#'n[ ~垀={=N`ZtZb6!Ÿ:kJ~5,t6Um*?n!!?:[67RF ϻiż^4)]<8oʟ٨UـfΊ1'_Ep LjqdjiGl vum+%㓨mG"  (mBfiYo >ޚHM͇1k|r L,6t2@I?'_mTwd֣-B1'7ѴC^ LK姑.&M'綠qKy^&S5);dwE7nX %&Y#@wz qiѫ"h5`+\\ bX?06Fq%Aaע)`jj.]"Ȫobl x[mAUc hN:T!kk" fհi6W>I,w{هobނq)8t|C(X#uAm!+XYYxXT{qÆC`il~i<EEE@c50='?$;DiNAetg]Ze+s 1uu<#n1ѧ:3WHˍGn:^0SiVMڊUa1/hvw!C>-0&{_`ֻ1amɛ0PU_a3*s !wzttTr{U^F[@9t-_#*vД9 zh/P^MUX ؜"ij>o361.#BZr.![ e䤧yyoeƻ/ A 3p:o?y*VWE ŦሗjWeӎO%tΕօ˹\;ۚH ~=7ͣr>u+UZ"ԢWX ]SJd`bT8P Pru1V$pbV|J7rJZG\C+iwXClSc(妸_|/{-ou C\XlWDQ;OOuEesǺ-[ĹJGUxǏ#*vo-)#ކV ػưXϴ̩47ӄY?i,O樞}O: w7⎛oğp7׫{~vGJ[55־<>|7d×hd ϴ h1ԁJZ|5*G2ukc-t4%mFz@_#ibeH'M(,dHpHOF~v.Z uחnKECITD)PIUݬy^ӂĄT\tIbV҃y} ]٫g=C[ؼLZ|kKH4k 7) %p_c.[{k\^0"*pvcj}M!-^ի.>tUpKRG5mMPYQFa5L%fBUTr )~Fё i| T ǧ$q_01v{hKؕT5%ۀ}8Z suvB[1HŌ a˼Fx>mAva :yJKp(2} ơX1rHZudif2BSE$n]47ifj;s}, D[C 3={4 ~y)@GKg{͞fV* ]Ն Zʳ.r@o.] vi,0]WK=KCr2nb#Pƾ$ikKSdgSF4QLJ@@j .{*Tbb&d/iR GOs9X>ǎW* @&~voۀxH -/+(3{~GYŞ!*VŲvUOSiT]t3PlfS9b 75v<I[H{]>}1}!QoV#I}8p騠7:ھ퓷Zm~X{>TtƤYCvdL_bZ|# lOY|\~<ҙ6C6?\6 X6i{]`?yl/NLA@KrBETNs"Ut,& _oƼ%^%b!ǚ?/X" qM7sc7?&*`zPqC#٩qtwqk-hi` 2xG:,iFP/2R>ܨT Qb3.Ajږ_1ց>1mHm$4#1`hj ڽ;pdgu!ra4Xd5F[VJ"9@O;-čYo^*9'C=uU(JFK;`xW@ o< O7r6WH;Dkd]ҕ+|'+Է(An۩Rg܆.8T6jLZ2.?Nӏ/a仇bd-MX #,`VXn/et73usҳF̃,j*u*AoQ1.jK;,ݼPE U?(/Xt,\z؀3f~=mfIeBwqǔ<STr3ǙẒe=,&#O _|ɜշطM7?|WiƱ=yUY= -s^,{ `ŗ6*o 厢?IC-`/<m^,ʼnf=tlV-;zгS\])sմHO%A V߱w.un a]> ~6v:dŤ,4yu]d,Vd@q# ֑W}e_IpHVloǖ/֊]$Egp:#X6<Of D؄njn*93hwEQ<8sW-'Ų^Q%M֮|ҳD&=/.=8ܽ$wVsWM[g"8ԖWq;Zg8s8^bhQ~Y3H]taPGɵU/V7sP1XgZVVڬ5𐍯XץA<.GzNQ ]S5i+:l{!])LG A͜= su!{dٚcNs|xYJ`Ѯ-XJi=UUΊ6l[1ٳEa'l@ĸbC >zի^孿cɵ.G#hlkkBĘ\{fCQ ca,却dI >>m@r E,DJ—֧i9RF`T `c`p˄Mjo- C˔49-Rn* SG6^[z7 rKʻLhkfA}2%faJ^z̡ov`$bU НIς j,2u2uE,xިjQهtt (z*TTHꅲjj Ю$mlK`i;Qx6y7R<$A0?0LZYW iJ,3]}H0O؃QP8?A@8#Gツ=d1_ZaM޸s-,BY47-PnS`WT1jR L 1%)@*V&8Kwʵ6a1ފ$ww :sv]Cv<mUa2Zg]0j%Su{;u m$Qr*o_'elJ⏋'|Grc}=Ӽ`gV"C7LCca<^nd`fX݃_*gBEˡ ?`9Fdx&3#jm3 Fia͘HM 9WfіAҍ|LZyfL]׮G ,$[i^,o.8\}mtd0oW6l~tcMHQ=/XI_B@d1}Jz6=#hH`EfCA??v̻wA.ɿ؀+Xs PS@[箢Ɩ6O=dQ`ABW٫LN+;$T1Tԙ% gc͖qYDP?*7,{[LN߫^Q.ewJx7Z>WuȾ)V>*`\%HYֿﺕ.F-vA ]8e:Ҳ4mW'Ú-$_ۀTְo{ony&^$DB.uU]3 "E I~vpja6tHR:2Zݴg)4,Rai@;V h7@MPKCM&(Hؽsdi'<)Jzb}#ۆzO^  ۛ9٣zT7AOe-%"*ʴsSozsN =i*( ׵v]uok/HHH's{8+o~{ܹ3̝;>99 mzk('M% D'tX1Ij,F^&$T+}=BArpchoBnӘkisNzj B@1 Pτ9Gc)g8&aꎃ#VHwcY$j(.0נ1:;&g݇soNg5[ي_oc4kAnQ] .큺>zT^wUm",:LB{U% E ʯw4QZΙFQ @Cs'&M  LH$ KL)Ӿں25UǚY(*Ȁ Vְj6f0}REpsU._~z4aaªSXE,~ꥭdOAK^7aADKhm#+f;UpL"$*Cn"e+v; t Qku-M\MkbJxKk\ϵ˙/gd?sfLIx$>A݀)<4Y TOY.bh ۯ\)X 4㽷9 =j)VE97L2uM Ǫǟem)맇>./$ P24ԗ0a{mxstF!'yQ0:jiQcvx zLuD~\1%l 24%Rw 99AC?9 E@* s!$䐆I|!Vs[]zf|24ț)"4d%VqP/sM}O>儆7^n3uVyZ 4܃FdEG<$OSS W]]q`\2mW'}$V p&[- /oe఼ޱ`GXjMٮo AAq#*P"> 6FdRǑbIJ釉vV9: u֌A\#(~w2 Gz,ί1*fe]?Y(˟n \)S^ct Zbgu庫ñ 4^YNVRn&9ILxtPj޼0E~w!}ܼG[Fx`5ߡ_Ÿw*ƚ!.ht+ ]jܠIg6Go&&Y]huV\T"&D&N?_'y՜?#4(xEKȏ?SV=t'QA0D )id}zϤܦ%m*k)lC8E~f"BcRb JJ (܂nоUJE_B8󇿈O8O'a=VJsz:b2lw5,zTZ;5`6y&tm?a=1^MώN8RJy1$;'Ht\2EI MWj*DpcuC!V>=Vy+/uLb o^@*l UT]Hˌ-cvc_|) ŏfs#0it%Gy]7~p♜_C<8-\&\S9>Ɇ/$/epL m m9eP@Sg: ҧ=$ 1nW,'䆇dg2$SW#>nͬ{E_Jb$/x*NT :ay;ujwg"8ԒkGe(ίƱSTtQ*X] G/G5SI& CyfI$>F Uզa3ՈL(`ZD L< Q1'hA:WaӮosWF9յM503]늊YMLYaڦXtl6PfĿuu*ެ^4F ??oV7ҧD-p%g(!E 80r `k}4&ɐE7MCIlǁQTQŠ^:y ;c<++P* kIU2FJ1c.8Μ(ժq}̭$bJC{& v`\q/YlOZ` h3m*a#'Zt!ɂUu=bnԼB%B yB9 ,ĊF}S'H-mGYENGeu&Tl/AGUcVpv11'`"pd1nr(-1#QH\xUTnǞ1$HrƠET+ͯCX5IRkꬡ- ӻO塸voG>U("nUU=N~0f壒BN vkA5ύ_K/4kms 0G1m*@-((D[q"AVԷBgMxOR]<*|Ei9 X77Z2DNf&* S=m6P5G S`xw?ooSQn/]%V藐V/{ee8"Л#)sn f2W3dUhsK}t@ v7֘z&NVjqe1vY3F(;{%8_/^}Lψ:&(@/Ev#N]nJP] M)ԯaؚ jࠏ, Z~?-=G1֕ҔXxT4/-Ifxi:)^+UQ*VN /¬IFઘD$/gCFdop fe+*8J#%޲ CU>>Ǜ鱗3 }| icB G(1Htp2~QTEΆ/9`m?I pO\ŠՕ"`YnCz U+ksIޙ?wP~dXk+᳏0}3__% 0?￧_=*u4z^|%b&C[Y3s;1! D~TKO9V/)6x_Ĥepe&z51qrVϡO NI Ճ27AOP_[\ UL5 ,"] %I. 3,RRfoz #7>DŽ:PmjYg"dwuUÎ=I߂v. 2p6ueB)U\^Ӈvr5ٗ[(BzU+^z5~/a7aːA%"LwTL &p\{Yu}ԏ+/`Xbސ2RBɛ8Z+񞟑v|OTiY۹^fx#4t2 .<}Fdw{څk?AFJ2s7_cJ٠YqFЏU [㵽}=9-$$_cCuNS Eyʤ^ZXűG~za}(~8sZcSE?ݻs3cYX]fͯ`/VTFU0?cbr4La8N  iҟ*NSN1eߏȣ֏c288IJ$묏_Hg-sg> bPXK1.I Z,3V\thO(oZ-{x-I`ySmXL43i6oفSY`5WH> TT#ܐp(Muh+AqQ=C I1IY$pzCe즨fgՐs%f A"Sa# E+QKv=YŪӹ5s ۚ񫅅 9\,F^'@L([K֪aÎGuQ1耤bfd.YEWcf VSzל$P '@CX*HzC"u۷m;P8UP2_hK( lT3!lM@e[ukF6@ݩDښ$f@JwOS\*q}3MG,]AyV[J-٨MIb I;ru6A#uv#FEu$ Ik`tR>Ҕus8IUFT%pW1X8}"2ڑ4`-s͜fcoG }'ћ=82ba{/"1vzI-clPJfwOe 6i3&566,K)̍id fM X %shRR^| хVLRYZC<êE,?u:1ur s"Ep=ƚE/ +qjuȬEoS!tM߭Đs|P6뭼XuYo4ʴ4U8 tA\#ǫp%K"~m*Ո*:EIZ{yCQ:O60bGҋ8i*&m`; dݾIJJ ~!5{L oӰHwM6((Ϸg&z`X*Gk,d:{)U1_i.9b{~) kmmjk**d%fbpwdt`D|,u@IDAT:$ӫtd+5AA3c9אM {sd4*#,$ _,Z<ǎ<\ȐCY|, b =֨ÑH&H1sr7<]t6H!sG"2@"7a;Yε H*VtX&u;_A77 `ˊωs†^[Q"Ҙ+b21~/5DOt.M /Mv&>;woǛ}B\5pڡmMiF ="CUH_G̘*0!p+m1ϰ ; B|YfrKX⇸"1%PZD]{$Fž΀k k hw%CULYZ_/+]p<9[nǺOסV 6ƴ&99ZWUUU0M%g_y?¯)Nr,\JXOa[ tGǥ❏c뾇{Zw  WzՎLJm|@Xz߯2OEa: Lݡc"2Y9dd$AZ wkoO?J?\*)0lL&YЕOzϏBEi=i$J}C>M{zӓfɅ{VD5v^F AHewY]*fI#GhӵcgbGcc(.ɅAG߀C>J^hwl 54lY/crFr"%~zOTYr+ի  Tw 9 /ʂ ,9\ä.dկ`l*NkSR_W~H ya 短o߽'LXJֳ;ގ[Nsf]G.c_DBfK[(9HZQHkց-19=>?ի>r;GgPKpoo',s v0+7 \YjFV>U*W+1?>m'*ˤd?1dmRES#!{|)ms(.5Ul5TR6`W)xF]-h+~| vf"hg Z>' i9`ڜxGDkb?Ԅ,L!!#9X4;o[=@b TE#4˔õ"flk7x'jd5R D[C -(KгA_$S\C*0eNݖѣB7hGZ=cK(㵖d}m NDݓ)c>x1誯b %LYXJ`1sYػ` Z7 *F3 +N/TuAܹ. @xg5ЁVBVFΘ=fZH)wh3x!s b9ĜlT㶕#m&Z^T)!A<;ə(&lmU+&$F޲Si_;SmP6ga^:Ռ*3YYMV%֎$ҿ1uAVMWЊ }U$I̜2(U w'3v 8h<.{gH=fy v㇨T6lˊSmͱh#RIU<:j-)z'z;Ĺ'ы-A[u1fMj@q +-FT$_±7k6;OMDaN(M\?EH3|+cK]bq \NC-&*]oA:r 7bqx=# Z2H:V3 \@2W~3h3RI)ٛxNyUXx D'$7{GiZbJJLLQ Sb*m4:}ZER4'4ZfN< WmR@!"67'5lVy=ll2x # decoDJJ >_!iM)ڲ\>Oj)N ;퐍^AiRbV*ۨE[2rD2J2R+9U% LԔƔ^n.|ҾߴSyjdD29zF~lm ӴiC ׈C($7Kn[1>pv̓;J s06tIC'xVP 9(g/t66DĬYȯGM J=Нyor=,'y^X837 .$~d#+zqih,Ʉ3j) uEXp"W5k{4LūoK/p7EjF:Jxӵp@Ǫz&6GW*# )Eۺ;*=dG@OQ`,=gƩ#д΄ 6scPA r{K+-+_ #V ? pu8z D221CI ^^# =Gzd欒֜z[ӛU VңwmbRFEeGy%9 oW `,O:C[ Yoj<_sveJsW]'AA!38{|hb!Mj/6mIHln{;PaTUݽAz$1kEQy2sW%bhUl';$ * u,U' WͽE~@>Gǫro|UwK(+Q51m9'1Aʀ)_чIRޗXǣpwp9SQ.9;Zht7WG#9 8TD^C§bvh&/̤TWT&=HN`kI.%n z>x[{\tȣSJE'to:e,G_oOg? c+_g,?DNJ ۚs|iܵ<`maD`Uɀ8.?pR򔞡)bʺMAyc'JXHb-Anz{D[8",8@+ݔ hV4jQ޹~M=AxM+Z`J+͹L,)QDb$$!<nn_~lJVӉD$ɷ}ܦG/=ku4jSyxY(mf*`ؓ_ q)]RWRpre)7FK vo-kO/kģhya#b~X/doX~Y56h ł7@E#JPModҶ$CxjQ-iJ&ռ8Yxd&LjF1j{ĶkHrґD&,]h\YH!\Oֱf̛Prc.5%\Xkԃ-5CQe-0 J kUa) Blr)n[I+,^4o[+^n[@Id)|$Iߏ䘃r*@#?8/oҋȑϤg>{'= {ܖFYںXQjե lkeU^'`}j@euq1xz:(T HʧTx| ͐ -CQ}< Wslj-)9Yy>Mu<_?nJG;Z_}]0? Jz$+mwTew}_ƺ8z˜VxK,I'{u$̘-BÆv+? 0t},<S9 3'90bbcz^?&s^D:`'b 3kK8ذ~Y8g'L Vَ _8/71|}w9~c}:xY.h~,<)*zjbA%NL0}ܧ/}/~OJ$ U>fOJT O>!H&رcBоڸSMk>l𴳹rx)Iޖ-XyXB^~&F}w?R `2h9J1rVob._y.^z".F}".B)i|6߻r>ת-_[Ux Eo/m^.._zQVqE''QÂ.cWD}\t΄Z8u)-sn^q? Z EĜ$G'y>w 3Uc*ڄ` S&1q9-qʰ%sA ib7s9w6V`G$ QNT \><1b X?mš;"H%ZZ2}[YA> NHJMV?+h&$jP#y[Si gWw0"F4aK|(YkIG|8Ց5g-=:F20@sfF:Rp,>Mʍamr:%,&N&<:PϠ5 'Fc̝܋8dW T-X]r`a9R5a-:[WsgU9OZ@T;Kh$tΒ۠.AՏC)J(¸݀NTp=?ϿV˘ 5]0wCyº=ш&/޼ MɓQ[\ 7_/VHff&@ 7hS1>3kCq&(wL8&p%O{fm,q9AuW!%eRhA5Lp;-Š&h+ՁĹiﷆӠ:fџwDbs; /J4Z˞fD0 \9UKJj+B{?g#H5qmv}M7Ʋ:*45J,mMC[?d`zy_/<_zkF:4mZ閵hz&?#;4>xg|-ܵ9v—A!ej 3ȢtּP J5T>y}8S? J^`ͧѵ)+YF7$hdugU ~@ $WS<0(dGӓeļsk"%vPnm !#V'Q%"Hq9b*ǻ+\ԉH|ף_X+Lz#zrkiiCBZ[UNxS6DägMuJ .k?˼i1ob `(n]C5{#>JQ`UedZX9~?xjiÚQSKPՈu}Atwh>v(f_%ÒS6Ǜ';Q-M2ǵfъ@*~Mf쒘x-&ݰsx< }?c;vb]|N֨PAY^ _;t梛d ocV$%9ARJ;ݼJ:4l}yX KyxVx.ЙF(zo:Ix=:Cј7klErM:$1Y>1.mnA5! ?y?zL9i5d2n}YWgd% {὏?6Ib@&šh֢=|(Ť9xo-X9akFB#}"^M["5 P^E-g̈́}3-8 )0"7F1 :̈́F4Qvʤ(CnA֪rާo?}x|e7+7OPKL5 TWp8e 8>UH-t Jd)#ɱKpxVN; S:oohߌ 6+ b2zi F%87eIoqz:%qkv1ckъYY$ٳi9QY~5Dd[$݋T66%,t3p(*KHUmmj2Ҳ%UV$j7z]b 33-GTA`%>+Ɵ*Q$kR9T}$޳61r?GǻM60#m,rS6GGDR1,a±-CU!r򋐲w; N?<ܐAYICraG4ƬEk)'ࡣxW`G`jtZ;0iTz{v0z.~hׅ>ɴ5m匎M]1؅ 5XaiFޘS hjc @7!~@ PLSv 35 Tӧ=Q h;SXFhjюA c۴ T?Rh$} `/1.UaldNUS$$pME-*jyoV' F[26{TƤM0Ez6}a#ngg-ߵ^Vj26pYR2N1nD1=jCi{+ "19<7CA1V[RX-xӪ_?؋ j j{dB2Jf1F׷q$ o_b0/U-HE+54uiPU=>K[VT1k-N:ӿT ~N|!c8\Q 󯵱 ۷PLEuy7q#@MajU5}yDD=R:ZSQcgv"ժ6&ܲ>jj!#7:1*{}xCIEa#bTQAޚR3nS1S>]TE$``O0njn L H&t?ڨ5.|DW-瘢*լn}'Ѭ"Xu^\H٧P(ZەrY ^2IEޔO6ykki7S;^%rz}G?wg~߿+Y6,/@H |CLD(fu3qȀjB:9KvB'XKc-UE78+,ċW#g%԰ceg`߲S8[\4{yhsKm<<|Y:\G2en5b[m}Ę\̋rD }4ZLM䞓NPJ0-=R’vc5:d_<sQ@_#C0}ѫ_oZLI23zhFxM!j@sph+JWOPlΞ25_01@*ɓBpObʿп5v @کè,DeCy6DZzt[go(!4o0rBxL_gkeZxrR814Nl#̅=>鋖l>G1SeM&$=,H9V $w_׊{aԴ?kա3 | ;)G6yPڸB)hQQ) 8 <60$[<,Pˁ{bqXMLn&9`"SW1؊u Y 'PZش&';(Ä$#Vr \ qCj NoR&di<7TWI;r9Gϼͫ7- w@׎L|NZdd̆ +Zx.ywPw¸gУY^uv7IA-6m'[o&<QJoZ4WV df R*RVclm<i)I:]zdˍUΊ&~~ntvgCv^x`E#i%I(qmci]EOG7O&(9 koC JpT~+z<ו $~C)t(l.^~ bcbVk2?<6z*Fc_վg;^X'SJ9b%\eUad`Gݮ6Zсm'xb ]Z$8-i|$ƭ X%u-[[/$UZ"_s~q Un8 )/'?uJ4_;__~.X\^-<1|}V3z5s9.-8 wVMꢩׄ猊qW%Y5`TMTԠwKIhnƴ֯7AA( Ϲ t?N%!68 Jc{f:zg oJa\'&![%,]LP\KZm*'Qj 8v=yTd`{&_; .NHb7aVcuw@yv@ ,*BJ%;©2Vpjb;H8J$B"1Ay1Afфt>F"OFK:9>e Ful= Cz2s8 7y- J$'~/6(f_ 4:`ŪnM%<yTRjAηjRx3;yjSI$`E!&@X4 Rbm"O๙|2N va Oc B0auC(eN Ƕ66CJ>ٟ>^#(m c9ϫlVIQ2ҦlM+"t(^-EnBUxYPƸY$eU?+n{~/T [(w#R-H; `M:䊳.)(*҇ۢe4cbMjxWP\3%z/YSբq uY!jAM&A&Hì;?M&=gj ׂ;OšrO aa%yl_^?wfdτRboPQZJMHk[CxsUQ V&;&jnjbU+bbʔ 赟R] \tP'߆+zp74cXyc8;؜vXՏ_| CF}^ <u I&Q*G9DTdwL+9@hʛ;qv[3YA],Jcvb֌Yg9GCOG ,=_s5;/oY6*MȂ 53/Kr}6 ttΗܵuwK exI˕<(sןwA6Ҙ6m5%bp]QZ`;Ff NDpsPUrP(nתIkРZmJmGj"P6s͙ Tl.COKU`~3"yy3oտ?Ww1Vql$쯐S5f"_^X OA4D:(*ˀr=cpV\ xO?ԺJQW;/x>u ;6QX^pD7ݛ qmLX ^CeM :kѯA9Hmm (mgI_Μ(JFS^8dSTyRrw`M>gJ*W RǷ~c,YGӌIVa5k0Gɦ0 ^ {c0I G&0Q<3VtlN %W i+H<ŝwA}~<'@iTC@$IzXA rm,H4ߧwy'I֔qkW%X#SQK ̉%|(X;|Mm?x܇PQKtk1*z1w?@UW-N SU|Ey]'\ݜYTq< *Be.Fƚhդݏ9D ke;NfV2^SFo Am*"U7L= wm'.--QދrŊDz=k)Mf̌3ByB>+ڠeoō!?j3}2q= gzWk1R] W[J:7,Wf̋PrAti3'ƞ _Lf 7eGyJrǵ }2tƍl#%'d VrAj%'0u \hvR)BϘ73kr̝:uye%,iyitVb:9<!>4,)>mή:v V`JmĞؓYl`d)HL{zId;c<UQ)7-H=%I[=d0 Ei*TګQ_!IŖbɏgxb`OC1c\{ʈ~\ċM7 =7~gW4Y G_c^sm` >`FVG?J ERIY]8e*,K#>7J0:#M*; 2{mGu$~&ڪlb~eFY1"fcߜyBJ5"=|@L= c3 ^Ɠ>Ck4^XDVQQIF8<|5}Ph)ZhcaOOmr&Vc ;4YsACgl V,#7+^3g俐TUI^!D KQeBiQYQi-aD+|\O3g BN>n۲aGVPбӋHZ,) ozh$QU ,c&֯]x}=~QhL\/U8&1!^>xCl%L]2]|e~7^I'AB/RD@bvv==ޝ]v *]z5${{މBHB@Pfgvvfvv}O[J(55Y5PJ>:3kv}ߢsfb"O*NDRP(IdlXq9޲gX$|zPj/<='A\EFPTedM':v` ZFT#$=":m6 2X1KUrm:pZ@IDAT bnZZ}=Q@o^^iBOݐǬ直YS'#3=䅌<+~x7y"OŐPw:2E02%.6{ۑC5o *fg S JB5{t4ҽ<$+k13" QTbD^H57ۊy!Ԝ"u ] }cDHWK+?C]^y3NO;p:$A"z[ZDVrdj*9SIl74=t!\V̈(3d&v M2fcH3hVi9'‚P aޠ H1:$ : ޝ8s]ظDdT 8xo1iHrdCZ~>-KyT͍ 018%:#͟zb `9|c"F4:k`Ut)M*!o=Դ ^ Lq-P)E1E  ɩ0w6O߻=\V@C2IkA=FzPaA@b;jz:ac >PiF$g =G=m x![8:vdҍt{aJTu$Uzer]yC$Db]bFX<Evvg_ʞտSjAo_6tL;"O q$kp; Ep)*,`A5oōk@.;P;|xhlMfh yz$I *T+OX;fJ4(K \yE%^Ϭ'S=@ n㍌xAMM7E P{fH+<aT9Zv# 9 uxC lkW.etxMX5z6_x Ęa'@J>25tٗ}Ks)Km$53<ҒD?`\TI|B4%pU pu,U,Cx:f`݀,'Zi*lh_sFy9!ME`xE!<=sYX]v2q/PBE&B+Wkr͏?fĊ;j FViӽ EHK-pr$2 g47V,zaOg7( H3[Uz@~:Ωwݶ \Qv3.m06ns).YEmߟVE!*tQ4'`j ӳ H omPU+{TՔ9"U@W3${~QO#N1k0ye:4_1 VrhgyVUjDUHqwkԌPTgIA? j fZ 9L=Օ6 <,W={)lFyu_+1!%U0P5D+'=~$gI TgbSH;Nc_@+\4кRAE<^d6ʊ,dT66Z5.R^Gzi)\sRGU ;톆4=^HKjӆ\D'e՚ i;0q# Y[ oK[d׵<(De*)VZ.ƽ#\oV܆jsz hѾ}WPz>svm8WU'Qy<^ZpF}O^.*==Q%0=srF] `'eւIfhB(<+PƌT:j 餬 4W#˘}czq:!.}X0#.CD4GG7OG:գ8GN!K>!pA2k5u&lwo~h[6I/_6}|Rs}tyځ\EP Zu ٴ糒>\PnEuC5l!)Ts`eGsK"ɧ².2%];,د`5|jp;3֗ [c kn7o eAr6;/㑇q",6Vd|`u-6d7[~8wqVT LdO`Wjy0T1nbb~?PS`s6ny;6RbD==~Y4"9fj0b>礱FZ%%`0**"c9Z[Z$W,ˈW%h\qN6ޭ[x_}  ;01h&݊}w~[>| 6Nշaxe/ЪְU4} ]  x?ƌ6<&SHHj-,$v,G{jT-''>-T6t8 @?}-6nۆbi08:?F%plIxQSۆ+cuֳ0AwodL[{oR!,MNjeX_ֶN_#)XsshmT+MCZr,qa(*>Ԃ[nt=Xd  U5ѳU}vʊC ,(r ,Nn,nG#@.A<2̘Mic ֎+QĔ>fPovO0̃1꩐=t~U ٭R֭B&I?'KgLGMt;Yac's;+={A *qS#pZ!6Q}.YlCœ47'%()HE6t,bO'mE1iMՐ?+4mA#;Fdm$RO9c9RBN{wmDF8wy.ZcyOIrb"Y+nᳮ\Ua@I\l(cZB C+A4i,4C"$gMM*Z[1 2xn=‘I*mk@p͆_n4$p16xs 6L$j2DdHN^@kWe޿K)07D$aM 5Gt7gK6}*GF`Hߍ?ف ~A^h;!t#J4cedc*Pilb OF|z1 3} =T(#""mJjZR'-8V+'\\Eע<|R_љmccGq:. z 2oJjMt$U߾fv.ttxg":ᦢ:Ն$gzACnq}c$,c]5:i,tf'bckcn'H&"rrR؅l5v8K (tRlC^ЩIdvR1k#h"GV>ߨpmGeg94 ,w\֡MB-' 4V؉I96 mD5ػ}72i1״U=/@R4w1-Y!0Q'ϱ#s4Ì;>JWNŁ̟m (>Mjw/`df_DZ)2ȢnyZmT Khp8RlYM{F4 /6zgͰkZfy.uڨQҢ'_4uN+IY˜7X/H;Z @pr+;7z |BYްK\qjsD9!!a|sʸR7oFXm`s@mђL}TZR1 Y`{=}Ap+y0'/=~l "i)٭5ML678}d _XQt3E.PNY5Q +z2〱n؉_ZE;62K,'E#+5s00fp2AYfZ3#]ӦK;;e}w=Y=W$?[릏߆>YV%:d_i AOvէ62%2h,IVhNI o@ N ;~ oSx_xL;sMn"CcuhUG"=ZIEz 8XaN$zjw#*Xiw!X:Ud Mښk' Dr;30<$\{LZ6P-t"hxUʷ?hgNRw|$ֈe_ʑ93i ض|cT(^JK$t^_<ՍEtmy/SdgeE,'`:TYhP `9*-b%շp0 KX>t!Z)gmYg-Z!b$Մ$% 7=<nfK kpTPƼ(|soi_>Jt R*;#.,̌[rID1`A}D8k8|%oiT[d?~*bⵝO{vC[K6*HĘPL+J$_ ua_]ih[d1IctsSs"{ނW$9裏 ^+ BJHC?S|t桳o%PUUˁG(?7C0=|˝Dܑ .XP(-l#Q9YJ5\%]xv5YY)=%F&p vְDRQTRZTQiYe'@[HU1H(hš \i!O"-#wEhFE؛U g%ec:slLdZ$BL!b]-K^ q,d`df2*EJ"\IYR Aum shF ԒJEeuk6Ņg:<5V@ kTez*Ʈ~:1#d?#X:ۨbMsI A=*OERJzZ^2:AuQ-Yzp6튕q&%QxzT]׌ʺ#y$8|8i.3ڜO%ai.p%hhC`;cocl2DmE\GXƇc^x`*Nv懟Nѐ›j*/;qtAܭqdf- 2--fԦA.b>2B߉%򊩂#ZZ<:k2}3|b27I[C =*dT+f vsoE`@@N1%> Y,TB|^QVkvtO>y pr &rGh\Z.N5s-͑iN`dQI{yg_$n++`KPW ^ @"g2a**\XaA;d [#5 *hVر1"՚;~>BS2t)ÙivHy m`jBb\^yض{x/a}5 m$S:%w>=H3ie{/*؁x#1%.fNjoIU5 zT%6qޚ 2q0Zf4wMc].'Get=om;ΆP U E+kN ~RrR^|q5]}o"ܕmT {mm ,'Ȥ[\DZs ٍ,,B:w^{N*Y<5-ERV݌M-نJZh?~wc˗ʴCaTZ]_($6 wr9l^88!i30' a7aQ=)a<F{:QdɖC=^fL2k!ê,bҵ,(&w<CXfz!'X_I<13g/ i:i xR#Hf:$~(z T33]4ji|SIM$X %m ͧ)mJB yb7GgX؏9Ȫ:)]cnJ 9/-9s; rȨ8HS!,&y)nɓhlR ߌZ+* ֺ06C| GgZ*Q_SS {̧k˔hjڝ0W6mv$+Yԇ$jb]˖ćT*E߿˓ipM$D!a|((Tj>uQ~ g[du * +' VZ0ZY:0KC1 v-*WP_h8u`TSeHB=T0OOtAge:4dhheٵ駡Ѓ"@avNT%7@M?Sbΐmg{c0VX:X"=jȰnO6Zk &! fXH2ŌI.tu( =uhے<\źEN7d"*Z:! k2uTZ9HQl& EutqŶ71VmhhP[YkelǸa1҆/g[h;L7#7(dĺsUH;~@ʜmVw0O-&/XZŭM~}+k es({?kN[7^~9Ϗ'xwH==΄쀷o06} dM Md h $D nnŎoc\oBdt,>rz "z/j9}6l| TcR!ۅ^ 6`ᩍWϜD[TroD5B$̕oK,n>*`nO!NJX8 ٘5k Aׯ;ibg:MOdu+"*!XQ~+WH! !JNOV57,Pf^T_BécDnq3xg8i1e(EVh꒬܇r\x Yl{XhOǍH禛J1V#S6sϣ@~׏3OJRѦU|’ՀN pjJT gZJe#;CB"hlYg5iko!#))"l5Oއ=8=DgKu#M)!g6Ṇ ٖN\o&I$NBvq=1 0S8tu]]QX-a{a \KaAЯyBmT2֜.IBXc݁i >5z0uUAX1b?@I?j/xxfR ؗzYeTW]AmX#2dpAu{3iP#u^rT7ٹJƮ'0w4 V&jCn{r]$'&_92s [A7k hha6.Aq)FDng9S6DSu4Kl Hhhh~iC'f"v̛B BcH5aq'\yTuxgfJWc_kaߧ4)bEs=6}g#u#cB wk o<i̕Jb"h!Pۮs>AP/2$P pm)Ec|&X jɧ=ċ6pprrcȠE5^$ Җ>ڸ2Jwp3m-TݖBۓEDd.gbotC֎:X>xY6@m 0̵6Çzz,VLVo݂عy琓y"TaDfZ GxdoGPͼq8ݏaq4 Ȃߦ7NP&vصg/󗭗@K C?ǂ--*}{y`*;&F= IuE:&Fd!2p7qgaS>%+82w)3xC5BqS%?-O,d`kLpRs|Ư*cD9=sVɓ}:Z;X)V^**)V+gv憵S̠rO`_Y(,mm̍`f~A|%nWj5-:){ e0uvl߆7yiغZs%Uּ>XWu5ϫG_yUDvحlJ4>oŠ[F&;xWÃvUխ{enqd;m8y|86Ws3 n@L Ʊ*<^:@F豃11-mÛcǎ#٨̧7q`T+QV;.[8y"v% zO+(ZL5 A1:I/ACM%\ZEͫ ADBP((xv#Z6t(XXfj<_I|~5 EE?|ZO9hOUea>2RA%7%lѫBA=|Jft_GY׽f_,ז][ (aQǺur;9 պc8u-(on#> f$٘٬_ʻȠw`FX\}~~jέxEuPДs))!رz9]:ȂVfO 3 Zp!{ޡjV^eeHȤק_DFNaɍk0;(`T5Ld~DFc*-";hg7@3v+/< xu8mk_#Zb슚B4In*dwߩJ'mTY /':toE?J%ֿxE\rUX{z%PEWئ6/T6'^#gL!ջFi+V`/$t]_&j "Cu(V;T1+Ų`:(blg4l$D8W4&>Bc¡_Ft1b倪mebX8n?&>}@©Kyϵ2 **ՖQ Y $ >l歂9tLm5b]yit#G]:;:&켂-}\w_C)DLb3e[` 9JӞf̒BKIA} ӆk]It"ܲ"H2=XF9گ!ʛ'Her=36SRRi(-MI%)zCW"e-EejfZtML IsPϱ#g ♣ZVWgsew46({|˺|?b'pn6(j㹬ߊbQԄfsL%@oCGc;Ke-ŕ߮}Z˶s.Y"s KǑB*k<5 wo .'꭭$1$VL-u~ )gdDS_3TpUݻ >> 9mȋ< y~ F-XԘAaJn'ݎZGbK1]H+BcI׍VާRN^gOddV h[Vg[=j{dX6f1&I?qGen4P*@ 񴭮)PMJK=y4A_m{>O[]y#ѣN3 { Vf Ni*́1`rU|=o.5gc襬 *8g'v88w`nF\'KP뱋`m8*V̸֥PyCXPVPunG/< otT4dsP|aŌ M*cs* dMe7\EA زOg`ML|/C ⸉] W0Id_k61<}>x; nط5_ |'r",2N#t"2#S 3 ETX-\$$w[$t)tS H ̅ד숏ywfîAU[(uՍY&r#$|xzeX6=ϗ5u>3GqNNmw.]1AEk'ZHbAwJ |}"6=]pcZ|9:RVՀ#61U|;tpE:ssATu.T $$$O{GW,Y vMKZcs{Ŭ.+b ͧBq\hsFO<(qPMAc:9vp&ȕbl2rj ԡٹ'Ed Wu<]63{uX4]f}\rUlq;S"]y$ȳ V8quO#D-RӳQW\iTL-AIa)J:Z/k7 5)~B sGf{6*rq*[J%i2#Zq$1 nyS-Z** Y`'3MJdz>rka'9u0.F'#p>3ꣴ.v o6nWA2#ғQ!#5hRe'TiѫehT9ݜ U~M[!JoK5W6HYUMbu=;ͼZ}: )63֚͝}*ȣb?_Kqݽ{faI4Nz0EmXĸuH6WK]:n#_ Nz@Lps3YYhccn$)II>)`ͷvy*UXxr@?m%zh&2i}y T*` ڲ>x uT8:ïcgdn^MXŶpu8*^BY(XjZ=TǏB\?"dD$䙞7EnA Z  ɦ*Ǐ!ǡg/xhA[%@e%oT@v hzRޖ~>^yŻ()*ez,=mG؀~˗-Syݲ{ZJ,[1|/#@4ݽs+sVPQYŽL ]miTfefC6He̥h10N7AP"`J1Um-Msi6uڬs6y&k$cv1I ?}ȜĽ~7w[0}jj+$+VE))SD/T~L 袍{7W_Ef{#zVR%#T'bƲiC[eόc3{I^!9TƇ@-̲6~$pu8zhGo Rְ0lx7n6i`]<|3 zNǩhɜoÊuw);(o׬ffG ʑZ.bÏ1"ZE]ľגY!M$Cv++-A@V>$bZhjNW$ZAҠbs&ퟹ"'9ng.7TK$ΚP!z31(AЇݩ̿J߿(,ژ^]cpL0f?QÙӧe?}ӧLv iY<0SW֖0u* b{8=ԳmO Dт`UlmNw~)3{U~'LZm>gmk. K!aA1f j"$wDX/_1P%}1sq?2WDjkx[yB&c5lX%KY󳑦U.`yU`zZR\ԌDh3'6ndHN+ QYFP9y$tkM*^q5q]z+)J]P4s$q c$q:.*OymA+UB3iA3Qh㯯o]]s2֑XX땓{*Ijk~2Kj0s=ؗ|v~֣GwbUU蕟At/I1fp6 2U:,z8N<BܞϘKGD-XIUTRfLՍ}$%k!ak'nNtL /CZcт4@Wg("ZPs[/imePAwEUax~e̞(m w*u{or+0k:PGn_mjMR[] ':Hx+2pچ.P)ʆ䥰?lRVaN9?}]muK^3ĮıA(G:&@+q]*.`<2%Ȏ)EoLע_| :bBmivki#vBY4YKabCPkGwu# %GWJ[J?CM4YEu(*߲?GK/>C.d%P ڲg} gRSe8/j` غiJݞVC]Bdm♧\?%LU k{eܩp'ƢWb6q9x>?^{2Bm KKKſʜpf,_v%q{\׮ gIEe;yVֶ8th;<#78$!)v&%)(,(:; R'^nj83XWѲ3f.oa#I0g1cxPl!7I 3LC_hmv▛Ӛr.sȴ ܘ9,*[RĬN7>I9IokvҲCL:LOFeu 4;щ’ lfT̏]͓<{J71x|ֵeG?UTVw9D[ky Ħ W쇮܂I l3}k.}Nqf hU9 V0^VLcRGض}ѕ'd]qΏT<T GP]]|e=/BH#B*Xpյkok^@AEQ@!  {;qb ~yy͛ͼy3߽sTS~('_ÊޝєsԌiy q÷^ VGc; ;b+eL"Zgu ͔_MF?g/P70 ]59UM`ey#eY*^r^ ԆjbP9%XTjd߼e#w`R tXdRa)殬;IRX2ͱ\ؚF!Qޥ7mpAzN}G+S~yqm9NXNY~Q{n^)aQ>܈7};w lSV:JZ |H'w/l0''Gz7;@ Ds(U:#d ƱHKr&~*V,wXH7_#hNwz"݊Ⱦvm&k2[F6{#?{DzްsoӚ*K3Z\ &ipwVT_odߧ3), %yϤ bؔq\;& B4cǢ$ ;dJSAVddWB(nͻg~2e^3ƎND2wpud/Pf}򩇐[Q\,mX 7p7`dfS: 4 {DX|M?ofq1BxTۍ^C &wq{ĸI겗7-[y^Tp-nա<W7_aW9d4l=-?jLp{9ʤ2NV'[|0߾KXؗRg իS)VTdw~t腏0R@Q_Rf/S1, Xj/V?UɞsiqUKN6Kɹ#$MWd[vTbIU7S{Kc"8n{'-^x9Sw. pםw*on-6> v0pFLƨ1Kű SʷP!kX9͛.|; ojZia^\<+dkZqs[nFGT2 XcT62JV hgNtH;v,Cimeh@Fnvn {GcL #󵔠eنl\Xib N;GMƒu*֣"" uiz=Td,1 rx|y舤X1}D:/`.bPTZ^@v;.?S0v(]u9! J^{8ɛ|D!p&d@7l^f(ϯi)#AthСd!HRPQ2Jc%Ezv5S]KZ0zHe]ՉseA8P8S2ݬ` 6C) +6{ql˕h8/%tXpʒe_\򀽋i_dm.A.'ңˍޣ7^x- 8x(i c?iLV Dz˱;uDDe?̬Xy=YvX{2%hu0nK׹2Mq!ҞsN?Om &uu!6gHf:,j+}LYsf) ]k|;:ceP _q^o6Sz8kӿ0`-$n}}- l۶5d zPSJ^B@4l%qm+z@Vg21Vm7LdՄ>sMU%1RVhl,pՒ{XI X"VBlLgKN=MLqR'ЎJeB>o:9C"H_ [$7?mل@/AՋ!jo MhKh~k ݱ~=ْ1a^=&R8y3\ f݉'?{V0;JiLXxѣsnW442_x]rp(55CR>{8.O}5oooL4FG,q84^.kN)(eu~5UQ)t`"7~@r##0l5bҢPzlSLaam+w$_?.J9 FeRUm<MEL\x-9f? \1c#P[/z"'f硆?&Yf]dzq>ﱸ!1z?ke>sNVƏ}_|[8*+; *ޭo2L)7L 0XO299|vJYqB0Q{o`l׎/$gU ?\7uҀ ̀3@3Xֽ 2kZpQEUyt@]d~.<{TvÖ4Ljk@A2~#+,vͯ-GrquK0BG*f m0ߝ|yU&~8Rc#khl[n^eX͌N;__W&v4';&{z2qvw C˯0>w" c׫`e,cv:[ØV:;ť8Z]"ZdϯǼ3ǣg$SA8fzd~T@ WtbπeS> }eoet#,{K%V~91k,)MJ/kQHSz߮+Dz?oVesB=ހ:]e$6}Y+ j,~+"`mmGZwo*;AdmGY^~Ǝ VDJ;1ERLRkE̍]AgMd2:VKO_A7ޏޫ8˳k'|:LP[MܝG5]N2 ;q<^ʦLuh"FWSC):aHWG6 I "9y=#h2;v$a׳TqGj"6lY Nyeap sq|q../^*Q-· 8vG叏Xij[[tZC=VyQdn2Tl?a)M hsqS Λv`vk ԏZz[k6! RMQ -{gu=yeMoSE9 SqE+ë\G-Yzzo^MQvn1UT+g=vT.Ep!C]9jQ^yqؚaɬ|; "y0՜ CÆc(ѕj)AbIRBm `??;*ō)lD'wjw /e#!. )Xh*t*X,ʺNJyD,@֮E d]ZG cN@/v7ј.y1wP6%2~dY٠T)ӻSt!>8ZV0e=QQtS$lI!Df5EnhL9%}VD]XeGMXۅʦ:9h|x OHP CZ%v NGɌ za儧OT4S'5 3(caSS俲Sڝs%~UރD+IN͚]ܻ}_Wd '(l(8wn"2VY}o\:s(j یSfPc($‡JOxŋDRmgM;}8ȲG:i.=i(ʬ!5 I*[!7ZG3@5onYt%Ojڙmj)`ei k5VcM&CH>ŻitDjȦ9`)dx&8?&1"; <ưR}͵ 1qq5W#c̓{y.v5ֳc>\js# l>&$ЎM}Dw>|- sK`e]`HZG2'XePW[QM )7vY(m,9\ĥYRy,&yt'L&ҤZR-ͧPVv&Jz'Y!+[^%#q(eJpO_}ѓ59U㽡*# LFSZ@&~9gp"s3!VdaЗPFNLV6s ڸy)ECckңw`ߚO1dlTϪ\a=ӦOD}HjG1R+(Ubliqij"Ys@D1 [bmhGfZ*Ҫº3)1{5~#p`魪o;~2bﺝ?|iLt[8mABA-m )0 wOʓ5ä$ W,xzfϚ#ʡ%Fӻ{N/`u>T2a a3wnBe[10wu6ـ)UT@0¢rlz_%DEUBzhMX'X>ptv.aoѦqFd!Ehzhۋ:eniSrq7ʣUT|iPE+#' mia_UO>튱˴ဧ#V򱰨Jզf`W7] ǩ(>D4!knؙ飚d&*qT뵢JZSǴFfU袽yJ; LQ*0CghݴL"C]+ǽ[/|nFy Rhiv0a1}k}Mƌ]FiLhcZ+g﵈)Mg,IӲeX̢Ip+$X(̹:yRwƌq s'QG#^T0W~6,B46en)^x#;5Lv&Tjq%uT3.Y:dF?RELwٚQ!).|iω*rcvG IRȩh1}of|XR] Y%Uu䘫8s2=J$m#+7g.? &m ظv-ꫲK"fUԒӪk+&$s_+h2fHG` 0U5 \_dա_5/ 8pvt$ʥ1LvHV&FL+CzA^y-o?C6'>w|bggDS64bϊq&m Aa)}"=8H7E;!:x#ԱRHYEIjq5qZ -pM3(iVVR40ApE6p 0DA']IGcZɬƎ 9`d=HiǏ+Sի^+k(*y<1@ڬ 9016$] V禥 "6IG AJGSY~.pX!}R#)1|Y̜5Qe̮%:7+^ρi9>-Zt-=~E\HuXX%pQ%g$kMH)="oI %XsԈ)z>_HXSܹsZ)%sr\^La _]]BV* CB9hu`R+'TJpk̀tڪ*i~w~oE_yt?)}ym>`*zlLPQ:$i ^dm;5j!J0V+ퟺ/:q<~; 'swdAڕʹ!燀QfuȜLn=Kk쿞ҥ5+3S|O FM9V[N/}\c::tǏ57ٻ+Z[|wU{Nu VIPT.6*%3`bjJCn!Q&0̈́ 3VNd>`}g^.qz:k^i~ 3&3/XwʸĠt1ј>} cA635Ě/Bxn\X.*l(""dô\ ؅< GLFZi0Fpؾ? #"(t2{ڊ7z/;BC5?[؉u},j\Y+.y#;0t^MPAVyVVJdUMS]bͺ/xV 雜X/~3[ܾ88 ;UÕ>S# i5"kvod绛ExG#":W磏:vګ.̸~g;5KygI0x&ڨs8V:0ja~ մK\ڌ JET&)Blƌ$U܎6ܣj#?\ ǢEGC%Z16gL_:lPc-8R 6_!:mY&}\=#di꯺jny"b {x?:D̳:1݊ys:~ÐLō<* a>;+5A#'(+I!ǷcKȾvWNk324$<(Ew0&51 Mr2*GCR>xj=hCu#=C(F'3+z"=0=XfӐ'bw4tK62e^Mfʼn0r'q<M5HI u0ɀ)jAsdHH4a.ŠGoo<:ixNUv/Ŋwi jYWcBpY .K\97^ǏK)-wUԤw&< ”GXL>DV`M C'W99؟'_~xC^c3e>}Vly1Ge:ع'n~ p/Hn]QÂMoӡ|ƑÇ@ܜl{{뙻ӆ1}"xPv]0o5=Ъ1y|08P^N P MV/$':+&M?/j4''c`7x·'8 aŕ#|1@507}[sg^w HuKkz(iI-Lo:j+JD̎m[ D0\"/r&֔jʣzJR|M5"/#m^HN3g·g &VLݎA?Sc3zz{YY)Y;fU_umߴ7Lqܾurs^c (Ji<XI'Ajw]OZ%*j }z|,7Z:F(4U:K]^~R-wE~d#*Z`zVi? Ѓޡ# [}b=e,9:ӻ$RQSO{JM;)-˪\r\v~# V9>3Xof~sCsc=2hUhv w>"X1>*Jf?r>ݬ\RDaGFah4uO cw"P-cGn #`Pt\MͱM,>"g-D޽ 382m6}p0@\Y@ʉF#Q6d+x}V=rNJRNVd2zDy_X1_'J ;EZT?s߰ppaK5# &0: ?,Vw ψ8> 'Æ_W2Zz%VK?ߊrP0 +qsa0_}=FI!6|'Ūϰ`e'L;7L o/y!^0]L>Lb&b4Xe>)L2ӧLW};o3I, C,̬#V,W 8 356lD谐^/YLIYtwݸ\uRʼn4m?f dF9C :[ׅ ѕ 7uKduwS@ZB*U}iI,2݌Cxn z*UƦ2>̵4EI[\_v4G=}U>{㭷0^~.w̧mu4&X[@IDAT˽|j,W.$v>PY{W LcRu3}}]./ӥPWUtbwZT`,s7GYa~NN3,$Vp6>$Eʢd2;N.,Ԫ#9vgڴ +3^  c MTk5UvLpp?v{:ȫhނ,|+|n[ΧC`OB~{ql 3stÍE]6-{TLYBRGS6^dQz06*d`_0 egfDu.)RWb"l LM?P9^ƥ cYERF$4SfἻ5G@7*z%rWoG$|@ᣟ~3.1[\^ Vd;ߟNVU)1]ta:(\R%0s&tn<62Μ<Ʃd$ E%/.{D%G(4<.}sb䨑ȤhuVV MC9X\X1#{s0c, PYg2x10@VQ E^mE| ray?F'b`eh#y n/QhCӌ9A.0vJ b$}&\tlQ 4F;9?Ǫ af7<\SP׺JtP>/eY\v gRmeaP Ӧhڷ֭50 _>{G"@&Ge-(8~GC0uXDs_v$!GUG2ifwiL kȊ򻐒MSu5=A '[lI=֯eR7lpeZ6}]>rZ̗~/ol^Kx?xUj(o,O| ֎Hb?pf. >Lԏ7AMbQvX},X.`ߡXLp}#%0iEjdəR.^fw؀)ǽnb֬0%KCt>__.rgUSf@E,20c"\ |pJ@> G 8ǙIˊ2ƿbg _@kLgaAl \ݲ vv62uY,I zȨS"C::|"}+}g$x&Y,?}Hk pjsJħwg>wtP|a;PҨ;@( $K .$`,}V$#+jbwv@Og2k^@gAOeӋ5.c# Rj@)q] J2qhG`8࿭Y,$܌RL7eם5*xZ.w j+ub2b5w(@ [-AޗAMfoB%1:y=u),'^HyI;qu ;9~`ݟ^7f#>UF8]kpVFz*; H9+pˏq>h'O^)im12[p7‹2(Y3b~J;WwHxiDzIb  {#~:Ƴ8J%'J nZ6QsN% `|ŒDݺpd=]qϒ=odG_Ճ :ѽPrm8|z-K`']H)tOo_ `z19{6M֓No9VsJ `}dܶ0A)ce}^;4XcȱJ{Q8Xa@judzMkȘѦ8ExL>#^/Yv^*:BUK3+&O,3'*AeʛbȪ%&IscQd~T؟T88wӅס_@T_S-\i2td2̸BBq&md't>/!m=ibRURgoL]/K)^Yhl~)ci^i'SF QD2Yu6`W(!UQe_XH1kVElsOwdOOxd<\Iͼ!X4^|R*RRafM&zh2!#I>E9YKKcM7c愡?{nܲ&BaX;_vb1L{e6rԷ#^5Y-[SZQB[Wˍka5AC)Rf7PF.sR70AY9l@RJu8tl@CF`+9t^xI>p}X!h@bNQI–1e-iC0,w*1oZ|>Ϛ2䓢ߖժcahlF`crpB 6ӌ|]Vt/M.$ !|Q"m *:ˆ)jDMwpruPoh\{[bgJA]Ɛ㚾M~W^W:5zbZ|nFTnn}YLe[+#|y;jz& )f͍ǶY'G>5I->6L:?$92l`9YdzڢEm` Êim7~t :udȩxEٓ Hl)=m;J8L[+Oj˲gs:mYW2R΋LP./NP2)ӃYa#Ue( 8][ݳm+,4znjGBWs)FE5~)S %OOJGS]Ro;/M<00\ 3f`M<.vxZhLɍ GGK/_}hOϝCxŧ .b]ʧ1cg\UV~NnsެYefbة~ e.A JTbI#r4jՖI}2 Y)&kouۆ/s)2)&}-,?Xj 'to܎d;`_R<ҳqd=8 ^o@AZye= Ձ_sMW&4`MHSݏ'y p$#PL<ة0f՘Oߡ&BN<25PΆM]25L# L/]DЕpt }75I5ee ؋%&1&sj"-liiٳ°#1ΚEO@ֶ6tvuA iKXx0Dӣ{5"zZOLG5?Ŵd3e(\ut۞X^sux)wu2{qn)No[A| ^~fϜE P #묇Y[/!*,6o1[!]dli F]%j2ZX4lFll;nk ڔܦ-YTm~ܵwA-1j\}񽖞);-?rLHEkWacƊZ^wãϼDV#FHJM7{3Z)Ek,:gX|2免1cR })Akny\w<h?W~'Z`,]:|,k hjljOq:0|(3(LdLQ9TCl/mSD1#Ǐ,)ǘƆ;:Ӆ 6U'|A6:Zp<5o 5$@Зv|zմL ˘ǝ![Aտғ>M 7,Tt:[jEc(lSt6"Fִ"+}gho"J~Eߥ6jNMZZt{ Zҋ7ehLҀ%X6)z\E[ΚѬg8̶N4vy u~߈ te~벶Ww}oCqa>f] Fs%0tBiQcZf*ȴMEM@+9H>Ivk mK h埍 Ϗ X0k^fQt(oj_MW)Af0I}dElVYgk9Ɨ8kx)~]Kv˹lR JgߖAF3]υxogcͫPH VB袩YWb539B zqsl Xۡk1rlҽ*AUcx 2P(A|븐:v A0:Hy;L.!"::ŸUz'jFC[&W󘤳(e?f (ۛ́Jq5ѸឧX?b %c1 z;Rf3Oce^{)L6 lW mAQۓKެ?A؛AIP@ԆwK75?|VY Kť%M܉75f?9`-N?V=9H-Z5̌X5jr6oڂo0 kUyS}+y 42`;Zpbژz_T&$c/pp2U@LՕxOe9s桔 6?]@ϕU-7#eBf-_K-NXeZ9}GBfF6n^5:[94\L@~( *{n,/ZXF3b%gЈ h$MAֳ=r^~7}%ivrΦiiOgmdJBɉ+U463Qgj@OH63z>&@ {)2 ܬ! EYA*8NӒDYRu3D /e>: Pr9Lާ00''p?UʏoxNjN jibZ7,=@sn1jla_q؁=3 K/UNg :`GܞQCĘ ʹon۳^Ѥe&JM qS.Gf&)D0J(Y扇)(ULxgewXԳo7|$%sYD.YQk  `;"JYR8U|w++PUll *@`ݦ>+qч1oij*xң_S@aHx2u|?z]dq2)50PNwБk?[7ԬuCcS5}^oVQ+5Q):XBU1$o!lT˔XFNWWS_QmxBACޫMUdW쓨S#Eg,1_7JXby?f@K<8ViqAdX+_}+fgޘ#u?* ;_Fpd}7^OX(㭷G 9f,WӉk ?/l%Zw۶hv$h5U@1ЮMk-Dw!ِD'XKWv$P>Ð~8t)++2z>ԛ@Újɉ˙y@G*s?&$k̬,K*QmjA1:0&Hʼnv*BgNxZ@l*2PE <Xpt'BX,UWWa;yUcځlM[q ڔyK+HCh+SV-r>T#7%;SȐy4Sjl߲R1,cFK#m[ۀb{*Eyᛕ,c]k_DsUǿ`^SNȡ]D=9Lm޼,& BGxzDmv_d xņv-Q S .=MېVPIhCv1c֝b02YL>LhWsJ(ⱳy^[U kc eMkhCc#8ⰀSr d1I3Vӎ9 pO]tԣ\*S1p\g' $"L {kj@ƑCE]s;~ڴ qc٥G{*M &>O>d`ό.~fTic/1Fn`EHn@řh#j>4wiS *u*r 7Jy{]v 9('*xjiC_\`|:O] WYE9P;ݶw[3ʷ'eh*LY ŬGc}\ JVUX @O{ J V=(?*t2޹|-9CZ`  æR^f 9,{a ZxQ˲g=ap@$V c{0lן/@ȲF>[nk `g}g?8 #,&WQ/sYE"Fd95*ըGŪ.]{0iJj'L;~8DUIa1 ~6F;Ya9[+1ωߛ n4R.מfCy]ɠײA502& t\uM [T=t6d„sY V?:Y0TV=7hi^|7ӮSlc'<&b_l+QuUx_jJ+97f?mF:c|j¦2?ڮ,CgZ_tU}n]*L Ovk'V6N'N|x =~i#5N=F=*!8xZѭm`@BZ,`!SCIj]ʥ=5¨Z8">K+gmq{+jٔscD?q 4nlzc.X EEߺ3d? -Oۨ^aê$2xč/ GEe9q rWwڵ[],Xs|fgƐ5beDޟWFlD]l[#ZoDl#B`sodfE7nɞ3#ѳ "~"~ -nȥ4]9WKYeQp)tH{w(}= x=ܞ Ț|01P:_/eװ辞)qXQu>~F5@`X9* RyH0:$dM=V}_ohXlbD['dun+͛3JSr&`<@E)KKK# b3ԮUVi_>쓐~7w)9&-5Ǘ"9+6=x-,9]ٗo~ǹ2 Jl 9X=q0XOս>+>PQɒy;2;u#_±obxh>tZo Eէ9N5<6$>Tzdž*UM^KC !2XN*Se=省.Kϼ K(l0|ri<FXeT7aJʱZ KtA_ Z-eUxX_vh) %a>0@bc =[oClqtVc5]ux䃇\(36L](i O' -S4Av ܇Qv,ȡYaIuR1g|2, W]$ [Å =5խ'WovqC,GkE-(bu.-Ÿۨ0*X]Sy ջnYʹ#cYGÊz~Wۣ_&-O w6D}jI}c`?TIշ"x:Z \l5UaQs8*g):2>k:BiL@ bR2Je7X9{2/ibs;~Z)f/Zl~̯,*G>J2B[;;1 ;^TK{93#7ǰ/8kMeo v2W˜G#6v/"|@7rpmt]`j?|# A8agʕuض/\eRVy p_Ap}: B9j D`C5`i#B=xn@\ Z+57Gc^e. DfƸ9ٻ?4zUZAZhH(+D~y}뉑<(JVTU"]hzvh%H/vQ"]NŘѨo19ͫ9}! ,cW0[bҥMÈ Όnrk<.&wnss]i-Y+1D/%釐H†?{E~ RIH Лt lػkYW]EEJSI/!@ Bzキy'LLBwg}ߔ;%3s}{ΡKF_ܽx!}` SgɽoД9-\G'T"{j۹fS u57YIqQfaH~6ꒇB`xdUK˙W۫uC_y`bZT3v}~w#=-]jyvߌ) }w 2Spx8 i=K>LVʒV0d8J6,d9?f&ö .RLL0o<6 }6`sYV̲dkJpL*M3дٶQ4gP3thSGάzi piqגh|LN3 tpXe_67̹ 9Ap_7Gf"L"\(Caȡ|ָ00d~gF%QQV䟨CdRB(k\rLD^f{56M96 .]?K:ܴmE@ҥicp  V%d ;y͵(Uh&׵u3sjt5d+CP^yE{@"A>>ؾBT03iSC0速*D c ÕO> L,ҡßUvl, 3N SzJB 3s ~ A=^|.Ƹ0 o]tJA3>WN#aPUv@a_PȾk빧$$."(/w~QfmZj-x#MSdnnf=":: aw۳+ŝCP؄LLdp0#/.x`n4;a_CbT -J߰! e148:FШж㻜/IgqP$B-D3(8bfWb:0R@֫Q*3O@jTԑz zY` I8OG9JT>wʄ6U~CLʨ@8X4Qַ=X?Y]ިf8vAE2Qm'VHL?Y_}}}#=DŽr5E11cBյ(Q mlz]E@`&m o޶ 0K 0XUtrzZbQŠun+W hiCgoCL|\r8y`3s~pQSП9Zh?OX= o'nI }BH%s:)X%~!j;˜l/U\:yNl%)r$*e"UGyp"઀*.f9MMmW_4Rɧ0X)xU64T5sO_!q2-V ak~_1cQPDJUeV8ux2At&󱐲*oOˣܲfDUe5ʳqKp 0> uXu"}F@?7#8{z2YQ1L;16$.7zcvHiZY ''gEȈHȃ^Ϝ]-(4!@̸):4׳ǣƼ[Yf~ P(:;+?g-0!U-+tN9Z]$8u$41Ä$G?ym c`?jN\؍!Ah(-]gf@ WG3IdZM) p űx d76BBrrqfRT?F6rȄ542fh5p;^" 7;,S'`hx-hyPs īumKL#XjFH+A*V6"QQIPCV}a A}3J8BAjla{t:5cܼv.u9t*H9`)Ӧhi(Üde[^  E X "91E,gYY~Qu6I?]J6SO<>nw3IVzA]h| QW_ #&@ɤs0g03F`rc= >Ad9a)zU8סN$ Ich['^'?O% B]8 xr0ʛ 4PX9E̺*jCيsk,_J5v1`X 6O?bNLW+Hc6k%v`}[q+D!!>Np}?kV;;4#߱G1؊0|e$fUf29 iɃ0 zu8$ssc *$!TҌ8=YӦSg!3qTPTM#H]+iSœ 6_EW^w?3q564d($Y"KP:ݽVo2_n:$G*}f&1ͿlP\:Q0[YdN?bv@. n!X:Rf*i2$b`87Ԣd0xy*z%bWR~[C3&lЗZXh7vsI߷gN1]PK4zY'i#u0,PSIUuZ2^ 'MMMe|>UVI]n Q?!H.kSXFs~oK 4|7ԖeJj3:/pxJep>}^=6wRGx!dh/nϪZ4Ut؏qe{gUV2܏D Ai}z_`m#̎JƤI7ȬcdV0&dбxQB1HBiqkϩEלI(N8f0O:^Op{)ad=sy#o]a ٷnfu/#n7x㯕 UБ΂# Qr#Qx\ `M|VU0P=J:e%7yG*6, ]Gsw|F.\gΜfv u:0E ~&ȚIVZȅVח磶 #k?V'V" GzA+,KM8rV/9.K%#^m_<\0I.3gNǬ\Qi^?|-7a2Q FZL,I`8v(3x}TP9Cv%’;{sL9j,uxD@,bRU^T PUD:WbaSZ=X"jaxJ+H:}&٣!|&ۖ-O߁AZ3$c$*jر}7"s(O i ֛y~4vE :- 3yp?liKGIޏ$jBOZC vRJۿ W}QYY =7F"#6Gq*>E(T û(5 Dg6Mkj3DS$dihxR(+%^L8n3Exf/O(e~ڜE8d Alۼ 5BU -pq>&amU_d\)TJ s`&y,X!ʋr } &J*̙Ol3%jgAnbPOlgXdj)6^NTQkPBCbqeR g\ן2ںzp `>Cw٪]wV8d~SW9#Ow5cvڵk̘!C{ qoY '_2E64cϫ93[?'NL\*0gysTٜЈ]B;qSɊt:[tV$J=*@IDATف%H:{F=GN,CFǜٖI<4F}>7j EW՛c)Qp`RJ  ^F 4Sco<nj˕X|F#{Y2H']Hu[Z%&y<:g_erMDZ87_} 3o @Oxvmc^sIәb *,-gdRX#O>@M'o][xE"{b??JTy:L W nZ6m SYɪr2!(2TH?LP{r֋Km8X:ߚ|5u/X!۳'ْLDI{۶w,CkǨn_Q1cIU%ZVa YErH@֮KWmD</>y0y:U*ZZyibdxls>,\:r1~b + _ŒQc7h9MA{[nmc dOH:vS1<>C&ݩ'r?X؈LQz8;eIcDq|Z74w9cdgyy9a-uf&-Y0m݉)odb0~; iGU> Ϣvs`9`$\d7J97=ٶڷR'O^C)}:Rb~/wL `"WX?$]q9|9DY)|oՓJƵ?Q0_ZL&͢ԣȘ~\vT~9NRXt"-m7ۋWƩVפ#{ ~ێ)d\T"# 3bv춅+LV+; c%?_sKm[&u섖KCǢ1oR{/vUϥ=W_VNҦ026O1Өwu)-q)SbUP]]W]j| q' m}?ŞG`9l1/nY7;5c?A Qq"0srENRWB/ˆ# +PL76l&c0Sz2l c^9KYKDž21Lx&FN@/+oc PZKM${Q20+mÆ|^X̜1|P_€pD].}0mDe;Kt±dd'2Ky}̈́H_G|=a"%0aMV~%Ra ɴ}[?YKll?n<_^ #SHd^uw7Ķay >"# ʩdhğzc:>fJB>nhi{+1"z?{^ՠK[+΂B7LJkoltHH'ZJ L6m@/_ $5-QQZ[+1cHmAaur)/csPP[{AԴ3>*:5\O9$Cޫ}2;Zb퓀\Z_d EaA>N`q!$(+rf„Rh6>,@v34`n)ţ?!SQ~qѧяrkn_4E~c7e-`GNn(ypdhضĊLeRu KuHtV9. I{ց2>_)ыU-o5! ?Jve) f p`J}1At/J  Zfv`ڴ”r)}Xe ZDa fy/dE3X[yܹa%x_ Fn^lfCԀ}mU6ڡo[/Fފ,Xðy&diŇ߳A샠siZzxwaLO2NSrZOV鄳b,0>Crz.)Qq K e9ܾYp HHNJD }pDٻg7E[p 6c&8nZ.`mNs#6h=LOfL 0ZI:i&Ϣbǎ ZvmS 'op¼q|/W_CzJ*|: ̮㭋,U*jM5_z6Cf` z?}1.q/^8ZG3Q͂QEʟ0W?f7&qGO!8'O¾߁V!%TF0!#wy;ӋًM,Rڦ;#HL9CVq$LJ3tUyZN]0so 2<`5I`C{QY.lxJK/Sm}==g`dpVѥΒD5SR"k+W`]`fE6T0 _߮wܟ>}qj/=HAy q=W)їuW◍k`R? έgF\f8 7=qS *w᥊ SkeĐI{7 V!LRr9ގuX_dHMXe3EYSA֘X1i5E Je$A10sa[s̹Wpo?a;,2ᴵ0cBd\7f)d:'Oic:Y UkOXVh+cGe%{Njd?GV0Rk`l004?\TZGO?d\*LqwYYٙ3Sa\ cr & V3~OLh >dG&q%&C9g䔉E7?^z6e f^cRRT-@Tb4Nme~ﭓ,<ش]^[IYJngMD%$zIUJe;Emwzޒ,/ :TE%{+P;JW skT ʺ?ɧݺq vLchH1A`DI3r])@Ӗ덴b]n>)wN&nV m&'U>AQq$2z8YI ypv@2AC-&hj=&5.CXu#lIh!0[5 @7L M$nM c 3b8*90SeT [!p8uMJԉGqÍ PavkUMwF𜅌AhQ+՚pj&f@us,\o=a{1u)hK 8H%(ޣNCbJumF8q +oT +'k\tH0!-y2 !TZ~`9pɓa-;]X\@.@&>; ?OqJxΉv/nK`53G $ں [MFSJ[ɧaM1g0ӂ4cdbI~;CQ0kZ&{E.}31j8yJz>]#" =/8>؞cp6#a 5%$>%H1Y)glE|^A<8ާ-Ʉ7(<LG=gwG8+J[p<$Jz99܄{HF$g$A_i4ϱP]h|"P|hb}*g3 ^EV/ڱL`(crVNz}I ,+c'&jMOlU۔G=94ZBbSc]fM7SV?IߔBZ"ߌ1GD[Rv䦜T3hJt3Jb~}`N:{}@L8 ~݋S}{Űgʉ1o`FI-tkرҿĠGW(<< ή{rRGo cғ\j]Kf$ZA TDG7bO>KXsӭ *u|?o[옑ˀ6~.O`ࠑJQ^|4JIMI_OT(Yx1@V/=R 6X-"?, 2kZEkS"[O: 12Kqm Oa꒡I'69ppcPO NZ!&> aa(qU4DIu;"M ,A/3Av skՄmove嬬NY%QqfܸIl9@gS34^zlDu1Y }tGP ri>́]9JeEe)ܞqIIlEeޭߚ+pYR?KrU Tv/&%żO?M~b;ȈՅ3Ϳ cv1s0VNf1N- #ى;> }oSPY J䦤!(lX^oYLL d*r5;b+O` 7v8UXm Ab"vHl0ɏaß&;eߝJ̒º[=r/$zuPVԤk>,6}J&NLtfN3Eӝϔآ;3{ vU5̘аoQK{^}}B:pg m2͘ zQIea谑dg ţ}: (%{L6dgV_Rvvv_m $ ym_KĆ{qM7a^:=r,>yoLZ1'k\bmj+0VLru3(WFPeYOظ]5u҅+";`HC#;؉}ꆝV/ ֋ê/^r Eje݃W8+ݼn"A-$T1XuOk/7)vIB^5X\<2Ӛc G`yRБaRM EJZ*)Y6X]kOj+X#־I2:}&&.m c+﷠̩ǜW&=;f'ze @c1>y4RXdڭ#'3<` ̙1߯Fa:;9p?**7xo4iV2wx*r~8 cY/ؠ/.cPQpUI^#h`MqJ-HBf$cq$̜"TvSǍBDIiʳd˄3pcBGV[IR/mi!n˾$_T&(o2_Cs?~[nDyuѴ܍/j}L!\L6i]jvf9`ȔVuZxhT }PG_(cFi?3?/C';#dtJ`\B]:xddee(Qؾs75 33 K;;z僭 /S zZ9^`ÐNtJlmHjz*Q^,nЙwX,ԅ+GNe~|v^wd~ }7_}= s´ֺb 'ɪ2]35*ݹHs4߿|pFF& (紊r:x(POټ(ɤM}7d*ҁoQ.nWϋdf@xݪyNkVOxJ檲ZHvΰf]Eb٣`lܲ~uL7R/{6C̖怊^GmNY GkÞYLz.Qը,b`6jIQr dw4I7_ ^}EȀYU0 3Lc`„TDފcɥ¶;ۊD* +t\@6U2B.KI ޏL`@zsAAAe6$,4zA,njpC{+n.FYr,9/Kaar=*R&]]} zXՓl\Mڙig *+z`:{Vu?3G}2[C;:r<(Y7׃ 404( 2(bFV. `AǮ iIĊ٘ z{PKaOfϫ_}Ә>k.z7+p]uzOjr>/yBM/GБW1ň_2udef(tm\.*wgLI>%'!= Ȼ5|1w, RDw\~d.2KsڶWLʈg`?֡ǯ˿A6:h4w۵V|@cdwXP7;vG_>3~MV.y>4QKyPhe;ݹ:k kR?~ώcO/>GH6H1fH.k,S4KñX|7q×aAnW/m|@b#>X* +)DXv=ܛw"e?G_LWل4.+f̟J@~ xJ9J+ Jv|ɲReJ5SLֹX `?YKG>F2 ԪW|J }W\T/TVR G(?s@t[Ӷa.n68/I#'LLB&=uc_`Ɣ:YFi-/0c9iu5a(OA6u[[oXekR q%K2[ASSsM~X S3ӏ wO8lzE 0C82wf| V3 +[9.f\`"qH@Gx0Ffq&@(TiC؈ j7el *mM籁\ _=~کX T%F)۪jeZkwV BF+k{:_vJ[9e =!`MUu uj,%zT无O?fz7z3 IAψ6~קּ>ǝGǣNHR*; ;NA1c8_"y"!@f􂿛3 f%XVYY owk09ɦé@ŧh3+biXW4jD"hA&n%jElgɃ V M`zܰ 蚻a] `o+ 29vs, ~,dWS4lAhHCѻ{MśV≿dFphlxnڍ8N>L\0DI98Ir0;@lٯ-zz-GDQ^bHd R TC%öY˶tl& ZPڕ#LYS/XӮTd/KyM261Gc%V-ܙ~ v3j ~L{ 3-Mk&41gMfL֮h3U5gjUzOFad򲰇AHsWAĒ^' r3MG 6\?5Pe]̴"CWJiQ>B` .GzzjW%1$)\TAD R@i--mdz4CKuWSRfLU(2?d B:78J )@fc '1śxmw$>ryy dǤbQЪ/B իE cu͡ou+W"((fr0AY^v<,U^4;5$.8ZǖTV^^AgY}+ʔ@MpFpG #c*2GA*OŦNz9(ϱ%W ;ov&Ai~FO?9m.)6ryQZZ{\w&@syA3 ǕC#>?*{f?UJ΍)7T|bO%K)xSx P0s ;L=2k-¼Keo1*31[HوǶ"STU] JL2sfhk>!xe~Jg4:5%9,2)1܀}|`rZNP9.yKu)}lTM;WGoCt` $Bkt3Q{v.WC$ȻQkquڮygNSA\Dָm{:O%T0&[8MGߛ m@YKÁŊi6e`OFܥpoSY9B ?ԳWVJ#;8~<f.V× z1qQTK!XW~<Q{ab_*70X75 '-3U-**%Yi8/r ObT&ϙ SLC'5c06x E!juݧ#%2OIec# LXi/+qksX;*(I`rr'*b*>zn",clmj!Fi^E4cOҗ5ptOJ ;#jN;{,_i8x,Ǝ7z YH Ol(BLZ}X k&f4]FA QS:-Í''x)3y@kX9{ѮK(iDjr***+PS sS/*dsK], `KE#< Ou#zq4jL -58س'%}@`jqc !&q(T#ؐ4f"*z8wXt?A=1Zwb|fK5H-FtÎLL-c)#c2Vʘ֔ç ja2!a_*>6L^@nBfAa=Лʚ٨v"šhu0r[nw/EN)>/g[J+Jz9tI+LW6cULv+B@:S"y!es/CE Sg>q&j/%jKdOW3杛 Gnꏸ'OlnħCxaQY[1vUnida\ECCSI,s($1qxhTxB#%W5L3l׊ZMRZ+ N> qPOƚyL0潕DO{G{"loo㦠4hq@,'-%@'TT\m 0p-*o9f:ǭ.$.ϒĭn]x x O`PILO%۶ЁL%6A>p<O/8@Æ H)V=mC:lqsQveUGuX7c˪'>+rnd*5iUk& iتD@yGZ]mi[|ۡnٯEw- [_WY ΒόpPgfҌР=zO#)Uk7P<krB>}a8)QNRmf(@E! 12&LgwOL aA/[`;`0h/=X")2`H-rz+VRuy˂V9+ʺIy*L6@^ 2Rqde{>߲)0kr +Q$jiN]zd8Juu03ia<;f. cc<0=ؘ|F&fC7WfeL6Bb^?Z)ַo_{O3Н'wFѓ9ƬdКvcNJh"ퟃa[ >rW/c84 0oʎNFY1B9Hy&=&壎i^a ;{"0*t,)b̌-;~Ffg/o >*Ϗ"ʁd/vij-l,uyanW%Aͦl$ϪS9) pz LUٖ+)'1 zJGf+y /}D Tg"08bNvP]:Y@6Jr:}Sa4p]m8$冯_ o/@HҦ?U\}rCF2%~ D^[ĆU)rl`G02Ҿ sL#+7CJ9>lEB̓Amۉhb|\]Qf?a1>(2wZS}.dҾɺd0̝ҫ_Q@Ѱ|k^SY&aQ} ڗڶ[j(kA[ёrUq(K= kd6GZUhFx>c8D2lb M;Q 57eFL?_Tt'b"-8z(+i|1=*gXȁ--!ۮi@h@۲grW:ȩ)GtxOfL,1 ^2JX]>:-l VPW{ 7`7Q noj`2&9v7m 5Lt=[}Z0|LFTd htD/c#̚6 pw(*{L`;vMN^a5Of몕 kl &tdT!|J?S۪u\*z.lfLd&v$Č,wB,ǫy:p5$)( ȑXKPcZ(^d/^6dڬG:^{ "Qg 4-}q}i{ -xe84mNA~͌M@_9$b@[w s-) lKA)=CؠMvb-,_wx F!vdsjߌ(C\_ W#r=&Mƕmݨu7o??GOس Xx";~eanQ1u4e ȘCWK9G6=./ޮ:]!ޖM&#Üx}Liq&l#3rl`I >HOˀ&Mփ C `9{w `liV"V1VbO>9n[o ßk+ؙsbA9drctu G4qQ,tU7^vBV*fEGUIhP=u=wPrU뀁YUvͤ#3rtZɪn/NY:Z~w>^u+@JJV$/|W-{UUٔ+eޝOa?zXp~ֱT:4taNV8&U~C@FY.)}|Y5@Xd9"'!@IDAT0!S*vۊ "`޻ƒخ4V(kJpf\&`(Co/oM<_`U>f2>;%cu2 ǧvoޠē#|z@oW~gT@Ͻo6ߙӟ*VjƠ3Uس}+ۯ jg`nan8@'(jR >s0Hi6B jJ v}ՏSe 9asãy>?du5U>\ `c5)(<r2L W/ VX?*4{ޒP4)6@et~DZcAEEP" RIBH{7 3{w߹w9gB/Pʆ?7m:d{(iLG+&t8`U#׾OTf>_{U7^Y`\YNmkx9IXe~> 9_V *'CIrԯvtK30Jcc,ZsD|˔&GN*Z#|x#O'P`мZ`=tz3M/4J_B| \N8F#ia I {+vتmƍobuW&VvARĩ_O;HYWm0YTQY;5P.zl,F c|q`Ƴv=v(^~e,[5ʹ}D{}v܃[`$JTC U{Rʵ$g44curd8Z2t\!/F%B lv (h0A } g)䓼jK I$L=~'c7[44"*1Ɔ@mi8*KGzj*p4W6oN:3Ss^V<,(|%zB|j&'bI67ŹL8YBL˨bT%6> /8jp1 po0O= RY %A܍ [r2w Nd$ן$o$Óx//t X4jȈ245FDÄh,~12Ya4O7d!Y2MI9 œAUR4D=z(ύ9s ː >dKΓ<Pn*<"+5AQ/JdH+BCp̙7^O֬' N>Ʃ~9{?xLEO,ƳO?>DNϜ={ q~pl_+Yx"cր"2ɻtLi_^+[d.}.ରC ϒv/>!h S0u"ɡ`ZAv)wSU߄3~1{ 3q5?/nɳ]d Idh -KRVz+bH'Vﶢ9ot1:VӿA YHIPƷ*TGC4U|W :=M!40LiMŧZԓT 1}D鷴ϹeEmlgUWK]}w y/m7&^~Tи׳v `R̜W>u*쮳\0'Yb~r1{߅GԸoݤ8u%}{H_n_K7?_x>uʐ]P?|u[Vc2˘\F S)3"6#Q^B5߽81TV)+Yμ&>˯w(>zxOF!a8y81c:ngW= H ?+,<ٛc`bfVO[;{Nݷ?GT%F b!#u -;\VFVHfȁkLP &I5ΜȤ0}&'1K`T1*[ S槣=G Ѹuˆ3]Gw- 077Aph(Ahgaݷ8g>Mu= GWdR"Q3"Q#Fs@hP/&:Be$yCmZuUl+/eb䨴'}e"yfg#1;SFUxIhOJd2vc@icAGJutv  2d"領3 %=Ww专SGȉ׀ۻ(=3ut_E&>X:;b8eWS8 y$R >ȆsJgieFNd7`p+{-."8?DX/=;z(cdo0¼*0WWS7o[cA~DVVЁ2-0:) 8 n:96/o/s&y3aLgM{0`k/z> :.j{jމ,<ׁvs#3R~ ~X΋Xm 9W<[&8gD˧gO`U70<غ5j4N|g+­,9IW,1 UJXx.VtzSK]dvFwMݫa^ `ڶ|Ft;ua~ßϕ-ˣǿo\I6d*l;خBJ z||(M`vk] ${D.XWSAb36EZF"##tb}=ꪛ} JB>QV=cl[z;VigV~1eطehX11#&sg"&FΧOSޢؔYs.q^w%^;+A'yIUVڹVb1h᧞}~2~%'`׵YUM6)`P「:!v- :/zra'E` 9ER] @W]=欏ʭ˄i%Wm᡻_@v8vK:9_W jwaVjmV:R-҂D\J-@oF0Ԙv.z$YGƟ>swRaWR?l :o;VUYۄ?G3gASM)< ɗ{b/&7^ ? d EϺjb}} hᤃ~SU0m7}|X=q&8wL[C&rrh¼1MLV KӣsHRʁsVѓ%6P jރ1ؗ~\`,9aTv GC};tAF% p2,=qH I?)̕ݛ[_u%  w}HrF%(blNq88DjkyOٙpfx[žsEjMF}K=)Q'p} pe?~KncR ;`0 pޯ(i6̡֨1#7)f dcI0>UD+ YW+\`AmL`L歮>R">Tl N?U|՝nak~SWG:I6i_2]m2Z+hUj:YeБZ Zq=tdp΅QR[>nƻomw#ұ9f l:1`΋(87d6Fa;0;8s| hbf(|$fa$ ~!^f.21#k yT^"Vۑ(/n3mAS/8^z<}>Ǩ|&!ȗ+4vYGo&C?O?F2Gh`ʙG1Vl|S> k>O2})sKzTV5cƌ٘5]8j^֎ۆ%b<,PxR~c *u2g;nvő:755 REɋmKg& J *6fp*`fD~ (A̹F _æ*=y򳏙*$0W1 b)Ds # 4߅c'Q6c=z,TTЈd~:(8Cm9mS"'-ˍ- 6#P)TzFH*7Ǻ}!c b4:Ή &)f qs$ ʹ3f.k[u4 s`Ƞ޺>v*,~3\@Vְ ̕\.mΊJl*yim. 0џukׯe7dNуb(&.i-^y-xy13_qpjؘb]ɶoϺr/0UcoW:3&Mj^OYtƫxVz WY. Vm565kH;vh/CbR${A!.WPtssVu?lxor,ja!JSwɾ*..:|y..U6W=kt× 1Λ=QL?!Hˊ]䒇+X~׊nvA Zq愲^(b{ *| M@F|OiWoR+N(2k]? 5K#+2s-Ij3Q=v*r1OB^Hؾm9--WO۾#f?-V歓16񫈔lSOmLPexo_)N З穽eO3[Va}q:27f^"|߃Gj%٩ p`Qp0gdBs%dںÖ9Yo[8Ӧ%IFmf \i KH\(bM(8atZ%Retɘ3#)"g*ȼ֦Ȁ}e 7e!zkP {| );d>mf E, 돍?Ĭ%K ZO0Id%fרanBBcbR ul'ό,xTQNb| ÖAʦٙSDW)㜑kB>ea"k9ނ3?rnAtm.z )ם`ChZQ $e34`?OwC۽9_aIs$d86!h,~UBHVA*w 1x ИX23i # /JRf-/-喕ܮg@oy$@XXo' w q#} AlPHb[ 0x0la/L.,t42JSO6M7{SȀl׀}4{S*% A.Xŕ(%sq}Oai0bxSSܶt2؆>2A v|~N&CA4pab>#D)$LUwr+U|ɸ5B_ÅLl4 -Zr's0{툎8sYFu1q]|ftA&ArL2ħddMĬ12ptp8/OT{"SˡksM3唆6F9Go|KC Q ^Ւ@o0z+}r/+N.kĿޕoXXPsHAfZ"ɸqܹҶ׳>qJRuѝTj{)(J^GjJr j]k_LWւ}9AZNMC~M"XbEDKˈ|H?yTFiPUoi1ܔmF Ňk٩euLW\0yF1kT|- K և H=ArcG( 醼 ,gq\[J=,$+^4<2X4#fiMmgfbJ M9hHbʗ^*lټ9[W?KsXJ?IR1d Y0QL D]8i3Rb #'l޲I~e>dgX_dUϧj&Xny 3L2I[Ơ* ~,80#J[ NjKZ䘤|Y} s]M>P^&&aVN&G .U޷#**ϕ;,Ғ(хV~F/J_D'G "]t;[Pƚv ss?DYM,@Tvc, %*td۽ԙQOV%E>jl۩Qfx?ftE#-ٿzÏ?[owXe+``0PcgpT;ϝ{oX7lJaJp\UMpOuWU)23b !U Vy {(io?i/fd3Jv t)˱fڠF͙9bd劑?S;8!`t7(ot@S(.^Ͼ{P l=pzZR + ZDl|kϸ"F/?áG,t~<?]JW`"Q@o7Fж2GVf5Ǝ/߿߶d=uLٝ"R{Y@֜\F@'^|+AVkGѐK}p,j)f1,H+v e$w[8{y:/~މl#l+{~阷2Ҷ3 l׎W/ִ:S?OQ˒v,27~L~C %^|(+~ߧ#(}S1{3?QOƀރ@^{Wbu {)&y6hcyEtfM\WgŖ-U!J7bԻszW+ ,|z Z;̧`U;Vi+4(BC6}]aLn$:,m~9w,CrB0FRN7C`n:o}4f2\i[8";{&33g,nNvwU2';T T|hں5g+DX|yr l+~u/kAC \O{/o]+ޟfyVnXfP'v\$Fme +vH|Ԣ]$#e_rPhNj{}J=tky߶+&*9qe{_ϫ2hF-v_JgԶLzzuLL"3o0psQ\<{V}`ܐ ((%]2tg%oҭ0!([`&T_f'eJkw_DEŧ"R_h񆧳=TS*!53V>aу>#WqSVo̢,FVn5\"8|8|^DG\9,Dxgw-rr|UVWzؔg)f#9<.#Eg ?39}CJ6)yK/gc&GnU€PSQdd޾d13صC'UlǏoFNJ&3TGNb6Y&ze#kz䖐QTXDr؛@}eMO¨>/%e)G[Sz23H![=.z>%w̆.eEԵ% u'!>>F6Ly,pv{is:vbO?伟V68DU|·tt)I| npf:=m1a'YE\㹨aJ܇b8xl/d2x+j+21^T>o>A`5GᆰH4i t`q'eP}ع}&QF[0kYoYF9J?&/)][|䢯Ie\r+2Zoa[ҧ3GzMePFd|bbn[g:._||WF n5 ~'i,Rz`<#ؽi5#"8v_`LjW: ^x*77ؾ}"=HCיZۺD6ϛI^>Zް"R$dW62؈q"QfZZ",Z%#@7SZ7vu{y{cx,y&{}%[q*"9cJE %""wKcbKaJdk$0Vy'Wؿi-z i{RJ_V&GaeOHHvYyQDz3?/xҝx?*;w_iQ^*sg'/dPjDd\{AJV6+r"*Q_Y4bѢG\‹ 'UM[Mu3h8|8IJe0c,-8l$e;g ge vߨˍf-h %ަrbaeخ>ƐDZK8u(ƌRWOs*=Ss?Bͩ=.gDwZJ(<3K~>F#6eL̓fT|zL<ϝw+l`^*Qaah<éP 22̻ MNd7ƒb/'S a9KY;ݱe}P/3Ƭ[1hp)ņbܯ'RqB܉5y?0p¢b"NTvG4R+ōtLHhrrMJFmׄvyMU$"#!8Gt:A8a~/++TX*:[>sG…&{;ڶn/aиݱ jGj¨zGձ^~ےjGUĉP.QY8A_ˀisAb^\A'Q6\ !Y}(k#Τ5c(_||.`^&7wƌ$NA0D+g[L׬L #a$֘ ոLT")=E`ق JN,4dwBÀQLaG@mSu1@-,M:u5 S7>dܺ +28%;g׶~B ?I\sGכ 1n?KʰdƔ9n:\xMs h$FS %uv,IL?̜'TA>rchXl<آwaTغpwr}!u IG%y}|xw8,ʲzjz9RWR EVY67H/eh^jDFa%M?ujZxMN\É,>78v("+q.`R:3JMSD5,+5֮h&9h%;ISm=_Oo4gu#(<}RufJ?VJ]ɶ. d5SH^ҿlҦK}]OҘ֛ʎi!ki5uCj*,P:SZ Yc0ldjٺc1~8|T wjm3c\DaU ܺ.>Ə5}*vB@FY. J1L8aE!%-r>%=۟Χ(Eiponը/;+#hȐSVCPC7 f)**}:, +CѮJ# % WGٌPYX/W̫jm'!֖**m܌1 HYUb @ZN"ݹ꧳kO<}H] 00'NTrIu+ĺc4#g"(=q)-1~c1"s-è"0=%3 sa I.CwQvW Seֹ ͞IBl(ӎNӦ`"i]QG)KqsqR#іM >|lVkF@}VK ˃p&g0F9NV)<^@ܖVWQc'10uC>̌*]W{Y0;a6io,oNRK\MhϿ1k/2dSJt(6μO(cJ2uڱ' ,FRr55OYsbR v5Ŋh*ѣszjO :KWؑCS2풗NW_sskֻV-bfM`O6"}8>Q##ϕ&-t,p2+< ҺEtTC>8S^=ӛRXD}A9k};}VQ|0=HQK(c`q"78h~;ˍk>XgڎE]ӵC\ H2{[Lp'_@mu=z]:J["z^mϋ'Fܵ+d޲n& $z=1ѱIB0T/ w-ձ~6V|n5FѶ։fk\5<4(w[6zT[6|S(h Ō=mLƥoRATN߉ 1\{鏯 Gn`=KplgOe(/+7bx-EQ9H]0XV9Tܹty6{0Y|Y:]ڀVG2VٱqcsЭN*~z|LUBFh\;pFGi H(E]X6嶃{XK4GV`H9E_{Q~vUzRGWbN"][me!3p49fCL1.0;n _u̹ >94>.t3+> M8z4j0dLڶ5.B2s>"rȼʽ<5%e/?\Z7$B~8 4TO3<ɚ~K qJ#Hhj^.rCL JyƆH, j FAJFn8p? o8c,.CyI}Ux8zuk[NGc}h@)_2igҷCطF2gk LK(Lo/7xa0I]ɱL!dHFxxUe%ƌrFT hnTU` s1 YHo% ?g-S&ĕK9s #Im20@]0aQdapJy \ɉ泚K0uȦmb a8t4zb73;>x$5_\ [XF}>>ZEL lv)NVw0Žx'POUxꑗB.;4h߅8d6tJ<Jn-̾ۘjdGVz|(,è@,)F5ʽ_R|46iJ@剟`kG${C/O/\c_[ .䜶f,|t4CHD2,Kփ56/T]Rʹ;YỈ\Ge~[Hy?a᜙ 9j(}8xDO}:eĜ q@. ʓ1>`ccX3Pd"4P۔.rW>CrT.C5 V,9yR?u]dvEUI-mQW`;S^Q ү{w}*9sT͛N{?bz1.tQZcgfcm7Fu,q1du\͇<jhaGyYhMX`~.ii0~8I<×@EZIҁYJyq0%(}>Zd/`42iՕJ:V~YޕҤ55m:ۖ3'Tèn:>K[ċjȨr|Z1~ˬؾk~KI6J[,XPXO>H%F9\Veb$)()`t;:3JAKq4>`c981>:pEu-~Ԏ_ _}ÙO5!"uc$RV^ Cw/,Xt!=lomF‘ iII8=OǹK熾2O5-q{0lb>+o Hgwb\<;p")a_ [T@̱Nd@h`_{NdɅ:9v( 8^k2$j( ΊOe&ƼzQ]ɲqҨ&*jS-*ًMThL=3'(" צTĨmNlܴ "oR~^;} I^txܾ.H:Bo_:3kuLSjag'E,:R(9g~ -E8x ]85FeQд,Lb3#}KUU%Xr;&00YmK8 `lY(ҍקSrs%2&wկ6lLeɯ+KN|(TW#171wNVU` `z~܎ H esm`4W*?t9]':T<' t<Ϸ矧=:(g$"@aKkwD̖\K&#_ 6O]_)5_YK_F˥d(w7ƵNOGrYj>rٿyؿUkI,5+175LVߴyuV-գRL&2?+p-lUJߛˡJRSɶ?p[Ymbq??4PXt}J UOl%XYvkK7> NtϨ!nY0X?ob p1`YU_4bR^Ѷ e 3K#>X9gE+0ڊ3(0ptxPW݊^Rf7HyɆeC1H&Y(lچ&/}q_mw>87t!)c.\#=y`F `DHN>g.4-5aj% 434h!k|LFߧ5:ۈ ǚ*lM)+=_L!enZM!)fd\ON! &"Vncu[띷>__b*>p 1a0HtΜa$?A&9 -#+g?6(jٌLctV(\lsS3m K'{0Vfux= lrr ^ޱgֵsy eYuCPLRWV~MDpyn-Lq&,&Vprw!`HdeN\ͨ*124rKxGi]B2Gysԋ5e0yb6dV2]]x*nUֹThΟMEl߱ AC$!Sn׏ [vR93>֖r4pJIǘR-I [wwpxQI-R TSaIߌC`@vNc:wWU6 EI(.Aј,QTZ C2c}65#>79=}6uyPùi|\0 &K6@2黴95d$!,b\U::\X_8* jXTMfp4FZvdYMmkL8z1e$5 !6 LƘ+DL쫍_15κ|zPܩ#8s2UȌ%]Jv mxT3X|x8S}{IhfBNUc1GL3R5--!A!'7+}>[.6;:3Uaz'k6:XVVxԗc[ﲟ'kenY{6}e[$qMAÏIŏ\Qm2_́#ZR,Yoz;jp6,%n_oɭsȺ ǜr&u>~* o&c`kwރf`A/od>)P֠_z MXU1HYNKg)h9},OtofS ]`55/;1iMe@frF39+,69apw^tt2Ps 3S(y/mmc}RaǪ%773]ֽO:?)pV: gg͂ u4tذj 0qdn,pFQ2`vL<?''Piǘ|dV ow֙n=S 0o~HNº߆>oZb4O}atPSBfR*Lt _x<)7 ;/#t9`)j!ʲ<'t٨<321R^;1e"!zߋqTV:FȤ-bXDGdAMhlAq{ca*Dk:ш;^6m+;bYʘK#̑d{:ilp!6/cJq8`}w˘'R+]aru뎯ИW*2y~N&=zmHv<~>7hޭW-ޡ.dzy˷IV3ϽvxJnЁ)qGɣHd~l>##K:m N yZk`\-!X-CsVY/ yF`.T3IwcJE}\cROJ_6z2O૯s*،z,(eFsBTfHG,()'p2߆=,t#clJ[3=#&xC_=cg; `lv Lx|o7zŒG\FBwwX8Nӑ s{"S[`>p3LYVQ\Kάj^:w}? .GÇ##1ߗ`/233O֮M8 K^|FnN28ѷo o6̩c(=O kA'93@ G HՅゴOw[sǫ쿎Wct):ݕJtؓ]\n돲,O=LM[\~qfŗ ;}f%.}0HX93?>~oolDYU0qgw;wd @ b%d}ѻN= {k^ardF"=; ?ۤJQa x~r; %]|E\rҶ>U [kw7r.D`҉? [YM)E7S>ckvT߁`/K''{ X0Kԭd3UvXg=IrHxGnO? qmz3Z(Z\AЎEl=B$㸤tdyvTnk!یtaGs>1 dQ9ױv)%[YVc -dPK1Lu() ygB([5J`-ߵAn*YI [xw9C,)Pu"S:{KƂ2+N_Xqv_COK a ä`_/<<̱K_MV%?ދKU7as Hf^*lG k#2^qڀBK[ƒmҒrg]֗ 3pC|d?LW(?D&H?PC wY%5XCЫ*֣/wc3#%xWdfeL78>Uex˘'9 Iiq4i퍼r`:,#'X8arLt*bh@V(WI]乓~KT;_~@ToE{E`"mҿj\7^s覦nY J$gHphmܸ 'އe^ UGfȿJ'Dp+=%uÚƆZ2H={eόZiLA^V<>(ܩw/saE?u)dFT0!=0FMNXؚ77SF2lY).^ P2"#p:&Xj4.}kbK86Z9_9'd EɁ]z=/πn3~}~X_ r܇$~jin’dhIY|;{'ogzAJhyd jS9>@%#nn ؏>?;rMFjI\rFM(Y(WWM)?Nx~L"}WWw^?b[Agv;r4v| [w oN )Hr:5LD4*JM-T&$ʢ8*ƌݶ ];y::^<{9,W0ssxW0gÕ4vLXi?֠A5,nYKwAr-zJQ~mic/J(15AbBJ[ )c7(jhޥp˲qeQo bz3HIM{eNӇ f{壶_Ԍ3Wlym3e+p*Ci^fc[zX`AQYRKYpNM[1}/:͝E?8nBYf($o7Q>̌b F#X0 Je:%׵J %zJ%wrzq5MZ3]-ylGLbgVR bC(kdZY\J,Na}ѓqdvP:'Aֶ"%99,:G0`W7!h pUXR.͕Qʯ >dtW},ovv5Gԭ? @ mkg;?qa* emߺߣ*~!Q܃N;OXUdSKxjJ,cOK ,'nI $X\hPY-Vw+.ԍw  B=s&LxBB~y睹s̕sssBA=dnM 2NWEl+QAcuWa)7}=:r-/ߒk!z%*c4I?cg}Izu5%%C^lZJrU"J} s(:lݣd(]DJ9r"e s5 n^tkrEF&`P]iI7A/r⩪,$,}Ʈ>%9R%zmin|tb(llmU-WVItHꐹv#~$44e,u_d1QԨV:qmM?VzR9RKL V8zy93v+-s]7wߑq\db邡A(ieH2xP&Э'%j VALKI.j2><!nv~i Nszr:`L|B9ix$j2GB~Nc_7ۿ2&*u4 us 1Ɯr~؞m#Cu0Ѧq9o؆pF+LRjUf "t\UIL?4R1D<0 !A5V5rס @AQ;M8|<ne|FP(E(cwu+P5a!JUg:F 'Ir= jBR#=QRkY/t/EIu^hG {k݆W{@(e"'ᅨ$R4R)U魖w3<'`X2N_Ii&8v(qӚO !TI'?PO r2aA(򣪪'OpeBx|sB{΋ {&oyN!+>U ;8ueoO*{q2ϾhѨ ߅M=iX0-,>ē\ n 'Wsd%}xJ_U'75ވL/ӬG}۵aShx~2HS|U4Wc< -g[PM,; 4 hnO3ɣzȪ܇,Uc U2V,;wbl(wvN;={ 2J%mXd^x.^O}]۶f<:yAVK*>u'=ԣYڏ:~vX.\9]D<8 s-ܜlz4dwYW }KJ $]McN~ک ohEq^7V`{b-O} >ob2l}É1p #2;&0uI\?gz1i@?q0-4XM%ga@TPO"m8Ǐ @cSZ !cjZjmZl0ô֣r!H(2pOM{VmXf@O>7ӧ0vS?PoO/-9Qi!j(ʟ] {~FG(<ãg $jelRfQXq=F\υ=뵰/::8mBg?4-& X@>_PE~nmo7࿑{_57>1H-* 5Ӛ +vJsz 9YmNBNNTr\ÕGDb[oS=QُZgqٰ&֌G6˵ x=4өD^xmswWs[9߉QfYڮ(/|v r>zD ~Nv:sƟ酛f*FE-3TI7trxj9*г뙔d|3C9Rk ?ݣyok7( }@[M>Y"h -2^^+/Ӎa[ o_3[KY\gq~.7 :|Q~I~{^/+L]PT5UsF9@[Gslmkڋ5 jXhlPB{J3 КueW/hQ+PYTJ xr 86j:=1~LB;AJGkjn}cpßQUذ[˘YFQ fIjO3RZT}zL5FT4L-:u8E~RQw*;h\ݤ/^ 'eCt01Uܣ7-"$Vg/e؁6C; h_tb.ڴL~i `zQ76+6f&0 1adpGA#'_"ޜ!hB^e--SB=CAjGF#hyrZ  ׍G.]*`A)e ;cJI@QU<}HaҢ  w eQOVQ[ iz&ZkKM55IgI4s?p$.$mIq6̛G0^K*h7SVuESLHclDOm43 Pk}H*qN-Qư/d)Eb ),zŬ7eod\/ ޼r2PQ_cǎ(?=}|7?^% K0HAPz=-'vz>a(3TzWIfn+GՇ>Llq2Qg d_1M:h@S C.wP?$MXr gLd[23_Ax8΄!;Ʃ 2a=43GeS;==;4i3`K a3c2 Bw0OP_SW[SIboR 7 YPq3fý {8`Ͼ,˕Z$zTaOAS;eʎdz`Ekq $=-1 Og?|Ŀ:0J2*T|hu6x$~SGyN6/鴬ԓr/ϕ-iujIeLZ7u҂ԓ:D}L97xw+w:?ҟd Ljo46AGջZu,Hzk/2aHdBRٞNsp6|FqХҋ],'r'Ã:e zR!LB!+  +,4C$E­޻q^L/LjJ=bNWۻ7VY LS:꩷sz:VUKKsb5^Laѽ 05W;&n/(ܾ Q6+^6}s9W_dleZ–r>|kW!|Y^c"q)ΗO^˧ cI"t-Gԁ(zX iFe,cOZV8 _Ԩ 2l4L_~ ~1Y^ SoU ;pH\1H/ hG#wp%g#(4z%[֧!Z:}pz09@zhWףoCpz댓ۊ:ƴ7'T>\ EOh)RI)qС1eÌʐf*7 a%? ߘA>c=v0dY~#ϔ~˅)oxct <"gU,QtɜJѴږI˿9f+/Xx ʖ3n@4律MI SlR W`=r ixhDm~~øPnu02jxi U?N57b6namϗ~^>\1l45s7Y&gS =ΓRN"  p"~,~R}d"E>gp3/°!1w&5|z_'QH=/*ǻ{w(Rqgoٌ1T0uO^뛤q733FeU{*_(. SWNM;kV/K+{t򛏑BW3꒷{eޜb?~ĕ]w]P$Nl%M z{3?0:u\;.-'^Rwر U{1sa'm+1#)է'P?Jc|IG'(뫄CJ+zYX(arIIa=8 K;7ܣQU ^KQ/\v0>B4KS-u M<"z0ht¢':RE'fpY+:K$ 73˰' f3//PMtQcZވ(fقFdeoペg/˹PLOGO7mVm!2JC44P'BFz񰇶|†)j : Eԙ:K aNoPݘ6:DױMS|7f t8ѳ6sƐH\2F& f;'n ['$%%Wdr's9("Q>vCs.5I]Nq: J9͇I a0vDT`%kAA. rN# mo<(L-ȺdGMٰEt 6"CB SO6#^-ݫvsP< #A1^*SeS RdM/Aa2yTzxO`u,KT#MrM)'+^,-*?8p(%qUG9@XR=Oi˯>3g&'{3 #Ժ Q#nCNF&NGPqZ8KQA_]֘I ;nzC'z'DK1_KoI҈fT>ΕNqt PB+3(rJ K:u}j}zJTb2)#f*H& :~p_TC=Ńc RϙԁRii4W&E#'A]}99Pa0efg٤P.NO_;R#[x7y}IߙW6j)$DFKƝJǟxRu'd'%7ZaI|'k5FXa8srrv;L$H32Z-}B"YH1e|jݻ7p=/>y!Lڛ6mp:OuWD>RĠEUi"'|i&( #lQ܃jY$oWF]0Ro6UKR 9}ҹ1UΑ.yrl:k}v_[c[tҶ;v@ttt+@*?`BOS8oI}{$.j{V\KٌL&=NhaEVʷ#=i63c~ʒ&zm7#1dPiz[I=̘0@l*,{Y:8*ޞ_XZ|"e,65FJ+=2ه} [{o7[to"/ M]n 5,e W/ǀ 8Uғ옯V7-٤ܷI ]T: z> iFIˈpgJ/mXs$'IU6,j4L R$ݖiA*//zɒrq ~ 5pzp<T.ʧ{4XO,76[m1J_e#]KO'clJӳ=ufƓ>0T9©xvwz@k3@s@Rf |~ʘ*J .άW[j0q}'wacbuLV3}3 QG Z,0nuR[ifE=cCLVf.I۸q./#7$oЅi}.Op]$լ^CIk?E)j6;Tr%oex?{1=>%M؃wh8l9gxv\3=ޞVπ~GGVi^|cJJ?~ ?'={}-}@]cӃJ5Y]s jwK;WU H)ΞV\wǸ$Vy`9Y_~[ՊUE#Kз5'KCaQXꯖ#W>F[o+}25u1#;~@p-U-;zkߕ@ր<ԙ EI FJz%1f!l(dٌ5iĮȊǟA6DO4&xc DyQ.LIwnz ǨvŠ_аDŒz0[Kg `P'聝Y6!! s9B`py-#**Shh S PK=3B6Az>@weݵIlچj6è׭ǩ|>+d;|@P؁Fo5(;t6w7{OTse zz2~.*z8~: K([j@^& ڇX1ommGJebsC7=>1ਨA7#2R bI[^Y݄>Q`fzW7a}hHlhb>_`ú[ɖIzV<&ORޓ+ BDGfFO;MG9QM UxW(s뢾6RjC^Qej:9iXz ?'N1?a0&}yI!vXO^+VC1wo|N$ahk7+-(gLIS'cYJئnK=>[z bGIfK𰝴Պ!8%ظ7}PQZ 蛘bЁĐRazWT6!G! bn s>7R6m(WOŊj ZN C~6"F e7erKǏ¤E)bo-e }}kߪxôӠ%>F s26u/C3@IDAT٧=g``**?sU?v]︄ܼ6xS՜3FL$Y p>oN]_3msݩϗ~ձMk]{Vv/C~zӒAPs:X%]iU)*|(ϾKJ>(ry{w/ܿY@+EI|6^|Y2S®5ɷBBh~kaÇX$ҲdYIhte:8~ے‹".Q\osbWgC.N)oL@V44dj̽{kBp̣HqțS:,d^$~pz?~m4ab}X*cO"~_ SҌ=v^#Ve?*z;ŏ>5fw}~?˷FRZnj{nSJy_z7>|g=m|},@,6ko)T^2\S9W{_ş|f̘z{}{STtǴj2|4r7'󮇻շ_2`̍wpP -]Y?M 043=Hew= ذVm64Lv]s%$:ȵkۦ#xI|o|œrn}awjH=GZ7 PGƧ߾5~mU:}X8L%mLosY)5h]_ǯ_ cuŮM[Y_Pb+{Լz_4]\\tbiJ=.Wwψ1E^p8Ds xؓj҆zp$kl]4vSWT=b%6`ȑ?/,FkaZ 7_B,-?RW4 -5E1>x3z$nXPBbDCJqM]x ;k "3C Rݖ,~U 0ﺱH*SXo!u5+J[U4Ʊ03C騩'z!8i(,ȟލu-($O(jP{|6:x\23U`Œ)h3y7͘adt:ېFM* B.fr8/z2i&C2XoԈH8d:)-4 +~_VaȱA LA؏l9_# W؊6"W1)iГ`p63B-׵5ھh8o&;j"OFyf3 51NAϜBVDx/|$_mcÖ9-9 1t 5.i̧C=co-ن@M2o*_6pmǯYMnӠ%ߕ'33[n=E*q]̻q8L=ƛ[ъӌ\9*PK+T jdݜHpVAD- _u&NߒW<.-hh3 Z5|IKJvq¿xqE9x@\^"otMWKF,PujRQP 2M +6B^]5C,E%vm{{вv쒪̹-’ b&rLBIcǎ}<0abTz:>]!Ln4J鯜ۿ^'򃵍 F+W@bG)? łnu? Vbw"wrی~;/j!YyW5V9&H}[,H*pvtySI6w?|^ ˎz[}ZS]Hc5^,83MڪkG0R?OfByDϗ~F x[ 3M~ G_c+kʼn*ƥ!%%-'jz ܇xj>{r_{>')[QhzYK<_ѳTM˸0nji"#?Uҫ|5۵M IUŨ(#Nk*-sAOdOy[L,Hc\L&uX[X^n\q(4k=%g?LE9KZ3马۳; H: .5cjf^|9x(qG{2(~|)Eu=f/\wZNғžSFIی;5fҟqr w EaQ|ax.nW;t=X mE􀥯=[p<~$ЃslOABQ*YzFP( h(5ϗD^qZpEFc-tpJ: w W` Aׁn9JkĊVЧBua\iQ9ZM&e]CG)1z;?33S;,.Y)}'Erz坎KNt9̏=b⇹h =幖Ϳy.HBaЄߩxՓX'2xi빲 uF |wOiɰx6ײr5 %%2Fn+{qL`i6*0X.@.x%ŬGuc+>+*7-jwRˌ1lɮ!eF~ |\I6J K1O!\O{ÉQ^uNk ~g ߋ4\_p MFXaƊ񻟕Kx\8uels^* 6{WWN&)Rn{e1sŐOX83()_^X# mD>Ք/̫STO5Tb:gh^Ls繒+ gzE;\TS' w_q"dէەJBR^N?2]vRa/ItD(eg%U 3=uaDf*w5ۤA!}zCr\ڃ&Y-ZZ -qNC,J?Qמƚ\wЮy1J Pv9Od"A65h@ZOfݔY7:8},CbĄPsj+RSr|/L3Ǟȣ7dY A=X1%pf՛&N\C|]vO_+o0fLXߙsa!﹓iݺy/k 6tH$xd:%i(wQE lމYgJ  SSj=7ՁچAZC*dr~T<\<@pS\O鴣`Eoѵ{ˆwvcz`?'KAߖY'Ȫ,϶3j*gk'CLM_OOT0&-u0c7߂Sim& ɝkVD*I{Ԕ>[FyUMah#g &&EVyz49id,)A/Q-E.n8Ba}}酚 CGe c:~ uw f֠-R Q] ]KT2&̂ B׼&}>ryŘ8fIHÔCA",y&̽ CkVH9 jI:S`SهdC E*Ai>ްyS^\LxEFaQHt FzrXW.QFwل^Zv07€0_IzS j +'p8RN.4$iv&";c3~p;Kn̈Gkڭ.zھ޾E>ɚr kom,cWf-< uiҒ^ezRt{4~d;^Y3# K]1ضk7Ft!pX8sۮ G\u?-=+fP 4 ¢b÷0Vz'I?evQGݍG}q-asZaēʂAӪ@;7 ětZ\עUSvm8_~iQ't>$d#*D5EhŁ B]$hrBa9_ud1hnNI,V1y~* 1T*Sɇ4y g|w>7wwpDg.yָnTe KKg̘ ijA3v }iZN'}U|D`3V%VRϜz+,%3@U>?Qvo}`pPƏb R/sM'R0P8M`vkWܻ6WNI-m`{U$ :號m1oW`kky .V򰌱D$>56 \dT³Ofu.]Fdt1ε\VVy6E|R;EK# 4mb`'"ɀ:)#ABxdH4UCFT>У3#i( RCC#Fbh?*]( fR8{d\ΣΡ:%zSU>t6$U9aP̗0"HE:l5q:.+hZ=v;{ ydo7zsoI9' FN:G6LFbVΪ0w)|Z8lHTgu'Uمm;V()nK˿'\.,6ޭ5pì {qz8RVgMOY+n|-HM؇!'a뚟aK0[*Ӯd^;:j̞y>؃ؽʴ*,y5*kqۢ[q,7,IDP6ܓã)8?/} 7Ϟm{7ѻ+#v#64V Z-[LqyE.]>ȏJ9Z=+sVI!:X(pfٺy][P=!{eRQ.5_r-o`5fZLlS%jSKߝ{+Vy7rWГHd+;ێ9E^K_}1Ub^IU/k@yRk1]m_]ḪTۤ3ƹ"?vV:nOaEUuR|,TLRi7NYЗt>#{亪OEtj_TRꄢ^J;I;Lr\S\GZugVLǢ,2Cs1 ilǤDCyt LyowtF{d1e9O wU1,WbmU‡ɣG&Ü5ڂ L\G7-V_twHW_">.a 44b,'xڂqOWF+ڭdp4"HGEAǼ<=agm]\W Rb9Yڳ~CSXLxv#8DM÷Bˋ`qҳ /1ް?>[s 0m4-چv@nn6IOຉa89t @fQ=*{տ_0)zCZfEAq )H"o˜Cp,'˹ш JFCVV^'.x\Ӎ`oImHzTI^hŽM57~vfP'@Ra_g>^&8' N;H@zMN%D.) Xs]".|?%mnFuKL -+}4dDZP܏ƄuH͂!Zkhm:Ʈ5m B}]} Uj3eKKa?# dY=y``+AzR,Fv4tㅭ1p71tp$o;b63n >>#Zh!nXyd=7݈kû r @] 4"6wV 7wմ z}3P:λat jOh8dʸ^^>q:ܴHDNP O!ufd`oz6،(pb1u aߪA+߃%#H `ih1#Y^iAÌ~4z./,[ˠ]?&yXE #FӖZb3*'Rs}SƓГ:8剡2-2F_h6. dulUޗj`Î{!ϋV9smD@X8Y2[-"mIﰪʠ&:57:tw¸VqPmlaG W2&z;c ޝ=n,,Ķm[akesQ@ZH/vL  ]`w…\W:z(b% L}˱z)| |e^(Osܲ/?lc.qpxF6--]g!=#M`OF$H{3x0v,~%W #z7cldr)P5c&vbKZ[< Hgl?{I~[ Ǧ`ڤqx/ `=tvC ?xn͢^-i"Gvyͺ˻IOݓ)/Km_jY%%TT I_ Wb@)5s9Gв,E.T1uנXGt,dm ?g)JIީby%r\&ՋNNNVbc 7|.ſ[h1vJ}h_yʢ&zV瀬j eQ' Fyq$I@>JZ5JEIm -ʟ~-{)đ Ҏh%oɒ^f. *u8]Y/hpBI^.i\:{(E@ h>twϥUqE)) _%ğٞokONTuTM?nY֢ d2q<<-aLӳ߉ A"1*/(=r]XF *my}Bˏ.5WZ;=t>zEOrekI!'kMN=pM,þq̼)$W`}p7>CS*+DeNcN`OS)[9OGU>!ᰶ>+kɳLyn pGpW̻2||1s\Kyg!s`آvíL#ϧO/֎g GU@[5-Gh0(kwuؐ *uU>P"`D^7qrKʳXt=pI{K;}<|bz}o?6~xy&r֭ƍCH}{,nZyi%99} G^k} ?ҀbNڟ0sl etP>ZogK[j\jW3&*˰%dUelhJ|8PoecN@Eev?_iXR5lT%dR_-;y޼=y8R.ufs.`^^r*uX{YG `^օ~Reب%S/{ھͶ?)#R$zuPd5;w9*XOh#Eax&+ FVeSK2,Hϑ쌬}[UUEboF59m*,9e{JIPvȏgiii7Ԡ"Luc|4r*x鶷7xN= K 7;!\J8ƥːz:UUYFsxZalʨEQn |=b0MC:PfuAJfհ^$7)3oŮ K=g)OLd'={c#Vذs#0'"H?;kƑhoףSn2ue$ vl_2BZ4os \ɀ1hطw&DnA"Ƥ ,[s6Jv@lߴG#,%vw HƓFAU)-iY7L>Á@)Xz#3CXՊ uvR;8kaj#9$P'5 y+ +Zت ݲ"6ԣԈfX7eaN2La!桁cnm5ds:8ػ"tI~2M?vd1 r~(.H>a'2Ғ %@Caj^ٸÕ * rj{ rPGO@:cjNqs?`#BV !O%ڬYH>ͦ}>PRZ {xO!5cVBwad%x@5ҥiH< Ι4ko;{S9Z :(8]V>~z+w4zRbcþ5o6J0~H7+#Xs<9:/GTN*qGb+>!j+1f8 4ިsj3C' \lCP %5uJ-ۉ,޹Csx^ٌ[o_`c jipDmk2NvGimu <:חˆ6nH#AmTL?z J٠f!1_L`/HY_XDsnvEw`;f͜ 3$&+śT6)Ŕ=f ო#cht`7EzJqfT7T}1,TAJETY\/"{J'*j"t3"F9K:ыҴ j ?&FGҋzWO# ?V>}Zz6gD4%Iglܐ"o9'Сp72K&tk_ H$$ Hwm0 K[|`$eW+=;^|Ty,BR܋D{;f_ r.2fq*^Z߿cJefzG}u޶-(kEWϑ{6ݡ{ߒ42ɳ^m[_i bR!ts;2<"tOjǯ{c`(VzKCv۽j%ME*ӎۯR/`)'1ԯ. `#7x@Bi- xJ(ov#Z<5n0n(G|\)Bʪ__6g 2ܢ݆n~aܠhVVf.-kQt \DǷa&f^w$SOshC4gڼLXzDYve. ԇ-<߹R69ϲyD}QeDWi>U6Q 9|AʒDG!ߕ1T~uMi2O'C $=JݥΚIm1yH}4 -4r `1X@ϸ+Dk֞Y9BR 9sJ:ޡ,DE7/l݈#;جЈ8nH/ɓhIcG&5MmFgD3lo_U&,ľ'`DOʪOV1CUաO_0U;#'7l49: 鼤=+G(Œa`Dz<)Ejm,Rf߉Ti*lЪ :f嘴MY[5OL"D3EZa -Rg8N 2@_ ttuHQ܈c)Tj^>=K aOy)bCn:A3iF CI*:ªVe# ӡ+2 )Ő v5͞*dffq@nRN$Z`.V-m ƒ@)[zr!BС^vtlvA>.4, $^өojƑ*V8>4EacCf4L5UHþHJ:)݂x{:#͂ k={Фw!**0 q[qb8j?:rc߮ B[1C? -xfbXX#b@JC s:kE#GԠﭹM #N)`)޿ppm'=K ,7] ` @[*TؖmmT[j)P%@B37L>Ph7ܹs̕1>Y/Ɲ^ 嵠nQ32`e5|ɰҠٟmw}5 $c샅6AJ#Վ|6@=D"5vx+x6KXC^ե`Pax>a Ӯ^" ZQb pMzJ'n0V7NflL/Cc ߅~uek`Wt a뭕J@V%&q5}s8ВN]"ҟG-q.vv&m`YMhՓYg(YFXz1Fi:8}'=$YffVvtl#v߶ xw2@;xlrړn><у#ƥYHaPXu-HǠ!5HGG^hԬ1*[i-Pjh)iW}L<٬YGˌ ^kO3XpkRbݞ9Z}X)8 .bP@;9iYŸ [Ͳb`o~ثx^{-iYI 2xO1c45D!?X仟ըvǛVkM^Dj9,Kvry%k9jSZ@ iZI+f+-))B B[uǁHx;UTS̜t"B{#<*H,<ŚT6-%UdApP\̦Q콳oxfNVI >4d|z:MYxys0yhU&;BN[o56vD1̸={u$;6RZ()))A57ˢ_!T^dTu=ώwvݚ'^޹:xP KF|WCn2,^Mrq?5 ^֏>x׶ɢBTSIi *50,YSmt愕%5;3wV'&sHEhwx2SIz>9p1D\}Q+Nj[3@ތlQgFo@8|$i&q.W_ǨIW6;?k{ʖ0BeoǯvСZpY]yb͟NhbGz); \Dm(UCc5U9G/%(E!: BI.y;H7F5A)*Qߙ:G|8vj8y'ܣ׋E9W/-B帰(}z:E+#Li(azN{֙,A82dY$Me>/N)d?י;mD^j o>A]6c٣{pmǁ8wÃOT?3ȤoXX;rܺ'K91H̷oT4VaSذt1CqIHN`W$LA=id,y y#yeu'"<$^tXKl* ΙY}FS66ӏ(AY0] ڠ1d{XqFD_O?X`V^F28:`/ 8fspӉuXfyarF!:nH =J-)2w;3; ^B4щ=bLB vP GqQ9J9^,$@e*˛^Cg>;Pп$W{G,a_eWs.5{*JW&piH9U_׮GoOwu'B7㠰`޳X @n߀bᚕՀ4w ʲ Bh=z9œ9Ockc/+'duDz 珶11 uS0/*FX?R ܂@m)!*ѭ*ɰŬ'CQ^&,q0&{o=wp\bolWY n>3GSOr%@di_MᐒTQv&ыo|(%-"hiA?l[nT`Ԉ8]X9+ҲKB:S(( HJ:.AZ԰~BBtڴ.d[%)o_뜲jj#: 2.'Z2‹ y ~eAA)c:4!.tC E{:=0ŵ<  `gl;sSKw0}E6# j#؞5hm ZR:} t~/)Ⱥj*,ZAdUŌْ&M_E-aŸ982e.疟 6Q/s"рWNOt ~]OF+@M9=k}?Ђ`̤I~="tFƴn`kdE:>`<0Q@^>k؈16/o+Oy6R 75/.FÕRG ޱ#;vƢgDUyR];/jH}d[*vd%mٱ ]﹯)LRTcyw"٨-@ W78t.֭0yT.SZLrnĄc[<ޞrr"<}vY{?/mGeE":zyUsdeff=t=SkjڔtFzYr1oJ+R>yߥ= w)!r=HZ1@0c*9&b8Qj wTƲ_]Kze[jwlHlHҥt`}՗{oo9I+IԵ7b+@r_r\ՏiZW&&O}Ed s4ckH-χ@.Gui~AVynzyN&O]rZwp 3[+٢'.6ȪA$*c< \5Xs%@IDAT;Rשg;K+_PQjy+G+(i)˟ NjZZ"cy&v؊tXE 4:O<<I} Bk }CsY=*'gQ{v3.Ld{,?AhO+,NbLH`hٚ4w㩙!FE:dBX8yܦ.c^*zo&#Kl>zu:O Ymڧ6p7Ò0!p6kSUˣF Ý?(ۙM@瀁L倗_xq:TL>n39EXa?M#H3 e"n%?ߓH =)SqޓdSUick1bZD^m d촋)i'k!"Rڭ;šI4]fBC~ ӯŦ+Dܬ|9G@Hcc)|t DE^4rɚ߶bH͑Ů^;Q+c@/wγH# VSX5ARr7>0yq~>I;qFj`GSma=F0aaqd^4whd- vXшщtǕE|eiW C!.+ 1gy Eo2ۙ !02uƮ%+xN2+v)+28rܕuZ?##!Ι~fuNOɊ}41!!{8˺J10# Nz6fc5p~q[9F8x;cdž`eWΤ\4^~-6+,48d E+Yw5M{MS0ZYrF =ɏPQoK'1pak`=v$^ʭqB>t2 qi4u@%}z"(Bf׈X{sHK>}'IT϶y7AG{n_J[=rugQQ #ɤBnfu%]tƌm-P;t8$bѣaeq}FjUՎu'E }Bྴ>Vch"KS%(6ctL&EG2aafO*6 4pEˑJnF>2i k .U{t?bT&mO>zEi%Ubh#Fs<$7.of3t,7?žFTHS3z'rP*rd^wxŧIGTڦb[W@'p21 i>(;Ϳ''˯pj:ry|IzW_60#97v"0jwl)Z]]\"ʍZQdh;[8h6)P[9[RBgJZZ9Z/zgX;gqdgaBG Sw|-e%ZGr,⦵wQݟ:,h:QI>b)zr_uJ9aLEMK~}&7\Qlhl,j6*H(oO9vš+6@+_5$P菥N'I+/q{&eWG֛9@+H|:g!;vѧUu)T=ȶzFg#E쯢lZgS]>[էcwdLa͊!|Wg,Ey}vMu/r*vewX_f{@,^| rC>;x ?WÏSWZtrŊ^#xV"I߯muۇomZ wF%m_ﺉPXq,HNCHYmh9N?u}v8z/`׼Q13[7WusT⿴;"Rz]-Ms-Fg%6oI;5fm~Sl@ѾW.'`jr՛'C7*ug`AThb7 T HvH]i,D˧}Hk;wkV/C5wLzыA/GOwkv#^wRe_G?} z}g=zi +on׼n;?24羷y I]4nو7ΦbQI]1zQ7mSO|Cc(;f݌{zaJIb5k!]=} GW^礰)W>\燎O>vbdcw5(" lOn$ˮqg0j>/sg>~ dէmݱ'ܛ'urzeMi"UZZSom["ѹvɏ~~+ߡ^ga$ߦ!q.u9?srG![mGe5zP_~&3]zdޅ'8ۂ 6!8=ifuؗW^7w)8Y+0(Qޝޖ[ޏ;1;Je+12Pr1=pb}&k/* O?Pً`jA:NvVc9DaZ#p3ȩ|y9!ccd@v?_z d9J2j@oV+8bږfQWp!Ω ¼T;2M%yVΜbŚ?v$s1f8|{ŏWhzQ}lB E B?2ӥzR2+Y %ݭ z@"8yZ%X~,Z /'tSDƐ܃qMc2pNîBzvw?C`Ɣ!`ȑt*ĎkOV`Rq8C#F2l*cf8G9g @Ρl|>LB5pwGޡcJ{‘tą5h<cIfc&#GKbu;qؽ}§8%824s5 U[.(KpE8&]pVgfCa z; S'pu Bf#3~9X7}/{k%sı' ^v('v+2v<ʊPDVJOR"[ #s>p/ ?טmFbSq-з5 Xy!f.X;qㄫ'Òuiy2ȴB!m.\xC_~byvB7D|ཷCpyh$;\m\b*?!(` %h1o:\8b2> X1wrn w=>Ǐ iwu$4/7_>ztƀZ,m?}Ы-B '(*0,_иf il͢ {Gʂo6z<*9"V8햾(BS2e &ߠs;m;pը=BȰkghmNih$w1x✶ۻwL/KYbvn][K S Ovx;A@Rx&wa/VBv Y #L9#5?.x0szI_~LVA}{vQR*Nc_ph@_} K*zи@c%<zAޞ %^*/Vu?n8㭝⫫qn:3R{c)֥o87ɞ/4Xͧm3I⯟$zΣ֯^>})f6{|^/}Vܖ*˲?"J^K&ҥ jȻgk PEĒao1Pʥy2eȽH$mN⌷߿3d,c}QwNGͯDʠc̦lV%QVk->+sRGX)m7*n'?Nu;' Ɔ>,FD j |ʤ5 oU03Hla t҆SI\ KBQvXb<Ӟ>'=8X-)0ݻ!ٗjZ e@WOHm3qҭ9tNKJ{mOw?XY?~5 տ +:bZn߁^t#jQjkWOzՓ)Y/F| 2h0t@'F N`Guܾ.MҒbf 50<z񓦴 J, G*XtJ꭛cԘ=kHH@Rq>LoM;s]^bUk{t)Ӹu,J`178i~Y VGS31}ˡV|cBu?1$3LnP%},7G)jk|bK ~8b˴릳Ao#TYW>WLl+AV5T20TzoL D s{5߿g)C0x3FRKDd%Jߛlh"Uh+ u][t_g[/sN͠Hyyg}U2Vry)3T'fU}gR>GyRnZiQ!< 9} ټ23K1CJJ& rш!xME `WUF"#}5, Uџ@}98Љ4t&3+LS"`k`XPK69dHuzn\\TށԽQ_M|O`u4kșjgalKng3yDɭsGFY#5޲ [E e|6("ڽK*3XWJkLv#zLtUщ]5vM K#m}׌sR;-s)¦6T-mDԗq[ڹ[[pߞ|Y_r`)WAK7h8Mx8QRm0tx˃Y}FQu1vl%eFJ.gaoK[ᛴ6nv0nD=)ڶhӾ ݐ- #2~n.LRTVDUK|)G-Ԟg)W э.gu;;z YOZ Taà9՘~56=mS{DԖcvF5z;$*ӳH 2r\R2%Z FDM\LHu c5 2 rq忢QcHF(ƥ 鯥Ց4qK.RPWZhXZ@DUHz;N+TlyxF_uUTOw!Yȳj䘈Jվ5(';iWZ}LӴޗ|7y9-).BN'r-;B-뤫'`?cc\,q1l۱ ;wXdS/n޼s&R7.w?t rkb-a??לWZ- s^ z򝙶v>SNPmֱ[qhtz٭)鴝ծ}A;"ZwʟۭSXsim~}wKou0, rSӟg^}7O zu+vo,i\kI&beg͘ WjaLWO3҈n53Й W_cC7g^"6Fz"VaTLvᅤH&?c,3?篾+]fϽ|yќfBnwƌZGy伧''&hiB4/d=r88)V,bi_Kۣao." q(-I"B(J%G-+#?CsM}@(CbcwbWL ۹#A;kT&\l,CvJL掊Lϻ\Ar^rɱHVE3'>[k4WsCcj͠u|P^WЧQ۪LjUW%*֒F+q5Ri;VeiUζҨcr掠kZiM_+W%zRZ9O3{91OEi휋+%\ lmxe`GU x&%l3OcagUi\x`!aڤ c|mkeܯ[c1Faie+Wb-w_0<(?̎!|V[cɢ粳3ݷƔf[ӻ/9YHMi4c$$f#jގz-11nͯ.CS;Eƈrz'9[ÅqP+r RZƣe  /;X]z!޺yޜhJ/ՙGu rtJ[{`q 膹?j0܃sާ;VE=={7Xӓל^L?z#qe?n,7W/[GV"f tD3 &kNgۺwu3[C>1vp}k;o%VÛ`;B扝H+o'ˊu~Gwpqs<{v`Oi͘ס߫g)R k_z0z9weDD_2`Ͼp5rPO@}UӉ%02c?CYKSK)B ,G5ueZ(M*۪mӷ}ZG>LK究/'\xL2MfQ!iȃ <2hү@U_|(-vz?$&ͷ܎z&bذHrf0C L*4owߣrd&lPAE/iBa WדC2]BPEkK?uK{UǖO]WYn窒 6ŲN,;ZWKC6%)'Pof&n-ONO cX{c-ZҡsР'bLZ!֖p sϾHk,Rqwթ*żJRju֞:.kyICC39&HbY^kpǍ ޒȵe1Z SBI'ߵYF]KG%@'R.oL}kg(R[3߭ԭ[HvQ,[)CK"Ir 3a iYhF+"9t|GЊ)$;"ߓ94҆uk FcԦCͳ8H nگWӎV6|’6Z"eRRQST*Pְ#*"Z+t2`PjZQ7#ϵ}+<9jHe.sq̓϶X5Lf:=;KֶX 5p)moTTT G/;tG>x7h9L2L0Yr~ݷpxј=1zmYvh^2 _ NWҲOLTe eSOΆyctG5ǒ65/V97\A@S"Y7ӓ).qCQQ#Eǵ-YMC[_#6ރ]"rp'9NQGp.,@ KCu*ƀfYk{R;odd!8ڕc`_'4L:c,Ha8Nf'O˻dOtmQTX:cW!T(:AѡHM/hX\qVs}J{g=lkil!o)휴YđDgz1UE#a3zlM7[\Z"gwyΟ/݅C@y?~wV/ g'9r/6Do\Xv%EiCOnzkvN.CN:Qc0x8@wE/O'-]t ~Ea!K2>%dm *z :IsE"¡ӈʀ (" )ěŠ Lf`'R6 &tKe5 <_q"- Ԓ2Pf:uc-.EZ{u+\x?ZL Wb / f͚uNNF`I@Vx:ewuw6 ~\$}E*oYs8k0)j.DGu{_M`tdH s-]3Xk=Xq/gLF`|95`bq|?' @ֲ<;;,V|zi-?#'31}v*]˳ ɻ%tM15=_P 5lmaN+ɶD4-ԝ<or*6SuU9=xFX_I-Sn"ޫxh1;9 $+r9I0c_~~9=:4mQ(L@]ߵ=fnVW1[h|}Pձ~5[O6SB{qk{l aܼ\:ߺ RC8 )tWQ+uG|-_~))g~:41L3J{~dcP63E )ߡQ& cuਡD۷<9(zAEQ)6$Qt`](8c }-i}ƌfUhlE@gZ{bZ!:)iŘ'Z "m،C wɯ|߮A*j&I9 k[ضy ^|9lں^c4rRzNoVҋP୮o% 4NoҪ&^iă䑒t]"zû5W1oNM/`YwDăB֗^xETppeHY.fG|ݻ ̤'L~*kdz.l,O4qR{ΩXDWMs2`[~1_4$#F 7݄b>7WK t3*0~.T%=vǬ_P:먳GsνǢO3šQ|+컰Xe6LFj]JyCt%-͹d̝ߊQsc?q1K'/Ⱥ#TO,wzUBح>wGAVy+һpLc뀭Q%`7V_^͸\WDyh;t?{k E? ɤ;M'#k+"בյQr^+HIZ}dH~qc&7kIz8@s~PVDYQ ~.݊[ 9b"P>-ό#9tPt&OW#.Olu8x*k6+ºl}{q)'J pB9V)Gx8}1pmr:ꫵ d]j1kWc4q>>ޓCe1j]b"k2NeJn.B;#;% ֌њUX9CW-ޫ!w( Gcc=|O$ㄽ3,FGpvxpq [~>M DR-Ǒrg忬'l U\vZr[]kb2lߏHY=z^;ͪ(9H82\ y- -h7P{FXh7z:R3" uhϐ+u($f *2xzc=H]iPQNZZk,=@Y k`K-^-%\üG I~vqLwNЮx=pɃ##o{K 5w76lg u <-&߀?LF/ Wp(@:t@IDAT6dHq9pнȃ -яn,$pZiKQ^COA6}c[4..0qb? GCwK>L:u2mGuǑI4=ss Hmi"}'rz"Of<cρ#8ZtW]7koOMeChHQHS{IQZ>.^^1e}-e#oq65jɖ 를?dɩLj{3.7 ެ ^-A퐓1ki /ZE7_a ]"}:v@oX%Ƨx7c,7Lzli3MșNSV^0r\:S zݯ[,jHuM\EVG<@*|> >ضҷq=N[?В#x=y=cζ}LdS[]>.@ICl^[a.(cL2,];錢RњJD7XSx<&S߾F+f\`I(קCFm :T0`uy~<{!`Lߔ ~R]twRΓAknIg0pI#S퀬RcuOk=Đ4=9j^?gŝX% 3R7Gswĕ" 5 o &3oAMVd%(G  ^/S,ںOy2ViV,U0]ktP|ƴ2Ɖ~Kߜq$J[$֋P4{DIվ WP}{O[[LXMJHfd YBI=$9t$=~tW3n˓ aǎ AXXD|xh˼_>"mgv]@)ks-A|,Ό}-o?[I Gk<&u:-DE'}-'o2iLT}عs; [׊zUvz3Fϙ23^Xڅ/Lľ72ΉK* 90) hՏ^-ObEΕ>QРCi^ӫfo$@!֖XX kqF8joԹ 0z@ȽKG/ßn5l?;.d?*{2'U"1ūS%CwsA xZeeGNkJQ xi+5cfuA3TM6Vs+kJyy@|W)U^]K?YD$,-B *lͧlhT{{Gu'kc&-<¶{^mRGwbڭ .,H6FMw_=rc9-qEG"Ƶڟ Qmz=FKY9fK{-]|փYaOTTYHyloE~H)\hi;/Gs^%yF/22|^SVڴlr[:P kr},힌zs:,z֤g'ŨSX/9ꧥ˼Y[$o%-c֘ٔN@ׯmUF}Z>F)2z+O/4nR=/9GYq!"u ze-:T&FAֻ#?|mn}qt/CYf:р&2&'+26#qg]~'-6d{ tšS=]HjJIPnciGlD(Ի^!r<}Ħ3?kA([b7a=S1! U6? {19KG y%p֛wܜ@K?o8 Bx 'q Vڸ#ca腱"sbO#Wge#aaaCO.58Љ*WEy5HIA'zFcr \]]?1$ |RLKOp=ux;<+ri.)k;;4fwhQ&b /5RL΃Sl,PRHORt0gbB]±Tql 6"'4{ne2zw.^8v`٣܋k=Ry͙7L`WgY# FhAZ Axn[QD:`Ɗ6u3o0|>suU{4zvEU\]epmrq#%|QE8"1Gb )[\iNo>zap5]=M(gWIlӹBu\\h?F`-*ȃ5$ R{ ^~-}Z3!;!);,R^.%HNlj҃+as-!(z`+lVA3AvA>ֶ֮c:E*\M+#-uYzEnUKWӶL/+܍/YÄ? ԡ;D`ѱgU5s{a;E`m#a㯯hޥ#r .6b"/*\R96Z{O{S8 s%r#㮗j1xǪ< {*>DX^eCul,/ KrLI|ͷط? r7b[\2\IUpΈ8a|`>PVy;yH]=pUpa{noڄp,ib6p 'A=c̼ }ޚ8k;p3 T/9!;7,ä;_(Z޾(zܴRˡQs/qp^*?:kHqkPS-a#T9rKŇYEyKXFAc/H P{6^i{>_.mU8_n[h o>X:\S_chװ5ouSenOUyJʶm}E򔳎rF9)W:[xiNFOrx)VʗzSrcl~yĚjA-q]wJ;fd]_}p]n38}b|'ض{} n2z_OG0_`EH9URmj0wrE~Cf:͞hվмz=/ /_n}k5[K~1!c` Vug$)JV;u(FdZt9H9Tx;t;t-B΢[aሹb/0Eypl8@|Ğx>&/LJ?=aoVMB#q(.ɧ n/˼ÓAqf؝pܟpwKk4`ḱ)g{)d$^"~©ע|UFVa$&#-1ߣe54nWn[-(L/ Qלz6hN&ahvO?e_cx }<׷1ס}ȣJ?T@ߌۧ݊x jJ6f!˜>BGu- pJL#R6 <"I.՘6(7T)[V-Z#`٦'E#j!@@B:KS@D3*%6&E5)-\ @Bi1GɚSNnZPѯYz3#e+GʒثV'C!khJ>W۩cA. .~08;3:2ϔi1yY0f35,7_ ^"cu .#$11vB/`݅%+끈Z}_YFS○*/ 6=RZ=kV' ]Jb<"h7[4vW*TK}#"5u3^?z6U;e:9''4(WaҲ՜U 2]5d.)B%1G]ӷO'BJ^0Եv<Q?uI:˷~puv6 }~2jl%m4ԉD3U*S$Nᬒh]Tmt#eĔS*V}U3=gnƻp(#$SR/\>IKi4>jktv𠦲`}v V:9f5ic<ҫ Mnyn[# -c.=X=},NBG+8k W3JiZݻc`K-|VhLd` F1ogM/wSBU\P9O fw3#-[wҌ6=@{M 0M"]kv%b+Pr.Vmb[`к\{f`A-| 99?(/gg4܍*|qRXؽܗ6Qp>^ؼ+ڴBiy!5ߘcH0Ycɺ9oi9 GQ#Gt$'r.پ>mM$"9 .[s0k#S#I`nFIf n썦8[xRD8%'r$LEwnOHOC\iܟFDCq?fJa2>ş¯A~e%s5-ⲭԬRʁH%B:%[?-~ ȡt% ƒ}b15Cg {lέ9" `!\;pۈe~d yo>k 46ްo"O`p>vKdݸw%tǂaM蓏ʉEq \3|FSCĒO-9i̸y=|ť>nBhhxRYw.xI*xLRTME Tq1ɤt ͳ?e##c $7z@4Q֗!p#Ad!ݗiC|iFss{ 4IDSqw}47^SksRpU+;M3nE QsY鏙7n mz)mͥwq:ae(QqO/$"$=s16ר+NңV_G\}M%O)5gp,|%CH=8xSno,zK}/H6ӗu *}>Q#r;<-q',Me Od"5u+y_gvnOszXuܽg'KikO/$\|]"c{+"^ywͼ]IXކ%TfNS}6̍،^m6}֦B\n4ǡ1i>LAcaWMV)ժ4Ԇri=+j?z)YFB))~H¬-kᆪǟ%qKb4۰NnJ^WU)j]v4w=K2R{Ec2'8?5SG!H.o?P̘:d,ΕvJ]5S/oEV-Nժ`XOLYI *}ֈjy&NayKjBhȪG"eK؊9Hկ'I֩-q#yv׏jwCYP_\)O0Czi}V&~YlKTLlHrt[5K/?u_9V''KDQ@Mzv Ţx9&쩢51\"~<6)x"LŠcg?ר,V&>pr_e~Xٶ3F/2rPwǎ> .6pomވ_Am}.Z@(撐Iۦfv/.Erj\)յS(»| //O'R>z1nAԵ-NODӗT\F6D!.>7hn]T}HD7~,h7^*fyq29{^ (}|OQM-atg( }l%[!= N%#~$^O W1Ӱb~y9{Q۟?QS~A{&k;0 2YS6*F#Es;ERRv|ϰ.CA#d tza#Pt<~ZѪC{V?֣6V@\8xcD&UžilHo:bj :/űa~ UE+H!mڻ#pؔ$k%!n3D^>R\߽%~_ۜiӇyiׁsG_dQ"7084/7>*[6=ܫtEлb]q%^S6+د/ē:*|@)߅+}r9{C~<%5u`aHHL͝XTՎR%ex[Wv]Pr:׵ю܍sǜ߃Dַco !]"N&\\˻thWVH+q̘(=r^O+߿j~] b'U!PtY%&&Yr_l=s6@QHX?/]m @KY8-c?/B[Y~2f3' Gaٲ GENB;慿=>r{e%KRE>i/1 zړKΆf _~WsB!Q:\kA'mTx ]46OUyW:y7ջZOPo"G){1?ѳ2wv%n܊=`Ǯm6hdu_*OPƇo''=㧎#׫%_۷7fc-mu-z'c&N>Ccc%;Lb ղH>ӷR.nc"yc8$EaKWKZm1=C>q՛?z:8 Βų4Jܿ2ԡRh䟂~Q ǡCpGa'59\ǖ̞Zrp/,|Yߤ]7:b\읟Yszq`|wZn3фowsD̼bL /3?.‹o6ҝë}5ꃻ)uT_*<7]R%}_i?ũXms߼j֊!flyݥOA &~M|SmK|}e%p0qMH?c!ðm$l{NlYj_iyϩ{p@}ð1ho9/~8)y7GD6{%ZH1e%vSuo. 5 o9-{ DUq!ms;cQQڬC>{ƕtK3ѾP<5GТ>QE~K73T%V7!8K[$_*[;"9kW"QÒ*zzu-Ɵ+W-4-Ψa.V۷l[J)})e^m).r?ڵCuV,\qX ikg3`h6=~nSz2.˥:ټ3)zTM'Dt ]vƈP7 YMu۷D@pJDXmvZZh6شy 6{y;􀽅FPn9G07)c?,E߫>cwhƏfGqaŻa(H=vT+h܃iЖ}ifcG۷h =FVmܒ5 &8H(\JmEÉڮrN)|fF)ˈbxiWnTke(͠PZٻnA&*)^ݰq{"qt6ҎAډt1vlߚ4C׬{Y -θca_3_|Je>T/4*7%ؕ$l*mdjNL~ƞnҗmmv*^ڥMD>% ړ^'R8&ypt M{wtDEjۣL޿оpl9C; ;t[+T梂p;[{S*>n(9XA J=RńXsݐCRn>fWskٽSM-EBG]U4/ŷGmH1_z UU4}J4{J240O5KS+P|.<7Jʩϥx#g_ Z^f2R?=FC{`WcĨ1Z,澃զgo͵`-dK={Ѻn`z_F f3\1DdiW ۛ-/S6Pabf]Y5gk1mز /l$9:O7[kA^Bں5N0 q2kZT=8m ̥)u¥par(um1mA͚XˆWM/,/وT3P.~uB;Z[bco. JP@{/j S(0OGW;'j Cv6SC\ Φrۑ1J9Ի?\'M ҫuغK<XpsQ^SfRm۷p</c'uk4 e)NI.>ok|4i=zϷJrY9KhT!1rX̼nSSSx9K׫:W8[^ySړJWٰPO>*8"gc_{4/#x|v 5p^DmhN8Җ0X~I)<z7Y> ͽ/+T~Yi/7Q=pqt"T J)x28T[5eQ -G4e2)`kkdS±5YWoX t_RoѮC:Ғ ;ɧܘmXWQEQE^.95k0;w;3IyKGǮC?_bU Mb/H>$n^|j} Շz%\"JeVN9haKb}<X8ojAܑ8G-jl|avd/H$|m6SyJ|-3ǡjc yeg.mi箁y7EAaZ\]7 |9(kF4ւEiɷ/ig.qb8\,"sݏOIw?Q h!ѣ m ^&CjkR+>pRS3+qAui2@~Ix <&Gb᜗6|*>}aP6'2ڦ"pv{p&8l()8b(%ܯiJDڒJēXh脔asl?NP^z |7!-`?Em߲5vYpv./A&mSpj; -vM(ݗxx?]: 6lBs(n!&4'qLI:"9O4o,\)L݇Z{Tϼcz#8$QL AweZM i¢BLYkڢF:%sL *(($s7bSi4NfjJ JK% gN# 殤Ŕ8Ug t:DJ+lgN=c'`AHFI3+85}Y_8>S@,v gaJΞ[Kؑx)8G{ޝ1a8p Q'J΋^}/ā;;f'':+w6[KSzC8aM]%=gNN`Z M\urMQ TYDlV{Sה*o@. _~3hMҟĉS@U+[5#FХkKۓ yZ-&4}x 1z?D^ M2'Ϩ!pPeJ;}{$ ^BȽIS 8;Oq|Q7\u$no<RRih.Pi_}A cNW. 'AyOj[SEn+LMEbU֝s5NxJ_ >5#$ I -<.o 5 R0c\CpCʱP֘z qHb0wAU!&6^C)D77f;p.O~*N=vDvl_Tj!07's [(F=jH`U\#'uҥQHd e'iKP,{5 ]X9]0G%kcڈ5|<1vg|?l_\`ԥ۶bLS&܂$d! CrB`N y梨sQ] p+oYǤ-!R-ZS¦=,*~7 "N.WC6Dq!<ԌZg[spuU3d,U=U#{Zß/pH܅mLNmNE7 ~Y^y gRgw /պIR׫g_LiJm6>>#nXB۱ú.x]~BdEv"Lak=8foW`mje8C@%26u]iu' 9ٷХJ8,㮂x.7%J;<`^|]KBk/z`^|LyǕ6B\VY+G~r,L IZP::/pC#HCF4YXU_jPM'x&9$؞#rQO`(^B:ZUӢ[Uy!D9)g>?3\=1Dʨb\ũrRX.N !B/}*"HZ=ӘO8r=KYd[5rؿ_x>RهwdW砾T8=XQK9c롪C78MS)}Fs8p B^URmג~'/gx 'CBS~Z@#j}mD H?)<|>>+_ͥwB {*zj7 $&O\GQOc.gO<"U?Luף֫4GZF'RO쇸dv{XUx(*3KzWOu?I#5^Tpe/]OQD 9o]~spsqx884miv'$$^aq5%C[Ľ(h\2R՝mhO z $ ~e69[Vԭ[ҭk^ k`z{[+dRn$8S_EΩC<8=)1wȬy %&2`{ v$$sEsf\zª_/mM;}'p` lMQDbsGs|F!LŸg"e[rFx`Um7DE4il dG3,jV A8piBc~>)\Iҹ ι/H$Fv$rNbt)2\z3LIX=s͐JIjtauSDZy*ر_-j=MIytvȤ֓ڀĸ!=Տk>0GQv!{S#Zjglы唝&VќX KB&~v@6ptqD#6Pyu%4>fEnD>h<Ǐ"A9f̘ Ʀn3wޏxP-r7ƃ,\{,wN⡇SK³b~?λAcXWYQ d.,ZاNbmQ"֑i$2+w5ʊRb6=85ԍ pKўquB`vڿHnI5Е6\n1\nvd_-+Wy. /UW!hk΁R0W/}KNX bX:sr3QBTkJy5}Vڀ-3K)0Bcp#]sO^T֥L6C`i[$G{t6w/kQ{3[hd.{hH~RK]{M:pPga?˗R/~?@T@I֧o-i}mʼncxxt!uqu|$I*b6;V$M62Rc=e㢅XȮE3_T9Gcc2~nd1EZd$,1'NS)4wIi:\#nqcnATuH丵G½`I֯coυCff Ϥl b&í? 8s]Iֻ=nڊshN⥣wHN-T\kdҸ!p:S6L^Jxsa(lgmM2H\enB6GƢ #\0/)oHT4avP#QIi֭;x`b׌6UW~ &HN/ˋƏ v=ҟp&= Aطw6m{ŽDh_7XU ҥU&8J"pd)%_G$u)NEC,%?xzhxR4E> 1T[VYV}ҩϸW [q/m>gτWDHC)9-ި0Kעgy);u-7>6Wx-_y5$$U'̓2c'#>j7|Y Oj'Spa~cM6Cg%wo )%2={ "'3HЏ9)hKvUE )mݣk;DY=U_x;XRƵE `c1_'$LT{xsO΄Z}nia҇%S:[H3h?ִY2#mZ8ambϞ]hѱ /gS!n>$DF%%gO/gsD+O>{M1f| }&T_>f ޛ uθkWź(r'FL9NCam4XR:wo̚u?"e8<(1eUo_:I`q'Nܝ(t}M*eX:Zw&MN67I0[6sA |oD:Dڼ"Gɪ QLT Iu#]Ou ]pǬYܔgI EY&n>'ERBi o/?Wj6Y#T5) .g$^BxVM!FNJԴJ.Nux'ߛ8htK~ȭL9UZ|Z8DOW#ôOO3$:bK̤„7'\JRTQˀ])N$_8oʵ> u"HH:몳>5n[}zut; g2oZ")h:T|<HgaZ@h\+w/>Jkolgl9q]Wz~{hƹ&"}!\"$Q CM!lXM֢]Zz0uÎ~n_$xtyjXM?4H*.>&Nx]{WCi]9=|/U7Џn~ANppxq`%^]efCJ_hy*u9Ն~H Ҹ$4c0MnDy9x]S)xqX&PbǧSj! ]zԑ[eIT?׻wL8Y}p*P`]֯H\4gk8 U6uPQaTOʪ IdkYIh|Խ1.mT?cH[vy(JYs4yRGdZsFC}SUOxFfIoTX^TxFߌKj꫋q9Hqf6Wpf"qnA%%K}%o5p⢍W[c!y4h}y4HDյƷ_h2o8 nD} _Zl/ҏv$Y5jc$6$R a_M׎-!gݫ5-Ծa> [ѡ7>m܌ؽ6D;JӵeLE g]6zWVLKGRMt"Fވ;̋YVQӢ595ʎ>$ey)J !U F{ԓSciu(J+z%ѢJSbiTriKfؿgX3LL8w#׌ZaOOȘ'R痯W`+mO}]XO'߸xvXEcBGh55)]IvĢv;E1}S6saѱuK AZ9wܷ;\(̹OiWTƎαk m|<\i x7BC(YY{nd ۱ BȻ6cpsb[,!fG]GTgnF ;G'Gb$yRb̴{]_ADe)DErXM}n&䁯 n [PSO= %)^oM;v+(S⮙É"7 TDd˲W?Kl:"%ylM L{.pEsT iv U} S9K;I9p}8 |SkAũz2 _ E+e~$ԡS+' WO8Sa*z8|v7uZtnA>T%3"fnA>GI"(7)nlu i 1عTyشiVG@x~x@_d U7LZO)1\WUDU\WCпG[ йcϦR':&R{> vCi₲ګW aؿFq+}G%`_ây ؼ9O>© K̡˅)r |I5w9%N]qǔ7OշI̳(KV_liwWڣw .Θd KܺN+-%=-N}:=fnd­o/P7w4+{rK~^As2O,v(ӗplh~7 kCI=,2(9\oQE`^.)q$>S&iw*? 9^[E>_B`}G(ڻ V=/*Woi[TO Xq״i$^gkfmΑdջϗtjWk[s*ֶᜑo '**G5| VuRO}?5Z{{j*KBZNҨ5>j|,3;el&q4%sace*'_II}{ A22sͨ6 ~TwkEICǎfK[0$<_~mN?Äh̨jymq AeU5vHF̩4⃣7Ca/?wcĐuO:eb`dM5%vY*3t tU58ycoAJl*:NW^/?-/o{&V^~Cqp,a!:Ρʷ%n<o>$仡G݂l%Fݍ~?-/}b ]<-‚ λRi,D@zb,gcHׯۋXJNgRk@ۛs.t#8p8i'v"'qLv08W48(ɧ;u|d;7_jsNI8?EѴ@q1ڮF=OV32Q(iB1;71rd)~hfjko9Q͘16KEg4x ?U+IЪvd]$Xel|R_Y^֧!yK{ő1BUNWOXp/yoLZqq1yiQx.Nu Uqq'X+/8C[Dv)VSR`2xyv'?z GMJ7wjm-Q|.];w@19~zq$_B\ꪻզ\U$@GF]<0W.rE W`Wc8s76ͥ[—_k~ЮVpw/׾ y9VI'sYֳW \zг{oSAnQUYZzx8Z_C-2{O ^o̼/|Z7U0$8U.Ydim ;d^B7c 8h̝NOBF)M(txB"\brTzQ}EFeG9/f*\= lS*hsI'+/KlljC\Re$%#cp N E4xjcpW"lx\ʳ _/q ˨Gړ?* '>}}u=k7 Jq5CS+db'UnJGPE$X'NT!\PelhUׁV|_.}PȖ* u}PjFMחR9(]3Q!:q>fKZ=TpN?ko9O"֬<ջp!YC8ɳ6LZUS$e+Q}$U);$F(çUYqԷԪL5N:{u=!?TW(flM4k䎃xE4(¼x١π~}jK="@ZBꪯ;ƌUw_m;2+ 6m:PU#|)l^UNNG#8 a]˟ Q/'e&ᩮX?'{bU 6QAXXhM\q=ނ6S;_DɄMS?#%@nH)ldd%lI2wŔq#h: 6rG_T0wȡ~V,G֮8u AC5g-"[baֶ=P3IM{r|XEG2OvDvȌ?Jژ-JA-sk[i㓐K;bՆ}žX 킰6A?jL-8x{b!HN;DƎ +S+|" RGA(!q{%ޚˌ1h(D:1~tj㋤ͦBxy$zQT>%b耞p6ah i ~MHB6`UѽGۢg`"v_/#Fb)֧Ь$=x?wUMMgTHH!$$"M);^Q‡"{o RHϜro {ٳ;;gwvvggfj`f+4ڬGhn½;wAQ"(,|p臍عc?IQbM8B} cm)4m\,AI56&;[X㑛HMc8^#@uHK,GMM SȎV6*?#4 h] bm@FSI^ӂ *#49)~[8ۋa]{azS"&ObY$R:CX$<0;)]z >"'|i!38Zi4.7⎻:T7"Ns+wO7Y{gb4驜r}u0?@#Z4NMVUƾ}0lذvkle+u<kUlkxq:wk*O?MxsBr}sg͹. ^0 3L`GnA6yd6zw"ܾ.oA&eFF6 펴#*PD l1Q.\y!:+jQ8!-ڄO3~Q+iGƙCGJ ʝՑ,~71U^Jŵ{d!7ml ֡ЛoA,YbV=|r=Cz!,1ĜԢ" ||2@ĝ9O(ĦdkNhɤ~C- f|ThnϤ) ߆ 1BMӊgnoqRۈ>+`{UC]u0D<=ʂ&yll XꮢƉdz,u#9t)G'3}Y]}DG7 `q&u΂V&:R'o,(as7wQmWJ~38c M?FYQj7yYj|௫Aߏ#o%y[3y<|O^?:b܈xü+ uB\Gt6"oWPNqz]X g93r#v6\'^{p3iT`7_['*%z.?t-/K-i䬃'Tִ X~. X݁t#O'etN=KWh3ɒ8rɝ֮__ vxwBD̛8]/ RhTu kZ9&t:>9iS۶t 1L9 /|rj ݵ7;o<c ;s }Ԟu$GqY5\]+zq@mGeu5JN x'~ohX⁷磪Q&d޽fѭl#3=H!\]P`';G!L#{Y`5|~WpwwP`G}\*քB􀐁кJ{p9 b}n ̋|%w*E^Pu>| sVc9FYUU%pWs=@i*y}s_w"PwpBr+OW^ze>{y_ZC,|I_vU(,<9v--0FbA}ow+Qdiݪz!"[gSB=y[KM̨,,4W_Be]|OI|{9|qDLl3 C)V;[ xWPrNR8qL7j4 W3, fueI/'²`ݖqzau?&E-Fܱ]hp ӵiK(ʛދLa Eކ p qg1܅d7v8Vn܍t1^44_~ "B0z< W]mL$CK϶jnK~&]h1>LgVו{NbCV!'i{K}5(C[K!=K?t73G/G^r:~J1})޻^3ZrP%d^g.Gjq w 5n0(6:Z(ӊ 6mtqGRD7epz1T!3KҾ oHr٪E9mQVq{l>(iSpL/77y+p NBVUA.Hk0ҟȳ91E>:RA7p 61]/B>9eV-,d6A"Of+`Jɚ| Qd d>Ȕ 9?^+.) YE1 螘{>sCR?Ue2|1M&3,ݬv`y3v6ul6LpCq#O"?.V0wª}=`?xLj-2B~)7S:ixpW G]6ΝAI.|"sɶ+?!dt,aebQf92Eڍu)l)h c/WK:|w%7$\J:!D<| ԭAKZ W=ˤߦisr\:l03B;-,c|'KE -'+Q|P]l'+(,*ü9Ө.dR;ٓGQRYhe5+Yz%F> XẒ}4 JjpjPKRt !mAz`QX|9Hkp:~u=A[>̭á#$ ;FFڝزg토^06C|B"mp09uF(#M-;z,} $ֹBDK%݆b'L/OV<-,[N!^Nme05p;V f} [l믽E>ba``E_|OlҶ<$X q;K cLaAJ+eeEeUuaAfϟ/'ak'7?jD %gPEm۟,\L#cX~euշ$KbPE$\h{74ar9op= I0}IdR.#%9646FA ',9$ n݌_~GSF"kEK @1tP:p + YuH|iۑ`c߀09L `֘Xi y8$ϝ#Bs!l 7>aF'~RThXoQ:ճ C Y[L2WIXl;?@WT7`d L3ɂW [s>OϬ^"@n;u0,0ԙ,zfи=U1$o#AMr Lg"% fT9=̫0&$f#9S)`fA$fZ,ग8` &$-V!5Qƃߩ=#iH&Zxe6B"8_B ?އb1dpQZ#0djFXf8HFBT=1O̿zx%[nER~?yxťD#w"|m({+Nq=bه*SZ/ g򷝂ɓqmW^]nj7w@U?,L;)h 󢟃g|ez"oqP@8 b2rXrxjWGW,`8QO7y[ӜΙPC~Ir]E;v e_&wrr^')Ͻ`է+ѯOku> X9щd5N{ 11m{wnq߃b^JA>/ǃSyNDX(:#lOT؊pcd&Lؽ=Z+|X 4Cs4;4fhp9q}_uq b!1J$X4qPeɤςXIkD 7vݭU^>WE}TȕXq4F`ǂ<-3G ZU5v)<}C)6(NCjRzzeO ^7?hSimJ&D<Ѹ:*o"\<Z%⮧?p\"E xVl=`V"9MUo,ʁq08qZR˕-MD uhj(BBj% SOGȁ$3$HO ``ioT4h59~xv.FMm GҦ%j3Ͻ} )} E= <L[݄#{O(ҴtAcN"Ap>mI֌ȗc$=ge!%#ij6>-rJ9$H(v$tb=B`p_O2뇣۱n+Z\O<c5dqa<--dS~)4=餐 / 8|/|/%୅$m;ub٘LYT1`Nn!Xгf,3h̬IGA +%$!bϭE`9 OeɟUʽ d[.l A9|bPfjlUm$/yX+oK 'y94G)ƯW Y;ӝ7O=z]3'a<}^F$dqU~uKOA X] Lzb{y޵ k7o{-=Ez+WX=ig"VސV]n2܊)+CW6Ҙp*-'1gJ];y#$ Hlڼ]z>w#=W_EIr,F]d~=d$ې^z:OZr 4ʪ$Lij/DVv;Hq`Yy(Ci^\%󲩘zt$+`OByc!$$vljˆ,LZn=Μ8+uYH"ai EMb/$`{H tbϜ>.aGG{ y3SSgO#sfF:h8 iTFV93w6:@|O) t,y"OŢIXmdn&U`cRbh0[hVU KPX^A0 ѧΥt ÇQ\s[gسҽdΥ1ID>{ 2198|6nہrw4^"<ѢIW^~---k{pYIyâ%iU$~y2m} }}?Ó//ZaH US8>֭ 58w.wbULfg 3;'nj xEQێ6 YSΨ3p()e|*04bN>^OV mILzA[9hiROe_c1'_dz5lg"L'ya&rÖIDtȿ.VCӔ^3-Ϡ rq Yڏi|:3w6Ӫ_r%4;8#T0##d}7p),|DA*9OaDl;_['qc'\oc 9565u?,/N #ԁa.(y'm{͛C9>Ay&qmIΝMD"tu!|l؝'fhɸYm91SGDeXrZe,*y.L_Œ(Cb OO\9XPĻ\ EW4\|hʢȩ{o>f԰#w S8FoDC~ aOjt ƆصgHX ?N(G/V}1vo?CdfÓN%&⡹3Ѽ"qrS\ze!̽&MS{?Ό#s) T`7|d#ػ(V7:8S_]w"R2[(;FTwC$LX$1 O_ xiN]׽u evn޵Ӑ hFeS^-J[4O'\8'|]x‚jP s*‹#_3O<-(_;N䓏_~HrNkD6D+|îtEԻ"Ϳכc@!ߚɅOQS}ͿgE:um(]"H'ʇFTGtl E俞uٕI+nJ=e3REbk0i>Df{0qX"ٷ }(HKBi4k264;F4y邜.遺Y=Ñ۟; Бs<+L]D0Ԏ O>>f#sޫ}46݇HP-]<rǎ0nDv#b1u@dQYw[sr1{ikrwgGM[jT-oUyb2}{:֊z0tC,̴5QE.so7زf #k{GH4BB#wWaDad6[vv5)Mp1T@Duȯn&<}LD,Md=l`o&2=YCXc<+8{={ D0rǖ-ɚ@o]p=vn 2WzNH)b׮7 FFH~ Oι 7E*]M My\QMJГF5=u)>8Sj*MǀSp:@|r8GsCI/9% L|7*RNM' u Mϭ5 Q^o‚RGCUaC2PI:b3H𩧏x QG#H{JE)pwIMU&z,2{gA90n@}LH:d@nmR -tPEV@a {[{(Q^C#2 XO VmPiAEw1]ЕtF2}`L/~'uH/r=X$ ;{Ν1/2h Z(x2"[Wc9'JƋO-c3ipM4z*޻Ttj='~)Ch2xTmm/I֫tKtJ$΃)}B$X]|'Xh)̭m1hpDCЃ0"] sZ10^x/ )B×3*ju;Z n&׽a3]zo7vK5Y:ij2lnֶP}o4\*zR]=}"Va e2g+˿@31pZ<qcַ;3gͤ59I(;ȗ3s "frtiSIY((!siks'ڃs, .ع(.S70yLhϿ?W@!fĤER6.z-ۈ9YHÑ WۿtLڢ#QURL4zH!MZb.|XzE<_lwJf'7:X<@S ϓ;'C!=\1}O!*?imzn˘AO 7Hy,NWT>01XE}׎xy:q/en?bN`X9$JI~.rYpniU-梁>"pyXw"AQufӫW.*^?EQ r J?8~ێDEzH*ڜ[];؍H1/,7uAi5V3?D`Ocm;RL!QN!nz+K3s rȗdc&2˚HckrSOƗo{LJc5OaE4VSEdbHd~(-} 2YL^I{=8I pq2 ]\7-2CKڍh! ب]@·̇5W#F>,oJ Xslv *un79=s'WW) ;C, d s SK{ڬǕvs,ta.+2 u$ &:s||r \Z&KkN?FUTD,9zJmڸ '=Ss8:^I{|ūd>h '݃_L'2"C&!y?3|D:и1'$!GC!?xnΜCxtVKn͈ OD 7dm(' tyOܧ0Csg2"wy-Ŧʺ,`pLgWQL$fb/k̦!~}K%S0?k(_[bX ߋZY#tX*KK#Sfhh!$"kW%tD/wWhuzk>G<ԔtBbϝ&%CȧAButD:n?6G.1?(NI;'g'x0o[^# $njfP;'$}\MB}zЈ| ~(?+fbZ,"FqtHN-񍥇g,ȿ@UmšUD޼F}U/ƚ,aQ/s㡻n=.}_񚹩I=&*,-U&=ibg xfʛUiѦm?:sBvX-GpK1֘.'iqLw8a@S{U܎GHsEucoF t4wXUǟ 2NLW:ZvWrm SFڰl7jZ!}7mތ&l/cYžUoؼW:^߂mc %&8Ybh]Q [$mr`A+aF)nlJ*8Gɬ?7o^v|C1e Z30>i> +z*yÍŸyUl*iX+b`y'Wg;]GuT~H/Ѣ$PO$R$wvU$d=u*Ohq4AKs{y+r /W؛L )t(A0&=8?C jjDT΅#+F} Ŗ=0gBͪ-89Mbڍh -29!4I T)W;!dR\䋴  D 1Al4P]sv! p\ (lӁ4#Ԑ?SK`8&wOsO߰Vpu5.]lkJUm^p\ SpL>Μ>;_`eUx"eF>4hwK0X=LmC_FڧfC HpQ@vM?!Ў)'0@|r^Q2[;Po@C&ƌ`A$_K ^~4Xvl%Cq- s1=GTs.مgr1<,;)#DZІ?P\TcaHZ ^tիhOYMkʓ1WFQnsS3< X2dMH~nuH!.es?'G9OLBJ2q\\PLBW?HL N<Glrܵǩsɬ ub}#W{C'Vڦ'i6atQRmxR$I,Z=|((FiY:q:y>N(&}$s+aQc`o:MEF03CMc & _;Z#_F!%֗yĝw!t i3 y^b!Mˇ^\MN;#_OUt_PUsF>Md>b{wB4F.Dd;!$A'P7ƺVN #F4KW.Ve3i/%41<1."_ 9L_'OmEǴWL AywDE뽪KW 毊h*0yS#|g4fb}M1 jÕ*>-8SkwPU^0 f,ڳ;ڽWQ Sk1ζ7> k+]ՕSi.dvv6ݮoo:/g 8Ւ_WI59w4 ^1IG$oUuFGUFA&l٭}qbZ).~j_nWق|&CmX97xeX| djۯ^<ٵk?L5H+5 N@|n^49R oj4k?SL>hy{źl't1zdƶq}飺kG899|V y,:EւJpߔ{ڒ'=5ֽ01l0M1#no0UB[GT5y?WN#]9WټsrQږ|ojʜ2$AT!S{`W )8zgce#]#5AZOgPtuX|jlmQI*5̈Ǩ#| $nwDOЪZQKsl5\1&-KMm2rIηhbW.SQU4T |)3 ^ܮ?}0m RSZr Uc ;+lt%o&H~CНeO7qZ[6.0:E_-C٦ߤ=_|*}=jsd8 _hCCwt2zr@嘒OfI? dqkbxpc\U!70~?v}?h: ~RJuzd^xZ-H2DV|nA )T9X#]4d"1;ӊE= `get̥5J_D/1#[˦jGFuQ>jim:lv=izRXcȻT6iY[J>5hY CЏmI^ wŘDWA2 r7hGsX~B:t졽iBIMKLFMߵ $"[" =ԂoBbe:qqhӸ+.&Ⱥ󶂄$E;ȿi) pA Z8F&"y"4HPOu>W:23fIӛODl\(W%R)4:'cyz>Loy?*0\ ޖg^)軘:x/'D K&|O]'ߙa'շ$C#ң/ 1x_ -1NqNjH,D14IٺW}qgzQ9b|(Qw%_‹o~At 7|?J0ncǧ'.xq`|IBPn,T:{6ŧXFN ?Qw|7#0lQOZ0Y`uyflTUfX + AT' F \LwZ)ulW.|4aĩNjS[ WDG.ŗћqꂨ+s3c\+בȁn==GŸB[ēS1Kb"?KN # $$ ȟH:q N'S Lh:آ-M(+̃9uػ/GNGFn9[ɇ9b?N+[#-ɚ2ۨiRă3 _~5$* ]֭уĠJUĹt37o5p _^Jt1*=!/ o$0LKWMr/6_ ᴌ_hl>aAƧT.:ظRf>C}Rj_`;Jz'WSqs=y!V7AG\|9~0xeZd B BFJxzwƟ,G>#XOtzNu :EUN >N~mǿoķO=jaxF7oD{u0ϯ$o:\/Ϝ9MztD4V*xćbC 'x05Z5('ȑ#xӅbX+{RL(?:53j7tX/63ڤ5s&7F!LǧѯO4 f֘Wxp +5UtHӜ|FmHPiЂݖB2}yEK_7AZ.<}+;mķW~': ѽ2cX>.?E\<:hnƓ=˩h$ `e?[ؒ[[(ei]Vd]>MBL=TF\6ۂc"[5  Ҿ v#wQL*T_QL:wDKek+mL$YZc{HP-1YrsD!l*jvmyEBi#$i/nv퍆>dFu~5#R.]h{Tm/ě=V/K(pǴNX1e*9|Us!N!SNIYx{.r-Ni`y!N-pk.&0́ CAzd_xQ nj/<7f@`R| "FM$⤉Sgb{hX(̜r/>o6, 6H!T?9~`.:I]ŋ;uwttQYʃē'3c<0ʌ`¸3Q}oV{dMx\SU6'h f|E=DqpYlza*s^tbLp&0eDfʸI+K>Q+-iDPFɻx󣅘 n͆FPN&ƓJUu5< IV|-&MPb.&e/$DI&A5 dNdFzoGhϭS72h(WLD`zmX0+L+8,z/3nb1m0xa.WEg*C'b.5׃]G&-zp<)gӱ{e o>t8& \)^/^O 1#Pbro\ Q?%N?og-"tGΛ7O{E3ΧނOذ.:zӐF V*D:_,wf& |vc{gc˱3!YIK7Lw\V@fN!ܬ IN_E|y"B˜L946%0`l"eeY}adU4gnLZ*?Jf"nzpΟDcY*DK_qQcޮFddֳD$#Eia8yT9y?O 87*AY?of:;tPi^GUNE&k>{!EsB[JtO;~r<;m"+pe;KqpwK{TmæYgW_L҈ o/¨gÚu`4 J]#,"31 ?F_Qz,&0&ʘ5)n=T.K|rOv Gz.3DR|धޡQ 7{'TBXZV2zb M-eH/O<0鮝-Ŧp5A=>mMZFo*m-,[xcỎ#-l;߬E0/=g{CTTȪ09T)cs‚H,ʺrBy'@~/o 5u8c%f _zXIz0F0p-6XQIYTYƵ{c9 !C-x඙Yotuv@g Ӏ@죢;-,8 skuR/MI΀ |PTVSt5FSywIxj,{:Kdᑻbi0v@г =\н?C[ovF'ka߁( [f߉ "kvl>6,;؄6֯wt$[Na̠B>ehln=Л鸚JTw 82v#=_^q'*i5  Ihk$ݾ{7|˶Qޣ$ xu<^1Cӏ\U;_l$$2!_5f̞ɾICKIͯW4Tk'ֽGyz|;TFGxN^16y~y]с 8H:Hx⹗u\oEA+ mR]UB=}U;jξ"0b@p|嗄7LZ~:ÿ\˓&mq{+ V!16qѧ^ogRN-@ZLf̹>~=E8][Xf|iu쫥$i1hP̽NЃpvrPz]מw,ڮS,yw PPcHVp%*a|B9 16ONۦževgv'Ş%וId&i3<\:*3Ej $ "6 2%d| vIIPr$u \_S iS]RF'UE!o!@z*mWc+G "Mʒ)>GI?(aۻS?<]G1zA.f Ngd\W'ZoVv,nŔ'"L-~V`l&+YsXWγ+9.Pr%kMB䓋WuFtEO`)Sڣ&I>b ɣ"eh/eGd {ƭiS&룆Ue Xɼs;#F ͷZFAz[ObʭVފ#Gƞ+c+y Y2hݖ-\чb(Tx[o_?E=sy'_Jߝmt=!4~I;g^v:Jށza;g@(p|_8S`u9<[#|kRK}r:y_‡"(nr cF~ _xGg8~!,o$Վ qqȿqع2~ J~?iWJI{emSߡߝ>9z4LnrOw,t|ED}UʻW Lޝmx zه sdzUʏ%ZP>H}ذKd6r=2#w?7=r֖Mhb ?&]eWo#=[5j{4XP6 ?b10tQR yYq Q FQ3xc{dFг՝a~I#==@UQ@ݟWT)I2Fr XU`=֢>JhUMqbLAea mJ"O֓޷l3-%m)Bp`,tҔpr0?-tjk)zቻn 6f\ҵIH|}B97@e}m9!sb$cz5#JatX83Y%oDF3i-cg?涮ؾi= *Z״C=kqDkJ̐yO2:>q^?91啥3' GߟW tX{9xבthjKl _O>-_EO 9o6v9tw4'>ix>C+{p1;]w`qD(ǑB8P ŭfNϥcI"iCHj;׎t(m"DE*Wl[^joVwx7 <;qXA{4L)=N7{pY0j`L2V)8uO@9r֏eH@f1j: m'Oٳ GB 5rΛ)OV!l$(eol iaVP\%ӧW?bܐPx1Ax{g/tXڻzʌA`ݶx AyUbHIgR(ݹ!-E&Rۡgh/.RU("4ZW*uJ܈SGڄ+IqWtB ;uMDdjJKOs}BybMI|ƣ/,_# û4~節Iqq?ZF Y 7K" D %(~y9h)Ă?BIqZڌpt ^{o_u_v 9oxt*ZXs}V_+@л%_:Uqgͽ^*Vٹ~Ί+]4F#twK˵] ~@[ޕ -A-iLd>kQ z1BOG3^=S y6+yyY~*FHp 2Mʚck`x-dA^I9NDC!^{86dKz"H:פSaͲ|Jivyo3{1'ׅ$| ."IRQw܇ޯ~({̼}Z?BCu]WUUuɧQQv;W5dZzOw]5=}PMcDh"C/snfzo !|wy6=;6s̞{z;a8o?JR o|T)ןx풓i[l|K|t؇?|K^:8yFsgq[}?_ȼ[FDeIüyw`B}w]MEa#\~s+ڤU~.'Ё>AC~^̼x"ߓ:`LNs'\:O?Ȣxji X%J'" gO%c 1qzt720j0TWc۾cܛX1p{Q즷gs- d}wa8͵/Ow*b&3ƥ3CcH` T@ 1aCL[aAe pޞ((GEe za_miGel oJ=|i,ĸ{Vi0Gc:k5Aj,z7`=? ؂0Y1aCZ\=˿]F+ = yp U 90n#پR/?Ìp QG%#`*%6!ܝ=zP/QJ*uL8+NUMHr;F^/|RɘeZLk u;YYG#2=I3K:Rs;[Z7掬F#F􋀍VDY !]PJepVfzrsЖTcwmel`h_~IOp 5 %F͈vr>M0M8`#۴{jqbF<^'1bZ ^jhЄBƭB‹9k;)WD;R 'j¼')߯ i{"O&an4PynvгS3Ű1Fi9걧_#Lcׁx>fس}kS{eͳvy"4Usʧkwy#ʳ`KE}ȱ*R啬j$ko<zǟ!|_02y&[(Z%|zg()3h2Pe0E ;Qekx Y ˿@b61ٰ` 7R[U:}7_چZh3y(ܖ@T3vg@iםj]}̕V.}xYmRJ˙hrvK) c_STUbUyoTmqè}WGCKT(b]r]M*sQi^oj]_6nү}jSA!KyYsa;U`K `~[ C|.׾e8~(6dN :ڣ7I}G?0検E ՚`0Ţas+0-~d\ԪjOD.33}bfȰ6Z  ydd K0 y'O 0eCaƭuӯ÷!!C`gם.#SU7qno$cKH;mOPo$ԮQTw{ur;rM_QŲ5o7KiLGOV}zI{YΤ΄_RޘCE :4wzeuۧ{F'=Su uv9{A: Æ߆8߾ nĐ q0Q?ns3[:n_ %?-Q%4RG dDw0IZc&]AiU~J9'uT2UOȭj[eW|'#/  oWXZ9 ~]b"dP̙92hp+IqNBuWsSSkq#ƛdm؂`z}IyO-xƏGPF# 됙øʎ n^͖4Z9 }V$ҏ3Z^!F|`fj!r`E>5lei g-ϼǏe{L?Xy#{T؞e̻F H=Ja= B]TxPQf&[-/X-oyÿ~ڕ@? G"Izp3g4R`^+}쏎“TϡpyRYggj6X.tV+k^Wu:- |B3% ߮UI>)2柖i=v^[{N)O'섄xRq/J**Wކ>ېGW~\y/O?CXRCO1|SPS[[S`^^=SN%a~.E*{y;v;(X4 -؇?Re*uK-O_f1gƝw?}G]`[qzЖXӑh"ij>m6jqA˚5v"q 2V&loajeF81^Hr8pNC_ F܀S}cԾ8E/KD̊13PhmiC#4ufv6BYuRQإF C2CL9 F= -8Nتl4z"Ȳ (Vh Nfl)7.pswb&qF᭗eV4$^9zؾ:ptEZYh$t6%&ln]=N{O؟Xn=u3m7"*5Yƍk8ፋ+{O(Xw M;Y3D:&6N8z0|aoѓJgGkl pfQ16z4rI#ȗl]!za7{K%vmHWTYayu81O LHc0fnum P\Z cN'ADK{gbhdKFu w[B:]ݽk0=z%-LQobx֌[K=B1qh k{ȗTYՅA˚| ?oKT'_蛘tH+KæQO|qa88adziڔqX \XZkzZӑW`dp? KL?p`d%˂]ξD ]H^^w0&?VjK o3gsaAG<iC(h"@x!a01qVT*%0k4[E-È{>(g.O&jyag|d冞 #IUv> zv~6gI$? >_~͊ؔٶfF_ TZ_ƛKKE{U!(r/Jg*0ePpVeQ7YrM혇\v1AbK(cYSi:Ժi*r] Iõun&u-<2p&abjuǃVUb=3ظ !96d`$'ivD JQޣMp CMėkz`[nAMM Fhɇy_|.&]sRW"xzCȜ։H:~ CWZhyˠe|^ywq7 ~a2g @T1X|N>jU}2Tz|kL2iw'a:ssOe1rK5K_h)ytB[Иm^xDz!VHw}JQ'&-OggUwh!˩Ꟗc ?i1t4neAWE\ yLQ%<`^DxR:cϹ+?#GIQJZZzKD*Njx4V[Ew*׮ԿcO~{?N*jh[iiu]d ›|I%uU?g @),Y)޺moAJVsiMjTR ,7?d!"-g-4 wtB@\5a.R*MtRiuGc3Ź䥏`܇PX jJ>Bz4ףG30,7JGS|UW}Jgeu5O-IӒG-?z'tN[VSnt5?m!xp/gX >wt*X!s=xjn~WJ;. t.9R6irM}|w%eHyJ$uTűj롶SO?&k-K@|[^î8)  >ڕ*q>~l&CsD^0{lvm>v6+5TG"wv -5E(:-nB*ne>ִ$|1IT^cE]pѸCxس\"':z?)ؒ+\'>y;Yޥ:&q;mNvsCw4T(.#c>Yh$2UZG1CTq.rbypm#T"(Iz3|0ssÒ+c:RJuk0C i7kǂl8Ux+p(qsw,d7a*!t([z2FaV //w{Ax%gTPiT(Y3U+ @m' P,_<9=}qΞc}V:< EC}5222@n;# u؟A|l"akJ~8 g&4G c:…0GҡȾpF|y&RMlJ0{=ޫTbvX;|PbM/<*?;|vqiF5 H ̔EF&[[8LQT^vm.80&T[wCoh?\JMoF 4'NmԺj$K8g0i JG2h3coѣI'Py~ГÛ_!q{yksk;#ŭ TcQ3m,_RJ/B̼aʩ7~H$Z!ƌL#*=f8ÅJCzZ Ul AB\7Pȿ QX7^;4|ˍHXRDҜ]+zHOO=h6_O?Zxـu,FCSDy=Xtyj.wz(L}_$N ]5UѹX$/z>?I/X.iM "I=cG nzHl|ZkF&OUFch)FPpk [9GT^+:S7MN_Oyj2wqНq*ejۼ{ϫv'}1ͶNbK>.+QM?pݍsNT$H@41ni+TAD 7vRQG2|dDnn"Fa9(;Z)ė_Gn ) :yeM|V { $A6wK ZF+Y^4kK+gG1έZ&<("ДԝXr FM6w^̮.~>N3ґ6T: A.ּ 8Ӭ?y8C?Wh,4e|,:- \xYÏ7/Uz%,=ܠUAfX.%[F_B ccr~ʶ|^gNw/1tv]rAj5]|6>gLI=:KGe3/Ir*Ԯ stL2TF c~]?x# aMZT@!>N1z5z vH&L9x"ߦ'50Go=\|ه8yw=BOR3*xJpH (Ust::y*͸o7V~sYtAq>7{%=hH<H51<{^MDQZX gzV 6A=m quy)=|.kbCG´ vzVfMxdS0Ǒ?ŒBd{#4HЄ/mNj\{/U||S? Е:&cWX2eLrRQf zy )Kb ϕe06^NYQ’RVL) ЛWoXnͺUlC8܇߉ޤQK}+I|DvS}6ޝm)4 WTS\* XΒ-A\I$8c"aW8_{F/r7nCbR ^KhW¬1fu{PN"w 3 Iu*~Bw^k޷65cl&8-?'S]P^U7ބk$;lHMO!oFTЃ3x:j =TG)HD%a5%NwJ۳5h> [ބw 4+FXZ4JLndP1;%A6Iφ3"$Cem$Z$kvwr-_3<3~Ũf7ci g(?`lj#'hB_DzzF1R:HL4C|B6>,iic\>Pױbvbgޭ(Y؃Ti/Je̟}5V+,mlY hd܆+m^_VS1w ?6֯[^y7R8ƗV|0rKjD]ԅN;d "y%I~9 ]yUa V)#1 r)I u@\JW-G6:G+P!B8iWQ>lv"YiI[֕8V#R=[mZ39)վ ɟ8y+몈?t-##3/ԜPU 8""'Xҫ }R Mi^^!2لypuuy.c$Y"7 EkbeO.o7OAǓ(Ysr21ƩH+4*5a2O&cu4`XƭF SO#V@v(,.2%O=<,@-#s] sJ*Ntg\s ~jSMjװO+̫FEX5_0{ˮu:+Usьɰ7a0brnXa1< n0ӯ3d%m<=K^YC6x$V@V#C6ɗaތ'/P[0 ԰)2C0>ܼ. 3;D5KDo!>JUVg|=֬X޹?dug :xh?aX]d.|o7mOzֈmz;HyWNܼk+q%ku<;d=~yضhWX= 4Dhr_O=ezj߱{U٢AOut5/JV.WXƠ>E 5ϭ?L R_isoWW& 9tFz ГԎ^]&BhE_z@4^ BMA+A q5g:IS8x Dc*cajD3zQ46ٓ9¬ldΐ!{>|}?;v-3Au0N'b=0Nπ1NqOHP;i3p"щmǣ}Py"B8v iC j ڽbTJ8Qyc5JT5G;{*KB;{߹6ȵC?NЉ!|#*mMW+) 1:VUT1-F!m j[ER'sdnv䅴UkH5(96J)W]\9uh*$ ɣ!+V.++%aj d\B޼Y&ՃS9I?a)W| oዔTz=r-ʫѲ 6lěsG")碀yKVW/uϝ(>4k dsЇq%/(O'Bʳ3߀YTÅ#{pH!etR1J#09ND2 СQZRx6/=,hHJ"8bu,ξ/7‹Yyj&+Iq;0-v\"FOgP` kAT @)A4 = c`8+^{"}kjz!.=O?t7~ܼpHMNEp{lIoYG<^pܫFQ= -QOz=K ?)ɰ&lyrz:"T  kG`ۡ4z"m jXM!#]"-͑Gq, QK-ǻ~`gs[\uIM .nT6O ~+>%KvBDlMNɇkS*ICp1eDu7^lTM q;];{ $S's'[]\\D_8T«$Q*_s$: 7s }(CI \N0 C Iu2BN=ь37MPHIˀ ?7# ׎}}c̹! -SMaC3: IwwJ%),pj>Z]4[_qlӿA%ߠUӃV#xX;r){/X ݽ^wwc9\ 5gM>o87QhaO=IS# rvF5^5 ={{hœɱzw#0ԐLȚRQūFw;Q0UiL?wcW M>nAɎm)i=Zgn\J s]x&u$pм s>#M6 Yg BuJK _PWۯ-MJ^(4[^T++;-c;x7"$:i[Wu駟O]0jȻUaqx-v|//X* Rag$[BzZjZ7pՔM@8lx,cs@' PL&M19gIq^!ax=J3ƺ°l)IҒ 4ll洮 7vnWfGAgI.GBheAB2!o K+YIBA9>C/ǘOkw7'b7nJyj/Wo/e.K潌cW+(ec&2i(BrJ ӏ^:Ȝ2:kWm86 +VT:ٻa/_-77-d3є73/\C#Զ%Ȼt9e=VN݊1aSxW7:u\[/>3C@>ܜ=x.׻r^ޝQNo^u+b|g'o?j?KcEf1|Ƽچ|X^x_~ozr䇗?1Q]"nFԾ͌s>'dQ8X^qmVDz.߿Go㶸Ns]ϒHIڟVcx)xXrm՗V3ǵ~3^^x1_OdtmCҢs} }c[ٗۮ׽>IxSᏄ͗ϕ%ݫA׹x8_캄tB1H﹪mTZQ2&Ux%*?,њo4lG(q69̼Uܐy!b“{n}J2"Lh ċDy U|YwaCV}QOٴ-(-o0X=a[40/t7G=22Q]W}==iQ{]x"WOUo'xaT6bMM3--p^[ *r$Xy0]vT1JH 3g\*;W4ACyU˃6 c]P#cM;ekj>p>˽mQGkKijVU~**ZͺBNq=Bf;}[G\f&2u #1y/o~(jT>4bQ 礞ڽE(.yO-ʡVbLYǒdWBu($$.Vܫ-IΩ)ol\' 9}҆v($IT>r^dHzeٟBq5y,2mh!qT޳+s|5rM6 nk YiWwSQPYV=t\/M5>BKI]ʗRe[7ęOO=Ŋ]=gM2FzU) J=0ۣ\:fptx?s]dO8JI`;&5\WeZMte̻\ S*cZUQ{9#ĴTzF1 D_)sXk!ul{zzB>Q)J03'V#l&in&<~6Kژ gfٛzkKh%iRhnb5 ЍU76gP-:hdsF^v(*N@ܰP+.-%ll,Hr+zsGzFK]z=#"pY[qZeMp5A_zR60%Y(l04o1qƎMMĈ~A&8Z5)T9`gf9܇G B*N4 Ʌ-,HfXͧK脞oD_:!,46`ӰYش-ٹy !ὰe^baڌ&>?lQ@#}q02C,cuĕk'k*'ze;77n AfFE,a|8J&4q4NE_iTVSK%#I|t$P!]P4 ^g1~Kh4,E.e#V`q@IDAT"D:] M0Xu,H/iShx9|2 &Tnczh>t`?#v 'JMgMվ.{^ɳ#}-OUIqm1\ Kf3ʷg~|J _D $cFhW^5[atRMcI38$GAxWԔ2,4%QG/0մ<,=a:f@] Vg Gce&ۢ7ጂomilZنPQj6Ƕakfd}|dG;rpC#-gD>2%\-qT2$+iaӎ=5IC4FbPBo"f. O2>]O(Uh𡁱.tFt;' 7:AŸ]>Nh($ފV릮SH)nCCu|TAcwYUGU{^{< bLn'8s뜚#\R#} 붬&dnOo1'P^{DXS#Ea=G.*gI{(lݹWjHE94?q4:QOw |_ƒeaƻɝeyR15RǑǔ˷̟@ <`a[<|ڌ~*Fx^u./?zNhkݭÿ9ݭϕםNuUOv1|B`]$H% _l7$yϒKټHI:;2D*|gG%A&>p%0 =kNź3LO&d2Z(8q:qp&-'3qT(-ɥ}<SbI8"Cj%qJ$qcidoȐ0+PB*Ӱ0v؉:ZW7[@2z&2ka|'㿦#qC=#Z)o1 $ycp1ymxl:lo- L)Tw MUF,3{"tM:~ bF ?+iS8oG`t՟V3r )Cz%`Ӯ]IH a?@TzϘ+er6>Vݝ#=Zz&wDWZگ~$V^Sr )KԣM[ox 3$ Q 5t+`[rһ m2cXIcǍbyUs,_%#\!cA$Cos?e\ΐp WOI@C/;WEyR?ym嵠`m 9E JktFɆAGf1D{mZj ֡nje+yJ ޅoMJC);$V;(5%nle4+2!#xc>[;q@ /9g(q\YfB801™c}GpH< KʙԄf4 v]إaO:`kSIJCӟ́N]=]M[# a+CBN*Izݖwݍ 1hFf"t'xS€4ct5fL F;I`;.Jt(R#< __/JG sMuKSO[.C *Md 75B)iN1TT9 -Ugt~*PFps%h,ex?P(QPb.D7@ V+'"R^^w 9G E6;D2Fć&`ogx8z\ 8# 4Ű&i`P,*0،cD~1ر:eLefF:2uyϖ5P2;QxLx ͑Y#zp $nm=0v5]gu6yl*tSbHZ :K?(пaM ؋SR KiSчABԾBXddropAd7: f,Ah燯>#L#+y˴ ^zk5l{ALhKV > `\ IdT2 |edf ѪZ2?o@ֲca,1_3l' !vNcŕ̵QN!=$;sNM>Jn~sHш8.;uɪ9d_߅6m >xsl;A-cY]{y"qϻ,$oGCw.\FiP9z[2Gj\ n&2jN,u^jߐEG1K)Gdq&ξ +ej<,|Rf5Q\ouk|R@~iTe?Ϝ`>н!.6_PoԘylr,M̨3vJupC]sӏDFJ1_uZv.;e3\czFva=|#"Sb1Z!o[^|cb-jkD9c9*cNI~hf$GCM&ϜyKW".Ә4i #Q9h?tM`jk`QS+ӰvZDr>sJsr#;>gHZD.&nPцI-43v^꧖#.91=wMDϳ. ULIpd^ZQژk"֪eH:R8=PRՄe &Q$k31u6l:85> eU-@@E3础9OcHf,L rO\k%sh{BUl͖b|>^` CO!,ͻH؊bэ062q?S*8_vMv6tvToYA^rq>i ǯh2s~FNtwvu\<"e۴iK݌x.G3\X4=sՐ\ 7lD`@_DOo^6{F0ڢuX|)_~-^{!UOWgT z <*P#p~:-xP1$*YOWk̨3+]֛:: f)ΟgOJ"ESF[~K}u=>yH~*zQ]叟Ss@äH[UߟoX+sLԸao5߇_zofRZy j0"l51/7/gVHM>Ŝob=эm80z.VDKsfƎE #!>!ulHuM<uFL\: H*:H;y 1!';'kRx:a$]# LCT~ F&z#&Bf^,nN$3شtqque0>lA%k3R`gA'Nt1"5}k:$y?-: jXdPfѡj1;[#B@i\n.$:k6G[259~~ñP,6`I[>S\;OLB3"G-,<1$[7 ݷFVhK>:kСMbW\썳s鐸t=Ŕu=ؿg?ܼeaN84]Fel:3pʆF^+ n!Mz=gJJyh㥣Ut}̒3vfrq籡t_Fms\5`kQ>)հy(J|A-o)(bnB6Z푔E\ݜIfܫ= p4Rdkj0sTl~倗_!X0Ir2ݼ4K. 4g[y^L6 Dg~Z1g/^yW̅ƍup-c餽 3#O8/[1(*h6a1rC.$"lHbyJ,&c.EGa#L rʳ$*V"0 r*_>UDS,SbQa28]hDᅢH>JJ(Z5vm"bb SN YWeo~1/dRm՗\7>*"zѓ,e݋-RRٰr^Tƭ'K)r ZOk _=I'(Ne'baMp IO5~ /PLՁCDd|ęx[llZ(el㍂Vx6eoÊje0yYXzxDĉju:3k(sOH9#s RS8hK}3|_hᓂ,;|RR||}< r%e%Űupؓ'jDcӂc־[HHM Xj!`eQ[Wk]'`an.i2ֻ}Ս>}z|H:@E9iюEIHt r5sz8$ʇ_Q}o֮?[/t:Oa۱dS2V`zi~yb^P{-N9 GY")(&}/:梦 عǎ'bT8}K꿾.*gNCPA^5u[@me~!L8YÓ9L Z[]w#8zuAٜxqgHèRw̻|z^IĔɧWUs$ȁ6[P13]k;?Ն@Ι*;Cb-WllM8_oYY=dA*Gq=|8"^{ ^A:pp8,mRUeu9N'A>!0c #ޚG҆m @)3ܬQZ_} =FvtHNTsfLCw2 cDŽYԜ2ae>pVO;Z;,7F&QkHy6X:WΞ\FĆc 'Jy+\55.hh-Ֆ0vGO F9vQtXܤd8VVvk{{ C*iNSw>TlO;}=P'u$Qfۨc _^\mff(F̑]xMXEb:q|'pRU[b"mcMFD?(3m9@C/?adDIɧK`!̘H^ww?b(bjjx1ZwY|]ySPm J(G_o-%/=5m^J_G2v\l%JV^ #aÒ{>v,Fq[eFe=_/~ 5R|Pgf|DBF AnOitO(:Hq/pb#ܦZf 49ͭ:xGk >y}:nRj>D֑]s{o |6֓vIɾdVLcFTzd'χ`P&NS}T"Ac%qaʬjQGj~(n&rxT04 _%ɄLtDK7lCUP`h:\ЎFSTCVC 2/݇qw3uVTVn]w7z;,SѨo,Ge-͉d*Elڢ\MJW` ()ä+nfg9>0}|D|8>vg䕴5G]#ρ`uvW,;ʱs `C?SFuq;s^~?lqQ5mHs.A94@>zW#tjÍm!J2/ij6raK*)C ř,QC TrƁci`.c$r(r>#F63}qd+w̴_$m`s9!6# ܘՒJ3J0 7nC`nr!~4X1:=s@A\*1-TZ ԑ PI m0;ԗ >GS#È;ôyepqqWhctk=Shp^ +F|Gڌk0f7dL tUNZdF7G(TEvYfgD97^ _^Z IM]::0#x>r0 l22QW^rBK$vr*mI#yӃ~ψ-96 u qNܫB $yHYJ.ⴴӸ<|pڇ\-o*}fĿW mo jC&`EțƧ_~ oV&ܮo}\μ(<2Btz0eU0|W~*2T<Ƈ.d "p{XBVu[Sb᥂xДEӠme߲J?~~bC]]1 r-_X)疣;G%NQErƨ!z. EPw>YsہK}`U pa=:8P[~(d(߹R]j51o;S EňPQ !6Xu]#ԭ..ʒrYCnxnX&a]v hה"`4L9E"2ǢΪ jS"vdiG/Z޹ɰmrq–pΖ́a݉DJZA@Z̿p \Ș7d~bJ55]s4Р\ >ILM by{x?. IMwDŽf*̼  :\03pA&#-%H(l axO/Љ X(DXNRQ{V,ǯ2IP]LnVVm£/8Cq[q͂e:U\`Eƿ;tyvȒ~nJBr9'?mU LP֓q騥W(}ֱDO{4Neqjr٣`UWR8gqL8[WE?'>#~j`r>t,0"]Օm:q-vZƕx8?/T-dbK䞟PB94gft$XO*EW\o06R,{ Y ]]Μ._y/|HHYMi˗R-6U3H !JzՊy2#hhcH7aFlF]_4US?eqCmGR2TW{\ҶܜL`V?ږ:t/gTψN--CվO\<^r1٧uJe9P 2vTnjmq`9sȾ@6Н?mr2r4;|ૐ;)!w.Y~ L1S[p,6GMtz 衬m@ghfWZDØ2#3RLK|z:!U&FJ5*XXa9 h\a[PcQB^C$i;QF;SL( G&XjE2񉸂Q=:# _a(,-9rrIEcƘ:fz@0_x1*À8+FSU5-#I(ŨV+,D{85Gf4n]5,i2e =8|/*'M pEwUe@MU6}E&{4+/-!n}f| SÌƌS0&j$sc%hTT6j'/OYÏJ:~$',TZKj|I) ż$9ܘO֨ vV&hd_@ sYqggU|Q&هQBz f/C F#pt!HgM8j1rMD--NYv$cۧ@cʳ(kU?NJa} KiQUr^o`UB}X.dp^|7Jb_Je:a-X³ϭ8a!}u৺@!&1ݘq[OeIpW/੬#?6"}IL>Yi`ٯ $yN)6V*jV+$+%E|n6'\ϼB L%N$|Vy0& cs?r hD8ؙ1?scsdW{NuLhZ[chÔе5}5S,w~$:x^НүNp&۵|FWד]!~ܑ{͉m&ނװ S>̇ozY:CIdb~PNk$1C3ZI=`?S3x פ<4I1"uľ8ϙy>*m|m9NJf;t*Ff~)2!hiieaѪpw=oZ˛@ V gę<*NX,%1acပ & Nԓda3-F8#W}|q*8P؊[{ ϑr韩+ 6u-SajdʦƐ%k)ve1ʗ^hoaz fzrDxJ[ĦX+t wL[GG*R2>g"FJ[w ,؇ijHqEɲ(;'+YB_13Јtx#3~Tۨ@]Uh&xzi&`rP |j'AUΨ1Bc-a>l*̧󲱈`uw F2?/v\-&qXSD chc.}F7,]>| .iG+Y[q EF0sȦSқo% I3`sf0Gܧ6paI[/lE|:d"dtb•YsQͭ57/ICa,C0fb$H3}PƼd[]t[ش[8n$}çNF,8vS PHE ڠhu|)|>|}:IRmu=wI]+>xjK*zN5KoYM9=2Q~Gճ7vsG"8d)Ws7=P+]K3];Aۚ50c*c1e$Դ1H'9Vy%|$S}ߴd|l7NKٻòu 2Y^Kܩ7Ö,oySeKnXk' q ֝>X/Xˆ3@ ImpX2NƞSJ)t(>ѲwlZU9k *"?>`W客x LR9B2gήo/߂NZ:&UgxijJ,!bu4zF:>?v㯹XN4|`:!X@q75D2e}q/BB~etV~?mQm#YıYz~3`Q{axD/(w4Y*@{CS5ǰ^{oƯ}4,[˽!YzwClfW%UjDQ.Bh@ΏĎMyǝ`b@t#Oʵ~SοB!7lRpojzFݽ7 h+8w'E)/bnV3J ; Fx8! 8r(Y`1l]A .$2tz22']FLGa62?%UȢ3ۃ#™?R7Ša9)5u0\)w;?hgTk),iFLБgS8+ X.0k\v'DhfZR共*j#R5i{K1`\5$3z#$ 3'!e)O''9@IIgFpP)"eNE+X顳60'X0 ѣ s|INGOkNŻ쪇nFWh$l3.|cu1B hkIw EՌ{b;vl9/S?^[iߢqh=_~gHIMAU~%^NEsgIj)t_{6SDEj43᦭pߞb^[3^O"FVď hod.J'yt6{`EVrC)Qlc>_vme?\\,8/߽{ vSGX12}ncP&z8%E x##L"Js|6aMl#{Ќb+@H>jx,+/{](n6`ʬR7$iъ˛[2zz0<|FQRVvA@g*0vy5mI GoM׶Cƴ$0j(a'.k#M(nB gռfdeV[%#WEaqFv6'0}LTu`y$ClеAaU-J 񽱱`.nZv-)N.2RTyTYR'(筞j_K;ēѤ5C;ĜVLY0ha؝QLۊ4yb]065C8RiB%F$x,v3V p$[B뜚*D!\^nȲ"=6a|udt9:) T3J)ESi>6PB$u MH<m+t1JZV6̍|$#4 N}2biu:8nBmQ5}>jVST:18Hic.bER܊ĶmyoCmjq>R6&@.zr9ud$>=OU"Mӎ;ϦP|]kdq򏂩3_n4R&Gǚa"g7*C G`Œy [UۑV{ 2?YV>2rτ+3p ^吕ApJ)G(;ҿAΌt=WCEm"yppmOGxQկ<[gΩ ZՇ.UCi7J#Fb_H `z?~^ܩ֚]/¸'AοtIGUV̷Qiըřd -rr_ -7QHyωLl`UC\Y84'xqP4۸VD0ݮ޷ȃN ϟkPTTJrD2/rlvZk<|NbJKS(J| r5 Ek"{h4G׾YdN@bQѐ4Eye-Hd264hWZpLE$eɄ/'onM&^KO*Mhi]e MϦ/h6q4Q3'ZXIչb>,8rU"kՋĢAn񨧁/l.NK̈VL4YT 'y]Ԓ\r)=hCC5.BUkmAwwԴgL->J]4 myU7d(``uz:Ϛ䪬a_- W~1o>.p}Z8sEdxy#w|4"£2BxϑMHka@'c)^qEXnŴ;`no_w?|et$eUGf/q?!@k &K3/]"_H<@ʩ<SlQA)$!:~GfnKOw\p>AHSA2 *`.1扽HLDQ)kgdԦ`@Uc#fmX*VVqkachW=SJ/ Tɉ߻CyKkh+Rz:<Xqӭ?>L22zDi-P>Nr:ƌ Exް55󼆎>sğ.D)8*F:ű]UgFKVVbhƖi F04vˇI,-l f+J=-trJθ'{ <9thjii!0hztƎBJiپ SgNpym@_|H(4٨,ʅ'mnge 1~<ˆȟ s~ahb%xFSNz[|vfvJvW,[7g)bvo%FzܱtO3Ϩј:{N;nGFA ?[P89{hFj_gm^2/j ׭d`h-M(fʮ0Gp2 6+a=ƹ9%&DOtFcj;ݷC-mݾeL @CCÔO%'j59_} >rn3Rs͌11j8vx72d0H[kE5( TJrR9Z K\wzN~UAh'Ըkk>%}Ճ)%t"F+#WIC&cׅ?Y|o&"vr,bH%U/? #{0 Td[ΙTU] mk` @:<*Q\_;&0hhҭ t?~TYH< S‰Q'Πτp1ZV$$aT7BF-bjPʽ%r4U =Fe`ɼUxׄ /dhUBҿ9mmcfw_{ z%q|dfM $;|8 :Fa^/qHGTu`\7U4bh̛@5dK#o([ISWmd ==fa8Z|o |]l Hᩗ?Dʘ`ܙT[e"x>aCrA7)b*}wL}p:u5Tc#fm(M;az$l^d 1O#m0wE(.3'?&^U׃Z91->'19TlC@{3h* 77Z`@cU=ܙ7uX+] =3FnFlZ xZ\cM >3@]=· &00#x?1X-ecC)\A@NΒWIvfSKo_'vduE}T"Ŕ'zWf #J s.CF ٫MXt= EdQ+c^NF:@6-9 Yd6U3Ͽ#GEQQ *ܾq[7J6PKt6%n/^D^d)Y QMF.9r .F[Qdh:;oőSg˿hDCE+J<^G\K].ưWbxj:=4=?.i@E:UH!EHMSgiaxT[AHxU$4#їիT6GT{Vya+*̡QWaZ9vmJm릑R4wqs LC9_1hb 0{ qػ )[IDBNO OϾ]lqFG5%1-J3_ݷ_È?548ێ923lZ 9HB ŝ0G Ӱ,Yf"X|*|h4c %Z`&Vd+ƏMn}#%`TK s3q7oQjEW6[7Ɣp%S89C[ed-Ѳg-Bof5eg&Cēȕe:*lH#RhHQ<;3[ ~U/l-9`dD1єtU~wmhq-$I"q(+^܏dH^c d}5G{$p(~Ye(EwLk\F#y;GSiiRMSVבOu)E^_ 4k߶tF!{EYq#2Gy]~ڰ[~ `+MRǏXFzT`J X5˥zr ŧ}+|)/~Ȉ)Y_~9(L}#;J]҇Z9ؗ @x{Lb7ܒ7T")\WrŬTU9O>$)I]Դni18.Ĵ 7~@ϑ8E_h?ʈ׳@uHox1L|u'̢,ʪMky'}x:X6vՕz:U-`R2%.c?uSVoJ}u?L@yՙ&}~ȹُpK_9 Tq2>3G/X"hu S>eLT^q/ghK^ 35s OBȽ#GAgPaQxE,50okU1qV1QJb=9ȌNF0 vK#%zi5*<={ID,Tj:!3aGyC]F!ȇ2nꥦgƭ]Ą _LJ|3+ ѹx{S)eTM`<)1zUQiIIX#ظ#z8.P,(3F2ZyB8>2LiSTvh F.egNL)=WPZ}1 D@d=SusD`pjcFSy2"6;zuy:z?QF2cF1 I_dWRR~l5~Ipur43Ԇ&w+q|IgUlFv63Cv<ќsW3kq:[yZuBIqhSБ)GѪq սƿ2JO;kuK++82bUnN0btt._vo>_|6([3 <N?bdFi0l% /[ /ʓԪkN⦛n[oSNGI?O <UA_8O&ϼҊxZGS27q Vp%ֿs*<ᡣA Qg;d!2_O :y=/AT l\ 3B'`Z`y5i4hFO7ޠMMm"cB Krt!_܅DJDpm˭AB~l#2bˀ?}QOU)e/ Mh;C}cJ:w>`HX9FB/4UNլ+!Jw`-I&@7*˂ooJ#r⛑y3 `"n4瞯}  ڪjwbSz{# ?! DVvro=-1Ic?{52"*QOoyqIanYScɌxcF#;/n7&w}$A$G5'_N3SιLaLjkt6+FԩJJ- J`+P 'TOokL2.KOR%k(\Bp,+c=J@ 2 Q* ߕ(McmhKHGwU6 Dڂʖ7QŁ=-$ y}(KEH%2y/N% m$p^LүSU]iK(Lgzt1쩔TdtE澶}ZmX;64H2r9vw,IfV#]jpej0-lЩצoNߵX;n?L2X.@~'Ý=Xi7&?o{V0Gn;P8F<'IhIaX$VxոH𥕝"mMt6qvӪk4|6pW08r*ƴ%8XӞ{̲Pp)‘]<#ZP.-xȺ דCՋZF2!CYg8v``35(`Vmt4*h=dfm2ed#wތ|CK;]݊J_}XvrrNr4f4y4Vþ(6 INLB[˝;vmI:zh2V2^($7r Z=,C9?9 |ʂQxW 5c<,+BqA&wF):zcC:^$c?{WOeիz_=BgDx(iFd^~a쒿8r^},[/ZLzvcR/__|Fs7q\.P eu0`\WQ,lSZ!Eg-_r$FyQ_&y "E܉l6:FYrRoԛ0ibLM.]oäp p`FږƘsM.#(EڭJȺjqyA96lUW?mqI~ʴ\/& bvsRI#̉rYĴbKK/S -4 䘏Q s9E*ƌ,'Nt8R*QĤ vEs 6-2~LCCJɦwsvsnԉmtD0jl>/>Dz""^WhÕ_oGN0#Hk>nY#`xݟb^})Qs/Ye<7\u2X_›o) 8ʔh>F]JQ=c_~@d2a2x5`zMb$ҖdOa2OJ~ٿ-rk PDQˉ ̙rK_}&]F-o  FL6}9-/} eS-+j!}BfߣmsebXQTaYEڷd/7Ɗ>|]f"|)5<|L_ߦ^_8&i1~ 4Ɛ(/c:Yr?O,S_D=b<0B,Ө撾':JepO/us2M-mj!7#NFlg/\5]ƱJM-et3C)K1cpgt1}ݞ3yB"khA8#ƊUwH9}"/cfPO0T Kf.EI1ww]GCגUHK:,̤Tw ΜΧs9 O=4琿 l@scLX0:x-'xNf7\=TA0#M3XVs8UQ$FN'*?}>?_1C)Ac {fV=GOLu"ŧņH#%+faj- W:w~/\~|^d+9j #₝aaJ3>Ǵy*Xc'etۚhIܺZ,`U\~"*XP-F&Ĩ$/{=I{E){2J0}pzf9ZwbH*+ˇe돟`АHa;f'' bBCT!,`95Dϝwr@|̘D&\N LFܷ',$/@"FP_WbK"d@kwC7eF@˭*ݝɅ)/;_jkzQuڻY]yjRI~iXN6PюTdHRGfUwu{iԌ0\dHLkk!ZV};uv3ﱞkgT*2qtl1 &YdRܛюҾ=n셢&Fwbo\LXN$ð.FPgvq3Gx> "58H^/[a)ccg+oQtTa]3+[6lLv2f8עp,+ yvPԲ|Fo Ϫ0=60%O{;ރfޟtFO:ң 8u Ɍ> s]R2l iAUB 5& 7lJ `_OʏԠ p(X5_zLi#,~Jdafdv;Jҗ1}‡͟~ݾٗIWN@Y.[.TZ.!׾mood{_eB;ɏ4Bu;xq\{6Lύj} +ֵoK{biۣjT;KM'^ɟ('.TdMGAnD^˥dI]m<iW2{'cI:cxw$87qde"a:o54cjLU䚥^9$'"StHRD!xPg/_<عm+}H3Ŏ|o0'ad!ibH;tP:y+VE=j|y*ӦNnV21,N1/S@x'6 ) @3cq8wǬ'r׽(/,0k h6(wZxL-1f\|;:kYCp֩tSL2A ÆΞL&@bՙZ+SPX/2>Hf&͊J-i`f,R4PÑԈOڄv(/ctk)n&PJG;58|hedKP쫩Pl4]cTVy0Vx9^Zq񁧋 ,Gkv6ɨC!>,3I[}.35n4L?d%54FUQ8.u2mlٵEF0Zke^|GL 7A7Bʿ!p"p]/ 614 w0 lf :ov I_\fK|p|ص; v Pׯ)gҙu܏`XFN,LOүsol<:Pb t8_}) qÛSa!-0HcveD$A.OlCٸyqǯb5YS ΜG|p: {kϬ߭^-3tM܀?xy̫`!rSȠQR&A Ga݆ x5Մq<(ۈ_]߱}v>lNjc G}A:)yTDv~>XhŀsO@,ǭH:~-*/"^~ ys1o220R`˸޶֦u?O>FzS)s7dKY '.:g92J}~Ϲfʟ^@g}(}3} H6È(~>zXR \+qմh$WjLt [&$ խ:أ+ {w?za?-bJ)FpQV_(!>ԀA%¬f8$j;;j,r˦/主fL%U(;9|WO'S }۩<N6fX9u0.oiKfѣ~$ 42YظҊhaH@7qU-9zXzd4dBB1j]@WLA5&p1~7q;wPZğzbٵW9ْz T:@aq9yZa\Ȋ)b ("uvj\iPj@%dn BZnA 5`ST*&dЗcsF[)FH\ah?o|nTJhj>2‡¦W۪ [v=5 }{I/Z;ql|#*2U0_Px$8Cah4x>[ n҂3aVjث:d!Y)zw?KМ J3RkБ5liLLjVepvؘa.~he.&]O@֑ ޽ƸDJ9-/fDS:@VvF[nC箍z#d0"OQ2XUUz)]&t 1ҿɾ*jۑwHU.N1?9H/}w^QXY0z) uİQ8v@cZnzt:CL]w)tM=Zm\ʟUͼOX#R8! G:/Ǎ~/@P_yIZoKnF,?}r{yO??AV\9jx(bJ3b3E9AG5DwOm#nt8P>Mem_ϕ!בHJ/k,;tR޶;Կ)Clq:}N.)驖w>?+ F])C_{d#v/ۓV_]7qw}[]^zqK:V,yXz_M 6/.ꅖ-(;fRɖʶ(;" 2v 3S@??_{w{Z5yt``\6GKJot{DZɄK;Թ=ܛPwq!u 3O]nRZiVk16'UʯƆ"a^OJ?SX9nSv ]LX#0Ȭj o8SiP3A#x~ iBÓؑPĕ.]Vb8{N&13SlD)g'ZjzqSCG_;AmR2ZbM#~Ç2/c 0x6 (c6+3\ `}Gq{R~HzI?w夿\8eΞ: Ro‘q5㮻•ӯZfL6Z >A̪mJXZ)eom#h㵗BѓA<`ggSq0AWꋋI!c5i4tLA;LQG},!\#|9ү0@hOk@Q“ӗ2: i]>``{`p3ZA""h8 )Snc:$>Np'cٗ3 2+`WVfK_:ٵm=)}0aEٸbtb7O߯V NÈTպfzvэ[rO=NXF@t3?p=68~=pW~fEV) IOnGdIVSV~T aͻ(ݾ,W}8XRl\@` ꫨ!1W]\+wuDz;o=CS=txOA~N?ć%~$uJS* G)mF `/&Ois}o]KmǾ8Rےzלťl9~ (Gw*m'+YJL8ZZcOA( ȐF:WCGGhUbi v֜=le1p*ZꬒM̬5AgaL=?[CVزs?rŷ~lνl fMd菍w vb ]Q‰5ML91`HTWTm~!?g;$=D0drs$ $-~mQ 1ȅt>~MHZ]FFiS8ɸ9v5%Uo"#1Ak:yoL@Y`̀wY h8ۛ10@WC#PM˱RTBz:9ƻ{\:{xi[5vU%V OY@QF>3SMIY\i'[<4) j۳%v3`m` IlAIp"WSS11sK5%N3(nf (݀pgx8m0bBG0M _(6/̻:(P16͵8sq.9>6&3t$Y2ӿkyz5:HyWϬE'0mjz+w; k/'\<sVbjl}"#GO!CS2 ~L3>`𛭓RexĖ;2.n^ڷ\oXy\E#8Y.vY8e\5*GFEԎW S3'OGw72; h{y+?+3+-+{-b%8)^|GnO(FFQ3nfDli=X#XrvDDi5N~f'6݆TnDןbM4Ahu/ʓ} cE;vaԨ=Gz)gBLbLG:NۆM?!gܞEhƴr(e?Y-sTbO*c.E  u6Yg1ڲrWKmej:Y.Mo?ׅV@v1er2΃^v9M8#,cq@ 1{ܹ4ɗ9o—*L\\$ipNn }o܏^@,V]FPf*sȳ6gsN~g]qw綫}/[GB,3" ˟oTUu|X<Qhr^~g'eQ<=w{dm!A}l#Σޫ[[-]{OVe ]]Nz?G0yR=筞0y}Q?& 7gAߌXU{_0{\8vLj f3B9JSO"q>E' f1%D7:e/iY47[߫k  ?;CYEeJ`ʘI[*j뽮/3KN:pһ-wV1hN? ظ;:H_Uڕ2_j=4dʹLƆ)xOXUMeNJ-M5ͣ}osʽT}}ʳmQ}g.yO[קkiGW,[Tgj,%E߳~yWՁt 5#-n (\7_5%Y+c"㤱0Ͽ}%' =ӱGmRE3Q` .A6>s~2s415 koabi FEs&AY)u]9g~ 7 .Kg,i"K NCuҨ^+IZ[YQs+@IT:JI\sQKP,]4C{RkPOؤ eꮘ@IDATط0R$*gN1v!,r4`aA6uhp(a=Ǝ0R5>1D؈I$ȤqNC#4P Ngq9@9, /f^Gt.;KNMپե9N62tm1SK-K$)"$ď2OЭ/:f%wx &ݏF\K G  +&*MMйN.'tH= 3~>(Ylنc K+0@o` IZjRLr j P^9nD3sY P[ cpM7c[g@YhܛnIL~f5dfdT ]fL;Zi L~z"ݫ|nZ\J!v'sk6h4Nġֻ} +N[oB%㘸x~C4EL"~qK]/T 2гuu|Uc1c⽽̻~6>(} 3*Ӥnͨʦ6N&RFi;cKVֳ,S.O6'3H%ao {}1CP@08z:% ~)vxp$(RTRg.Qc|dO܋Ժ.X} ė޸ C773%ٹrz~| (0ոal'&Lk|7qP,f y{%cM{g\]IGkqDj d# +z*&8WhTi@J_pB>-h՘cϡLDBAWD_`?M:I&F]'1(ȟmgpL `imkGܪ76fԨȤ"f8e̦懆O߄%&7=CU% u8VI_]HAOL knzLْU_`q5 `+ϖ66,mlX4r2n\R_Lz*ʑoϾߘygr1ojښzhmc}%*˙=^6U֎P=Fl_ ~SǫsaH?~yiE]u(E.GIqW <(=f:2SAtbŽw}0YK{"/`Q~5u(~^9resfoO n} '`8iJ/tNy@=/:,[N"Ȫ?rm}rs`@#]=l@!+ /FX:b')X+ +.z:yj'n,kCHxM7*eמQth\|sTP$ƚjGM֋mEf+9}9KtRΩWR",v#ϙ܈}$ucɤ2DJZ]1vs`HubM-0:Hf;:$mW`hS#ı14_}#:skg #Za92\Yž4L񂦳YMH<\3{&) r8{xltaabA=lzh)xS`y1x2f}3 SIԵ RhTt,ݺ NX`[⤛zT4WuY AZlŷ⣏{=H6Wפ_MWvQ,wejKb!̈V'~V!ij{r-b4*_ďoHN.Hݥh?OeA:u>^$uO]l,v rITVp%_K.{S/~$QyW}:ڛ %5OS>~Ͻ )0}p1餣=TXDB tFW#,'N#$`}\f eҾ/wf1GgRGQ;8D.rہL̹fu)B2Jd^h}Czi{R.?z;z6{6;O)亥_w_j]SQ:\(3q!]e@ލ<\pM {|B*m~d;1el4iB5sJN(j jqӭKY\D]dX:y(2J@Cu+ }lN*ɼ Go訟zB/kIyˢ%zS70et8 f~'bb.xh ^pw}kχ2ۧRJБ~,&Ixi=5f4S⑷s'cq_Λmg]AmZ qZ_8OG|J< /"RMwzLC܁ 6;a[-됑ׂ:5"m~ܴ(dэڳ`&P/=wf8iHB-T9WM@s^|]}xWZSF6.xg0y0h ~McƳ0 f,⯾",Evʮ<(m[;=X{/y6002>oZە _~-ḿ#I=@{ PF9N8:Qr$2NaP4רOUؕi?~L mR G20B-b 1*d2S|Q&+{_Sri:}}f4:ljƺh5D^M;4`wj7*绐E5߭GP`gAYـp&@ ij[حɻذ/b`;\H(0AYn0a|O*ךs<#^%nna֭ %zqY3q9g`'N`aB퍵b_8`0CItE#pCt$bKNC r5@=0ѕԎ'Mn QꏪT8z #%ub="\}ƴ?tݰuj6P&,aRrcw"@4q'pxfÅ[5.-)Frv٠s.o1AdhF\V d_|g ذIjS<bPikQc g=ihh#gNṋy5Fz'_>w3w008Vd0X@t0Hb`GzZ-LX>oV%S4UL۝6[j 8PNL%t8Rēe/iͭ @ss+:QJ 阽ѠGف0A~E9^NmXC\2VѷWHăLu(MFCE Zt-QL LkB{z;+dr ja. =ڳzF[vHF  kАc˫Bw8?o!sWΑD\N5~d^y9w? ֟D O~}Q-EB) 2`Bg)L2X ؇ҲTѬSHӽCAe\Sg$:T]O =6m6Oa4h78HZ) %SH}3ڰJYp VM |=ǐsIץg;1.\%Yݣ Z_xNkK:iD9eKRغm;3UU1.αa!|&8y꘽WK&74tg(r16 %:SԽ_7%?P l#z[&n-qj>RxV(:UBɪR46{Z݃ ߢ?u U'KkΪ6Fo9KۍPvhH a쏊 &uԤ~5C- S:**aSX PIUX[RvPO{#:F?CM5&0)&IdB`xl'!T؄HKMä ci,(vς>;SQ)u06c`J rdE lIs ??/(!HI:PjEXb&V*8ɜۑK06N)AeC#K) 1zfIpx-_|zRMdn 12} Zz"2r.CtiWڑLV&^q-~# ðeZ70{5͈zEEco,ƒ=>OcW~o?yqlwoÔS{U_#}R7.D>A9ϴ3)/^8I~'=d8/ooH@0g2k$9PU0wy  g:|==])ݠC_'굗:[?s.ξTt^*Rdc(Cagu4}_ăv`  (,yҖ{'2gUkwI3#[f_<O= OBOm;ICp]3ۂ|Y[Sg%GÒrj]Z{H(.fivcw* jSsUozv~ȳ?>UtK>ýi/Mj]~SMO|WKmhW?޿_9m2әQcUhfbs1S#4C$8Q[~9dyg=f2r䪥mMt830",m.fp$$}|L43(_fӏ#O>? .ޘnEcdD alXιq&HJ?8PbYD%(5+Pil 5Vܖz :!Qa׉q6aa9]\9jBcp[>kS] R&_{`̬]= j; kl#[ɧplO0󣽕u;n}Xx?(Q 7㦛n%VYZA'!3'ن sǢy = xIE@M4C"zOc"b=H?),aD>F]H$M:U\DS`珫y q^Ë?R_T 9wڷi f'& ƎkE _ .3+Xr24;\|uߡh_81C6=6Dy Als5ƜsfSG&0W+#1Fay"99YLn¢st'jɟЁݮésNAMU-@!\%AJ.؉Ӱ̘um*LrbJL;Djvri<'O܅hUg; ~`l*]027͟ãQRG@O)>~"Fp~^iΘԳu shXю޿T Xxi >.g%)Ū_a`(avԩ:hCI~νnX5$}B9S%XFoٴԵHIIe" 2ÃlR>~SԇY?.:S e#}G+/[q;Qk}HêO@ub[VU#TRw [4)kV{H}{$'cBbKcf~QX;|H1gR[( &OBX^R#aCx PoFv.b+f)j0cmeꨆp)=K bO2 D}ciysn(;L##Fb`8?HSI=w&j]p0f'[a@05}+;$QL0 u;sN@Y%e8 򀭳R*qצ~"5̎wwPXF\jn160bT u]{;NP/;afg&Ot0H:Eh>i>f9R ՝㥱n ܔ8v0J3Nz0q5tu*^]S3ܘO]JO%uh=x=Q^Tݶ {7[/6P^y(c sgnYP6᷐~na:Ra̹VԐG 6+MJ_ )m Q1TkQBQdh™p% օ9e |mB֋qcKV:㨱[P_T)Cuu@-%,Hojnsω6Y d GE㺥72{(@Fkҿɺw ]hK9~R@ֿɔ (Zc<ԩ(!"40Eؾs )5($@JJ >xVTa'O7_gD㗟a$Z̉Ś"|4DHH 녻_Uߒv&T1_U/b%i_w*ڍzPNwıNDIro(9 h8+Ǽ0/ìĵϼŤ0bʸfҔ:ib\(l{c]z؊^^Sk>uj_ijb x2 G}Ϟ ՌJ5C+Пd!# F *`VX70jQi>Hg.A0C]WW(G9cN3qlDcO2v+Gi(V\IVi/uu9ֶ4o E5I| kv(6%Q{KMGWW@{Md2m1pFlGPnjQnz"&L::HS0qlGC=4 HQ .8p9QG}T`iO>ٳ6 P8 Vi;SpɅZh(:D]1MYINA8gaN3v҉EqCdu4EaFnqg +LqLH-p߱t)ͨ9To;8|H&Gl=~C8ݡV_(-E.3] ?hxy1;vM!x~JЂv#AAs)q$Z5uªKlM5m!DRU_oEKkSUъ4~zi۶sm}K?m3]Mշˁ s?KM9U]cfhˋO8" :>K#4<|Pwo ʾ#ˤOT@T}Gܲi::}!ڂB#K=J}1'?͜0y(ݳaN/=\d ]d)/ X(YݷJ05m04q Px vn=-GWaKP1 |8򷣠4qg:m:9jSYh;\l# pՂ2* tXFXn?N5KR:uIB&Mأ54PJ?O_KFu0sxavRʹͫHl#U^na1sUTIJfb@ tXfc.Kc)vft$0#Kc :ݘD{_N䤧VQ{-8s>PH\h=qWKp/- /BCLcfs{oR+gѼZ@N\ ᑴI;1M'>Nn7gW{k:ba扵;a݆7;3(܂r*Š 'fV!a Ч5%>Z졺l}֤YE+T|fɠӆ0дlG 3sDjʒ8zɠ:≇YW'v[jH%|=iIF0e^99|5H>?L S ]'{K)MA ǛFE[PB+=v!A"eѿ`;bNjg/^f9&]qV6'Ng] eqwA}FK]>&13g~=lC8992@;A3u\}kڙiFZb72%v˯wS{2vhbjԛ2TI8袿"s~s-Vg.+r%DFY2}_cU_k|W@`V jowOL#eЈ.C/S3ʡ bٗìFI0VVLAchaKsTL &cD@pK P97^= QW"|[CqxNWhfeNυ>)qIOl8*f¡꣨P7b!/QXys`])WǪI=0Y2T oMV lw?ޓgѦC/:ROaGlBy[2Ò UBy2 DJ!&FoEogzY1X@ xq*` FW#Sm47à m쭭n0!P Lw"<65A !t& )05c澡ZHwʂY?I5][@՜״lݏ-H!mmKM]zvqC3[uI FvdJdDp!Xq>籠\?ΐ:7 ̠c/&mXÛ8ǾN92;DJv2(Z:MÔQCQZ}s1H q%l|p,) [ccp^{#tO.ɦ'o}A@ Fj}2ѫ: ±7g !\L.38`|Y>8ZN[]qY ]}CְsOǟx gV0*`&wK To_朗纔6k :+@ֿ i,8ٲԞ]1D*iK,Q()4"#OA2$)[oQS|ucqNZ&1| .ʭ9~`ˬwjߗ *g:>sdWMl%XH'[' CI[{զи( 'ɗ8:rJ-[y Pf8(+})٥bPOX"t ꜔|2]=̩#ȥACOf&( ~ȱC:M #!qR(=_F8HFڇq01Ŵ}>חx1AϢ4(6Dכ54w:\kS_߀<|5AC=Z8jjٯetq:78%%&aDv ‚~R[eBŎu( uou0gr(x匆:aN(ӌb-g\ 8WF%{#رt0 rX31F*,0f{O9L3/:d1-Ű'_icIW#]Rա+U GQ֤*BCUdzoގQ.54 pǫ۠S.Vה6'Nݧ\-4/˥SJ>Lng^qR|w ͽ㼫L?oej!07jV>;ouu5ọs@ۥQB3lwi_jS?.ӟY! t/(^}!Fzr/ds!Y=`@rV#I _zH3.=v*#HM_DLnՇ*񭹡rD.ꩥ"}`f>-p դ ZYq۝ hq `}Z:q+z^uOR_.4#EO}hfpﮇ #XOo:G:̝< CG^Vl.X"l|W0$rOXxWmGbS(c_Qw9fHК:jʟ9ͅ>/{ȱMcF_>L8A=c7޹jD0{~ᅠ眂y :fM^ynksBG]cP2TeI0/Q=x%駞,ܲ#F`Yغi  ޥ˶ Nj)p?Wf"QrllZ1ZODsI&\ tBW { ntQAՔt 'ofl:#m?jyt9*l,?,NsՓ5p\0}z}X(}e^rNf=Hs, #xX^S^I`dyUDZ]{2HuʷPohGJhs2iش)8{Jp.0yk2NAm9M&4vsnVO?yab)v0xi/\:$3<JNS>s9dF>l|ܬ5_]x2fDo| Gj>ps~a?>ߝw@ 6z;Dw_G#2#vI0A]f& ndIE1.ۆLO|Ⓞ"!w(-P(PHݗԷRow^@J@qww熛C}?ܹ6w}><*B\\hcvWݮedxm=%d{y0㰷q{KiWD=o^C{yh# _w+S5Z^V붾VY #x9#Q) TH3".@kdh825$ c* `(Hn@'U«n20pB*vSsЪHjAmߨ]5YA5$&z%֒c|UoK=O͍hKgA샯;>X_tlCΕAAn*K%Ǵ(rrPpd*F29wskNoiO~F233?Tٌ*O4Y]܅rlb8 ≔,hA2}ZܩTYg{:Isě_#ΊbQ<7^~ m\?:!(j"PUQB"R>y hCT4b%;5(;bǂakez3`c+gp/\D€ZQ0+? bEy'$䗕#z UXI:kJ:?H8@ Vxr"j,L/XW&9 d‘{8`\Bz6y frN998L@y-ݼYLik0]Ws JbDL_w9!tPx"qL( JI.a>+*T1 9l*A h)u{ݔ-fwaD:_&3Ч5Up+X53dn?m wOb+XeVcc*, SAf9b#|Џ,*e /GRᑿՔvŸ# n*|ı`l3I_#PWWVoC $6ixXfq~<#/orƎZe ~$uIՓW?ns +8ړAqi݁Ϳ+_ Vd:[E|aX |= >eh+`ijoNBŊQ+BmŗwqXϡվ2 ."|V&{e{{MZ z9$UXt2R YF};4(Jy~N5]KAwܮ[N9';OJY6bLV,p3hJCk0]&LJ| b%*y݄&%SG {'Tu+$6Jة[𽅉-`G %';NGv6plԍ bn]%x%@s 1Vx1M`k<61>XKfqr h0ipwi5ac>X[KQ0>s Ay031讠VE)d9dA֝ s+La.~#xb /RȈ[`{#2 J%PقJM,*z \TF.4eB ¼|Jt"6 I &p )R1̲Ƀ(AFe[l d!W?:$g%(sCk!ݿ~E~rlWn<#Ǩ)ϛ_ {D+]vw)߮/2,)gURVM)|GcZd]0_*\XrV][Ȅ?YQIhd@V@U"&0e})}xo)~y~DyG rzDN iEo9L0sy?zo\o݄QLoҋ0rVn4VC79IJ՝>TFXIFo|I=uϡo̓cRAN5!{#ɟY}H.V# OӯK=f~yNwH'׍~A\R>rϟ2R9AXVDvf~nAo~~?Zg_~2vl`gf};Hx+5=2RP̪£O/=#SZ|fF`{=% ?ֵͪ|E^i=sO$XLQ14hAUɏaTS0V쌲6K9{2QYws\J'U:[s!4r9ٔSji嵬ͧ,9wuj]3iKڊ>D@"߭H/|ظq=:ZX:] `qr? Y=+,QWӈ/Bz^1^y{(B.,^6EP_GyLَ++J̛``a ŵ:I<=&y( \;P}~Tbvv J'Y<,Jվ7}9U1ƟѮ  `EҠhCq3 }ʇFu Wl@IDAT}9R 9y&aJf֦J|=ǡmzcN1- ]l aeBG >;͛'x}^ӕZqlOr4V>,V\U QC򱀢(%89v* 灇DE _ʃGq)ي,SD~`1Q#zVY΄ %O?@G2ImVΆ7/fpY/4Xe 3ga_^DEb}m8UDf->BIUO_A$ {'u[ zߥw0o0NwuX8 <ǟ#1t3gO9o=`U7G/?SY=SW :bL7IBu?EJ I9?tID 齐E~~ISb˾rHS$Տo !o282(cp%ȱYMVIeߛvέ砎d y Vu`tPizl{Ec3(J6v)7Ձ33$D%!^^[IS$Ӳ,Ø WQbي5n$kY'0=|ChoF1'(筥ȸ@o$w!B1r?H6Cdg+] >Ɖj#["shء#Χr1hA7qa"X+d7vG)eYmL2^TB kF! ?r YM%=9k:>{~5z@ +__+Gv\p}y !$L:OU%/,/ ne)oP-egqK='I*8v͠R_Nd@.2?)8WHf7ijЁ}:[[:{ S^'j4|ܷaDP_EFc6*.ۋ{^nEw3Zە>mp~v hR6p&U6^p>d:gbrIvY@8unO)cWߟ`3d};/=I oc+Ϯm :b$Sz##ݟ@s7o18t8cyϤ49ij@ Sޫu58Ho;Kf~{ۖ?  7U>^MPpk&fXh.\͠} p*)T[n#ws{أtI\Sl R~%л%Ԧ2&+@O¶Xq־3\;{/>/xgTc},(7fKFX{{;v5T~1V1f_MzޕY&$aJS NW⽣{02vV&6c?KEI8|=צz7M=NO{RԿ7+#Ȓ]}zD6ZqڿvM=~KKg O!ҸO? >,ϛxZD9IH=Z{ssJS  vH$BF&9Hsi|,Yj'8٫xi߇56CۏcbD8t<* EP`q Y: yUBp]==. ax󟫔uㆎ`+Fy}rݫݗZ!>mvo XfgouG=+\ ن<]~P=)wn;_wK<e1cP?NuT~ug^n|[5ۯAw׷9ivϮ73.yNXg5p(dQkN$xV޽i&uK+qRVvHGTD";%M":c+K=]S2jh-yf51&0jjLV+4"0ЗpH-`A#Vv8PIe)bbR)5`2e3Z(L%Hk-Z2Hihh@ -~~ѓYkƱQwN${o7e'?q}OڸM碶1 Vv$9 LM:08W\1 ܯfRALjJ3חI꟰gq4:bM]~3& AP@ _|H$0{L: ì( ~Ίs nEHI>7lxU3jCo?d+GCK؀S#Of/nݷߎ!L?Z|7.ߢ2Δ+g+s Koqˍ`Ʊ~7doAj4ȧ8DZ:Z-=Hʹ(+!6__c-eVk֮_`wCp'XJX zJ b!p611|uYCUg]Ͽ"p`[s^۩V_CS-͘(Hv,Hɡ Ѧ5Z/3yX,zU|(tIˤ>W[Ʃ/1|jaIG4q^xOw<'}z&ӣp^_hf EO҉\h ~Kei7ߴ*F_Яٽ㍞u+gɆÈ ;㗝NB2y'3a5}9cˏq`_;ʠ>bD (%mcgo1t==;'՝b(/QH _~RȾx\]O{qXV=~?Mrj̪wL-I#3Ethð+Ok4XUX:슧}m5)$,.je,kl%=NmE:`_ 9PRQI:l?b0gڻb9'Xf/ioiNP9ƎZ,pq¯0a1G{r z[~Xj}MASA>Z,v0@,>/Cf DYfNC)f~LTɦog{8s.osnohxlݴ gZaVAJLq{U5h*~a Q\݌cH:2 :=2O;66JB>O.-:bIk >O7=uDzbtK*yn6ibVc*g$񻠡*b'nk&N1Xg*%PmNW"6毉=4S!''0Vx}w߱ޅc}?Tv0Rʠ?ee`1~/U*<-7bo=>,wю2N`A|^Ha_*gÇq86ӅZWG P-;"HXJGCEv9l ~&'UrKSSeK%lzV2y0/^YQwYBF I0xUYbfؐV2=q3L1W50g&aИ߆Rid1M`h=Oye凕ϵ\g[t)ZymՅU0 [2C=;G=[єNv^Osor Y iڷKs kNs@ԣO1*_A̐J ӤcDX0x+&dDQR)I额d8w Ɣ% 1ouDFQ޾ؽcҌ,V~7$=*vVQ7*48?,C~}u5aPjPvI7HOY1jw=Ni?Y n5D6$\Mq~VNdkXZ[ICQA`zO o˖ﱗug72&! R1#?\Az{xZIX *ffk''NhPze*ٷ"cnv!ca'fSeZLG8rЪVpw.Fice(32-A.|xx'reMH̿?{<>\d*UR"{a\+3V%eҗs~oAY[KAcCWUR$]v cCֿzBBC߫ ׫HMeBژY/xJ3rײ{vfsIoAJ{_Fksū{m> X)W ?_<*ܺl>+nd$#hfC=,6Ymp5xW4`{:pvRm d]o?4%X_XB_F.~ ۔tms":ᗖ7SsіCJ[x >B{"_nr/.*۔ oT;cꅖ]ײ#.0&"1wDkN-mshFČRtV݊l1~_lY:G.T{h`Ŋ'mpS'1ydzQeTX[ǒw`kڎI#a$:KjUu3l(GL3Ρ!Rbς<&֖d)էeTS2BS'+& ZϠ>s@9-7Ͽcϥ †wP"1i2ylq # .l5T$oq<YFIb'x:tZwg"vs6նeCXAdT2ΪtC1>! &Շ` Lz:q|e kf͘dk,Ĭ zR|bb1<,;As//_}^2d?M>fX/o7'PQ?"\rtTW Yɸ>lL W*4 *;bq#pwRA}HL<wr}7$sFN$}mغ};]QZVo| imS^QkĖe>XyXz-NЀ)X0>JG}X:qrc>Xtږצ㑝̘pr9F\b9=e''8AO*Č@OAuO}]à% zu%{E~-P3}mU?9DQE&-ΛdnGI#(I ]u(@ڱ4 >AYEgBێz-r^mVM⊜"8vچ[ՅRnlS?۸ڹJL(n\[ܡCbޖ5ڠwYǒgTb,PǫWH n4zj՜lCl ~$nҝ,tԼnQbU].kpŒ1}/XV}6v4&i@[N'XPFx9<i CV; s@RJFű*{&cTla|QJN/ '7&8C:YK{=\PQBR0;b_wU`rSO D!Șk YL04# "5"Y͒|N9+"meXVk0ghkڊ9zT-(>θ6(Vzp03|6z 2h%fE GP>(g|m>n}a^ hd֘2WՋNhH(?G E*uQܰr􀮠Zߗ"9`un̍ )J g,Tr%ŹjJ]/ԫ(anElŊV %O9JKq}}yK$U|ŸmU*{d+qY*=^<~OYQͼyr7Bs"^1^v֟)I<9v5?U6ykь.O83KvvSas?oO~]|Aɍ 4YGjهX:EK_"vP|@Vd~Cˠ?%O뀝7e#hh J<#IGH<01e!lV<.phJeXOډ{O[ qWi0&t2ZLԂ<Lń9@2e<`TD93`ZL2ZB J6IB ӄLϿ3n. BCrF9NTuCE%9)>D1(q,T2OXvydoRg1!{znø[Y hZP&dA&\@rS8>Fd#g r-|YߵSW./5i?T ֢\J錆n%Q *+EI_ѝ2?Fo.:z7yU=?}p d~tgn ePRYY+=.E_PV~~UmrZѡh?]Х]d_.?caHIqSg<{Y9kqyґՈ/}뮹o0sWSny>bʧW⻍{;Q(YɠOlBXR~fT8>ZXhQDvOK fBȦ:J M̫ܕ ER: ]TNyh9!M$c4N쓋 452YAM"{-mxgXeGy~ЅmndEQ`+BXSILV7Ŷ f;gcLΫI܅C pʧk׉QUILEs[sϪ6y}7%jOU9v^@^Rn&`{D>'V$mYe*R!~o9+F9jߧesun†ҏyrPב9ƾ?S*g4K;Fսvz礢wt?to޻o)*'}l߅?"[/9~v.1L>x*iUlJVQΏ@n_(ODjz2.V#X ɱ|ƟY9alfIs+Dr*LV`7_n!\i+,p02u ,GtCU0$iM}51&Jnltdt` |>bd4fFL|a8*?GĊ[p=3NJ#dp$4pUe=RkDsАwP8ͽA9/<եaIPpᅕ+f.8AyU! q}3 BKm ߌ]12"6GYs E?*%N&QPh̿F9r?y%9:uL8zwLpAS'%ݡ$(++˰Gz/`ͺu#=|ZFPi@gS5+nv$` OW4+R8|(ד\1-:$4:0WmXZTj.]<wu WK-xk, 0&˘uSTK)gRy# gH'6|PL̬'1|HeM::B!C OL[cM GAaQ;{v܉'`U !tS%{>_u.MǏsXqA9+Q[D"% ][MYȫ^|ػ{7eW}WU/7'Ip$i*D9""z(yM4R<+$i8@e؉{ ]΂}SY q5rpE.zX"*x{/<ԱE g?RYu (y*:){a_UEclܚfCJ>-FCu+H #۹GuaDL#V(cS-&E65V󖞓IVc<ΓPcVcq,'@nL%m'2_Jq:?4<|,)%_No@x2;<&ڲ\AkX @"֟{В_'NPRȐ֧4”$Sy@(ՑZPNPNǩf̸f*V!+ox |HnߪJ&PFQie ,AxZ"k;μE'[~kK9!aJn0lHjXMN 2ҋ /D9SLō\pGID mSK),0lx7g }"n ʩvHtieΑ> P9ST$͆/*Ih3b h `C B1 ZIdAȮ0=*j'٘yQFMbXJ+ieNV͑ A(Ah6#4{ݐERvp~xp҇*T84);uo*o8I)#s2ﲆUΘ{3aeg6S$c2Hл(~&$p@i2ӣ0 Xht^`d'aܲUؑSUS [H)yp:;b!i03u+RĠvOw/$SzD O!&O+M V?ohŒ3pC[ic?^jxAV鸥P}`0u{~b^Edʸ5ט0k1}37Ŏ䃁4VMe0v NN /wy,dN7UR֞.ŢE퍸adt!zزɍ/5IBI[$ 0S F;t<˽W{Oj* GoI4St;2IjCSYA،C^yu8z*o&%4w:C  n\(*$UUy6І\};O?3o҉pJ@iG_{X1 j?nۛ9Cw~GCb@:&7z&{0ǤQCQʜ 1s_JDZ?\'w 3s#ޅzfSs])wżbp ؍4s1qsɘ#񤝒&H4T z j[}pr,Mw9gk܂|Y{cMwdK&Hk7\& 1cFÏVOi0 \6uSd"s51dr@&O/ _:dP4(r8a~f6a?s E^a l(b6Dಊ2\x jȁmE<ѯtf`S&嘭׭F刻yM}F&RQ&%'m vmL<9Ktr}_=?1UYl']@7q r)BdU.9^J_8@-A}%qwUz^':ո%ޛWbKi} ^b/%~='V9'; de1}unV,#oN M" S ZkkQֈ(a}DۛJ_Wl Xu^>DŽԾwMxw0Qdb$ћWøasH { k r}24-{1g\9SIH{qC)ٟ *39b+1nĕ^HynS| \яC6&e :59x땯3ӧ\]( J5/ ?W!l_8]kj/{Pr 4)glF9QJL$ 7,vsrM'H"zRbr{ا 8D?d*מlS9ξf3(S*KI.k`~Ȋ*?5_7^A!Hb`U*N҂ܖU"Ԕi ] 'b7IMqլqX9D:bA׺"j R*르/݂L.np"޷f92 n=݋WX{ۿAo3uedgW2-Q(࡫kReQVo#D_~z>eŬkfH#P?iyqrRKZj |*hH[C'(h ?z86U`{b&-b%`*pp,8^oLʧSx]{K}*V}Y s2i/*N8"qU_әŨMq[%SVj[ȑT-Ț}v4(.V,ݏ~nꩋŠ*Vw܄Is'( TWR/ 魔mǑ|pիowߢL/Tz믫~+2)ʪ;MO?`捰X%,; PRw/)1{eQ5.MT>QHӫۿ۠*/YbTLI'Gj|,OYc56S6s q_rےcKKEXQw2O55VK{gQJr'Ag:y7ENy+rYjOUgoSߵ >~pf+aϑNgIqr$~ ʾ[QWg):x/'P6e>TZ%TF\hxL\s SEp+R n|7&+A:JڐQ9\lQb K; wӃy5N2؂(H|d χH79a!3 5Î`/:d(v8[!ܫL27 e@' +`QnRVNh{P}lІV OkBy[m)RVZ3{) P^g/08hpU38?(,ΐuF!8zʊ .<yJ? mFyw c܇y>VVdd典P/bFPp0VoWHtpS`?ۄ@G;kTIxK==`sLof*UV65B1۟N"X]y.d Gj ;q-)d{wPeE,87߭%јvp02xb@S'iD3m5xq@"HN/T*|qAj[p}=)~mmOlѦit;/v/+~߱Kن[ DBץl뿱EAVդz`_N\rRoglܴYX% ^9cPO]'O#IL7LhJ Kd^2ȈxXڟ@wy!g]v*U( ;ppf93w#f:%zJp&1ՕuIRP}Mc@COEW^ҚjB./xqn2r2_d{c=ܟXLȣ)xgIOSڒkV Z b+qJ#;uKI2$jy_ylqdtu5YkCcl;tư##Р#Id7+/և|!0VRFT֏ i)څwi(q<7Ldžw"di@Z6"4pJFFpq :Vo0klDҹ(*HF` G:Ω  K++#An]yG"n]Zce@!n&~00 4]z=ز%%8?V/Ffjʣ)*ٍC|.IE 5\-䥐 1a\`򑌙dP&Ϥϑ BPT!>ڤ7JߥgKr?ҩOPAK;}oʵHyTґTP[Jԋ`]d|Oزp*+jKËoϾ GOew7PXT+cOe9,~`%fi[4b3mI mMCd7@&<`dnM9R,b1hj7%p ZC0tEķ3I!Ph&#BsDNa ɑ8-3`ll)kc=qFMHVz3aB\ wVd!ۃ fޒLb Jic_ӻkmG>vc+pчŠGjoT$🃳;cǭKh De?#JegeL&+Rq<؟Y|͘TP)(,5@{s+aL&C91\7ܰs3cn`ˆ-c0t8e7H*OGW0#iΙ@evҝ.kK՞Yh4! E3тg!3^HV:]l.:Em 7HnB)LK} 1֔u;NH_ 2z0sGArŋ Z%W^ xZRw ü@6؏>v? Cݗstf平"(}W_xWjDMN#j^u>P J1ryŗFqk B_'={V93X*j> ft_w"Qz:)W"wlv5Z['%`%XՅ#m(:Ђm7p~R^ *k)y%:M**2e]]3Ubn>̾jڰ;w eZ1w 'W*WA]x?{o!Y5Ta!ά`Ko?IMB(8LojCɽ+c-ǯ$U 8 ?5az6/H`Bc)h%M}1t_=7eoXtWel+y@u$8;n[$N37)9A~ڋw" `μJ32?(,laH({t)$H 6VUTMe*W0.4nd+lg9aN_ 7.Y)3e!DcRcaKД-'iJ5w1NמW|OOx-(vԐg>-IˀVӟJKo_޲u:e Snð;k`_ψA(jgmS+~ϰf孬Q^V~>5x/D ںҗ!#S"I363oDr +eSO!%|r˗L$)Ĝ6|xo{HHk {V+H޻#ugXKk.t{/2]Jܢ/5 zUV]$IZs^ k,UzE}15E†9IBkU|8(r+--o&^yuel݂e/?ouXՍKN Wqp曵l5Ѧ.VQrFZّ+`N(fš32?yRټ2ퟲ]&f@B"i7Z+<xK9K}sQwa ]OvMlb$lxMK5_i]ajE6l%ݎfiX]LT#xjDfϬoL3rN[o!/^t:쮻vq! &ū۾ yK?匭x~y.jTC6ALN6ԝLF~~1*yr;j aq#a[;A1wB\:%I:3%JDpm>z(K!6cy_߭+3U  ʟnS5/bHLL,|dݩk$Rܧ2 )^਄2^kA?z&4Y&H &(=ݺϛŻ&l;w92SaUVL9%i\baeYS޸./V56Y@I$H[g V'RVo`Mjkȟy=?Z+RNҿ@ܝA)}nS֑㕩<zE~缟dvo-ƬyW޻O[.XH Wlڲ&`Xos6/odu=K , ^nlT{h1}܆^}lhv|dUW޽o7}[Ͻ.LjO8{2c`91S?[ /_+W}m H$2QG5ާo YL ox"z*ŮUz>]!!Ms=}h]mWVU5'jKcK)]:ƅ^/qEd.e*&.֤E}{) $9:(+ۑ / 2-͊wor0 ԓrϑVεԚ2rO՗6VNY?(M%Р_]_B{[*X9$}t'|ZctY>Sz|,YF~KJ(g'{~L]u*}W%H= <)\DlaE"ʾ^CB*Bh!tHPTP:^Fѱl{H#${־Gx/}Z{=_Qև}n eeF* l"N@ͱsu ȪLlfdj vs&xY[BVram/%";wA  }Z`d 6RqcRGOO(#+=9nцzX3'.>A?;/s3 .J쎟8C̣kbPD!UYڻOZA@G7'!عh#+0y $3GFj2gD'3YA7HQ1k%Њ%i`= 8a0|f=+@{Ԣlv% ]!?\iؿg^-8˿kKIMs~xWP 㕏Ϛq./M'2 _ 5(ė}J?_$Ir#q"#݅@yʖ H AۑW V}>8 .Xh9Ff͞Øv123Ʋ=mF˨ejnNB{IMU-s H_pxR);bE漮<^ʨʒcg# mDYn #*v/.ʲn Φd'£@vIt0^i?k#44BỶAdQabdSoNM{zqDF 9<Tj"QÚ$/{l徃w (qTr\,L/kzO֒*$%έ]reM ehց`G,Y%^*nÚU(h’9HJؘx3V~ yYYY,*wtTea&Z;\B,6oی**$16IMN`OW[hםE *מAi[8 Z82WIEG+B6P+K( A!>aLH1KX;1c2%́:ТmmZAiQ>n1}w }%vOF`x5gB1##G(/Oa!`&?#%b_>'Ak[V&U EGuYS*׻k=>=W*jq[0oou[PVv`P$ݓ ӻ7`#ߗ #kK;Xg'Cl5(g}ܻEcX|#6ډc *jD5oyLײ-k'~8#篜xT5/dݺ'TnV1*ە-v$EkmҟI^R 15 SM*Ys=/IOB'|w _BU{!TfۯCy2x_c)X$͊: `333P}M , Qn[޾IHܱn,>:I^XndGf¦^riVL8y;n%6Vm8 J&~wGPH(f_$2 .:QfE6=jIdDž JO =gt l[ ? 7,' B]I"b# qIu]%9_G$'㦑HݍǎaQGp%ꦔǟ=Q'2၈d[$OT 7-ƓeLG Xؓ1]FaY&=ޅ?zr~Uv(R#7o1rH8 7Ŭ^sdu9 $yg[qAfKà^tǎݛAmw%Y3^~Yû]Dϻ =f>Bjc6?mݨT7=]\nfo_'c{|6*ƛT.d߾ZRrT5W^1ir9Ul'W_n[ݾ<_q-MB"#c/Z47*X5jG.7R郤oNgYT~/O6479X' 2o+qX_Ǩ;O)mo)2GBȓ~Kbys#R0'2rчiJ&ĺ)ւz="5 q]()>Ci@/bG{狾iU|9s;K05F1޵};ZjyIs^ 7%-ݺvxowVJ s궑bS{_lx0ꩁ+oQ1q=U0z$nn&}k_7Pۘ0Wׅºo} `ǞCitunCsc=&OƮCX +EM7i)C0J,(Q:c%V.y=8V #C [ă_qleǏ1ٙZ~:0jD0ΚDbg ބx0v |xfV6Fr~}=Stqkm%l6dDDga)z:3A\S"+GJה}O?lۘ͡˪9*e@X~UnZן~,*{1*Y j> h)j9tqr Qcu%Շ[PK֏ysm ~updyz//quI *.E`?nSfoǍ"IJp&=Qcܷ+۴g3`A={OޢX+hǓH IBmbcC8S8~;{8OPa c'4RiI TKKAJ1_ç(>Ws7\5Kfe.Tڮ G 0r/z;X982^vǸc2rv[(Y!/vԴ8CCS‡8qVFsH4Vܳ&-\d㣠kaSnǠШzÒ 4K {xOZ究ăɭ$o Z> 'Y=giSF,Vs'9ğ7` :X嫵*cg3ݝ⚱3Yhb$7Hk MWJ&E}U)I(y~~HeNSx8E+ B(]\,'ai[OǬʸ^HU<ڃ`(%5$#J E1}%IAw Z81A=Aܼ B\vJ[Pͼ%ᥣKYZV_, +MޥfVov0QCӪt)/Vvs 7GCd„fmd-_DRE2, $Rf1L " V mcKx݅6 #LL5.TOu2-#( }n(0FV<}<}Zedsg^3z/YԷ9u*]lfGjo5GC1:781c?D{cWQ>f!a㭊* :-Ti7D9j kVg?̷:Z + wܶ@Ql-c2 qR.y(jCk*Hh5"8|Tա|&h6Q*k:ublςiWbeXe;/$K`[me2TkJۗG3@p|YXˍ9\mY;8FvO<Bfjo|zd (meٿKXYZ%FY/.RKm8 W׍m~7_6vm3s,*IL$RDsHJr_Re:2iڲVٞT5IS-Lbې}жg8 O@#ijG %q&xɳlSXoYI_@ZF|C*tO0e'+\o$f՘l[U{p f'r2c63zBb޾Zc2Qyn%[j; 0%zX=7 k:1u4eςw fj)][6b¢7;Mk89!ʗP)a79kZmiŗ+)5 CC˭ _<!CiI`&ϋvz-  y > ~1޿RXt"u>GJՔ\I޶Ύ֔{ } ~i -XHٰzH@gZ`٬ٔ6ƌ}NѿyX!->4 "q`hDjC!u_\ RҎС{/վpĽP|Sc_\\+1j)|̰2箇O}1җnQq\3hJ]OXB2Z-,`3ywTb.8L ӅK- :_u\dekV]w 2zWW>0}؃[^}9^5QO}UiLp+IO7ͦ}t45)խBqMnrM])ɦnOW7^S YFEE˸&C@.7cwkaL79{ü./!}ȳH$kG 5c|jx?XJmm щ݄Sؾm7lz&60|烿qɂ_Ӄ]& *q䕎 1i9?3sfLz{`xX@ɳb%n}= mZӿUL~Lz.*'TYaxL*x#u[?#42UhvC· :XOrysS vΊ=&j892e*rҟ_嵑KCF!ur`ww)* r9q]~Jysp˲>Prr N ύCfjs9 \QWY Җ#xd׽o9޾4T"2ԃU􀳻h{]-8vZQdAr#Ewm- ^cJFP"Ii?/Œy#S~2ɰD5+`ȎQVٙ~AlܡSgmIMTXu`&eo`Vr[OP>9\=iusdi1P>*'0崛{ \|IR܋XILnW;A;}uT , @!L5_N !a^xk%-]LSϜ(o" Qa{"9jL4ra֍7p^Lr#6=9AaC7V#vFE+PDp%$[#:f2Ti@lz,̌PZ ƒ&U|&WVyʆ\v'HsD7ivmſOHH$ UB&ng< ʑʰu_V}13>յ(<<:‹<98u: >Bɤd`܅)NX"rsҩ KFn1sS~* YO>xsGf&+KgԹ9gmЩc% Lr~Ax[޳o!W2FT`?au)ߡE$2Hb Z(*(9V \p)%fvnՁQ^MI'@dW`عzLf!jZS&҅60L~ -a0wc,w)%kBY Z ܊֯cEd(J Έ__vR GW0+AJimk̾1 RoI4s[mh`6'tu+0Dkmfr;(L:enEYffĜL%X%e%,EkZI#XE?*fMEj&+͚+o*M.`Uy y]y$B{aqmd6Ҟ+2xM G!~$ϣw \|ѪmSլ(mVWLPJ_ {aD_X*0ODK#/z&$xь;bٝTGY`oGtSU˩"'۷gh$y6w,ΤH.U}|Up[?AǂbʩǞɡt)\Gyg>ջ}2ssݴG̽v+eO[.9*@ЬDL~^.5urjQ璘eYd_PI1Zettt![.Cρ#=G(1G3myH۲e nJ( QA(~?\ɼ*073Qv%vST #ҴrKLaұկ[." ĮH{&.(:`E}ыw-i8IƋ$zp{15tEVSOI]X_d9chyNEnj_}K]Z|nd-df'L9#OO8pE"Av'Cf^!:(]O'ӀFyݘ8q^ 3;7_4^hn=ߓ oD9{es83Gg~2ڬ`΍dYl z׺7=0~M ^4Mf'ust 1{$N΢4 Dx4TLpEC9[ػVZ}uHbZj<deqiMg])WD)%,.mC rDQ'nfT1!ǰyA2!P'>Y(qlVU3ʉ)p$L&r 0ʵ/l2tη? B[uC}ĕV9&MCLEHo2<+T#w=A5 }QhO̡`8< /YQ\u+xw]$ܖ,S9LZaDdV<erK/+*׃$ $^r-$:׉4C"RO"+ڕ\SnEe,$jwo/BӾ$nE구_s.ZWR6F (`U6`W^|RVp3q牴xs= ?;]|) :g ڿMPş$(}+025TmX]t _ITiaO(H2aJ=b)?t +I{AeS3̂-'X(Vm#\ pBĉL0l7}O™_@:^TSLdi*dQ){I;F,t6҄e-M:hn˅^7&ƔԈ3RFV7q3B Hkȋ$d>FN5=2D|C)Io ȵ-¨W eǷʛIT^PڐNkc( }fvjE5%cѸӧzcZ;NCqrerB&~iy}^ew-W*]@"NJ<uUHz?reJJ'_{}N'Ýd&V)fJR~N'lFx(nW뇩ؿ?/Y}+tf5ɫYю'&\~!O=YC|kLMMXmᆎ l߽ Yu%O_ ЂQTU6TqCBJ*l)kNPJ cn$b_ÍsKi7R5͵k9АƳJ_վdT ?9Y҂Uv"Ÿɬ <{~LP ?/ɋ^T_= 0M }?2V)R&L: S'?E q\4՚861Y=S4QC$"4_@e/I:l.6~:7Q?d<$|?}oI%~$uTϨ<Aj8Q~$3ƞNFI$^upp MHgy8Y#f}*Qy߀306ǃ?;y(q:9fO?-b-8Jlp^Xu$ F ߉o_]zگ#٥im05d5H>cɴbx:[Zw;Rd }(./X*ttӊKqAL2P݇ ^bøa&O2N4`%8ϋY^BP`";Qr ݰfeV碶O[a"Mg XML)Vԕe̎g|zıZ=ɓ$AoVSIyɝh $Ee 5e oV+WRzA+0DVP9.Yw&**˙Y(it;Ildz?ـ̩AE ̘q> VmWXߧ:lEsY3Bbz{9ߵ1SA 3(6ڲqS#/ j.,s,ٖ .NV3ZQV}_s_Zb+mwhIHL7!S##_CHWZoqIl&MbBY_i-3"z~|v( B77ڙ>d 뫄dyoP^:B,C^y-^8}t,u2^z*#Xo[ sX&ܿa>T iA+ ל9 E>OzrIgE-aY}Z#a@vV$cۋfW6`|jAݦ$ϴ w?SU0ij~\cw-?9ַ+l}! t(|>RiZՑ֊YD7 NdV`XT4GEqF"#&!-=zBrr@PB\Hҹ VSoYUWo{s,. ^ 8B4Ԓ ߃ RegrLY2I 8_Yh)g3]'nMnd $Hq\L84ALIfJ0# 29v²|I*DtWڎ$$%MY([2R 8pAT3n iN4}* ~ !PATՔ 4bЮ69*+ApQS烇2HʃvGM){V]*Gρj &d]>R+ko\лbDZ6+cRVN}pre ={6omei,)2j>.c J廒3+faLqؾybFbؔ(v{ahO,RTqU3{(ƉOZ0$[nƩS's V5'r~X]Bm1>: ')39pJOb5%E)#u=ڃC5-]럴h&W{ǀ؅U .%_BF5ρ&LoHp;" (O`~9rLgp>@R9~HXt;A?)W7h.#AJ_yM a(k~Xg9*/<]u_ʅUl6D]wYRAG!f$VU5z|GU*/=%G z!Jyk^>rzD7Ͳ*Ԏ-/#0}%*b_%]y #\/oo, jm+ZƭkǮ=_bڄ)?je^Y(gcGU6LO?nRm;EO Z2 %DCh(w!<>kL12l5OYIJz\u`KxOm#fGL2@IDAT Qbnb d!UOzB.hg&P;-HG1`Uۮ!Fiw}c/u  zzDs*O]vI!DK: e7^'S%`BՆ &g /I;6ã8?_+j|'ۓQbxC4?W_ R˩v֎dPR}2H5lkmOJL}/B@{HqbU3L!,DM-fL{6}?׼r)gB^m8ꨥUE5Ȥ,HUTQjH;%(p1@g!|`NF`hXkJ?ܳlabX7n|4;>*9){wnWF ,S^Tƺec6Si3L>wn=n{߄ OHcxwp\,H́OHJsR著9W&ͺk~oSCA#`" ߘ%qrf$Tl^Dᯅȩ-)n{1ڰ3Xs3+dz껭tO<#G+՟}ﻋD{dw߭e l8ޙ6s' z6$I~¤z%-p68P3^$ʂRI-C8[_--X3g7ަ/PHKhض>#KJL\ˋrHȤt#[*)2B(.@VF%QI>.8 KHB,i)>_rGzPɊ;OP7U|q$)ݳ~'gV1+eQMBd$H˽bFưX/UfH9+nnB(  &3"!z՗eN;̴N.at ]1&0s߽z9x/mVӜcK,|pEמ0)h~G̨q[w 0g/ `m>sϵ#2jl|C'Ѣe n[Gc5c8Im_΍Çӕ׾QbRth;NU GX٣KJ-e*Ƣ tU3[J%$dz1f"U)fPcqxoh*dR]؛ UuGv㖒 KHray%A^><0b47#(lmYSEe{0nHZ܁'|X"N7ѫ89<;нp0#M cC1vd縆E$K.%eۋ`UZmVsZt=1i~JHxaMw#xRF!&p4Cv9wuAga> ч^# ߡX vR9hk$ڮD3CЭmjgTٍQcG#DkmqGwF q>}A+)imՅ|vu yϧח2Cm_z3/Z  M?sd$&%c$.i)8]WL9!ϦmdH$yU$XDӵ&Kzh*($ k_2 P(''{wӁARק˭yؒHF8 h:V#kC-Y^Γx):dT@)ssن,cًu(Sy2ٮ$RUa!C^Y!,f"I Ǖd^+&cb|(i!)`J!#b߾]%P[cH-A0 rDV(meZ4upӂFqcL|RT7 <Zdv-rELBB3-z}zpwu;\9_Z&sd8?5Vh[ )?D'ʣڙBnm'%Z7nVvoLCh)24q55\X뭿{iʥ hר$wႛ{$ۂ︗ ׉l,l~nX(u4_hhCE. }9+L~OMJm(X "w,<ӏ!&Y&VmR,`ne*J8#A=՞?¤3'P5d"Vơpps 9yP_2Kvʬ3}ҶJ]}+44VeDij{.u |V7| ǏP+O[ NO}*yV+u[fK?t-R&|x)ӀsL}r5`|Y_WվD=K% YFW]쒵<~8׺e{ҤIT *+ש<^% ܷ\j|~. Ț.1}MqX>F2c'Sz~ 屛=y3VXװo?ūlGv%.Oɷ`E ⡇%lq7m8HKh_by7f挷7ϿaOh\XXV[/5w!p+h:WT6 = 9r</k2--FҙTƘ9o>}c9sU@Yfl$襗刉V70&eM\m]T*PzRfaN(f߂S|Y]ϵظ0+$r۶&EoI0Ģ++ 7N6/dQ NNRȵe%XZ28D/g0F?`UV~ v& :)- ¨VC": bߋ#YC&XIkhbo;%|@ ™@2 L{U0nVyO=S8uţsĬ' |&v-r ?D42diZILCݶزhLIGQ0*=ذ}tq|arXV;ӷր$%[݀y31-8ƞݴgsAT[ bwo%xr3_ s̛񿩥&"7lihhĺ5_cbب!_}%[}9{II۟ؕT:RQzìˆ _% ^{fUAVV! X@|ٮ ˆB2a5}=5QOIF)U'P~ iʡS]gϲMA' l{{3OSP+]5ĒOAVO2XIdHLJ,ohRy{z8X(Wc^ Hk#}j0pfd29ǐzNNxLʌmsN&g2aC'Q1<&`Q -o݅i"I9 o葉J{d3 ~E;4#(о$Lě+KO6VY+d BWK8eOyj:I?wP~3lnNs =],aKovZFyYxmFhա9ȋt]gsG9ʄHJmг!CLĤ2*XJipԕU۰gcǺUh+O 7q"FE :֎cg$>fih>rA9{yCDUtz-t)DPOet`9I43 YYٸ}TKNd_2| `K ?l4zRrL1=ٜX+aL!DC*N@4׻k77ؤQLgD}- KKԪK\Y&^mWbdK5x-eb+%=uٽ~#eQI)}r+2ǕwqTk]r <@-cT68x~ܲRtqB}X݄{֩\ CUKKK艶P<"ɄD'~YM9\EKjU=CQ/w)I1eT&Z5VٖXu;^k6_K6~nV |ZCnŴI3pY$*UUopYׯ?DCm-+$X*vSN;bˎLpMb%>}mPMS\9=r8FD % ÕmaW<^T 3CvUh|i++Kiwwގ&% f 9ڞ޸ 0v PfoYX\qW@ӴG c@H2p$,>t Y=x;vdOVLV4O?0I␐P> LT-=nsPFk`h=[8hE%nC嗶[aq/ v+ ,Xi1aATnb`'/sVa+nglb`CTA뛣͂͆0\EoYyDOH{^W|W󇯿طc C7% kj7J,G#yaaH 藏w&¶t-#9bO$MxIHKu$YŬ&$! }'} ?2dB@x A-t_<Գ`]eA=s)߳* n JRᄉDPbcb_g]ǾEOL~2߽ t<^G sqY6E+=pqu0_~Z#DrB,6 'aBT$4(:{`մ2Qd3".^ aD5DAAuB L2) q<.}P7{ !ԿP8 wq%+│7188t˲Jr&214@Ϧ8N?}$Dk2\d}Ɠ/bׅ=%aoo*?{UvO^I%$@{ bAUWUwUUPQT.B'BzHキ78@tgms{眿UE Y]6WUU}܅3A9rX2@+Aru뿵9I~J]MKė$9,"CY=CvFGbRttRr둧5u1Y Htc IK=g{j&#5&PU+捁ڳ|ڬcyMG35*.>'%v<Ρ'^FLf=0O+譔j q6>k-LRGֶqF:JVzHӕ 7KՑ a1Ǒ~$b/#J?1 `WC[j^@<) Q\^bj0cn-OLKJf{r-k]6ih w{ ӅA.lD>_ H@ٜYH B%)uHC(&zcʀɋ^:>*ehHxz󴒹*wN`۾C٫Ek9ݓv|1)~'fJf =D<2Vm!<ܳ:Vg0}b&*X%CV1Ī2WgGX.>R 8| dSy|.T5'y% W>̚5dJNGEX$|nL &Ӊ nή42=|ѳg{Y~#y̢cTu^mn'UOĩwTN?ZҾ۩O\Gln֛Ǘ_|Dr} \/2N~ N@&?N|;yi'?^9 VbKɢ!C)HE/ jV~_3keIbc G)zW-^&&=c@if#ɠ(#QH->BY}MVx!뢏eYd͔-ncAO@Ei'l8E<$%&k}}De/#̾~ CGMF흔o)I@4UVVa9Lƣ3eZˢlV->>ˁDzQIbCnEE G2 QӶn` ȖZ Ͽ!ڻ丣3=я}~zPvє'.$Ȣ5U&GK&L aL#*9I􁽻Ȯ`t:d7șdzJ#ΆdF6a/0"cFzػt ޅ&Z db)IʘcaFf6*Xd%QHg 5ds㳯b[o(଀ԆƦa׾&/w}GU3,69đRF9N{^v^d='QVPggf < k"*߉AYް4(/s2"XۇLL0Ymd`sg1Ӹpb;FJR.7dd_oE'I$JOAUƳ ]=^j+--?6raa(J>mȡgyavLf06'ihFBnh!QG.9|'⮥ H_!CB9ˆ11b?B A橓,_"*m.|3}P9^dZvV< ܴg6]Q').,bH8K@1b?*0 }mۯ/'A`'}(^Ţdp 00>,'YF1t;D2%h%לt8pnk#c&L2Y[zT1 E}kIHdvccPtdx0YyM!c{S)_~r{w}su#+_;,DN3)J7VVYC9b/wGp?,xTyv)hW,0mX9/YlVX}"'4y:@_,θa|Msg-(ےMQcȾao,Ajr>tA,y2+rb%;?iy)*<(^,|(|_}jj~L~ُęh#S^K&igk+Rio_3d QWJbEv|G*@Ztć=ξ|# }U,du$d|[$l0]P̙YesKVFdb˞8n aۑ SSs3i*B #)5Ye>ܴbJ!>% 3'2]DkyY= ".\oɨXGoW?iX̹<pXx{̑ŝ9)>!fȼx$1;vVTt|wNo朘c-Bqash} k?f%4Fڐf_QKp*>&Ms+GQ -NYdmRlJw /N=Kd% o߉=byf? ,f3pPT= &`gQy%=ќ+W4pĬ/U&ٙ]̋qla589 "xzّZqˋ 8 m+.2hdW!m7:9Jٛo 3…s9hDFE"?>TܩR p[8W/P@VW)*19ٮ둾hձߴZUm.<`:g 7#x{s!Ip6,3{غkpb{#͝dZtBdمŠ:2irimv&#RՈ?<ӣϘl[9E͑#T58P{ڠN ASI_-ؑ(<ϝr͆C-V@^ng&N^h<Ms) LÚbץfiEff)͒~>q ,1N=R$J6j+Zfւl9 0dsG;"O0W-GnXؾ(̥!=t_L[QGJAlQZipӆPƉw)#02@joo1glgA6-*(p BX8+;w'5I$؂سE0ÜJk 2pGjv/ pU')#+ ׸xB6V{7vCל[QFBIU+u)INزG>! ކ& 8E'c)HhHN=gĩj;JߋbPHMdX%qUŬg~4͑Iכ7~;͒'O<OGi]+&\fxZr[1yTXN" ==g9܃&M& /$g~VSYJY='px k_{lG u{s7]*2;2C9t$WĒ'M.aaf ,ʀ>@$Isr#ȹ .;0.CTT'ݿҤQny'*ZY>Wj(h$-*:e`*W45yb^ƭ ʂb64Raؑ|}homό>|k7α '2I p6nv܎8^d!yqӍ}h~66nS0iv,A>!6JaG&(&'r_YW7R罔e`rzHBjͧo>5q̒r(#iNUz&0%qLXFUkxT dR107ڬ\N1~.n'("M{sa* o<1t4!!5$*:XSXA-dX^В2iֵ\NY<4$?0upG»/)',MV(YA0߂a_X/$)b}\LbTúA+ʉ8W&dK/Y0zZxq*PdV$7?y7:U;zbKĩ3gƼI|е2*w? STTcu1W=10M~W=9Ov  ^>L yp#O =$wIT郤KEI Yʦk`gBVFC3.KmՕlFG FG  W~-5= L=wC& 2 pNV8y5j,s}v'/1ޡwyeFRO)'r߃1dZV[n-tM?U(y)Xk55Jٕ0G xïPgbdd ;/ 6^~ee kO>Iq}y #L9e*I~ReR&՚x{eWXJJ\!o*?+Wx#hA'6AaJ^l=3Sr׳G3Bz԰xXq&Sp_L\. _˙W4MeI Q_N7S Zkaɸcmx罷GlދגvQM44CxH :ښޕɑ=Z+Fv.Ŝ/19tR߆d԰ ʇKsL9vdd]>hiUN ^oͫ*c{;|G_6UYu;P(KM;}oRmU3R-:`>SmG%i!۔e#Y`yEmq}/5ov"a+Ac]}'1ށܲf;1Z0[HGcc-I>uY*HdچI˞B׫61XaG6 |ϔݸ'W!:^pr7Adim pCM]tV$Ĭ$󣬻љw1&t]JЖtG_إgi[[(IpU;Z5R8@a?#hL_^bA61&v`RZncnRݮSo!\ Fi(ߐQFLJޘw' S)g'|S3yZVmg gd0Jbqr`e?x-\L'][ӊ&d[/ !}&U%cG_7ÓڴiyO0T=Sq2e~ITZM0Lafכ)nr|Ou[wkY uW߾[}\-QA}1ڱ ;""#9 rJP+x_y:-@IDAT휨ZIlCd-r\A^:e\Zז\|OERJ+_0,zdgTVIfi( #ΞH9(W6~E tJ~O,_Bܺ^YYYUGZ$iC(>&Mq91ɾ(~W%Д sc[jG,tY?b%I91|[z} &ϘU{G*זVe7F )b=>O#;Q9i5/O?XZZ:LŒ~N͞Ay,FO2n$p-oބ#ٛ{JEJ (jZa|%3 |^]Qo;iGaoIsq";6o3M|b!ީ;yh@`}W0sՒ 7BNb]ϙAU._}DuKOO l m __5 ux%`^(|p3ӽ%0fى &n!QWOssO>Eϵ|x:Y.&:db塤vfh  0Z a־mJ&XAmw1oغ44 DDV5{wŘqH ZSp܄1L *кh_=l ̌J34E% SyƂzPBfw׵aH_͌*4;#߻NtG}}\'&M)N gǰʍ*F1>u@!Yc'fb<gxٷ,&Y|ӏ [wt<]z/8//V\xu 2ȱ {Y8.L F"5f&Ba&/m3ŝfO 6m&hE_=oezJYЧ,XW) x_陘N` ;3?C߹k }jd?9;}f9S">|2q$S^@,h\B#ȩ/Td{0mb0y"RRREmqRXGaJ6%LkOW[C-}9{,hא M@ LKC (f,p,Ͼ}UNҷ;G-#J0~wٷ,ְ=r%{T dhMIIÏdaW[%3z%g;А";qh6esj7c{A,nr1c T* 7^k^k5'yM;~&( ИmmJږvՇ$'s0ɶ}5~K2\/]˶}w𜼄;oeWx/+UY}?h(;cnTK3(;ATQQīz~G47`,+u(ȜUԒ,K⎜QSeq~~diϘ{K}C+7!-y+n+#A&ZPLq YdR-GQFuTh4AS ZjqBnpܩc(UϢQ3hՕmf16D9et7lZ%׹v-jo:֥zH_ch6B ^|8gmUBh"-1ȘX/.f*9Yd>cH`p?6Y"jd2/2d~a!q6Dy>1|x>BE7؂16o=*ZEVzG)˧r3&P(;'Y!Eh-z]6YSn~kr/ aQ/G1f2ر,(E:lP(t6d!7@;*ְɋp )WOo -. s|lcАz={]X2k<4,53#FQU4FD 9J ބ,ID dm-\/G't^FkU>|wӵY+.|CM-z6ʾCb;[TYKKJY[yo"8yD sT Cd}\oQpwNSK> IȚ JV<ȳ2ɤNt3hLAGP2)TyB\e( fojwFy |;  I hG_'Ke- zp4S~8'0;D. oణILxo$dTPJNHJC4Ρ3JgZMY_;NaR33v Ky[< @H{cwub#4eM`evbDDD̹qlEqE QKYǓHyc&سu8r&ҟΘQl,m!ѯ5,wlja(Qp݄8WNzO ξ 3 v@uqW%v.r3$lSРk`_La2ŁK͉mٺ^8GK(x0)Mހt+0ȚEٸ3'N B ꊊ(Ul$B&B衣MUdeOqt} &sA?;kHHGSrT{-wk)]}'|\OC`ߒJq jN &ׯZ!@7S8>x{Ӭ^G1&99ؠ('CYoi`&Z^[C!b^Iw'6cथ" 7n8sݫcT/?o]E9iX@uSWf{ۧ2Zz:2J#sGKD\ @/O* &|_ ?89Z?;7Il"c O'y`biOvˆIq.>X&c"5Z`@fRCW){/ᾇO3ƍZ[ Jg) $ybIi쯌xm隴ȹJvYP5}׼1N8CP&U+lߺE(?}x9ǮIcךr& A ;$X#o6;b\ɪCFf TsJw!a<qeǍlJKE)V0导~~U|vĝ8k'7C:}Guz<Ǐ `+ VmUOF=2V]&$\@eai@҃.صcY娫)qz_eq b_dO>ul[Zak k4) `QK! 4ZI2u:N؍g?{)wߧm OK+} ڲarFYYr=kStzɲ-AMi&Ɓ,*S=:ʽ\ 8!}t5M_V,`FeGv &_8w j:wݪ(o;>c8j2Мp 47?YYHlH Y56Щ/ކO￳nc4]oHi,~" Y䏔l`)U7ƈjEHi9kk謜ޖh} ggZ$/:/Xe~۶cޗ~c"2Fk1G2P/FÅsfRh9GPCeU5nf~7nn&i2f0)/‚2[+1nL;j }|.115o!pȢlmq^d_Y>3˜חe(*IEnYd@;}.U% o9ni7X*ytWR\,++>T$p^"~t+ǡ]rב.dBZՖv+qC^C2ħ&NC8&W1~M_o:+W8|xa2ߺu!¥_ϛF/_B4=}@?ָ񔵾=|cbY͘KۨJT+g ått 6') Cḻ")_>ODe0ʶ;+Wދ)O'1Gp˕j3gNcDj)܉ף ooAr+PGZZ:}m݁oގG7WՁ9?+Taq_ ɧAˍfޘYw\v Oص#͐VKݷ (/F^[d3̻i==)+O\VTQTX՘d>G,|/eNy>9DZ=|ݤ\Ds:FF[1x4f=|kƒ#C[LsCLl"1Eb$" )Ps׻,׹?[X=u\7,)c߲.7z TT?l[=G{&qM&[*u\FnG=7OHJ@r5J6Zst/zanv9WbMzupA" U9ٗ,:U'>&juS޿2vݙUYY=yG^ 蝿3+ jݺv3+ؚka+%YwW?Y_W-U_1P esu͏ӻͺi(OX5:bv?LZ<4ji߇Iӓ %AbdTb3Xr &Ȇ 9o]Ԭ85[.1`rE,xsP Ȉc'qFsa-q7AY^TQy==ZBS2euϡЋɖnT{S*_A,XD.^I ~`\O?40@iE`EvJ|UƎǕ lrR5dљp[)٘ N? ӃQ]s蓏Ql[IX0XoQ fgn7{i5liBϞ6y,"`t_Z`=RDkdDUWf7Mچ܊MƥX:b"gM`U&ёQb_|^XSv1jH"~]~pI֓Zɏ1f`=]cǏVwWWw峇{PI<Ԗwy؏H{z >0}~ո}Wm$]р0'a͸.K4x.cc0KJ=N\]^g[ѽi_zL܆V6LjU@[aJg]4̂2Lk'3!i>~,rspd1%C vn߆cOAbIVx+ɿ$ :lkYY *+WJ3pyyz=d8|0?Ti=-gmc{*x:[+ Ҽr$'a;γxyWX(_RR),ܲs ڡ$iN ,,`";wvt/9 Hfs,Ońx\>fpB9_[~HB=lٳ 5#S+1,E rO8QWX95 oO__T׷c(jd =<\ٱP/R47M u EƤ0Dx3- ->O+FBV1]0n8 9L+6u?ֳ-%ྕw5wO˜&1sY;-MJ6-6n?l_~pt|-O>eܕyH:X%Iu5L7,tлQ>k Y,}ɜyٰ!+.^w0wzuG|N>  ˔Xke˖w>|E)J w>x>| k<:߿^aQ.;E΁?L}pɧ/G4䜾f-æom)<>,F'jZCM58>('#\WgasDWLDVgAa ?5U5j0ϚGLXUU Wk::L0:* dַ2GPF9ys|)60PӎOF$v< rn'0|x$eAtbB=-Y 81At[+Ku-G>`dEۤ|d!ʂTi&:f1ԔR@6*:^\HDZC?_7Wr1S`FP튥 rpuEG`*{cЮ "‚86w^VY&ڶm+h#`& ɅىX0bI,bmI1Q`jT+"w}KV6!=d"=NO ߽ڌ45/(9GCЪ?&H/S&E#ɏ>)& __JϵZ7^|~,_sfB&gÌN |ded$`3*Q4UNk,ɺ ϴCXt݁M!(T ud[ҏwoүKL*xUB~CK>Q) *ȳ=z#ug=w/MO&z\~%x?%dZqfe }zަpr Ο;E5m( J2\QYz^?'X`tOܻ|%? d$FF2CMI<j1!BX7;9C,ɂ՗EQXkwSCo7=go}0elɶ_ofz֧S1ޛ1[\S(g. pnN(dfSd;줠c[԰_f pR `={*@ ?<(5|a2yZ*1갅.JJH)9a݆D<2OcOMJDڥ| M9.x}\Q~4EmT(uGM-ۂr|(0h;rAeRz"5l\ZK g( ub+Őg^gȗv*4"WXe{{VrvIӮvjs%?iOY-j=޶1qyz7چ<9L2wd=u U;o0UhpU`1lwјx;̿M$$пUGGcj;#Q ) "!]kR;bJ#U.UAǓU=ʲvV8 ccbjd]ɪNOO?O S9w'~gKPPv~Z҃^i =48*LUQ.L eX/mj"!8W_;S;I{yL<sweMO:;o NtssCpW}L.!L&$]KX ½hdh5Xo6et$k+";ahkAR1@d4Pa"lJ<8 qCs Ktx#l:?}e:Rd2 L0a , =f 7dg'J8('xa߀Y?u_Mr×2!J3 ۇ Q#HzTW`i[ye,X`'_>Ho:TO?}Nt8V15ÈEAQx2YQQH'!EUU]O_l8Oody\94kּY%Ksay;49RN^c~yXtQmO> {Ba :z)e-/fܠQQ^vx qA z:7ǪAK}_oiTk  d5'Dו`TT L8F:ڗiwLZyյd|}\?maT[o&gTU>{_kDʟYZm/m+  j\iE)/|G,?{2*Y )jii/>OP}d!ܾ#䡶V2(){b-5d$uĨ)+'[ <$[[3os}k@{6mVaڳo4И(9_}|xXLf$POI+qL~Gƥxq:9D]h'ɘ-? Gczy^6V,sR[Ν?yKYc(2>K\>sA%=1R̦Ϯ>YT=e.j+KJz`2MM)Y}q/2L=^̯|Qlv_c҄iw^{9^YUw**e2\6062"!;"Tߑ OmfL\{_t1'. ӣ?b?vTbYӫ]ÂAyKKf}ISf^0>W}"/0d,BFfd#;r9 bSNd #}4+Vǟ$hSԳVJYQA5DE^ii{?r>ZT ')iEjREvojj1sttm$8<|tPdmypJL:fPbb2Z8owxSs;<]e*+5-_Ƹo;y,9'OG|~?*_Va;LJJɧv}x}KN 'ۖ}e]y#=)oa_ƒ+W*J2wҁU#Ǡ{|E)hm]T5&jN.ޞT3e>/.ϸ#2"W-+ag@s݅ӟ؉Sx>E3\6N~%Qagq1M\V~stnӱR[H_-ɣ3s'UfՀlO*9U )VGU7,cyOM3KV́oV 9[v/.:0;j؂d:s>Z߾!HmbwzGs5c$zfs v\~s+<vV]|dڀ( rˮ*tJox ;Ejóg kIn\V,Ĺyz_ɧ܅x)VQ@ळ'p".p (.$lyˆlf{cuUKIB:|Qda\j0ko !"˘P^Z, 7U)d2e#/23.`9'߃} iGEYN,gDu1xf8s.>~X:)7a&#!9{Ny6һ%}\B62{#:r"NИT.1 gh_G0MS@~,qF<մJ AhԈV>g7Z#k{#Q@Kxmzn)E$jEz[GUNVzpX8%V1.=Y{:+<~IS&cYJ܀2w-JwOur3J^ݗbG \]IMKtZj&=4^6H _@kr LA:,=%^Y!TC2ǗUd0-EMU)*(`oCpZv%[m6J嚆 /o&#@Hm2Prq\S&~ UصAu@9B:<ÔB`K\ּ߬$.`>+D_Yn#p}N[(wPL qT )Q *uY_ S񔠳cp6xu4ZamːE':͜71݆cŬl\HΆ9+JӁl}O M1dzd5"jd@omY3y8X@6HzFH~6>s~B8>QLs`BHAvNyrT~ovu,%e(BP,e ܽPˉHɦ%8w5bfMGom!xԩxg0c"Z0QVwN][/V"-`4$)$@ ޾ؒQЩ.uW{̫{::dyz=CXT*A%PqEȑVݫ]{;t&Xl@G?+h n蚯ɜ:~30/**D!R>0$3-;ݶR8CF՝wc+ ʬl+Vf`OIֽI3^ER؈ɸ6&*MD+JJ1;r8r>Vm2>Jw&@.b(ǂMYdsf- `L7joK^/?*",b]k掎UuE~N`2X`ҙZ⇣~OOH;-VsC?cǜrI/56|'͔dA1'0AC+LVu'PyiOZcC ')w 9Q}{zRH&_ewcB)m津L7E@ \UVuXϘv,:;|+2:2f ˣ7zۛj`G֝)GK0uG V^u;d" KHMlOu?;]c *%1:o~7c0% p (ԹPRD,4oX_ iu]3N!sL7`}}OoV<1}pUe;y*o& 1YlXaDe;HfP6#ZCAX밃 @9ix>UOiwdQF\/Xo1=i*/#|To9zܴ3VyԜ|lpXeM@V2Q/GL}5S[1 㣔LVNӒÜ&Nd;J.&-WeNop9윯t.!qeH{|#8A[ XY:<ؒk߲gr CT'nӳ1s׈Cڙ|ȚEpʒJ@Eu^XTuJ^~eooץ 5Y3wf nЭrqq35ӧ>Îa:҄;#vE`|Y#עi$ZtW%n|NkQDj GN\{w$?po˙knA?N6ay5,xW9ތ8p/cUשּׁl~vg/΅)̬ jLPlmhk)X9ry;(5-n8{#cPȶ͆4BhXҙ= `Ӹc# 5̺hT?'9ӰD; rƨ;GN5I1`t^}86(3&"x]M7FyB?o5}-WTN K,#~ak$5dFT0Df2(V9du!Ott?} VGfމI8jIeUz~ڻo»(>L0TWH{Fe3'/3\GۅȈpw>*$DM2Z } ^Z(ae([=5_dNJOHY9w,8a-g֨ ȤF \^~l_T*@ 3=c VNdBRa5vT'}^."#cQeQ1:i'â ^UTRbJ1S7WUSZ-nЏFWi'ա:.YiϺ'-Ր_1|Oٯ|Ud":v|0o-BMSTҦLFP|T_q3޿-\9#pͺdAKS- 9vZgꥋIf$ofws쵘u- *MH KG'!n6OY`=gS1ǙQQ4!;j̙s:Fm,/eǁ*jiw7R/,,!}1W n~;zcK93YZ`u#HYhw)Q^7 ~7@IDAT\PZ̠qWwʡM!:xzU)T[un KOdl%ta&x_7VNʹuH,\ ޵/1ʲC./[}DzytvU;aZSHq>}]5 h#+gxDDѱA=zj!Ҧqaմnj:][AY[D:ItKFg]dF礠pJ2!Antumٞ…þZUout0"9˯p]`[b7P<hb3bZ2R'^ev9p(FGrj3"0j$L:/Twϔ*Nn+ouPd>3=YZ&fy%m#6U`fM2OHw x*2Ig\ie.s|i'ͤ*zs6YHڲ͔m}4 Ӧ_dԷ?.$U( B#؋rB9zڐJ$.vނտ$_d}H FBΡ:p1{jظa栶11<ҟ7.soHMڝpYYT~+on ?Ϩ,/ |NE4+j/2(ً:70xmaVqc+)915e~'N14̢*@#}VdP`vi )g h/]9VHkLOUWy>^? 7>Q ͬq[k4=<ɲs1xÕp:?kcιBqq zfNqҞ+޿v I&PP6ķ?d R¯q3`i716Os٤Ŝ „oaAG L2='NG=W-9 ;׾dvQ,*kRqͳY{/g~kǜW~sXO iSV3Rߚ̌4z;Q1nw.\B=ҏK.Nf'kSkDB2qLq{H~_J?i먉/y\PwQ9> ̭J,\?DIH_5\;#wr0ZV6Zju|f *[-leP7~ 3lN؈>tG&}x4G֎Վ͞ :_d#3L,p>JÜio'n /AB_6uC}Jq *ȾOy2 xzS“s"" EVQX"-~v|hHB>jqm\su~s(A.?jЃЌK*Py.ȳ.es|2K;z<.7Ϳt^82C%/]J] Ժ=[Rw=ne0I?W#ԇoH$7 7-cGZtN\1ROYp o#E *N.Jf-IrGve,u$h-XO/rp>2VۓzE>q,։TJ|u&]C]Oe?<k9?CWu}NVXqgjw^#՟XGϿR\0ҷ#wcѯڈ~C1;_(Z}H:ڌbdn qie܃$F_W)&[ER z*,yHdVO'3Z1:ڃ:[ɏP5z?fc x & )xaGQN,x.M0%- :+HYb\\3u ?Y7`O![d4SO>?GC.oFk|7|}ZHBXɬe'L]°0aTo  ش[db_}@:HE2&?sCS0SC2mWG`__xqI\1,YH Ǧ{i0BD ,q)%'ө?nЗȚCg7`KY×q#_`(±.'c~Zn5բ t RI3p' j?/S( 9N$()%n n[P^\H*@ҞMH9@M ޚ@TH x/:ͤb -)|ԹʫԪ}_ުu8XYt/8s{|v".U-{:oE[f&&ņ;џ m/pXbB>Z`ڊZYwa/rO:^Iw=l5C3a!~{9) aaec6>0 \^KZ<:f.~>ܼ6qoGP:jc kQn:&\ORf_$lA8QYR #NעR}| y8P^Gq6'9jxq!ɀ@Ҽ׹Wm~62[:_ JQv*j~ݼba_`)~AbU 8&K()'1|؈IhN X_J!3*)3m0W9$t12-dE}j-*Hy#"=,dvkLXo.lj ŎB^YwVm/9a_AARw3^H(:TٴVJݿ6Ҕ3E9htG]l)v C؂t|W 2rا {[ZW*ܽ[54ҧNm5Pc29=8AvL ?#f9cAkfD@P ҳgtz=oM](~(Y/ jn@~ b=x{H<سgkk/?3nfl!: zllm`BT3~e9~ w:C \nVs:IwLN9MAVrXV""T,wކ~XCq:9eɸifݟ}'wEm&}֑9}׼:_(r՗'vK%jthj[Mɜg_,z+0g$\Ӭ 5J5ûYWv(>6b; ƕW۵R|6e+;:,CC)7ѯo[f!=$n>IL։D2m?-]WQP`}S?awlܛ/ϼT]5E"x,;ʡh~N?wȺUh."Kq9;ɔ`pdW+rz 59\_[O~8E 54ԇ\$(x Z+ٻVbtQ,v@L2x) 8I\*`$U9HŠ*4 CG[2,Ãa^\q24?gC1%ؙ֓>"Bof2p*vUؙX/,GG6n<)ق0i a`1]o*σYZQC6Ld&C#9mnE| P|j3<7̸R$ڀ#NFUmRV)o3o 'nU7uz!EGkg,L|..?myW?m];iӽ'݇m^_݋<7ԼxB-YX\DGᖙR|<..QC*-Б(|;A~KDPZH$P *Ƈ-2\D<2[[zJ\OU,VFE@V3 .1$ M}-Fa0pvfF`WԊZn^ްdւlZ]8SB~;)ZrnrwlŤebm B-bȩ)@vmtQVL*)4ܮz:zٜ83;7g-ɥ qtz?p7iFj55Jlpt CQfčh8a#ӓmڔ ݻ ǩƨ~Yq5/6"Teh61nZJm">}P|llZ Ԇ@BcBe F7/)jlN`"j=C*?$P֬ l:A#GL K38"lhKO]ZL0 ۗ`+0*ٙNf (;Ra\Ce~0w H%6oރ&cwV+)ݲml7QxH1s:n:O+sCfGe Έ/)#YHwB=Q)$y|?F1ZJ:Y"d瞽Xniq畫I 遜tnN% cP+ޖ1WR~ݔ X2;#^heɽ(ї'Hь̄˼/F}}Wσ!GHFy0㩡:f((O(W2lmm{%.*ǖ_γ|uB`bةPۚ3멃A;ei:(3/yw3w9~'F6JXJ f\v9NDi2N28;9(6D9V;„Ç 11OS]|OuP٤@-?z9g5ֆTm:_h豘Et䙿22VSAa.G O? ό8FʎKlڰIS9TxA?U9 #GƬYvWq#* 2)I]%w03i[I,ߋcXq+vyS:3Z2ea73f99{2k3N ,t+Iijn'Uھ}d-`fדƊq `ҝץxFi$0![K/KCŏjk~5䝠&dF^}~;i]4'k}21`BŷcP)hɆZP7:WD((gFg\ld:I{9lH,|Y<4{6,,p3D>^{' ǓΆ3̥㒔nKYp o.Ya-,N޸!.AtA?`fk;cS]qA6>yX,Ggftu1K6vn1~f^32`ZH,f /*߫ݶYX(#ܳw?bGULU?| N"z@=j-ÒX|~=q*$U&LyNP[F-ĎX'xߥl*ϡ[U28VRKרHzxHpNfu{WPd:δ[pp3~l [J|f yS NJo)+.mXh%Udcذ8^U\OHئQ>/͑s$yō޼smHmx(|']w pV¬%KRFsN=Sk+1ٌ}C(s8r;M[,Q/XW}O@1և ŧe1a5q!J|_ G'>@K:j[⽹o1̆}A"L:Y^&)g3R+p4QJ*:O=K {h!Z,)"h>‚H+6$`Dl(_:QTRn\W<*9TD(;W23Аݳ\\PdfNIoFFfm)DG>{u#鈑écR3!/T9 -'4cֆ;6Y%)8Q#*9;W<$u/ɜbT;2ӯ,ŔP}ܧצ zf3/>4o'9v><)5uפyHtU-a#1yӊ߳yڊ,_?jзf_uL*61Y`KacD]rM#evl;>ed8ONӲ M}"s嚊4wv>WӲY)~@$C=: SoN,[|&(6 eى֧ʥI;J;z˾ATX"9'-0GJ^5>{l߇;FI ^wgy' t̸ M|D~9YEd #fX6w&kĤf!vp{ڻBsTOh(tϓXy?#gܦgM+~e+qŎ~`xWDI3Ø0z-.gdI:[fD3ӊUʬg>NqFNqbO=iPrVi_:YboR:=\;#&a/f\<$ 7R^Icou"oС2d {Cyz~<\n37xu_h~K)˒7r4H.t4ԩ=LjfnZx?J諏^s4t62×/73/7APB֕?YKmF ~%ԩϪ?o㼇f P+L+Y]>tٺ1o]ymfX$&N- hji;rٖ7vdoA uu1RM5 xxi~uo_XH{&eHM<r6K YoR֝ ;Io쥴!hs n~i'S7~ }' ~%È~ X̘Ilz.?!t%ؒ75\ TZ+NeaѢŤKm2R w"އԂ#=`f W{KjR$muw?}k9nڄm&Zy2>/ BP\]Q#fBUdn(4pϟ yy)sGtI|Nm&ٷ]r9|Vg Q"X#`E(݆rw*ct&뀘FS[ %uJ89c`4εdc;JJZr^I=SVcꖯZ ?v"8q Eup_Ufa|Vf & O͞}-C)} G>R]l\{O_`Ҹ!xG8?NxG4VߵWE،A[+6ԓ{fi2᮫ltɜsO>|͟N$DU \S0ሊ YfR(sxS;_k,f , sS^ڹ%;O?LelKaA[ȣȀpĀQӶv)>T \뼏W*n234 nbw%.Ҡ;= 2#A9_e 'Ǫ[$ _*=RڋAª4~`ڈ8$uerjYðIʩ01K΍wchtv'gV6 CZqԒ~^8~.4)o2L%!ff}^zŘt4䑒|-Xg]bp@EzvdE-\|-28H0Y7G;f9N4#[:̚oXC,hc )?[ԅ.m&%#zLCeq&G֕55𙐠 S^il+ 7y;cH74;0އ,S`Xd;C "c;mk6Au`>%,Y  ㍼C)0ep;X`jjk>d2u'ʶ?[QY0UeKJsl?ZIb7WdҴ3@%U_ u+nto9|5uO|i.}oplw:aEMKgBCc0CAw,WĨR1vgǗ.ĺRu-ȧ^%9uWMgwcI!qu*|A(f@2im=7٧ ~9$Zq7ds6?h' ,N#CfO/hUmF=KPe\u+Fj<KBL*dƝy`]w8e$z.+%v謼zNlBâF1@u _>Cdd~cmV&mk@cd #Fvݓ@:ֆFg3#,F䬉HjŦBNZnђ{Y((m5_G dZ0V|DUL%&`5 $]\+#۩1[PıK`Ȟ^>~\{wGu$+/ 5$o_;0NXQGgJAxLFd Z,^sjOjIï)ǁΈneևw @Cdb4ytHR91UXx)Dʎw`` JJJp{la;7͚Cw2NrQL|80`vG3>p7mwފ 9ݞb? ZVgDqlh*VndFMژ6շ'29P_B˸MD 8T?r 6edY]9\N=/ml+ |䣊L庿%X^]CΕuw~nO>DMM>q+~Pcc1zf"G$,*~I)Neį f̶db3#-nJ8V̙tM'= ujE$>]Q^؞=;ʫ\P{Iݟ|4)3Τw|Ckk+ 0O̴̾\ x1}1{*%x#}QC4@VXaӾSo\#fP ^`MJmA'&fY`5t"%z<~351㗼ܼV9L^/XUU2X *m1rs)h|qLFcbK>m{`XΣO>eVV$ލVa؝TX6vX;4#ꞝX?#ܾG,oYO]iػg7r3m}V$ki|%?jje9w`. ":VrNWxzι. e*4p`,OxZfrJyy8k^.D㱩9gq~̚:}AkdS^@Cs#"K罇7l~-9>fƾuG̔^AdY8!G,&2f^2)=cTuW 0ZgwP/OaO*/Z\:\m}RK;̞96{iDm+莗W,Y'}"%h2|(n/^ybuAKI؄h"˾D˱6M;r36n^[Vcī&-}]JD5{+RRPʌ#ɜPپj)vH@1 t;̎|V$3aPD%ƦjX3@:̖lRfrM&Pl}ks^s-JmQ_]E)f[aQXswdȁw ˾Be 5=v~x㖻;=#ޠhF (:Bugd!.7zs۱n(~bFz 3aZ :\%x٠a˱}z[0aMl%& *l`5(i¦1nXWj9w6ÞVkr/ܑlѣ {}AΩisv89qU+ǟ")1oPMFA w:!'Ћy;f_PWG=XtmUU1[0;?X!ȁgY×7 Gvdׁ &a8^nz%Vs^.e-8qO;Ind\JNOaGCM-13WqDzIt/˸.9/M @*}0%U6w?-?{at@-,6vaD`&H8o0X{LVmȬAL? * : @7@  CEE~ 2C36 1p`X ?2!ԝf3[O{{tfɆsijZdž %1ZJ 3Np}k6dzX# r>,E(F'{#)KE`{ȔWVZ`YԽZ]g|WQ-9{?c dkS#qZ6vxsU7zՆ6A/"AeL>>Vhzu`-mb1Ф*btLbhj {}oeȱLSz\,9Y"5^YQs`:mk^SB x3YQ(rFEwJa_Zj7TN'aw`;+O14K3/afXךZhx# ܃OX=v1d6?߸WaB{+:25-9 ]3$S.`L{p)Ŝ0f k͖kVS}K? aGRvն 6 J1go*23rgKuEKOGJ?y"~E37y XuAVg4;WnFr9>܏ö nߠm{vlcȸપR7cGY㭴ϳ54R>X)iT-зv)*ͨ@O~}Ͽ% Ǭ?B7xcnǖA+p%*l @IDATܳ 6uR|~j˒/Lj1~fc[LW)Yf2a7- T%T㤯"6teΛ\S})oRO`_}K)꘢yS1ǧ1;:q"\q34]s뮜<}毢dO?Klgjnd?2U^غc?<$Ó|J8tLZ7Aqdɢ~\JO>]gg8[ vNwKt9̠2Tcw+cOϯH\KغfّHe n~i Lu3n$ d^4a̾="cSV'OGeV6I"Hlkoq3bG%Eکv8a:FVN8S kFG7`Z9'u~WyWs=Un@%i7 2h, kRuQM"DiY%8{F0f^&LD 8 wA*J;X/|3bQҢ!5k m2atvR0"_yEldO9L`:R v6yWaΫox c; <38LC땬V*YZ;>/0bC)jrye@c˗-~j=~X8am p2 i(}^O o=jj({o53tߖ5D 'w%~XL&}}Y[D 6tU~pt%3 K82 !)Bl^gH@:FZ6(V$vщTlXYU4OC㺙7z:Dq)Vk ;xhjlcʙA@3mg{g%Pj:N˩-y6\njk)8fN CXҡZ@mKK;s2n}2FaPr9a uPٯ\.*=Vu)Gu*8F;Ál+M&/ CGqe9H\{4, GnET7jmA GG7Ʈ&6)2Ls=K3 Hʜw(s'Y%vF&vG`9k88tt(pscnYvd"V[mn6yub >76-b e^]CN~/*z!O<|nо}5:?XΌAΆT> *c;oj&0 u;\Wd¼f62ep,*}뉒fU[EV _{V,Z@[M?\^B]p2G"eyjHm{g͠t_L&1{bi܇+GQZgO:~LF d {f\koE?'kr%N:_֬FdOD \W1(5X+.*!*&#L2\ l{Ocz-)5I'31x`u`ݽ ZS>^pQ3V?뻟ǙAFJa&%<S8ڏe}xX?֖uK!coʼns fJhmm87ީl&}<%Ҧ >̋~V9߇N9ҧJ{o툻;PW; gX{;|^'Di+ CSNlzJv~~C܋C=g9_@+ek$E WKHxJ/cڱDi^y77Iw=o^ۮy Rd?r-,&+gނG}@;{ p6%0Cg'OjZ1#54ȸd]¹_y|FA4Np_x%tT,R}l# qN>hM[ہ+1AT ^ƱG`$T,N#+{Z 0ge5 9)Oaګ Cho';PIٰgo+~2DOSb s[-b+w^ @ws/'~;H9~\Bx`}4Bu[GwPoMǭ1n{lLA]oՁU) Q^yi1eyJKË/, 5QdG(z$DjJ*#1o-_88E0PlXQjU#Phe} ѐ8e[cQh1Ltۑĸ LBҀh즆MQGwo]tr,eFgy^v6Ֆu#SW0Q);܊uBj&Fv $A#3{B5'̄  ox>DЯWY[ X1C3X22=㨣 i)!d=:*ĐaA5ێqC yCF[Y 62)zG+mK3:騑Rw$Yg0L،p{;f]e=E7p!NfkX!ÙFWxl8V)Y1H#NzFOD+'D'1ڈ6f&rR'MFGљFmu'YFi FPmk-T#L|(Ga:A뮻 o3ꮎ 58!"P&tjiiWhU.deF:3SQ@J:n?3zww#F,PKBK}ڙәNuBK HqZ$bDHp:y?{Z頑O w>\TBԓ&Αu[,qf5qh 0woM-d"u)rX ܳGƸyΚ\'&{+HNhtY/ft+k!bFj,+QkA38x + A=iLkb3UsMt[ `M%w˨Ĭi啶gs/, #Fu2]xbj{v禩DkT[YۈB?g+a;I Jz2Mϼ2v*$)+N'\0\n@Vi.d1τaox2N)'0v+0gJBgLa2bkϿ9'2"lړudCQI~YbdbM})[P5dH:#ML(aӉ) [@\tnR TU{=/E:I?V́Q#47V]gGX<E!:6`?~<3sUE+"A^ ' $92&@̄  VdRJ[ @3)mK H\ ?.;.|t=-WHf+]6I@e}C+Lg2% g `r^|KM_XlT KƗgR^Uϧ<},f9 :/~*8p4>6UwXO]Nj`^`rLvw_7} F{VŬ*ͧˤG ɳТ՚{1Md.'%w dU"J[M]V~;-ց_# LQ]JH&:`HAbLZ[7%uMG+$Oʶߙtgr?E:dDREC7 }3 O>qc+H YHَi?L N[3&^3Q.,j 0[ YyDo -7RҲ] & a)%l[Lg XK -mU\qxo=S S ],`up8z& W/2 ???Cckj:::dpp!-=֌#fbOŗ_S' "#6lҒӑ{Rޟ>PoeB|c&(|Ldp"ux^_gOU~E3G)j ;U~ݮ~].plU.??{ *hٷ~UJ1$d@6u ??n2ʘMuT@$̚<1t\v1OMA<.zJ$*$<:u LcJOG~Ex' j3^EyԜw 0y?uFrj"Dž[ﵾ6$ ơ>ʠ#w>x;v+&[XTB{"tA詅ZI>W~u#ȏT;K0Ԙ:'RC0K}j #`5`F*FG'71nk檾LF)鬺Ӥ^GVdpBH:vDmlP_8}O Z3KX^= ү5Rʘyf<`Q\7^W#A'D >ؿz!;7/Ncb *cׂ"߁714~LOUo> ޝ@&ЮHDIGD;Oo80XxJp%rqC {1vh_6 AhH}=[^N,fsk٤^kұjU*E-2,m;%(bV0m!H{YԒ|ʸJ[z֔]j~(%\m+i>_bJL0Ǖ䞇碀 r@mi,gݥT^nԶg5 :M`=|t/,ߢTO7Ro_apJ 25^'dumjzV%Ns}Vƛ z`>nSKQ }:||;pյUp&Tu#Z=;uS;z ]^ܐXؔTw1)okQqw45};bTA6&?g.i[2C%I`Bk=wܭ )wG2 ޴ˊkX`ff~IU$DICX}-R0aUL<ȖdďUlޘdy/Ɉ$j7sўٵJU]VO#}E*ُf z 3"iboʶS_~*NѬ<?oZ였/w[)SgʸJq8 #FހS+cn}'w$VRm@YE5|vh Wj6#ҏ֔r0rS b 0 x pB,zagFHMAlڴ~QQг @S-LQEI5r?~YV˪T[#h) @Q=p@hZ702pRcV̘IfL2qQl*bUmu‚eNͤ5V[&#\9XEFNZ2%Z &T`D|Ȥe 8yr '= (1z%:N5~%^j;<X~8}W;:s)h iI $dpvC'˼Y]dlbdjSt7 K09o1ޚ̌)=sѹ >trMGj.B]]1k#Qa|6'G2q`C%)m f4jVu\ȶQ/ eW|u]=HDU#1TL0檑$:󒹬j-ײrM5|dڱ{_isX" ?v2V< W3+x(bH³ګ1$Q5gAh.Yxnިa̡1bŎ[utH;;("gtm[g54~_`OVeY3 B3p&*a6+jG.Can)~msLُ]0Ê$FX)\H3:8v}{ޅW_{z/Dcf3+/ O& "eN:{FF Ym/V|{ׇAx׮)6 nFlVѓ6:BGAl۸|Kdz[_ٳ[ f:Vʭlw 0!rOYѳx>^0kTIeU i4wZJO ǁ=߆e_$B}OdNO7O>D;ՉiJz3)eL1tLQ x8*A:~CԞŚիI!q#չ)XmguN;| 7vg_~$j„ٳfC@/TFRLoض:8}ݖ(HOCZ9Ekꕸۻo޽}B@+gaޖt%%:rMb|c@1 _7<`a}} ަ3p?c8U3.ܓU4 6wf[ZY Øc^硬ZΉ| ׁ`APXumX?XH#;4*󭹱^I 'K˥VY܉'8yEgJ.O3i%_0ňPagO'/{/ " h7T}f='UYUq|?6mPlL$&jI">:^oU&?v cH=;Y鵏QyRRN?^wˊ^ܮSր]H&O'Ig"YkDPnP&UPkt۞OL"Tϱ u5d1BᙓJ0ӥaiU{a7kŴ 2Bغ0Uy&/1\α؄un?~ ROP1FҽU=<'Jra!l;g0rZݢjZCDf&ذ {O&aƍhml 5hOc&NO Iba40:(dv-܆Es#=6'WVK*a&mPR#'N"ɻBSo̲n{ F&DLK>xj(E*tz&nt`LG[/Y[tF;=X#2 ̤~Z KVvnxjLpf0nmMx̊ze r.oAT1H_>a&8 2M,+2oXEw[i2-Cgw3-jُz|}h Hg0]̘Ϛ6*۔>:@R,E%ITҜ/u>\UVogXmΞ%`h #2K|Jկܶyadl&8i/$#6[P׸:&FSkIrX8z~?2'?"lMʉL%A qw"{/;ˎ "!^<L1ښd&V (q{N4JaF?⇅Hm^F@GsS#]& \&|>]\K 뎞z<˗DKS.&z}bdV Yw/XUc k3,xFX^~}Q\VܬX- {eV64ymm~VJ:˨.& 4III:A.ZwށMyoz~z˿XH5[i@`HzrlYupF=~EL:v27߯XǪHH î㍀|me )]+l7y e`ϙC6ju+eqxxIJ(P>a~zX6}G^N>[hu|k/aQ}&=(ՁA[5K1| I@&\(aB@ȱ37EX;nymj{nG$+~+Um&PWXdS0fxԹ&= ߓ &?4#L3=W$u+XA&y0# R᧯@fF6|]wsh6iVRo7=+~tɇxU5; w&k鯪}m|^FlX{jrm8_>xoA[6-52oh}0PM}[93p6m\+OiO}CecX9zDWuʤݏa[i#( C&P9%#'rb&mâ`CˢƖr#sR;չ.i! Q+Hލ2͌QLynA;i9w&"U׻dÚZؑ=ߏr Kf*-.Yͱ?*DV6 ލA>H=9{6K.>J {Ixvx ȟ_+y=BM?]oIf y&$4@>+$Tt!BJhooעZ&Az{&Ӧ18xd O-tR *ؕUtyj&Xf`gawC+c ڛð,:)1!Xd5:=aS~% Ka嚍ʼ"Ue-eFN%SO?߹o x:1^nm {vRV&[>oo**AC-~`O]]J}׎֗d={h|tiUc^M6q@?52˘BRHNNƤIT(w_g> <:*1 f?DI8LlA 2_;|Æ(_0~^Y3K`2?J&n[-g߮,:L"9B!Sڎ3|tĬ{0OMx}63--Cyvz1ҵ_ {:ms{]e'j_ISmJ֓e}$ەj#]h/۱ϰjois5^W࿢҇_t*Ÿ/OݛsmuXFPتHM$T[2z3ugC}R N(g3+y 椏6y(f̝#0M\ K?+oTq6A!lOҽ Mw1\2#B_Ȍ Je\Oio jtʪLNphCavTuA:="j<<ߣnU2$3G%UhQo@zS=VV7vbU+:YvH6 I%iO* SaKʎHwdhfjDCm x7î# "& %A54A1AfQ3l_Ȋ2Xl.:ɠΜ܉>a2~+O[ RՒ*gO#Cj`g >NjUСp42ŧ[p>Iy0v.+C$)R人3sv++S#HL]wFpWw[f<4;&LA4@U)|l}}O( ŲW8D3+f3f?Vߵ3qCp4IaˊJIXG!gY *\kJ%MOBk3)j]0[֮& _zCP Ɍ8̪!C7hL-LIUVbsk 0#}gU;\"Z2m{= JJvbCT <:KX08eV/:M覲B8ZQG@(ǛfD'ē#T!ܷv۽n2t |yuR1 _.\3v[YǙ!zm߾}@J؞~j?)W^Ė @IDAT4b KOo4c'LRٿ>d>#XϬs g_X6Jwc8;`f8W 3XSͫ2#RwU.̈H˞3M*؋Ƥ?dcH=sŸ FGzL 4cK~Zj AuQҗJ֚o粡G&BflK*˵G"_G>J'oOq3 ۛ?8L#H#wÓN!faeNJ&f?D)u>.=]J\a3025U:)S>M(9O-hi x;_ 2**N"0 '[Č!^0p+NcQbP^Z9P}G[R?@/* Ek_|:e~])UBJkwnʘb3]S*E9IXێr\J+##]f=MeE>Fo'Ǖu^H?WW!>r~k?w54GjivCR8Ҫ0 1Q杞~ZT;{[H(KA]:i'M²kD-7`0&VɵU8r,&Oc+i/K0}܆JE{OGn3g+{-sPǑUڹrRFټH\<gw0ZOX~#yjURfL=q5M&Pl& d*뵹5(;B~{Cl?жz[O{%O[Uwѵ+-6ܗ=Z]Tϥϑ$w]&ϒT)J%NWqְJߵߓp }1 NFɴ"=t lfݩt2H}ݎ;7p+6e*3&$\>h0É$3侧IICJkc$ck!\/>BYtQ3v%0(t:m#,j#;}|Rzh* rĠ.OEaLm꾍1){kʱldBFa#|h1f6ڄӓN!` Ac0h$S+*Dy ǎcMP|%j`sV@m}הUK7\4U7H ;ay/ ʄY>zwaxx`N&v&7_ i36!\>*崽s2BJJҘ>, 6C16Rt4ԲZAVV%e-E# R^2MCA@L蕝J mE:b  D-]8CR"mOFsB(ǹ4 ?N=vT#jXb! +ٍwpeea~|ގ7d3xwk}t/XebVH~}]Ncm۩7qd"<| ; [UW7 c;?`WQӚ0%b|n 3cz> I::HAڰu=̳Wߺ8]RX҃KXEeczXe$}p!Xy+}Ss KcjVڱ@C~s'+|T`-b_XW΃`&T6V!}{aa;u-AxSi2OVjPXOxp<| 8 \nJ&RzדNY&+geBGkge4ͬru *3e_MwtVQ<<1ƛ. Aʲ"_ s3|2.fgL,ԫ7U@uT')Ah l̨7 BÏris؏Ó6cuǖ}_ۊǓH~u^OOȞabZUUK)@S/']yZ1H{/8:Jb{pWVٯdKddRoio"g̃?ACO%)ڳixYpt .M7иX|9)+0m 3QK@.d@^X{xֶ!z5`k'Ծף%!.<(N2hu*AQ5Cu %‡Iz-\ `~^P r6.iE&)pv;%3hwHٛX),.<4{>v̝, D[KR]KV>V_ >X`؀rRwߖ_d `uUWV)"oO6.t٧תJv$'>ef]৑q(DYO^* l״J40ktGUEhcքm8pҎWox^6Ќ){jUkt.e:Vuu+q^|ϖ$F9Sx;pS"0֮"J>f;K#C3L@.Ǔ:f) OΤw!vDi 32-$l^Oz|َ(ۏɊjDTR)*I{w۶/I Sr$,Z8ծdb4==dNmͤ1dWBIa6̘fhnTʘ+IhlPR&e0k[2QjIyhhk1,Zw&B|OD_ X4ay o_==%"K9*őv XnDz29GlBij߀kfHKr= $ӕG˾U-{wT$%ϻ܏ɦ>'r }.RI\4X6y4f9'aOZr=5b/jg vnqӞ?5?uI RX(Sh:)Jv樂yqN!UߚshW:s3P N8y* m[`na3FF%𫨧fh)B7PO ttCʼt6P/6c2xtf9hgHFpۍ_.Ƅ;e=h9R78 =;/}AWgl<:UI:tš}hf7m( ]؇Y^ȥK=̚BЙNC[aon}dm [0yGb )vȧZGZ8Q2knGs/"ɷ`Lgݻ?j ȥA2 ieFȇ1e(c0V0 BQm;/;ҲlmYE, aj@A~j!H'0a!W`ox:KR7z6`B/fU gRU%a˚6C 7? KPxG$6: g,S–ut *1{p dTd݌m z-< oO:[`g:sd/ٕԅ5v\kMX1iӦzNI0d*_X=bC oq`O#WO] 7WGH&xsz G Li3gP\2h2yt 1B,Hm}ABcF=3+(t8|rZefB1 6Ѐʲ,Q@e1b<}mlv?C1zڇV*R Z _ M2ߥJnSr/}/J4ڻ 7'UqQd:Z~o}_xU Ye]]Atc dlY0,z& HA?~5nN3q~5;9WC۔ vZ'W穟S< Ȩ:IGwd6xi|ȊaʏzꚰQzbǖn7 Sϡ\7o\8Jַ8r߼ 2iTPJ@VKsBнv:ixՄAdV]VP^?a_oU4+:ťWڰ ).f\0x'8ƻ+ *I/ޥְFi*B*첟TS3S̺2{6v\g͎FS uH|$=aZd:x*།$ g%Z-3仅az=~~K<=λ|ǝOpi3l1|ꃝ ]~iyZJ.?n "da؟ROBMev`M._3_"^HL4Umm0`LNzc]@&U+JףzNqjIL IPO S۟S/(r1!`|ZW֪Sء1`@J(2o fkk5ΥOtj*H(Bʴ@&X7nÏ*\X@ՖS7Z 4$&,c⍷)T4deF݈2aAOMNI#c#pjVٯ}ڱa DD?TW2U\jh'TPN:9y]hXg߼x9ཻg#;`N.8pF{=%R]JS.45u_ʬ.o\wIիXedJ/q`[שׁki1rg|,q9oij򔜃&NefN;aH's_cC=_,嗘;4a2 vۏo.3mM >>g|Ev Z0}hm8Bݽiae8d|_XI<{_MnTˆu=]Su76< Lo}*0rI;Xz1]}y Qm]H)|kӽyQlA1<YUc2iw* = RpCuŧtªC[X_Qʚt~H11$K:RdVՒ:0 tIwD[chjFQX] :wF6;T|63J#>JzFtw HE[D&Kޣ´ػkĢezKTMQu[&rEQ?|&3vRIOr~eTVSs;j2ȨI 2Ԉ140f%MdT(rq~<%~V¬ V,Eȑ\tt SNA+`;^F帝uЇ:z65j鋃uh#)Jk*0,:gk 74 y>֒\QO/o*I/̰g%ek>GGw:o0u%.g _V)&]G*9 PU9&OzR}YQ ۷>LQsg+V{:ef31'bѢoҿ"EU@Jv)Rg4th ӕPRt'wSnGpr#)x!sNt虱 6֬>5m-v inضz}ӄk6cLL$HO@N2-/.HexO:Vv܂s4'0ظXu"0~psI`giB+4gD-KYLn-oU} X1+ aSYD>|Ktd"6ix{-0i(:HfFJ߻ƽ1([􃁾BÕGÍHujy}sc>{'Z$qYEفn1%%8͞)u%9{(l̘̤:lyOD:)|gOqb;G~%K \I%[Ex.Lp;*ӟ~Nkya6u-emEs`XBH7tp4,<]8}" y9y6Bpƛ& נJ-p J J1e 'cͪ'F("Q fq:} h ORqvaf^;Fea |\Y/DY;G=;qO/+YQNA0|,t2A x{Y u~R-y%kz}劔S0f2W A70;;)Ab56&fw~`/PӇdK[†>l1ڷ &6&| e*^(3QZ$>Ҩ]K ]cRJZԺ꼍?FA^.&2YLh3/ni2:Gɉi8`gӾ9ᱣHK{W ET̝wk&*63ӫ˺gHXMƖW0kܤUVm~/>AqӝG @L^my>mhm""ZIqlv-vl}^ޮWL~4i'jW>eO YN?FەS!"@qk(ӻ9 %|u.}s%MWOԩ&Խ;ҍ7`94760yV}n<:m1 >3';NRR $^U=03`@(&rGJ}7`z#DZ38Lz)sv&#Uƶk|ъ8r?޷co~t^6yLR'I}yA=+< k[Rwo{IQ|zRe~^(~^5]jl'E?f߄yO^wt ScزBMk;+2y+eo6VKsc䦧j~n|{y*&&NKA-&*1s`jz ʭ !>:5e,F />&8g`qv=iw2(0Y{[1 Lj8 o˳$mZMZI|7p/}A)Y-4~tn>}vJ?h%M5%9{YM1I.+YH}W^YGi=La`in/3n<\jٞb=mOH5()+d#vDhv*{t#ۗڀ\ku5׶~ cT\dn5Y%췽}U'KK.C{xcr2Fuo*(|uy9{LSeHbBY\;bǒ`?pϟ^ČyO_O*S&%{Z]=ag4mi(Y*M[M.PmTT]mӖ lk Z<5v%۲om\Y^_{EicP{O&<;uSl]y&HJyL2{;KH`9MEI ZZ̓Gy8gGֽPZnuKKAQF:>>ұtP-=LY٦pw߮|jwZ \I&/Iɽt&Y^ eI7)tyXgV~&gJ0LXmhKZGdm W9gUJ| 섵;S{`j`B}v@9T_"V$8 ]D%wVn4_ =5E2.D(rRCNG*icI߱"Brq JAC#qOED5;~-L4ޑ'EcH߻h,)!'Tem)ipL,ma{b=p6PO,F@SJE(dg1%=L{N10hͪ^74!+ DQƤ |(tˆ9*CH!4BޛbYݵZVE]v@@EM:BK1BDܿ? 7oΝ;/a PJM&c3‡{`e+~f|P6_~#1$r="W,H#[eNvBbj:,_n@7sЅg/eQitPcXoO>Nw{b`xga.A0\E2sATxf\ΖaM=;z@gՍr: ɦ WⱌZk/ i DF0l0͛ #픹ʂ`EXP8+H6O۟/b' C՗=YXs^:ϝf읶8RbB D%c<#q2ۄkYe-_Bye?ԝd{k$T.7nվNvK/ ի=_|-"-]lĝS ـAmF4raF+.>d4;Oޚ,g;'ÞwQ{{QU*NM(s+wDH+ Uj($ӓRgJi.~ ٤H*+?;'4SZG8vqsƍ('@UOzа?%Fv]< ٥F9jrG+ˑ_Z_c'[!bdA,av )f?}>Fcf][TA@%OP S)]]SOܞ+ot o1ؚbOw#ϼJǤW_x\J_Zmوm[HߙK[Pic"8}u,z[U2\sp,E*1◃0yt ;-U]̘6U. V$ ,ɼkغk z1\\aL[u7ڽ{Oʾ}Դ4 D`/LVd%u  k[' w_`_HpTT9|JV'sRjyv"|uvXN՘#rCU*ɼ@hh+#CTyVxʣd:J;p !dnY]%+ !;#'#sJ &jA'^kdğM+PIN]\_G~l皚d0h>OKW!}3n*Q`OocUƌp2da ;o&8{glog8wMÓ<{!c/_|cP8\҄_z mزt *}y[Ox1-!Y y/dk)DN^;яm3/A=лge8iM+p14z^lFM9ٹ} 9t>ݥY %Q5+֬[K`}ʫEmI%*J>$'[Q=/3 ;Z_UV#si(vTKu/V/xiX3hh/{m-V&O jǠH_"D :4v9 pMRԵ\ؔO!|ԮRH;8ϬNOVbﲉ3^N7jT u˗*x+j EOT{w{&w-lmɤ|K3g fwXI`=HS#'-xIj;~l|)ozxc\-,ZU.yGTij7P^H-[>58G^omOb U)e_GW-u{"oVw?0s+si+Y9E\8IuzJUۺim;i}T!Ytrm%`%vnYK[M-CL:Zz6ԭ2\"դO~Y_\ZEqfa >̭-)|NrїNF-SaF)u{ldzi(#~wVoA#*H4]џc+9㵿,6"+797m *gPp>{c Yͺ2A`H8sۄiH튤Zd #ۓ8FMԩ h81<(]DZg@uʔT5=zP} =? j,UⒼx1{d,Zso?qS Lm.<1}X+|VZE(//`/ݴ3= Xxgh-JꑛvqyJ` D6b3(1'S0ǍGJ%!Cv<~2N߿́c+"%9Ͽ ̈),3fݮgǏ61$@?l/+'OR*D$zxa[ z-wpwY36<3J݉G 5V*2^Wş~,jAIʪ7cIUdw,PBZ_%XXR%ߤ)c{w܅*l]#V YPs17+*s&%PPQ{N.RXƤe 2gbCd8QۉXo%ѹcRΨ?Ӵ=we{Eq(_2_u[a$ɉklZUt~|<=QC>톾dKb%CDD>_Cm6ULmu1:T2IK l2({8I|CV粲]"s=)p"{ҳi=@ImmW__dDs21l9tso#]Ø;i aBӔU*W 税^\l+%$ɋl_N:ÐLБBHtb,>]h1qK a\C :Z'* 8 (:FJqoBFR*wcx1xqH*1BC}o0f_/h˰A~E=.u&{3 0`9tBsknE~: 8ueab6jƤA~V t %玒LƝ%,sd'As#%CvxZgЬ . Z?d  t:p X#+;m2. /QAsŃ?9מzB1h8v뇬E,D=M)Wb)Ȟ.ʏqK{U}rw}_,YArϿᔭM5|}BPWm2i}Aՠv%̅)&Ѹe e)xIj"y:>R rڵ&bI,ڷM)_J0uϧyK9bmo@1-YxIjY(f&}_lzH>zGRa(}hg![vGʾyԱu7sP=ѮOwϾOk=HIMFtA+opY%>2^(>N0BUz;?;ީi8jRNS-PYՄ{;lb(/lE9}vE`FrOɎ̥I'z 9?0qBqץ5^4ňA8{&+YY6!9N!6{l9.pmqpC/+ 8 M旁&xїW"BLEm1% TR~+ڿ|7. ׍]0='$۸$?aޭ%˾W@D<.g6oڛѝ@Ɵ! 8x1N+݉^a)Is Rީ$g&'5|9|̗İ̭)Ymoc3sZ\}F (_|!5c 1gOxm{7n[kjbbdx*۴,|f1f]qq*ٟ_Yɨqavnnv ud:$lZ߿>+:1}SDYzpی[t,GAvc.?1 bZ껑lth jlI YI>|<=p)\svt? =wNw;1|Evt&s;;]Mw> KB7*t&Lm. H[?}"z[ftG)p_f3ޣ{{lX ~Z#M#sMtlGAL+*Oחp FNЌEߞǒR†@vYn$I2CW5U*k0 0j\[Jd!>En pw3fk9*)]4h(Ŧ~Dԑ0hIjM񯏾nGowOiT 9 Ͳ =|!ۢR VwH;M:x~Ypb'N(bQΙ$Әh`\Q4AscǙwͦ7c-b9;Yׯ)8vF:Ҿqshǿ}=ZՖO5uDVa R'\,'Zs(Zcx!<4Rs`Oޞ.8`0z#Ǐ`ʌa}|]o+ϣ޷aJ01X0n9-n2YVUX q3tfbE8n>x(2C18_N :xi(}]~2Qo:̑|=);4ũSg qg--D >~(tK`#$%g~Do8ga۾R){esqV&:;RtM0y(eA)0zԘ=F={GYZvh&V1ilΊLupS^dr ;2'Xh .Xߏd  څcOJYӀN෺2tau<{}E2yIˠ i<}a(}nje{<#c( .1|&cŗ)u vE#{i.]:#,dJ{t?Ubͪ}*U`54_1z`=W4ڡ$v &c pIe)㏾XAA Ȫ]O~chJmp<,o@yޭ;C 3||7nؠ8\8}[7*_uA 3,8Vo؈f(3-i(d.*6Ъ2s}_ɇ~i rRa уl"GWO[ՈTJjb `뮼?..Z^LgOvܰ1md߹ tjiշq{c`ǭҢ| I¸*ZÊ e Q 2~o{7=0 b$%1$m,s;XG֭Ɣ;d?9;{QJӼQZ#rՖ݋`\mo޾c~EU]#]Ud&m%z@t/}m)b|?c5q!8+v)20;["\}yؘ`Hh? =)\RRqR>/C ÉL~+.<%4v"aEO8Q˗L^ :ǘBظ BG@73Q8|8]- V(Ǚ\3%V0. {PZ)DIn{# *2FЌ\$ЕIg"9~?#jL3Cs&.5h[rI<Ћ_SsMwzصn?r8'v3">9RFFͽLKB=LLplqkA9Yz\;~}s}+gx:gSd#p0*K`N'^|s0QGi~&8޴΢&tކ{#s* {lfE'}+WXT~p`Yn4ɢA>_Xظ6#e!#eu4:C &*jGV|rq4,hzt3Lֶ@VUUOHsb>(;1^ӄ+Fj3x@fx#ZiqWkwtMH!47V#ާ>Zפ$ǭ Z83Q`[6m[ h&7*ں+.#}O>`UA:)\CGvY-RGIrn$}JWCR\gOߦJ_c)a[GIr5qyWP`9NkߪchÒxΌ5O<8rC ҹvr*֭*5mn.sHcDt'P)ކ~XgӐDv3~ ݙ%9+KKs#xJ$FFuB"k(DŽpI\2k*WC:zyCkkcJ9Ȥo@/w*}lHqO1a~$`Fh!4TÐMـҺ=ca0Q:;akochH?U NvVjC[hU>ct |sFFyx; `sC-mhU4o.wyTf,y]{Ț;g )%\1J|f#7螨-#XC]s,# @z : daA4ltKh?*`xXf ^0>[F/l'Y5~ ew|Eɺ0n/kiI>j) kJv\ػ;pmbQV4Bv^%=b,!lI U0F;5o7lw ql  j1LEU,yZaG_ӄ` Q474"6.'T*ճ P$=0#Qp=(JUq^T^!#!hhxM)S(o `æ0zzOpr84#`oH7NjDѷΦ/K҇y}S㑗>л//^Ψj6I6!cKlV3Av;Ul`. JoIQKϖagQY˂itKHä2RU~rx)Oituh"MkJ'+ (ՆV薯yHapPj mwLXAɱxsn%Vr*6j>kA:haJe&M :O`Կ?[o{GABۧ4C^JοQR&|1[)!%Ȉ3ש=$ދ2),.ϑDX՛>/Ǵq~Ni~inu `@(NJ[ #zt4<{ɺ$%*3 P d F]=A~}ˋfLסBPR߈ lٲˆܵk/ƌg()pB ǽ }(d3 @?M \%gVðϞ cYw\7 CF!9"~\1qRGKb9ٿaa 3,J}ᇈ`\-ٰk= eTՔ:8L#q)B< Cݯ2suvmuQƑml*/UqTV.[BѾRmѧO*IuenFcymۈÇ+$|pGW7O{o!hg/AA!$_EE 7^'00UmI#jVWڛ= 4aέ#1x4NS˖ [0 ZJ|a+`vtu"P$҄#lXk̓Dv})+a+e\X`7 dŧT]p_?Ä?H/Ʌ 0ߧ@E{)-Mox*t*t`tDNVkD?BM_"5QZ;z.x=Ȓg7ar*H!:l+glE؂q<|Mqb\LMðcaK\ 2x0!ICN;u&֬]lgO[SG²5~O||%WUYuz=۬fΙ_K:C9 ={73^H=:J[R鏖̥|&DYMzAu2eҶJطwJaa]z4 /C6y(;+C/=@Aʺ^p=Uwdoټ߲.mURgiq0EZx+yy v+rk x*y?o-k `l<.~q-jaT-K1^zr~zjmR$64,df5ul+9TJ}+rutU&YJֱ]j_Xˑmr{ IZArm]S7S}*OXumؑ򎨠guQRz=>zIl"6#Ğd{ vBu^<[մ!r 6ֆ-sݑdSG2ijCEƤx"4Jcd46sV:W$вW,5<0' D'_:vsVRcH<"^V=é?~+z]@<>[ߍnyэF}$GsŔs}Ib}D3g3kݗ'K̏Id1;b}6}(ud%UJ*8Q~)3{F?ͦ{fJv&3qx$7;cAp!ǥ?.!* 9Eq zyQ֯<$&2Ê<.d7b<WDlM2̿m<P'؈M/mUsZRa0=y%A>H7s4k[NKщ`^mLHT ?0T\D`MP4-]? n>=)+gcq|QkRK+C[&boQ–fB#cɂPxi{q<&T9ɨK0҅ 4ћqrE/eov*͠arUy(1T;v,e MवiEW2j߶} NF&T(e܈-[F0 FX0e064:QBmj;$`i[{>.DЌ X&O-Æc_)2@o!Cux~ذ~vl])!U]BCcaKQ2kQ'=c\־7a(R>,/5=蓜b)A`5sqdWo8;ڡIMOrT#R[f4aؚ #5yEdH,lI-|BQ :d(Jq"b #}4ܴr(o_1I[( _R_ w- k[eۄM'cf^pȪ&tRӹ3'N APN)ɰcQKYvz NNDa-8vׯ]:FCTu`(dߙFpg/?yqeh#\Xe D2{Qm蠡={v 5رHDGS+ k߯XNYKOx`cTNt۲-U}})))tT̗WD!9)* jgqXX(!X}y!lC"(kű!-vP=Raq%WȘdl-LVcΣ2DgC%OoXPcppN깄snxtsMU2À}Y:鉱pm,~َGcP$s~G w|ҟ EGV9mUf{kFob:l ٦Taشf=;۱G' JA#?w-SSR oTѩ CƣO8fpU`$$"J)n"蛙#|3Z>~^RYT 1#x}mRjfh*GGr S]?d& c3;. aJ:M:sJKvCau(F^N ޵YEj=kno&dÇ |6GfnڣOVaz?ށC1c(އ}? E@0Pjؕې/V86C„VϢ/ytJ++o'T汯MX^Pط{`o#{H%ߚ> ?d>jlП},{ scǷSTTULL8[rSv~5Μun%cU`cƏp=ioSaҮ$4&xnjG! M bg{mz.sG@ˎoW]>z4 KiAQ%],]h UP i4TS+M/Tž#a$b *CدCjuL/H;]\:oߕcK.H*&venR)]ͧz9Ze6%HCz:GG{.d"'`\Nu Z#T;✠ 娟rGshaOZ,廔/t'$ɳSUYu>͑7W_pswqxR[g6d;y.jؑo!t6v2aU/l;TCB[LxH% a{264J#2{LQz* ߬6ҩ=*[z(n}Mȏ8l?hx)PXR7css ɦRgx s"|3Ptwܺ&5oNh9I<=d![/f&R1Ԇ 8FÈ`f> ox0| RSOK &$HfȺze]7I>ٿqW(M Ʀ44H/校ɶ2c},., !j@ZdIVvj2>bQ^\@/zjX.mkgK6r|N)t¸!dBYV #POO[{v?Ao_Wo%/7n=Hr#@+[W_Ra+18'O\܅2~ߓr+y(@7+Q=tgN$P Ȫ{uUd* >nH}VrEn{^'w_lٱ}}=Z[^(Yzm1㲁* p lRZ̧~+Lz5~%/ <8OTTHz2]x: #FOTm?o`T[Kr~:SvP]CVe@ &_}EJNQNOVV)"Wy lؖm~,o"0֬Udi oqZUW>_]fFEë=H4:Q6;bCf |VJe *e4BB2d>^9d`QәHå 4d#4S~ #?Nu>:xH˳k>")!}\aXD`== DvFq1lrW/O^gg͖?4%Ky ܱzALGȊDžD`UAw5cnj[6CY~"Ss Pi'q OI&K{ ۮGxhm h*Uwן!?n[s&̞0>[KQΫ9wK_,>=uΛ) Mm2>T+u^dL!NIGԪJOڙq銣!NuSbwuI2>2t&6Izb|O4c6߷^_ Jʻֻs:_ ug*/8'90W5,DaT;. $RG@팕BoMG֤Qh cM)NP◪Pu*1tҙieK1RZ N' ]"UvQae&)N0E 8ЋfbzSӮw?SyW]+`Tq38Z@nˌ;uŔ͡,Ǫd$S5@' jk/CFf,%HH==e]=('&)I}>q1)lfEY{ 0x ʛq($Q"cgbc\&GgVU獛(!؅24,3**q1>ڌ|N ;r9&1F9-ރ'>A"/ 6Pzv&Wb9uBiQt')FQ'Wqrz9.w(7+0XU!;GahSȭC~I5Raٓ`׷7GÄXi˚oe׽@IDATBtG(;tN}?"Ѓ2 |rjY?HN%#7G߁)Rͭ߈zC;pAi<>cGEォvS;i+9R-U7o)w(y4 אh8{SR~hmi3XղyIN6VlھwpU\AlHQ^^v{ݍjbLk4 MD&||P4&o޼7Ν;3|;#`Mc!29I킅?rv&S(FHgL:]:ӣ܏eFҺPF}/ħ~Kg?tgf D:g]e]3 Zb<ͯUuXt &q( _'nxyB?ٔ@7~<@c_5p$0Ȍsgl^0&vŒoCfe+YLlhl#4R8wᄎ#ps'R߃,;lI}%104-> bQ&+ V)Yv K)XsOsonrPhh( )ǟ=sr)ÿ﯌i2,x338р%-kаlɾ t~q-WE} ꮀ5싍7M%KOV%|Z`|y|:% ;@eljGY972b|뒵^r֮XAGҙ,l#7:8Auci=ezd&J3~a!K&I~O_O0] ]){bdaİpdRVVJ#r+xx僯-`i.IqIXIyYl̘v7:(9sVEg2:ˆw+ Gs1ŽC;WG)3=s(6)C73d HOVmzַ$fhoo*0i81^Y6:љj0܏Eؿo7za 3љ L]~#|2,Hgȑ$1!ϝ8b: kvOᡌJ;`[IcN"?*e;F3='1l܌VgJIpkuvUbI2ϔOӹR0aCL'#ɼVφ hkvV-E)cQ**tdg;,4S/P2^]ޝgי`V`9ԧ|(-Xe,$kun+a1G5@%O9jWzV,ŤE E.o& ٢t9zPvCxgޫ8wso](^xmh4#/fџZ:s| &lДOs58W8l 4WORх=}CvIaٞθ9wUME2tS7t>|̹tIB5孫͜0s8ЉIOmqc/ΟQw<%3GAmRݑ[XGZ΍tc8ͥT*`|ntfÚU97Ŧ՛y=J;I:] )6('Xm!<ȤPe~Da1Z.UpBunX|'amTO&+9wԋ'ƾ 3keDS[7@}q$-dz|D5 Ț5e0먴**-PajK;{V #?ONf| ]SUdm7޽( Mwla<ػ3CKi]zhe(wBh`;r8Mrj^yڞKtKMl,o'Iٖ.ti,۬7kiÔ|@EM0e,ꔥ z Lok@@:N^%վGC9;Qr3{jz)N ") ڏRt/}a :R-+iɋNt0є]Uz]!uiG;I^NX{~WfomV)ӾMAּ+KMh̨W6}eFpHEZSLQUqœC5Ϣ6 u;l\5}V6}N0#XlL)\|@励wJYx2T?GK}a㪝ҭGs ui;\m R[3iT]&uw0XVF^#`Z BӁձ4&@FŔOTNSU8mӭ;F}7f1nW Y =em]QFp ~~ʹ$as&NWh@:B)S{6c& )Oi'Sjҹd}Q.`aWJ~%"O%Sq[1dk9yr cU\M<Jxuw^/<4|:ۆ2X@1066dHvŧ ɗq&\(ݚ}GϏ<ͥ Z.ƨB`iXd$z81Pctva2RPɯʟ~AG?dH$1(Ia1%Wma8b_㳷#L O ks [\*=Ws7P!l3B15T*l CmX٢4m8Y|.[dec!#4c7ð<}xJ`jLYjJڲ8sUƉ`eOh xً`۔)SCά,c0s߉La#G4ԥ\p[&%3 V ؔt" Xi%iBkC]PXd%}#_|e}a 4tS;=w]tXpU> ;i iԀ1c<>s#*D&w @_bӦ+Ǒ6q8_d3ؘ02'5O<*k8 ]$Aiq(F#gba@È@FVIy5|Ki4'0ݎ/Ә_-K/hI2Rmh[YY2g_l]Ξ Bc{{#ǟd]e{IiQWJ!J&\L`R*,(^Ebr%:\s8$녨gK\ޝG0|t.>` h֖hPy%S2Q3O;@)P$1'1p8o Ʌ|m<"yĴ eyo%^uqqYb1~qJ(LEg[aԨIz2&&;vZܗ;eN3# z%_K„!憵kxo1k}GWCI8~.z$jS#:Lv/D!=1G߽`~Ʈ>MI`HUX%=jWtD(F^n2f?wTec}OP4)+l>Ёøb8M^2<G燘_1fN tilҳTUөY1k{te\5 S=gPLwgؽs+/ӈ9@:`(]xucpP(,J8J8PaĘ1f% $[SQ#N|4 R Mv >d atJ_R64R 9Ѷ*Gkz}v=9n-߁ k:pdBI TY2X/>k'7!N%C֎ ડ$Hd\32J[4X:sok6&CK(FtDQBzBI[I*Lj*cZj뒹JJ:)>2>S?~Rn߳Ίd[o_©0vx  2b<ץ,b+ש P'IN zrNհ1$ʺZR.9N5j'yɱ2֜h9/&:uEnVfqDnΎd:!f8{{ݱ8c1w1!s+5n<֮^?S{`:91h3p,ga-QI"$wCu+V(-ڦɀE_(n^Ĩ vm\qcc*jN"WTddLݭ?A>:vI)Ͽ_C.ƌΞHN:Tst0'c5A,!c=J@aXjV[Ww*ΔRu)*_$VbX~0"hJpfvfwtc]߈p$*Ls֫CCtbXO`:TR NȎ00O° dg6q tfֆe> [*o>BJqU *87u_T{6W-w{=0:}a߼yC,M̳6׏?ԶVvqze~&RQlH4iQDIXjҶJ)v{|')5j9iCUR)ZRN\D^Q5*$Zؾ2դ2*!6+`AeCNɺdG&fQ9NĉBT>r$qT8 SM.C*Mw'`epNBJ%LEoly~YIʃSxN}>f)όOo @ڑeD6KijG;Fꬥsz)ˡu2FY=ԳSSn) Hɸ@; )!Ͻtz>)޽(ʣsr8Gv~5Y4^mk)^㛚RU*ov-1Ka *)';]q:|G:LE$W44K$vcrR/ܧʩT]UCi 83ӼT;nm:RyTu&dO9 GEpK 9 o?l-,/etGk'cχm`HNߢb_y ~=z-9ṿ?Am@ÔhٵwRrp8~l|?}_s+R&Ì3a5I(sl䋯*ۦ7mr.z!΄*hhמyCP[RI~֭_q);ZY81dd{g3֬?^x[[##ÇܶA)]F.5_8a/'@gG/mPP#Y;q\W?6QsOvHzvg*aOg3;1CDٔ{c./E# KdK$mjeqB%?;%^L󷌬>$%$^"{Łf 8gƏI9ueSc4Haiڪ9YXf-0_WiMSaU#T RY'pHe- ͥ0?@|!VLU<Ƌda$Ci_G$$RUMٙkW%1s>/O#1+jt1﫯bj[Z_ # ɇ1CJ#"I_$UP1d  /8v >3KϿHdѣwu,XzٰGƫH:ZHQ硇]G5-)oiDPӔp%eMW7?>.}:2;b`sY{Fv0'#y×Fz5q!wt怶fj|ts׮>uZ_-ɾ-+r { ܺ󥑑PRsʧa'8wΟFpmj]}䷀ywMN/W·'.Z,2.EԆcߚZj^< u?j ' Ǯ;Xb>l|2=֚=$ uWf^*sG0Vפd?4mȹAUy%ӈSnWlN`th~:ad??5}E? >& =F4t`G0 |7jg23gޭ~YH9]9Glgu͏" 7m^8\:& }?󧎮c5}9> ]$h1A:ʁ1_W'JǠ1P5NBGJ#l k==[CFvtL 7G0t+o%y-I/r^ʟk_u7f/S6֩f :7:l$[-׍V2/vuUkzMV巜c[W1Y[WO{I)7T4i>MenTqM$xki.KCY'׈Dwnz~j(:eMijGQ]R;?ջKG/TJwRVivHI`^:^U&y Vܼ\8J]zN[s06o$=:e2Wbq! IFbb,%(w2RsQVeH>4 #PV<3#.e_@=p,d처Rσ5g>TٸH3|B2d$mݙsCx|@::R†$3맍wwA:zLb歌A!ؽs1UBHvw4i̘1vDK&6gK&\I!1,J_pRRaXn=YMơa<?T}0G-.|VuTwt8m]8Fp#Sr&+6MQ1qC @SzvgLJ|Hqzb 5XpB#m(O&̸aٳbYݑ1n79rbleipX_|o*|siɋ] #)и.\A#v̜roLdEɧiJIMG 6v6%-dLxZ PDO>am~-2Uӏ\#%kTL,?i&_O0 rw@c3K#%`Ǝ dߒ~qJ(Iߒ`66̎:=fM}ie_ŌBɶ|/ !~=C}/Er~5ga5ܽ;@cBT8K?|;Xa=%Ip՘x2NZnf@۲BXzFdp nLV ̐j%hЗu04 v8ЗC0[撌앷ަz45 87?$wZ3MCV=}_m K? hHJ!͆@{78z2GyY |I|O db|h̯(,GFF>%)_v÷r8'a!xWq۪J ^d>6ŝ?4aaJǯ6d@i'6O:eMLL T8IiRV=-a0fR$)9QY7^1@YL|o2iN/o7") (ƌQ@VJQB_ V9TDlͥl%>GBЉ3 28 wl0hP1(e <ŔlϪZYۺV/KsF+ȞWΟG9z7W;%%"/=@*lxrL~PC6cs犏>"[G&dD Nz $Hႃ[7 MٞHE HNcZݴw!ٚKΎn5lj$9>֣a{k~ö⦭ٽa6˼a-Оk|3m,YؘKtkQOvXd[cīo*咩 ,ۭ9S”95jRY%쑹e>e(sU-ͨ.5sҩPx)9[g$R uشeM/1P"H9 7e0G5'(M?o믿72]g3$F729/N %ى!euhd*,XjLC=6X/aiu{477wȘɠS*9Ʈ8H[_DgWSX瑐e7j8$_y! w)6d֚]+-,Gȸ\߾+~[PmuX ;thp Ci%e"=Qdw:HAUq q).C&W/Qu HntQBuqWY»{8Jghݱ}ZFivۚK$f+{S8m7[.$.mk)m:3TF/(iZv׏G%١!ZUq^m0al\[!ۻulF_\RKc/U} ՑO0:P팢(dZq\f[US S8):(q7)R+4yU'!{!3t")}fh^U;^Ou hQwgo%vbQ^ WFՠt*Іl>n]a?d$De2j Zv+&yOeA\)kVϫڴ5uMl:~dؘ*#TVW겹erRNy+Iݦ֋ԯ5js#ekܷ͎Ӿ&r?R>}n9K doSr()6\ұm㇒{ K,DSe"{ni nV&6`YEB:07]J9}VeiZ>)f0d_18}ʎC@YPSxY?L XXk('-S/ d#j,j\iǩ"5~$b)]}{K 2ƒ+/L`1:yXUYI9V63A:XX||v8eܠ4S=(M#ðjwpE\G[X[/7B}U'.lk~QG9=Ƅ${ȔYHɹ!H Hÿ3 1تJp",aH aީQ42O-WI,x 9Tꆫ)-mo7.9Qti+Bo=zwБ臈ġͥ`Gt XbYdt\ufm6 V~t65cw'AVOJt,Y,ԣ,}4iɒ=,lqLұ3z2h|{O]i`3G[xtf!\Ly1/"/Q1[; f^j(%I0B=(hcF# 82ޛ?Dgs degԣ3F@#z[ʉy3H|c#d*ߺD;\rkO mS; kcPk+%lܜ=ke4 oR.m|,wlmN3QjwhhcmT5\4d"{xԨQX|N8: a !Q[l۶[;9֪=bRAn2 K:{XH4>uȒ=/}J5 t'~PIl5;=%Bm|=SJ(ƉxBlr*c\D<cNHxL:f2C](qՊ8pp?u pU`r9gNSr[ Pd&4X(]|D Px c6ơ=e' `>JEhNcPƿHXnNοw^d~yjDG'0g;7_3lC{؞0X_uV)wLU% 9n2=4E3r≻C`\_DPޘᔔL5 Hs?yϩZ#L}}{zhb"^ nvr|<'(dr ¾۟FxޡrNoC׾c40Uf3 n)3|θ ̛o|P|OO@bq,Afٽ2SynR0s` vN*6 bzR`P}G3gAhy22 .)Wu>chyƭ׸TmNeډ Pm[HI^OYy%%gD2UW^ eO=XL3_<`ʐ]Sf%i]ggHZUSڥ cWJ'KG'GO)vR𤋮Sm[}[[l%Sfs=^dMS`^_gF%RSGsnu^If w/E%4//Ui Xz!I-}d&Ust)yIg!9<]t5H_M7‘^7Jj񚦼\+9W~8 ;w~ qler~i`\v.40"L[!^Fk\F_to* G'.TJ2ngAY Ȉ5~YJz(N.})WB/_Cu5c< :-͛_Dn[Nv% ݻXᩙp0qG \JFd |aĖ'h"M}imF)b/ഖ1 i'0o3d {U{YVc?U-WqM%Ꜩ?W㑪ot ٨yȾ2| Ǝ   酌Ɋ"itoC!%t,&\A0'% ~{GgXk&M1d`ƨKm8Niww 1$h!q*<)|Qtw#4pdЖ,~ Fm"^y~6431b5ɵNtw[ ڟ92%7~2T-x`sƌE >ɑV7շ_[= v`J-=ҕ=80cO N~w>ݺcĨ1(1C2J i!<xgyolĺ1hѨзgޗc3Z nO?T>ez5)N1P5ϸ ?vu%ɓq ҀiCc6tk+휷O@ݞT&0b ׎V$Y=,N0e.bWS,")l=f|fL/'`|$qOzdK s> aHx N)w|sP ®қWB#b`Cy(n0^/lOO)՗ts ,wjE5*zd\9o»quEٶ4}Th 3.mYd9%:]w\;Vo/ yE8Jg:]:ءlg5_k,Ϡ#Cn V1XA4cW,ȕ03__ frvZ7aR9~A@ޛcNu_uB ;%&j^}`{}$xTV1h|/{mO@.Ӈs+C˻΀qL3Eksj:NJRQ9Rk7l~vWa$s2':sTq16?'s*a8۵7eh]ڙrW+ 藺B<;+l]Љ7{sz`&}vuqM,ЕT)EdB6k,PΐƦF-=D^[=xēwc1ǭjr'KΩNY+PG΍knwĞ K:30%zS{OeMāmK0ᗩ6Ș׌YjdEšt s^L"Ѝ 5OC5WPMӨ`? 9wp\:⣢&5V|cp}/NT)oI{K,] #amw!j1ЏHsrT SՖp[݌6zSTqgx :m-uzHE@@'֡$l6Ƚ|؎4Ia:qgGq&VƘpϳ|&4]MdYջX~fD`wF. {\7rޏ?I:K?Eh*|ԓOVʎu,WGw+٨`14Lؠ=*`&%iכ{j}ݻ-y /0=MVs/K2dv~HI5Bs`rsE^~9,1 q7kV\M^|BJƥV &}j:aNJ=Y:J*ݮ6戾Q:0S ͏>EM%xeLRI9CakpݲJK{̲R ǪO.L}lMv_Nmyщ9z-r]"'qyz^FI+m5ʡ͊@Od_u[Ӽ%?UR:=~r#UNoDC7->)cr$$˦PKZoCR{W|Bs5.݉ll-k) w\-uHHC, \{ !mi!1.7|' i(SP;iOz+ Opk':iTicR5˹o-vYd]ob\I4;/uveڵ~#NǙPo9 A0lڴ4MM*8Ey'I PBü%m{Y%.P}09bdFUڵ3&N\Pʬ@IDATH*@UK?rhcdQI)!73$U|ABzv>7SDŽISߓqHjėۻ\4#D`2= ܩ.vh:1S j9a;1ߗkVyqfvDg}oeȞ4ed`wMH:X`՘4>Ÿ~ezA?-*'cK}8{v j&MF=5CG1#F7 d?Py"65ڕ+.# cא=ٌ\Se"}Î<<적, 0'm1o-^zѶ=E#̞>cv韛qPBot]+lghE%"h'g=RJØ10 :GJJTOS:G_fv&ؾm;Jh^^|Bo2ckm6'FG|fc|.{Ιm_o'y mة= `|^X"(${8V` +"2.fLdsxE `xQAT͸@@x9M;|$(o8ɿ?Cm ֳE҃hJ^8{ Jſ=bѐGQ]LX޶tF'}0*BrQzkt9hsTYqp޿ee 1=?I:RZ=040ųO=?~cD}>t!x_^\*JcflgZJ򹶠oX%#3KYۢ4*x4еDfpXjWgk0V2|b1TZ'LY(O_d߱ S/5ȍ^M,IM2s'aAG6:}zR<~Y9aT|VuqJ]vnyq{^h&_%éZ):|V߲~ [bi=þ=|xd!C^g13fJV:y0Ā;R9lΏcybc9d ]:fN[APPʳ'(RɔP!ԣ. }Lhx?ӓDSHJuE037_~I<4|˜n:,[-^_!HR?**v~;" qtF*Uq G% t `sХw&4es۠ME>xb8CuFӱҿ9WN!vS!P-ruAq)Up̌џ1cWZ}a9+¿'jjj~6!YXD?S!>0M ECm ˪L:eOs .N=ӶP2zng\]8܈;>JѦ Dz w`XNXq+EG_?GhtPX>ˋp>2퐓ī||t`+ ahY4Rfo\< AxosKth?Z'{Nd :]L|E)%+vvKˆsJpoLV8${q. 2*FlX>KQfpjMB>jzB +.eYGPΤޤ:`>@Ye/zB ]ue鰔Nz>I1(}Tgd&+ !U?\XXI X&NH9erOMܴlX$yk&d_sJژd^ @[Af=zk.Z>U%bg&eYJ.Ql",QTEͻu}?r&h_ԝW%l~k-+`oOSrP(r*- /ڈITrhiZr.MXQQ)15gkl-& uG 6]DUdQA{=VTq",;QBU=5[VCiȘطg78)E\+@Tc")uV )J7a1|/&93&HʥŇ0?av) Es^GE@,^$12çaAYJP@p1 {cԻiúuXEiZ4 oQ*f!  vdr^̠@H|Zy?ڐCA=3Y-K `U+ksɳ<,vfGF R٘QqCaE@nUbHmذieۻaPY;)TU:9dSq܇{/RVtڽO)ΐ5w7l;a/{0P{<؇b찳,՘9_)Lc['O2L so93PEY aBFr{-._A0\ܼ=&S_5"ŽA@{k82KF~Z"dFF_1,CFj"Aaܠ[Xu$m 2$WOv/VWW֗ĶZŒ55-uJ/ϾF\fl`m7ceFQ__vԩf$J;zW-S-Vb ~^d: Brl!l;%%_D!X\t?~V o]z-ۑe϶ܘdy9Ϧ68vx|fw8.oaʴ?ae.%cϬ0}1GKylX.ʳz1&a;X-ƴi~Z:Kyч3f&h:14 Ԥαd|궦KK9K'#yP KLp:y+KQq$0W69ąKQ(ã7ٶQtXLUwprE^>ؖv팗^{ QP*t?W@VA%t8{*}FL~.͹H!gp\@'` %vjӋ8w.@d Xvw@f8Ȱ8~Smi/|;oQttw =&?qdBPZT`xm /#A O{TqZHp Q[MjgӮvSQ%5QOrѓ؆u pA:/W Fҙj2tAgʴJh:!>.7mz󚝐v.$2Afp#"YȕqSYv&X;E"FBGF[Z&N KW/葓r݉+=cj{vXSd.xGؙCvfwźcy޲E!<|QYyH#n|=G .4(EmuxN.aLBH!|FI.NNUI ÿ;r/<=yrO*IZZ_r)`|U`@!r$;GK_Ň FCO{^C}.Ȫ*6J95[@RZ[.7MgUØlvjWj.?u\τ 6nENM2w5͒][LԲКqmsiʫcuuYCi}iC@*|?z>GaD#/Ie *0>ţFFA81wC:xCG<$݋o2{ߚ>7mAtd&)LL KNv˖ɤ V1a`2 Ӗ7KrAx"ɀkf2[UKV(c #S KJ*%J1'ȩb4#@%zv6M{I3xh 8jO/U{ W. ; 8NaKRYÇ2059Ѵ1ܮ._10ěJ[ ANB%>EԳg'2cRozغ\`B$CN;1FYOؚWzg fvLp6%Ԍa8E/SzVpbɸO AlզّL\?Ө#+4^`ʔiәk494{K 7sSN] w,V9VM-h@#4:0m '])S:n=;h0wM }R7Ɗ4ӒrTx7YA&k<ڟ͝ 2s͏>@pd~2O66!S8{FW˽{8nݮog^$WȊ "TEEGC?'BBl/uB\ ~G`)(ٙ?d|UБc0z1th矧ccx`WS0Ti+ pȢ~:Lvcߏ,{C2%}[S?gz0CB>sy"";Dֻz.\xzޔw7^FJvIݎyVΝ;+(Ea q1Q]UD L:ĸs$ C:I2N'xgnN(̬,|#R8pad[}6zA RM!`Y=8Hk֬š1{\,[!V05Fs T}',D e>Amgj5 G' Cnj4o)+a(Q>4/bĒϿPXŋ?\FVJKnŴ9wCm]ڛo`9  7,WMkcʪ?yuV`͇*stﮌkn8=LAQ?S 1;Vrda\:GgXo|FPX05kQaz2>9~H!;-4n{.vϛŐof>Co2XX}vn8)e]{w3T=;O>K  ע4H H.sq[:u`U׫lL1#4Yτ ߥ1 B'QƏ`dX:lw8gQ2N]:|(1׬^/gTsjIXE1}CqOs,~Eci W:Za{o cd%ʚхϾOf؋nypq7+@F*dC O'cR|/(f+# ~زx)MYGy/D5 \:rٓL 3{%9\=gH8i $)g8=Pӏs4vM5n(+)[~fLX2 @5hҷ+Nt~ X?}G(̣ԣfMWΫ*ohE4yV8ztC1DJF6u>o:KRGb#0RƲb, 7$5g.zO(u1g)gO.J+ uz؟UGuOW ֗nW#h#fx:1=PXXy`+:}ytdUӁ>-6Vq0>bCY;{,}%*YÏFі8i%G (hş|cqQ)ڟu~F̕O;~L % ]vj:l>j'ߴxu_Y9 9EM[GǴ|J_`Og.tlh<x`=D5 ٙO' |+HR:EVl?O4כ} <69ʆ\LBnva$/hl'ށ!z+yKg1v)|kRmgxo_~,E+aY/sV%l!a0ɭVatj2~l4+3I$%@FX5 & $rj O.UN\Y{tؿpﺾp#5?3* jV={ 5R:@J!K#,I36_:[ܟ:u 6mBvcQI&CNwy"e?qb.n{(.֧2beReX#i\㄰=ՊZG=8d"(.oA Csp!:Ɣ ˺TCYnV1N٨Ëp$lҘ MÚNјVrgsE@R˒wv{دjl8nNHf:]]8L0W>PJ8p1u /cǍ>2bЛ,mB- U<^~ } Âz!0?J'C{Q7/2BJQ7dW!Ugkq,rȼ_W9t(GS-RDb-p3U}Fcu͏f{+I6l?X01(g)3eF&H=S I9RZM)q`Ifnܷg*ahb]9I6dQߘsەÅU螩8v2 9&4nYj)6:O;Z-~=dլ;,, )ޏơ`%KzVlHIr#hȠR[^|UŔ)k,8`,~zmr8t|2t l?#L `Sz:zM@.4(nQwӀf _?e[ hi|]ܐGi<-:54vY:w1_lٗ?ƜLJ!^ "MdVefȮvW&v%ٛdm&w^1pXn ŋQAqoA7YjB@$=-ßF\ѹ /3lg[ilbw~$ K5!r`TUW#@RCRV9eȝ4\Z`뺵c#<Ȗ b~X=LWO`ӖH|Ǻ/9Y) 3$N߲oD-;񔥶3cPf hDrq !ƀtgKP< q1Xeۉp0c4}1cӉRdHuX3NcWYny0X ڨ2|u;Ԉd ܹw\뭜qmKE#jruvR~tSW+:}G4Ã=L0?cPo2GuEaDxa XU+%'̘E!FK%`6Lȴ ~ݸOՈ`_ kH$K]>0+)vm~F0o;P9A%Z flc]ؗHEy!xT @ zOܵ{=@MS _87Vd9Mjb"Sq{FJ(y??%|=bl  %#[ M~d]J}EUw8x VNIMbOI=x~=ۛt{nY70JuvEF6Y4c鈩k4GhRu⌻'jǍj[ә!)9>L+d(s71pJ޼U`U=c5_9:3~ jTNT6ȪG QF0seGcv}#8q,,9QSU8{d &YQC#gbbM~dqr4B?zX nwG~. ["oc ҨNfKS?00Xaoi3c\Fx 3t9+; _B:3 a;N"jۏ ܞ9ބPN 0ωl"%jf O6 %y pDZ7٫Z+ۄJA.'li~.tf+ġs=lLZ`DKk+"#ˆ؄n=zS⸄9h*Ñ=TI"XvdmK];s5҂?k3\ʕyF)5lj@bQ+p{ w`:1x5|R=V];~y 8} THG,"bȚ@rnF ۉ1Yًmشv#IsW7 [W[چ=aU |wܿrSTʃݍc:6[I0;s)|X8E{T0 .Q/%m޲-\UNj>bJ:xa3=l؈_orX̞4#xq~_EᄆEP[:v8~c㺯u 8k؉ylD-TA.Ts[EOmm*Nu\n|ey*}W?ݴA^dg0i|Ҕ)ӌY-mxXN ֮) VI*c:S|;|oi! =>{7m.t9z- "5%čmb ]\SFFtPnrqxჯ%Qe2[eݡoA&]_K4jcNb< "ȥf\I@( (IQvBQ;F k^Y8+ P"u6qUpNfMS˘C{ߎr긏_vYJY]o_5O*ի!\ۮ.S^}vwQ}@ F!ɸFQP9MͿzCI>zv|VWFiatʜ?ʍde8gjU혴Yzho߬=J.V{ilI"3@UT 'ǶP^f:h d'">1)' ă溄auKSz2,i~nyw-&Fခ5B°@:AZ@grzRܽ=8tQ0isGImT JFkG8͸ן e[q^<{#FookQ6Ʒ2{V2ad͛Qk+H:K99xb`߭z CT2(Ls.WI?SUy !SeZCHKd1GZQ Bymy a(gTl!J:x8A)`~N-uRfj"Q]J6'ᾧ_QPS(j ɚ^2Ȁ8a"ALOJxy"1 S~3AR$/ mMZm %&#j9njG)ḙ$_}?d)֎ z3kZr2KIYpH?ۿmg!*QF"̛;G9cXO_8wEmY#\@C!fhߺPc6_&LӦb1X\n2#+X/j#O4-# t?J#"pk,lcTf$VFm'j41qHCI)4ha k6nEedbt t_2H~Q0?RxUNf?/\Uw @&!7#L;'ͯ'$ĜQV"X]*xeq^:~;; Ɍ[Z|x}L9m7d`ػ{+l]~=FMGNA&=Ŷl6_2wiH2b3 ud rS: qn ᇋaoA&CF^@5DF[; 7?cDD{[;1rUdX |@Zv6m2h܊?LjXC9s [mtJYu3`l9})sEs$ڜiR;il-e~@jHIaX^4 |; TPTl Ko`?}=r\:;1Z>2#?Ndr/RyA;ef}9o&b &0[[[J)33f*B"ƒ~uC ɀ$k?z^緟fl e"J:T=^~U8LKyPtm%Qvٶ;=t](zͭg^} o V~7}{' 鰨(G||*B3bBttw; Și$ ?&Tt*+պe t dE Ʋ=8yZ+AS"<)o;c\[qj[h <+`m&é+3 4KiF={$O?£o\M”N*Ŭ6pȥw݌8:ƗdI1YzYU(m(͊_P^qq艏} s<؄hݱ8}j"y=__{n8~Qcg {RtȢ 1>yjkAd\)IT1ŔuryAhȕg%sT'*>+S÷O;ЪT#^gvՔodaRiibl؍c ! |SFj_]f2r옿zbԔ6NvW'e[N }ÏK:T{U?qY_CAxc8><%.=w ҉\8w2TQށȩlUbVͷ1mr Dp2Yϣ9|(]z t g+Z9h lba~ݵw([|ئX[u2*t@ƚM¯]>4uՅ3>`9%1jl`݊rT>/e|2)ǐFz.*U/w; RhO*-bjy? 3;dP[/fӾkz8O bFaJ^z `uϱuo[<rgU^>Dw2] 9v:SFRIĵm$tÐSy8Frb*9^}^F\L$%!6 9=JKYim _jNk+Dx$=e~k#>-}u:$/+>Ûe)';WS7^ϕҟ H/qQd}q)zi#:K:_r}*Z)I}F}^ l硖}\7Ldy7PUyznNQdJRUMrq]'$?^wx\WtZ0 ~>nD )z=twy|0S2Ą[XvC3lC !QaudDN=]+PAXCaxoZk$Xa݉޳g^o\2fDbGԔBNI7׷ݽ'=@J%C<՗c:49P^2XZz͎Ĕ,E`o7Ƥ ؂p G̱mNwhL!0 -3`x8t_b[h$t`_`}(8xae85r>[>4^'/pR/(i:e]/եsR*mk60^[iÆmXZLojZr˖=t90$"DQ9(-ϥ ԕm}iU-d^&:Th;^O @*Ƶ4̪$C{O vh[Vjֈqe^'ESޮH~7, Br]Qp~q@(ת hrd_Lw'SÆ̠D?AkCgXtQY_vo)pqIr"N`Ϙ= |E'_J9fѓ&C̡;r.|x3lxk9` p{t+M y 2/"7n7(+L`$Ҧ3|ǿcx0Z*j:ypv'qlLǕ:bu5*g>N3GQsgxza杋(˸MtC"54bզHayq!_/eH*d'sN޴\<β"CKWHsnd,@Ȑض099t K̚>.NW&jR-uZ/@c@ޅ; ZEX:#=a0 ]W};MQQ8yߍz>9ނ3?)RUj;մ;'Ap/ŶtN"ZР( (k\[ļ ȑ8io_cOWTI j8ƚqz-cNF!A߹#z):D)W@]_b_ tWs6N%(6E-KT:Wktcʏ_A]HXK2q2z 3(Gϑ;9ƚPL{ٜtDŽP_C bSN׵sq5;Y_1\cyRbs6Gc iP¦Z;ʤw_?G>;d?>~N{I\v2oG\ntݮvK6*e#VXGS A}Our5`)a <>'.?V@WS]٬Ͽ3}j U{zs+ף{|G5>k׭k|DOh kƿ+4 Վ@mFk/(ADidvjg;/_z:qkFZc檬S']4@ 1y+8F,/7щ)r%)ܘ㔥ue'N`&/kkR=ABkS=~lI쮬/k/[sWN|1U0sq®-1cH,|4TO&(0ah  l}Ot!vvc%3ڱ ;W\[iva@࢜&Gc4*,R+ SMF턋d=mSJv3Yh,Kc840-#<ہzhM\ȼDIC1rKeyÙG5A i&(7hc:=.+EmUd'›Ҳ!2&Fb۔UlSQM-[q,0 O<FN-ېvC}ƴ^ksc ^ zN:{18F^4RxKh]qr; ыe=ovihg}WdƲ ?){w WlGǎװyd_ c`UHg aoKo̚=O?NδSE t yK+Mcs6 1w{*tȁd< Rj7ߠ#!Wd ^83cKpI@k%\u チ4>ڵ ~5lA5cCc(2/>"o`ڏ1,P<įNY1Ȥ+3'1{, '!Wv*e<{xНDh#{4S C.[{v'"saNA|]ͩ46NT ?20C ŷ_|867 <&/a=k*sqiH9XV9~0eF'[vp{jfl|X(/D$,#U7~7boOaʕdK^wq!=b㲏ޡ18 `Auk$W;XeqgNh0ߋ,rcr8xキwh)NvËO?u*W.*(.|kYő3.ydv0úue8xտ}|!}{C7# + !tZxͿc0CΨSxp.A×,;ѷo? A':43UB/ɂlLi~+_v\S6j}=A.0_>x7n `l G@_%W￰'`|dO{u_Tmf @$KIbU qpfVKߩl:pd)9Ǚ$JdOf؅J+z\u^AWCk.dZ#50,\Nذ.Ƒ}[H9M'V kw:hZ1qj$ hTe.eiHվ&ߪ]Y{ zYjW1uټH7FEVF8`UIK \{y>bGՌX^Jf/~=rP'_1r *8qҶ/')f>_ EI@]/A'}˫])_PA[EYOB>RVwuGϹ6\܇-+@j<եg>//!Z/d#@bKjk܏7X8g^xsyr ^s7R& ?ujiPTYuҐH'|T邎@*i0`pw-I!w6зZrj&K^$O-7\rA#ig # *ɣ1r2_P'+R`C9!gz؈j ſ,] C1LP 60]Ѱ@4ymH,2=PGvES~2Jo?2-W1G㠡[ QGⓈܻj0p=\g #P߸⮆cma큨Nqm4̘};f~72+ޘ3>bϿNxQ*)ƺgs7pQ o*$ٻJ5:=L4Ggö~=QHrB k7#Ɠ0cU &>HH~ /-y$q-(Y2^ZdB3œxZD/FN7xH*aN߀(/́'hN(UwΛal}wHa7+3x9zC]Vo~$%\à!Õ8H{x9+AMh)@9?%2F+{嚗!Ө=k(=מdMGD9r}= *Ȍ޽{+1Sp 5To(:ϲ;>&9MyXtvPRV̻N^h42fkw,z,lCqxC)o7gw݈<BWٳR fAyu1,h8.%3u {(#:rhc;671QhХ1Jnd&آRdM5eAIg‘)4_ģ>&3+}uD ӧY ևV h-![0)u5D.% ^ hJ|DG/Y,HID 'n^tJF-ߛ[6QMy{; 77B烔r`⎖:M';U&;ԍPVZK(a̮cƓG  (6 bMݻ `B%Go*d@zzW78E;#wP32T%o 9i HNJnwÍ@TL@|<(MHC~ 5a.AèЙG {k嬯[몊k; "㮅wDx~mLi;`ue sI.NBc|h9xsŋ}{+FHW;JZ_|F4Z8-fJwOdgaF?`6C=X{fw-=~Ɍ#chlc) NI 2KjH91A.z^njh 2> :J\+}H`\1SbĐ0\LIklzV7X|;bS] ]Pv1-{ܥ$C3caʥ:y\OQЗq,H0*31{av}dsyl߶ ,8 oG%Kc]~eϾ+( FPn%@gV QɓXGdcENEm8r txgW-IDžGGSy:o|CKa Ta՗J07}?w4.0zeu=ۯh2qL4W*㸸 n*'p}ƳԹ6uOT05]J/k *GQM緞Wsux:攔Ũ¢YN1,x'um8b>2S3}M IJAJ\e`ẓ;A{8cbvVvϧDiS3yjieK=ػk7(k؋IL\#Aa4 &s9d][מcN$B:$#|ӵ>}6oZ?ԕKytZ97!Y2涮Liw.yy ơmò+\%.&X5P-S zdo$,8G m YK`ɜ_mZp2%1()9߮ePJkKa⦺*WH~TkUC_N*mu]AT;M1iҗ6GNw#N`2h X,h;koZs0 wyà*qW=|Ķ~QPRaH#kJD :s^( j$;vA/bog'@(;e` <9z5GS:ga?j\;`xJw]K_%}/]eDUI9ײhх"}db[{\U[ڒљKF\-~_+I:޻6ܿP6^s~[>RRfj)eUaup[2>>oZlod)#94!WK\G%)k*}YrYo:FmsI4ph4h#gUF:bŻFu#'{`~vP$X5r5L7+ϽߎpwS8,e̾x#r:vE+L޼f0aܘt8@Zߺ.a[I`J>Nd nP 3'h+> Uڌ44R@2K/װ􎤱Lcp)яɑ^'Xܿ^$U>Ɖ4f\$I>5Pںv6>"Z1JI{!f`({zھ} ֹev{ʀ1(Eihܽ}7'Bޏ2 : {rpm$e=vwfb\s :b/*1bI4d/}>V傁{bc x=fϚKylBjrJ_PU3ekne-Ϧ"vʆz0f?7>Q+~9F@R%ì{ѿ^!h' .I3oSl(3Ʈ'c,3]Y͞,.1E}g!~eHBfg3шC$eFwd@h("0nދc;awPMUM'N!;p'ƎLFh6nފ^z f'@dΞ9WXϝ]I<,[`q]LYzq]#E~ٞ<0/>$jiec E&/$\ݕNy9K%0cFq^YY 6t+FF* ]7wO2`A krZٍ@[N8əܳfth"VQSnz4gaa8w>zL]]~O=("B{"`8E ƈt_C1.[YTᇋCY%j uD#o*'2u&ֻvYJY+)ztRȅw  k6B3ۊmbIwsa!mv"{_nBeqPPw54Bwt顖@U|pv.*Ư% OMZ WdžΦ Ʋ:i&"bxTH|8U,,!ͣFtCةXb_as2{^:x ؿlomA8SEI=W/D :yۍ oey"?%J9|.7cԺ}~t-֢$#+|edU\"Az@'_P8?4݌\!qD UKC2ж't=u"2Ah9_߫러pU>46i.cCZ8:swsAeM-A*:@MkO :zH:bqwƢNMfUWVQ|ę/MMчŏdƧ'g /(njXƎ4cZy8 +;WX3VwCjطH)BIeLD&gOGaQ.ġ$h\J봧'v1ꦌ}L|tp1#t)ϷiD/?˗*62>ua2᳨"NB%'gW`f5;O3̂7zmg K>-:)<7k xA]~; =: NwMX9DPvS"V 3وa?\oZE{MmZp5Y/#-.x865’wV֧R枟C^jR-DMuQ;.tdqSoGz6 8=%&qnƹ|\~ vs 2X$Y=xs$DbKlj'@,e}o(1B/vU|pyeXk8A:oaD}6<Ǜv >+ӽ+CpUvUH)[*(j:$~t:ֱ]?u!Nq8S558s#a8RGa}Hܐ$6Pd[곴e~Ӏ Nn NZͫh"Q+s{h;)/ iWMmrln*:*'/Mo)Uevv+{HK9ɱYRnGO[>:8B-4JR#{:Ar'Ȫ#K9ҹsN8_3[X3İk'd=Xi8Q@q*J! #t>+y1j. u̫ipӻUgn:;9VI&h+[su`$oQC.yup83F\ itKǟ-⨱5NCyw`(N%1eu)eY%r;0v4r:zQ͏ZЈOén?-d# ^j1ل  8S"FO . @Fѧ4v[3Fn*ë;+z)KN2VAMs;VĤ "}& K4fRF1=3덈!z{b<,1$0qfJc1Cc-಼7JIw*""X v;MruvsZ]EDE$o|@~}^;.[~XYfJ2 a{%N2O1flDzuK5!"67+X3X [[=vdEM˃ s~; TbΒh%@š`3Y"  qie&=\یsl'y_ ~]DH(#X@Z#ޣ}m2R],ŷ?|O y1,zK)1fy}PgH,ol1;/N!h*=$EpќӀc1!Q#j+VԄUUȔfXޟ봯C: D=C˻4U'Xc@ Np(Keq,&blo*F--p:u9( i&ADQm>ΧwߵY J0o6vgf`n:4€J?4-{5A-u|θkFhWbI$&/ߵ"6Tz0 %jyի>:OKwR~{wouVO}*+{ж.רa6~ܿ_p͏ڪ -lK~D # :pp`-"\gv>y: 6ۚm4W,* t Ycɴ Vd-H5517~ZSaW\IVr *m1AvЈ+ 7v›>;c#&L|2пL[LBqukH0kda_jߡў ?Y?M+9): #p "hIXJ umRZR`+pu%K\ML{w[Ʋ+u v41?x,>p|^~ز};CdUU}ox3Щ>KQ|O.Ḻi< КF=?|ѥx衇x_~uJП;kÇQDo+-YY ז2\zffj`nGeނsLYLLWa˶]TY0g!TOs/XزdBOC'^+ߠMzP雂}a?7 hK)h]҂A>R%;s H !VQg^ꢚʖV}p`=C:9GOԋT=eV<3,k%Ygg7:4ZHzs?n憟$ޤOû+-OnHs+mc7F gĴ l;ܦD1\^۲pCĎU2 |H؄$8H)cE C!/l.2(=$,ru̯d,;JIOuzF@ػG_{cԋp5tl($7 S2 ݚ;H f\'ռ*96b`&z`{ia{~ #tY6@l%Z~5+Ne`uˎ7E9.?,j1d "YVɉB(e<=G3cmQ=I=Ǩ|?2TڒSu쫴Hvm=տÇ ov;_0z4|K^Ws{%Ζ×?v~W,5cI}>l߾d}M۶`$nM w췹"xQ*kF-7Q|ȧä )(Jjs[Qah +Z,|qv25%g̎V9.߁!x1n8ikB%a>(%Tb &-w.DUx!=YkfgWrgԵt"=zOfluF zdrs8wt ьOGEVKttA0-lbi{ s CWkCa簀_e-q%{QQ6 {+OY__oU`}gy[-_g{ٻc3"ϭNNR2R~>G@IDATQg=]y i1J[)3g#*1g(xk|*}U_Vڋ*e(j"*0mF Ӂt jiOV~K!u;b2ۥ%5Rle%%0\eP]\i=܆lz3q.$(hs}dT$&e?}|NgHs%Li =5 ?x?zO\MyMѧiwպs;FʠZr_xAN4qr|6b:|{9`̹A۴lضw/_y]9|*N|߲~5j\ )59T#g8P6e$xt_HZ1V[N03e@PנK@! WkB\R2c2+?l2(u#|4N~K a vT#:+X(VԳQXH t;?C q1WL-CGa{F7u+mڋK/C = *ʽMH#;k ^A0m mʲ+C.SƖxgz6tc2w%Xsa?|Zݩeq0oa^M*G]1xBY[7^f`2S"A8(#hE)tacGhHpJr ]A\z0dZnA}M)˴ly}7PuG~m}J:w/Elh[oYFk1B5dsk 5Rqσg` sXGPE_TgMkF.u9*:_&O *B}CMy [4 Y(d?!pP=Wۍ,,J/*=SǏapȆ[mFR,Uzf`,UHط}ǐ _/g0ť%Ƿ%%$WkOdUk.S谞=Eޙy]`$ &}1r\ˆ!ؼ{fQ"RUy( › ]_ok}i z<2I75Z>6>TbM,嗟]n.4s팳b9Lƶژ0lPlvPg 댡lKha˭Ng'0s2ð>0o.;5gI~xh 8XaμTa1[>t0Cr*B@g쎝2M=#uIIqRHeXzHU۔z{[珓R8,M@VIbBN##?Pcll rvHGNIY8c#zy2ڄ3Amq.e&%?\H@7ΣAVcpovmyBc{֐^lmT@gr,8vdZ(kLA f Q6H@K2}}@$ų=ߥXH]!u;v>m*~M\s2^cE k˳$3ײWA0b=2]E >Oj^Kkk I^j I#_C: CIyܶc?Qv`tЙ S%Ϟe,oy8?7d- 40#ulnǙ Kk'wDJN̻˺١DZ_GrQ嚺i/؇vegNא+-Tgw KTk*"mpigęRm{UjιY+k_W19f9^)D+{GEݍ 8iO'Y\Xa*@Wh\TpG}}9Vl]U*WgE6Pl hRKE%TR2 VIB#zynVAjkgezӮnެ½ SFuyp M>H (Ն_UUͅRu1'`z@L;AP_^r`O+ލéƨdLRR\FbX_pJ2ܻɰgBpc̍OY}S2Z- 9Z5j ]!,JBLHIBEM*uNa ɸuݼ} `]"j:eHMe r \| ok{@V\Z:! [66BEG+ )&x۹Dƾ L K1``hǁ}T\bݲ̱מyrPM}Ȉp{ʺ!2VV&J!6UՁغXSN8g>ۨkEj6p o7>#cǎfGو:".X&=J[j=4ATSrڻ>*wnĕ&lݲœO=`:(9VKq~&.D[(NoN.N8Gv]r".\R:x?XړZ hi Q3%$D0ȓ)'p e"`0n ՇuAx5<.3W4~Y Z•viYEe$ nO'38)2\n^x?DUUqQx\ wQetTƎI=m9Box̅ (B:{o YoT^>sILj`~VXbY0ʞ;HҧF_tXGJ,y'ڬ6Òar*>;z<ş66 &qibw:/9*V%Q)224h@_]:r3X@0bU @[K^YظCܛ P}>qտNJ4 bWU5..ŨQ!l\U% ~{{]u?*šD R~j*Fv|I4p/?|(Ͽ*%>T5U8e`=')^mu7RubY ~hW>8YG;C+kb]t "! _2p}ma ۷hځɻlmqMN2$ Κ5`έ[+g|PTK%~#Fƶ=GX{31s*ޝT#<2}8J.E6-WmF}*2?kI|'psa@Z6.߀uS_<|`-K=SJMf/VU](/Z1f$Q2_Tban>o-5_]mp0ܻaml%hrp';-qzu-;PM.EmYW23Փbc9 kJJ6 r I,$u14D@O}'@ȴYEvP9(um;{/ן}’$P9(ٳ/\&37S*5u:nX.$ E]DTUޅ23!3A!_-5TV*!ߪH\u?[r)F9q-䐎7ۖ1uyu?' C).=6P#M0}hoy>(> 4>BVOS[7x4x4 <ķC.3/ޝb]Db ԲঀJٽsI(s(ʪm$sGVLe@x P=H2ˠ}wOɣؿo/*g°ە9N:Bϊ[iANI6/aRn $34b+|71)zxw0rCzVϭ $qTUA\ rPiQU_~^$yq@!hͻ4D܍em+o~%G-ODיXj3C*;%pwxloxg"ifq'+lkF6g2'q1r3J_IӔy\5]=t@tB#u„ |U{VTytRO+X¾…4WIr_ 1'1eU7 *;)62 /GE;  ,g]g.W'}Kw^mmł4 >Ng[mUEo/}/ӡ=]Dz!d0eI+H@%E]M5qK)T 0`6m LMlCy]nZRȫӥp@ {*&=/%1 S܍}Yr i vՊ ŝ EOr4R~$#OFFz[0ѭմS7TscFUM#Ibvy0ΗьN~U$iEQ)1] @pr.Q,#ީkRԓǕADKz9K<]5+mƑd9٧L}[هovHig巬"qNzvkAԨx!lzr~RP:]9< ; X:^}W"N% 8A6> 1jf-ېW2biin7 Ps']J]y1^•e*;*:košlZdġWn"E:1I0V*hXժݨTlU?JGvnñjrL:ѸwT m<o/SZr!'3FXmZs8dܟ`?n״c]oWZ?y ʪ /-21´4F[KFF;<a}(J.EXtT|ko_hL=Bրv\IqZ'az38UK{>nX|YQS&2ԃ;=ٿ-Sbgĺ)/u{g/LG9:yEm1%%_k%`.O*0Vo.Z#aĈ8} NGq0| U.TRuyj>c,[=a' w{ @EEgcؼ**rs6*pxZ .i GY7 $fSk1-gϟ?dvRux7Y¡GEu,Y3Oϗ}K@`P7"X2m$SglF2J'DE #ߊg.ոc y}T;c` oA>BةXߨUkPD:DfͺZᔺ>~* hI'(ˤB1 # &&臯?w_F $ $<>&YEp ?5#7~.̻2j8Οb 'V-_Q9}.N2 M%AF V΁'=1%C00%91],31/[Rm˼h|{U~ң+Fxgfˠh*{V|N}%-ֹmX82ãfB.jLб/^8ꔒpuVUϦ suK؞_`9\,>s](u|9kO$-#YEtٴXe!pUX;1݉a#dbs{`ss/u1Z6 J$_k\:?J]'0眍2_} ]w1WjX5.Sr`R: K]^KX|CFbpʂV %%nT)j+XmȐ:M>%O )T%\a'Isq⹉ZsSƺSqbv\g޶,n;N'kCotOq_gNuek*J0ooT~*ƍiE`_ϰMRXXڃ̫oGVTI)IGcP/_$&ҊU:i3W5AI;'g,l7Q^ۼXj*8RA"sRQDt%*<ғJfZ!*_']MK8Mh#Z|yWY#wCv9ygsQפ K>SMa I#SFHേhKj|9?\JWKxcΦ@'2-24N ƫؿ O(>^`/nͰR?-'iTق<\ {M-N8 sa;] l)MpNDj9I151-({7"96et>cΡ(ĐsT5),WXش4)TN\mQNUE[[)vY/Hŧ# LgC~zT>^EsDY+m.ٟ'2~/E檭EK\^?n/RkUMVy@U[XļU|CmuuVDV *u~4b~1m|?6\dҧ!C[:+VjEAjWDJLUQ* TX7[mlv+I&DԢtfn4nTFi(Ŵ".vG+@^%9]5ݳq5a !ʐHsl/[MoA"|j1W1x+QŜKCf+O='n î)_do倸$8Ce/y>z]IՎʯ0| .*#̃Uu(6 t7A@eO6Y^=^έh.O5h$}VDL5N'0 ֯#(Sz2A֭ܘ@З p>%Qs"u:4CA-://wg=BRf!jSWtrؕ쏕kyB Yzr"Փo#/;1ǯ*~N@QtF3Qr, 6'#3=֓>¤J˴kr<60f̚Kbo$aY*}zc6@Vfϸ NӣJ@{7WLh7:OL" ZrRPJ1^` -'0腰BZam1կTU"PaK)-2 y:}hl{SO`]T5`͆-38 L=֣ ƎTD}#vb]ӵO 9\7]&޾wl2͚ls۶u]>֭^NhA9"ÃQc'bւ, pQڈG#QTY'>`ol \AdjR<>8wM,J( ~q=B(YU$&4$UK}۰f76ك~`DA)4Xƾۙc@6*+cl?7X)l3J1lTe$GVYg0^n_I$tK4)?~꘏3  j&g2qݜJϲ33BwATyg5?|QӐn ÆJ4Td4=$nݖfIk\l{05aѶ\0  `>s j]ꐣv/B9$Hƶ!+9(!q&}mhjG;'g*@XxcϦ($sJI(mQ"SS Tɱ$=A5>l .jݣ̼5$%i_]ī, :eݨC#=sz,*gXG;:QhSFM,IW+aY^ԑ8ةD~ DiF +:F05FmܺŸ Q6 .ny=`Yc0{='O&`!x5ڢ3%Y\hcKE1cE9[7J1sAPEkJJ-]}Z䥷CsB RF QZLDO/Z]ׅX+.DzJ+Rx-ߢ5Aܼy3!-A*Mq|Y v'`үou" 'ˁ6 %a_e~DqۻHN!96yh#x<AD闑C"n%vHՅ>0Wd>$`ص/n/Iinݽ~e_1=XuTl4浟&ZU_&]-hjA щ Tpg acj=^.2 j4ܝx8 'O I0qqxԹS- CZ,"QK^ wb>8I7hSmh9Aѧ Zt!f͚whȴ1 /?}./˫Nn4dx~C0U~w>/CeoYi$D]eJm~ G*J$s v@VY3]|긾QϲKA[c;Xd J}%YQ ($ 5*դ-'T?ۚm2ICzz4_*M;jb*RyMytkXL8n2`K G N1MI4tFĤo5%?qGU78AwD9{?>_V^zc iP1X= *_׬(f`['tHvj7Gs> udZtx7̀c-6@ ]lI4t(@RߨB̶_$'<3U”zP:3 `j^{^+]u;En8y=6;ٞ($5m/ ^%K]۞ھ˧g`R]&}AR%xr!jX݇_~\=fu lOz,ʏxPJYyk?*rjkRc}nhY9&9^yi/CDNF>?s宂 ({Y=u_rDF+3Tz @̓kwvbAʍ*U# )XrQf%Joڀl07;do:"oYBf%o|G\ RVبNMud-E9Eg=~۟Ri - \Xdݏ-;u T6 u0/Q*=3腗2e4jœ/W d2I]~{xJL3g`djߙo_)6&-~}n ,5CG"0x3Flm^Mn,v%Ę,W;G{w780qR 9Rfq< eZS16?8y+/|9.\!9Ka޳ l<ـJׯEtda&Ms:pS!lw"k@Tl/kdaĀ0$2iKY$ۍV ܽkv}e~S$||i5\Q˝|\_SЎh`QTX]b~ֵ[4F 1uFgơ"E2ohϪ Т5|fX^S*58MfCaǯ'1h>f(8t#Gc䙴 53;},AbqC5tdmBY0T"yر{>K"F©CHĺ8^wԳl@9K~j5vT8eby |I  hVXi?!ɯ'X]]ϺW7FQx@+ VXijdX;pxPW?OFѳT NjٓVO>Ri? $+<gI<ħ҆y ~FN~}=iإPCNǾ\ۺ_:oٺpLVE IԖfc91sa%g3hBʛ1c`nޙpdnUQ7 98G 99!T6JN쇺]UQ}u Y^ c6c|$^FGoA\9G4S~]TA/s* d] (>,/5S0LG*.L(JѝA ?WZJYqT1Wx}ZD%lf`IzM+Swc#d|5zn볞,haC)GCY%9hIk_-5<<\Ls*ŁT~Si[NYZYc >39 | 3 KJj`=$٘8`@;u{tV+h@HɓTH^cp__}hؤD|٢`=B"Tٳ_M#"30w\۰<Q`un7u sD>:sЅb+gY];\@\}{`6\{g.P 7 ի<*1 Έk^nڽ{?Coݵ~?0>;͉TJ*!6:~>'.?s@H抉%;HD|NXlG˟[W7Wd>UrNeoϭGժw4bQҢ{7-+L cބ!Te3Vo*jIqوb( 7<ϹW_0MhQ~6NXk .8ebLqq[de!y'+@)Ѯ x:kb`t/h]̜<|6njgwNa a;kɼI H9}<[wm (&om%Bhھ%`D ž*@ZGKYwfb¤i ~_mCI ֛{wSqE96ϋ:xԘD*R ^j͂Ki$> Usݪћڎ@VWUU^ j?N~π*(U^ 7ږԑ:t0E* 1>=*Sg+==>tm %h/~v9Nsơ۩:d8{RAUq =3 Q`EMM`/,t?v짠AϚy/rvF7gGz#$H$f"|LY4GUq> f RK=Dۇa#IQu@J&;mbiO& `O@Fr F eSס=h.͗}DTNcIJa]m?t#ٞy a.O؍$yR!briɜ׹uOVr L@V!cHT).ߞ&)6T fY@kw?[1.u`kfl83z-8j!8nV(\0wЧ} Ο=Eq7G]Gfߝ0$` 0jpUXi?˪KFt_f?Ye'E]ƅĞirBKuG_' kewۑrX(%`=oG*˝p' ɓa@xg*-t64CW 曧')8(ӵ.7_Gl%?:O~Ư;C3}+ jŴ_˫oKe5_Ex̓vHX:Ol0¤~3ˣEߺq+j7T֙Nlj+~(h B9jX&eŽ*朂b2'hnNT#SH$@nL+ v"٫ǸU0kD=wMNGs'b{r/Ř֫C3 ;y f&8q4"#;E5n-$ Ssi};fǒOCFST=z0g|ZŻb`hC]q&rHC4Ï>DіEbEU}iq .>^(.HcxHS;ove ./Tť͘ǂ)Hiw᧟?kzŅ Q AB^TQ^ھ)RZ w#nspI ̙3rgΜkxM 56},~?W^MWY ,VaתeL9N˖&C*Ai.VU+$@UqSuy p%S)qU,"SYp:``ɩf}aSֹd;rI›jZQ۸ #]5@ej/6$ޯ^6#" $)B> lt[H($.ƶM{TLrɽھH=XHU*kir΅ck-ׅoKp[6FZ<f5jYA͕s`mSx٣dT+>42jmQ/em-2vP[וzLyPv9d8d̓ td/Qr{wVļ$b"@5E3;W"de5yN %[4zx|5TXv Feu x\\qb]|2jheӒ 3SF 2Sձpa0ecDZۉ=GÖ#2}v%Kau%/EMB&sMLJ42ڋzwfVj5b,%;{79(OIOnڧU(GHP.Fg)WWMi}XZF1frTdKƭR>K/%y̨q +cko*aIqK1hJ/V{3]xdoہӮ]> K^yE Sr.ٖm)4%ލ]B&MņR)G;]bUvݛMw{foay>;s 38vg{8+ ?}zc,wı}Hϯ t n8A_֞sl[׭ jᢹ3cw0x*~U_Àc%6\([M63)_]Vߎ39ht s|%!%= $fB@Nj.O96vdvFз Y`1ji]cic'# ^ZI9POX⻯`DCk>~ٻw' KKР$xP>USt`YW5^wїN |p-]G:_sV 2CVO/oe$Qn֑I/WV@?ZӞ.b߱`Ufh{1!Zs5!_̼s|Ղd{=֊ J[kʌ#ĒcM]Ge,E@$,ۛJB|7˦<`"ώLj*VT1~^S.TK%']>=f;d ÍM7C؊^5 `'Oؐ gPzfƟFJy蛛!!1q5䘩c7Tҟ4> NL ޾eLr~(FCNtTudɺqfp[UUֱ'cvzAja_k:癷'`[]{#C?K;C{)d~ز_8>L+ ȞV@Y}Y;a ;3-0ӧ ~E ;&L ?>L:N2[)I&@齩WE`=zC,L,~ =6eTS@ʇ|]lRP/,CQ;-W{Z~1<#xѧO/E%޸5>UeA*8^m"pjPN' {XbFyM zZXRĀqu3Im)Pxj~1ޣ9U*3) 2]\GIN53+4lZ4c>M5=pxZ\XeH.U{0B>.x^Oh"V㝜<8ۙ߶7Pαc scD e^#FOfT(IPUR)7 8.Q;#9+Iyw;9>S'_b:%<3qjK,F3 e*=KPҝl2'{+|@1 TD:ׁt^m!<8>q02Y\m `ksE [;7:hzxy~,yNܿqc4Tu*(R-,LwV)`\Pv 6֩$C U|j|O**^O#%'=6U n~A-;:W)u}r+Ä_/?6'qGTU6҇j#mj?q_T쳖=2\m`eRh-&_4q.ndҞ}~xx0_>6696#G 9Σ‘D uQqi2* 9EeAҙLZj-!惚"P)&"hBE ]2mJ rlH 0?n<-*Rw%>PK0c%W`mxJ{e;vBs]VϹJQ*?%Yf^EKTw $G<4t8v”1{?>+(Òo{ L0G'{$ֺÚ|Jefo7/׭åw0 L/vƾsvd RNOll^=R qd9PI>Q'€ruV֔P rOữ~X[|y?NTIDmY:vnxєNfVn3 y0enT""ϑՑ"* [Xo۽?SYW٧#|{H2^Œ&Fvbo`pU>RpYjkXHs T-!dtgR2FML/b"0չI@`]7Nl˶I;yE&[mFS32Wn` mpRk^y x)u޹~#KޛR9 ^)CJt8eݕ-[6mAFPX߅ x79aΞ=YUV~[ޔ1:e_oXg %ʯ0Z\\=Џ^/.g[JJxj9]/?6zqtexJ!Uyk|o.Mt 6-ϼ^d8 +R߳'6|ʾ=Rie󦵐Ϥ `Vs舄j9ȉ2"UBϯ"[v6FE_@{GsT,7™2me"$#tP2{a7 aXؓub8ŀEYK"$yew+r+8d݊B^ǣxtr>L`u(ɹ̱H=^Di?;'AGF@X[dVAPe L-;[IxQˎ}|+%dfT̍dcY !9n0e1 *ȃS'υk|m1Zb.DξTTX[\n~=),;J2F wGh{.?g^RY2FZ1=Yo| [pZq Ӌ<K0A^M c#dm UݘVx)q :Kr7){0PRqsvGlwN@pA19FSf $\dh0tPge9x6·31 *O## akk+z*!T6gap%;sl[xv'{kסz-MSz-wrr#k#&Ħ)$a&B3"r&$Bfh5Ăxc;Q^Cf Rn,~As\Dk2X}|د6)䩳 1P_]@)E*f~=-@םlW{TgId_IQ$~ޑ.,Ffb _#ܫ{3`]CR ʖ3IVwh| CJ-|2`AY†dF .ܙ#vX6"?5hNoΞ-^n]y3!p̈́>x;+ۣ)ySeM|mn\?{ .o:skx{̲g&SV) VXOКA];#s JNU>jd0`?.B|bW8ϤWƾ?zLL_o*,]=:{QȂdJg!2'Ϡ#Y|#xχ7^©GЧo ek;%kٓ{ikK5YGGtСEڹѮ ;a&5kG?u$K kkx2Mp~qIgQ,W>zSj@-/7+fbuyV8(4=FYmΝ3##%|%,|Wsk0lmX+%}وa3Zq{mߵf@W&E6%&$R*(+яJ(ZgNy?`qu\>yr\yyi0ӷR%*0D%6~np#SzB{TUUO$뼐54[E ;ƈNcPUc2U@;&) * 5޸^XoiKG]+)ˤ5V{,znXO)kѕu8ɣw#ERG-#Ӻ-0jigX]r:55V%HJ\1dR _73Ic:7-{xg}3]dwWi[ˉь1lTqm<<9uehx㞆 v h$E[WƴPHjxe2O~W6DUXYqUo> H,u{MT_Xԕ1$0idO7׎>ViS6yr?*2*`+>cӖ&)yIj{^sLmك_Go{u}9^x̝ ןvn^ ll䟶gk!!n'sd`A0[nvs\\lH6QwyhjAX0xBǶt2앟W5f~`cӁWb ~h߲"bpfǜii)%yzR*{9%66x)c̞/e )k(6CkX50laLB2a+o`:_Fe097r. w5&\9_|bFq_ O٧N\zkz0S㿪UxSJo ;GrvC3L:KL"8\z>rJq]ѻ \;'Rr(BiV_ eO̜2Eob`;]|ddad g|ACSk6 PZ42(\`Dtz1=$2}![u$;Vkvpܴss ]^B b{''W + B"IFh_9b0ɭĎm[le/y< t!K@ߑY{㋰z$h$ɔ9|'ɢ> t?o+/z"%+߭Xu? |rt`l;'|' kގHDnY 2ϜK@Qi\p2<dpbЫ+}C״GG_re \څ׫O_|շȍ`{Oy@l93qdX^NAZBNҙ > "<]Fĩ3O-%5b-%UCn_K׮ػc3ayg4zff6ad[ 9I~tS6?itf"o'+D&Xvm(sHNDbAv=ⶳfI*3{x4.ٖ RχcݟDDg_}(jcmrRg1auf>k#: l\՞gMICw飥BEyՕ|~;u:m .IJ'jϵZV됑MԶ`mG9? CU@m?"3=TS4)|b-d%6P7N###8fpd ˰$A'K&x1saϊB;s9kVf`nGc ^aA'%2~WI ȤBʨy Б>{dᳩ_)HHJ |1I?=+gTS"\?lctqE1ԫJ'&ysܭ# љoKs^]Ebm=(5˔<: }or ?QwNRny>D C"y/o޳FN^&HY#%^ZU7=m `!\`.*J>&"lJ'׶RaMX+k@@|aA>FǙC[pax%;#%ca;r*1nH s.EcIۍ_U0sAQ:.o, y53-@LRo<; 9h+1^tL$Xy}ȜA7ݨTUsقU>3xFuHx9&HzLE +M4~&++bu x`cwkJ1M`ۜ ͕nvS9|gq{*41!K-y "ϿW_>X2YV 8]fp 魙A|7-L էWKnu{O_|b!l/~XIbW "_ 9Ɠ`áio0e3ߓi=,)f <2#g=\(avw&κn* k ͗?쭕{z g0ktz"_–`Ic?˱zr)w 8ٓkAuCzE]I )Aw=67tO'/"4 N+|ԩt>x,yia.Y ,N3Llg |)tn6CISw/< Enj@(;;:u[ܽ[cKme~L`t@>Hyɿ`}wb_rJL9x6C;}2ViT$7*לP!nd*aLp-^Uso!|wSQ{*p, ?f)lH{SGu{TT6W|p,ph=Uߣ1ɺM 3j؈pq z3̱M bbi"AJʯo&Pܵp&h VpŜR#%Q6ǐ&9H.Wr#*_ߓqhZ!QH.cZb0 1H)2#+4ףRIDt=ЩCXPqJ5)@8?/E7;l%q U>Z]\|W͵Ͽ*g+rRΖaUj7׳}"u,jsE]րɱtj46RS{ NBA M;*Oyɗf-j!/)a:p -}Бpcڎ/uK5fi%p"kok/"d`` ,D؇^1@HpaL``1 : 23cpҍ B;g̖Ϫ Y:z2kҚYAO W)#[V~#GR^p=QWgk PaJp>)I VN1F0 3Ai]{ X,%3zC0stÁc1̝dz|TzҰ\˕[;pOhOBMu-6oL5G0;PyѾȁSnPdscvEfa9R}%I')\frLM|3S>A_=ud>YȹԁF*TJ&ǧc'8}x;VioƬYdHkw  ;)9slvs}|I ܺQZl9X0`;)<=Zk=; rܹ гWJbHXKkA~ 5 kL^'{ DM$~0aCdXb˕NL4`wk>?W]ixif+ ?_j2)%3'_: "F;R0)?Jyy (Ú//+qNg}wuHSfۛɳê;ob]m?QoTV9&G_>*,erȿLkz>*f~ڵӋH% RyX!2. sQWM5v0l e&R{+;̬m ęxJ h[&z9^65}>ACG¹P s/+ҹ.Oa;7*G1:qw( /s"_XY^KMĔRLG@tL,>{ cRahyg9`|ïHbHEe=v 죶o9J9+'X, `Uuax`t&Jzuar)srv'w ¯[G?ftli9e#u6A g*} wz֣ 5G(mt;@ӐMFhfdjS'QU^|OOSh ֑ ;CC׈ X_~=Hw荁AA8a4Q_erj(ǗB>#T#B<D1i{w{?Z&;pѼyJS#޵'Ɗ$ُLb#嗟V#QHt*e&\E;sSڒ2r1nUM/14R'GWj Z{T;/> |;Gᱧtt.ܽiAn*" CHrH~c)S{|40ui ԒkđFf#ZI}پ6sCBJ@7&A94xl9RPp`͵X&+GK|\~-/]6*ۏGFv"tj΍cNNˀ)j)|FDr1ZTÊެU|G =h&^)¤XT*׆L17z %ӯRg;])D FbYErʘ4Zʸ1`ҟ3GRHoj@DԔihyߦ<[~/^#טyb"{w\sjϓk kȯG_[{h1X) *Vվ?d5`}INPE'SQcj ^BXRρyi|glC;.̓=_g"S\r.3^*oim;񵶽/Y wgm:he\Λ? =Lal!C?_jnտPoO-)5"94a4_YO@gfV6/ǥt'+2iK΃uHHQGؾiD#EEϝߎ0A3J'YK/bav&|B81`&byf"9#& RrJpr aDf4wޅO>.*+`2u v¢J:򉧑Zi %3G'$9H g!YbKG:*F&EÚ/jQ3N<n5^ 7ofݵizVha |YkߴPׯߨԙ3g jW89pٿw2/jZ˯?u_R\@.]JOn@IDAT7?ý-XYo"ka;>[뻥28>S־[8GPv6xq6,d_}x$ӧOe*-y=w;qz "~lY|}lk۽egO/J{veyRBfؚ#[l%u8o{Kė0&/ 2 +AȑÇcҐ56Ǣ/0ӕ@ȓ{xCTlÞHNÌ #{L]:kZS S7ͺzqPzw۾8{ d\LctqEXJL2]L0ep|ᴑ(籗(Q'K}SA[нW,srJ%xx_3ů;,?31c?2TzQ9Pp}8bgODDǗv/5j P ;rTUBÑ|8< K」O5V%+L(ݑ>#ot_4Lt& dȩ?EQx׿Wߦomw~yۚ{ ӣL5?ukлÎ N=qnsl.-gOFlUHrSg}{!C{ecvLhYGgueo='R{I2l'HifA\V}1͐Beާ8m&LE\":V7[d}Z]mSs+0#7Sdu륬=k뎲rŚ'@0[jr7t]܍deÕvh'~ o*2C_(7W֮j$w7Ow9nV\5ꟲ6=%kog1$`ܝz|Ϛ`w?iW,3}Yo4W3o4᧴éG=pc_%혼1q^K_|TqV.3cҊ]sWiE6Uf]L+_H[ncmlWN>zAl.:^ͧh  Ffnyuȗq?҆gŋ׭ӥ ~$ޏP\Z߰oWl\/W'J,FN8-~26I]9տ?N$dWL۹ËKC"c`UMwi?ɵ-HJ6mK}U˻E}O|U~Ԝ8\whͿ V$M=I:m,O~FjZeS䣬jՄ/ 2 W:.d=d/s NuL.Ô˃ /|QTe0r%g^TpǝTV"Wm|R~k_U򿦿:_cEb굡^GMME6#KSӻL#".c+ j{I:U}д^Kտw2_@RZMޯlR/S~w<_7ؠ+=ZnD ߽w8 o.gK6[dkw-YV>mfcf ͬa6w;zTﺟ,-ɐd\ۂtˆQ3@E$H5#[LZT*-٢, ]·Z$kG>^w\6PHlώ^n Zb_؟@_gyQ`Z~4BEFihzL‹ d.Q{dIFV@s1bB5QAVI* e1 ]0 \4c{!f 7bZS_J`#g?_D77&nj3,%BQY_ʎڻ">8̾/W%l1u̸평&1 ]u{x6kXQ'02#.S~/ߧxlQu#/{ =hP_)_mY75p-Ѓ8ux7}9%֧/hiLk>e0ŵMZY&!ϯkF-)S*YZ_(v#iY\9??wi3R nBB^dM2jͳE;D]WQM^WLз/YB?i4n)諬~B,AÇ, )i>xj-/2v}g`{3ok]]g<Ą82ּmwJ=s _5IOB%.9_Fkufkv[`EueL gCqy5Ŷu.$s/ {!ЮCaFCd-fB5+TP Ba}9}`a0ʹ B@#.!΀.PXq AakI$Ƿ+ ƖR¯oni}HNa%6瑘Y7\N6T4b0\(;HR$V ?#=}m5eD{̄gUy3ĶȄ(]9uCo^|& 30Pk,@q$ٿkĀJFF. Ohd6qR YVd;_ ZOUUm#{[2u?XD1G2 _QhXۺĤ8 ?g"uޞXfi5#צZc%S1OFJ2τ5X[2DR)&OK_L|9YHe~j~r|瞎I§߮FnzN0aώ_mIhkV2BŦBcMʏ6qdu7wv46VjC)Z=*Skё!q0;Y }{#+LF98&xDbh^Β+h1Qe1ƌa T8 >_ѱ{_^M.d4qP$v˺v. =g C--> CƐ0E.&0#o=n]0d,?c-J^%OkV7֖E_is j۶rwuxFT L2X3T+|^ey| \߯/|xV ozv߯e;L&( gG{cF߁\J2Փ >MO {2݁.mOs[i\*u*XU٪&FTy򛔞7OR\OK֓ءү "0Lr*8v!mJ 巗>yzfb/nsOڑkPǖؗ:OQq2 ESk  w/ FWGu-Ncm5akb8r9}au Ԧ "Rum6^U#؀w*'N/~Hs[nu]n[^{hⰷX/p64c}nXEkM+) bW#W[ %az\7Jv|ұS/ Pv;#ǩ hdc=pH셔HV:mrPq&a9kf~ig/:"KZC,n38U^HKKלt""6! 鍜 բAVfE)=ZP{Sٿ82e?ߘz<}2˭i@oMƌ:2Az 0ҍ`N#BBNSX$ܜ, ݃XD}ya<~8( f\_ 0jǀPwd$Ae{fd}/d]y(LRS > yFoe) o=M:Õ/`UV95شy+ߏxjE9`{8X _^u@GO?IO} =6`ʗ *Jq;| ;pof4Rk[+80p(k'JMbBRsZPRTpFk[l) w>sT ղݧ)+;'u}raDQB ~ڸw͚ugL2s$s׏\IשGh;8w!CwQRBFزa پ39&¢|F7Ll9 ̑1dAʒ4VRR&VoN?0D!rcQU&k p"<ڥ#*k&Q< (ae+K捂 Y+\i-0#K=46d;i&ܐͱGBqtÛ70yL%ɑd* 7>.x(=:t\}`eeD]8[Tm;΄a٧5 ˀI -A(ɤL\<|m} QĻg`jQpO@"v#u[7dR;.)Yi9~*פz>Gtd¥>Jy]GZ~1 L yRv?r>':1h4ZӟvNœS,D>@f^]W]_!^JmQ=uر{ @^d`AaW^#= P`F.όeE$4n/~|*S()6wŦ-k0>\L$k}ؤ 8~6=}&`emNc긅v=J֊ХSG$]Ns=ǝ2ix~'x7g.GaY a6Yg:xGiC כ$$ /2eO#ҕ8q4}Lѭ)e=6n}Ҝ1xM81i;$p\=}Yb5%;=1rNöL~)-) m U"07} c=Mo=Bquve &5,+3p0ǥ'm&NڸI|RT\xW?rLCYU4HPmG @{&]8v!d|uMhAj\Q]G*@Lդ5 S; 1Ҩ) |)^픩e ^GMȑb 2׌4%TioW_2QSh2H5B1 8}_zhú/ѕ-F혌dJ#}%~8=\JiNa ̜6#IV(<<]kEl#(IRn=94.:|\9l""1.'CRR< 9 |pB4+=Շ}?X9t'PVu7&k!ttZoQ-w ZÕa -+\YJxxW~.` :͓]GbRr׵r_\nYY?aԵr\"/,xYUHoH,~s[<ײ_jDkerȵ"c)hoIBQoz;΀3aQ- rfgKlٲH/ ln!q&{o؉ӔJfO?y/+jVtATa_&E96BߔåU!kuKk ҧ*A#kktETTꌨŭnpY S0@H&HZ8 ,V =6l7BWj)VSd#{djO 2R`caShH(kXe9vow+k=5oBͯ('SגAho'OMi)ozS6x'i_5/j`voDY:t"HгB;^dZ^l@VX f@Kkk3tKƋ/M/$H3W2\ 202fdm\厑#"aCjm3N'3(?@?4$ftؿմuגp4.UǭR2J"];sbsxއnJM(ǩ %9l"Y(.(GEmL)ԯ; Y_ܹsxW+md_avқ#bJAs$̕r;>D_ޢ? M4俏0Myr=:ҩa;rR|;lKGP* @ 1 tiBY غu'.;VUTmLE!n82}{?}9Y(;oDzpú!(3mOֶ#A 2V*0(rNNP |1fvYM QK#626drz%.UA)[t :͹za՚UYˀ\XqwK4;Sg~wL,^N$?>>m%;jrPVY%PH}%vٱʤU_B!cۦ ]RnQٓe:YXYA{u*R}:5>;kW0?U:D ]|pr#Fg'M^ [.Ot>?@~):>Y^@߈(\zd<>j%?2uAU]o֔)HK>_A `~*-1]ӱl~ɴ^{r?ϐf= $I$֪V7eßzⷾr:]%L;HjnFOomV@V9X{G"jbX 6Qwl$O!(eW*qs{Wq-"W`r0%$3QzըR|?]gap4&tɷ4ʨRRG59A`:gf%s`ZgLϝTg:veCEy005yC q?!=jBrEʙurǙPB՘ *U撥nٟSٮu䀒ƥg˂GabM66<£U6ԔAgذ%ۅnB#{ad?-<7|A-DOi5 @~NcW&}"IX/Bo%tyU48 頞Gh.1d~;Us/5TDc&)NL1 (zᣘR d(';nq66֐(HPS\lI>n=gh*>a UhKhrĬIh*օ|(gZ 1ba}=O`ǖ݃>߈=_ttާEs>Cgs@(:ZۻŌ̃:y ᶞO<gZ8]Vg̡H`y9 Bo̦.Accd^ZCmK`]5c<97:u׏>D,Nՠѣ/9/so6?rʑ9OC# A Cک8;Zї`~&՗_Ç0zK]Ecf* Kkj>gxީ?= `):wt'(,TO3&g[Ji v4ĝJ;T4]3F ҈^F@+&hAxztSfXs3+&+T'Os`mf&z9OWx"j­_[٧)$kU?avlqNlLEc1 _|1\m =EYh0!u'o(N'KVcmLOϵf;!@'fJ]IvH2p(wB cxbȭ3Jk7OĐ2 }旗 {^1cg¡ Dعjv>Jk2TZT::G]2zt`Re1ve~v'K~7].ӨMä'6Q䥧R~HKKVTs?2ϔ4NkG.ْZb?.$ѱKވΌp9ރw?S2**+S2NPSRla|4?? ަߴN; )jY+LC| u_qdgzb4%3;.g`ѫ;Y0a[:ܙZ '+V4'Yz;Wr^xlp:Y#SE UEJSsx9PSA՗kvWʎ^$S΀k-G_7GUE--0(2 BtQ eYtG˹"7<e(=an]۷qNyFܾ#.IcJpe?EsmXe\qx'Ұ/y/GH#&l|{#g '=# OơQ8F0Զ{p1.׭]}*f3ntHM2{:.tԖ,Ēћ!WJ-ƃwL"o323;&tZ%;;11OgrK:x恻a"}OF5UT=HHJپ 3'RV~xL~}X:O;›|7]rA,X7<(Cלv?TI$z oqtg+ɄaQwǜ1Dvh[[܆/kg0wquݷ_(bi @5 PvП޴'dJT=( /~3OjT=Cb<У/Ng0|ijn7*LEDCDPpeqw<ۦA%ģ qZ3Oi%Ǵc=ѣfYw_3;#יVXq'ӏ+ VKu݅:sk^sprW!+y77,Ն|!ǘaoFlWxڲրo*A˧eY;}H7o8הumPq?&ݜ1mG Zm)ř#Bk';e^S!ൾIX<7cFcOB{<ԋm61amԅ kpWjB/r,`ij# `Dg:=]Fr?0g| μκFh8-f#MzﹺVOVc-հe,?~x\mqgLy'iO']gѕ6nC/Z4wU}<*ϜQ ٳ/1A\l5gr3>y v:zUǦ\ )U4Eg%{R-εwu*븆/C/7:vXJys3\51YEWd7 ءo칪wal tJFNBdq,c<؉ikG imi=>PC$K$iMif4mYDQѡ5&(X j hAEM+%܌) 8d 0L D11 Jpؙ@a ,(w nǑÌx8_xc&" q|( Փh{M)UKsZlø(ؓ1qI2#;wm> ;_|9{D]n7 QJ>FElB!YPpn~fLCNx(=M;s~*ZTcIzPd@1"֬`{?O߯<s5NS)>L9f0CaG#8rRqL@Y7SၱWIm_ݭa\޽Z J> H3OPrrj=N[ӧގ鏌0o Ћ k{ (jvd0WQRZsdjK'.k-h :wqwLZ=sS)4a@9dKK ;)&퇸};N@锹g^3t@?~.xO hFa2;' EW`& rQ(1Gzf#VSƍE^A>k SV982"jp-v J3۞POf yaG)btԀJA~?Jr=cm\\.ܷa1B+cgAx~ԋieLu\~8$>}킮!JeG&L˂l<⧸c)JtOwrXH:_qK0PdǠ YK%Z#e*x.R' 7ԟCR|"܊Q.CiXQK!vqD9=X^ǏkZ̅}(3$shwT[[ѱ8՞UnZG5Q#ǴzL/&#VxP)0-%ެ$LO]ȅ$99&&^}zcԋ 'Wp$L]yLgf)E쨒XlO8 'ѩ}jX jPTޑQxdV S>!0C$OqSPii-؟x.d:2&+Lp*=i(dsTEq5{tEF/ c.5H}u!Nh_Bҡ 8nh1/GbF)BL >l6\؟5]>U˪]R*[ߕnԽEܗ<5̕sWPXH&nܓl~})ƺ ?-C ΗRF&v NFi9ztʆb+;Gǿc ~Cߢ1.ycO!ciŘ75!! ͺM-F w1!4,m 3(!om)b"+&, CL AHi,f<47þ}'ee<UVWVU?AOOҒ2ʈxԜ)` }#|Rk})Oo&pUϾ,6yGJC} Gݯy1ש<ӛc'zFFJU 1JS+/2zSgN(#ЊqMirX` W;ONgB tZk)gM%na4]piad=w;EZk\$P*[mGL[GK3Qzp.,,j k1]6<Ѓ,2b9%gY\Owo54aL_24(9wEui@3e`c' :ƼloVb `YK^, Bruh֩+!^;pm' a[i|_㏔uqU1$ 3j4r6!d0H'UmrHOOyep Kr~q6>|0ܚWYh q7rts}Wj@5}Qv5h nl:Y3 %B*R-A+̖{xtWkS5Dj.O&l@]cy>a5TY'N:r)u|Ϫ<UYVҐ[R%rt1Z=*~3ckE$J,vR>X]j`Ͷ`wR<`bm 3PS̔2~ɩi(=?Yi'oVɥ95θ7 Fj9e0;ǰncs5wcHf9 $/#=eR!h1=BEFÕQWNFxVBƱ#g_|cơ$Fc)D| 5. @$$2΢#vZH0t){o?y`mx"KV$r(k C֣io061ΰt `Cд쭦QHM;:9}52'N7W'LHػNdm:Zek ئquW`߁hX|el cƋbBRGk8|8228s)e  v&2(ل:P2ՑɊՔy!=}6e-Aed"_OH PY,ױ.+An RtblPkGW,g@+1F>Vc8p TY|^ 3AkϿBנ(%Vߗ|>d kd[<[cxw DȞ-o2ިajjNc3٭P09y {Xd&z> hQE䌑̶=L4;8\dhT s_}1YFvud4csJ'|zz淬w ͭ ۅ FXqt6p/]LwFiqa<ЈN{XWC4Ta[QNqCdt v]fڋZ²c Q: |p"쐓`nm{6P4n= c$L7$+hg Pן1WwxOt%[Jg:!%hc Js'UfM u s3 ;4PGΧdl]F̕ )i* sb!w1$6 Ʌ_ *^ΜuM,~c]Sfe+Ω Di{lڈrN+S74)0A5/I.'MNtRƲPG n>FGc:kzLIEm_B C>B~1fxP;2$Ok..}1.e%yT @^7`%d[Mn8Β _׻EFe9M06t":dP%Xg&f6nB'p\< צ}쑣vtl͍adn/d$(Հ޽?kO 8R("g[*_Q \F+:Fp|x>Q̱`:9hr6Kx7⋗'c\ /pLZRf<&FOOǞ2|e;P9@N=뭫ۧJ0zQl m QWebWKs0)'WܮA~fWcԉorE%hl, IGǸxC}3::``/NfW×Dc1u9n8W[~~^[ RRBg8 -!(q׈;6cU% ab|vۗmu,w<ETeK.hha?a=WZr_1vhlF#lg^K,JGW՟=k$,$ GX5'Ȭ,@cY3V.\r8dD?<Tl0,ӟ2WP{ ¶ƕl)yKm6R=!ݶS:[r, ׮BeiLC%>.ǜ~* CE,_4F s;`uxErfi.;[ۏ{~qnwL;&q8xH8Pp-~OL@ߓ9w@Y;Coux_xfLq]UvpO! y ୗŨK#x6[+WEwBՖ\j̫s/@RaK.{C~ע;~HCs9謝48Wo5c3'ThRXgrՎOŊUkN@-~h39=Vd>Μ<TcVHdTUX@^GSj0*/+߮˯\`Uk2ŠW{b`PJk=srtB$fOЩ" k)X<ؓɧaPTѻsrg2*3"#`Y121v3 =p@$rBahv޽f}Ef6~ vAߒcE(_@őFN}Uf]=`<_]Ym\߇@+"C7W[kңX#AWgaHP_7|<#98[̶([7ÂoMy>%(Fzt6iL)j}qOY|FZּ,ZO bH's4TQH<+6mڀ  >$D% 72ȑCѷD $u=ѳ(D[6ɭ?zBqzڿ/ێ]}<2u4نs*a#e;|t7 fƩDP3`['y>6y%f:"#a3?Ӧ3OKw! K֐-W'LƤqm?iMtjm1 bI␧qAa"ۂϒmh[;QRfONK0p5{6yr[[%+8ij0r|Zp6A v4:DP#E8{fT,qV9=2U Z %Y ,"8 ͚tItgv@g_}ͣ(v K'C)iԶ Z0NٶfOo>x3gecú0:Z9_} D\ZLI {\oI%)v,.O?D __ɷk]ҶU]7j_&Vp!oX;0¢ڀX&U`#3N\vIKز5hnņsC *Ҷ,cra #JIWzH5HkKem/Ё{W;c[)j)LY6KGV_ցTˢl99z*jt:vVt0םUjDWqJP}WPkHTZiL>JT 6Nͼ 3ٿ?Þ`>Ψ98Mňw@ ǏٌiXl9QA^\W[;zX /,@fA?S_-DK|[pLwO&, )?Vy3#42u|Lxy6Td[xt8FM,{&6{p>.dI$$Cvyq=% Q@{yn)jMy;$Y/$F>M[{-#MI\VDP_ ڏX"WX|-e`(G7_c&(f뺟88Z[od cʺO@V)8zvg[UW:FRIskj{ʾ*vT:4S2#~|WAzSbԀ^iñӛR:zx[\H# CZFX@9zN!sahZueCq~C[Q<4z3rQz֍8N2'lhx<.dG"3~}2Ǧؐt:Xa#zk^u 9 /4dhxfҀ`PWX|.';85M`3rS魗Oo3E8WDÍrj5uSzcWtRN)CsCq۔[gkb5tdKIdCV䪑"W+|O{8@OKo@C;d ڣA Ƥ^NI#1k;} /_iS'd'[Fi\`Gic?>CU#e#QYSc9SM̓p޷M< __o8S R %7homiBI^ºc_V#ܼ<W(s]u.6c!7<] v6| ;G)QM#Ҁ~%Y9)0''t[;>}r̉#t%`Fz~5J E(P[Y&i,ЛqAcϾ> -IBqf Ocd,puy1\l xvei{)wM0v |ԣ+L(om^ ACM9%K&x|=ׁ߂>]:?^+"{KlV3hL6t*oc,ƫ/܋]wA|4R5 폆a/hV]ȣ(_=pNWX5yވe+K{7qv{_w>+E댔X6|߽[VN5cE/"k[ۤ?,i4I<y|TJRS!栱socVʲR⵱4zzP8 Xӗ\ZpwȺþl,DvF@$F o#?#]|qM*'ӷB*,_b5xwWb^8p-edV*nDl2#P̺XYqV\v4KJLN!c4cӠ(h=<k$ӼLwNh*l޹'χ(;h6G=8Kw.?4A( kad=[򡳃¦1Y 1ʤR{Ȫ0ۘv.y ^|ٚX+<>#ܺbTq asT+[:2k'ѣ/8fmNR,86us2% 2󳑗W [g[8ѩђN{ Ƥ?*I&N%K (q\{nwaáeW.4u*v}r݌r9xP('qv͑Q7^zϯRiƑ!Z)/g51ֹl.%1Y.1և'0>2lȒھu;ڗݿ>pm{y(GOkV_ߦ6gBiaYro5q >NY/i@~ |Am~5~r^*^~XCxݗRHYzHͿamLō #zSO=kw(Y%ni2fDg_U֩}Po)_vه][VQC\>ˤrwS9(: ;z!Ç00 =cL9el:cx -zC&Z#EPUuQc._vUY)b(=u>Mg¬K?K0#0RvBN4u}Yp,T|^MUN9ңvݏ $yVČXt%U۹xM>dXn=&dQbyN#*1k]f du[@髌R2mta7Ad.[=~f6:7;wGXJ-0"Vyc»K@-E-dzڍ~eac¶=ĆюbܤG~0zY!dAyy9lmm/ɫ1/~jT3 (jf/ܭ”lB9L[gdس^<$X {_~u.4?We kj+ʶ!xq笧rض;b줻 $ڈUkW:4eLo_~Ⱦ_(ݾzvW[V*H"1>et : .#oA~x+i8YoCJ͚7`?x CGW#h@fMTUPc(>t`+R2`6 "e]x:ce [7Y )y[v& Cz6^07tIv@ 34(Qp:_ 4N/ 8m:fc)uk7EvFg^̔FȀ 4%Z2Ř6nwb˖ғ铩{RK?u '*i\,@! ^-|PL` F% й,e-,lmľ/lز;,lL4?R>۶3y ՜u`k]/ضjrsEpԭvB_'o2W^V7=l_x'j³R˨VY'Ndif>dq>*{0hx:p=eڎ.Ͽ,[F:W֬K%?z{˛1ZVD﹀o͙͘ՌyS *ӵ胛Е1;z a+EcH|IKƾ1Jg0Io9i^=:WJ] 2cl%ܤ;QDGQl_}X|F^C Ntv0"h^|:|!8)quȢCȩ x_;p5U% jX%jljҞke iO^9Tn^&uS@ (G}Dɪϯ>J_Ν8 ]iZ3d%˘Çf*L4 ts2Zdj*Ŷ(6[ PD˾yaZŦCnlՓhdTѠ utqt`U qwyEZ {VʴΪh%jUe=L[ ':)vғ' Rs|ePڳ,0?r:f;<6H"8&9i2Ɥ!q6DǷ\54Y*+o*JqND)|eu{Z bOe$*''׹JtJC층4Uq;K;yיtf%b\n(g_`<%ut*#At}ao!!=)?r < B:2;c`Th7ctAH _zƙZG]&NF8c_πCڟWvاWrO4*8Yv[sB\W2}zAVkORYԔdu ,GK_-F{^pLWSUUÑCeίSmߧH#Ϋ~n^)Ӎv?ZYff[ MA$Yx2;q۪db5N(.KK8 ࡝T{U(iߝ҂AXu uzk{! r2q!erU6MEЄi3V􋺝Fe*"{BR2hQӊ;> JyAvk8!%^pk"oċo/\y>|#XWbix2:XLSPwOҳqV#z6֝@5.=렜zM4lj*˔JRH]Wo 5rj;LV?~}Ga#Vw/eG]cs>˜^z[^sI8W c^.Q6?pmDua!8</S4a~;)tC47} 3-x8A۹MxΩT7 MIO?[)ډ* pF A$NnTFH1#PJI5r3u?DS%QT{cJ L@F 'KΕwqG/+Vc{w&Ci u SɩsgI{dxyOCR~aҲƄ Jǡ\,h7oLykPm٨0@MB:~^=D`t_l8tdۻ頎Y h[0|Jjh_~Lf!f Μp.- p7vBpP UhܤA,8}Lc2O?_vbp<_|ȀP;x9O>c;L{ "@n)<}^a8B45,SC9 mHQ>y<>1 K_z'N#}Y\b<0I p}m׻'&MrY'upӪ5*~'g$`xˋAl?X_"M .Lekb6ʶRCu)e߆6#?2@W؆_7IT_~6J~җ0Y`ρ\%<\}:@T1GsbrTv, 9~xשxG|T,߫GيgkhٳܜYݮ qeb5];>ٓ1:C!Fs>aC|zE2WsY;d{aIX+Hx@IDAT[dPm6b,M|V}'(.K#ӽ:V7?W^/7fk{LXuQ(/|') ž>X0i<_I)/nZ,a`: Uƀ63}9ؤc--ʾץ9Wk+Pqb >}xTJ>Sj$=3!cW~6~ [#-ں ڼ[Pq/8" FKi /=gNJ ^A^GL|[x}DŜeoiu0Q_s"w2deo (Q<vzFnL#W@ml3.+/Nw|\uuuB&xV+k`M,mkA&V[ +9{ɋߍB㤥FA5Ѩ6)wz%L!w+|{++tB˖FSl,F=& YD{xb^AtVS./;^"VȐ掾eb "j=}WWL490Lbm62ϼ)ƏGFcԑm(wo1He4~TZڿ0Ä-|I~}(f!IW,%y yjS05tTXTsջ3i-8: 7T^('ҁT\ba_ޔRX/;0Z]eJmvtmXԵz`=s2rRc܊l"VBjJDJJQ|bXU*/ʊȸRbF?oփ RP{|HY+; X1ddw+}w!xxK\|{k FΊzV7"S)DiuGʼVQ~[W<-bЏl 0ՀDw_*ȇF/Z@o77]3֟etk̟Skg D̘8 HMDJN%@DsUv*JG'آ1Rzn1$7n6^ ࡔ҄;S׈QEH?ܖWr(]l ֋a|JM0N23 ؃(gD&>k.g1>V,\|Eo)35 ,ߍ:87߄23% q=]-A0G iY8KYd%j6CGZ<:*A`P_g0!|<́[}z"N5uk8̙Wy$;Uy ba(h*%oD!RR+k\  ʢغK ٳfwWN ?5~ݎ`AK[֧_ [l62⿺󥝨T!"SKs?#`v~Qf<=Eg `%UCAVy=IGS bl`~u-c[: Is 6`V&{C ~d{$زqXY riig(\WSCdA50T'`/FId^@I5gv(%'18$ iC0tUoD&(K}Ya"!q(=`iYyn 4 $ҩ2z6vUTթaiƔ~mFZ '4Q\ڍdkq=1\(4ɜf}KIQ%`a0N1inEHg?<3."88+쯼h#%,}4La^Sa[v줌), thR@6C†L~!aO&.fbXth)C%mݨ>`H6qwE{a֝?{&=ˍ6Ӛ_,+Rt%;LٻGV%E8o-}.\JiJRL?jY}_ltx :  bgH1Qc_m]w67{ZTѨ(`Uʠ(#]X&ءo:2=+QY\,VLurvGlAUrjrRJAy%h/)Ul(\)L5Z}# v |?Ң OWoT,P\R\*g fMs"fS#th9bXi'Kdط2@/*$ZL XV28MM &Ww&C>##]US?^.Q3>ydذ) W|/ qi!'3 G67Tzf65O 6jE_2331eT)ރ93ı]Ka;w{5PԝR=ږ=௹^ $5S|7;9}?x/%uvѹSv6X1H:OJ+77r;* U3ot^bʍ9Q ܎c~~ GGUޯ3^J JA.Qʋd` a1%gj$qGG;NdgGݹ_x`vd+Jzz!??U쬞ML̓`Z:갥׎{X`[;M}l&cՔѶdzC   t14U6Ttq`V "$H س XT۶e6lF2j.5 Rr+.>sND>=Dݚ&+-D1A"}3"2AvlNl"Yμ3Å0N>Gi^Q t P^K%}Y(**ކZoDIJGFap\۫'N$C'/1/\>EIG_ 5& `doe(=nVq *)y.'o?F{WVv q1g1_c?Zpݶ=hXbA1%@u|uu<nvZJ:I^~IL:~6HS6'x3򺟽"zUYt։hbp%8 (Y^BV3>e ȗX 5v7M3F1n fHfQYysŏ_INqgkT^.EVufݻ_| !8 0ՆϹi (o6@P`0ʘGՋ0# HYjե}od"?mYK{C 27HÑJ!>ѧHuD~l㚐zce3 ,>D! G%e6Cf[)lj,¿?}:MŢEHmSq~Xt8~[}(V3d{BUq%蒑#(<`;ΏB<QQaEWpKn0)~7^e-ܧލIGBr 3ウ6M֗  my!HN8ʠiL)x>}q`ɼƬ'{R'emƂRJ$+m@֞ڋob S?Rqɉ9XW@S'B:VƄoJ oL~([T` N*w1 f` P_]Ĉebe2rY1~Ųߒ[*E (OY`R=utS8][F]}p@S=Ŋ0kiRTUUdYJr2YlD`9JJksų"UJζE?KpqVe}r\ ^WW~mafv*jlLr'w[ñk40?`ۺ-L㢎hVU1(τӟj"+H[g_)_˲ji35˵j.޵FU&QmSx4 Ȭ鼮KqXbM3+|YGTdi2&qo`Vxi~퍭@POцbD[6f*9U¼쮙*!z,<^LUTLyM*ˋ9Q[RpSwc w&nϲ?b}ۏOޠ8F-k*"?+Y(#1#7>DvD~׃ -o4URc {u7ݎB4Ed`ݦ#$m|6Dew3q$Q4'N?ry֌íڵk_'6_Lԓs1? '6%I#F:H=i(-F9ԫWo^ߣm΃8cF=;^IˇZK54u`?ʘ>3I^`(?Yt0ئ~dN;m5iSn50֬yF&2 c u5M2k=sHF\t%۴]-XG]#Ι3z~CpΣˤ|*F8g-NDE10`$BkA4Դj0 FpY~m1"#[R<nG{Sxc &d)?,Y[F63ɨ)@{iRvڶNAkXfUm-y{`7$2 @KHE#HbCxEeْ/@vz6(yGH?+TիV  kc+Gh1;paVap}Z!ʔ6J{+X`gPX ֦ sTJL*#9:3 =ֶ:-M3ȢifZ*^xy|ͷXpR `چ JÄ 6a5E{P t`a}l&7=x.prcN]rP=yݹ,y]~@G.ȢO"}tDx=Tbb2gd֮ ={1욭^LGR3D)9)wIe:LgSgj/b9`)CfHʼ<4\(fܿ,.dP ĸA[FiʎN;y5`uw8>_JC;кy\CBlZ|uɴTC-k r A 1Ƽ9!avw`=w*4tZۢK9߈ûzHuJ[=k0v@ Û̞BG2xo}`oe(ϥ"3 P!֍|̀53a"\~& d<2ā O>m-yؼ}7VR]؀1ip;ge㳏[.Uy\0ϟ~yT00q5" LECG1tRxڴzV0(/,8WX Q*^ <^VRyߜװk~dfe0,>G5d`59䒥SK~&)ʈY uL7O>Zhc{u\κnT8 >01gP5y&Uq8'Igd u8mHՀ:2,AaT0%fOp58PPu^.b^M[SmG1M' دc`h(`%$ $Cg@M';EE`U?ym?oy,|d" F[?mS1N 4zΧXr<DZA [`GգV2|lc@5^Oƥ@Kk Ul6 %#`v2E[0AX0Paƚ۸^΂* [}&`R*^bJmA PU<}}2-ExG "Yil6hR#``rא];h43ϳ?J57lڼ<}}LaM7o~-׽g=NNL6b쫾yۮ$ӨfJˮWhw+ 0m_eqs65jQ\^Ļ'JI+<Ã<i3?`ESsmSlph)]sb#' 5]S8Ch[Yfip{("np(?D4F8#1ZJc&aݶd##VCGMa^6)ݡĎ5>#ѷؾΟ\;;n#>q nE  or<Ӂ=-SWYk L%W`5=|)GK@ ܑK@T")^yx +}J4榮ơcLNdf^.)zxg$Ֆu9b8zBGWp(v)(#37_C?GJlo=2S|;岿w,C1pSpw!Ѿ=?b]س F"VX' e2>np5`$hrm-^}|!6;ݾD<%!]L1o}=(Q&?'=,jmTD߯Eg~֠q]s|ϣ\!UI-[ KY`_$j9)Klo:s&`j5yki9liܒ (hKU(9vL 1CJ^V䢸0 ~.m$9EUH%3aBvjLeUwle)ǧE&߾Hf{ ,Dž`$GTl ʼnh?>\M2QO *͛رH~z>Z9R",*(J; zv8k ())>>WYOry/~ ??ʔ(Ͼfڝ`ʵϝ=Ie/6?\:8M@J@%`Ȑ!ʫ3gb$u (-.b%x^ftU0߀i?17$2^Oes˥2:͊g6n QѣI>~*ć܅FµLr1,˥|7?a,>!cS[m{`: h`x/+1߼ N2˜=f^Z~~ZXac#@b=LSUIԋ2ӱ+Y4hByˇzcz1ܶf.Zضz?RE&#n$Шoekn/+iFDA0i$|).[ ywm߈[Nǡ@sv ܄pu2Frßct  xY>!;ۚ@²^z2J4&uJ BN ^!/:5X8sB5l y㵍<},dC\>j"msqĉ! }x< o8d~SX >#Gݏ߇,Wݝ7v,2 Pivsxصys{xsҼ+l[s@bFmﳋ Ex*Xrj}O˪ҥyyd|b`\{N3|}@*Q{.r'j~|C4C*a ?n鰥|H[C9GhKB՚J'~c&nZRK?v6oݎ\{@-J#.1cde2]D;8h b]7KK嫿Rw]U~9M}ۑ%`~eا-Ly4˻ ]8&>.7K>~3672?Sw(+b Z,; ǿfwv؄U v]ToYn-bp3&qCF=F _pAM7DSmX+_ `jh2uq١fy '~.PDJbfpu*;3os__Jy$30':RQ [oj.+=<ԷG2hI?*l621Lu+o3GPV@5F*rD ueW>1 h;kT|ʔiq%oW~'7QW:J'IunGoIjqK$F\(G̹8*`>E ζ /xoez@!l}_ݍ6~G1Y%dKQY [j$w#$ܶoNB]."'*M'>^޿rqy2zDBmydU) NS6QH$e6s?mZ^V,v)ʒkǖG&Tn^WDq#YiiHVEWcMPjс\C2KI§8$ӧc(8 ߺPDǗY(w;yL5;~?qO_vHLZQ*Ў%1(uL);ǂu? 0aҤx衇o >o(h~)ÿV P*q՗o{MӥRMm44"k' LөmBJ*˺ =L`](l}14V߽2uTI3n?Q$PZo>f(xxbBO<پcGQJ5pld$„VzmioJ]]w6dX\hx8,;-?ssMduM-2ʘ [PѢdmΒ3v/Ô.3ޔtDMI!s?{Ґ,-Fʹ ;&ezmkMlc~7F%}6ٓGp6/4Q fc쪂1X=lV!~#qݳ7ƓIن f}{Tou cBL $tn8#AcgC{H6|ZԐ )j mosDlE)Z[^V򊐔Cn]@R?;#jH&[zuL\|YǼT-Eł]'o`Ӽ6~ƔObMc'zU`ޮ+82(!<94 @?0> y @=*/.ȯ)/#Qusƀ)$\!ZZBg LnI<{|+W6KL0}`Q]-;-81g}nb Γ͓ `" h:qR<RZ,#T|,ܜ\H ) ny `c!h`:8K>۶mB>ly+RdHC] ),.M2{ynD }v ܬ,ӥݸRޠ|Z_nWMǟ_38Go7x%t3#kH#?%5s IvJE sGʥfWe&=ĻYuŸ>u[TM Ko,3҄`l]3iơC*yzQib!7 k ȯfg"h@ݽ^q_`޿mf<"p:93fYqp:6 SfŢӧ)0>&q}s,wN\u?KCCnjlFpv 71>.O,ʙ.&Eu~]IpFcc!3U8wq6jt_4{20E@ EW/dj:N=zLU'_톫 ~RڕC!!aKw7``GZjΖ5#8Sކ\@l ePgμv.=I^*G`|y0޺ wXe <0Tq&J Gp"$⓲o`/Zs&m2/řB';4eˆsC3+96*}kdJ7G_ XsCw 2'6\gJT6ztZ:uH<{}fY/6AX1e}~AfmSX"z`axOW-Uԧ@#':*^T `j*weډ Vǽ:ؾ ?x{{p/AhoWaxE^eGC{J\O Aw^z.o~2d 1)ȑ#/0D^|g| JFړ '}yTh"hH<[+.C 0iٟO?j92~OqIő4C0U1899KE}zar0r-.~ bPI`ΘU6tNo?٨" &bGdE'W/⻯A?J>S맸gKw*w܆C $l4y+Y,̣sh7{.DC OV 3OXk*PsBk2ύm=b|;L |KfCM2_|0úiѓ88c/@Cae}} ii 2Xk;ѻi W_GB18Qcsx`{:C6.;=PGf+ZʘmQb:G `nwn$pi;k;yrϱ(lΐm(ꇋTD:!rw;c΍*r[^*L:~a~R4THeV'4ӂXU/AoS\O'\"kZ暨e!œpg?f\\)ԖX9{\L&83C¤~>?/4.7cyIk0f{ٷg T0S|o*ٮsu&zeSmcb3"p| _Ϯ$OG%WbZ /$ GJG+ʷJ/rPBwE;pUc`eUYs`wCEam `b=O* 57c7bJ^| 0O<{h#rqWӧ0E+kL0,l<t cz)]F+Sdc <><}0a =S:gMޞI]:̝m6s>-\w_E<=c1u @Yy=y3-?_G1ٗ ! U#9UТvY-kd ߪB3=.UcP$1κc!fUJCuo2-AU!4]Fvaz:_If9Zc"`5πW_EW B]FlB2u5ÀpvF#SȨlUoA^Q܌K4m՗^[$,3rH~J3pAcC:w5k(+( :8UVdi\ `j؈#Thi0 Q~zM/7W** rSQpTbiu[O?D,3#EuYl姾M}+)w@.DZcmj 0Hy 3EQavćL`Z`P,\w5?ı=e+EA4D4'?*ِ\KۻAalv~6;@IDAT.vM R:'Qʑr,tT=  g[Sʥ須2L~0ԉ*!t몶LjjT]IPmV%dCMmF}Vh1azJRV] CS#Lg[Un A1--a&H$1>e]ʝ}73ݫkvZ2κ>z3\#P*\gz2̵X^YM`LtН}G8yR|d Ŕy-Ffls!ˆzژ33)w3JxGgӕAcF8-Yz~$.~6`$99wWL&:\ukpAl`PÒǞQRf2&0_VQqx܋/]!{NDzR"fNd5v A?FVLOaw&rԽP%I572.3Og Qc/''G:e{>s 6Z>rS2G 6ا"O%A* %I2u < ΒtemHcGŷ?P҄E!#2q$fJiCOCI{Hl󧪥EfIyQݰcJ.r9ˍ pA:S!e.U!3((A.S-ZYW4_$xմaRu T7ӊҍD YO{@ ͭZ015D)3*κdŪIϷy-ABC p d t>k~AP&veʑV1sݺt`'I c}'LB@(N.;@f,?eZL2d5Xu:xW t1rK:扈d4pK['X7cE4Cp݃݁=<<V݌sV {dEVQN\#᜕K_&L,%1g#Pk+`7-DBh顺 rK>dPBuZUR N8wk,UEm*a 5=#Ϫi-/CQM5Ȥpv"\Beb> U8@g @ LODŽ9ǽ?FGؽs3\M^/[P*ؼ&o[6_ڑ,@V`IVI MtڑS<ql>Xݒ_1#*̠U+">(w=uɠ͡jfu!Of9ly, Qy='ce! ŏ-ĎSbެ{pB:Nmɝ$)fKg~|2ZOO>y'lVg]n -wd` q`dGcsMaɁV;aӎ=Oڬ)eG2/,V}*O uP Yם^i+GbD^X7j(+/Jৼ薦W2+ )Nӭ}敉HT'`Ё]_SqIdc^˕ݰ+:OcWc?;ЂY[rf[!66~AHOW J$hba>{ -`?+hD= O>]Le.a|?)I1w|l۴E*o^p0ƽQ>jΐBfKuAcpd5۪㍛Y9Xjkᑨ< )?Wx ZɊ}y،{\[YN? Y,yz":mf(q,BJ/v浳DH`Ԣx)#[q +esLzly([xVGM8믷\ [ M(jA 5j/#Sp>=mL"۫}}zv8ןW918Ҋ8[c-}3&WKl,=M!ϻ3fVknj6|9Ǫ?!Qzz:t\^kV!"Hn.Ak/*/#A]bԬpZPO;,u 7 ~bLWqb%9V_d p l2+̱d,Zh{1Q@u6Ұ} <&̀ua~hRŬc"LFxd$5zAf8vLn>2U à!\}Jnjҁԅ${RRyUC>:|a#l q8"{'~){>>̌ٿzy ztZ`jsh4B'|Z^ uNA>dV 3fj0anRMPh6$dihhf,6#F,S- MmrTK'vةpt3`3c*| =a&5vey L,A8W f Eu԰5QVVN N,DY|އ`_g֊^g82e/PZ, g,dV2bdЉl!Q Y?\ۡOƈ7q22n4{Yjz d KSSkfA֖f((LA1]Ew;%րuaA~v"ȦyG8US,U_ ;I ̩|R5*jUaEwM6D|B* Z](=YM u* @iEA{:LAL #7qQ hd sf;+@9]Nfep(:/Q__|Ս$+dՒև@KgswV1?W19Xi#̚+V:G21WQcЯ?&LFes^/@Q d#z:M (0d/d&'XKzzr=*JJYhrٙg}r[4wLA<c`ՠbq3rJ( :x]ߥY̓sp2yy̵}L+$P{d43A蓏J!co t{BЪ>Jmʱ Ssxw`U\[wA:HH{{L{K/&&FM5ͨ ("V Hk"/{ܩΜ^kת~u/*Ċ~ӛ:|xW0ۓw7m"J `V{N q&5V7}Spٕ4 :mR-vLpcYr@,ΚgW5Vucud|(@sIRynliϘ:YuזLJŻ}’*4tdk1N!d۳6B~V>0iI UC2\C${J<)8S֮_5O>-#>oײǞ|xOmxFK>azvIņUUNw/4$Z ɦZcذ&R ֫ Jj֡jǙq!yOfѧ}0'>8:FKդPY#2];!9>(5s#EL`|[0< Ȕ+2,޼VzԼwCQiP:&=5@xO 1SXxbo|LXu1U sUgcSzy6kIγ}t߿K<+TBkhE7|n8y6&\엻!uŊXrj<) F͗x?df$Kr)u VP)O~OiGeyĘߣo^T6WDYQx^%5.ũ}>8М,835q>]PYƼ+瀕zqy"/\BJR㏢ބc"ҧ*9о@m燹H&~V`ࣴe8(+#:f eKBNn6ы?S(}-ZsD&URL&z **eie]~;mmoU䞺Jiq>%a&`ܡMkХJNd jۆ 9 Лp^U 0ii9w^G%ۤ%ÌSI׀=ԶA!:` O0B/Xs5j u՗!mWi9P{iJ"-  W$SRi%sF 3zPLzw&dKv"_"-.ٗ&#VU[mwԓ x],8o@\a-'G@ `0үo98PN`q8r &^i8 @O\w:sW5Vu^ԩ6(B5$SuK׭N'M?` O ݴ Osմ ?g?Z7 `J{c^@zGХԵ kJa0B!B)m.ٻ. @6ZM'媕_sbۍlNȦжQWGf2+ >xosd# .k';? X̀ {c '>~G7콰L; V]F8HӇbn(Z/8S6hʔq(AN7Ga L>FxY3+ڇ1`($lmSGOӶY6W5V9m`uϝ&C8QB5BE NI!yϳnn71eTѓTۈOl4.SVȰʫiEu9sc ҔYZWE/oJ&ȁ_4d3ǚ-[}4 [N]wKx[B>ط yY@{Y|sx/~1YGYָ@vt =͒"bǯ 5=o'SNXeyi&'*Nk2ARg2#18 ^'}==5w¼&mV2&F}sى=?'(y" uЙ\Ed{3k.Ы6K 3(~BBE\Ġ*,f͞MΛ *ipL5*0;W8er{jTӻ0(Q#}]R6X;ߘLbnJvcsS@y'vt8__J|'>!oЕ=r*tr#GfR{jqv{$u{>G{AZ|rer햻ICXWhߦ0<S2R.U3y~ #UoM;kV%럖♹'ǘg*L>hZĻX}wǎcM%0W[6G4?`.!ctvm]xXeEƣcUcm2lFKΫh֑Eă'L2ϓڋAW! dÊ̩7ZKEQ"QT$fJvF }+k;725N" @tcPK^}Z1䩆g;}R}\ У,( h1aoOW!de\_ov@ mj -$< W|^/5z S؝rH.oi)^ G)+Y_4ē!״!N/y62GSM|u"u)T0٥Kq0]$]ffnSͲv"ڭ= cluޑC Ul2nζ1 21dYI};KCʽ(g_cNkuTKu5cryJ\WmBCϠ>qH Dʌ밝d?Zy۷oF^~% 81@.S]\9ֳ{KUjxc$"#B^.ܱUޥOg?02=akflf獕! 菸X:&0kȬj-QUIKPR>ΣdZa ~ SR8Kllh@)\뭷1P\p1>Q")(9 r:K^0XUU/:0(@9*2цN1l] (;Zhߥ>MW&;o;LС#} ;Qn/VF(&L:r\8ٶCdzەW$6`\BIq>jxH,ARF9 b!!=(.p ܻ܋B)V?9P'BfGs ]K"?r3<2  [)yG&Yw#jK|ᡀc&ƩnKqHY=هعٻl3 8"wj9JO}K--??_ѽ$tvr/M;Y:z_!Ik_fьi3\Gǜ2kBI&T•gL8OI41DJUa'Ƌ%) \IƿR > QG#88X jPUbJҙtzu;ѿ2^Ŝq,:]sxA2쒓Jqd6.mמX$V~ǥphiу KX2h,tZ,!zI4L@ѓ\r(5/Dru0YBM Ӎ~)\_-F}?A)/מa;|||xO\d JϘ4]Q֞|~|ݧʻ8V'?"Uy)+?Cyd}Wa; ]y]zd*dnN\k)uiF=|3̥U!qj&D)I`|DVD'aՑT'D7$WWᘳWB6rsнs~ZJHb]|<<=:~g0wrܙ0Ew< 쩜ƒbJ2KK+<9`- UcϜbX;0d^yꄲՀlaq:Ǜ%ܦl:T]Ɇm+*B;&w˶ReT~,:(Dti/uߝ p3@}u NYdJ"d3ZW*w EO_}rb˽6'MX|KbJwueIe9#N*E= *Ǔ-].+M*A,m4 ʾU桺\T?Qd<2g[ǿyFѰ~fmLU$O"uq%>R9_oi›ּ5~.W!ԗĕcP]Yo`1ZƵp'ezWϾ5;#+_,Z@`}&i$[E0ǎ 3s~m9ϭ {8ۣcފrNT1 Ik#*|vm| jcR%%JDvxpNIq4$<ȳtu{5J[@t)S+kUE*ϕJ>K]4/}Pb ZXRgeޥF漯D6bH{_oL%YKJiMrVNr~ke;?Sz%fΘ '~5 0YKvw> ݃$zՎ㠱0kpf=wY`*2&tVC~d/HNPt d-Iv8@~cVF2BkZd+E slZΧf"<* >nUpYkl='͔ߓ hT1+w,N]6EX}ه89°6C-ZQ,b"{wSԔ^fM,X0Sr_v-;?`Mp꨾e͂俁9$pW9xI;1KpTCpz5毭+;o<zY " fglP]\rdB:}Crđ='RI 5W>v9\NhSU_x1 LGGfl 6w|uGØ`{$'k~ j1vW`^G`U5.t@ZJ&ܹC"39ٗ@IZ2Nشi#龍K_ DjYwnZ@w;~ӻ#A-f_΁) f=yL^8&q4<\ȒwxF-([ {c-<˹ `(2ڼK &Z軨 R42,jP^ܐWETN{~ٔ4D=23A#BjH OoeTQf sy_c2(ʐM$z@db*-?uvt8q]Lx(=j~ N_c 3cP@m=lpL 0kCcќ UAl'Pwx+oJ];ȸ?ݭP>mx!~^@5ϝg+ju*6NY͙R!~à%HN?&33V./qΝŦ˰A'u"f)$8dS\fwAWK0]D ;T+nc ǎGR ~el˵9y~ 椞~/JH&M;h1ܡcZSȈcy 뾖2b%S2"Q-aFбSF B]zOw:A"T4wDAU 1Tnkg:rؙGBaI^IѭɴEX#HL;x-QZ:Xe- N:UpjbnC"%')MI% )Kf}=%{Ɋʪ2;qW֬JJ۹sCQI62ʆF%2 df^j%Ek-L}¬Hww7|<7/^ohabTlR,fZE{vF{/ٞVh=q<"m]ґS1LL(h@hܰpѭñSg:$Ci?kցD0;=OR[}E]Rm*zH#HH`WK/iR4ٶvB5˷˿ z!;1s#sqX8 X- 6YOż'|B l# kJrj| xlqZލv{AYGⴹV=qF*c7๧0*<K F<]~8wn&d1z3?0cɣ,|y5Zˆ L7mBfy<Äj zf|MU$!_v5r9Ĕl[3?Bh6Ǩc`Gه?l^Mϸikn?~\ Uk䳛QpE+Ψa_τ ՖCFP&cT`_1v\OM}}۔^=2$^S߉ϖg { Dni;X+63)ml_T׿3?V9zg&J9b VֹLý>R•Ͻn( =E@)Tc4t xvT So~A:(z7tAna)r K54 2 A1?o؋Ic#e5lQV\=e]2RcPC;V*FllGmjc{)ch#֐T@vW,svąF053w˖s4tAd ?˿}1{EK :Id/}׷ReOiNpӶ h.it2ga9[wn {Tʀ3K }|=bzr~2&L_|@G5dTz w¿LfF5 ETB:y_q`]`&kKUMU 5ɚl[w!,OJa@KM΃Gٌ(… z2(SPPHx!XCv}EZ> g428}{W"LGt!&#Ƒcbά{pG(;i) O<<'qdZ3i@ӿ3PXb'u4"@`Oּ 8SJWhI UϫLЫk\Kuzf9SoJ9bYvG<߶{a1`laYˀ6{y tFЫn598{Ve1uHG'C`oܶu++,à}<n^>8M8u, Yw'M5r.6VF _A;ogd&ȜUGdM[] {n^Tpq [Ad6V]挜{PZ ;O[Yyl傼k/\m PinPrc4ΐr7+^^{-E%L{2PdMs{qp."e)~C׈l1ggD%ϱ5=ɮc:Ŕ =E_Ww9;D`:EٰkZ1ZY9Oؑ^{J`f{-1FEI<y VK/Z 2i4%JqbFpNBAU=&ɤ+}'j8P|{0@冭o`kOI:B+]&jXa{QWES 8P4-.3qłuP~\/uc5 Ud-$g=6(x~%'fQҗ #0 GSNl~ұBC)J* 2iXD|JJʴ1z$gd|qqq:RawD w݆B$O\z23),1p26TOʞ1Gon S6wtr# F%xgnوʊ |G8vJʾ~$VQq6T#B CߣN4ƕj ( 4ǣ׆J#b _=A(l{nxX'&P * kF:mTrz '13g઴m mFYu3%@k~~*vb_ice_Rϝx^C/2<ģxɹʡ{SBX`2dx_);}+&$]={}9̵;УLyUa;9^T{.*E٩!0LXHOwFM*%H;?s1OG=c©YX^_ {nxO*vJo;z uL0l3kKuLjYs(]DhCۀ1f*@psXf` * SG6ҜOޮ "oZ串Lg؞zrkyDPA՗I垕kzJ&U%\?^R]<=er?d}pxEl]omބ֢w2 nZmL_ո>N9S;sJYOou_/A2F &= 9 "B#"Zq>{1==(a \[;W-p1Z 9/*dLȧ(킽U+:QQ Ipf; |0R@IDAT}/"Iya!7ڳ,LpYݲBerr sH)l/rj[,mi VW}_\>TrՆP97n*T3>`_H?}4,fR1vle7t`~-W3~6O]FmK]jYO'{uBc]X`U)jì4bҀA2u0)"һOTe#ZnyfpVX))qa|0`[ʳe]ˉ(ACh׶-^BYΚ]zz#ҥdaR,ϽFv3  ʌ1l d@Fv >;+ -\si@k)|F;9;ׄonS! RS[HjnVJ erEa<4c&PLq_'3,țhD+=c1@|HN>elm;=c/W31!=~gGP1oЉcpg.`f4r8 (HU-m"ly>hhU2`턊<w#Kǐ傌ԋ.' %WJ-2 N XbDIUQD@Ι)#PLt(ϼɴ~^ I`׶8IY:K:x"RewGO1R(ZDcd_"HL%fqۓAYEE4ls 0'/BFd&i!a'M qhC`m~e6\322BF|$S];ʍZъZ29ƀ&a{ؾ&F 0EY3뙒"zL,"xmM0- `8Pmz*< ʆ`ʢS*2&ɂil2,۲'R%r )6YKݰ8l$|a^} 'Bw5fIs|,9|oIV%GkٺmIsæaG(tH]d`ㅋaea];. #+B%{R&\S15@䉓8DZV8t4sh zd$pUXVt(G*J_@iY:'E V݃}L9x~Est^#QrTU< _oOϲ]+e`E_7c89)drĞB&I5,*ӗ>UULVѰ$-\% 'Fuu96OX~Zy>ac؉Lc'-+: jnlMk_zuFXMV+̜:c䈑AoC1(E㱊,fͦ||k+kx,䲯h! jz^>XRImڙ{(}XL,5-y+sNcw@_G?0x^VdWXAc[ ~=-c؄ӈ2o=~3"2cTGLW6us"ؽ?=6ҳUdu= 1i#CYl(N>HHHDA0&e[Sg~x<} ts3E@G/>C )عy5.ЦMLaNFU{ $8-`䉓R q2+i(߽㧔BDC7XDEGNyWKjF%Ŏk'|j#!%ӎxۃV#ZLQӰf9WB`IS1H"jKt*XB%陕lG+0lpDIzs @hƛZKfYT.]Sjy csYW'& P$RKcYUY[yn<*'*dyh ŋ9o`5l'gpy*i^XMϫ6|U XpWdq\g_#9oG|%9wuiDS{; GK,a텧]I{IkAH|/ЪM7'+gT˽&(]k-m7^Tx*,5eqg* =[_`2 =I8O*m-onV a#LB_lz*j>Zo.El狏SA,2W~׫G4xĺ"Ϸ jDH$,wK!pIŇ#vڥMS6I)L(M{٭0~p&6!Rƍ#XernW|SwjV kf%K9s2lOf #sE, bs3TqДH@|=6r,u(C 㘕S]Azޚ"dwm,8\f{xϿ!Hb{fE)J898rʼnly5 ઼s 9ȃjW̔e{ зQ]|:xѣ?EC*]w֒4;KyY Ƞ_Y]]5-3dr|Gfs*/b\T[zJ4"cڶbqm&?C=KSN~VrBVÖ=ӏ=7Mf33WSPLĉ# w+u7σWo;ヌdb{(lkaBd JIIIQc 68砂RwM\"kkhydeKҏ$? zzԧ|tRPu_OL$+B_}  C|+3xp6FG-6'ڀ2>7UJ(<mJRυ}Y֭cfnIdbF:RJ8V|2ve+ܿ^2[g̶0JqA ߋj_ۓzW HMlmkT"̑KJ۹R2wAs/ eSV}5"N}3&^ z*){\LbģՃ`=Yk-m4`N g)\K酘0iR/V"NxbYCLSlIq+B=uQ=cF]oل?]l}CʃI0qh\%V&= +ptWL:)1qJ:(/_UyIٸy2y`FNONc1bhV ܄^!'/q%nUTufI=l:JIt0<<ŧ? ˪ nuCDQħc`uiG虴Fz23 ͊UxlȞ=y @r9=uյ>aRӏP|YT9 /rϠ)heaCI鵴)F4&6VP* EKKK@8s&Uy .6+ۏKZȰ\\%!h5FL೪7tgd9*`byLƶqm[QC{[`쌇5Z[jH"@CKhogD}S˭YR6Ewfc 1ug7m =ڇ}sl_ĴtGG]_QOˍ^yse[^=}ŭ_/٧sy1䴿+vgv \ag:;YLf=~ )wP4R"O$ xKE{\YdYhkg4r`T&>k5W| T`"'BGBcA+3#0`]ݯۦb<;}}ݲØ4r8ҋE^Ni~ $%_m;ѕWzmne&CmC)__'!wymN` f 𶅶iCVs>b7bzmZO6]2H7(3`Njހ被  W?| qg,# kP.؅O@[xӳ}=0dz͸g&ܧD`ؖ{&uko ;S&MlY)~=ǞzZq>sD,ٴ e )rawLRʽ7]d:g`݆ +e_ˉ==q mn9,`B; 6=pFl8,c!0$xGI 6Yqu<] [RL)/%i)`MkgrfDL̍n;wl N+T ̳-*k#2A%Lubt(GP7H9ػg?yxUHouC=v ښIn 0lT^1kZE@8lxmZSnU.q<ȼqYm(`8B,$ENNjN>NGB (\&G#QH=: r* Ҏ$ale'c-t2ac+de'eˮ[$@ i~q0Uqݚ|d=hF,>yN[n{ޣcc7"U}DyJ  3h\G>fg`0jtvjrH,P}ƵdY抭E:~'Oe֘4mԚ clA^StℲܫ|(I90_D'@:xdx@5qp1SSdB9[e_"3 z:}><1@U=ڍٸ{ʯT -emic>Ӹg &#1yd?],ǡTO0bQ%= P2 `(ى_}WkTk0dGeJm74n8 *28UQF"6!Uyi:LrxxbSxjZ:QH43=A\9"[7B`桓_V/k c()lO ΝE۶{f?z{W}x?`DJc} 6AnʺәYP_r.>fiBҪq5:HODMFֆtoL.!4&elԮ B9xo?8y,+r|=1[5 h^B|{.&`W䪗~[U#v – ;qٔӪGO?O_e+W>#]I-aCp#e%E@li~;sTnJp)r}{`YVlv ,Ub-3ET6zd%V[{)DrBANfd|`=PTZKV6Lw9N:E(+K:[7jJ[7ӣ<$-Iwh&%S _NI-#v]IJ8uRTR !!-/S) % Q^qCESg9vb,_ SXX"/ږRyhtH2 wXz}ֻ?x<A:3QLA|ŗrꕫφ'iU':u\<{{#HCb.Roنue{wa7ap\dFxTKIQ(\D67^>^ŭGڧטKKyQW^nj+#5$_ -- B^Zwrcu?|'`êyu>բn')Zբ.h~VP-'.LH$I]vWVUi3MMsO<;\Vlb@4\č_%hn%c 4ulk\\AԢSDC3UU^ygxouL7M|)ڷ:V# ).%(x;YtdN\(U&\/o|Y{F_D@ywʥX2(hA>h }A'|h&fFyU/=1%9c&ĄپPIB:.&;wyȩ 1X|>*+A)}z=|Mewȸ* ~`BƁ \zcc*<8x݁~ہؾw7ƎjwtpR ?~l4߮WeʊJ 9tHɢMԥ#_%+;NJ M6&dFVL> wϔO?z¹Z2{&ELJ c& sU`D;╇PFkĜu@.(~9.& 60/0sߞ䍴PyC0ضU:u4{_E}HHB- ޤ"(DP+VދB F\&\b@';}Μ9gZ'о5?v:}؎ 1(L&@$M4cl޴{mF&nL{?q!e_AZYgu;OhRE&g:Gfm*%8~[~ʱcaK&CAÕA98z%#n]jym1|~\>АP&Lcʤg`/UU:`2XAu:ڶ ([W!K'c9 a9jQiIr]#|ڽ+yZۚ1Xm%߹W<7E hKOJYT+Lyvld}LV}\'BcXr.s|4e3޴s3CSh fN5l UL)]Fe>lݲu])V :L^mږy2]^-1N.l_&ˏw G5ŷgcnlC5Q2 okd>3x¼_2]2{ X#n_,R՘w)ZP7ա:7|DGRࣷw[oo|͏Hs8r3Z+Lƴ;O]ZEaBKfÆeu VAxTfƘ|Z{Wrcp6F6||.܎95gܯO<>)ubch<#c#8Ѫv,H3>r}zdwT;5`⨏GkT5ƀ6)Bg\6t5 r%m&DIBpu1~HL$&OT_\\fVD ռ/)P=)3ܕ\,1wF7:A-2].#uǥLخRoȳ.}m6'u%zHNndVX1cƨWLrJklLwb ;d_=WpT-V:gV:6P($H㳡m[i1;FY4 dlo'f SV hQ~m|RrJk.G{K_;MX_zMl۸na%<wu4P:rH@,_ݦ?yQ~%@ҷ,uw[ԥbcpF21plUl_2*S<.]bm;(`÷`چeZ` YE+F@[~.8lU"J"G[֓/z+yad+:׷|Eb^|~8O\Gٴt2yO%ܻOވ(D8yl/٬a ҇z2q֋3 `=}?uHiߜEO=WwFF*ە-s[! U^V9Tˢo)w[V-q,Q?Vp4ӔPֹ9f3IƜjYd~,}a:z@Oc ٝ6jbŒ꛿:P@G&d>l^'Q=){(Sy5@A}d='dkI'`萁e0ޅ]Ėrw{ j6u6!YG?}N^XM F*GI'#SC݂dE@`i=왣q]MÞ]Axޫ&2m=]%Ȯeٌ@B=W1MW|j`jnSGH-.^n]ۈ~Eܪ + 7AA(ZrN”l6֚绡4{gOls61RH99"d{G"Hy?Ϝ9Sd2~ôG`M޳i С={z2>'[{& ءOl[2]Ҍ/f0=:( + jgXPT,LM@Jy\mL@P?!!(`RIޕDD y?z"LEbT RvMʹ1ݐSBk]"[R(Zx8қ݄rбoC:ALl<TKoQWV E$Ʊ^ҭ/L)Xj꧜a4ra![=L2'Rɴ)M_f Cw_o~?V0i"^NLЖ!X'TZ2 و,0٧ ТU.]{bĄGʕw6H~6\y+1h&LNΣa6*sFbF7sXNH~O{b_|xr@UYŧģx[Mzċ <&ָN?Vz@Q&O~27 o *KR[;1iʒ1n]UWSk{`C$7d7^9]q3kZSCXG萭g_N?i L}yRϠϭ3}B`\]ˉUߣ*g\N(уv+5Z7ӎ:dnڰ ?, 7>l6tqC'ᇮ+fhoŎL)107D)MZ:njO#__٭0kgNr)ep)ǛNY۳K0&˽ΐ۰>"6 jyG?$;ue5ūEz]Cy~.!O;0~v f|9ǻd&xխ)n݋rJPѣ i f|_PB߆`a>97nK0jYT`B󞭘LWOseVnuQe|%g-jH,FiH\eцϰLǕ17|hܜ9 U,I S]=[:{ Kp_?-)qI#5؇I[bi7aC5De3SWkh)rLLv\q+nM=q)*!h>'̅q56nj\Oa /ÍkC&%H(:ʺQ5]OXUlWYFݎ?~W e6ڱ?S{ {jY5K:G 'ۯI$nݻ[]P[TZR`CʰQ4XR8#Bݺiw1k+v#O>Vb:ϼNDG`vvvLVU ,;YK#19>hvr RSnp4' f~N}9Gh!ʢud;>l̍I@߁ґxsJ5Pw_ 6FasOO^LHћ.VAu3I_ѹg\jn_ ѣNSh>? :wےr,߮/uJѮ L~vX]VeԪ 2Rgԯ7dyeoՒ/ql8$_K yJf_ǽKZl}msزe_Qg{WoaX*u{ۑ|J[>GJCreKA{泰CV4H~.o'3ْrAf'3BS 8luѣkkd;jOV>L%[ޟ2uᏮZs [AR ~yYʹ'O6búYzdQ^o'P1#%MpټAtA5{ϻNrr %ӽnapV](!)̞ &u~.('HqpM@Ĥ !UKuue,$R⊢M+!-[Q2%{|a[« SY㋅}0侽E$eGZz}C)'XG)s*XY0^@vC)3Fq;ZM=t J`ag WSOG}xWJ^$Y 6~տ+W?u5ަ~~\\\(hJ$C* ^uB {ahdɠ]xq;F~][XoLy .i=P;8 Ql_)ς /wc8/x8j7!kQxc?e=ġ5dEsO~WÉմl|.r>2$oz浸L6eqzPnc*^@)j4H2d8*6S1zh7ʀ)EaSJ_eC- 8Z $=})aesρTX[p8ls7~p 9MGxX0=k7W_D2;p12ۄ⑇&0QFӃlLxcӗAmaMZctjeX;ټ|[6akZcS#AC[0Cl7Fq-̮\Sm.PRy_JǑc 0NCg|8_7= %t,?'/G^-5EnѿPe<@IDATuOwOH_T[67 i-0aa7n C@﮽њ禖Q;v{o}-<_I sČ_H61-0')$̝3L(|0c `8k"@ah@@ړ0v ,.?Z ̞К-Ha&SjnA),Y(:Gtr23mt"ՔN%NյL5JۓXo@!_|Eǯ+ASpk(6H٧KQe0d.ZRԎ(1 F[=>Uɬ&h ?ԑ+ە(& qI21esqûX2]8C}:&ЮcoϢSvV/[KvsuhFS&1QRf(Ѽ].p 5TAvx!̺R$LK|C[c`ݪ &)*Bc\E/td,UeeU2wwn(\z+o~E}w_ H3jfxXb bcbQk %B_/?p'ND=x0O+ÕM n0Dk}7t߸0QH-[8FIuQdF͚Kxlog)ZN~sV` ۱L>}${XTfGZȳ :`ok/)aȤyTSl-tf&og|iIw=vEc8hF7l6_'egcg>ts>Y10Bt=іzg~e9 lXY^X^Rd$AC砮+FU,r Wi/ho\dž&WD8؏S2W=ݹ6GCϏbwUEwڨ,-l_Q+z/.T "-K ܋mqI2jaj;vIx TٽZ)վ>w[ĎN2>^hAiz:m&Y= Cj`s DX_(,,u%AbJ7lv)5 6S'!ARE]m 2¾!eƌv~I[ՕK}wό6ga)dJ|Qff 띶/g׋[΢}Yu@+LHI)i޿6aPJK~Mfd J) 4j@G4ͻM/XȄe gD2W&Y2V #+& Qۻ7d&9]QG.D+Jlb֜Ѫ?>5eON"{Aa `UE| k.%M3C`f(#;ʥ⮒ɶz*CÅʹ b%hH{.ft~%5Ԩ$|נҾ4菤koIA3"I7;Wls 1mUv.tO.y''"ޫ :#L We$i?&L_l׽; veC1""3!_w9ܮZwʿW_/A.%]ܚ( =bΟq݁lX7&Y$(8 D\3F{оw7?N"h֘ܗPQBJ"BAw6?&yLNBPP pԺ@p AmX(F7,zD:A3cW' ,ʀOˊhnf&\+D YC"zaGv5CaK&43/X 2F4ǡJ}F\E 6 )ŝܫ%Ӭk4=8JCD`LU]$*&2_,9w&&@W޴1Aօc腮=z)~ |vt4,WTқ֓  `A0rc ٔQhleT2sc޽hBU "ax{:;݃fak͆3B€0MOֵdw<PqAV)vl]/'C;~ۃz*#e۴ ~PSX@'v K^S1K;Ý`Y0E>M>Og}Bg%D?BlJ`cpq"[=޾E3ߺѧ CSӲzeSφ!#'W-"ıCaDQב@V6vd(G{YWZ1qr/IF8>2`9y|mMLԻ 2BJ#?0KBS^ØCՇ89nEٗfPz|O/zFźKcjJ .'h3ī;P.7ŀ>oގI=p1&z ={j1;HL{!4t&:]?~_3&iG&Wfr:t֨jݖ+JbͿCғX`\Gg^A29Xz- e{^_abB,Ы[_1Yip4wj}Au=n8$BC<3DM`oW|KT<xoSRЄuT~)ܰ9qg0^KE\}u :ىxf“䬴s[5UY\.˸ 9~WZUK޴%%+o6Puo޻{'&"#n6.sէE.@oFBE!J\`wiQQV:N>Ϥz jT[[-+ ȹ->zwZWiM巒"c24/~חW_KYѣGFO KW+p*E,ceػ3$tpx<=] yxLdujN^0₫ʀ5%)fbZe+iT* 4e*+lқw}6dyT ːK*)9sPG-w̢+ GH!k1V4i5Y'2L%c9Zρ,h!&,(oڠ‡>R6ZE]5*)gT$ =YcűQ:a B aD֨|h,laBaISmA x:HL{yy ^͚6QXdX |ͷZ~@YT ZG6[4fd0]naڿ\zR2 4j5}KJv@}Y6d̹" -k&;;7.*u`OVLteQ"5xn1#P4d!MиcF}()Ah(v.:bL롚rfQbʙޤEeڥ\P `zC 0[Vޭ!gQF=_yRK=0gL~pM6Β!ruog+qc*'hɀAu1fu,q05B[`\ij $2JCWZf'#5lJ 'ف>bA{)͡<,N}4/? _Ro s]Pau.V i TI'5`nzJ੧'PA?ǡ#$>C˜ lN}S2дE|ЛoPB5Ƈ0=MPDFdHw9^x D KR^3Ca2ıa?C1k_F h;<HIBJʬ5BR943fP׹|Љ#A>\P~"'[~*]$)&($HRRjK [95kr&H Q< :TU0,JA3<܋2X$ĝe%ÈKL\xt9yxw/#9- uN?䍙qlОC).Y0׌#M`i{gB9A /ep]$AV)~Ae&wW%TkP]juT/6مy$t +߆l/&=+h҅,]ַ6>ҢM VDacˏ굗av~-?@ϞyoBطW'|Wۓ;wv3Ez=K2_;vEY+DNLY* "ʏNU[b ζnJ#Cޡg[-+g#&)laJtbXQ O¿P(>r=dXEI3g(kǻy5aanwm7d[ з_2l0|gؽs'egCV}Fذy Rҥs[̝?cw[3G*HdXO mUƶJTfRT+eL)N@9Op|k[Vsܸc97 Y=~ Y.ƏčLʵǣ~1&dS-!m2Xs.s|kesM9î|>)0L4fB5EMz*&9 wͩ2#L,Ja2ۗ6Ho%[̶dε2&!z=TJ0`b7U|⨀x׸z%r֞; EET (u8ͨ'j)%EjA̗Yn:KWU"c~VeWW7SǢlk>jyknY{w̉SgY:4+VQ~cɀ2i݂@JM,{Sy^:մxfRN}U6:~Ag~=Gٗ; jd*`}eGqn4aro pl/ VW"oٺ~'7”)Ϡ]۶(/.֫)Etkm[cu0<e]Z*ّ|]IV1:LQ;K`O*wd"ς YC Uz Kof:> Oc ;S=8DSt# iOQh߲ ydod$6" .ɠLbXt2HGϝS((dRɨw¼;U1wdnc p>[N>U b/&Ѓ<|[ho~hߩl |7o<7⊴+WO()%ėp~X^^X ^Nki`Uڷl*Ed#% ^[Z`d顠17F:帮c T_/¼9_`ʍ9Җ 6vJVWJTw 6!ʮ г4w7U%>"9|N5(wJ-yOw)Ͻ9qx3F:uR3Y$ oiݴ?A|='0?_kDK>`_S,$Z<1e< uuП&ͲaAN->R Kr Qb|w/ c&xd%2RY%όzhODŽGBQ#Cy'#ђiM0gWgjkxpڏ4Y`۲/ч>eO:7܋KDG&ТǾx)K.<|C?pTK~ HO.SWe˴SB*li-5k`}u*˪>ˇY=w[f~6YB]s[d+| W?OulOJj)De8;m,b<0qҋ_)<6m/P>ksۻËk/MTGi'{E,YDtЁ}}d_tbQaȶXURQ&0i<1i W^ŋҕӚʸI|o,!9]7$}r3&)Emʽ~W>WlMUmL^{2yl4NG&1$5Ɵ&4@-rZ"/=Iy:3uEsp,,ҦBj][D֮Gߝ Iִ 9Pq'"i`e$>:ܤN#>{!dULp~@HhbM\אyi[򬯍P 'mvaZT^WLHe[S7 \=u_1֮z_VL3E~Om8;&/4DӶ_h)NR?05a li<85vPd< zKʻEm\s՛q/̨>y{wkbbd~ihoT(<:g"gro2ȑcuBCYcي8BRaۭg.aL>G q'}S4.\> g`X\r CrQ"zOQv,P⻱KgH=O ^R3 䙔$q<=ڑD7zeGά[n`u8-+.##Rn|ܩȹI(E*_iO/%c8!n/R6vɍ9ڟYɬo-8C `8] =qck7G׊K/c歘Nur&cm|HY:vοcٗvZx| mW>Z`%CJHBaS,T}>$ ^T D._#5PoHM;j`l&܏φ5rQVۊz2/ ,+Gі,;$22-)Y_㻯>OQ3_]^Hl?^w0vC/u5zTwkj#+J`$:Ni;{sA$R(;ٜ̆xV$ ImJV6:QIekA#y$ح)Y\lF:p8td/:w;=,)ޭifܿts';8qNӳ+ D ;=!߲̅s0p`[?g{ah;-ei EU@0>ܓOS%z`27y*uaPȼr0 {цޗaA+-"J)+N[j9{ ͽИD1F, ە" tDm;/L{31aeJWk2ю`.AndX* n> nrk``Ѥߦ탃(t}{)daՋճS^wn)SLrTW}BPBpXkp\4=9sq:: Z#C7ll(9|!zR'xbӊPjs%Wxw(L`m2Qn-aLnO[n vQ# |̌y,l[֬1ҫ7'؞kFr,NhuC.(Fٔl5~Zʕ)厩"`O_͇\Z2z/\"kЧ,L=<ޢ:VaWw;p&-zĹ?Q=Ҵ"M99*'_΃`t;w-ѷqd { 7>Ʉc)>k#렀Lkԓ"vCC} L' a RZ#w'. h8JBB;*fIo02%pQz60}0HLQvEn2Ȃ5%ɢ&02e%?tB;t$*K`C&ݯo0[UF2޿o%=sPo  +1{XPmպ Lrȃ=~{K(kԞa *ڻC%MʝLŨ4r4RoGs?Yqg}>e9O1pOkNV?[&ODvu6vPbD"vU8uR[f_玟>fL60cضUs8߯ATOHŽ};`GfizR6|&3ž;w;M1%? 1c4ٷw&+Ov;|~ÒvH)цX|*f,2ЈNpػۣ @~TWavA~#ݰzu2Tבe p|˝ȴG9}̛S6!O٦ܗN%C 0s]Y"v bA`W~e&a(-!Ӟ{nȤP,~t]*\hddȵiDi'auS^Q׏U9^D>b(RRSwAx!(3* {NP u {eOg~*.+BbR F 4}XԞ~V14r Β ,E,2O#&]]5lp2zp>]kJl#}e$z玵Ӕ+u[LTW/Vp ~1Cbm2icg~uZܜنɇ!UM6P6j;^~Lvdd!B0¨epjD"+zV ud5|), S$q)”ha+2ֱM`& r EeoV9^Y^ֻwTc);eRuRڮb@IG7yݰ֯%ўq4r/ٚݢ%븒%jfLkCMy|~WBH&&mԟEKT5PI:`룛}H!O2GM;]7Q' (.evҳ].:=0o\L{f뀫hS[TB!A}go S?{OwzϾLk`c玬8kJ6 {ǤnEgàpJI+ XmRB?$=#TjDG7_"g{erʊBYH`kv}[Uݾ%H WS̢#9ҧ3ZOŦC u(D|4swU4Ќia&< 1pn@w;exujEJ1=R(Gz/mc*g!c,0|YE&(C{((~ Jd&A/瞣e A T܏m?#)M\h["LJũDJ'A8]t=7AYLjH"J^j57[(A=~fEVncSgF\XO>Gν}0z8| ⓡ|,K۴x14pWbC9k6Mp | 8LðߜÝ&xS5;-9ٺ%?7OГ!4-%+ =;m({lĠ3gN&]zoJg.Dn0ĉgg1͚8D~(oOI[N6V0'?9m:ϸʊ2tNv+6oD [dՏMU@5ӏ&QJ#%RKPv/Qz56~*.\F6M dRRSzWYeOa1 R~ M}x}+VCCЬeKџv/Gij|G*+DYYX=١nH,l<2e⎬ 3 ?=}5Ϙhk('$;IN>~ٸ.L mג9Vm;Uh6\*dJ:9{ :NڍLz w ל჻XOk> &$gUN Q.X0)e?>[3aпʀعz/ (KyKgUyY̥LN8}, ln_c3[x8*,d=]\V,Eч.YtV5^|Mx]7f|NUStȘV*#~ x,{ѳgNJ>6qQLp|3y ^ ]Be~-ukѦ㲤v wS?>KCІknd/ WKKR*I[C8^C0aDC14Sv®e1,r*EMբFx㟴e0QKqGY\FE*+ǨFelOX}hϻg }}̟|F\%2B[K)G[9tXlFDDhSC;y= Kg~`/,*gV6(v7R{aѬtn 1F8QKxWf`dW5:20~ Z4Cuml *2GD0G`x0N@oHÉLr@Reu N>Ah@YP5IGѦcr*NCw$bg?8Ȗ1m=+ٶk'L.^̪tf"5ٷwweǂ)0{gas^ٸN{! *ۖ}˸!_fmyUIQ=YVאGfR(.~nqo?iĚ$Wwsuyee~%lCf[wku K:Uʮ?A&Kji; Q@cǎӳ hϛq)D'.l^+Pd>zVZS\E vn7@0&.L5kx`\-!ߋ#qoSgխI/nȷfFTFcݒZFkJO})uCd\&C+u,Dp墂\d`jgB#D|iץaUV2LEM#cXSTEGC#/&hL{3xźMdT1N=΀z%i YA2dt ZIQeE)]v+ҁ}3@5A9D۵WܹxWPBa'oa/kQ|1Z1X5ޮ8~8 U0D ]GZQϣ]sthMW(6(z_OQdIdߩ%?ۅ-znd֔Ól^zn[ xrfNpm&mm3q *TgvlG&8MƑ.f^F\Z\mG4MZGPHJL"tu'#H!G&Y>ں+$!B=!D@݊(uګu}-ŝ@A"] ɿ\&\BΝ9sf̑Zm$]N1%$Vmd qI=u]R ,Avа/el&{0;fp3c衣CN2i|hIc=aŒV>6Q4#l2A; 9xtΛG) LeI]D3ûmS^tDͳ1 Sc}$[ )۶5l{:fuu2Xûg؁@{:)#NL|ғ3N}Is ;smjjll ԓ m5嵄pT7K42ncCz@IDAT*p&| v\ #>\MQWֿN@ӍsWMI)m1S㟚\kyϮ!/'qh[( *<ǖNHbD3 Ik ()@mڭQD͓q,o:=?Il<#]s4}j1LV;{Fbw;6h$RJڂ7>H--@` ԄK/lq7 KH00};>yq"+eA2=zڿ{Y ]p2<?&LhA}'/o|yL8Eql8Jץsdڗrl~ 5CwPn PaIeO C@$I& , r28С*/Lff;@GTUe"_Y]^#ƺ뎡uIEee4&GSUV*`llKU" =Ęٔ5v2Ξ N: 8 tp}\XzFeRB0*і,ΌmgI >v0XQb"1HT#h`0 ich75Æᣇ)2/q[Ȑ4ci Up&FU<лg[^qٛBwV:N,LO9M/><*U 3-ϓ<_w3< BﳀȎLB#OE;ЉNMXd:~AEd)ᵫa ^0unAo`+n&>I憆+ :q[ "^ߞv}zE<,%BrӲZD&cuf(3fpS:`SN_'N`֓!]:izPQ joiqt puhV(l!`*9D /0 YO>! F +*ߟ<>[8A6#;scZ0\C2m[;:JI$}m +1*%{mz&U9sf #8FhJsԜ ջ|^w`*c]@IJN98G(SvE-Ac8ˈ=Xڋ۵tX ':QHQJkNT R@Sn~P۔jk d:jdS77NO knI!I3pXh%  $2 yL)\-~)(ɔlj=YL6 TD]D!+uBX'$K" C.ةH 2~V(C:r_]9 p3kG+Oٗ@; |r ȶeDDEqBP&/Z勿Bsc cԕ@Y~nHG7'M-B% gPN7Ϙn\y@p`dD^W$/=6pc<'ȒĈZol$:玝DjB"rԜj]wOV2}W;b%d;ٳ F9PJJ~TYdžuT1(d)it8S8-%dOTʕ ;JGRt)Q_QnYuYdw jwn0%\[^?/Aǥ0.cPm?-AOK= WҼyN8us'H`RC뫜YN-k;=Y4=x4PSK_  ENG4`;/ݙE7@AIB) bc RЦMkYQnrja-?L3(w鏴|0vQcHC~ŷ2erx8l ‰*X02d1ٹeH[V(}]1&xC!FM_>B #RY8{ - D6nn.p4iƺx%eDѱ2yn%d {e'g*,Kaa|[أok2/HMi(J&iIqxqLL{ -ru`(ϊ%w" $6>Յ]ds V=nd:w3dl r[UFAz(/`2^z7-v'"/ɍFvmۣnsJ[1ޭ>~_F&p-sv-+ U G])lt"ZG'Jq2U(-.+F' "ҰkWEFLigŠϨGmxMN]heѫL{&i YWС+يz3B['_|d>b\t߮ 0}%nj^y,v(r- W)G_3T "a+OV3d}y|gU=U%1`u]tR VA5/E9olQ֣8-Ģ$E$Y{Iڵ4h^*S}C;[8_wf/)CG\[:VI ><Θ!dϚ񠒥 XMqRGJѮGO^^:.E)2&1S@NRSl6$ۯΰ.U%S!N?5%7bE3cPNGHBJnFǹ;Z]t}L-&W_y(,YU7= K=eqr͸wZ-_Pb9WaA6YsL.j֌\}f)ƌrOw!" b9,:cv9gU,T93O& <32OgSaǂhMۥ~ ~}0zx|,N/RIt7zwE 3SGpTՎO~YsÆQ|؅^n.9U}^},*R6ڷc;_Tj&.;r- ;h6m<Ze|!ǑcKӰ/.u~;06þ=ǹX u5c| Rm8Mjc 4z5PAN'37xU׺[mdpR?yJM7| $g#Jow:_VdۻŸʛBS"80ǔx];C!b.FKAv*=oA +] 3&!#q(Vֶҁ FK7gYh! j[YذfUoL dI,y :p}n~3ZS!cMjιa⃡}mARYk~p!|?eq05-pu`QcNîdcz *}7ե)k/cvO?]*b F)lP+*=){UW10vX `U7V\EJzNk~d0+AwvF!Gu;2r8v s7SbtJUd^gZ'r~}fGpG z@km.rߍ15 GVmk殸ڳ8ʤ3}pW%^Lˇez$@qH.D;=med;gdQF2{Pz|CdE *Y NPSkM̔ČgSБBr,_=uJJ[#, C#zw±uؽu)!J'7_KV8~cPJ)O+VH AжNmlR[s+kMi4JE9v>E>l̔]6pn#G+˥yJo6)gYtZ2sVz̮Rnc_M;?th悸\=0NHq?QgȺ#1ydFg#m@od&M@mbV(3ݲm:LR؊I"99Q11mCDeof HGnԯd^g'giiB;}oGP}ӯb}=dnk+WpyJf[Ìj;T9py9p0(@na_{%p'GSj,cdhRQWܩgBFd_i/% hoSU^nh|䙺ZZ29֠aWàV=v5ANy%NÒO9iATܿ7?T?_Nhӻ?.wlRS!vOZbPL>9<%IBL1h͊*ԟME>W)d|"8R0梫 ry8*ﭼ4k ddE`_AU<$*VOýD*8ZVN=,ĩXԏj$_y>+Qa {O82^܌D0u#0jd:H‰h8mr,` ;]51:>URy`8Abeg}Hpjۣ`SX[ MOQWZQĻBYLŴ2Oljͭ(Y/2BJ9V1)2f/R6etva\s]V5<BʭWX ؠֹ>˲^Oi'+L/W]pϿ{Yy䷱gJ/=ĵ@gb .?ǦOsZ*U:(QҹMeGݫ/c厝xr,*kztA'_|Op SyHu&ܙ%u C8 נZ E:tgNq錑3LHU3Nq?p߬9>}rXEEƿA z^8PPVefe(I'{2GK`:|z.Dˆ>,qD5K;\4Դt\˗E9p`Q3>l1zz՜vT8?uuu"e9(67 htQHŖᅤTiwdƧG5ƏX{fƒǞk\P{C#ՑCę얶Eo vj[7֖VʘF98=M'cIj,ihj:a5xsk?ZνK~6Y^djjS5kTSvo[tZq_}Mke V1I]dYvX1<m;S6^O6V4 =eybݺ_1i{nXWUJ*Ymx8m/6d#'"PV(E|=iX9|x?쭭}O#E }4ԡ*:t5 ]zS)MMV~KWTdcEfUuE J^xEpͿ ]kg\ӃJb_LFNW'lPB'bcJ}j %xv`Ca^R"Ӱ> gk56i2GKd5E2oE^NIHD_ɒ[-1ß_l,UfL :=5@Ue-z7{K*T64T'29pu`! ;jq4j'a-ڵqr ,"#X*nSΫfzcWdƶSÖF6^.d^AU2udٶgfm׃l2dc$M/=5GSq/=yRN=lMʯjdJr`5ûQgL;[ë#k".6j& cn쨑W[Ny &ظwja4%u#(&t'k3xL5`l; /XHDw̚5WݍM-1}tx:jr;gF={ɚRJ~?~1A*ޠ2$voI >l ;z<-]_(klb:~da` 4uյ0CpVy]ejb؜,Y?N73@CAb$W{j'k:<9Y2R3Z`LT <\,ΝdD] YN禠>.v$,#*,s72ݝgUཷ)Et04|/ u`|uq8ة3(4J2fH}; 9prkW+K)[z8#RX}6~2\3ñ}zpA:J&vUV?$#|$rK=f0u7#+[8{3?.u 5c?/`Ic b>X *r$v酅g1Lb|l(ݧ1Hj:뗓T 0D>>Ɩ2JzV$Re_֗q oqPS ܗ1iX ٸe7f;~T3`t1t 튗Ѽ^-B0JJA҄E&ɉ_)N+aC-CY|V!0:9w1 bS_edC>1섡> ʱ"*c:5^6N fc1"NQ6K@r:lXVtL >kW,CXTڊc;ғk̜9?EQiס#22 |-R]{ŹJO0IέG.صw2:n<%&1B@}oA kW~}9J[vӊ.~p.Zcn^0֧L=>NnT7_kPo\%AO2'L|([tҸ ХzNwu>'jϫڔ o_]~tvs;iG>H-kTV0նNi]T%O1pỮȀ ֭Oߙ%vtEcA#\<ܣ^] 5Aa;B /j9jshEd.n l)d1flkt sqr=:3I|ǼV(\IZ2^-垇?~ f}vX0&P3obT#If-C_];PVRB9bc:*ggbC浍"gdjr$5?ÿ/*J2iwD$eK悑 &*9n Q6 d=#1ZvRl3]*YAӐC;$᧕qԹ/c-~+19߱x6o'F:hNI{Jr6.b?QNqMd}RFu#0(S':Fj۷aLҽ0p8_YYAz# [ׯ޵fD, VSz&9"aiL狊3KsM(I8QctU飮*e)hI}xٰ6mjJ RZ\oZPK哝|֔n}y^Fp_1y"{&?X`<`UV0%%'cO9t3z2GȈdk1:јع VQ{9bxsי! FKc{X"s+ uu37ݡT$HϨXFu1f6lq%WWҾMw>eur+ ɍ=) ~[9(: {%NMvX'H$|6uu1e::cH'-确k/f!=chQQӒ<W{yp&*qiOcϽ.z0P%1NU9kv-jc땈Xgڇ8&+%2`<@e *6/^`P C'x7`511XD3;w >mn٠A&8]$Ygq\5``ki988] >ر4+|yxjޔ~oG CxJ$&F~d &CV;\<>\H|.z_,cGꌧ.A2^W~ "0\Z  G[,_֨БD~~ݶ@ᅹ*&4> g=ptDSBt4Ft S 9#&eЩd VduwѣaTqVE=?Yxeر0r~zY./NDH N2j9R8H -%LTͳ|ϓG9QSnǤ\PUI"1\PK7i`mx~Q%Hݩת^ z">>E~!^G~=]ajdP,sV=sB2f_QOz7Ք@;7]t$o:?]\f`OuǑӴ_S 45PFi+ʉвqBÉdz Ճ=_̇)HoffּlSN`D#/iDIXvez 7(#Ɣ"Z :?w>v׍devVb͹GdEJv -fիi,7@wo#,Xb3u3Buu`aޝF2"ׅ!+'"ђ WZƣ%C ]$x]Z5=4twc=?`'ㄒLe;i DV) x^8nXXZ`1X{LH]QeWK8w+2&C.Zc3zS? xx>صk7E{0|g@zzWstken$G]ɬf}wj6;v(I^p1ȤZ 2Qc98Iȼ@מ,-%J/$ >GZ֧‡rm:96vGQX< ADRcx<Ե7&qsgaAUs[7Td< Ď_ )MLJ2|W*t̘4MFsK0`sh)Xn_صHYB@Ы}m.}#p@[n=X_πэ'; mUdԺ'> ;vAA~x"-<'q1pU+Qs2nc2Vwn1y 6]ٌ\Fiq5&u<Ȱ, H|L>},`;I/62հ32Űw* R1L*N1:uQ۷YyVNg e2p)ꕼn&70#ph g2AQXil,,bXH<^3 ^%SL!T4YOcbha~u"t$Cѫ@`UNLEVFIa[U"lz:ImkdCwvR> G: XJajs{%g#ǏVZx"tuVzY|-`ՆMA 3xyvQ"* }^G?ٙ:::vs_34"*|M[޲+/{$[ڨby k- ɪ:{Fl=d8/]a:{#GoBރ~@mu uZjr -"},]1ftja7XX^KࢗzjWi8IP{NJ/p ,hkոr,ynXM2wtªTce±X8e&E#cLX:qb#ۣp%#X;L`bߕM82,;9 Q3q! jz$L+E$}?a]9'03Ookطf5 .A՟X#s 7~ܱUK^[_TRL>a"<P B콦Tέ<cK/SB -M[Cv|5Zb~0=qو'P]S$#ϳ64`8⼡8hIKh԰!tt)7vJNTD |Tǂb9~ T4p܏z]7Lۯ.GQ~6,nD/ضi3q*PwKl<` G;Sgm-DY"owFj2 % bef %_ռwr/q'T *}j1\~Cp<,S&L hιftt,O V˚r,aN j"EC;~7N=ډu!ש!֓>˕t#CcIG.xIygI s_S}rua0g/[Çc}C:r\EŔ%>AHHOG(e9%T_JWRRSy_+ K{RT`AQI%%.#y'oh8q s>HIJgq2<N8NTڙ _At2>m`Mӷח# }TkY:Ur˲چI$s9:WFiټ*_ rɵCKӞ]Z uCsN?vsgNs#~V8 ҆cM5r<"cPe:BhX;q~jHtMzo5 ,Mg{+p/tny9yk;dߔj?N:EYȱF,Eqdڶi/U[g$FtN6nR3 CGNVW-6!ƧeO_Wn$=K"릭ݳڢ{dU XhQJ:,.Cĩd?ʠ䬃ww4/S9wB/s ?HfFI> BA8vE利d̽xC@/ͅ˥0\xl^O9 4Š]&F2elp2klL0v`2 Ĵh1fW1^76Df^4!~Ј,jpt308VNTXh|Z!5t|JcB[Ϲ*Y}0hɸ"6-SGH<ă|ޜgk-+2O&AL@Jd{jG=]|>蕅J#л]~AJsSRN9dԔ՚@p~xQ ނӟk1 MGuj E]:C QJ2SL~'4rJ$ c}&6,焜wsI=ٳkZ&?t<33/=]8 }}ơ;v @]hID32 (}3[Dl|t #zkn +/.!{Ec￳LMU=gQ*lsѡ0\<,gE2& cƛ;s/*eh=;lhO|%g'h7#="#Q®$΃0nȋvG8x~EKVpԀ}+Cܠˊ)z왓W@Gkܹm:ц,cK;G$ftg-f ᗫض^oV(H3Hm`:DF6B>\oN9~a5Y4b~miZ^GSN韅"J2o^q`~u.,r'vxu(hrbbSPb4Sqʠ<4d`׍ qaN.4!ke\ut%q/!+: iMGW"1oNt3 2+)ٿ cX-G\8mzтxnzHzMW>nR 3Zhh}6'!uy6򏴗j{u_Y}/?W>|/<)RC.dPn۴dxx0ƶEɖ\FJۧYya>F 0' jfeXH[(t5 pN5R_REdGz/#o5~:#l_-L;Sꏱk>:!*ACGSʟ{~y> ,>\䙔aMCKkyA6;¿Ǖbb/4&2|YLC0cst> <1t uྵ [Q52*e ȚCgnTLk[9Iq&b˘NvE?MQp m"J3v(naAG;4Ы#>-_}=1-qig"lڣFȣ:{m{*v;uyA_qv:zlm:Y>N rI]S~Z$]O>x^sQh~W_dfr{T9%K%pմknż)āSϨfa"%]x%0p |b)+I H78ٶ_y_'zDeXOMYe,(+:|N6_Xe6t.(ӰxJ.~ҿH{q$}OsΩFir^g:Jm>-4Ϸ8Z5,SSYW.uu 7Wm_?q13NM?qRק#>5@+:n?q5 깩KV9BS)M5T}9dmzX2R=ěGZOƆ޺W^A0-z.ΌWDfLSj` YONFq_Nĵ:C<'-ʊdOTNhݺ 0X)w'G0Ak k_=&FeU5]PsfdR>3(pY43q'62bvyJiRgR GR&90굪2z(hI;c" UXqFg2+\: Lވ1Dt%k4E Ȋ'zi fd%u1AFd9bVxޕGN⒞:ST|CEP&P @H5oqA\Q^]0h1KEVFu#`> S3|t~44Jz`t?zwCaJl |) HfSi$ӳ.Ġw wA6ِ_t1YixiũXK5I,_5c7} f.wg~&KazoJ y-l!]TPϽF1 @I~xk 4JiݣgCuAuO"e\b :{ݨ HFweiXe4\XJyd,lWߜ8qeFO5iݸi#>n¡;aif }'Wf|Ѕ"z,(2% 8r=8 jm2 *ʔ+hGVKJ):X]zէ'Q6Wsѳ[T̓Q]1N?IF'fA铧hC FG32=1e(*Rh\ߒK@`'cvg@i]}e{oͅw;?W<ڣ] 4Gd<\X*&ڞfdfw[93|Ǝc4 }z1Cv]">?I=|k-jj2UKgdzHKC)5=p.n:ٻ#)Hֶty%d֗qFBu&hp?3 gg:sA6:* 0e40dSӗ(Y,fZ)mhͫ,^>#Eq9| IUK5 4ff\oSd B+QCc8^>o|8}6Y\)>gGRRGΝ= H %1 cC>s"UUAG}==Y<{6Ljȥ×kN ̗\G̺R# ]sZ:$By'Ѧ 髄"2'c$劭XN~c,6R Iڻ)_Ŗ?GJlJҌ-k6Oi#wKG׵ksOgնq N *0d@hkJ՞"m@ci'Ĩ~7K}N?/(Qe1|;bbb9eM['oہh:9xj=/ҁa:{M#rQ7g}j8BN+3nj?_b hZ(pmZWÏS"?ĚHd ::ijA$l+ ;-2VϝIKo/†jxdJ=WJ߆ n OuRHBVeV~>[СTZvJ*kMaG7GlVJ$"f% 2з\ØtpKW>Kip԰ f؋ ¾uM%E~ #Ud(Lch]5a4TJ49$y+d'R-|,h!~,B{ /a?Sh eRrzlC=BaI>y~>7 p=]75GA,k>?CaK ۚ:Mkd{ v k>(2ɸ$x& VG 6=<{8 :x(ڕ{:y_NE,#Oo_ L/W/Lv'.^A &+\T(Ye-}z! upp֣76]/5]>K'`S)eLǠQ)Y xg~HFmZlԑFy fqgWoY{+Ga5^,/c.z3dҶ}fxs"Rxplo->˿E-۵W$_߿ K<~/_"J g$Z﬽IY^t 4WQad-[!Ǖs:SEaʲ0jZ_{)KeheQ@zaϹ6YVː;ᾷ_/[HGnS۔M)yOnƠ)1Nכ42FO3~Y^|:ֵ+klE|f8ZxNM>^.9m廹3?sJ`SH!cZDԾnuPY]>nר]kc٧ϐ/99; Dž J.2") FiռROs^8GpT>Mmb ՜v;rQ4kkPUSA8ato})sŇoϦ׭iU'' m`}/@BtqkH ܣb †m1̾9w;Tz$p\ L{Q|4 Re[Dm|~ނr5H|чԓ##ذn6o_SaUoJ/W֝o&=8R YaDo ?,^xAWmO7 Z< E%xo0㍷ѹ;0MEzF<}EsT!UF˘DgԹQNRGz2Tjѭ1֜oܭ4k.EwǑ6Pڭ+~UKy  >Msևb{NxMxLZuگ[`WGD7ɢFCI.9QKc y:9o,\fmPo/ٍ"씑‹oKL7Q*\x99Y{u' WY)jWĞ{]CW ɰ޾'y0C;F]OD~Owɼ)W)=iL+צes2ǟgCȤSԔd搻߀0L>LhȈF6M+pl[ fn(L&k-y##Жrʃ(yΤD(![!L0VV9i '6QQ¶YX DSQlyCJ@U N]Gi):p/* фn#@ҹlkdh9@qԷGh(_KE~E*Mql, 阛A9=KOad-,CFEo''0?e8q&ǍGf`ОJy"zp|<'!吽,#D;I62ԍ6711Q ݇+IIp:%oʍʢٓ0j$uhvQc鮹L,5Wp:!|~2 $z9t= fti+~E+071^cQ9Vd`ߧC,Z1߄,ո;E61j(lm5/(#S GAAGOqab"+1l'IM>| Jn5 ED D0f)[9+5wPHŝLwHfdl}l81۶]}0e!Y';dQ 5$' Vl\fdkS;cĄGpjYxi!Sgt 3x1PAsn.Th7g|Bo/6)/O0љ==: cޚlDn]v Ԗ!5? BṡyLܜ<6 tym*NW8s쨞vn)OL*h[ԝ?}&5<6zjjXϓl]E2eX$yWe>u{hu \ 9cff P7:kpqeG6uh*gܓ *ٶ}b8c4;ʴD( Ӑ +d\ZM{/~6|(ߪ}/Xx gx\ sZQ_{ũXouV,Ɓͫj> JĉX߽6]9iA݊2GgTaj3K&)Y' Y{Sy< SS>QꈳY{Uֽ6Wʊ[#*R;ǫ=y[)R0DZ놵z'pTucɌ"߂u Hzb1ezilܺ,{dC-Xe3m^hx7~}/[Qd?od}OjHn~߿z6^wub/%`{S{.]K. Z8VO> 3?a.Vy_Ȉ҉kW1bHe=3mCEr)v2'ѨQ;ua|adns8NKfI!}/_1Jex9hpCs!KSw; z"}T* >'Oƈჰyt=[h8!΋8s .&L/7Ak>FN4OyKQAEY13Oňq Cx-(z7\.UG5'r%*.&N1\pO==e<%}Zdl$ϼ'ѨexI[J]d,$e|#vA^e/s8]!Ǘ:eV~6w?IWK69M}d]P@9ڪu۶} ccCju#:au7>W2r4SV}l T c;0\sprt-;0uȾ|E-5FeN:=:GЄ``6UUUh#I;BGSNBڴ T]pT<:tJqv(1Js^ݻ#)9/M K yR[({-)8fg:pd2gJ 'LAVOٻy{1?rkVD~ (Cq\ bc)r/>2#Įe^ΔUHc>cgcD8gܔl30磏 >}?0 < At4/ctA50ٳLPőN(UUNeNWAk"7q9Ȳ 5QY^E96,b ~ 05 JjVjb,-*tu:s&5RiNe-%L^|dz jw]5gwe[СJMJ y.O^ɾLk=mdHEiW\ʄ_\fЩc *(9$4.yR;#Fb^вm{0O n66E#'>`3ar݊[o Mp`v=K:EJGYtK.k `mbuQѧgO4kp*Z _2p~2 yq2H77H3^|aKv∑x/1bvޓz& rB:›LH>ax )`1pde)#&2w!V!sWhcq*+Q3k[TUP8 ,Y3%\(uh˫W]Brqȴs_i2&Su{H,gJE" 5L 2d4khU}PaM0 7n:\gkzuA-0yJ=U 'c_`p>ʈwW$!UUꗗ郘ǨuO}=:t*uEUV)Qg.C@J"jNZvyo+([*o-ɹ() go?tRWe/c !@f4  ЩJeqzDHK_zIZG&\*MyBLUTS=+d11i 4 BL]G~hagkQ{ ӊldT } Ij%k9dUZU ;x٣Za (XTM3}_gZع1/]mkМ6(}$Ғ081 zs?7p<|F7c/[0OuW K'M{ `m ûqI}^cםr\I'`2єzc9J%/0ݭݒ1jc%ĵY"жr,UWǤ\>fL Bƕ9;ѬӮ[* +eΜZ"3[`Ł?u77ҥDݵg?y%kC kpݕgeİϧ1ubp&}9|;h2b0̖.iRb?0| Zl2:;޵۽9+dL/r# QJJE+iO!`ҨmZ5}!f<`sd`olH^ӑ|ҮeK4)ї.\1@픉0h06-7GԑX -A1ɻw.+z+Wo5?112&Q٘"5=ѿüp;zUfPg ΀>Cޤ]RR#Eo`ZS^K2Xl{`UH8HoCLuאPY}m͠@ԴQh!w{~r83]ZOCMFul h[W9RWjf\W4@c -wዹs!7^_}d3b}wiYDUPoN5*umW~u[3>|W``R6npfSJטD0d)e-sqE]0ԪuGXe ev4)N&Ftk6\A⛍Qdaaw䀮=Q:-=]$ڳ B߄YO/\!s5TwK 0S.o zf"RhuHdg_ [mBIt5'톇 g#vmSoY1AS__$]LS*ʣcp`jJPodz6[KԊN{*EՁ--.o}{wekiv*̬{FUUYd>Mv/U@>GmY)N&qJ*2 $&ZWnt3&!@ /^GZ~9ٵ?gqgu3FVpoA)Ǽa. z}p'= ˃%ϞLI*j3\m%- vt'ԦCFsƸ;2/+xgNE!O_tLN.paݘ˵6lA~~1ܛ231v(8\&G,ۉ,AwB4JWPج*Pxwh߶]AVy&U۸\ iGPkU [Vq"j]__931y<\r o 쳝^AGFzRlV0nMtyѩ R:2_hwC2t"+גX8`R .,3t+'r Ο;@cBާΝA=7̩| "=tgZ2f8壍ɚ5/T9|8w [2Ħcʣ Rɼ7>ʱ0О_œvHvi^W)r3(ћ' qrv`r֩is,ѳn_Sw!`=:RŁ fw %1i0?o92B`5 @R) lZZ3m\< nCMe .9onj֔R]TPF0G/AΑ`ln\[#*, 7SȑH(HΪMΓc?d&?p-). J}jCRJ@äs'DW),u#;ack/KƆd^D?~CqR`U V)zyM9RS-{=z&*"ϰF)j=qM8IYc)WjKf.%kB3O]nOuDfKQ5K d8)x$ VX0{Y N :^WYUkbGKIߪ3Um;ZVMʿaЈ7Rq22eiYS2Z 3p j<{aca9hj7!#UyD?jQR:| ,*pF9M-SȾDkj;Uqd W~V_f{[Ǡ.Q\),l{KAco?aJ! 7 dS%3І);ߌF QL o~M+25سgT3/ Ϧ@sVP*_cω&-+oS4A^i8g{Z6^;+[E|T4=Ex=6WLFBVq)\rю \`GfCZt;g_7i~dl3`,T0j"&&y|.5}HސE-%s9;5-4#4]DjG@Y=9\eיCH|xkij>K^oooJ @V7$=0AW2Í~tƱ|,YAxwq&%eLE# za|f=ѤISd(f@F-qzr ߑcwGL T-_Ξ ?C͝;QH걏*94%&?M ݫy/0K=#Ƿⓙs9F{p.E4!c gW#}!ԓ>Cl U(<(,uhqn ~f@vi@+ˑSs׎/SE6`\:]jj),~^Y8v(2xWW)G9DT8 U'Wx >ZL5Ft"ep#| œ ,CFG;eK'!EnUhyTx 7ȢӜ"fGx LTJy2h9hN[,.pnct0Ҕ,4ow'$U#r"ԘBЈ2npy.5ڷk*cgϡSP0nڷ=EbbTu&NnF<*ˏM2c3ƪ  9[iWO~UރZV;'T][)GTOY\<N޷Yux_kEU'n*vB߁ .im=C zF^Чڊ,90ay7䤟rYU0p.-Z/ yy쨀&%3g,芠<)d\:r(.*wDM2? 1eL?|[Ա>U:'cOx3[ Jp3c#*mq"- =hޙ9=I==~_|C"uUa*X'':ٵg}LEVm =Ux2bj)V ,tܡ%XSصiAVcݓE3'>>{Xwl}NWU,`XڵklCYnڻ# ~vP*_- ǚۨC(yraKxo[^{`-(/U@͂Lv)`YRYW}9uRE`oޯ󿜧}|D)*Sq!a٢$z˱%,ތ1RO=<=a3@IDAT8.q+M Sx2ǧiKҮWg(ť%JtxVn`^;f,,._ ֕ak7;4bl<|`B[񵝕鯯OU4Ԝ>2/c_ L?~}QAQ9hq_.*krL2RbUuH stE!amRy7x}}n*xIO=-۷"sgo)ǿw 鈁N֊bNJ]P|brEBr}bS+ 3H}'8b\I8r06^#3 E&̝qbL o]+S#2ꁬ.9'ǁ}a|;O{\/ݱYlK ,wסvd?bc&G%*(5jiyo0FR6tJL%b4@dʡM8p1]"^ "Tr:KaGH&{7muSWJ4Qnz8SX [ͧS16`N\Ǭ2jueI4ρ#k< {G-웞pWi(2V"jees)sZ 7[d͐.̃|W|rGqy̹өSWp3?]Clzf<Ⱥ0 Yh;=LiC 7o$`qtxh*|e)ZY6tk1QNȖa52(sD,5o(H004&/%?z-[) \_=sN:NgeE%N\3۟CqK]CѴTƜQy4ZaCF67;'c57lK02,q *}e;^X}9j¼@s_4X^{EꋸD3ƬY)FfM;\N9tp4-sE;SԃĶ)|x7`lf=yRtA&KQnB0ԛ+ Gف&DQג'%];&MŻb` ֠Sn nV99ZU+<^܉tbsIsF* ;9^?cj`x|$#Kc0ğ?}GS Wxg1q18XNM\K6QNxݛ[/ ~EvkfNO#^ INVGEY%N>L\7q` 6l] _[ kгG$+SPtF7uWrfJۇE0& V<Fa=~!CFׁrw,w+hftys8#d`͊_gi KO3TQjn>. ^q81CJ.Ij#/9J:*kTf KkGw.1&zF|PAs s4,>a{WZٞjp0c6oVyIgҼƪSFaq6Wt7mQJ|W ,S՚E7KXW+_\yHIO:eR\224 R_:}tk_:T C>Ό6^!{n&7sT$ʿn2~7nE`VUYufB2s1﫯O|0c_Ywo{G0pJmr_֗vLq@s_OM\#蛅%ؒ6G650Τ=-;)˱4L@ Ie֥%%`V2Yh 9fP)B:2vkie_@$lmF߶VÞmg%(<;{cË׵+'^Ct>>bV>=:=q ޞcx{/N EpNAd,qX s5<5;`qhݞd2b]-NA HLƛ>ŋ x+ A]޸O@5ޗz9vMVdl[&7+;j'cv)l>EG1kՏ_vV*6Y S{Np5bd<胺_FM&A$mPl,Gh|}fBHwɱqt03!]7YtR:.;ӝ^OJ3/=#f̩~]P0o y'{0s(g O], YF]z1뽷yĮ7Jw`~dz(R럏?l8Wqf($ZÓ@ͺL^3tlNxA>6Mx c/<?8n\m<w%^ ߛH:STy`hКQCƔ_ cifZ}C|1g>rߦ]NH\U+"tC](e5ڏ1K+H6!zGavUeXֵ#}DYOHO1r[5 [/i+ ѓroxIQ` 9ZfI/WY$pN>n*rmM=VC=U 'l|[ygc@Lyvm,ﲓSX?ABcL9y`;~-Ydjjv |XΔzJ0A27OgKz ^ --yR|6Ԡif}&Ō2(%0~l#P h["H;+;Lyp %3kp- t;8Xfmw2wgDP9 `W3=%cI)(Vrq(}H`)zs#\]r3γ1בQѯTroڇ`xaF`;Db"MXFjjDJϧUZZX"Y7p&w83SFF-e.đFg?t^DyyM 60vOekkж?HH#J;}%+ k ZU IiXVOֻq/L*`DEJnCF$9t zaw;^G vW* n2{":)1QJC{|q'r\WBՔX7XX`/fn&&1/X֖W?>=wqrtk?m;"/ES9sӦ73^~YSњ٢;xy#8Cf#M#z:_[Ua.8g:Ӯ\1غc:moMHP:C rщ{lj m AUJ||,%L-TdhNpKʯKixbn⿫H qG S֘$%mjlw.k`h<8k. ij{̚.†CG~ x74C~>x]@Xsdޫ8gJՍYj (IC2Crm(?UЙ_-T]SM$!8(UvdR;H9lc~if}<VmeQdLa>񓈿\,Qĝ=TXJ8ٴdʢ0*89ub [~r?U{]!PRhé[60>h.م1p<3pvBxh6sD.`6 6[tr" kC?r ݌‹ڽ-S}tcbf403甎?˹E"{ gcQS&?CՀ޾en)vAƉRsfuo~Rd5纽wظ|(JK86Ac+/>ԭ ;SƿԶi;5俢AK-  1j 6-AQQa4/vr/_y@5BGNB)+#RV\U?U@ֿPQBIC)i 5?d{;OpyL䁸xk0wv8#"Nި[W8Ղl)5'E2%PUאsGw>N;C} 9A'=fcf2J#3zE%~5+}{ګ60źC`(5+{:'xetlD/:2澋R 3ElgE)Ly+}ʜ`[ϖ)g +2;9˜gǗ`M6,ьS`C^`yY50S0Üv/Z]ƕW̉UN={K)+(o6 Y.T3ɹ*`k E1Q&2U-dRYSt`ZMn&6\'mL1ጬ|@G ۶ADشn91,̇בSh ǎ\3{GlQ!Zt5%ݙ1 1^^N?DAbAl頦Qɏ~w.xАJ?O3Qiu,f5Y#RL"O?ܦe_TXT&8О3`Uv˿|$8߂ b8k&.;tG'XΞ?~w< GbŘ.]qu2Ul gۆu-ӟ{؏<w s`H^xQ`5ׯ ˳~5L0639b t@mk&Ha+މ[_ˌzQSFIkh.\Zlݎ5 de^OEێDۨ]oCAګ*}{`qJfPYׯR=l@ H; ߆֣fn2:a*)FkFvdoHiO',Ϟo} Gᅥ>4Rtwn#D:t Z& P-~6|7JM)(ܷKqN)'?*%*<Wll!C(MX})"mp 2:ڽ%z tkhŖO&xbJ1j29j,(-v>dp @3g,|bi*)V:3wrĻ!%? cduko6dHݾqN͑A Fxo>)F&K#"D:󅳶 M-űiU}~83G<3[}ʟ17S^E `mm]W]CT un9urmC0deYe*w, ,2W̬z?A_YnchtJE8rb]{oXHa[n:g9TֻwJieο\ >gN ?+ G }iGŋ*\Ǽ_XW*$VtdrPyf =iKj*stf? ss%Zb>c޾td?߶#$ʸO^T@59vMu-~VPY9]ۻڭ]Ȇg<~ xkfi 6axSDB-Wr۴lU=oGUe}ۘ=lżϕի37U2 ' ' Дؑ|s ӟ~y}*$/7 >rGEÏJ'ǘGh>b4H؎?e{MY+`JL0̢_=CX(sw9n7RGXfJH}frSֽ%2^㨋n?ZO.D~XSߌϠЉ0+S [;;OaA amʡTugChWzxh9 ~a 4khQ>F>&._ڴ0zhK\B"Jk^M5}՗_~INlB KO!NzxLJ Eʶ%K:kSM=S9~̑CgppJ )Z4nj,\PUtRFLkuo1|G" kұ+S$28;#k2'h,{-}c7?A_ZJ"Tkld 4mZM&3wVnj_^gw ڒ91"BJtU@VZ%)N?~mF;s>$lKq%>1} ,Q@炑1̺lQ x ƚ&&_y$ 9W{Mahr0%dzQ8/-wŰGKzEnhR&,\_t0N2ge5[=T;\{9y j䌼xf}# "(9n!J I Ewv](# :d M.s[ERW^B7(@7r<7>8,tc iJ4eC7c?`Rp4, r*l.ۙy /?y %7 &%n_C|2eZmc-{vVhkoJIF9JU,E&\ykR[_gu=9KlɀRW^ ktv<`sNWU2t$lyi|Ě֓hL@3JӦÚs43TS3"J޸N.d ]ڶiMRLy&wsz/"ҽ)F}ϞbP}L,BtS;&‖I.p!!lQp)O SH1USMUݠoRi|T9* 2m?Ƒs15[i«u[j*|3?\k Z:,`b᠘37RK3E ,ٷZ1)s~\t W+?-Z9Πn6"೜AiT]JaZX0/"IOeҭd\ \puoWڄ6":J=9Mؽf$3;k053pN[Q֒rްtܛ; v/3m^ h"砆6)뎓ͺ\Z2b@JD)2.n^̽qXz (Bi0Qr>1 _~5 7цNjʴX6g1"D'%>!X7aW Δu`J-* :+fLP\YYM}M,KH|ҫ{\u%GÕ_qfOч߭JSmQh'#LbUSq5zlx}xRu:E)92fRMm+KjJ29,Ƿ4y,oG%Yg G[Y0Oo L}O~a$A"mcQx}Zɚp"摵CN{Z" 2^eag\ƥ8y^!#L|H ݁y+@ʺé+66* z@lvesr[_Q0̽~"$Es?r1^z /Pq<}mps'W{o񋣓3`)֫x- Bk}c߈Nr7.j9ɜ7S wD̙̿{3;i jNcMUw{-m*^raTWU0p L]م輑|OtgCuCd̟"/~(l}nhzE9ŀ21UQC QonDEG+1vJ0#Nd#co<#J \Ʀ j1hlwa ;mX#<d a%T)㮩J%~ansɀlNa픵w[og>| ~ ovQǧbq ;;4 andڔJ\NF5̱]L∯㒵`Fyӱ) O GړZJ?eZ62vUdpI ΝgWd oĄRs*ޞjxj |0bشj%h~g$%+ УxcA_TRelsy58e%C݊pe|*(ն{ס]PMb¬/ɧ#%f|B`M\8?NTw"N5ڢJz_+^7'4ғv{((`bo_M`v]Ɔj@ƭb;u@`)}W^{n,z쏋H&0KG7~ScbWdsќ{{Dž#$ĊנCǦFvČli*Bɼw_mhKyZJ+5WP aHڻ4~̖GcQ03&p8eͷk Yx'~D-U9q9QS]$x#t1,w+TN'{8Cͷ" e*|^я| Ҫ4Y-|s=}ζnCYX8"Ҩ;j_ۧI\kt2RMO]¹* =`ٿtzwXRg' AدšWȆn#uP iwQa|!GoTfx>%}KJʳ s._۩17`gs$wt7w3:GhY}&F ?E?ب.шCI+ 8S.k (OIM5_0dۯGd,y46!v![˔pKp|V 8 72nppm]1 5D9 O?}4EhA r9*a=1[-KVCcO~s)Y;@-]*O˯7zKYnC81ᖊnAUBW-Խc>TċX77OBZ%?hν<VGWnBt7}4:LDY|^ieBBHP0"tهXn|`**c†2 ߜ9ޜڥD˷qz8hg9hy0cF]([/:!{%;FW٧{Ͼ;~Jͅ$&Of^){fW{~C͌*ȍOZn|~ .beXi'iǏhF޾C; ](e*SXhiP*:SZxV,C]UAϓcus7U(S͋<h2~}lA*tyZLWx."}x>Kex@T-$t% N.gkX'b-2e2է9߽+ kx+A7AÅzaqx7QRTAŢ6 s2۴d<<j݇ᅨ&93y^T(!s}>V]$:y$Ї hß=&ig +20wv!d́2kơgh`[~(Z,WB{vi2׊S?6Vd}…/O\>'h˩0e˂EpY)LcL$XMTΕtw֠}JTߢ!.n-q~-MMaNww 0Lm /ִZ<ӑV?T`'`a hE^4ՠI0: cLQ.L{\y~8iݚߢ28n>"ABM#ɉȧA `p?ۦ&GxοM'l1D|@-R^_a9YʯDɯ_fS[ge+&\-;W_tӶ-{bׁc\S4a-04v~73EbF `BL3.amw3j!Bʕim@ MY#fbXQӗ|G~fZ枖U /&彐 L0Xι\;#/3e4mfip^vlS8s ADD^dzdX\qDǜ_;~ـ+d*ѲJ8̊tvcZ\NGM'ϦCD)AG"(B["])g`kO/z1{bgbO%#&H"#Ln4M>GNG'bi Ԉ022L'$K1t V .#Ð/f[YG׉l߾=Ӣlu2ȉ`w꡼AC)Ր^ u&'}u.Ą gdٻb TŕFjhff Ea)f׸DƦ&{UQEsjhWD:,V[ VS!B?C@T]\)Rgs%%clO1J`k 芖 - re6*z[ ZNY3gי`tM%hЗ=[)Wt"+:߻`1UW&3h^jFѧ\mhKf _GAP<(؈YQO*5IhQ鈸X gl-;!K l9E|=޹u MpOA;1]9oAW~sIqM_!qĽ98wyiB22J 9IGanQ@Vݬ9-c 9^v?=`ͱ;fҧy~Aj$7эͭk:؛1ݥQQ6i)\wx{ % yyEs "VK$ޫ/'|rΊkeSCvFfQBaW kb[$ Q{hݒD=N/_@ѲO*ͅ*(gKN(wW(2DPч$`dž{wc<AJrPsny =njD]p/D_oW#_=NTY "Ӳ)&QuNYJF'YKQ!uChs3LM7Ž҂E5olgi؋ؽy}}'#%%>ݐ˹չ0Щ<Sߑ ;=Pm1-{s6{*,:Z5zL0u?c&m~cFAS ͛gfL)t},TX˥?{ߣi3cqw>\0)Bc,Uo)-1?zPwʻ}V_(c̉ҝ'I_>Zbq}ej* D|V9 nҲe @:2IiRޅcÇIY3|"/| F= ~n⋕~pglj8x݆M5-[3`M5wA1} Uqc}ǟ!1ЭKY)Y|.@}щ vϣu;,77}"מny _NE%C7Ő0<,8E?mLC7NF|)j9l:æNYHd&D")C~#?Jf}`/NR1ʍ|$pE寇~vDڅ #L*CZjd26(a5ߢ }me)q@N'-I1+SEGcl}cϤz*$bPjƙbAAd/yJ}_>i >HG/c ñ?ÿk5jKF J-3Rf$CNە?󱻔 ؟u?m嵵@[ pqqB9 @ &UZC&)-Bɉ#`zc7hǧ~8x 44L2,_ؑ~1DG6rI%8'rh4p۹)\8b:i\vdpJXrXU8҈y¸5x4b#q\M J $xhO̝v F38Mu Msf,`S̡w-)Nd(zCCx!TmahTb̩EYrJ]5JW`\PRZbjFSTAOK1-8WPnMO!F01 (.F^i >\5d/61劀6k+FRj b"0fkmG6}U!Z6Q,gO@IDATR*!O`# Veqqr&(@XG|ItF|b"#kVA಩*D_u{RXU43TV9^J@5SOWNO<I Q+i؜-.{F^u|h{_~Txz_A9L&d{?%'~ٌqeX̭Y5 o/39gy)&{)R_MX_1&j߁}05| xt>yX\&tȇOFAm3 % {^RJ!#D]goἑ,^v&PCaP.ЗaQ~Ce7b$UΊO!>|k`wAa=wQ7^!G;)}uھi-hٓf<^ԫu,+Uvݵz>uPt`k>zh'`cTQ.QݻA"h >N'X+K45ksڳ4?UaΛh^[9W -HP '~;BSoVW[9:בy(MK'Cx*@ PJ8x~M<1i|4xE<%4+_ca?Y*s^_u3+rC6vU-MS'O`]tRV@֫TJo:;} /[h:cX 1ˉ~Gꅻ3HW6dG 19 xcT2&KUyh@ \#KWaSFR9x54r]HCPϙ2c dJAS K@I/SQYIE+pdȠr(U0ixoDZܯf.X^=gg/`}5nBx7bҨA|n.jq|=X\NKWL9'f}Yʐ^v*#̹\OA=kL5x t}')*430hi)%}$O7%(owY}nd)Ѥ0?HKO  t.֙^5y|绹w;9#O>K?yA̚>somg̙9{k/GnC꽴Ww}:T?'miy9EVe{5+k2QؑDLzR@l*F: u sJysnըJ@i[*c~57)QzVUZ*vtM'~.'';^KeY![f\׊>WU-!(Y #L>J\jK޷Y܉ٳaζ4~\u!(e(ǴE)MMQƲƂMmܗ̤,64ȯ3")W-YڅnFum%bҳ1,[PMՁNNQ`h#;w { '%$Pښn 3еMV5%ڙs441&|/?˸އr^U@VU>*]uVUS3*9Yl;i4u#.9u|?4nᄀ~A 6 t7G+2"ܕZw~>x)^z!4Qa* Ia];}})zA=z/aԄ*%iҪ=A` O4:Ё=Xj 9R #LG,Goy=w-ӧ%mo/?E+g!<4 8|~LXݽsEgb۔8;ٴkX! NoJUۧ'rEaO-U(#瞄ERBzÐe;zbapxDyؿFr3CVtz Uȫ_lLeCUgN*ߧ_Kɾ69W`bZ@Tӧ뮾dFbS.蝘v-C {¤UB \~!Ⱦ ]iN`W~HST/>Izuׯ,-)\KA ;:ı= OMr;SI5 r19+%*V^R5IMFdt8vU=L@Cccur0EƼ+ΒQ'x(4~\Rп/r1u$ %0oej'sQ=Iѫ:4L'5j>h*7YO<;Am!.ҪDO?2 "#p/f.GfA6k?Z:VN^ k{UxvWNЪRF>C m$b߹sdvV =sqm`Uik@"hVhu"EaA}/ kOVg.oN>_~_5}.Fb8ЇՎ㔭#sOp\qC{P3p~ZVYe Y%dTx|p?P Gď6uG9:y*OySFc̠PN쮴f{i։у[Ye|~yhӝZMjd >X E;ZRdp%KRXȣOρ~4_+Ҵܙ4{N\V UghPrҿÇ#)) 8F~].`3tw%Jt^|UxṠsbAM+W^2y]Ȕgߪc:ޟn }zCVƉGGqӻNC.PJOU3h_!ieVh\VB-@|J̘<IpQ``\^HMU`:O}52(k-S X붥d+V$7pTVͯܤ{ tVnn:}ԯ9<~H- Uʫq_T{]ѿK絀XhcmY[-@Ѯ+J+zŲ&}mo9U$f$6k[hk-[/*w% U-}S`ei2fJD7MvN.4qϗB,pC1Є!'M0I˰`abPGq+9(9Ǻ ;r*ٷb+LQޔꆮ+> |+c͸|?FY1duiCTlifۮIGyRV_P=&co@C E-q@Tfh{^Sæea$jJoב2buc ng,]$Ŭ[m]H_Vf=k\Y4B.nHKq͖/ejͧ$^(_s6x7JjGt Y02-+S7Qk۪j%J$-ŖL ).B:海E%jiS=i›f|8%b'j?{M=*wH:6|< JrP#mldc+<7= i{sמCkPKFɅpJ†8zRC OB6L2=07 <`$~~ "h0~9 _X4)1 t$yf"'?v s߀E[;g@Ÿ|) U5SE9Z%xMԠ"NTrU1hk [gixw}0(ƹ#G`>Ə .]8'] ؐY{CNTV T<2REꜪx\)(Z o6~ZfW7E先>߷W˾Ϻ ׳R{F=11dp&SSySå9"P|pW ༠_Q)̞ۢ"ؿ0_p3QlHfS4/%Ӝo'EaT:bڔqH?"L/.JJh~:Nޘ5&l,VN[eab ,x:A@R |P !Z8g$s eVlP\v`b)3ȳi?5sFvE/@f?'΀O)yd/~"џjW%.B앹\C?4Ƕյ Z@ӵ n8gڮ݃gˏGѬ\c\8IڃG⹷ӄ\/D}{ +KHgP9gg,%aUXR,*.1&ߐ/)t}/3O-s+8*d$}Th$K th5ؑhR op! m_ ' E2Y[# 6G'k]QyCf=5EfVZ2W_K֙ڳQYA|\4F2\~|1 6b QHHY֩ UuԶِfϫ;2OJPuTFH)No֩pZU4_NsiԸYvFz+ 82sci a8bدZ$Ǐ2įPajmHPp'r)_7߅aSS U?r~}/Z3k>{hg[ [ dOx3דI}f;fQʤBCh_QU$*ɫ.I 5Hz^M[~~dRw\ЦߢD@( ]W -m5&ݬa_ʚEb /Qg{P : 3M2:*@9-y)ZK/>r MȆu׌U@p+Q9[/eDv\ٔXt uu/̛f,cE" 660$304DqE6J1omJ^KJ(&$..̸a;Ύo$՜_ (Ds[Xٺh C@`O~J ՛V"'M\귪&U'cq?nz꺿LTڵ_g,&"X:^+q\S\oTD)Cȫ搾T4deiywJP&?mZ֟BzY z G;csFҭaWUI6tudVdpKMw+ߌcHςds;E &5dLT/dTה-LCuMU'gSH۫P}i)J%`0% Hۈ {t͙OJ!cS.K%X[1o v4oYTjan.D ΝP cVU{B'OoZ:wĀC)ХP[dT$v؊݆_G~-+yTR%*lߴ^(c#ԧOGğ:ȱ3fߘnYFF]Pj)ӏ0_ I;XM';:x"I~g<\p})Srߓ0۽er߽s(b ع' 3?]cLHS1T1#;vf5@٫qNU2l,-q|tn#,=Y.bIF~FT9qOQ5X60rNd.rﹰ5ZRLªqs姭sѠ e?\*O?]R˳oXqQ@;d1QUP4f5OsmƩ3THҸQ} NAWpC*זrPe49i)Hh=q!$xHKYɲӧ]n]r z&1mWL,ykktLRтߘ6ybLeٽbp!>5U~JK9Oi\M~O6=wo( se53XEDҟ#%oJq%gC`ݳ']d[YAVV|6=L1WW5c^ #+hk̜8WFoM4MO7!`uGw0s1<_|47cOb9 h &]Sb:u .Ǟ=րZSM6TsUΡer2,o DYdͪ72O1@wk%#GaRؼMYJ)seup_oMz@ҋQMCmFUӼ1mlk *> [έ[gLau%1}#zyd K^hPP hm-m-I4]%]$e$VJI$&#">LLY 0!-%AIFvn˸ܽ^ܻv2U"O9&t'·f;ggWx6d3>Xts 7{ RQPk ܕӕ Za+u#-,=fϧ4E'1'>PXb *a=rȴ;"xX{v‡Zs@)@HY7|mȸ%L8w A4n-ko )e/.9+a aIFF(ύk6tIaaSn~yi x8&"i1.]0gXa5bway^]vai ?A43u9r<||i > ~Уg/| {!OO9NY$F0t![@-]GQa=P@Z[oeg|XRG!归smDӧѯV0!a̙K)hX3 S |&ٶx;CMgNÄ"UEL1uPiכ5)wFTnR4խ;quS4#gusѭn:JUːY_Jj0{*Ig(0D…гwI>Q0>rZQzX} {ME0# 441Iɯpr9\x?LV*^Y^J:I OoWJ nJܷQxwA3odiL«1gЭQs-27/ y`Ol#zx5Jb/WTbvvL7WՋl-SIѓUB>J61v<ڳJB3w?NwEگ&'O.} CU;/-~ؽKLͽ 7طcl%N1oC0vLݏ(-Ýphj$&f_nm؉'GxG+:tdV1|y~U }t~e~&@G. Ջ:G1-vw?nI?3ݜq غ+U~y {M?s,ZHhz]1ށo =5۾Bشm KSHA77mnG) ^c+ /,BhQ5FjHj?;+,yoO.yI4dۉ00A0M_4&;/ɺT Ki%H?\?epA&4G(nϗ,>Zu\OF#?ퟛS SnA@ֶPEX1B^m"_x-=SpK6]&|MNÐo G㵍Mes}q$"|_x$%^XIOB$f >]jC( ψγJ͖RoɦJ;I>OeͦirN Nr\'ؤQLI#K-zJZ~-dDZ&sq{y:'% Dh^OFլLWFm;m-Z5CgOY{kY¥h2 $]=/q5;Q 1cLͷߡ*2~`8u|l[`hl!`t\P4"Ȍ녨Ӝ`/Jy +lg^(25XCg}=i *+PTxES7fyi1*Z#8vx*iE} ;YxY*NPqPFfh 0n4>:/4/~B95aXt\v "OWhJGd\Žq~6t^^2I=)Ϯ"q׎4Ym`4hXiktWBҌ^A8ۭc҃"ưs {hR2R2EQӑDpgKXȳ+R 9"66.0&0E&58%sɴ˾V=ML@9zJźs+GϠʹ5_+ft5a%vnS'Wt3 v:_/~6$-l÷_ qS.o]Mr$D!.;Wbii&8܂_wPz96󾳴@x#ӂ~hy{Y*G_~_&WϜ݅olgq9f@SNpJ='hq؈Q0/}cg}Lhio9QHp fTp5}j S.io(YvbWhutQ.y ?.?Ca-YıYbzW65đ)o~ÏoGFM뱰j%.bY咲}czÿfPPpPX>Xu="}\G%a)~ioeqR%,PZe%(otm-[@&#IhFu ?]V/EQRwMCaf4L y:L!N7Tsd[TF6Cc k'Wh@x 6U5b S4))۷z:?\ PXBQNpZȺǶ Ә>F".{q-;c>8 5AYĊ>}4*A՚*/q`nbce!Y4W%ژs=L4ԊYӬk0<2%fPCqZm]rdڀ@c,q89:G^Ic"EF/2*IϾ4AmJX[#IƓmg#S4-u .6  DQNծm{;{ ̃QN|!MLC.cjyźsrBGo|Ūʕ$NSa'Vf],^Wl?W&b=0޷K"4-G-=B(I>\gD(y1'4֝kÔ?Nݻ{-NS,ͷޥč:B*B]tbѷ߼ ^zYU7r![֠H'V |WMuwt긢K٤U4O}NrNڳ9/ߣUZsNE8DA85F߅n{lu9>D RCA:r gOurF䚒&3Zscl>nFEVߛH!Hڱ!&v#U#%}Q;¦5"gc?oEXk~5Xr,z!lua8X^MVX$`U(J&X{m,y,7C,[ފ?l<}vDeM9_??zM?'Op/e7r2 ]C` ;^Gy5tvAqA.^&$ݹF{7XjSnGrLzn#}(5 ;9ƎG`h-y5{Š&$_zuL%$O0tmŹ ~j_&e|+r| Ƌ&ӎ}XoRw랁2ρ2l d.KEX{:9vB]W?t(jèFCH aO@_ׄℌ?x t.*%웏Q!>x^ƈ--zk)V%v\Վ)cZq ?0^G&TVVި޴y-=k5z2#qC0~LtRb<ؽէvpo7G-Ӿ-oԿ^qw&_uaoMp?"cX6yX٧ g<}-47AEdٚ t٫?O{ Wi)m\|F8~框{ᖊhO7"@wήoR:NKYw ?y!! h[@LdS%JlkmLw?t@IDAT݄eT\jE%Mjj99! [B6UZZ Xu`a뵞[ppp:Xw Bp\Jc0f,8ElH ed`Hd}TT=K\E=dga$YEFN ΰ36.-1^,<ʪJJ]lQPX upckL`iXBaͤ$u,XL Ptp" e-ٗ‘z¿[wG" }DƝ;$2ck t% uݦh͞_"5WnOs {2s1l FR诈 e@} i8)7܊76CY+~*de%2MAž fK a(`{ژ js=*vSA1RKOZ,/8^]YqAS];bI3M;j麡}{3dfb0!ִ!'7&d#9ج=kPZm=GaVW@Ug7TU < YaIS݌o{Uģeows ˆxצ6wWڌ4EhQ^KQgtDmZd'M t܃ ]|U=齇H@ HGP)bC]P׮ޤJ F:I yLx s{fܹs߼[K2B&K <ۧ5\lՏOwоuwcXo*[5f>"=̮sI F=mÂV\e߿͛7ouj&[Ě*cL{wOsmuQPD%S}|v0MQ~L<^~WHYro#Yb)JMV!ϗ(6btҒdeO=ASN01Ɍ+4=X _AaH_\.EHHIS C%\/O t}f2J[s(ħtgބόY qODž?xx|=ʍ{'| hӻ gؓdB~5F Wv0C 9,461o M 8.H;ܴ^ia37\Iȸ_ ggؽ|)\'8[+Jon 8D7lK~o~ a%h]U,0cR9vag1,#(:m*+@CǠg[@%ԗVitT>>wutFv;_iHlCn :vv19mgҦ=6gQoz>\:0uZGqP\HDlY\Jˆ}37TODV~z 7O"ޱ ,<82Zpա`iPj]c9ff7ΟAW $~t% Δ ºu__ -uc{ɊVY/e"}Zߖϑ0F5sSQe1CX`밑)=ڴJέo=ӷtsmsTI^s:3Iѧ^) ?K8~=[dۆV,yv)o`MKtp 163&(efLeSa!kAn&Qy[ǎۄ* W^Wl )띊.),L?+ȁ_1i. o8׃[Pޫ?PH'e[H'㣫}Z/f"}]k'|r`[aL5~VPXz'4sa~emQbfjbRF|I <ʂwW!_`9R&!&vݛBG+ V.xa󈋋q~4֝dL_/qltKįϹY! <8z$F=> .n]ǙZX3 fa1ڻ8s"}~2|[sn?,\.'~X&@D!8ːG핾~2WòUyqLQ,Kttr8Yh^D@{*R TUQXjt4m[|x&kֺM  / 14:"R dQ1(;5@S -1lk$LB21Tꅛ ˴$Z9*Yy%Ji ]ȑp z([k{15--)٭v7mЎFgK̘6B j:99)AA~1 uѹCy}/2jWچ 7QYO'$Ά(=D3y)\~6;Ë/{It831QJ;qdHN?x8Y4y(QgȞKER~ * ݫ {~q$!E EFmAG$#G/gNb .54^ƜDɃߺQ+icS`FΞm&p9\ӊsщ0gEE 8tOτ+Mzj|(+N/Mw6-VVM.vw0:'M!c`P}B)c鋳O#;#޾5~hg2T]7 6nXCV|&QN%ئ'ɜb1c'X E)>i4|.B6Nvc FyM5`"Wt$#)π[ KS&AE"%ՇOɪ}9x­ ߕ0v\̃|["pw,LYsbG6q qʓ2o:QZ`lCuQ.x\W_ln{g]$3 \Zy.5]$VT+ߡ*&߫(='f7! F#Ww -:Y8XtEy.պd=?wD΀H3&E ne't\bj5]N(pȫ- zo;᥷{ l^C.1 {qGђx`T{+/ic^J٪F *ۏڷYk/{MG(Y[~¼Vm\C)u#;"*oT9wvզ&1N--IK/aW߼D',#)%W s1  {`pš_~ mOSCg234+p>vYtH=`KE"5?y8qYdAKR8XjKGa}=nGF>2aej=kcFoC ukoag9kPp NiELuKۺ@NY>;59cV±~j5ZyBvE=hߒHxnmab薥tS^wZ簭-lX&',1+Eزm ֭X=ѓv`ԍYiT⨀-I{W#;RZw᷍6ePp]odU{5Z<8X%]Oٷ, '{YfJyw2g8{~!3saNǾƒ TcRj8W8kYe5C Ї}ݦ-D- x 0[[߮*!'u5|-7VWD廯sS h@Diyx<} ر]<5d66-ܐɐ+\74뜔1mpwwEp#cuT&}]iGZ4} >Se.#e)sKNo/b 9ߐu'sf#c{_iFGN!̛y2}j#ד>Atu}!eI抪b|4V^$B`s:ZiIߴ- FCŸSv=iJM P& [,&Ԥ hc&u1#ӧմmjk,TQ,t-T+pz1\{MgY28 +Brex*бO>؟>057.)EWPee kiA62wV}R.Eрj3j iw%r~^8sR]:@Ue5󀷇5\3%3+?'F "H|;D.p l84O;LV#)j<.tй@Lg0<4h31<[FHcÔEΝQQ/SY42n\XzⰓ¢^:6v,';/h|[]hNC_Q0c. FId/8e?1C,CGX@VIVl o g #]E !KfʮJ+3BS15-68r`'-fo8Ѱ|`%Hx{"6$.]7LV(5W*\ç|QXeqhG HG Mp8M w܉~Ύrd8^>).cv`++P]L.&Q,TХY`~Џ

.b΀fy/zV0L_u(imNb`$AP2ZmSun ES0 992T/^2?>a+1Ӗ' {ل$j":nFQ k)3)pMwG|I<oUӾU}/BHVѺ]%Lism\~*8,gŁ~JM>#ˣZ"q|I:kYbm^`'p`@> а *M{$hGpk.}cf Y?]|:gyY@ެOw{ώ^9>sH^z_^H[Q3Fn3_p;ӥkÏ>^uo{.~vVlrT\b06z\oyn;_Y\hUTo#?bkJ&~|ZUSҀ+Fy7:q%>~ %{`sUHn qIΗwu| it B{4ew9>5a ~/ov u,`/|L~MQ?=14J?5|U@wZv lV~:=0ūk{f{8wdE<՛X4Xݑ8(y!8Ex-`ٳгL$اop֘\sاd* Yl}>_h3{>_]žhޚ؀ѢGHBOe9ʑ>8L6$ I'eoQΘu18Q0\- .4|O; ߌ+ݗ_g`%d؏ [o`gljrT-"ȎnG{ WOPb|{f/֗_|>=mܝ@+O׾ ;͖6.xi;I@-U)?{&XT翂,6 /u_q"56FPNDS^G䢾'÷x3ޖ,;{+ Z} VjO`ߏKk ~GV)&ٚl?Y7#76L-#GF̺+# ֊g^ϼ >1z5pl䱣v|㏷77Ur=vZx{o.'ЭDf&a]sGc ?̟tc>įw@{/0rfWG|6ɨ4I ǻ,@y8$ރ`+;\I}?A֊g||,]'MA[wŷ'%^r5Ob4"Iy *{A=~j6Jt zhO{Qlue;+xd$T̿΢a?|=K|/k^_~\w;po~%3%~*xGsJ(XNu6:old]s/Kt$M?l{;v\ |GuYTh^oZaя>=|P_o]R|}Bw~byM脷󁊢dR?^9 x~K˟fUqmٵ޷.~_?*Lч9J;TGklIF>?.k#'B3x΂hMfm 9EJk 4')aߎ:>F/(/+nH﹎B?;se@4o~d/Z8Տ+hLݞ"+ݻ@[:@j{"Z\uu9sn9{);Wq>s*:s~o|i(H O+$'{/U?䙘:M߬V߁h729 Fg2r~U)n]s@̛Ԉ1@m w=kNP&vԒxnN\n$_lo-X!tak'`$M#Eܩ2Q8'͕oωq-X8~TA0F:/C1f_ Y5Iq06Qz~de457ʦC&82> uagB`RҘeQڃ% O0<|\V-rbHj su2>ҦC`TMLS z bYMʇ._#N%?0FlNΌgr[)µ )ӻ^ ]Ū4)p/­=͏b"0 IeWmmoT^^es k<+ h狮e|:h-<3!xҒ^1U]js|k}!ڇ"4m# 8F$= Wa=˨\6Ɓzج@JKڜu?ܴ`~ЗjLO%\{ZLsB2?Y =˜Pf_zΘ/s= eɄmaK 624™mR8,Hmٜp__~pAn7pq km3jg% (lra.#I,@UYyŮ_Cas͑g!#Wv{I0Btg{tGsr>'ѼB^exM|#s~JVjicToۿ';rB'LŔ_{=T\Z6Ύc_Yܸvlc70[7LJ@jJS-e>lN_QZw1ֺ7Z>m~ 5 >5nĭI)5I.ۣ^l&'d3fdT9|:)_p[;&BbvDk_{n;p`5j>pfC67L_k#dߓ{< Ol2G}d 9><<1ЗA&'g($a_ 4]qD$fu.t(p*?li]5|7 '.0zp5vnduZ 7.g.*[6\G%atd_-H}Z Qk%<.y%2^">%;.ag:xp''ɠ$|X $IJRs?.&mx*'i\Ѥ(Z6瘯Nⷳwe86ahqyVs+T \ϑW3GGǜ] ΣsKI=Jy-S͂gާu잻%co..S;`әwپ%Va:pmϒxS_ Bw4o}7,t?Y7ty A7+Rk)y=nA峫7w.?;w}-ny_hoV?*p/_Y,yYWU}ǎ!o+?Zhq~R>۱ǿ1ho,Q{v'ۡp#K«>r%V`Z6{i [._ldB)rwGt o;Hm&;vƧPܜ`f<>6|zS2R}+윕~ =8zǧJnܛy}q݈/ˉl3Ndݣb~ʻ}{b'7+wyǑDu+J3lEt8ޝ8yS>Œք:B/='7uzvbj~/5y^<~:$n㛻dgqi{v`WS jLiO1ą)OK 6ʋ2# H̖ʛ8vJ[ u쁔m-&`V{-38읩Eaxq~{J" {Uo`ص8x}XgLFJϯފ9nO;s}0b+nAx7+`$/s5Z'G`kNNgcԵcc!@4k)n*ܵ:9޹8B%nyyTѵu4RUh1s&Ӽ~OnwZ%zKsd(z/Um 2IQU f-xP .egBQ--:3R,!T꘍)rNWDY T kڞBǀɢZ۶0u'(J[R"l\`תBv3jB8Ds KssT<´;־6 OWP}@궔}t̩oY:9yoJl= Tq\499OgꙜ2N(Y؛ 8@$w6ę%<# LdܳZ3cj)pu/y<@-وSD&2%b\Z=#^<9xD(^69ti|R+,8ësc0~'CK@ 9tAuIHٻ-=*6rsǏ <;uVǝ) V@<.%Jx+ea+<~dqYi;oR/rbvӀ%,OGhQH%mpT1կ>A`|+ˎtuú?o?p1<:g8^=^X}v%K2v[ꌒҥ!D_ltcRWg#C4Ys ^5 DvϺxdz&dᨑ䥛dET9uӞqɓi@Qc q_Bx4N;Zw<%.-ʘq?lIt'dz( V =/]Pg?'/2D ~>ZeXw3Z$OhgS=n[{g=5ź_I\l&72N9d ?lp75t"t/̙ĜE"Y|l͛,Y OgJIFKf!suO9,ݾ^8xeY}jIxwfz;.A7dmF.{V 2RUB.u.FgU1tԽz]\$2FW-ݣ?$ۛ!: oBGuױ`yϣy56hg0쳽lOCͮ#ޒ#/7Цk'+ڱ#mf{i\5B6^8hBs5)8׺|9$\hg v\Cs|>T^YF}3 )x~-uifF\ A XVgݭEn4is𤮵1z* X<ճv\[mEh( ZLp-XgJ|3(|Ƿ|b a~q~ &lxËכ v1g'9 nuwYkX0Nړ|=¦b+p]w]6W{FU+⤃G[;dތp˩lJZJ uQ8ujl[Wrvd9T@}_:j*lGpCGpZڻT&`/qHS1h\ }B$N|v7#\ؿvMG˞`3EgNkmcx7VW5 ]&6 }g{ ؀z U&qpfoū<1Y> =Ҟ$: ޮkÍw>=^ }ex{u|:.pq$Ϧãúȁ <'#C.COѾ@8~ʾa3]WGGjgE1==|=yO\Y+o{N7m2ћUv}Lg6>]Z YG t&utߚ=/~1e|55{"nƧ Jo౾ƴV,c 0g]Z[-g~=Yk8~FO}׸@653,cA;`%e:1|/7Ûy Bh/" "xۉc Q.[KH ׾+Z_m|oM1\I;UjƷxqxXde4ZyfV{c*k0z" C/ckڦО>'&'~ Lab =FtMM WFw6pѸ #%;muܾ(|`vβGi ħevW1nO8l m_cbC*/koS_xs%u.nudA_]N^Ms Xެ5鏖?~rg=uahw_9W%u3dEϊFp$Ԗp'?;usn)XNؙ2FjR'F^Gk<V$1>Zf ASZNܔL' pKǺp@g± ƲOsa qoMkJGtoP޵Au kŧ@p9&Eb{BvG+}o<;i11գ'Ŏ,(M#*k7ŲWg/DgԎ)qX&͸a ֲGxx!V86o/Lsz `K̫G@ܣ⮓ᶽ^mɒ^dy8+:~GϷy ?xFs /(ɹKGHIč:y<ϻwd#8-~KVrt1ۼk[ 1vgJ&(ZbA@ hޜ#^xΜ9^ ;u!G~?(ᴷ .}3L\`.aV*>aC}h 6PpȵefHMA{^f׎>Z8KYMcO{C}霂7f[?ֿ/tE֣T:/3{q/o^&0u47?~*IΤ8zorȔ1@d(](2f2%Nн&^w3ԑU?{r v_hqߧKyϲHC ޑsSQ XQ9Ixc67e$49@{jgԽkϥ5ce{5(}ќ%)LJ_{$*֋z~|^hj%x2d#b KJ6|=Vz"?s1w6C _uXrÿǯ 5#ut͝1كy G5kakBztu5fЭZHkݵ/9&N^p.F@uq€ӒJm:߻(WBD;PdԫP(,(U0t0{2{9%A}&@: ~: ƻVkMx/#־gVZp|X;H 6~\Z|rFN_>|h$ Nxϙg` ZSQosG'*Z O|W Nc׼Ǽg Q;zZu$G)(87z(}q=}J.yώKS[pۙcb.|B?x2xAW-''J Ԓ OָoS*ɺ&כ~;3۝ +3A #m:_Un,-jE=F޽ȳg:?ϧ|NC -M&lO:R Dl>: $>Lq2µhz¾3 /~FLcu|[OO~Q]vtd~Զl-i =/@Al盏k.[ {iխ%f2|yp-r1oYj?oK{%c[6ꨣ{}Su=:b'vDj`:Ov2E}kvUlM;f˵O>?y51?DcǎF_kG_EUwJ佶-)/!9UVHgo遛"pN(F>>($; +"Dy?HI'rN`ގs%B\.֤ Ɵ:vb쪇&IIr')D;vN=w OR S8G+&P寿}|_xߪ˷ȿ호E I-/}rw3*_my?p݋9ӻ-otuG?r7NNϟSg%;2T eY(o,|JPJF $RUs*~[Ƽ)fT^AcSCh;CVYP"DrD9! mUǎ8/jo$AOhk60>qx,i LF<|y4u+Klm7zcp`0.y!|g|'2a?x#7_9ۧh2wo+acˡNk< _4_ucygδ33gSwf+wI.HDɱF>$A#@>[A`ذ@ ōV(*r}g33q )#fS˃xnt MZS^}Wf|. C<> +&gJ y2=mt@l? %2Wy Zlcme/<|OGGOY>BATҔɵ=1Tn:8q=Fnk kY\ fc 4a<8C te&8qNci WmtXttQU:Y{:3BzH#`&$ Nd@U.Wi"P l}WQZѪzFɇV* h仆c8U\} ٵVJ;%mhooRb#!C,US%m:ePpP> l֔{)𫹿\^`& s&/knAO*7"{2/*3lY3*UU]RB+5M c}WƬxt k`!s4r0 %ul:<>du)܎7"JcNo5lO9f$1({*P vׄP1w[w{om(e.?&F+gؠGZA2)*/{mgMg]suoV4 +ZSr 3Flk󲮌Aټɜ1eRbФS8&(l'ሳ1;m FǮ993F EسpIV9S6p G A.# ~ye(NjԣΕ  %woISǘ@4s:gAաqө>t_yuU7+ϿE@x$*LP{pvՎe~Ov\pϳKB7t0\cZ'e~ H&D-ST Z﮻Uh򠶶|#:h˽SFIÇK;Ї0-c,څJFC EP(]i7GkCcf}aH'Mtpכl`0ۗz RϴӃ2^O,eL㐿LyVhOh(` 2qR)2,| sL` ]4pOMu<$YM:ҽ[Љ`z*> e>.? `\8uAkK5P!ۏh$ц1Ƣbpqۮn;sVa Q3>lHySc:!^~5t({…izG Ah|s$0V/Ͽܝ,p]:G PDvh._䯃Up`5>Vj(3s$řm%}JuN߹s'STa]o0PU:ȵ(jq,kJi}:2` 5 < $DifK}mN K?\czӹsgN;"HO\BdT UjG<=Ix*G.k̲=ysiD}vѝ5a [Nȶr_tn4k>.^lt42|bkB"OQ$|z'o~'#i'`v6N0[ZG2D,Xk%t7){b NSH(pݤe@tdRec`|_[R}&pQ9&VGk׫$dl:\XdҐvftĞm>lok;H[[iGd~]0o@ur;}Nb| EB|G}jo {(z$=V=qrk> 7Jaխ\ 67V(qM.[,g'\$x܂ ]hO 1Fm񟾯#t6ńv\QwթVwߖaNf*tKgN$Hasbo>Egv*yD9k{nI/vLmȊܰ%?tfOe2t>W?S@G!8l ;na~զޫJM}ѥzW~y췦q2y,r~'yJI1d_TǗXg|'Y"ϫcu>mtom_i{ {^Rqw5Ώx8Fk1젍M$;e$UA`BW؛{-;)%4@>cM"4X<>^"3g5ʳ.L>Ii-1=ƵK}S[;\ޕߢ&%ױG<F%6r`"*IGQ"f /G4U =vSxp+vC}bf#i$t%vT.;VO7YAnBZ>ZgŃgϧSgwo@u]'dT$`g2I2d|z.\D$֩TN3>q/]|7OPHEK EԘ4c0cYFRCՂ1S_ʳ"ιj3Ep9 hЅq?*c"H:  Ekii67C㣆65G@Oc ea,BB03  6c\9s)= ,8ӳޭƒ!cPj Sb pE( .[M srk>hP:A%gG# YANBԠQNc lkJ Da#ւ-i"Je#SϽ7i`h-ȉd.JZmD*3 nPAZY˂8T1 cL2c粉#IF顾Z~fI%q[6rv~J  ]TE; ]UPfl砃ShV UҔNT=Jw-Z@a rOǹ€DirܕLpR4lq,XCSaueU}fNbta O[9faz<L'x鶁VX%y5UYpЁYOҹQ*+3mہOorUfkFc@FQPPi;38}r~H E{ã`!k$+ <>, (O҄IEQ)1[ ~h8&O'1.}_ҹk +H*lor鋭hBA}r*B+h߳qU,*%%@%VY'G۳̱Knk\PZi2i*c1VD6u>5\=gFwDۨvgV4s4,{'Rd"sxrluw|!I =a6^=6ڬrо2u]]0oUn&OVe9gƬGu>rQit`]d8WR Y%[swָg:FQÑV7kV9\]f0Q] onr"Y;X3FQ ` m'rJae-/rJȃC̗qD2CM`V%S)>9n*#(YQꨈa,S'gB>vQ5XZ0 =1t~ ˜s8?NYWFo ;~~.^\w݉} Cb|ҪuEl%ᨪ_s7L~BeC; Yd:ʳ! G!a>r1<; 6G;`ey+`l-TE$5kK-+ЬXQU30w `@E䥩c 2aj!V53!C$$Afg#'tnV.t=>Ou6TbH?mun1L*lE3K\θ}n,wAg!炭mA0vw`."HG:ˎ!;GN҉(1اq)E% yS 5kYBw m*T~_`FLISru8|9F]7[C=nI y4lO=*8Ö{ўm8 !R\pg{{q/t%o Vf 0QZ>c_ ܫVINF .tQ h˙XyiY2ûFpMVЎPX-ՓΜ%qgkғWJW?x{j"_{l дml꾰qt#ٗ֠#ԉK׀RB1_M`x\w`±^e/yki8wA_Ail$0X"SSk- &Kq[ZcVkdiFsχ(s{w'M9N^|yex#A`Uo~%{_B%h_p XǓwaS6*`K+|3Dn-u h5yi"0oOAxWώMa<yTp|%S_ιx }F36=d{Q{d"#I,3=/m AK1 Bޟ}q&e]n2^&Il}n3kPuWJ}"Q+SZ=?ģ XWƇ.`ۊxOVv^fgoooAЀߩ$٦yMLѾ^:&"Oc]W//\'myG_@γ榲=/1O/ܷa"+=&FxD˖ћ[s*R}.ol `=50ǟi 2PaG(e|[E!*)DZG# o|wGޙo| i [=߱(Nm?0S=MS+ Щ~L&s̏KKˬ>`WO/]vp;ią6ljFӦHr/:D:78dge-ߟ Y}t}vE*{4'.gR}(d sy-s:"u <  T`殃IH娦F뜯ED51QZXo#.8.vFլo13ᛊEleRʑXV.Ij9}2|]qs,{2x0[i ښ{`(l^ 73+lձbo׷&keL7++exQ|[FŮxW x!~B|55$|Gifr6]|4?jNJVgy)_<!,ij+@-נŤ,0ԞubhMv]^ Ѡ} ?f;:e6D0߸q$2K=F#SeIGTڏ;N-mK96RFw Ca\^Sv=U1f&{2(V&-]9&Ub{ MOJ,I;ﭝ% vFqZG}EvL6RMG_"?]ieXceV, 64_UYJSq)N~7;;G@+Wb $ ш,|m^|qFA#! q&6O 7'n)SK S[#!u:!ezHNy&>#jS>dɭ;]~Q :+4: ث* D_Б(`_wҭ}lV|/4~jJv@{wZ[>d+tMY֨yL,ŏNL.Xit -U5hKs1\b(/g*l媉Bݧb[5uI9U.3Fl5Ä63R"6T 2 6D|Ӣ?MPRΞϭX,Ď3#akHf,AbKײ{XyҌv\Q ]#F?럄Ͳ8L"HWjF?,Aq;tX pgCdfb*@lvK \V{ Qwcej_Lж`z MCI^At奯BPֵcEhhI#, ҭbbWڞXc7 ̆"mkj3S`,ym帊J{ ACbu*4rtȹ'"ձ7? ms дl97iV|>0UTFsN@QEU:tnBS | Y ,trDU* [&S{Xå` i`=/Y(φ wuJ b *%xaU!IA5NܶV_Y(Gy~Aj; +fe]*n9cw~;>h 4IK.fhn͚90+jeULFlIUry%MNijU-:X(Up&:3OY{^Yn@p!ԎҪ ޣglLLϧeOeA2\7Źh6VtcvӥÌI!nŒCf< doVӖmhFvػ=[2MC5!C Aa[w]?A E&NɹjT*8]'A5ζܢGg`DQ{k(w-٨IG`"l =_twKĐ]6IAn4wBҮG~fjHqyX~2GkDy쳾+dKW[(O.@ t`pHտؠ#FLfR~:* # [=ލmTޗiA*|y;/Le %m rL3mF#_O4 2ϳG Sr]ݣTϱX ``⊀|.kGg/q]XHZtp\;kfZ1À6P#hgETz2d=Dy.:_KjB7w,˱:##'VW(O4?{(.:sL/̑x-/دT:w1=i3JoߏtA?FmpJlGf[2 8[ ]՞4ox+ޡ4;E+6Qph;ՙ%ض\Z g Ln~&K3ͦ+,txURӪv+Q{H3H sE΄b.w\L 9g&Sx0hT}{גwC*HW9H$e^҆?wHqV GVuB^^ Nf  >07uk@!}cs_*s>S,8kI;nZiz{cVʹdЉ=tC2|⾬!vv13w+cCo1oRxPe `kxs-Lt(D]SIn!W# {|A1Hp}9)/Nx=uBqP}bW_|a7PO@!WoKgڔ0ATV?njc7/{n~ݔcd*e$wtQu Rn&$+Oz_!/O.rAyf4*y4|bh|и 7YTyb3&[\q~ =' ;?'A|@eҧשVIȃ7Ҥiy؀{8܎16ρ.ZF*1फ़x X7+|3b4[F75&WA+t*D1RfxDԡ=J0&dN[P]:W'xg$Ȅ.K&#Ag$2m Yk|3OKeD0Yw1C-G 7vRaVֳn>!҇G鄩*Jkˬ:A }c{=V)&(+|;ԵLk&T#wal>yXz P^jLf m9Gȵ*-/mS+=fH٩%iPH=l[h{4%&ص Dk-Ry1lq;=+u:`=Llmd}=W?OX%s :W9q@4n{谑EРkD*Vr۵UhgQ?9*ʡ)͈pwX@ =Hz"_Vg;:v"_?2$ ؋5 ǝEꂂw6XڲgG;`qd'!OtckE{a軵3.UzT?B#S=m/jC KTςd4(Y[mp8EHYE\{+ ԷR.(Ϝ ȒC'`l>M5Gq b {z:Uڙk]瘜w9]p޵^ZU6T=2"c-.F@{i _e %] 3O'01we$ جmт_6XsLԮHQ\b:2.c&IK?'_P.:˞tsr5OK_hYbN]Ts\I{T ;rw{o]_HdHȳ& Vwއ; IP_l ݉O+[cTv6ݢJv|wЎQv4EpD`[2#i\oZ uݹ;>q5 ,-vX iwx1O[lVKD:Gc#C'֋+7Y֣;*)TEPBE6>1Yv҂55Ę >62b=A/WŸ&^x1t^UG,:zҳ/ߗgI=ՏsʧKmƾ}@g9N ;G*15^f''I8o9$TpƐAWv@01efJs='v\'曆W}U|>OFː=ǡ!=s/7bSΐ 4b3Jk<1[->==nada*s0u %YL+q{~=sVgȷqXw@%UZ"xN#hWTe]H/eb_:ok;TBYad@ul.V+JhG*PX VypV9#|8(5T<ޢ^Wc! Tf *dPMpN0Q44[ȺTcH}>EƸk3>ڴFOUxNңJ6< TX' F5VB P٫>gu5%ggE(7ph;3JPej+{8#d@Lu3ԸաlF|Al3In>!-襖$JCC@ajO(7d[F" Q޵B`uEm\Rz`ce͏psF!2AK8y:5j`ݭfoĽ>k 2+HZXKEitd#moW߈[Md,I )4 [sF*(Jp Eϧ&kΡN2FypP++QD!<샽0({-Щ4"YP\HjF @@ld+5¸dw(**G&#F|>IG` xg~F6* eWE>QRS79Mfg ffY\dI{ʪȠ&ySPWΰM2>VPJ<2A^fu &$B`\VU-(g&d/-c ˪qD*~ = A Uj)3Y ?G6йBUzq*,c]F$S"!c8nX+ǿ<bc$p#3aF[q]S;-Siz0}Ou/ab.};N4z,xDfvz2=K2zpwtiH^ ѪgalgGD%c')Q̬iIsL;±Hʕ0 8Oҿ6 ar3f׾ODmH$LYUVTVB:"|ce.:jTf*ȃ8>_ A̠/t apX[ !Am9|#W٤\1 40GgVHHTǙh'ؤ-``Uq9*bL(LsT+˿|G{ 5r<{γ*vH}IN-Tld ~!GQI)*xgp{o!G P]|󺱛Wk8OQV#8Ak+taʠg>s~>YCrI\@#8u=oqA6va!IYE w-;=gq *}Ŋe} f@cTF&7H'X/u$f^S"qF$? QKܻuzT;4ne@_]T:Y@]Rtv-y{ ]XE~^T`~v]v!LuW J=vBr}mj X>,qgH30[gݦѐ~GyHkxahX5W"I/-msC./XX|,3yGfv} _ ⯿s >d/ [A&@9XQ-^ h)Z@bP!kA@+>C }C/[nRWgƂo.cjԏ&( ,FFd(h?/2' 螱ϸ f[T? ߨǩjN|?+cx6`Hv :Ow 60P ߇-zgyFB<'o74mKm#L{.*8rj<im0'xJi(&[YF֩=T>L `|Gd~*иL@a;"N_,.;QPaO uk}&:ze'^;8~^YG̯ mڂ]`bw&{qtoEA62ȯ?* o-KSSܰ0c8vfJt@IDATgi;p=xD& 3hUNL "e Egv&lm#L!)$ Y":1PapDA33!LXD+z{٧rz8>SZ[$dA%+mZ8$]lD1J]atkߦ&|s|a+ ]JڮToqvtǤ0\k>3`snxʋŸW\V޷={t)Y"JE\9fO2B5G!mh] 8;Z /{}=saCyA\ju0uxi{ti5hXoJC(æʙ+F='kK5]ičLYAx$MhmcU~ý0Z:`sRxkk77 p]'#ɴЂvv6 !Y>4fdP xtGD=R`Eg2젢s|bL@KG0ؒ$'a-Nk{jK^x gvq8vD38Slf Xekkaǔ*$)U0ѧbV8oSYI}Y}= s6#>S-&[H`GiR lN}vI~Z_iH%>vd :Lr6*2gmT {wO>&> a?Qj7&l7 s*X90s  sA\o<nL7+Z ^8d=Ϥ;h(vr`V[mjP"]L'p`rj>o%hMJ#a0 C43i`\KTC]s6U Ͻ<&E6+a{î>)>  \&T ^ Ae,,!$^a]zU٩` ̀3k-? BSgʺF jhu*8g)f!HPEv/K'vh`bk!eWKY\ݣ@/3gt0٤G+ϊ-TfQg'T8f[MYjDV|f;勁."(>"gAtv6%0/8_QBCOh`^W??MQ֘]X$iʣ^J8(YdM4Xh|.٪ YY3c[nb\.8IfX3]_m0z^4N`Όc2FËRy{wxx?M#~8l}x[yBhm--&#(mD0Lآk/R̅5`oKTz۷3 /uhtGLsquZrR;߂zU?ҝ6l;ڙJ _зQQ-Eg1;i}nXZz5Xc7f/Og3ko|{MgSs @Ь@: z DŽ ۘv2D;;=")VDĜme+mA0`}ڥrQ?1_ecx^ $OȄ/=#9̂k{18$ EE"p[I*u tԡUYWw[uDVE \]ٹ-7&NSDjOoCJҳ]MQvJ f Km{srGPv'H]~<]yLv\Gʫtf}hiqxKrbvV X%zڶNܠ] ,~Z^$Qpz2]$]'K~IO+}937xgubnP}B&=ԐVAW]beB61;E $h7Չbut2*KAĀ3`FleIր 3:ZLmbW ^+^CH`:|:X}TVl#\&,!66rw΃i5V.R+kibxf;7aaon03bZMsc~i[סE Zb)sNРYے^PYEC+vv>G @2G#1ɨ.~ы6kj]ZG[0kX oj`Uw[0)kNs vA>?\czKVOX_gJ+G9ЁS? wJC_߸3./cNIW`8o ࠿GrKpX5u=PR[?ϮA +6Zi5+{aKЦg=g- Я d;\*(XOM&5ӉAmmbrR|«,s Gȉ1|mRhk0Z}Nc_Ob.000!{K`$1W|!%m! A4[!sfEyT>@kEFXOVV:siVzĔċͲJP0"r%Me b$ 3!]_kN oٛUX^Xq&; V΁|=o1A;$-9u1%j@lhݦl8ǃE3~53Ԏ7bk2Ӥ!Ȥ@b% <m4?h3P-mhÞԇÀzB^7X'f/*ŌDgG lm\Ȥ׸풫c<:G86 :T]?r=;W_H_`ǩwTZf-5J;ÙcĄHة:m[AsmúI=5sY KǖE~X= o[/ jf|CYKe&!AR) y?,y62D:V<,J2gҵJ4l6yk,G09=HD|L;Y3u}Kֽ2y;{GǾ|,4F;\*gVfZ"{MVU8|yhjI74ՌTvlf Vl\ F#Bz[E3<c`FĪ!llYcY2;]r=xB$?3{VV%՜ۢA8ƾ`c<n{-kfsU`kUqg Fi1 F[&}\' u=0bt?T>A|a!O< 6pw4ڳ;#@9*Wu6h`U^,S߼96')hC}M8 cfyL(ј^ξ TVqlrL83]'x~&s S00i#=M<8HV6&LO dvsaiDlgcz9Zei?|>h:g.̹ _ 'i>3 -,me6Ix2O~&EPNАWi"R<%Ͼ?ŸsȲo@Bvx avzy3sEfQVh# S&/~yj$=3T҇4+pd!Ʊŵ f~vZ*Pk$@&*@'2d- V綀qmEvZZ$Ktez*S/; DHv{Dj]yoIpVI? ʽxD΋#8i5}>־0H3 :O=0zh)>t sWZZRwyq%7p;`ٕC{VSI d =;!`-xbЃ6OLFB u !露‘DZ&[O| ]r={C:5[>73H] ndu+z) IE# 0qslMX_|YOrC=otyAt$>7N}]/'9J%}%9;1+Zk:Ľ^F]VIi(gn&ʗ>z_ AZ* B3f,v&M7k _@H?ȖB&jk`g03]K׸ S;̏uJIiF*$6>Dw Pq޿ pص9g1XgrDHMT3"_k*ĠmaCbG=tW龞5@$VӬ + OD؇C V~^^zD?!Ȭ=垝S!;Dҋ`6kb'!Q _΍7#3/7Em2Lο%g=>Dc= t+c a|3~kKt,QvS*SO_;QH I5> `fJ#K:9^ Zev6-o ] ~8X?E/]# ۑD]d~>݂4F56r\f Ǒٍ}Aު}v#]&Y+YwmWl[2+=Oёiݴ e6N1Doҋ_W>ϵ"X☖+9{}2@uTФ6v#sg_?>3_9v r4t̱ 4~?lC^+( )җ#y|c]3i ;\AlG # TI/\o`UА{L'mg*K4@C8 vRn셗Ov.NoVKsư[Qy,L'MbD][˚> '6raU[h\<^?Z[y mpٕ$2 lOu-K%ǸowއfBOP6hNM*s.:X[ӿе*Ė՝ x@Evf/2 e7O$.c9H&?7{ */m+ %mF`?'$&8נegE͇x3сMrH(Z 3Jvʺ! y6Vw (ql ʬޗQ=q׏v&t8oǰffjk.Pq?L5ؼHkW¡[V b_蒈~{=t~*IGpa؉`UrsD-YbT~ҟ2>PjhérN|џ%:TߩOѰfҏ1B#tz-0h4|PO1}`h,x;ueA[$0c,$"Ok䳺zS,&7!Ԁ/teoLZlCxmϴn5G9ELd[ qE,5$iˌMCLwB]vQvʗ.˗Ϥ4ƑkTWwjd-K) ptQ^_'9;:耆G4/צYAQQ=AЛH$`'gjC$5se]e-s&;ˑjM [k. 5Ɩ{vok(Sw]O|[C‹=&WT먞V6&>Xvi6Q!@S7މ{J-2ZROVTBU?ӷv[od~XZ!+( Bx83O2ƨ1S]E6uv79Hu@>c/棾0ED|E$VOUސA>c<@Ew]>r}jXC*}=+x3n݊٩[m Ǯ[MȧŅEWډ7UK2ͿMb;D׵uof,l{Ϊ"ː2;TTόA0($b,{Ģ| cF;=m]' cׁX\',xDZva"辺Yn`1.EXa1;܋MUB{.I\B6@9ToK%~[ףBKifCغEBah+~63mefˀ@SAZW0NpZ l*vuXt5A y8=NfUhCTZ$۫~p60V0"lw^RԈ8fU ­2uR9( sdŰ>ǀ]NO&E #Nd= zR0J9 y 1ka2@wU RgojZ&dÁB)pI=M{e}^0L⚾lO".cҐI!Qls{P ʜd;g km mii@0@e{ȐTbq>Y446jyHܯΨ?Yڞ7h鱻A*g?7GX gy zNz)-'멀!A+f" ܆LO"’vYU#К.֐oJ)8VC'ࠅ6* ;)mt>4 ]T, 85b۟#[XP F}V(Z5$-xIE%M=u1L=#S({cbp/s n @}2:39"&{d 3(=G *ZUͦ4hd^ 'eYxsfq?^T Z5DS'?# k4gY&%b@ONM2g5X&Six~2/# ςcctz{{ho1`71-dWh0rt MDS-&Bǟ}ӰU!ҰV]L$X"AN<p{l&MR|ɕ/}{DRg^ӟ¯9]yrG_ ZB>H]8Vӓؤ|ici. i>cx}WY=BhZYTCӳd<9.XJvQ3>jLo_OϼFm;@]\G<^/Vc Z:Sՠw$)/!EPK+Mm9 {} ;kycqX;eV2X::Par ec2+uIzʉ%*Of1mma碑qF΂,M󻾿f^]U]]LOhVF BHC`;l6a_7a\7# ^/lC,Bh4f^}_22+<c;$9S]]}볡9ёwr6s-ƛh>Ɔ\a+x~:9tI@{Iw3Øe6hc\(D =T_+Hh59b둑nK'mJx@;ZҍSVx$!J{fބW&'ö+e0{: 8nn?}7f1siX?~lL ٥*f Pw:V3tڒ7ݷ_^0IXgntةgQ+/k6tO?# >zPh>/QOp L+gn|7ԯg9ʺ?\;dFa?.lI@0H`g,_<Lj #5C>Y6ynݚHvƘha혵ǯΪZjl&?WR֬ Y3 g3>zh_d$stgڙV0QO3:0`scow ?[_3h 1hz5 ".gvYB=웳l{dUâ͗l6?u?N 9,ٯk^뜇5ܓ馍]͹#x{sXpK 0hm ;%ԺGMR}|=t.[x\{wߙX>/{a=6]KO_(h':k\fK|/sMSw[v8`NtƷ&,1A2+$F϶VD(1﫝|ۭͳ>0Gς?zPzK]I ͣ-Y6ϺK99_bs ?:{0YWg?_g&CV &P"(q|$n{wju\W|=\A0s%A.hl:$ɇ|G[{YIixό`H|+| xܘ?6]}@T4 "YoOJ#0|Mn*iCC cK{ӡ֬}?k_J#rp676`G*ӱfd *GxĴƍny_\IK}ڏf7b)H=u~>|IJNb'*O[N0W*2zz_||SG;齃G^hzz;q ښʛ#ڐٗު%{5@gZAsm?㎵pΠ;>NPi:O<g>oh/ >$G+6\|btVqMN7o:O:-aq2ٚ9wg~a_gWk)8^[Lhq%zVqnO'9cv[!VfẏS84ҺτNi-6cnP& D=m_צw77f1Zvʽ;u#.6BUوy K>}xPSE'r8رO}~\ڍEB+ >󝄅ۛ鉽uP(բČf=̑~} 0mĒpCX,;A423_0= 46E}t$(3eozof:GyVe $x./64 Qup齷~s: uy{1}Y;+n);@KǏWn:wO\w\m\i6,à R RRp25.gn*P)gL mk{pF.@Ik\ <`Qv]׸dܵv2;؞-XYF1l9BPy̚79s l0ޖºPL:h+Ce&)Ɩiݪk Z>IP_@o*>fTe?;Ԃ|XŘ9,Z{wU*Ɵы(_Pg|]0=pz'C>$PqLH[ONF|ra[o@|]<Z0]%4Iu}5ׇdJD4>Lvs:=%a@?%7*Z霡2v3vZd$ -Չa2Eg:Fmր#כm3c4139_vy9}~,P_0Ϳ ӫ SƇ-V]Mn8iF^&t/,p|y>< G ?k!m̠tGRT$C Ej$`}JX 2zEt$E=u$ʎ!;˛srC#_-Za'.^ fRUɐ}TcpT@#ռ*Re ooV/Lʴ}>>o73s>g7O9/Ɂ/@}ݣZrRGr"RqR9EVx<;ӍNN期adi{} -!Y[A@ n>ͱ[co\@Ʃ20״?e1$ogoۺڋ oiNd#^8RvI!9x9tn@3]վ.w|Z5n^ oE"ǜ`.nxURg.yšEck{c]gk}ЭR %Ahf[Ɂn$S51.b\m-= 6(ҳFe=icLu&훵#mL3ϓcqX ~_7xXkaH;^3*u6v xtzPwɹ\sq/~˯ЯZ|(ŗw;q hVU֢rsqaxm9 GTމvL}xGhF PČ\ü {ՠNkpI  *yWAr,e { .dO$?[U&vlӃYU % xhNِ/oi%eC. f&ݼK [w 9 CK4;ZZ~Zo"{@| *=`{ ._ёp}gwIKUI4SngZW|4+x(cıQ9;|tN` Î5djL};$4Zv?lnsRw[J7S fS7hGd2iF }Gz`rkЇ5"媋 wQo ={G{Wfw#ف!dcqxMscF߬d 9=,I tҵ`-#=w\>b L>3.}wU}qtFѾ+/^8;2tTnOm]LuHU!ߌJmU43M. nY8ڒIpQ0%3wS/eޚ `Z=pZ@jكzO@Лp:RsAAA5!? BTAg|'MTiK;pߙ+1*:\ OW[? _L5CTG*g%U/` (YU~|}x_q6kIvd#QTn_l[Zڹ 3[ԑ$'qz^,Hх*ǾECnˆYw\jV>{ǟIq @o!)_8z: qնKa7+D =ÞƟ`k:ÕͰPY+I ;};o?ovdBUzyKϻ7_t ӗ>UxQRxc&ޟ8:sBIa[FyAհnR50$¹!d$Qpɚddqw,Ggoԝ-{s1;2ÞK b_~ctt6oޚ~WީŹZNH ټ Ҟ7?2hD'`Enm%%h-,O!U`rГ|P;ͽV{=pC86ɺăMH?@,/x*% ?x<Ŋi6v ?ΰ˥1=7w|'0j ~qu] I$랖ވ>iadiǺ8jߍʻ 24"g%TE?t㫠{"q}o y@=amD(;{-=AE]^S ? 8`ֲM "\f0L! 7_nx1Ze ]xnzLf|8BneOiJqBYj3daT ޭk  j$֗%CȦZJY X0on@ΕksslzTLڡ!^:\;v0"uzUYGS@ƥu@  & iF~PL6l}+>rwHNUW zw>CDH@(,F ;w Ȋ*?bt4(c#cO}Ms_o޹6xWujuªGtjў%2ƼznGk={:8}Bߵ/:B ]1Rκp+bžp,48}msԳ+7U dHZu^qwc=}wdn7e'̆B. /.h@aeZlǕve-Y+ |8{Gg: =1X.9\2Hu2y݈NlsZ?$6>]Oq,̗Qk*6VOk%&Ux'pwayS4xuͶ  k1q/!iT T :'ZN7&eiWލk"gQ/^;rzͯ,סpG3[Bqًd#=}qZQ|ϙg@qlePKqo4-㜢Rá{vm]k!x=C1k!{kkxY=)˸o>M'q8}L9ʻd<|}4mHbTYڝHT0o9 2g=omf@ u)J]溳"W['y6;Ň_ELlA̓,A)-OU0?xL C^n=֜\y{ / h?-]Җ<>ak! ^κ; !5s,s:s$DZ0gc@ttֲ3gxZv<8~|U6υd6Ǫ7rn>m[CvJ=*-&f2T.]4?ث9]/Tgi t0rx5uԉ}x3+Pώz9VEJ;r^2Úֽ񪼐k= 9*`ӯ_禿Rݿ~ݝ?,whs2gk.}Aކ.צ9Uxr/Kq3bϻ_zetux/Atь柏$_͜2Z}} xBx<,QUIЖ[`==CS PB{/<> T)~or|IN5<[Gƞ;Z6nm߻ub#NldfWj~Kζr89}2r1ThAJ>I[k3;`̝2&/x٥G{<]nUfU{9l>Giгz#&m FLv?-}oXfut75Ǎd" ;#tԣޭ*$Fȅ_$Üs}c_?zhVtqYi># }b8\{Z2!y>l(5hfCxJ҇uxgZ:֑CM<[cACf=A3?֯Dpk3Qux ۳Y{m|\;h$ž-q<Mt!IVy[4SC@$Z'.3=UΜiq {3M;rkwK:Wg qI8\;:8[^iy)Qڂst^XLNC%G!k,hU%̧>ڶک?AsĽc N`5W%9zxt_ڰ@ёٳӮ'j8,[9_U[7ϞT8s8/w4ZWߝapkMs4e &vSd%a0cϑo %Α$&=a8-{Mwz6|l]Άt]m=7i}PqGr8UpdX>!i]U5݇ƹ/<ԙܻkjlku UzGV?I' 6WB1GssеyHZ>A/x R/I>dX>JX+No],Ʈ!◾8O{٬Ů]9ǩN YuupT_J-$^me2bG] pI2TL hJ^>bRw*X~Cs]MlM),}=p`<2~^0[2w,[q39=0ӷݚ |{'6m,}8nB1-J*"e#9^F%\< emsMq;|]Æ>b(3wT׵+Ys_cl`LZQؒ赟xh6im삜|"$c;r=KGGXNtrmOW}co|ąt%oV}kg|j?[mlVjFSAx\dJc^wYzKLæZq|0K*@jL3./Ƕc5r$ ѥp(*[u]Z?8Ygɝ#?_[]#Yy|q?__(^jr xIbQnzx@z:JaQTdjհ>;)>gO=%@)ܫhÙ_(wޜvg;rS"YO+ڨ*7Z#v|_]>"3%9>Dpqط'ᩛ7gJN޵?'o|{q׭NN~޼n+/+[هs7 ?8֚&{@r+{[okL1.>x8M?;WX+(Mu]uhL/6QJq Wt'wY[2.z%ڡvڈⷶrf@zw/lZ}d(}ҽ>-i+X,~/Vs߃ jU2۶1)`zҒ7S] Q_IJf{R̂ϼק%K"-X"Dsq-m|בBuOMGG0Pқ1Kq11CmG 7_Px)u2v^==eG@e Pq3ōH>()[]o<ܨJLv90B`E VU53fK ހy=ѦoG @FDŽA2},ghh2( gmmڒЂrcՔE릵uX9[Rh%JJX`"\V&Pۚ Qc2ߖf(BcYH2"֊a= ._֘ ^Bncz1j܍/wNSᾮ  {NK*Ly~Lϻ}OSuy 9xD\.Ey('d^K 9xUy~'_X d23{yea|Fa$Z?hM`.k̡Ǩ,@Ksÿ́L`O)i|v^ս\vUq 7g0t!O)_|pEKœsZ)aEjSi?#w%K}o׷0|}C #Ӣ % VU8#3i8oѵs7p}s>(WjvG7Nzׯh= ?]Su޳{֒ _WK'"<L؞aFY/2HbG=&}38~sl9r˞ ~ޞ`oUaǓ .O€kڸXkH7j^;@Hoe qd=t,N6Dk ~K];jCjy @Z7~}?Ӄw9ltn9KWwV:{ZjVݰz~Herlh'Yes=V)_)ږn{9|N{ЎCq[5gN{o4k_R+s6ηrȐ?>"| i߹Y1^d GO_6}7jwx$b1='g=^?3RUi7Z}Nߟq{Υ:mRƲ9a< ̫xښwVj~4bD _[}WkoL~@^~ʺLSQ[G%:SKĪ8Q28`ɄkQ@=}%B̭ʨR[X%g0ax{8/lݐ.pV3v CvyG<*U4vFJGXNIXuEʸ[~Q>yth8$Hu!s\2(QU }t= Akf}*t|G3GeoגyTn`s&ݻwrtU NkWh/?ӭn|?!@"a}ІkJ7ڌfߛa6.]#[*1Q۞8^U̩9= 4Ǥ@ >̑SoZ;(-=tK+J*6{Kǟt$'^<ѬDU#ߕ:IphF}LYcnx`]s3}՛KEdcLwpxឮ[ծki:4/%hֶ}ou#t|8Xp.?4xű莃 ]ԣ=zXw1%mET~_v߳gVf&`*ltM}nkn&< #G@U{ss6Vp=[~ә_wÆ=?6n\ PW{6a0?L ז۵Dg|+\в}ގΆ '={\\78WHSױbV~dN;BiK~a˓$cG]e1FoKLO Go|PݵJu,0>v:~t$E#8U{ l όhTǁ@?xH2eðw/B6W@v̱z`Ʋ5>$$#1f~pU#/ݽ<"ЉIu+x@$1&/nݸ=Z{rSoJx7+ M'ܗ$JP'I _l~'fKo̗2:TO|urFl%l vG~G |޳ B*Gt:zHɚZCB"TZ5|7|ӇWP(-_:*wq\E}dz=KX[\|0W%'ma=gasⷛ/ձ=z:tp?`\{*G^.X ,j$'T-/ŊQ;?׽gGb+ 7u ݻoK&wo3ڒp=Ϸf~w} qA*T2c^#Ӆo/eGsvE;1Pd=֙f]}1VKog _aCHN6fݣtlfegݕ|@6䏀/&M4H g)x`Ywt]s]TVKxp}hǑɎ'% o+ߠn` J k阋wO_{?9 SD bl`x|&_}x"wf>N6\[8*}G Jspcd{>]Ȗ=>(,>4y>z+}G7\tI_-,BO.3.\2hI R]G/fgW%.9S@Z|o@H[ܺ;awHhԽ|C4SI/'>`d[ıO-)0\}kt=$a,>(a^#^V퇵XDxuW!%s!8ڀ X` }sƯ̇AiSZS"zp>i3@7P'_<1lkpY}a@ C-F?~ر1;mbUTni,ݲΞyࡀlMrY~ [nDp,fcM O_#Mff9z;<T/bTL;T[g;j1ѣiӹ3NO[W ay6N;0[DvP푠,2'Ep7j_z䩗 =\sC2W)Xgq )E,Z%'Bzqn6WN"D(k ?˕d$7g`iʳs>?e{C@qB'̰Yn| nj,x sri-Bn͠`U$hߠ)JR5G,2-wgr: :ҾrjR?vCȭ6Vnd4A?$|Mdlt H?(`Dy[kv屧yG2xf|TOޘ (|d ujr톇)d.`&@`*Ycny"Ym.u/y׾^N 5e=8qH6U;*Be o>8{ 1.8Krh Lr{ET~2;ƧO IhYU*zRdUV~ΏpAU|8׺j5O)P1ΠWt/'{_LP' *n?vAa9_)e qd}DƑӪ85w|07Yr'd`~0tA zVryg<1g/;0y΅! *yS10Cz&2*kA+:Nh# ;e,R%T-_QbJNvq>vU>2uDQ]"&;n9#ej~3%g`+\#s{8{&?{YH\/DKsDĝ3@w<wGésܙ3pkUo~[ߊ~[v]t˩'̹.wK(1hh& }=T%h}fZ{lm ƙAKTٹ/}wIٱo|LΟ ~zd z3i ;lDv\ei,HE~/c58tA뾂}%U+1wcFhņя?O}ۿ:pp== ɼ@ɓC}[fw :{O $7q2ܚ7G]#F6F3Y:ӧ?tўU0f[ɤƸ>^Hd {}tAU'1L g% *JbȤYMsz wKsNz^i~N'̙|o:pcI /|Utc|~|nOtfѩr2u zY7tϚt؎g673w $nMIkC[<}c`M0 mD0|U$Y#4y.6#֥9'S cLHf3fB6柞0&@OUsڕƘ 9`ˆj7{#9u懹A(A}ݰ*RӷÕh?ia?gtY?}A! ֛c/zZKZgY]+A2Ɯ9o`Nf`X-%da΃%0m8o^b8MX< LEZ g]n&Q5KZʫsi->WpX7҂RgA }6Ѐ$; 6sL?Ka=6]9єޟ/ }9ZM$R5#t#\4A3ւ=ٰ&YLv$ eiֈ⨅yﵜc *u A;ETv99oCd&ghUpZ ḫ S%Ÿzc"Fk$tA[dq{X>w8( ރx:**n ]"l7|uD{m?1}ǿ.Pyk pFE>)xQX#H zC=niFi7.z#{O1GF:|$JNh: \d8+Y sXVAWdxf9/?I-dT;L"0ލkWM=Vֹ*.օ״;DϜ^gANK˯b{ |ǂQh˲'/{onn/2?5_YUlŜxHq$'.vT`zՔc^2xxt{<#>YNWg8Con^q[,~pX6{qxε^ XAJ/lN28wƎ_lX89#ilƟ?YyV2~ձj7~ קϞ:<*pB*[lLc/;&1O4G 768#L8πNՉnؖ]ǁ'{ t{ѕ $GL] l^?}tZz&];{6KsV4K~X YD:&8uc @Cn l漺ڷ:fy5Mv(4͗9OszSPzg̟PuǦjzeWK>dS|v#M;gu5||&xGr4Dtf~ CF nn\(j Q!oWBWއI!oO4B89T"+MxM"ޗZmfce)mB v1zaGsN MjЖN}KNql]WӁ-:սsoAC*DWA;zWnS%i,,ix|4k؅c18P2 !L*r!!$X/o(QA9Rqh4m~+eV-7ONwm3? :ӵHj%5 x(ހ'1a`x=}[8֚55.:4φ3?,If0-4pvŁpu#!WTCKd$y|G8 \9XMyߐ?w(?~%!V]nޒ9-yS]b-_'<, # ^n>qs|3_j }'[^^Gb33߈7ҕ%a.vNx: #/~a%J uy_z[3BUGg<M B~4 [إ#~KS1_b ۷Z7vtSI\f~PEϭw+6죰ڎ'eK;]0ܖ.ttfA `\$I4Ʈd:Bn>|vʹnmafS42vZ~YDXQpXՎ3kӻ %֗k2}o]o'jkM$J6c 8? du6pc¶޸[r}gd2OW ]FHj%KOm ZgIxq})V4FHD#'͆lm-w *@~ttO*6ޖ5f篯Y,K \8! BF-uZ?^u$`9dgm}G+~mk6*zE ESGГ$sqލ~mYם[#J<F/19NYJ{]kV6R{ڃtYIHr [ hhimp)s2";`GO^~ zy/ Qgo޺ Z1{|0 !Ú{ֵ,It]A A( ޜٟ/ 4lt|ؼey2c@IDATHRi vM gѵ:ZeĻ| jDqˌ!UE=9$|b*@Ӎ`>Ij6b8/U|EH\.f-^A6 ;y{!OBH9ijӏw/* PKQ!>ٓH5y {cFCry)>I#(ȎI)mmT} 7m(c> Bi\Pt̟3^)(|UbH ^+>'(E :v.` ^F'2߮Nhc?~hs ͺ͂O* #t/+p<}Ir5R#g^hY=ݾhyxS;Օ i ӍK燳o}km7\j\  ExŌF4D@:b# 7N{7YBŲ,d ^z|ݮ6h"ZV!:_fm-܊PZ/ [;<]WU:Ax̢> ւ@x.)g) zR笏1֋Id<̪e=>/[Cהv{O!Ix=<zN3X"͞ +ǭ}NHA 0tbx#QQa_);g蒞߼8F:9PkM swF1dXk_F2#`XhX97%(G(g`tѽ,d4~[H>SL:W3,~^^bhtny n$8}?tc@>:WYi>s3G 9ϭ[ZCa0$%qv9g$= H:A# HsWŁr|Nn}cA}u&.`:evɅ'F5G=W#!\+V eh^ׇT5 @΀a (hsnt#.OWkOU8A}ӉuYZf5to}TrkcM_!~Fdxt4wOЋÇB_AˁmOg o_>?6M/׿Ozo+u<4}u:tawUzM"eҶOwĖ\m΢19$af隰e/9͈|"p9G+-9"!,U2Qlfx l1FU. Zg rȼ^ufCڕ3s<֤ &ӿF;?c8qJ]wʕ;9Kjʃ$P-5 AݯoYR ;C3 A`o L?*ך4< /td:6Gt~j.K'yd(ADW rZ^H؝c.Br>q9̜ycKX4$ǒVs; %ʤluȨDxS5FHKvpڦ{Twm GoAk9tw߉[>0I =QHZ%Y-' H,VB:#9TXsm[7EkfgK0Y^Kد_K?N|q=-)g{Qi_ߞ?><ঢ়̧ LD"} -3g [9.ϓf_oǠIJ{+'I^LUhO@׮*}t\GA37ҕ3|}<d{s,HpNx21tvÃऍɹ;p }>vhn/םWzj}~pNiWa^>&tΩv=po # E$ycЧxu9^efwu=KW0tTs~l搹42]1]Ç#ϟ2W׋GLvXߝ Jq:>gOH .d?dk?$p\Lx%PNd^CȠ5jcf L;33Z7֕o73.@/mhzIQm#;8ɞɠ$]ؐ|1y ,]Jij]ɳh90[\.ts޻8]]qZp:+_gG%\QY~Ku XhݕDq%]ӏ#~05KXAi Td'ʾxܧ[%:;o|睂NޞnN8<}ѐͷJ09[;zwAlxU+I)4 g D}haU!gWl񶗀8֣kڂY[>PX'ΝPuhh#U?GOΞgԸ*Wc*_O K%qU5E 3r 50yHb1v_=҅͡+ 2  ϓiȱC7ߋ΋IQ^{饃Usln}sG߯OFڐ Vdz{|޺:0} 29oEddqΐ;_ |g3EUXx :緱}oɦ^Ē۵g"$X;Hnƻ#þG3_9KNT`5P0?U`+a505{0jZv;օgO<~W[@\|z?oN{!S3|{-z^ 3\P61oGUbc-ػjxm'f1"[B_5^kLI ł3A`uX?cf4C3NB3گsW/3iuMï!6kgMKرO#>y1l}#tS1ҽ9*b+[ߝg>󨔎? k IVыޘK ȞYMF uHx98*` =FU~ru}-wIp}GZvjrx`2Tb Z#vrlOuF/ƿp5Xz(%K=g/؋# ]$%0kd<1d p)_MZK~0!dw&m{6WSؠtR^ =(VSOg+*_ Z$YC )=;[ \k0^)ؘ|NޖDڼ=>~L:VSLhdf!SNH#X=qjz5<{[Ժ:8}FQ!Z4^ عw=`t 1b x⅑aӳKE-1y^ܛRcAۂ ^.d=ٮRfͫ,;׹U>* t ޞxyNպy4&sӖ}Ӗ) OJ~oߵ5#ّa ;cϞ l^jYJNJ͋c&Dlw2Rm G-n60W1ujld#[S~\{Mm DU,n[˹d9Ζ<PFExG0S w堋PAd}x [|d;a%T%0~fHdL>|L.3iԚ !;[i׵c9` );3&-0{@lovלƵV u}ǽ AP-t h@}9( F gvTx5LZ]۾}(ת !5SC־LZ+?[~4Zidor`޶z -:ovG㊶r<k޹~~OVd5aƭ^3Jȁ@'=5-lܠ8ӃWs̜OC1?:VKNXoij&뛣5T0h*,5[`Ł>>z4Llgd|qUsƅqQ߳̔uɠ o9 m\ેKX'Ocu$œ}=KUc|·i[8p/+ah8S_, Koךh;Z]+/0@j (R ;t^zNO~\:r⥗ꊲgǘ9~tˣZ[BUE z Szg2_gZ( ݵk0R [nӃ6gsTζV$⇇щFF8P4Cht(Ih#xnU"guSѶ z'zi|jZm#0{,dHQ4O OW?~ok?2OߟLO\vj+z}8IK/Oi - UL40In0 Y xkeGxȿ%vp0>;w7ٴ!nd?=rl8$$=I.g&w6 nOv<9=.̂wniG8M8&'?̉ӎ.OWC>'dON2|H GJZiY8f@$m';ztk3iUwcSj΍`蹍Ʌ932hEF3-xn,u-cqk#.r(@A72 ;{b2tՠ ϶*mfbD2 |X4 pGת2}<=7sv{+ZV?2GwXU"if{t? z=mA?Ж%̧ ftl hs'[qT^b5ڞh'vݞ6^99Gr,]TȐ`l';s_B p8*BIdiBc54X_:I2dRr=ӅKTsn!}*@1,2sXֳO`fϑ%;?ʡ6dl>*9E6=Yad{n9cڑv?|(' [;{$ͅAQM'v۩:=+ATׄds;24~v9x.:0-d!3ȣ+gFgf sLZ^ڐl{K__m+P:6w٨)YQݐ#DDHr˪'ڃ1ud]BcԪ#Gwhzō{-CoV %$#'Iǽٍh_#Ygrܡfφc\8h~U6v\9'q 75Zlm 䏺Vpzόf.^zH K?q<בŔF5xn}mWl={EV_Ё>ٻ{2°0nW;jWYv>vT8T $ۘv @r, r*"ȹh(!fȂaKGcvbҾg5)=kӯ2GI"wj[pnfg3mYϽcaZ.1m<ؚ(g$># fX fIɡ>gK3 $|ta*; .S 0^V~Wls,S=GWOޞKڗ?=j:VP13:U$g3 Nk/62?I,tB&G`9{_ :}˟#1tz.u{ڗ>OnȺm}t[B ur@ kYB }@\r}']c5WR(-B ~o?dݖ[/qjZڵfjawsONr߻yc@=KL楞h P+S|U܌?x2]KuBJ~tKTSǎLW ̱3_<\?mi[7}wOtx/ rK?xΌ[|+Z?SIWgMn\GS0kd|TTrgUvbVIV%$Vs(67o)1୑x WF"ߌ_λ}XpmMrQcɞ?ƌLoi44{C@jϖD+{ 9@F"\0YfID>+ [|>Mxc:wfAGӥ[^~s ӷ|kxmk/Nʴ19L<[asvi?>oG/u^c۞J2¼\a>i44yRGRMת|t.SP +6`EIfzk= `#qD/+G"Vхȱ(?ڐ %3pK̇7tvuN20Z'S0b2c4 /,dxŋӷd")t=F~JF1lANy  O6'uvϞy8yJNJ! E[ju#G@t#ZjE M`;v5ש>{絧5s?}<ꨠ 3Ӄtj]%0?xu<nW|Գ++E˵G&V`Ӻex=كD{l9jĔ]i{g3+W{zpth[J`t-bσW&!!L`χKd\˧/ݳ鎍+jO310-Kv_=|Պ0>TGn3Χc/$<PpG|G" Oi>'<13n|(s2KF ,KX{?O=J'RpK|'$B`-7O{mYoi&,3X zwbmaxE"DGMuƠ>LEkϚse?8b[:+*+ab&}UT_1DϜzFxӥvc^p}Ok2U9\R ^v86\ LS"}7eրQKgqp3Q<#|$kG۫1G6L>lUK@c&Uo*6z(aHp 0QRhZTL3%Fk'OP/R+{g]t0/v HS>?v2ϟy+d[}S=ZΌ|}fUgύA>R]2Y`kWkT[n+k8vrYfĝ?uTbWՙs)kFFœ6SQw§2˻?O8GblU=WA#U$b`(s+z (n93\O+t+=UEbaeg_MFX~'9,??_{˿ߖ_eW~4'DR~yo/'owŭud]<]dm(G0zT*MUE͂XUK"վ>Lm@uvp3?O>K\|/v]:n7aq)'cX <G;xSZbI38Z[__>/ 3_X~﷫{ +"fk?xs*Sxqc> >TṮ]k4 tݨB-ЗȘ1|KPl5<=2\:|o]$^ApzDyz;mij9VgR:ǡx p1y{օ=u FfڎV+:SرmZzLhs_е  p3V2=Y>SCy5:n*m%}h唟>&]?NchD+idzɆ? `t tK T^m=FCM[|Zwcbpg'sRTFc743NIا3~+SM3W|,ٗl:7bOgh48c#փOҞ>gqz܉Hw^o0žYуhaUѧgCH[ H.x/푱8я x & B뺞IޙAmkkUmsGV}t=)c^hċpWEq{Խ9.^oUxw&gݷ^#V42@!'o3^+SUsͱW9ڞ ܁W䚭1;zo_뮄K3 'xnC{CpE:QׁNp,WmF)Q[fOo4ɛmO}D 4ޟ?WbC'LJ`KWso>%_>G_4]ݴڲ?E%B8DҝQ鴥N7>NpB9<I"*< گorr>wdz~2 m=Lg.O_~ݹ7^JZKg'9/z[vsB3S IoF|^[}dDɂ]g]+9fN샞"41 êH-߈v>U^(qmvO,_IQ*y=s{Ėzel]+>NU=͜o2Co 6 nM]J({%9St_cFE)}ڸkJs_/}.xV2DWZL,^#`2f<bm3O8{|;΍9k~_^eZg\Y߽<[|7c?D= fFl2|V-5Al8w| Du7Ư t~>|~[׳SUfko,Ms8ß/.~uT' hF6ε/u_%p/a.$=4 :2[K'}Ըt][ޣu8#gH.0\9T@OߩwOtw m-JBA~/O|$,%^O*3ڛa}tis _1t5 Mek#dKk3<ɰґn_G/: `ϖ#\,7;%>^-IT)n]8gˉyg,f%37KF~%1m[:$M(#=Oʍ!~$u|0w\|e:}ݸ=FYj NO[*HGfV"ˆwzlu&VoNtot{)ZLs/=va鐺 ?~#O|YtJdN<2/aL.ɾe7&7b&ߣ~:A|:hqP­elAq5[3Y%}T+h9}ncYwSqoٟ_B9q4u~r1ޤt>ؔɟ{phw^_Wα"V4q {ݺM`;o.ɂFBW{o% w1ܾ۝Xw9[r;nͫM=_':{vG\_v: 'uS]Om;5]I+5;]dV l3f׊%nJHx4;W9fM1:==ͨs*nY%m~㚳O|0@!'unM#XTK}h—փXgD?1S==J|]+*k[mD6 u' u˱o1lsB4{̓O;QrlKr:%gf [}y<|qt >k]:y|GGpՙ*{ݧc{IB/5|w8p:Dҧ{dD | bZ-:%9 pIs Օ`!!m[ٯe{C)R((_Zlms1 ֦C+&|ΙQX;hl? 6k-|H (r^ m!*xT!6m%3~1j`8v!ABۚ(HooEIqJ"'6Z6u4V.kz&S}OJ wfg9#rܥhak$Y8Sj:ޝUo킮AӞz^L@ Gv%7^JXzzΤOɊt7 9wuKG?nhl|Nj1FMA)pr63Ԋjc19;a' (J=b2΄}WU毥6eҔ g`G;?N0Wt߳He ׾;Nӧ_^x |Ib}͏I銆(iNO2t߸}~(z!ڍrJ23GO z[Ky@c.'Yk)Gg[RB(ÿ#cpТ)|1 RB>/*׎SB L&=@/ mo?+_MypzU+:Kq병9Kw"50^`m?Ȥ/}'⋻q?q_7W/˟T8~~?,]A9H,Gɦ׫kQ>mD_]7 /N%9"?m ETu7VrGuiю%۶1sJoE$ӑ*Ң5t;X;M&yf8~,_? 7FZ5\^?ܓ~1N'ar?nьgKNc,NiNhћP{y^{s2y컮)eεo!C:rsu.=D=O[W!=nd-ꇵn/Au{.U[S]jzs@ v4h=Fwn[s'ǐvop1ozg\ ㏾$>0uwHg&w~tk$'1x-:KBGkݑ'U5y6}:LvN +ǒkB2@RƛȞׯg#g2ϱ~a7ޜ*IOg?@py Б5wV j%Ac R.o=+Xup`>6Gpq1I෿fU/G\ɿcxZ h~0 րM@[߃ĝB/>CPW\o-_^/_ `#=7:bޣc;UN@6tjFўù6gc;a8ő&!B}<?G2 ;>{{s d(߿:0cqX7pM|V(?͖Mk#sKhrdҜMZ;P +ٌsiΫ|^ #gֱ^ܘ. .]ג,|?Cm0QOr\e+[{7쵊$|~GX ɒw]KT} E 9ǛF=9^9w|[>̊lG y};/\O_8' M/luhH3ݧ>G}㵁WznrDb~ǖ}&:=Kv+l->_=eĮS[{'[:X&j.}8v?|.xbU򭪺?'?Zq[\'; ǹ] az]p0n>¾pq^t?b>|H||k6᳟jc~ߵ}[K+Y^>=*"8=mIwړ$~_<٩ۛ/"1o w<{}ܞ "!)aO|"7ۿw[Vm_gN VGl m U|\=w,#@~.۟ޟ/1]9M!yfw=7 *_~'Tw#sdFv՞hj\;ˈ'2:3t#3W*8ꇾ}>Uk )O& au B7&V~E嚞z<~dӋ/^r潋gE7{J#g?.??QSdk)~KjN7_zux \'85hMxc:=?CA@辧O>|2? L%ɞdގ]t+;$ I:x7sg=z$@!3{mb)$B K^ˍ5=m&_6:~Љ}xvxQ+luh]!6OYw7KYW{hxEYzN͸6W|%jwLh'=njnS<[K?FM>.ja -:^4+KO >Sٳw};Jrggjf˰&i=GAsƶ/x;e wgp[9RFYw*vcX{/!,ed% u kQÙQhAg픭;wC<9P_-kU-1Ĵ%P^!j^ю\@Jyvhga*o@zS[돢Xٞmmܭʧ1#IpU\D'[{#FּZʢh #LI4Iqvw3׺Q tɠ)3*B2 HK58[.(b۝owdpJa4Wˊ&m5BP1ks "o˓کbk`VC:qGѶ,som1;ЙY2|/V, 2 hϳ ;{aqjw/ii#Kw[{ayS:ѵuzcqzIȹykaʞpvKI3$@UڙoNnkl{+ab pD镽8f@vJ9piUbIJ80"$F8b`-04{LIH1 Tx2Yqڗ{rH?*8RK' "sG>0s=7o^h< {rbY1vt>`L)IYo_#zgO m J㙼/©#ݳ}yܵe;rtƞHn5W z,/Xj 12쇓% 9 ˒Wy\OIG ]e;.OqX ߙ9v O+^鳜j3_zJSLcip?9+d5,~%ݩu$>ǹg9W^Fk^y7Yў^{mJ7Zg9چ Z%p?-+_YsZ$[bpKth4۶aR8OeS*8{KBoO3h[}!o㦗}cRg?;wrsdO-@ӷQ]}gk&ray0/x8FsșȉNnr7}ő57$kKb$]˖`[ n\GM3X{f[?<&_ӫg.v,?9Orʕ>|SΊ$xI'O`_~eΧXF ]G MK[=n5a^m#fp<3xwk'E =&x*rstU#fϮp}_m w7ϵ*7Z'?J6xHA*qho OYTĻ8 =4[wy0Zrw2i|Z')vvD>ItDV`jK7* (ZRs6:OQb{u&b[$] DwSuz䟋˶%̲ؕVʊ9#_j܂~N uyˑ'az 7֞O)"YI㞊ݞ<61xRc'aV$6Ԓ$(}'aN:0ҽ*ֵD5F֓0~Z ik?C =woݡE:slx=D&Q a,݈L9@Fsf1KcɊ7A^olq &B@s*> &΃u noȚn|ďVw(6p|59h(V>OuԱTO'IL`J6.܅hr=|}LJ I\CFVDW\wgnԾvqkW E%6~rL.p4|=*ߛ6GpLo쉧3,sb lۻ괌Xh`8D?cQböV‹/-◖ϖ?|_}g#Uq,7_+! I x`^xLn^eM6Dmr^2=xmٸ|OHAk 76NBu4{ͩCKP`Ƨ_84JCB{'cw|,Ch~&k#DLk9 J`696↰$ ܸXesI(AwZz|h -&DhΗ'c';/Ռ(!"[>d#C껪`Pb{F^mUjB!Zk2gn`/d]IssSK]+U/л|MЯ\ۛRo#v:`"g©mMq؝BM0)3IlݳWMlZh-RZӈBB_.\)#,^S;XRGO:oPn290>8W jY$'9Ě5A qA(Ι]j\I|>DyD>L#`<1Hؗ QHyd&lvL-]U+QCR( 'A|Y{x xvqپv4*`>ru搼_l s/ż|{jZḊPo(+ +r3p}4 ޿qe{vTFU {#˷W^ j]fӎ`i  Ɣ3O24M;qi^xus htJIe÷$A%ܦw0CqZ兿{"=`uSrLI]%}!Gv} t|NIJZ!95A7&p6<𔵄kMz{ ^Jva,LiqE`=9 εto[NU6'xi?uj\ `0^ Ľ?pl+|GO+k_9]%cVN}#uЀAOJj qKNkČ8_4q4yq{}wwO69N}rRG D緫F!>1o>>L7dfdp?Y.4E\ZwtIɸ=Lȴqfrt D;U¢eJ|-aDg2k}$e~:=@Tvd>#}{y{3f磧?mfwe]8XO0lY۽ 1jSݓbV8R[`qȂiXMn'ۺQlfwgArCRmSm^n/x=^}֠rtnf?Nn };dr$6^$GynkPW ;81AltK+I] alL2.!abգߎѼxom;%Im\ _ 4~ۻ! }QLʏ@) n9']vdYpoͿwL9+4PGct:ry/Ѽ؛sP;[dcL2U1y\C[o*2>o~t8z9vO~l:+85E@M~Oɭ(zz?hk: 47oH9Nr|}I2pӑv_kbĕLTbƑvN݂~/} 2n_Ww,{mAzƾytxN̓[B% :n$ g,0:%<^S8BI!]8kSp^2RS(n ц3,gOބu}=tIt*P;ə%\|7i ~M#Uɖ+TJu(u>CنiwyK4I>IV>Wni8H #<9N&6)6ǂ!5:С|*넵=s$ֳi}_M8 SU`_s{fL&غu$ߚx[ O{컭Ӂ9AK,[cלO?Y'$n5U?mxl-ً%K#U7I}f,eoh՝|ʯBݞ7.;-}L>)~˗_<5{7RSO)`VhkG2{#_ͽ[i.|nR+ɆhZ$[>M(xɨMk6.'NKIGL e9m1; {f}Na _ u? wIE:׺Wڊ^^GJW-ѧ٬4LDҹ̑@hA]5} ۗ'SwJ̄/ֱ;|},l>W<,>;t,Ľx5]n|国no߁r혎V7jm $*]gTM?p5YpCLH4A <t)1h#^IM_%mDH}ރuyחSvo tSblPEoSq|\CK{ ރ޶..9NtIlΆwGK\ + ÛRs/};X [x NG,;puo~Ӈ_;q+Vp]U:9 x+~8\/u]hd!k7 um~~U|=lot{ECx,T#i[8\qlJZvrt`-ӏn wJDZYwS9|~;PcMy4?>SwVh@?/)_{[/ {?"sꔍ'Xbat/,=,jQ`X"0yw~:=\itrBh֚Bd7شk|+Ύwֳ%&u뺗^(oepz%H4E|piэl E"3i%A6m-u`eK|؛| f!>6~oΒڣxT[N|&*ܧ׮boGYsȿ־1/tTԏOo}u~WF0hcTU/c >Ъhosw0Np5tyB6b[cXB&0Om|,wLHj 1 3JIkdmղ$$͢E֐bވ bxvc~e9on2\DUB_),=U>$={rLfG]efjKr}.;: v_us8J!-C^Ys~7ژ3U^/j;?|GTL:?^˽yOZ/p猱[9sa_kw/qP?5OR68bpז'Sio|g9xU\mznyߗ_:=Ŕc^cJ_g26/;>Woe4܉ڌ4+Ѣ9n_ %z۵Å7K Afcm  PvF*={y9Wr Dt3y=ж(C2|NehJZܽ/;\[1U-qpyi|h_A;T кZ D?;3y>`e 03)8v'OJ Ka#9Isl ;Q7 |ڣ9[+k(uuHhψe جgi͜7Ymʒ:hJ)%̽gT1;cȦI@@aTPrv)9 8i[@Id';k+*jqNz1c0|_ͥ7m{lzЬ)Zpq&Nk4i"V.ub. ydn:}1>Hat\mޚ3:b|'~l}__]hc*i?̸_ͳG@S 71RÐog{9:woqMe3A=a6s8#S'goFY*aM:nF,^Ӄ0xƪU5K]r >_1]Aи:oGa9sIsXx)\Iu៤rcF~a2 7[7І~lk@H ̫Z,e|ϼ[׿(il=S;=qL]gkG>ӷs |po8ohL.1Ug~O.=b0۾| _O~f>%K:ւeޞ~M÷yop}5~h3m_ó Վ>$g_OGptlZTƋ%h=nE_!{F8u}Ə7G/VN"߼SD2$hzwN>ƣ.hȗ'P?6l.W]KSRc t)'06'܁pHX@_+-=ǝ}g5IʚONd`iO4_Z)%S~hP"T3~g4]v}p JVPHˆnIUj+\=z_ؾ]ǞVͼs*ܕI,cN9$ W*9m|ˁc5ml n?lk&<u |YrMU28{TaDlm_+Jui~(8tkrN^`o%K6n:#6;DmAWE.'O?`C@BGK\K" ڼes]2 _|U][kd`O똀|ܭxvn0`q- ڴOBg>W=Z!Cm ݸsMѷٞ =T]-\۩;M ʞU`nEkk]p |$϶5U_ ^2-v`v@e_:zd|pOѸBA)V og *өvӍdI?+yڻkَ>t ]ly"-9 \3-MhݑY$ *0B,|ӟ]~?x sd >vKfw(J;O^UQLvou`A=.8C1>% `:]`]0q!_x!{p wz5)}Z>Z6SJ=~|Rg;ibel'6Ο;;| \qxOo\b7}?/Żuto3ZxgF/ؘz]?+]3xb$κ8Qq8xESxtP%#KP>$MD3l׊'q2]kn\$zPGIJ"_KZ9!4,}C_ G~䇽˷CXUڳ$=me3>۫.`>j(Sskk98n)h ϝO@S(>Å%'E>> @aq'-˩ ח{q-izgy//}#{r?y h8QMbw$!E*.66%hA9 7^O w!PZHUƽw/,a91;+˒{5,\?pui3Ʒ2F\sNʨuFǒ]bR)kcO 8Buz`j+}>wJL/Y>E/i%~#Ê.dhl 4?=yX_.#Yg^w;^qyŵro[7֚hs2!? b>|պv<o V "ˆgVP Bٷ#Y;uوF7adVsr2*(|\Uw['ZgT^h_R=]y8WU004eޮ CQד4Ps0zxw[.Ņs!&0%^9Z'7w=՜UkpZA^[έ#)ƞ-y ϞUpAp3f\'O7ZJww㍒yU-?/,GOzJoh*˵7d2rV[/8>ɴFÏɺWI_گδu&]r(dhYF~3tf&?8b}#'[˓(h }z3ϼ{O䏎_Ͽ T?}uCg;nӂK,aG 73dЀך #E 猪 |@6`w.KΘd>#mD;Jd TK軪H|c4#ʉ_=ŪiGMIaXpR2Be [8σ$`GL7sm<:!pOCs?*lW5+' 2V%03N->^`;>.QBH{&XJI o Z3(tuNU0V̙n ʂ*;>ű,G{kcK1.sxe6uJ>{JNN)ٱiTkcx Wu=f鉂!d^wgsW3Sپ7t<̛gmL'c<:[{3Qh`1Л8&e2.3kC^G;pa#>>G`ɜ=w.f_9tմ/?zwy'=#zӖ@O\G`7d_ӏ~=asFA JtԌ`;џȮxtO_-ˆuw(;G(]6X9 x ->4NC%5nt?[=}w%7ۯ0ɁH$ =xso(q@Y>n+\?9AHed .U 'UL>R#F/tv5.?%npmzy ̏Sb{V2kFo+W8ټYk://ݴfNx8z< kM&*#ͱNGw(]0qw'\g3;,G_$ChFwaS"MrP"ihA"ImlhdwlWrJ%Y 9| ty: ے?\q~O=Nv6+6:Fh!XOtc3w{UV#ɈdUsʅZE,h8˯F>]6p#uSX7z{Wf0{ٖm>^$uK&Gfd|⦮!Tɟ{fitVOF {$|l"~d|̓5nF4 d;ykvo XwtpmޏoK"v R'Gm 6čo<?jAx~/M(||&#G +}W6mMdIY^K+s.8>`|CÓuljl^+Zz~ysm[ACH}u(ohlHN!F"n}26ƒvx:Pc)|In{WWv6qh u*ħ~YkȄA炙C|HCU_:/*iWI x||k#w/K˗+u-huBJjo[#+qQ'J"U| vl9ܾ#8N.ϮCY`i*52lxunb?^a%F{qǃ(VUqCԼL<" IvZ9G-~kW]{Izpt9JTB-zpTrG>d{x2Y /zY _|-9=wa'B?wb D:"OB_$~f|qGW혣WU"ȇ@\ƛWNU.u C 茸QE$qroJrr)Ƿ.'8'w5ؾw)xړ ҙƦd3El(( t] F!D2I>n@Zw%)>f|ADqQj]-j}E09}ɧ8ѡS\}οu20cqW/?`$ֆ?Nz8=9Lȓ/{yO;:NX 7^ӧOgn[^s_h=ںoBlAr⥫mlljtء6(Eֺ.iMrrYwe&>EPA2Ŷ6(ަa¥ᕩZ֮"f!VIW`VešZF!@8awN;meGl 8oOA7B#6i_4m֪5R+!#3F5EF!VS&)B9DPﲖ2}6 j~|D$bbAGAi-O6_p^ȗ.u>YlOY8ܵ{kZզ˝;Ov=2bhkәxI )x?<Ýk\=L\`%c^6&ÀvI9V} 1j-7έpFۉ-OcQTjG:ˢqmgo =Yl}^pŌ\u=gQ;r=*MbkbrR<Ց0K!5ʀTc~#Fe@(Rvh~{؇[Adih&H&-acT1vP}K794w//Wn4:g;\6?x?~3TR,]+ڹ{y_Տtw \}˯7sIa GIPLfU{7۟]?oUaKs{~`885lzg?~|gag ª2$ wRcbV;~ڗ3:c?|ܕfxW23Hڹnѣu)Ue-){ IK?e ǫPw#3w,i$^.;ۗeLcE2' 12Uj1LwTmncV#ST҇OA=;^@'MS ~џ W?AJ6e8c}.8~t$]:RHpshMw8 6e68Y_9WƸy pI >'3%we5+@<];Ǔh̉պ0FiV~'negs&sn^[AMj q2z|~D|A}GFN0zVM*zةShߌ^#'R9;(1cm::O8rZyF"e ieƴteչs$BWIWZ>Ko?C 3\xi[6IXg9|Z%}Sr]tYP~( $gh$Dq!wu۠rPq=9}`g+O%XT`=ZEO%;|D ꈚm;+~ph_s4뙽鮜%k;|,eް?лSЇlhoz xn.7á0ox|'9B#:;{vs|fmuÍ&1lٝրķ­m[uIOILI>QjE;g?m,;Νrp0YuWj4gt9o:ˍt`EWiw֥G3'r7h#wy9^|E[s{3}Yu:~ U:Sg<ņKmhdrs)-Ӄ Zs 9,鵜9;]Y ŎؒȃH'S q/a[ =av7 q4<9v%O|# [yF"6wc7кW}VcV?E7?~jM>< ёFpU`Aa$, msNހ5OPe2xiѽ,g WMF|Ԛӳxx?  U{dTs/l-?f6rp"*M>w4ֻ=/ t$P}f6?K֧si{k> uފ;xtt+(?}3cbG-+/]tNoՍ_If/&m]n8({~,?lO~t .|{}v9lz*ۿ8JߡiۧR &>Gc1NJ'#d6b5m7qO8q._#l{l Itdt) %֜C=KaM(2rK🸋>RבO{蘝tĉppr+߰}g 8W̋|sX ݊V]NC%al;}Vr(Ko\\s]k;@"d.z?޾nu Q$pO׹#@7xӖ-:`W͆zpWϥ`$ػdU 7I69"uμoܼqGqDF{> n~ .E_|9ßE|&: q iA'-JU]8Xfk}O?w%+xx*#nx#Q3={ӄQ+?F~D]|wN~ӳ}kϏv3ӣi;[nܨzE`?,޴QR7?~̾gW)v58#F(N*n 7|o|}o-|wU7Gk̮HZW_,Ή=e`[i''Uiҁ#'?3\̧rfpi+ 3Nvpoοa~xL9ڃ#UN FA!ܔQB Aj|57A0@btjgN:mBH}89Le_F1K$&}J-*$,{P?3(y 4]5*͝ڟqLb|zkҊc8%a2+ c mUtS1aչdǴ(Vл`[EFaM+^n} ٓ[O & )K |lӈ<GƣVR*o=U0?L/JɄ U1ݚla 0]npi{x'9I L8Ix\`RZ$apN>\eIq.6-Q UpCo-H2`oZDkGO7)[.Տ  '9 JXQ%lz-E8ⶣ裞q k/a[nӪD_Q[_z{䓏~solywO~o/pYr=p}pvݿVv{2nxiҦ< #}iY.RƮ|t(D1FJ|h &̓j?o%>)!QOV6S<ص{8[/=yc"2PE:|~>rOt?J5锻E;nbxZ;Qy/;7 a*+9UGns@Co]݋fŀ?SϪjhGవ8 '۽;9]wCpf; 9ۄrNz.]ϦsKnS%$4fn𾣒t$s}]<x?Cֈ?l/?9OfϿ@^/oֵޱo_epn:/$8gY69̗V ,p/_}Uuus%ϯ\tw(?^p#љ[W(gu >nfG9Vӿ+sOytMyq47۵;;zKifN&:2ȣ6v q_XBk,=x:o|i?1iv˯d:+;CI#I \ k0aٷ{1h;|>3͗ϮŶ\?|gmJYfm5H+˗{T>0\=t>{Nud@mo\X~t gѾkZ/B+?v*fkG%'} +A7h|7 /t ڕ(87]Sb =CA}FwFv_tŷ:cGKsƻKG<ΧBLз/v&$}W>Ƿy::y3O>QIB֥3K" V>5'x(H9E.1nydG| pw1rve>OJx ˯~ݯ|^tv|?u(r?]BњZ,~=[n.>Ytdi556wh9Ók@֭¦!`wj`(@'8>]2Yb$QY$7J rDlxQ ן'xw;Yȭs3?볒/[g ཯z%s\$l|'kͽ̯.rq'PEd!GSY}Uo[qvj-[t$uW%Dтyړ:~wg=j_LB#2i ߪ}?q,{sd~SȾ]4c4otkWk]%3~dz_PG0^%y[U<fe ?|-(aN|HxJ>z c? 9O[<~=Tݾ%۷\2>®hIq 4M{PL5|ss$ܽur߻>lٷ-ḳKګ' m12^vo[GŭrWſϒF\go:qU.53[467_ţ'gFֈ5SD$eS|Xf_e fqn)VmnDkW >" xКg.xA wq_PnK`h's l)E-) sZ5NzLkמÝnU߉ fCcpm\lBKLl;YB/b`[O1⻝]BHXHDKVq}D~늡7ku^g֚]F˳*w8?O7,oT-lh7u=fQ6 E/N<>, ~Ńy8= E_+ߩfk;c -pKFCpn%&Aճ5ϲFo>ǔ  Q;%/ 7В=Ɖ <ϤVy VA+~ fm [o$?ј6+JPv4I{0~3xϺk ߝLϛ`is'AFA1ctY?`LGP5:a<~\zGАjǭ[d^|vmyB<yKܻ|7k*zZ/$0hh R.(743S%cߎ=e4Kʚ>TVGp0;C/uǑW.,/}G_= MbȀe:og4rG/|6sm49@^ el ^p#{"ޠ5؎h^Pxsbn = tPZia}[p$93 }TR`4gdp2*KfG_^eSu)a,u᳂رIpñhu [A2qU豞'e񷊦CvLYOUk,ɉz׌!W^9Ggss!*{=]goar{%djrm_s"1RsC@xρoςu{Ǚ·9XM}`iݳOLxrR0߇tSKVy,C?vF6Ys[/k~fjXώ]dj(D˶i|}#dZv+߹sC%Hk9~}3lҎ)1$ZǏ+ooF4/c%h`0;?ꟼ?miͿrͿD;JBF-Z;dq+C$2پ7_z%=<립g\-cx0z?&eɣWH# &AIX9m_:jQ0;--e2͏LuѪUxU?d@AUV%6c;W\#|[{=˒ ^txxUKRR:Dk~+#k{& xǣG1x=0o{G9o7i> mxP<8}w732~' {'hc3Zؤ`=_ub`b?tu$#InMѻ nGFOv<ȯ#n^gl{=3Uu;Z{}1сl_f'lFWl݇;YFg9-]3±.?Docv7xG/[ 6aّ$d w,{d(B)V|nSȚ @$w |{/˾D#bWIŋ |أ#58Gz4WrlֆFck8? sӷ?i|PenZ:;BQ&IpGW&/|Vz}]"1CO=U'DZ=ZKuU@7Lzz{аZt魪d0=+`1Q|*l^\\%!'Mex"Y|Kup|0xOt>J^@A=~֑-pgBFy+/_d[{>OIE.ck*.v3Tnl=gJ gc|`=RGhgou\"Zwd/ ]^,1;0s0g#gIMk;zր-o&KaCǦS<+PR(FwS~>{%}N:Qw#3<Kјf-j ;_~_G32E[xk;q'cΑxp?^7ۇ1$ uu w:Ҙ7/C|3AJ-e16$Pq#{ȇ[J76En;$5ţ'u!3pk#לC9hjKSpjZ VXΎq*~ C `!~7&v[y)nconYOJ޺~Ҳ]K$ ĹZp'yCӵCDzCTlI?|2ĸ;7"Tt{ &aP9JJ$ZxBtNi qch&Qyr^@iO*@)2eū[Q31d{;-sV'HO}ns@(?2cdW mu=M+b#ɝ@c6{zTr(vxB\A?65iy7meFҮX3F``r򙳯P6LSSc`@s_>?oD=熽S!޳::Z=2 .Ǎ=xD&ʹ y4W0YEgk,hFI t "BϊpP956C*VP -Iѭcxh#= {CGUY/G0ڦu2G^c}4|lAa%b ,Ce }zJ4W%&2q&/?׵Z\ϑ*;j?Qn$];k~o< 72^HփsnBSм^>[_Z3'kQ{ @췖ieT0ikǛ[z8N=U= O/\-n:@<+S.8hksϙP{?)h8?nqí;({DпQ;ppa|_/0~U8"гYMN#<W}6QG覄17~H{1ΏO;B* eح"U WS C) HM43=T=)&k%'H跊8FL-dèKf5r^OhfhشWw';~L,Ƃu?/wbEoͣxxBhJ«Wʎ7'Kʜo;X0i`=e[ ^ vxXş2);1 *Z7!};/Wpyh$JY L_`ftɎBF|xD߾>ۡx*<|x[p$[pmNhy&z$vrN7 =CjLk[@y<D˾ˡ'F'?' x ?eu#PS0x?( ]ycm-?D1^4%<9 9N &Y< mQ7ܛjRIbG538\pĽmOHTӁ=]ϖ&[왖 HsІ+ڵ# #> uk[/h|?8c6C8#8 /r Ult`Wm:zP:-/XH8=_E3` a0Ѳ;`ed0_χ - ǼT=ypl)/֮^4I}_tz,\L-\ZTwr:q7YZQ/XӮ# qz. fdخt39p]NrfcxaD}Bk^=/b]Ӂ4xMW fAkPa\K-)$ul8銄&tR._njsO= ֪B:.hoϖt踭[o updtKN&>> g?"'m[p/']/8?x@nsGМW=FoUQ챻uk mpz{_L@IDATÞF| B.0ǯx@vd5kLycTz؝[X%4xrUs:< _WA&u*zV JNymF> kmcWCd˷7c p߁ g-y.`Lo+PCN0k4)AS*ӯ^YhgkfnSXbI$[tgE v~d~iO_OzodƑכ g믿5 .7':>0HA/-dz+yյu-~5]&G 9Vl*+r|+Gk[SOq=(!wkW^9A7>$n_.m芤?w;Ӈⓟi/T +~(+ع?Y*88^~t,.'u⧝\߄0…e [뺈O ]Cj OϞLNOQN2I'vh{[hvW=ƦYMZ!M'ux]O9~.gݷaf9KgϜ&WUzF"aXT1F,K*Bx![@8~huLݛ-V感zD1uLN9Zg%Vt_6mIP$Ս3uus=H8w>[]Lᬸʵ2ֽo]b?yOG-|S[If гx t v4#e~eI 7z3ߟIZ~x'~zU СV ~_$"hm%;_F xX(?/$HHّw׋z#.^E$`9Zv@Ntp}Rܳ>yM M"6lJY8$JA9hesV *#nx>գ: |uQxn< UlC*@9iS]_BՎka*6{%sPYo'G y㖭NXۉ1(s%c˦ĺ ][[H0;AcOH`ra 43 P "{%@b3 ID+efjCdh=2 b n(8ZrR)O(a(;g9{* Q%F1NIqv*>USP5&ūLyxy$7I01#X eh5?F7?sc7,(4`HȯJw6 . :|isÝ_XffzЄF娛j-дJY+c#M#DЏ8nz?JYq6ﭪU(%ag_fj% g_\vT8P0lk]!6:r 8y=^[̂ 95ji3ikcj3_.|o,LgABρ{^-[1vf&޳*mo8<=Z8q4XXem엔"3!.FX =o.J 8}8y%8]ڵ)#ڶob( rN_(p4e ; o%";»>?B h_Suh1$ `Hf߭KP#1Ή8~$-&eCo@y3@/.kt-gc2C9ws*evϞ fKϚ=_ 4(GMF>^B t{UE~ D>WEUkvȍ>] u{:aJ3!>A& /=#9G(,m6v&{c d1'5D%Uu29Y7۶)ΝPd\.f}-d07*q`cnfrDvԁFET,NPXyRv)H5 !%g PmF QMLwG  /?𲞦\K~.: o}eZg_?[^KUߝ0ٶ|_J|;˻pa_7}7+ vK \mxgK4q"qa V?*7?xfǎT yZ^zcZoOG ډE:[sl>ًh/856O[ã;Nd+)nMMX܉foZi]]A)7K_:fk 1+h r @35ҏ$G6 Oܙc%tycwujIs֎Q%`Afy>q鄏/B+r#22k{0,{Ys' Jmfrn<팸-'E?d#yyJ‘#K5pr3GPڧJ\JśK c4-A'IY9/08o-N 4>XճcE L\z_8YJ?ƃɂgSnb ?[mթDA[Siα/k[0dFәpt0_+hzۺ֗4|=w&[r+':+'`Se wВ2m u'as6^BWh1 6祹Zzά&}Ozacpdhsv8,u)oZ{J_l#ѻ#ʚ(s^NV9kL<h0.lj y`y]βrLY2U%֒Z+OlڵfKyߩXY. [[v<j~x$÷9pL=3k;pgHdUvkl/Y̢Z?\7>>vرttkvEíI Hp$$ӹ$ eOZOk|toӜSpHh|ͱ|bv4HI*uxү6x-}ߝ8--0dH;(pX=J]{翕n׿.;+,צ[8-/Soo{;yq yo1/׿&FK =<򷽦3a̯Fgk#ȸ(zZw#^3 ~VٳC@~x= rVzӎ`0'zV<&Gj^֊G{9j9,Od'N6&-IaZ)F8Mq{OT6Nb$F莡Q.׬乍׵==fK-Ig˓xN$8MF>vB#x7کCp:\/l˥l݇eCX}]ы| '1^\]y}_E\'TZb?ۯ]\j:x1zصG_˗S T BŶ(fzCnhL~r ޓ-KߑO,#:@6tK͍tޕOxų| Y#l< (t!t3L:ur Yu~#&_FW"/2\$pg`x: kn~OyVu =|m5dGkE 7#Z f+DԺ@ZBST6|rrp4T&z2T@7~xO7kyR?gI&G|3^:ա;g@' d|M=<}XQvA 6Q}/qsWa ju3yp/Lk! wf{=j=|g4i кKIZ}P+g$V㔴?X~ֽuvV񮍊Кީ*}}pMxxL08m_,F {V.et xFl86rtdxPĵVÉ{~IKj<Ҹw~rsAzb hMbp@8zpX0*s3y@4/6jxc nOIW]s]_$԰0Ɔ8Б r زpy^鵛; I dsp^k{sCg <|ILnmBO&;gw6vun\ٓLu%֣Gzk$ɹscKd=F cXUIJ8{ iKX>/> IYsf{S`"AU]";!`M`KNHƷl%xON)bip{+O>WTh٭gX^$DNP'N(h9bIV~m8wnUe'N:}tf_ܫxK/Cyy*{g,N%w}:oJ# '6v``[ ]';Z g[OmM.kI*!ؙ{Dõ:yp9?߹kO Un)L1= ~|pЁ5& @;\~$NQa}p6wXQ<E 8I9M%>kW $\K"=U8,ЕtaR}yg>9~\t{A0<|m[L|8Zª>Wq|olCkPa=&m1kyq0ݳvHr g`n'x!R:#*<n+R"J J?5Yvk)$2yH~,##ȅ"t[\)0 X|kw/+>MNN4J3 B>e=˹B%xy3)sX9! TN-C qHDŽK K1`b{crΝS/"^ ͜=a7Ƽt7Hh i/$pS/(o,N==1(dth1 lGS=;$fN5IG %QlWw!$5)82 oL cgPL$1Bc"y *}&xLE[[(v!7HyeF7`U(1煮OVWRȧ m[ܙ?HX4C$8*q8!fMh Q*"8t $Kk֬) 8$h h)Y/zhHih;CҏJ.wDK CU8$ T20Yx!܄2O'&4Zpo3{ 9m zqڸWv2&axb5|KrO@XLa #`{Ɵ4YʨO)0Ho~e,tEGue: ;68cwSU8{gMo\=ixw_<ٞ!2#woG k5GC;#06^>9gZI3td/olѷǎͶ{DÛ~vW=a[r9^:A`[g [ :l1~ztjY}|~ ? t%{o61Ѩ#{hq.fpͮ9١>S~US+qݷFv^rcw׿6_+_Z\%?7 f"m ~]iz>4{rNoSwXU¡~K/d p?${h/[z=D;M5I=+6< gKjE=>sǟ^X~__zk[˝ 8+^X2[&> Sz2c $nl޹npy//NhNbIΕkw^{,}d[t~7v J8ݽэ峫dCt9I2=Fpzd[K7s}`I'ז ~•WI|ѹ嗾Wmb?z-1?!['뾀0[晧g?\Iӛo_jƧ?xGx勗m%,U0/ uϜ\n=+h.||IbQh΀htptUg\~ʧ[b*o[7 ֫|lw'0WK}NGLc\vgQC[_{syxuIٖ 2yu6F@k_>tΥy|+n,,_ysx| 6?ĵݑ%k]gOWzk5_\λutWu'i O?Z@E"oCػx':6ÖdWpKdT:Dۙxo t!vj6A:0}8t> k\N7: #{L)a*cqO[;?͏g*Y(ԽMObLpеۻoc.<~HsݳywzvWֲ]YgP߳#A:x3yiswwGWCb*W\ήGn:lY5 g)]_c?kJ'ڈCg];j ~UE9pl:7X_BlvWϪU>Ic$gN6:|@?@֞rl.IQbR NaJIƏ^BW 97v*rS&%;xEo+}g9 ڰIWgႮ/^;Yy:Sg5o~z&"a11Cu3}X*ݻ!yj["I2dE#U󱀹X r r SUV:6hll{~v?0t+nM|Lx޹jl  ck^x~xDk|L۷EǏN-h]_cOL`znvP1PU0(OߓWH9Uyt$`v';a }ܹǩn`/h/M(?Ml=xt|fm󎦂HŰZ}&Y+Mst+< o%t5 :ݕ^Un䞷΍sB1y:R21q4A;;\ \h F>6@҇aJVz ]%o+ur{hg'|Z6HsׁB@ym8樹ه5DtVÞ64D(i-H M?7ረ zEM&@F)&pӝG&S:wV+qPe #3v.d5P `j%P 0D 1(Y9WE }|$u$g- ' k#[FPǁ7=IInWak/)Ap&`d/dqXN}uy7?ҹ܇-)\, f|ٿK~2)"e0'~e54)q s &/isq|JLZ`s#/s`^ps]yAЅwko+§xQϬ <ֵ'C!|g|5~lh\YpT7vq/`#iQT}^*t̸:{H8T Qe|O^,g^r̳#!ck0Gq-R@bN: mQ]e2!ZO 1ēe,H\NF*m]qa!;Fᆿ71pUʜ`,KʭlzD=q R 6K:i1Roxo;q" Kr=sF]"yqqx_^8wtÏ?>|=\UoYpj#ye:8tY@;A6Ad`7͜_+ >&xسmJN =zښ$4ҍn {h t]N %]jm#ģ׮xHwqaH1zr畄w{=HY$%C$)޾ aC5.>={&>$3^.+A ܓw3o^Ȕr6;snN-xWkx&Jn@-idϽ^G˅ ?&XA5>mI_pv8Za9X{O@ym oWt`휢qt.A={Φ78lnLs9$7i<27_d}lpu$g^C 9!trp5o_[ |}YRҽ>lsLL߁Z֡bl=MX]9K2/a5 .XDJIX/j{&+I-ve9=$mkm8:({I-gڂ5^%hx.9w~+o~n+9  ȾƞK3f0qV;ꋎ?g_ UG m0kU6ׯ\Mcpf]ogcɼ6odzp`Ý5*V}inN+Vƍ]W=lh{??8n_n?#!H>ռ]泫}8:A›vZuvTЊʖl!,w؅~f3^`9VaNһ{xWcyF2׃)2Z5 'gǟ]^-{7˥,!DO7w]|}6<҈Ӿ=,vOKiIZ`i=vW1~/+η~d?k`5 GŜgKB*a(rTE~;Gt\sZwjs|#->lyX{F 3&W-I5c*lBtMBͮ4+.,~b5N1A`n5d X 8KU(kkjX?;2ؓWk_ [ٕ[6= .ln1_gWy%=]\9-W^-zFE,;,.:RSv)ڝo,K l^t1;w^Tx/&gGp k"]4{۵ pSv-}Kƺ fxof͇mEffQPJvCm4Cp.+ܛ^ml7^H/g5C>ȆU?ڨVp{*3U3?/]Z% ml }@R'1e0kא 3ȩ`Jv*qw4X^y:I:_.:e@}ENh*J'V\7*^%4>.0$90HxT?ڏ"#~GR m:V*<5x ~9:Wp tFu^D3;u#?/OҵT; O zhOd;wkIWz)Op:7:5' kl,hK>6 ļ:Oc|.U{6W]̊YT'cO7._Ml!.?#Ű]Hc_|J/vߕ+ςl9g ]:t٣w;, Y0eb.p~x5vo9PVa6r OnI9jcG.nfC+k7 ŔT:$Qw>Q,{?|3tm;[LW*:/>t=u۵56 ?lx;c\ WH`ט/o:θ!}s{/qp|m8\ EV\wBa;v xyCYb.wgbeֹج9FIwvۃͮu#}dz XP[s^4-?p|k_{},쭃c{'t5?Uan(elM  #Bk QNCB`JDWH_ W/|g0b;_V?Wo!g k_lL9l3e`"@@xs̫Ϳv G,%#y%-ya`S|鎰w7& wgc%`/-jvp4[٘%ng}bS-ښ PBٙ*[B ^9TC0lsNXrUshʸ!0iprR)ݰ=^٘:d9?O(|8jvM[pPb *)}z:/jߑ[e (o!W۝[e3 !rK_\sS ZW8<#ž[4lmq\׵q|9xgdW:9x6;͘H <ٌ'Uyx(S lo=9b?qyj(Zs;o $pP= )7j-dﴣRIjG߾-5g3"QΜ酶n\8qr kΰ{g/ SOܸzS'GM$ign׉S/-eI'˷ߨRt`XKWkdv9tg9*kwHF΁q2@0lM9 F0F!(pC:p,sFo9{Oe ?g֘5'f @ߺq1Q ~r GYpݐA }rW/mmDtFhd(~|q$Ȫfhɼ;k`<>73,-JnCwuWygvwaa ؒ%e[XKO[08`  ;f'LOtsy5BbaTW{|TeD>3d/|N5XA /G`eMm* { (aHZt1t9:l3nnj zWAI~3 T<κmb#8U@g93@T>ʿ;W_ w.gMڑ!C<# ^]%3 +uD9 drB%I]1_K<]9d>cps6g<6Jd-H:w' ?cSuKvL3u|+MPa!9q&0@A ~!t*g}$*=38#僚#ụ9^~3 hqP.F q.=l#v6ߕQ3'ȷkW{BpԍN<]8&1r78+xmeFO;-,js;utiQ2a?ѫ r&?9\QGt?z Wx#,%z?yȡ~>v0i_u6B\Pghik#jUpĦ"p]%#NKOu+a ] x>S<9_aCy@xN91uڋK jy*@IDATڇuL%^acN:؃2*tNh58c{[Aʺx$C4ЩKZѡ Ȳüa,wQ}}Z '*mmB px7K,FvKw]&.[] nzډGȳ[;g,tfevj<\TNMNљz>e#XVƤiPbu2ʻ?5#* WS̪·CȈk:鳤39iD+j0bW6&i]pbSw8<ؽgc\\OWWtf{TJC 񠭫TU ALfwx{o!dd-;0wM~7Sku:0=3?+{f:]?⒬A93YqNLeL "ݍTM9U ]d <8lGD8= ZsOV$VYݻIˍi t4ɱxUFf~<u|t:Z_y6]w?kt=#QL=-v8Jcia ~|T7^ 6PsMuu;iysV]#8yly|}R'Q38_R'#@>2nĆ}tkd1VZ{T6ǀ͑:I?p+ekR/gVS4buw g' >"@#PV:yz>TKM[$΀}"3)$  x3$ ޻AU#k)g[Y!lYcqSۄ&Qo%|qw#SX`&oWy->P\ TZitv<0un g d~&R>Q|6OGn#? CIg-aj{GT(8e.o]s/]zV"ȔY:u 9γ6;PT6nXS+tNg&'6~@lv5 Oy Scvt$J&lw,r'Bs̗H|Nl,e3.ԐWG߾W{eRteJvIN&[LOG!=]t5WT7Lܩ9~6'X :੅ƏPJ Ks'8qLzJMblftxm/ i䈎+HcW6P!'y+MV֛£8G<A0Rృd'?A&f9 kTzY3 iDxEG[Z1.oG]iPhetfgߌZ*R*m%=)c`^0RuØBoB(_["X<@z a9αL0{o)rE93YRjFY@&Og]Z'6 ,VVp$V +s g3Y ?S>z]N^z@*f huF3fvVdA\QT:#Y!*q̄| Cpt.NM7!LO !Q9f:K1%T3pq<<_fJ( IXH/ 6UܥکWsZxP ۞veghVitUNah >I܀t2N_F21Lۘ.*"_"S¹ML9'/nY|k%PhG5hn}Ow[ ʺ*i320>x9fXEP1 6iW rrb,]LSS88 :U803KTeK ; qH5(Tg]lʘgE U+4n2suD6S-?SS/)h<@3ADfL =\X<< ,QqLlY*(-{`s6ÅK F ˃U8‰tTrm9yLY 5+_:m9(PS*Hu0?;\"| G s"ƨyVL˃va@{KW=umѣA9GXFO;QD!(m f9E>|63UU27XKSCIO?̛C#'瓵W[yy?m0aBx8xv^T8zZ'6gm $m:Uq<"x&~X`셰71Ezj q6+$ OV5qLL$PO5J{u_YNk ?_a(G.}\P\mbt:YwMpw :]֞%^WSdݶ~?<ZiV3QO\'A6eaNMr!vG%p:xy$vu3W#C Tq)]8+'_vO9= X-o]k=6cqL\sCC> f=gS'UcUș<׫˽v!{OogfSaK950}wiBqn_4xwi cmp#Ftuu1Fx: `-Ax_O~& ҃ ~(s;"Yn*K:Qgz[㩳Zh)xY!q_}G6/Ԯ\xjNǕin}Ov>5B[9}t!8GLeRЈyd e}m$dVcG/a@YdeQdEu@|)؃G3$p&qC`+O9c& &~aSnm]hF>ݩrt2F)X>u3_||g=ux04I`j\70JgLQLwb&M4z*A{{$q)}^fgRmm5:qJDV%J~gGP|RosߖP2A_B60x.="I|k57e&&9~#7d^:rU=\u_+#6$2 kw捍 =uF /@X{155u &0N?]6C:i //s6LOhB-嵏=,_>y:%Kv[=}b9(~S&pѦR&3Ԑq&,KZ@{{clb+5Y 6 qBcE: ,~vts fHȎ= Ekwh7v؉oB H I@zVXtƼ sYxzo0N$]@{cMM t56m3M(s 'vď +`l)3a٠p!=sߗȋ nBtxbr^ؖ.'1$IGb++oLbo~mυ;dtqW[CG%:ǼT (k[^ 8ǚ[ۣc5ExdVZ֟},N٥KkSmյt;K̃2]ULn v Me#R 6ULj2'\Ħ& ɞlƥƤ ffm` c6Cy0ϓ p7DA$6Wjmy ~p /& g3({`PI Q=Vv"{q/m2 a#@ 2Qߋ2}+{d;b<=f\-meTwH:p}V gkSOR˩g cdsg' 2^}>#T9dgWOh:WetoL{Nʣ I0KFJOuVaG?V?F TCSA* 3biZ%pSߝ~8bG ΰOƙ@W 聏vzp*ohSqP =p;Li.-̅Pcl=<ǩK"w.΄F01 lr13l*vɊzѕe-ߊ.{;[a4R"y TAV,>y#{?]J^8QpTE\LzQɑx fZE, \ /.˿(%0 5 GbʹY9@g[j|r>Z#ڜyoI/WƉI;:F$IRݻY&a; `,h4TleѶ,Ʋ%>(#VŒ[V mF@v<Ҭ6 s2@Z[wa;Zxr?^2c^q,e * ƘZc 8i;rF^+Q!s7X}p t?V4f~KX`^=&h+ 8bYh:wU9$~-t°)WKb=d}+vR ]!0;("M2/ Gx\NˋkWK EZgE{R`(ɲIFbMޯB>Mu.|_Z!õ(*ed0楋=& iSAC)vf$V {d,!6"kՒNϕhF, \$/8jjz%p޽[^ThNO$ĴsO( 驗>_]_1 565'&J3M#@;,C; }腏ylU9ge@i8@Y{~<ఁcrXK Œuh\S1~l"c*ct"'@ڨh#3<' u [ 据$ 3,m=iE)2)d2xH f{uVߢX9c= M=} GQ WP]"}j 4bw|(^lbr$:Q/u֮#Zg : =ҿ5d[kuyx*SRxb/u|D%`+x2pG580 @O,3 ]{hksL0{:t\uL*/X|DRmν6L!x<ϬM^\LT_4 }9TDh;2RKJStҞA^Sݗ]'qґu]|<煡tL8X/nׇ\Oq)Ia`-K,#I{6|uA^D'Te.yu Tc#H,Q'p`84 NyL{]g%4,=Y9Cs1х|?[ƦAR8=qd}B $8]p^Z6R=V:ia3_'3%p=BG ƄU0ToQ&gg9N#h?3܏-`7g^I#.C$-qE& ߡM =Kv$TQE42|uO:SY&xpa 1tGg:d^uk+ԎH,Tf{Ԣ`^[_Wῖf%,M}wl}𳳿Η{ VØp}LͧXagb~3*e|  hkҽ-1IK _qDcc?ŕؔdLM[FؔIuTjLGRJ$PVE}m=OOqS؃=A%w:R$祏QT|MA8 ?"IXA>Bߓ E?]-< 6757<ƮTB0ڈIbk}SjlVѓN8 : g-/\Ư4EW,Y`YSH( -P.[ZjU]Fz#yNv]Am8v:OM 9 !~[͛WPMIݤ}++R@D~zCV_L?l|%g'rznً|4!HMs~=&tjCO÷'$ק?H>d3Fghw:xέvp6o~9~*;רo2pv3QZoܴ;mdVso6We⦅v(>VQY[C6~[QYowv)sߌ0mpcڱqHH&~g ~C׻m(F7s j C/_ yXL i Ft>~IQoz NAy dV1m3$a,WfP0YY<8n}>'.ylEjӗ`7:=G$ {~cjh}nkkX[N)+Xmuo{sMX",n3Bτ kqL^$77cG-_Q|dǐլS?c:(7)[Sk[GaS|gB!l1e\ceqX$eS&er"q1⭵<4Mo:B-V=ɧOr5&4 @7iޜj9u};$P|sf.CQ$QċygJ%V_0TϞ1@|Uq62GXx$[%z< .O41]09OLĖM2MMaW015j)̜ B,?z2%t.}է_0.Fwњ1p: 'ACQ],f xlyhEE,T  met0˸,*5whN0ol&W̟aj[-^\;UU=+{AVs 9w۠ 3$lB' bfOxpgu|,oGo0 KoFd9?z0]r-CyN0vjڪbJ*?3f/_M$X0CD?Os'+1&F)O}/tZMj`W**V;:2s,LY&`=΃9CZ`_M0Y~8PUn<'Ո 4ҖĀ6\e5#Le-0=((')!dy4,C1 1x{v *&m8,! j 5\٘&w-a>: :G$x߹7VQl˝|rp͔Ԉ. kqx:jƗʶ WjlQf30nYm0sD5@ZF<|Z ` v^ !`͜wh~8ΡmojdwuuqNdЧ ]d:PzOd x GG@1; < vrVᙶ6p'1952GxȷUI:f +=-5t xs6h5I& X; g(n'KY[80h+ lVQZ'] 琣`t}fX7ϷV:M}n:Tuv l{榐m0Y@Cx_N$Wc)3|١ʹ*K5uJѱ.ty<$n. sP$/l!ߜc qXǗIe8MJQ%@mc+WnWP%LKXoeY:|/a(/QGtb41 e"l7aGjiWYxTӆ=4Swk&tپ G3pϛ_ζ+6a:k@y=\~HJ+y JS$`++wk D1&^q<-1{|}I iG6հ'7iH#%Y2C.-C ƊJ6X|sPdb![\4a|z::.|P{>Q{k*kb1:usB/oGOgU{@H<[cp\npaDW@ ~ 2Iq~44tuKC6婍$p x§b'%U|\ԁ"\4fxIYywBOʓnZ]rlr0GՈ btMi[!'Do.*`? Ҷ^MvwxNX&FW^KG,~1ݾ>znsР|7'{C:/gSq3ϕHgD}'&.VKԿc\+UD|bR,؎K-=WRJ:"P_Vnfk~FwHJJ] 4ʒlK-M/q]*+Raiu&35[QbRNfq_;1GiKw L'Mh(+p( l} jחHU=A:P&|K<߿GQcW "YC\ )p|θ_]'1?z"jۡ}r;=ޤ'gl ZSUDo`ڭ*hQˊh ]C_>,$PwR;+ڴU.Y|:9Up =VL2vfRmpAjH>l[m;Ԡ.9>mnt^jw-;xQwSL%?H]FxGQZl;zSVwRY]^L8{ɦiׅ/G}=r!{X2ꚚbͬJx=obj6#0xD[}^͢ <*shLw_S"!x5vN}ث~p[d!N;%,;C#J )QאkSVr&E1E}AtgKN( nm@CSKY\9!Ch߲|m[H.] O~Uwv pz/Lws.sjr-NC#O75`gd/Jp Od{; ۂ0 I& 3S 2`3Hnnd-:BsVtV7TXc.ζf>5VlS/%bk36Fc錸z/=ETG=x!3[+8q^:2~a9tJDG+("S9P7k@W/DƖ[E=G#ڲV˧NL:xcw4S%@–bjF,AǧDe% ct,φ=GA2 cy!gb/*؄FMt"aUfdQf(tih٠gdtݯ8XBp^JPyx^oCVH*1qJeJ!3upGr3g|FJ(W̙r-U(~[I (UBpȸ H**]izfR0u⚊<b`qDSQSG!/N5ȺWQUz+Äd@QY' I@iK~qn[-nXe#O89/$D5ȟf胷y;qO(KІ $ h6,O[m=e8 |a-Ƌ5l<2w/1=.#ӷaHCH`F5a󹴲hE.svtx>G9̚WcާTv61kUqNe&m ue9'L)V'c.F\C\Ӂe{8|脰4t? ؂KgN㮾nġ$tW/: TԐ3Q5oXjrg*|L2͎- sYFvYc\}$5o<EL8@ Hfwyenj lG੼Q6 _t( iF~A;:5 ;VVCN2"Msyeؼc "@aB h)fLctJv$) M'C˱E $D׳Uc( PI<$Uyr>`.lYinj[l@0qτC`k`+XAWb#V k$ßqmߧ,0v׬"\^ Dp@ŀ+pjR{&|lqh`:_lpoec昷zHˀ0iSk')"C*>:ȭzWK3Ki@_ 0;!q{FA>O?|x7}|&2!5K@:VvTW z|8yq\עK԰@]\L8Z*L6ah)uH0pQ.._Y7D7}|7?ߗZVM"쫿J* 6p.+u_Mya;* $'Iot>:28hͯ}9;:;']Р=q!?vEe}81N 5kT;@;t]HV@fɋKHFR6{ʷ$\s8ۡy2SoW@&Wֲfh2v|!/mmիOoIp|u@nj$S3yD싏pxLԒ#]{YAg]C+40 9&}fMlbOK5x‡(0V$*Ƭ';vy@w녳kR{TUP]1{2lCmO m<`:|Sӓill4lae93fE5l?AӗcܕQ^} sOg)%}o.xkmިCԀGGÎSiV^476 efhYYV0ܹϗqx|ts}{9=I<338b o;*B`"!c'^Z$,풙Z[4mGx_(G"4V@Q_Wbb1DЃ]3bxd_5LHg$SyvI4e nrj*M;tG{˸ !\,siyeNB?Li#ҋ˝};NtWynVq}+ly c 1ng'&LO7/XĶ7G+c(`nr&.lI*p'2G*3iV)M7Ҧ=:RoM [|@ Ս^: Y&˛ V-L /CQ7vdyp@[DI8Vt}ZŅ01S~f^6+(l=\K+t]OɊ`yWX+k;OP]}#v;FWOw$y7aaK\]x:EG~*mmNo_OٹK<яX& vΔ7IAUfzr(xh5kM~x0*2r5&p٧TfITVc 79⬏=b3=iV9r|Jb ӳ>̥Y*ũjmYCVuFUGӋ !W46I8/Velp NfR&9g:*$&VF&"om"dRk6ʙ G`ͶB򔀌s2`6ٙY /P՝1N ȴED3HBEm:6 h"#SiԷu(eg׫ܪH^LeC&UT(v- 2+(,8}8wG ;kNkG{#@vCԅGdiX!AB2Sr퉂B0`O P9=03V*(O,pgĪc2*u[Kg8sAF\jaDV0ᛱbfQm{s @bīPY*S9E\+U$pfBzV $>s[9AhQ^ ,d*۩Du)8. Ec5  h/hDRAQ9/ R՞cWy6s)z^ԫdigG4;ɱ{)/E \dX5 ]5 z1hpyP]`հdAΑE9[{OdŕI7^^gaIls3 x|;( s%F!A h\'dUF  8J`!SA9T|Ii"2<^(OPH70($<}:x i9ol灋G' h+jlEV'SEǶV?Qn9pd:mpqLI qT>t<{F ;_$?*f/-Y>9kkO4Q du(?g&5sW%~, U58  Y* VԷ:]5:`l2]x*oJq% cF`\:@!pR>>, Т84 }=ͼɜF voo#N q8Ed͍-z# );^uF _PD7=o=3,߼\71Yp:T iDE oBuBְom`j!s =5 |zOQYIÐ%HJ??^:MN8Z x>Wnx*p1oV5& s߅T셹rFG={֜C1>5&~2&[3 ӎq룴15t䥎檱>,g/nu2*twGOkY*ONOcHM39ЦάGKVVtuw'/ԋFSz.z'jci`TС*i2s\wT Dԣè zBɜ"Ng Ex]8+cɳɪ^&37Vtp^:\ aP*VJ6+ .Qf1A. eO.… Νq|j dr*ʺHa h'ßǦB7 ʼ r3Z{Hs)8S/^lEO@ % øY2z\wq"62ld0C{V$9H\w\,hEg:iL61g"tW{i噇[BيusLG_7u7:k:hCcn E*iY9|U85A~9?d/-=8nKt.rT)vgZQi^߅aj6% xy}5yu&WUF}Rg$[hzo+m#?wla+d[GyrK$8׵0>yЅ`yoCb7g,^&<50LHⅼCކ [ߍϔ3yOPA!qx}>7_3dMBZ;#c|YޤGg ?)W1&K٩.,(.dOzZh7<-Y7x>ue*w^"U3:g[o7haPI; a[ol"DzL,){Vd^YaXɄ˳ PuVS6JȭH>[.e-bec[2֠? :/8o~ Sd$ӽVVeVQt)7NuYzy0k"c~ܭVY g)bHtzLhSt_w@7g<ڠXib["Hlu>G巕͝$MNN$\@_c=*Nrڅ_0Jۚy|OA|o= u}$H |CO u̠=[zq2Q:x<8ǥtp$oM.601)-.Ln )a!CNG-vϰ#:݇k6>a= %1U6a|0fN , ~G`<#O{C:3)40_R҂}orDM[=#`?0%%)iqq1wu*ZHvMe4 \eGyT:-%>{i~nF|vXn[UU<8x+g1ձL(6SӜ'ͧ>"+<ZT;T PWƭE C3 T2BuCOd$ko7mpSoc$TgEz(J<_Yy Od5T4B_|64-dPοڴ:(2 r0 BS%ȱL }"sxx'}~VȜӁ0CpHX]=%v9-$,מz>I-T7Xia~8R5-ԞG\gim2v 37c404pE:Ǔ`'xWkFPu@0o=}iA==6A>a.޹Y89`Fws844ZEP1BfԼG&0V4+spV {.2Nxϓ7sP&#78+pfgUxmuMq6 衞KhTwx)kL u{rD,(HG`V%mx[{Q"ٝ! ۝ 0t5&Rd|-bshkjQ*`b*(D Z =*'}tKJa"LldBԃ]]AcFc Dtr+i{fx/j)ԊF|3IW~Zh3ЍCLE>&BВTƧ EK#H!/1"J&L:  c*_!Ptύ@%u}+CAYAYY53eEPLOx`eYXn4!X<lT;ltp`PE> ]gT,483A1dmH "?*aQFHb:LqEC[\NٓůԬAeΞWH3:tUW "St,h ¡/8rOmVU6mFj'[7( v& |dsTX.Naqv\Ȗ[<" to|uc>4 L0Bf S r"8 'JbȎ]pD ' i Th``͚EG<#DY^jqAx#Op%*by(#O\֐ɖ OhAʆY%$>>u616>_ixȧ"3o~ji2L+0?3Qpsiʲy'R?\ԩcv/$|t}ՇU|9[r )Yȴ QG$` r~j TY鋿+ Mu#]y[_#3; t+CY DƳX^!; XnWpDQՃ&y(ͪ,pD+RoO:gbC?c"H# $O1|hu~kkVӍfAl;g|UwʆEa2aҁuo˺ uofIPCalj&S)nLئ&'3Vw!}w2tp0FT7KX˯`gؚ:M?>sؙ[AƇ7Kx]/?dzڳS30H'bvEEby3Gݷ)Һ '{ 3UfOH|PIC2OSϐ3eMDKpG|poMeGa*Y%' +Z r|m(iߗj_GL+)յ~<'ܡ׾dh H#9h8k*'9>3yW#,Noedy,>l3[=!3>n ]R#kE'ܗ,8b# mq1f= 4o9hVx?.B q=YI$822k\;묔m=|E%3M)0;7I<߈:xsge~&xe=CgPe; 3ͺO%,`1nv{ ^cU4> &+BZZ eq%m07\&Z쭟f|iWzᇿMr1M?DKe\&o;:-i\~M?woƮvV~DǾ:\2T <2tLZ>ZvDw%.TQOh/'Xϴ 2=\pF=4\7 {.\LQWt,чtE~g:_ 3MRڗN=joigv8ac4RVZ^n^jR١ǙI)CsއRI:쳕J]E* &xfĀs[#7?$k:q5!%>(kd$nÎC+)(kt-}b]-4u`wr)^.j==b y[!$-umlt<}vz;FM&Hd#@!A $I?0 ð GVlZHS,;ޑwٝ{0D|GKާ|ooZ$^-FK+̢1olUJ{yOOoϷk%P@J_2#Kwjsw-'՗>m9XÙ2vfőv߀´IA5ЭWln0 ߵ}Оv؏sZ.%NJJ_C9:2&9ދxTwݠpm݊ϡWEK,(!\K؎| |[