diff --git a/.dvc/.gitignore b/.dvc/.gitignore deleted file mode 100644 index 528f30c..0000000 --- a/.dvc/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/config.local -/tmp -/cache diff --git a/.dvc/config b/.dvc/config deleted file mode 100644 index e69de29..0000000 diff --git a/.dvcignore b/.dvcignore deleted file mode 100644 index 5197305..0000000 --- a/.dvcignore +++ /dev/null @@ -1,3 +0,0 @@ -# Add patterns of files dvc should ignore, which could improve -# the performance. Learn more at -# https://dvc.org/doc/user-guide/dvcignore diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b4d5298 --- /dev/null +++ b/.env.example @@ -0,0 +1,19 @@ +# AWS S3 Credentials +AWS_ACCESS_KEY_ID=your_access_key +AWS_SECRET_ACCESS_KEY=your_secret_key +AWS_ENDPOINT_URL=https://storage.yandexcloud.net +AWS_BUCKET_NAME=your_bucket_name + +# Database +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_DB=building_detector + +# Geocoders +YANDEX_GEOCODER_API_KEY=your_yandex_api_key +GOOGLE_GEOCODER_API_KEY=your_google_api_key + +# Celery +CELERY_WORKER_CONCURRENCY=4 +REDIS_URL=redis://localhost:6379/0 +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/building_detector diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9a28592 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,94 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[dev] + + - name: Run linters + run: | + # Run black to check code formatting + black --check . + + # Run isort to check import sorting + isort --check-only . + + # Run ruff for additional linting + ruff check . + + # Run flake8 for additional style checks + flake8 . + + test: + runs-on: ubuntu-latest + needs: lint + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[dev] + + - name: Run tests + run: | + pytest tests/ -v + + - name: Run coverage report + run: | + pytest tests/ --cov=src --cov-report=xml + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + + build: + runs-on: ubuntu-latest + needs: test + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[production] + + - name: Build package + run: | + python -m build + + - name: Archive production artifacts + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions + path: dist/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..223f35a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +# Используем официальный образ Python +FROM python:3.9-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файлы зависимостей +COPY requirements.txt . +COPY pyproject.toml . +COPY setup.py . + +# Устанавливаем системные зависимости +RUN apt-get update && apt-get install -y \ + gcc \ + g++ \ + && rm -rf /var/lib/apt/lists/* + +# Устанавливаем Python зависимости +RUN pip install --no-cache-dir -r requirements.txt + +# Копируем исходный код +COPY . . + +# Создаем необходимые директории +RUN mkdir -p data/processed data/index logs + +# Открываем порт для API +EXPOSE 8000 + +# Команда для запуска приложения +CMD ["uvicorn", "src.api.app:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index c473ac0..3d9cb1e 100644 --- a/README.md +++ b/README.md @@ -1,346 +1,232 @@ -# Хакатон по цифровой трансформации от правительства Москвы +# Building Detector API -Разработка полноценного MVP продукта для определения местоположения по фотографиям с собственным сайтом для работы с пользователем +Система автоматического определения географических координат и адресов зданий на фотоматериалах с использованием визуального поиска и компьютерного зрения. -## 📁 Структура проекта +## 🏗️ Архитектура решения -``` -hack_digital_transformation/ -├── configs/ # Конфигурационные файлы -│ └── config.yaml # Основной конфигурационный файл -├── data/ # Данные (хранятся локально или в S3) -│ ├── raw/ # Сырые данные -│ └── processed/ # Обработанные данные -├── logs/ # Логи выполнения -├── models/ # Обученные модели -├── notebooks/ # Jupyter ноутбуки для исследований -├── plots/ # Графики и диаграммы -├── reports/ # Отчеты и визуализации -│ └── figures/ # Фигуры и графики -├── scripts/ # Скрипты для автоматизации -│ └── setup_environment.sh # Скрипт настройки окружения -├── src/ # Исходный код проекта -│ ├── api/ # API для развертывания модели -│ ├── data/ # Код для обработки данных -│ ├── features/ # Код для инжиниринга признаков -│ ├── models/ # Код для обучения и оценки моделей -│ ├── sql_scripts/ # SQL скрипты для работы с БД -│ └── visualization/ # Код для визуализации -└── tests/ # Тесты -``` +Основная идея: Визуальный поиск по базе изображений (Visual Image Retrieval) -## ⚡ Быстрый старт +Вместо прямого сравнения пикселей, мы сравниваем визуальные признаки (features) изображений. -### Предварительные требования +### Алгоритм работы: -- Python 3.11 -- Git -- Make (рекомендуется) -- Доступ к S3 (для работы с данными в облаке) -- MLflow (для отслеживания экспериментов) +#### Фаза 1: Подготовка базы данных +1. Извлечение признаков из всех фото Москвы (предобученная CNN - ResNet50) +2. Создание поискового индекса (FAISS или Annoy) +3. Создание маппинга: вектор → имя файла в S3 → координаты -### Настройка окружения +#### Фаза 2: Обработка нового изображения +1. Извлечение признаков из загруженной фотографии +2. Поиск K ближайших соседей в FAISS индексе +3. Ранжирование результатов по косинусной близости +4. Определение координат на основе топ-N самых похожих изображений -#### Клонируйте репозиторий: +## 🚀 Быстрый старт -```bash -git clone -cd hack_digital_transformation -``` - -#### Запустите скрипт настройки окружения: +### Запуск с помощью Docker ```bash -chmod +x scripts/setup_environment.sh -./scripts/setup_environment.sh -``` +# Клонирование репозитория +git clone +cd building-detector -#### Активируйте виртуальное окружение: +# Создание .env файла (см. .env.example) +cp .env.example .env +# Отредактируйте .env файл с вашими настройками -```bash -source .venv/bin/activate # Linux/macOS -# или -.venv\Scripts\activate # Windows -``` +# Запуск всех сервисов +docker-compose up -d -## 🛠 Использование +# Сервисы будут доступны: +# API: http://localhost:8000 +# PostgreSQL: localhost:5432 +# Redis: localhost:6379 +``` -### Основные команды +### Локальный запуск ```bash # Установка зависимостей -make install - -# Установка зависимостей для разработки -make install-dev - -# Установка зависимостей для продакшена -make install-prod - -# Запуск тестов -make test - -# Проверка кодстайла -make lint +pip install -r requirements.txt -# Форматирование кода -make format +# Запуск API сервера +uvicorn src.api.app:app --reload --host 0.0.0.0 --port 8000 -# Подготовка данных -make data +# Запуск Celery worker +celery -A src.tasks.worker worker --loglevel=info -# Обучение модели -make train +# Запуск Celery beat (для планирования задач) +celery -A src.tasks.worker beat --loglevel=info +``` -# Оценка модели -make evaluate +## 📡 API Endpoints -# Запуск API сервера -make serve +### Синхронная обработка -# Сборка Docker образа -make docker +- `POST /process_image` - Обработка одного изображения +- `POST /predict` - Прогнозирование с использованием обученной модели +- `GET /health` - Проверка состояния сервиса -# Запуск интерфейса MLflow -make mlflow-ui +### Асинхронная обработка -# Очистка временные файлы -make clean -``` +- `POST /process_image_async` - Асинхронная обработка одного изображения +- `POST /process_images_batch` - Пакетная асинхронная обработка изображений +- `GET /task/{task_id}` - Получение статуса задачи +- `GET /tasks/request/{request_id}` - Получение всех задач по request_id +- `GET /results/latest` - Получение последних результатов обработки -### Работа с данными +### Примеры использования -Данные могут храниться локально или в облачном хранилище S3. Для работы с S3 необходимо настроить учетные данные AWS. +#### Синхронная обработка изображения: -Настройка переменных окружения для работы с S3: ```bash -export S3_BUCKET=your-bucket-name -export S3_RAW_DATA_KEY=data/raw/data.csv -export S3_PROCESSED_PREFIX=data/processed/ -export AWS_ACCESS_KEY_ID=your-access-key -export AWS_SECRET_ACCESS_KEY=your-secret-key +curl -X POST "http://localhost:8000/process_image" \ + -H "Content-Type: application/json" \ + -d '{"image_path": "/path/to/image.jpg"}' ``` -При запуске скриптов, если указана переменная S3_BUCKET, данные будут автоматически загружаться из S3 и сохраняться в него. -Если переменная S3_BUCKET не указана, данные будут работать локально в директориях `data/raw/` и `data/processed/`. - -### Запуск экспериментов - -1. Настройте параметры в `configs/config.yaml` -2. Подготовьте данные: - ```bash - make data - ``` -3. Обучите модель: - ```bash - make train - ``` -4. Оцените модель: - ```bash - make evaluate - ``` - -Все этапы автоматически логируются в MLflow, если указан URI трекинга: -```bash -export MLFLOW_TRACKING_URI=http://localhost:5000 -export MLFLOW_EXPERIMENT_NAME=my-experiment -``` - -### Тестирование - -Проект включает автоматические тесты для обеспечения качества кода: +#### Асинхронная обработка изображения: ```bash -# Запуск всех тестов -make test - -# Запуск тестов с покрытием -pytest tests/ --cov=src - -# Запуск конкретного теста -pytest tests/test_data.py::test_load_data +curl -X POST "http://localhost:8000/process_image_async" \ + -H "Content-Type: application/json" \ + -d '{"image_path": "/path/to/image.jpg", "request_id": "unique-request-id"}' ``` -## ⚙️ Конфигурация +#### Пакетная обработка изображений: -### Проект использует конфигурационные файлы в формате YAML: - -- `configs/config.yaml` - основные настройки проекта - -Файл конфигурации содержит следующие секции: - -```yaml -# Конфигурация данных -data: - raw_path: "data/raw" - processed_path: "data/processed" - train_file: "train.csv" - test_file: "test.csv" - target_column: "target" - test_size: 0.2 - random_state: 42 - -# Конфигурация фичей -features: - numeric_features: - - "age" - - "income" - categorical_features: - - "gender" - - "education" - -# Конфигурация модели -model: - name: "random_forest" - params: - n_estimators: 100 - max_depth: 10 - random_state: 42 - -# Конфигурация обучения -training: - test_size: 0.2 - random_state: 42 - cv_folds: 5 - batch_size: 32 - epochs: 50 - learning_rate: 0.001 - early_stopping_patience: 5 - -# Конфигурация логирования -logging: - level: "INFO" - format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - file: "logs/training.log" +```bash +curl -X POST "http://localhost:8000/process_images_batch" \ + -H "Content-Type: application/json" \ + -d '{ + "image_paths": ["/path/to/image1.jpg", "/path/to/image2.jpg"], + "request_id": "batch-request-id" + }' ``` -## 📊 Визуализация - -Проект включает встроенные возможности для визуализации: +#### Получение статуса задачи: ```bash -# Генерация визуализаций -python src/visualization/visualize.py +curl -X GET "http://localhost:8000/task/{task_id}" ``` -Визуализации сохраняются в: -- `reports/figures/distribution_plots.png` - распределения признаков -- `reports/figures/correlation_heatmap.png` - корреляционная матрица -- `plots/feature_importance.png` - важность признаков -- `reports/figures/roc_curve.png` - ROC кривая +## ⚙️ Конфигурация -## 📦 Развертывание +### Переменные окружения (.env) -### Docker +```env +# AWS S3 Credentials +AWS_ACCESS_KEY_ID=your_access_key +AWS_SECRET_ACCESS_KEY=your_secret_key +AWS_ENDPOINT_URL=https://storage.yandexcloud.net +AWS_BUCKET_NAME=your_bucket_name -Соберите и запустите контейнер: +# Database +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_DB=building_detector -```bash -make docker -docker run -p 8000:8000 hack_digital_transformation +# Geocoders +YANDEX_GEOCODER_API_KEY=your_yandex_api_key +GOOGLE_GEOCODER_API_KEY=your_google_api_key + +# Celery +CELERY_WORKER_CONCURRENCY=4 +REDIS_URL=redis://localhost:6379/0 +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/building_detector ``` -### API сервер +## 📊 Производительность -Проект включает FastAPI сервер для предсказаний: +Система оптимизирована для обработки 1000 изображений за ≤3 часов: -```bash -make serve -``` - -API будет доступно по адресу: http://localhost:8000/docs +- Параллельная обработка с помощью Celery workers +- Кэширование признаков изображений +- Оптимизированный FAISS индекс для быстрого поиска +- Асинхронная обработка с отслеживанием прогресса -Пример запроса к API: +## 🛠️ Структура проекта -```bash -curl -X POST "http://localhost:8000/predict" \ - -H "Content-Type: application/json" \ - -d '{"features": {"age": 35, "income": 50000, "gender_M": 1, "education_Master": 0}}' +``` +building-detector/ +├── src/ +│ ├── api/ # FastAPI endpoints +│ ├── models/ # Computer vision models +│ ├── geo/ # Geocoding services +│ ├── data/ # Data processing utilities +│ ├── tasks/ # Celery tasks +│ ├── utils/ # Utility functions +│ └── sql_scripts/ # Database initialization scripts +├── data/ # Local data storage +├── logs/ # Application logs +├── tests/ # Unit and integration tests +├── Dockerfile # Docker image definition +├── docker-compose.yml # Services orchestration +├── requirements.txt # Python dependencies +└── README.md # Project documentation ``` -### Cloud развертывание - -Пример для AWS SageMaker: +## 🧪 Тестирование ```bash -# Упаковка модели для SageMaker -python src/models/pack_for_sagemaker.py +# Запуск unit тестов +python -m pytest tests/ -# Деплой (пример для AWS CLI) -aws s3 sync sagemaker_model/ s3://my-bucket/models/my-model/ +# Запуск тестов с покрытием +python -m pytest tests/ --cov=src ``` -## 🔬 Эксперименты и отслеживание +## 🔄 CI/CD и Линтеры -Проект использует MLflow для отслеживания экспериментов машинного обучения. При обучении и оценке моделей автоматически логируются: -- Параметры модели и обучения -- Метрики качества -- Артефакты (графики, файлы метрик и т.д.) -- Версии кода +Проект использует GitHub Actions для непрерывной интеграции и доставки. Конфигурация находится в `.github/workflows/ci.yml`. -### Настройка MLflow +### Линтеры и форматирование кода -Для работы с MLflow необходимо указать URI трекинга и имя эксперимента через переменные окружения: -```bash -export MLFLOW_TRACKING_URI=http://localhost:5000 # или другой URI вашего MLflow сервера -export MLFLOW_EXPERIMENT_NAME=my-experiment # имя эксперимента -``` +Проект использует несколько линтеров для обеспечения качества кода: -### Запуск MLflow UI +- **Black** - автоформатирование кода (максимальная длина строки: 120) +- **Isort** - сортировка импортов +- **Ruff** - быстрая проверка кода +- **Flake8** - дополнительные проверки стиля -Для просмотра результатов экспериментов можно использовать встроенный интерфейс MLflow: -```bash -make mlflow-ui -``` -или напрямую: -```bash -mlflow ui -``` +### Локальное использование линтеров -Интерфейс будет доступен по адресу: http://localhost:5000 - -### Программное использование MLflow - -В скриптах обучения и оценки модели уже интегрирована работа с MLflow: -```python -import mlflow +```bash +# Форматирование кода с помощью black и isort +black . +isort . -# Автоматическое логирование параметров и метрик scikit-learn моделей -mlflow.sklearn.autolog() +# Проверка кода с помощью ruff +ruff check . -with mlflow.start_run(): - # Ваш код обучения - model.fit(X_train, y_train) - # Метрики и параметры автоматически логируются +# Проверка стиля кода с помощью flake8 +flake8 . ``` -### Хранение артефактов - -Артефакты (модели, графики, метрики) автоматически сохраняются как локально, так и в MLflow, если указан URI трекинга. - -## 📝 Скрипты - -В папке `scripts/` размещаются дополнительные скрипты для автоматизации распространенных сценариев: +### Автоматическая проверка -- `setup_environment.sh` - настройка окружения с установкой UV и зависимостей -- Дополнительные скрипты можно добавлять по необходимости +При каждом пуше или создании pull request запускается pipeline, который: +1. Проверяет форматирование и стиль кода +2. Запускает unit тесты +3. Собирает пакет для распространения -## 🧪 CI/CD +## 📈 Мониторинг -Проект включает настройки для непрерывной интеграции и доставки: +Система включает в себя: -- GitHub Actions workflows для тестирования и развертывания -- Pre-commit hooks для проверки кода перед коммитом -- Dockerfile для контейнеризации приложения +- Логирование всех операций +- Отслеживание прогресса асинхронных задач +- Статистика обработки изображений +- Мониторинг ошибок и исключений -## 🤝 Вклад в проект +## 🤝 Интеграции -1. Форкните репозиторий -2. Создайте ветку для функциональности (`git checkout -b feature/amazing-feature`) -3. Закоммитьте изменения (`git commit -m 'Добавить замечательную функцию'`) -4. Запушьте ветку (`git push origin feature/amazing-feature`) -5. Откройте Pull Request +- **S3 Storage**: Хранение изображений и метаданных +- **FAISS**: Быстрый поиск по визуальным признакам +- **Geocoders**: Yandex, Google, OpenStreetMap +- **PostgreSQL**: Хранение результатов обработки +- **Redis**: Очереди задач и кэширование -## Лицензия +## 📄 Лицензия -Этот проект лицензирован под MIT License - см. файл [LICENSE](LICENSE) для подробностей. +MIT License diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1144466 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,83 @@ +version: '3.8' + +services: + # Основной сервис приложения + app: + build: . + ports: + - "8000:8000" + environment: + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AWS_ENDPOINT_URL=${AWS_ENDPOINT_URL} + - AWS_BUCKET_NAME=${AWS_BUCKET_NAME} + - YANDEX_GEOCODER_API_KEY=${YANDEX_GEOCODER_API_KEY} + - GOOGLE_GEOCODER_API_KEY=${GOOGLE_GEOCODER_API_KEY} + volumes: + - ./data:/app/data + - ./logs:/app/logs + depends_on: + - redis + restart: unless-stopped + + # Redis для кэширования и очередей задач + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redis_data:/data + restart: unless-stopped + + # PostgreSQL для хранения метаданных и результатов обработки + postgres: + image: postgres:15-alpine + environment: + POSTGRES_DB: building_detector + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./src/sql_scripts:/docker-entrypoint-initdb.d + restart: unless-stopped + + # Celery worker для асинхронной обработки изображений + celery_worker: + build: . + command: celery -A src.tasks.worker worker --loglevel=info + environment: + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AWS_ENDPOINT_URL=${AWS_ENDPOINT_URL} + - AWS_BUCKET_NAME=${AWS_BUCKET_NAME} + - YANDEX_GEOCODER_API_KEY=${YANDEX_GEOCODER_API_KEY} + - GOOGLE_GEOCODER_API_KEY=${GOOGLE_GEOCODER_API_KEY} + - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/building_detector + - REDIS_URL=redis://redis:6379/0 + volumes: + - ./data:/app/data + - ./logs:/app/logs + depends_on: + - redis + - postgres + restart: unless-stopped + + # Celery beat для планирования задач + celery_beat: + build: . + command: celery -A src.tasks.worker beat --loglevel=info + environment: + - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/building_detector + - REDIS_URL=redis://redis:6379/0 + volumes: + - ./logs:/app/logs + depends_on: + - redis + - postgres + restart: unless-stopped + +volumes: + redis_data: + postgres_data: diff --git a/notebooks/1_data_exploration/1_1_download_data.ipynb b/notebooks/1_data_exploration/1_1_download_data.ipynb index 2f15849..5cad04f 100644 --- a/notebooks/1_data_exploration/1_1_download_data.ipynb +++ b/notebooks/1_data_exploration/1_1_download_data.ipynb @@ -45,7 +45,7 @@ "source": [ "import pandas as pd \n", "import numpy as np \n", - "from utils.s3 import s3_download_file, get_s3_client, s3_list_files, s3_upload_file\n", + "from utils.s3 import s3_download_file, get_s3_client, s3_list_files, s3_upload_file, s3_upload_folder\n", "from utils.zip import extract_zip_advanced\n", "from utils.useful_functions import extract_coordinates, move_and_remove_files, merge_tables_with_tolerance\n", "from dotenv import load_dotenv\n", @@ -150,6 +150,54 @@ " bucket_name='s3-dvc',)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "e37d5f12", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Август.zip', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/build_no_norm_aug.zip', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c73438c7", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Июль.zip', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/build_no_norm_jule.zip', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9738b60f", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Строительная площадка_18-001_Август.zip', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/building_aug.zip', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e095c92", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Строительная площадка_18-001_Июль.zip', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/building_jule.zip', \n", + " bucket_name='s3-dvc',)" + ] + }, { "cell_type": "markdown", "id": "6cb09e4b", @@ -194,6 +242,54 @@ " bucket_name='s3-dvc',)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c701796", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Август.xlsx', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/build_no_norm_aug_target.xlsx', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb64e467", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Июль.xlsx', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/build_no_norm_jule_target.xlsx', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb680372", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Строительная площадка_18-001_Август.xlsx', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/building_aug_target.xlsx', \n", + " bucket_name='s3-dvc',)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "203f70e7", + "metadata": {}, + "outputs": [], + "source": [ + "s3_download_file(file_s3_src='raw_data/Строительная площадка_18-001_Июль.xlsx', \n", + " file_local_dst=ROOT_DIR / 'data/raw_data/building_jule_target.xlsx', \n", + " bucket_name='s3-dvc',)" + ] + }, { "cell_type": "markdown", "id": "f099d5a8", @@ -210,6 +306,54 @@ "### Извлекаем тренировочный датасет " ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "4be05af5", + "metadata": {}, + "outputs": [], + "source": [ + "extract_zip_advanced(zip_path=ROOT_DIR / 'data/raw_data/build_no_norm_aug.zip',\n", + " extract_to=ROOT_DIR / 'data/raw_data/build_no_norm_aug',\n", + " remove_after_extract=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60a1aca5", + "metadata": {}, + "outputs": [], + "source": [ + "extract_zip_advanced(zip_path=ROOT_DIR / 'data/raw_data/build_no_norm_jule.zip',\n", + " extract_to=ROOT_DIR / 'data/raw_data/build_no_norm_jule',\n", + " remove_after_extract=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99de0a0d", + "metadata": {}, + "outputs": [], + "source": [ + "extract_zip_advanced(zip_path=ROOT_DIR / 'data/raw_data/building_aug.zip',\n", + " extract_to=ROOT_DIR / 'data/raw_data/building_aug',\n", + " remove_after_extract=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b336c3b3", + "metadata": {}, + "outputs": [], + "source": [ + "extract_zip_advanced(zip_path=ROOT_DIR / 'data/raw_data/building_jule.zip',\n", + " extract_to=ROOT_DIR / 'data/raw_data/building_jule',\n", + " remove_after_extract=True,)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -503,6 +647,154 @@ "target_garb.drop('geoData', axis=1, inplace=True)" ] }, + { + "cell_type": "markdown", + "id": "f00de88d", + "metadata": {}, + "source": [ + "## Выгружаем новые данные" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d17beeb2", + "metadata": {}, + "outputs": [], + "source": [ + "build_no_norm_aug_target = pd.read_excel(ROOT_DIR / \"data/raw_data/build_no_norm_aug_target.xlsx\",\n", + " usecols=['Имя файла', 'latitude', 'longitude',]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae1fea8e", + "metadata": {}, + "outputs": [], + "source": [ + "build_no_norm_aug_target = pd.read_excel(ROOT_DIR / \"data/raw_data/build_no_norm_jule_target.xlsx\",\n", + " usecols=['Имя файла', 'latitude', 'longitude',]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94fc73f1", + "metadata": {}, + "outputs": [], + "source": [ + "build_no_norm_aug_target = pd.read_excel(ROOT_DIR / \"data/raw_data/building_aug_target.xlsx\",\n", + " usecols=['Имя файла', 'latitude', 'longitude',]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a96e1bb", + "metadata": {}, + "outputs": [], + "source": [ + "build_no_norm_aug_target = pd.read_excel(ROOT_DIR / \"data/raw_data/building_jule_target.xlsx\",\n", + " usecols=['Имя файла', 'latitude', 'longitude',]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c0e5c33", + "metadata": {}, + "outputs": [], + "source": [ + "build_target_data = pd.concat([build_no_norm_aug_target, build_no_norm_aug_target,\n", + " build_no_norm_aug_target, build_no_norm_aug_target], \n", + " axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e91219d", + "metadata": {}, + "outputs": [], + "source": [ + "os.mkdir(ROOT_DIR / 'data/processed_data/')\n", + "build_target_data.to_csv(path_or_buf=ROOT_DIR / 'data/processed_data/build_target_data.csv',\n", + " index=False,)" + ] + }, + { + "cell_type": "markdown", + "id": "cdfcd0a1", + "metadata": {}, + "source": [ + "## Объединяем фотографии\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cce50c6", + "metadata": {}, + "outputs": [], + "source": [ + "destination_dir = ROOT_DIR / 'data/processed_data/images_build/'\n", + "os.mkdir(destination_dir)\n", + "os.mkdir(ROOT_DIR / 'data/processed_data/merge_images/')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7c8b7e9", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/build_no_norm_aug/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Август', \n", + " destination_dir=destination_dir,\n", + " remove_after_move=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b52a46e", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/build_no_norm_jule/Объекты недвижимости, не соответствующие градостроительным нормам_00-022_Июль', \n", + " destination_dir=destination_dir,\n", + " remove_after_move=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d483434", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/building_aug/Строительная площадка_18-001_Август', \n", + " destination_dir=destination_dir,\n", + " remove_after_move=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4ff0dbe", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/building_jule/Строительная площадка_18-001_Июль', \n", + " destination_dir=destination_dir,\n", + " remove_after_move=True)" + ] + }, { "cell_type": "markdown", "id": "5a5e0dbd", @@ -565,11 +857,64 @@ "metadata": {}, "outputs": [], "source": [ - "os.mkdir(ROOT_DIR / 'data/processed_data/')\n", "data.to_csv(path_or_buf=ROOT_DIR / 'data/processed_data/merged_data.csv',\n", " index=False,)" ] }, + { + "cell_type": "markdown", + "id": "64d2d0d0", + "metadata": {}, + "source": [ + "# Перемещяем все фотки в единую папку " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1f56653", + "metadata": {}, + "outputs": [], + "source": [ + "os.mkdir(ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35417e5a", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/18-001_gin_building_echd_19.08.25', \n", + " destination_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image',\n", + " remove_after_move=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b123a07e", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/19-001_gin_garbage_echd_19.08.25', \n", + " destination_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image',\n", + " remove_after_move=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b193a00", + "metadata": {}, + "outputs": [], + "source": [ + "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image', \n", + " destination_dir=ROOT_DIR / 'data/processed_data/merge_images/',\n", + " remove_after_move=False)" + ] + }, { "cell_type": "markdown", "id": "af27c847", @@ -616,55 +961,42 @@ " bucket_name='s3-dvc',)" ] }, - { - "cell_type": "markdown", - "id": "64d2d0d0", - "metadata": {}, - "source": [ - "# Перемещяем все фотки в единую папку " - ] - }, { "cell_type": "code", "execution_count": null, - "id": "a1f56653", + "id": "decff36b", "metadata": {}, "outputs": [], "source": [ - "os.mkdir(ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image')" + "s3_upload_file(file_local_src=ROOT_DIR / 'data/processed_data/build_target_data.csv',\n", + " file_s3_dst='processed_data/build_target_data.csv',\n", + " bucket_name='s3-dvc',)" ] }, { "cell_type": "code", "execution_count": null, - "id": "35417e5a", + "id": "e1ec1292", "metadata": {}, "outputs": [], "source": [ - "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/18-001_gin_building_echd_19.08.25', \n", - " destination_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image',\n", - " remove_after_move=True,)" + "s3_upload_folder(local_folder=ROOT_DIR / 'data/processed_data/merge_images/',\n", + " s3_prefix='processed_data/merged_images',\n", + " bucket_name='s3-dvc',)" ] }, { "cell_type": "code", "execution_count": null, - "id": "b123a07e", + "id": "2644c7c9", "metadata": {}, "outputs": [], "source": [ - "move_and_remove_files(source_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/19-001_gin_garbage_echd_19.08.25', \n", - " destination_dir=ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image',\n", - " remove_after_move=True,)" + "s3_upload_folder(local_folder=ROOT_DIR / 'data/processed_data/images_build',\n", + " s3_prefix='processed_data/images_build',\n", + " bucket_name='s3-dvc',)\n", + "# последний файл c201fc12-425d-4ecf-8a89-9dd4fc0fb3aa.jpg" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b193a00", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/notebooks/1_data_exploration/1_2_prepare_data.ipynb b/notebooks/1_data_exploration/1_2_prepare_data.ipynb index 7956bd0..b2ce4aa 100644 --- a/notebooks/1_data_exploration/1_2_prepare_data.ipynb +++ b/notebooks/1_data_exploration/1_2_prepare_data.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "id": "97feaebc", "metadata": {}, "outputs": [], @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 2, "id": "cd10fe31", "metadata": {}, "outputs": [], @@ -73,7 +73,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 37, "id": "e7ef1558", "metadata": {}, "outputs": [], @@ -122,526 +122,6 @@ " print(f\"Тестовый батч: images {images.shape}, coordinates {len(coordinates)}\")\n", " break" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5fb26062", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Best ROI: left_bottom | conf=0.93\n", - "joined: MMChdUZAO_112301\n", - "norm : MMC_hd_UZAO_112301\n", - "final : MMC_hd_UZAO_1123_0_1\n" - ] - } - ], - "source": [ - "import cv2\n", - "import numpy as np\n", - "import easyocr\n", - "import re\n", - "from typing import List, Tuple, Optional\n", - "\n", - "class OverlayOCR:\n", - " WHITELIST_RE = re.compile(r\"[A-Za-z0-9_]+\")\n", - "\n", - " def __init__(\n", - " self,\n", - " langs: Optional[List[str]] = None,\n", - " gpu: bool = False,\n", - " verbose: bool = False,\n", - " gap_mult: float = 1.6,\n", - " canvas_size: int = 3600,\n", - " mag_ratio: float = 3.0,\n", - " add_margin: float = 0.10,\n", - " text_threshold: float = 0.55,\n", - " low_text: float = 0.30,\n", - " link_threshold: float = 0.30,\n", - " ):\n", - " \"\"\"\n", - " langs: языки easyocr, напр. ['en'] или ['en','ru']\n", - " gap_mult: чувствительность к горизонтальным разрывам (меньше -> больше '_')\n", - " canvas_size/mag_ratio: масштабирование внутри easyocr\n", - " \"\"\"\n", - " self.langs = langs or ['en']\n", - " self.reader = easyocr.Reader(self.langs, gpu=gpu, verbose=verbose)\n", - " self.gap_mult = gap_mult\n", - " self.canvas_size = canvas_size\n", - " self.mag_ratio = mag_ratio\n", - " self.add_margin = add_margin\n", - " self.text_threshold = text_threshold\n", - " self.low_text = low_text\n", - " self.link_threshold = link_threshold\n", - "\n", - " # ---------- утилиты ----------\n", - " @staticmethod\n", - " def _clean_token(t: str) -> str:\n", - " return \"\".join(OverlayOCR.WHITELIST_RE.findall(t))\n", - "\n", - " @staticmethod\n", - " def _alnum_class(ch: str) -> str:\n", - " return 'D' if ch.isdigit() else ('A' if ch.isalpha() else '_')\n", - "\n", - " def _join_with_gaps(self, results, sep='_') -> Tuple[str, float, list]:\n", - " \"\"\"\n", - " Склейка токенов слева направо:\n", - " - '_' если горизонтальный зазор >> медианного,\n", - " - '_' на границах A<->D.\n", - " \"\"\"\n", - " items = []\n", - " for bbox, text, conf in results:\n", - " t = self._clean_token(text)\n", - " if not t:\n", - " continue\n", - " x0 = min(p[0] for p in bbox); x1 = max(p[0] for p in bbox)\n", - " items.append((x0, x1, t, float(conf)))\n", - " if not items:\n", - " return \"\", 0.0, []\n", - "\n", - " items.sort(key=lambda z: z[0])\n", - " gaps = []\n", - " for i in range(1, len(items)):\n", - " gaps.append(items[i][0] - items[i-1][1])\n", - " med_gap = np.median(gaps) if gaps else 0\n", - "\n", - " out = []\n", - " confs = []\n", - " prev = None\n", - " for i, (x0, x1, t, c) in enumerate(items):\n", - " if prev is not None:\n", - " gap = x0 - prev[1]\n", - " need_sep = (med_gap > 0 and gap > self.gap_mult * med_gap)\n", - " # буква↔️цифра – полезно отделить\n", - " if not need_sep:\n", - " prev_last = out[-1][-1] if out else ''\n", - " if prev_last and t:\n", - " need_sep = (self._alnum_class(prev_last) != self._alnum_class(t[0]))\n", - " if need_sep and (not out or out[-1] != sep):\n", - " out.append(sep)\n", - " out.append(t)\n", - " confs.append(c)\n", - " prev = (x0, x1)\n", - "\n", - " text = \"\".join(out)\n", - " text = re.sub(r\"_+\", \"_\", text).strip(\"_\")\n", - " avg_conf = float(sum(confs)/len(confs)) if confs else 0.0\n", - " return text, avg_conf, items\n", - "\n", - " @staticmethod\n", - " def _normalize_overlays(s: str) -> str:\n", - " \"\"\"Правки под формат MMC_hd_... и расстановка подчёркиваний.\"\"\"\n", - " s = re.sub(r\"^MMC(?:_)?h(?:d)?\", \"MMC_hd\", s, flags=re.IGNORECASE)\n", - " s = re.sub(r\"^MMC_?hd_?\", \"MMC_hd_\", s, flags=re.IGNORECASE)\n", - " s = re.sub(r\"([A-Za-z])([0-9])\", r\"\\1_\\2\", s)\n", - " s = re.sub(r\"([0-9])([A-Za-z])\", r\"\\1_\\2\", s)\n", - " s = re.sub(r\"_+\", \"_\", s).strip(\"_\")\n", - " return s\n", - "\n", - " @staticmethod\n", - " def _snap_digits_tail(s: str) -> str:\n", - " \"\"\"\n", - " Если хвост цифр склеен, режем на 4-1-1 (типичный случай).\n", - " Пример: ...229221 -> ...2292_2_1\n", - " \"\"\"\n", - " m = re.search(r\"^(.*?)(\\d{6,})$\", s)\n", - " if not m:\n", - " return s\n", - " head, digits = m.group(1), m.group(2)\n", - " if len(digits) >= 6:\n", - " s = f\"{head}{digits[:4]}_{digits[4:5]}_{digits[5:]}\"\n", - " return re.sub(r\"_+\", \"_\", s).strip(\"_\")\n", - "\n", - "\n", - " # ---------- EasyOCR запуск на ROI ----------\n", - " def run_on_roi(self, roi_bgr) -> Tuple[str, str, str, float]:\n", - " params = dict(\n", - " decoder='greedy',\n", - " detail=1,\n", - " paragraph=False,\n", - " contrast_ths=0.05,\n", - " adjust_contrast=0.7,\n", - " text_threshold=self.text_threshold,\n", - " low_text=self.low_text,\n", - " link_threshold=self.link_threshold,\n", - " canvas_size=self.canvas_size,\n", - " mag_ratio=self.mag_ratio,\n", - " add_margin=self.add_margin,\n", - " )\n", - " results = self.reader.readtext(roi_bgr, **params)\n", - " joined, conf, _ = self._join_with_gaps(results, sep=\"_\")\n", - " norm = self._normalize_overlays(joined)\n", - " final = self._snap_digits_tail(norm)\n", - " final = re.sub(r\"^MMC_?hd_?\", \"MMC_hd_\", final, flags=re.IGNORECASE)\n", - " final = re.sub(r\"_+\", \"_\", final).strip(\"_\")\n", - " return joined, norm, final, conf\n", - "\n", - " # ---------- ROI генераторы ----------\n", - " @staticmethod\n", - " def roi_left_bottom(img, w_frac=1/3, h_frac=1/4):\n", - " H, W = img.shape[:2]\n", - " return img[H - int(H*h_frac):H, 0:int(W*w_frac)]\n", - "\n", - " @staticmethod\n", - " def roi_bottom_band(img, h_frac=1/3):\n", - " H, _ = img.shape[:2]\n", - " y0 = H - int(H*h_frac)\n", - " return img[y0:H, :]\n", - "\n", - " @staticmethod\n", - " def roi_auto_band(img):\n", - " g = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", - " _, b = cv2.threshold(cv2.GaussianBlur(g, (5,5), 0), 0, 255,\n", - " cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)\n", - " row = (b > 0).sum(axis=1).astype(np.float32)\n", - " k = max(3, (img.shape[0]//100)*2+1)\n", - " row = cv2.GaussianBlur(row.reshape(-1,1),(1,k),0).ravel()\n", - " start = img.shape[0]//2\n", - " idx = start + int(np.argmax(row[start:]))\n", - " band_half = max(img.shape[0]//12, 20)\n", - " y0, y1 = max(0, idx-band_half), min(img.shape[0], idx+band_half)\n", - " return img[y0:y1, :]\n", - "\n", - " # ---------- главный метод ----------\n", - " def run_on_image(self, image_path: str) -> Tuple[str, str, str, float, str]:\n", - " \"\"\"\n", - " Возвращает:\n", - " final, norm, joined, conf, best_roi_name\n", - " \"\"\"\n", - " img = cv2.imread(image_path)\n", - " assert img is not None, f\"Не удалось загрузить изображение: {image_path}\"\n", - "\n", - " rois = [\n", - " (\"left_bottom\", self.roi_left_bottom(img, 1/3, 1/4)),\n", - " (\"bottom_band\", self.roi_bottom_band(img, 1/3)),\n", - " (\"auto_band\", self.roi_auto_band(img)),\n", - " ]\n", - "\n", - " best = None\n", - " best_name = \"\"\n", - " best_pack = (\"\", \"\", \"\", 0.0)\n", - "\n", - " for name, roi in rois:\n", - " joined, norm, final, conf = self.run_on_roi(roi)\n", - " cand = (conf, len(final), (final, norm, joined, conf), name)\n", - " if (best is None) or (cand > best):\n", - " best = cand\n", - " best_pack = (final, norm, joined, conf)\n", - " best_name = name\n", - "\n", - " final, norm, joined, conf = best_pack\n", - " return final, norm, joined, conf, best_name\n", - "\n", - "\n", - "# ===================== пример использования =====================\n", - "\n", - "if __name__ == \"__main__\":\n", - " IMG = r'/home/lizardapn/Hack_digital/hack_digital_transformation/data/raw_data/data/metadata/INC/united_image/0a0ee2fb-b7ad-4430-97d7-281e2c293041.jpg'\n", - "\n", - " ocr = OverlayOCR(\n", - " langs=['en'], # ['en','ru'] если нужна кириллица\n", - " gpu=True,\n", - " gap_mult=1.6,\n", - " canvas_size=3600,\n", - " mag_ratio=3.0,\n", - " add_margin=0.10,\n", - " text_threshold=0.55,\n", - " low_text=0.30,\n", - " link_threshold=0.30,\n", - " )\n", - "\n", - " final, norm, joined, conf, roi_name = ocr.run_on_image(IMG)\n", - " print(f\"Best ROI: {roi_name} | conf={conf:.2f}\")\n", - " print(\"joined:\", joined)\n", - " print(\"norm :\", norm)\n", - " print(\"final :\", final)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "99b46a62", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "299610c2", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[I 2025-09-25 20:53:37,368] A new study created in memory with name: no-name-ad852449-0235-45d1-a60b-e535dcbb5227\n", - "[I 2025-09-25 20:53:47,455] Trial 0 finished with value: 3.0 and parameters: {'gap_mult': 2.8068367308375892, 'canvas_size': 3600, 'mag_ratio': 2.8965996021592537, 'add_margin': 0.48089093342192746, 'text_threshold': 0.30768847754184525, 'low_text': 0.5186617904372725, 'link_threshold': 0.3295188034326136}. Best is trial 0 with value: 3.0.\n", - "[I 2025-09-25 20:53:56,705] Trial 1 finished with value: 3.0 and parameters: {'gap_mult': 0.4616970821705757, 'canvas_size': 7200, 'mag_ratio': 3.9151446432090062, 'add_margin': 0.29848539656963197, 'text_threshold': 0.7381783711907166, 'low_text': 0.6797473138005795, 'link_threshold': 0.31919910593867973}. Best is trial 0 with value: 3.0.\n", - "[I 2025-09-25 20:54:00,930] Trial 2 finished with value: 1.0 and parameters: {'gap_mult': 2.95068046948933, 'canvas_size': 1800, 'mag_ratio': 1.6335501479294163, 'add_margin': 0.23019075051561422, 'text_threshold': 0.5364046793357755, 'low_text': 0.14346526109875232, 'link_threshold': 0.4549901859491947}. Best is trial 2 with value: 1.0.\n", - "[I 2025-09-25 20:54:03,561] Trial 3 finished with value: 2.0 and parameters: {'gap_mult': 0.7098592466029646, 'canvas_size': 1800, 'mag_ratio': 4.337665270375808, 'add_margin': 0.2092324992312398, 'text_threshold': 0.5999943848050431, 'low_text': 0.5505604402067924, 'link_threshold': 0.3594102577222953}. Best is trial 2 with value: 1.0.\n", - "[I 2025-09-25 20:54:11,619] Trial 4 finished with value: 8.0 and parameters: {'gap_mult': 2.6082037341148663, 'canvas_size': 10000, 'mag_ratio': 3.858049154855571, 'add_margin': 0.023438922614506454, 'text_threshold': 0.7258377412928896, 'low_text': 0.3718230280903212, 'link_threshold': 0.41824734965498844}. Best is trial 2 with value: 1.0.\n", - "[I 2025-09-25 20:54:14,502] Trial 5 finished with value: 6.0 and parameters: {'gap_mult': 2.6706992390768276, 'canvas_size': 3600, 'mag_ratio': 3.235255263782191, 'add_margin': 0.26475654378958785, 'text_threshold': 0.4536236374494962, 'low_text': 0.5543332082573351, 'link_threshold': 0.28821655261683743}. Best is trial 2 with value: 1.0.\n", - "[I 2025-09-25 20:54:17,267] Trial 6 finished with value: 2.0 and parameters: {'gap_mult': 0.582283392877384, 'canvas_size': 7200, 'mag_ratio': 2.7611406531446723, 'add_margin': 0.38970235970730355, 'text_threshold': 0.7295818110214943, 'low_text': 0.6309958719665154, 'link_threshold': 0.1740186779693806}. Best is trial 2 with value: 1.0.\n", - "[I 2025-09-25 20:54:19,088] Trial 7 finished with value: 0.0 and parameters: {'gap_mult': 0.1148899697656891, 'canvas_size': 1800, 'mag_ratio': 2.0909813860745077, 'add_margin': 0.38880953861561235, 'text_threshold': 0.5046870997550761, 'low_text': 0.2758043304152779, 'link_threshold': 0.4121455607297143}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:21,489] Trial 8 finished with value: 6.0 and parameters: {'gap_mult': 0.306489544901438, 'canvas_size': 3600, 'mag_ratio': 2.431735944829139, 'add_margin': 0.12216310769525666, 'text_threshold': 0.4190839052600482, 'low_text': 0.27219395882445296, 'link_threshold': 0.37805487357277634}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:23,559] Trial 9 finished with value: 6.0 and parameters: {'gap_mult': 0.7405645718677436, 'canvas_size': 1800, 'mag_ratio': 2.7070172489585387, 'add_margin': 0.4140575014567742, 'text_threshold': 0.6300710361851376, 'low_text': 0.33516922393069803, 'link_threshold': 0.17953131386104623}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:25,982] Trial 10 finished with value: 0.0 and parameters: {'gap_mult': 1.4093994989267604, 'canvas_size': 10000, 'mag_ratio': 1.711106955826645, 'add_margin': 0.34762496219028105, 'text_threshold': 0.3909935170351837, 'low_text': 0.11283459845938454, 'link_threshold': 0.6099373327834569}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:27,935] Trial 11 finished with value: 0.0 and parameters: {'gap_mult': 1.4792872699039796, 'canvas_size': 10000, 'mag_ratio': 1.5223010354107902, 'add_margin': 0.33563162563951027, 'text_threshold': 0.37565955475152524, 'low_text': 0.1168980126968841, 'link_threshold': 0.6325641683059166}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:30,647] Trial 12 finished with value: 0.0 and parameters: {'gap_mult': 1.363569314546833, 'canvas_size': 10000, 'mag_ratio': 2.1897337958053624, 'add_margin': 0.469594695826354, 'text_threshold': 0.48388464532737874, 'low_text': 0.21658316372857112, 'link_threshold': 0.5597509755711151}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:32,654] Trial 13 finished with value: 0.0 and parameters: {'gap_mult': 2.0469309820631105, 'canvas_size': 1800, 'mag_ratio': 2.006596797142189, 'add_margin': 0.3626671511083453, 'text_threshold': 0.36655356940398864, 'low_text': 0.22865266846485077, 'link_threshold': 0.5216438095511898}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:37,208] Trial 14 finished with value: 6.0 and parameters: {'gap_mult': 1.1069357731698148, 'canvas_size': 10000, 'mag_ratio': 1.8969889704811436, 'add_margin': 0.42390499933071407, 'text_threshold': 0.5157168099224722, 'low_text': 0.10164163381677017, 'link_threshold': 0.6704962998573097}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:40,128] Trial 15 finished with value: 2.0 and parameters: {'gap_mult': 1.8996243187385848, 'canvas_size': 1800, 'mag_ratio': 4.870066126775307, 'add_margin': 0.32483866469189737, 'text_threshold': 0.585824466151432, 'low_text': 0.4191998906943226, 'link_threshold': 0.5162837033151318}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:42,649] Trial 16 finished with value: 6.0 and parameters: {'gap_mult': 0.15078914260503726, 'canvas_size': 10000, 'mag_ratio': 2.336137777441351, 'add_margin': 0.15215492650074974, 'text_threshold': 0.41400283625495554, 'low_text': 0.18781709662258905, 'link_threshold': 0.5934394365460154}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:44,730] Trial 17 finished with value: 8.0 and parameters: {'gap_mult': 2.013170127993129, 'canvas_size': 7200, 'mag_ratio': 1.8268150446726152, 'add_margin': 0.448717840682068, 'text_threshold': 0.31527561348760785, 'low_text': 0.30206312727673806, 'link_threshold': 0.4580136822784667}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:50,832] Trial 18 finished with value: 7.0 and parameters: {'gap_mult': 1.059265015642122, 'canvas_size': 10000, 'mag_ratio': 3.336471276803885, 'add_margin': 0.282447622846455, 'text_threshold': 0.45135572176395305, 'low_text': 0.4253467296918087, 'link_threshold': 0.26399052554383395}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:53,151] Trial 19 finished with value: 6.0 and parameters: {'gap_mult': 2.381889433799428, 'canvas_size': 1800, 'mag_ratio': 2.455352248219552, 'add_margin': 0.3617385824967006, 'text_threshold': 0.5375199556741124, 'low_text': 0.17247623825345915, 'link_threshold': 0.5205447782602558}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:54:58,417] Trial 20 finished with value: 0.0 and parameters: {'gap_mult': 1.7314693373323178, 'canvas_size': 10000, 'mag_ratio': 3.1603467746819867, 'add_margin': 0.17358331235688695, 'text_threshold': 0.6662549037510657, 'low_text': 0.27133518926858646, 'link_threshold': 0.6857614766409486}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:00,525] Trial 21 finished with value: 0.0 and parameters: {'gap_mult': 1.4760274400451803, 'canvas_size': 10000, 'mag_ratio': 1.505120282497312, 'add_margin': 0.33500238184214015, 'text_threshold': 0.3640023294357934, 'low_text': 0.10303266997568411, 'link_threshold': 0.6226069867707704}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:02,569] Trial 22 finished with value: 3.0 and parameters: {'gap_mult': 1.0719868998063475, 'canvas_size': 10000, 'mag_ratio': 1.5514445085936461, 'add_margin': 0.38165340541644804, 'text_threshold': 0.36735195851134994, 'low_text': 0.15146302969794537, 'link_threshold': 0.6318307720851756}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:04,977] Trial 23 finished with value: 0.0 and parameters: {'gap_mult': 1.2827856065009335, 'canvas_size': 10000, 'mag_ratio': 2.0522093394602043, 'add_margin': 0.33364441087307467, 'text_threshold': 0.4009411598080816, 'low_text': 0.22636549446097454, 'link_threshold': 0.6997776020712903}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:07,408] Trial 24 finished with value: 6.0 and parameters: {'gap_mult': 1.688073858124835, 'canvas_size': 10000, 'mag_ratio': 1.8147929044605347, 'add_margin': 0.41187921882338346, 'text_threshold': 0.48018628231507815, 'low_text': 0.14505741985334714, 'link_threshold': 0.5725158142189293}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:12,225] Trial 25 finished with value: 3.0 and parameters: {'gap_mult': 2.2273244859507426, 'canvas_size': 1800, 'mag_ratio': 2.1619788064541146, 'add_margin': 0.29680817784938923, 'text_threshold': 0.34280209793757394, 'low_text': 0.3598483802527688, 'link_threshold': 0.47532698356188297}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:14,578] Trial 26 finished with value: 2.0 and parameters: {'gap_mult': 1.6266005039888947, 'canvas_size': 7200, 'mag_ratio': 1.8054129677884196, 'add_margin': 0.4967591135107159, 'text_threshold': 0.40062455240630057, 'low_text': 0.27142466964041806, 'link_threshold': 0.6268694818093563}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:17,799] Trial 27 finished with value: 0.0 and parameters: {'gap_mult': 0.8716046775322024, 'canvas_size': 3600, 'mag_ratio': 2.591535568961233, 'add_margin': 0.23398228930290385, 'text_threshold': 0.45887982369469826, 'low_text': 0.4700297698310453, 'link_threshold': 0.40555964970795816}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:20,157] Trial 28 finished with value: 3.0 and parameters: {'gap_mult': 0.12634067763172063, 'canvas_size': 10000, 'mag_ratio': 1.687707077278028, 'add_margin': 0.44168182474903117, 'text_threshold': 0.5678991209026768, 'low_text': 0.19168263433456684, 'link_threshold': 0.4849722942730099}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:22,844] Trial 29 finished with value: 0.0 and parameters: {'gap_mult': 0.917887107858529, 'canvas_size': 3600, 'mag_ratio': 2.982888945913079, 'add_margin': 0.3144487437683528, 'text_threshold': 0.32134529399419554, 'low_text': 0.11131753239257092, 'link_threshold': 0.6478445771500324}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:24,929] Trial 30 finished with value: 6.0 and parameters: {'gap_mult': 1.2354572298871604, 'canvas_size': 1800, 'mag_ratio': 2.192116830092118, 'add_margin': 0.3752636196109105, 'text_threshold': 0.49763505040728695, 'low_text': 0.3099171209105759, 'link_threshold': 0.5630321790923893}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:27,347] Trial 31 finished with value: 0.0 and parameters: {'gap_mult': 1.4152985716317703, 'canvas_size': 10000, 'mag_ratio': 2.271704485180925, 'add_margin': 0.46402968781748494, 'text_threshold': 0.43744132250758155, 'low_text': 0.22150449012133064, 'link_threshold': 0.5866215734802223}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:29,694] Trial 32 finished with value: 3.0 and parameters: {'gap_mult': 1.3470046288290496, 'canvas_size': 10000, 'mag_ratio': 2.019964977098176, 'add_margin': 0.4809199347109301, 'text_threshold': 0.48927782801688746, 'low_text': 0.2061179495820208, 'link_threshold': 0.5576719211378318}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:31,811] Trial 33 finished with value: 3.0 and parameters: {'gap_mult': 0.42628313834266474, 'canvas_size': 10000, 'mag_ratio': 1.5404390532162884, 'add_margin': 0.40748830793442736, 'text_threshold': 0.38476933858540535, 'low_text': 0.1395917836080438, 'link_threshold': 0.6056158927267469}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:34,106] Trial 34 finished with value: 6.0 and parameters: {'gap_mult': 1.5326447367463771, 'canvas_size': 10000, 'mag_ratio': 1.72870248378863, 'add_margin': 0.34528521463794626, 'text_threshold': 0.5150794337111221, 'low_text': 0.24899664426731927, 'link_threshold': 0.6577784494576011}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:46,792] Trial 35 finished with value: 3.0 and parameters: {'gap_mult': 1.8110834294493454, 'canvas_size': 7200, 'mag_ratio': 3.6702375016738, 'add_margin': 0.4364732116125293, 'text_threshold': 0.537895085676295, 'low_text': 0.16136650600797486, 'link_threshold': 0.5402750834526241}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:50,265] Trial 36 finished with value: 6.0 and parameters: {'gap_mult': 1.2219988072354946, 'canvas_size': 10000, 'mag_ratio': 2.482952487867, 'add_margin': 0.26693338583603277, 'text_threshold': 0.4302885444872687, 'low_text': 0.13132228009588398, 'link_threshold': 0.32944012665242317}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:55:52,689] Trial 37 finished with value: 0.0 and parameters: {'gap_mult': 2.38129567347274, 'canvas_size': 1800, 'mag_ratio': 2.8968484899989493, 'add_margin': 0.4686449723543468, 'text_threshold': 0.302028768728002, 'low_text': 0.19115299871272867, 'link_threshold': 0.37876224726940994}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:09,392] Trial 38 finished with value: 6.0 and parameters: {'gap_mult': 2.8763678218532216, 'canvas_size': 10000, 'mag_ratio': 4.438316910484946, 'add_margin': 0.29829477938301685, 'text_threshold': 0.4700875822689006, 'low_text': 0.25353183963236203, 'link_threshold': 0.4213216239998583}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:12,401] Trial 39 finished with value: 2.0 and parameters: {'gap_mult': 0.6026962750957594, 'canvas_size': 3600, 'mag_ratio': 2.0123631514680036, 'add_margin': 0.3923298820411264, 'text_threshold': 0.5656381172012847, 'low_text': 0.6985243561080292, 'link_threshold': 0.44513454191041124}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:15,008] Trial 40 finished with value: 6.0 and parameters: {'gap_mult': 1.552605334791691, 'canvas_size': 1800, 'mag_ratio': 2.1836186583312256, 'add_margin': 0.24118715165087418, 'text_threshold': 0.34225003730198067, 'low_text': 0.30669141039365844, 'link_threshold': 0.29277314219252115}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:19,676] Trial 41 finished with value: 0.0 and parameters: {'gap_mult': 2.032777215476117, 'canvas_size': 1800, 'mag_ratio': 1.9646027862079287, 'add_margin': 0.36009363571123254, 'text_threshold': 0.36392934369845953, 'low_text': 0.22829120356983643, 'link_threshold': 0.5138704932472115}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:21,678] Trial 42 finished with value: 1.0 and parameters: {'gap_mult': 2.176387089985841, 'canvas_size': 1800, 'mag_ratio': 1.7019410486508, 'add_margin': 0.3540410973587066, 'text_threshold': 0.38904691450406964, 'low_text': 0.173755568533145, 'link_threshold': 0.5359395965294611}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:24,049] Trial 43 finished with value: 0.0 and parameters: {'gap_mult': 1.9814160602074264, 'canvas_size': 1800, 'mag_ratio': 2.6618241803684515, 'add_margin': 0.0866096719455687, 'text_threshold': 0.3297646130497309, 'low_text': 0.12249114396162103, 'link_threshold': 0.4813419467114378}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:26,529] Trial 44 finished with value: 6.0 and parameters: {'gap_mult': 2.413259320694561, 'canvas_size': 1800, 'mag_ratio': 1.9177687920847541, 'add_margin': 0.31469920463221435, 'text_threshold': 0.4377968866124756, 'low_text': 0.3696136534062048, 'link_threshold': 0.607201945666187}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:29,283] Trial 45 finished with value: 0.0 and parameters: {'gap_mult': 2.64463349486065, 'canvas_size': 7200, 'mag_ratio': 2.3460275763329173, 'add_margin': 0.39700866313058947, 'text_threshold': 0.3774153417241256, 'low_text': 0.24211527857587653, 'link_threshold': 0.3648129541396672}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:31,494] Trial 46 finished with value: 3.0 and parameters: {'gap_mult': 1.836878721870324, 'canvas_size': 1800, 'mag_ratio': 2.126890360324983, 'add_margin': 0.20726513840245164, 'text_threshold': 0.4137371364867357, 'low_text': 0.3342805619353377, 'link_threshold': 0.3978205666085285}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:33,911] Trial 47 finished with value: 2.0 and parameters: {'gap_mult': 0.9236009105572118, 'canvas_size': 10000, 'mag_ratio': 1.7057803405365435, 'add_margin': 0.36889361538736837, 'text_threshold': 0.35131987552000854, 'low_text': 0.6331189497946297, 'link_threshold': 0.5031830624015114}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:36,036] Trial 48 finished with value: 0.0 and parameters: {'gap_mult': 0.7075348045987095, 'canvas_size': 1800, 'mag_ratio': 1.8754699231214058, 'add_margin': 0.4201108898173849, 'text_threshold': 0.6401314045523575, 'low_text': 0.20134221483850864, 'link_threshold': 0.5473098961171385}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:43,775] Trial 49 finished with value: 6.0 and parameters: {'gap_mult': 1.4055293711987713, 'canvas_size': 10000, 'mag_ratio': 3.4829554961756273, 'add_margin': 0.2727130551864318, 'text_threshold': 0.5107363738699169, 'low_text': 0.2931375550010872, 'link_threshold': 0.5858997098239191}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:46,294] Trial 50 finished with value: 16.0 and parameters: {'gap_mult': 0.28271106449673233, 'canvas_size': 3600, 'mag_ratio': 1.6064784759584878, 'add_margin': 0.49696348828068293, 'text_threshold': 0.5542307215159156, 'low_text': 0.1614448436114824, 'link_threshold': 0.4435283721263239}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:56:54,785] Trial 51 finished with value: 6.0 and parameters: {'gap_mult': 1.6865773792850522, 'canvas_size': 10000, 'mag_ratio': 3.0544204754949122, 'add_margin': 0.1930166327695941, 'text_threshold': 0.6943934752754893, 'low_text': 0.2687102769555533, 'link_threshold': 0.6833448732377796}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:05,363] Trial 52 finished with value: 6.0 and parameters: {'gap_mult': 1.7335815942306727, 'canvas_size': 10000, 'mag_ratio': 4.0263794400950585, 'add_margin': 0.16928223850489543, 'text_threshold': 0.7483832969099119, 'low_text': 0.3418904310684578, 'link_threshold': 0.6450346895704159}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:24,354] Trial 53 finished with value: 9.0 and parameters: {'gap_mult': 2.0730357287645598, 'canvas_size': 10000, 'mag_ratio': 4.9661237759392405, 'add_margin': 0.06628189141235036, 'text_threshold': 0.6993694651671535, 'low_text': 0.39641751411068, 'link_threshold': 0.6913533032142294}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:29,650] Trial 54 finished with value: 6.0 and parameters: {'gap_mult': 1.8378208995218732, 'canvas_size': 10000, 'mag_ratio': 2.8058557292492172, 'add_margin': 0.14877145505589487, 'text_threshold': 0.6067678630149258, 'low_text': 0.28406293177241143, 'link_threshold': 0.6084234792788263}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:36,053] Trial 55 finished with value: 6.0 and parameters: {'gap_mult': 1.6077956791294892, 'canvas_size': 10000, 'mag_ratio': 3.184685723255018, 'add_margin': 0.33362136342078796, 'text_threshold': 0.6586094330040534, 'low_text': 0.47617920380466766, 'link_threshold': 0.6612731611178574}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:39,722] Trial 56 finished with value: 6.0 and parameters: {'gap_mult': 1.140093656057085, 'canvas_size': 10000, 'mag_ratio': 2.5390512016510867, 'add_margin': 0.43015222762309546, 'text_threshold': 0.45677922363281287, 'low_text': 0.22243443589468803, 'link_threshold': 0.6776769331383322}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:42,584] Trial 57 finished with value: 0.0 and parameters: {'gap_mult': 2.2173003288074886, 'canvas_size': 7200, 'mag_ratio': 2.30125078762444, 'add_margin': 0.31399758400455013, 'text_threshold': 0.407354067246686, 'low_text': 0.1741364232105632, 'link_threshold': 0.5703705499828124}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:57:45,367] Trial 58 finished with value: 6.0 and parameters: {'gap_mult': 1.4348361111451478, 'canvas_size': 1800, 'mag_ratio': 4.119267428393518, 'add_margin': 0.3921988549011919, 'text_threshold': 0.6108450546952728, 'low_text': 0.10297918293515232, 'link_threshold': 0.6423078633822412}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:05,731] Trial 59 finished with value: 19.0 and parameters: {'gap_mult': 1.3146190886260487, 'canvas_size': 10000, 'mag_ratio': 4.517561455513468, 'add_margin': 0.46035628899869246, 'text_threshold': 0.4989918282450292, 'low_text': 0.13611074435464954, 'link_threshold': 0.2370550150876778}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:08,652] Trial 60 finished with value: 0.0 and parameters: {'gap_mult': 2.4903957108815717, 'canvas_size': 10000, 'mag_ratio': 1.7991544479501766, 'add_margin': 0.28447853167616255, 'text_threshold': 0.43034949021994956, 'low_text': 0.32262981212166886, 'link_threshold': 0.6261847736969334}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:11,166] Trial 61 finished with value: 0.0 and parameters: {'gap_mult': 1.5420067502330739, 'canvas_size': 10000, 'mag_ratio': 1.6027903475171934, 'add_margin': 0.3483023224854118, 'text_threshold': 0.36393439736200833, 'low_text': 0.10422663391107893, 'link_threshold': 0.6208477423703296}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:13,672] Trial 62 finished with value: 3.0 and parameters: {'gap_mult': 1.9141280029919703, 'canvas_size': 10000, 'mag_ratio': 1.5213430371729078, 'add_margin': 0.3347560723493002, 'text_threshold': 0.3330972928489088, 'low_text': 0.12091536219081386, 'link_threshold': 0.6690028802757306}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:15,964] Trial 63 finished with value: 0.0 and parameters: {'gap_mult': 1.4423427725511269, 'canvas_size': 10000, 'mag_ratio': 1.5108889381954187, 'add_margin': 0.3806898775360643, 'text_threshold': 0.38740713862944387, 'low_text': 0.15382441727496243, 'link_threshold': 0.5866630175683626}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:18,364] Trial 64 finished with value: 6.0 and parameters: {'gap_mult': 1.734875836674064, 'canvas_size': 10000, 'mag_ratio': 1.7948695199875504, 'add_margin': 0.011307090053004093, 'text_threshold': 0.3507411762015381, 'low_text': 0.20246618057597243, 'link_threshold': 0.601242330820969}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:20,854] Trial 65 finished with value: 2.0 and parameters: {'gap_mult': 1.1757405169069743, 'canvas_size': 10000, 'mag_ratio': 2.086165783438007, 'add_margin': 0.2456882382996693, 'text_threshold': 0.4741634337377318, 'low_text': 0.2684493145468628, 'link_threshold': 0.6333830867101429}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:23,446] Trial 66 finished with value: 0.0 and parameters: {'gap_mult': 1.0583138290250695, 'canvas_size': 3600, 'mag_ratio': 1.9833204433007152, 'add_margin': 0.4078906425246266, 'text_threshold': 0.37507193446364606, 'low_text': 0.17773740261098023, 'link_threshold': 0.6550365183841861}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:25,700] Trial 67 finished with value: 0.0 and parameters: {'gap_mult': 2.1113828186904646, 'canvas_size': 1800, 'mag_ratio': 1.627737129670728, 'add_margin': 0.31184312655078883, 'text_threshold': 0.5238607673015194, 'low_text': 0.24788455119303154, 'link_threshold': 0.6997993963347023}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:28,419] Trial 68 finished with value: 0.0 and parameters: {'gap_mult': 0.9773717590997882, 'canvas_size': 10000, 'mag_ratio': 2.4010170219452776, 'add_margin': 0.21829639411230875, 'text_threshold': 0.30988261906742653, 'low_text': 0.1398668395141619, 'link_threshold': 0.5298214659650317}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:31,028] Trial 69 finished with value: 0.0 and parameters: {'gap_mult': 1.619967386716393, 'canvas_size': 7200, 'mag_ratio': 1.8845116539294495, 'add_margin': 0.37112199407447244, 'text_threshold': 0.42276720376960203, 'low_text': 0.21533980924102802, 'link_threshold': 0.5734968318657384}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:33,749] Trial 70 finished with value: 3.0 and parameters: {'gap_mult': 2.751326216417243, 'canvas_size': 10000, 'mag_ratio': 2.2278059789258613, 'add_margin': 0.4494222828148234, 'text_threshold': 0.4452982706384931, 'low_text': 0.11598893420937323, 'link_threshold': 0.49921300401957514}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:38,611] Trial 71 finished with value: 0.0 and parameters: {'gap_mult': 1.2993737247556747, 'canvas_size': 10000, 'mag_ratio': 2.043840714353784, 'add_margin': 0.3350083247295932, 'text_threshold': 0.35748588299055994, 'low_text': 0.2265551804542083, 'link_threshold': 0.6748472701551019}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:40,711] Trial 72 finished with value: 0.0 and parameters: {'gap_mult': 1.487951326924774, 'canvas_size': 10000, 'mag_ratio': 1.7554868354126691, 'add_margin': 0.28706797466207484, 'text_threshold': 0.4008671166219604, 'low_text': 0.23519385817676244, 'link_threshold': 0.6174831773618225}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:43,253] Trial 73 finished with value: 0.0 and parameters: {'gap_mult': 1.287024339527743, 'canvas_size': 10000, 'mag_ratio': 1.6619019790647513, 'add_margin': 0.35253473628188264, 'text_threshold': 0.3995679960639146, 'low_text': 0.18665460608037232, 'link_threshold': 0.6997429613770489}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:49,743] Trial 74 finished with value: 0.0 and parameters: {'gap_mult': 0.7917739839237641, 'canvas_size': 1800, 'mag_ratio': 3.691191180464256, 'add_margin': 0.256227708458774, 'text_threshold': 0.588628250867445, 'low_text': 0.15526564029661177, 'link_threshold': 0.6388558339492125}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:52,332] Trial 75 finished with value: 6.0 and parameters: {'gap_mult': 1.3836209109248103, 'canvas_size': 10000, 'mag_ratio': 1.9303637543024748, 'add_margin': 0.3266009581459893, 'text_threshold': 0.32642898614871146, 'low_text': 0.26056379346676267, 'link_threshold': 0.5581534261963809}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:54,961] Trial 76 finished with value: 2.0 and parameters: {'gap_mult': 1.2096224319499855, 'canvas_size': 1800, 'mag_ratio': 2.1238326363224926, 'add_margin': 0.3017380262152115, 'text_threshold': 0.37394001822801004, 'low_text': 0.28678593358242277, 'link_threshold': 0.6599286178042858}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:58:57,430] Trial 77 finished with value: 6.0 and parameters: {'gap_mult': 1.7802378509775458, 'canvas_size': 10000, 'mag_ratio': 1.8816946343259815, 'add_margin': 0.36388919602950753, 'text_threshold': 0.34090268515882893, 'low_text': 0.5479980945347005, 'link_threshold': 0.3892473209789098}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:00,036] Trial 78 finished with value: 6.0 and parameters: {'gap_mult': 1.6665504567091305, 'canvas_size': 3600, 'mag_ratio': 2.054080103730055, 'add_margin': 0.3410899908917761, 'text_threshold': 0.5498926207140523, 'low_text': 0.2100280220064789, 'link_threshold': 0.35186590062085316}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:02,646] Trial 79 finished with value: 6.0 and parameters: {'gap_mult': 2.2858125900796873, 'canvas_size': 10000, 'mag_ratio': 2.598654169175222, 'add_margin': 0.1096485806039654, 'text_threshold': 0.39632565711047857, 'low_text': 0.13232194942047554, 'link_threshold': 0.46478059695144425}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:04,819] Trial 80 finished with value: 6.0 and parameters: {'gap_mult': 1.9478604127774308, 'canvas_size': 1800, 'mag_ratio': 1.7354733093971937, 'add_margin': 0.3808447412146811, 'text_threshold': 0.48479170584830067, 'low_text': 0.3556634621163809, 'link_threshold': 0.5922711205439385}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:07,509] Trial 81 finished with value: 0.0 and parameters: {'gap_mult': 0.23671399010645872, 'canvas_size': 3600, 'mag_ratio': 2.2341864972807914, 'add_margin': 0.1768337152281278, 'text_threshold': 0.5006948515280124, 'low_text': 0.43160854679965444, 'link_threshold': 0.44315830511907794}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:12,406] Trial 82 finished with value: 0.0 and parameters: {'gap_mult': 0.48961947690267943, 'canvas_size': 3600, 'mag_ratio': 2.4105107256619434, 'add_margin': 0.22217208323937157, 'text_threshold': 0.4656720325400188, 'low_text': 0.4844647385891675, 'link_threshold': 0.4065883472444202}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:15,689] Trial 83 finished with value: 3.0 and parameters: {'gap_mult': 0.7997340915545504, 'canvas_size': 3600, 'mag_ratio': 3.329512876745448, 'add_margin': 0.47893630067320886, 'text_threshold': 0.42471000078598803, 'low_text': 0.4466149722453414, 'link_threshold': 0.3563209303791829}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:19,726] Trial 84 finished with value: 3.0 and parameters: {'gap_mult': 1.486979265948101, 'canvas_size': 3600, 'mag_ratio': 3.0996875437037343, 'add_margin': 0.1406713123567832, 'text_threshold': 0.41231281178387974, 'low_text': 0.3988143194327536, 'link_threshold': 0.6880342966933964}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:22,964] Trial 85 finished with value: 6.0 and parameters: {'gap_mult': 1.0932715433629328, 'canvas_size': 10000, 'mag_ratio': 2.7965070007470225, 'add_margin': 0.3037215646374164, 'text_threshold': 0.46391666668681963, 'low_text': 0.5906737765487706, 'link_threshold': 0.43021720939102975}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:25,413] Trial 86 finished with value: 6.0 and parameters: {'gap_mult': 1.5809283981134732, 'canvas_size': 1800, 'mag_ratio': 2.903098445629802, 'add_margin': 0.323204629547763, 'text_threshold': 0.4475691348897395, 'low_text': 0.4917204876920026, 'link_threshold': 0.409723948089749}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:28,208] Trial 87 finished with value: 7.0 and parameters: {'gap_mult': 1.0241737060926785, 'canvas_size': 7200, 'mag_ratio': 2.170019590734165, 'add_margin': 0.39982023963456487, 'text_threshold': 0.38733220577207395, 'low_text': 0.5104734664626996, 'link_threshold': 0.4278163892556177}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:30,772] Trial 88 finished with value: 6.0 and parameters: {'gap_mult': 1.268613828376473, 'canvas_size': 10000, 'mag_ratio': 2.501792093226784, 'add_margin': 0.19746104473498233, 'text_threshold': 0.533720206705651, 'low_text': 0.3001198513836001, 'link_threshold': 0.547632988263816}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:32,882] Trial 89 finished with value: 3.0 and parameters: {'gap_mult': 1.3478705357481844, 'canvas_size': 3600, 'mag_ratio': 1.5703952619051842, 'add_margin': 0.2383571152444115, 'text_threshold': 0.4911376231475963, 'low_text': 0.3204541870778804, 'link_threshold': 0.6127908600439828}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:35,365] Trial 90 finished with value: 0.0 and parameters: {'gap_mult': 1.490753514396979, 'canvas_size': 10000, 'mag_ratio': 2.6871785603774363, 'add_margin': 0.2705280840013191, 'text_threshold': 0.35332971931310364, 'low_text': 0.19192155927759122, 'link_threshold': 0.650409989571328}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:37,984] Trial 91 finished with value: 18.0 and parameters: {'gap_mult': 0.6059944269888327, 'canvas_size': 3600, 'mag_ratio': 3.057057959857495, 'add_margin': 0.35778874256558385, 'text_threshold': 0.3212941201056074, 'low_text': 0.1174286089721853, 'link_threshold': 0.6696455061067778}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:40,618] Trial 92 finished with value: 6.0 and parameters: {'gap_mult': 0.3775662373815719, 'canvas_size': 3600, 'mag_ratio': 2.925896099570541, 'add_margin': 0.34378187458078385, 'text_threshold': 0.30183448603810026, 'low_text': 0.16525888651370374, 'link_threshold': 0.6300161950690972}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:43,262] Trial 93 finished with value: 0.0 and parameters: {'gap_mult': 0.8521897751266599, 'canvas_size': 3600, 'mag_ratio': 3.4865557187596905, 'add_margin': 0.2894311604971045, 'text_threshold': 0.3717456107531875, 'low_text': 0.11135697155385867, 'link_threshold': 0.601458513802612}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:47,807] Trial 94 finished with value: 0.0 and parameters: {'gap_mult': 0.6891387968747075, 'canvas_size': 3600, 'mag_ratio': 2.3574090634090874, 'add_margin': 0.3717055471560436, 'text_threshold': 0.5113421563825482, 'low_text': 0.1454440500741882, 'link_threshold': 0.5800254192403381}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:50,163] Trial 95 finished with value: 0.0 and parameters: {'gap_mult': 0.9404696206232311, 'canvas_size': 10000, 'mag_ratio': 2.5879800085298745, 'add_margin': 0.3178008713854836, 'text_threshold': 0.3188847847129784, 'low_text': 0.10302789858767883, 'link_threshold': 0.6469583229932883}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:52,175] Trial 96 finished with value: 2.0 and parameters: {'gap_mult': 1.1576708263622413, 'canvas_size': 1800, 'mag_ratio': 3.16407741524424, 'add_margin': 0.32888131722555225, 'text_threshold': 0.3388924348605037, 'low_text': 0.24394707724107206, 'link_threshold': 0.6660346756545124}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:54,166] Trial 97 finished with value: 6.0 and parameters: {'gap_mult': 1.3644247440046287, 'canvas_size': 10000, 'mag_ratio': 1.8352085571892742, 'add_margin': 0.42619636062008526, 'text_threshold': 0.3800261620480223, 'low_text': 0.1296581027202471, 'link_threshold': 0.6787481334559138}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:56,295] Trial 98 finished with value: 0.0 and parameters: {'gap_mult': 0.5284987720929559, 'canvas_size': 10000, 'mag_ratio': 1.967725610612323, 'add_margin': 0.3076465681849014, 'text_threshold': 0.3605602907368438, 'low_text': 0.14851815752665998, 'link_threshold': 0.6373355528450428}. Best is trial 7 with value: 0.0.\n", - "[I 2025-09-25 20:59:58,253] Trial 99 finished with value: 0.0 and parameters: {'gap_mult': 1.8840728444738277, 'canvas_size': 1800, 'mag_ratio': 3.44988791521599, 'add_margin': 0.17183901821211403, 'text_threshold': 0.4381693314913302, 'low_text': 0.18140874209964664, 'link_threshold': 0.4916185895177267}. Best is trial 7 with value: 0.0.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Лучшие параметры:\n", - "{'gap_mult': 0.1148899697656891, 'canvas_size': 1800, 'mag_ratio': 2.0909813860745077, 'add_margin': 0.38880953861561235, 'text_threshold': 0.5046870997550761, 'low_text': 0.2758043304152779, 'link_threshold': 0.4121455607297143}\n", - "Лучшее расстояние: 0.0\n" - ] - } - ], - "source": [ - "import optuna \n", - "import pandas as pd\n", - "from pathlib import Path\n", - "import itertools\n", - "import collections\n", - "\n", - "# Ваша реализация расстояния Левенштейна\n", - "def levenshtein_distance(string1, string2):\n", - " \"\"\"\n", - " >>> levenshtein_distance('AATZ', 'AAAZ')\n", - " 1\n", - " >>> levenshtein_distance('AATZZZ', 'AAAZ')\n", - " 3\n", - " \"\"\"\n", - " distance = 0\n", - " if len(string1) < len(string2):\n", - " string1, string2 = string2, string1\n", - " \n", - " # Заменяем itertools.izip_longest на zip_longest для Python 3\n", - " from itertools import zip_longest\n", - " for i, v in zip_longest(string1, string2, fillvalue='-'):\n", - " if i != v:\n", - " distance += 1\n", - " return distance\n", - "\n", - "# Определите ROOT_DIR (добавьте ваш путь)\n", - "ROOT_DIR = Path('/home/lizardapn/Hack_digital/hack_digital_transformation')\n", - "\n", - "data = pd.read_csv(filepath_or_buffer=ROOT_DIR / 'data/processed_data/merged_data.csv')\n", - "\n", - "def objective(trial):\n", - " params = {\n", - " 'gap_mult': trial.suggest_float('gap_mult', 0.1, 3.0),\n", - " 'canvas_size': trial.suggest_categorical('canvas_size', [1800, 3600, 7200, 10000]),\n", - " 'mag_ratio': trial.suggest_float('mag_ratio', 1.5, 5.0),\n", - " 'add_margin': trial.suggest_float('add_margin', 0.01, 0.5),\n", - " 'text_threshold': trial.suggest_float('text_threshold', 0.3, 0.75), # Исправлено: text_treshold -> text_threshold\n", - " 'low_text': trial.suggest_float('low_text', 0.1, 0.7),\n", - " 'link_threshold': trial.suggest_float('link_threshold', 0.15, 0.7),\n", - " 'langs': ['en'], \n", - " 'gpu': True,\n", - " }\n", - " \n", - " ocr = OverlayOCR(**params)\n", - "\n", - " IMG_PATH = ROOT_DIR / 'data/raw_data/data/metadata/INC/united_image/0a0ee2fb-b7ad-4430-97d7-281e2c293041.jpg'\n", - "\n", - " # Получаем реальные ID для этого изображения\n", - " real_ids = data[data['camera_id'] == '0a0ee2fb-b7ad-4430-97d7-281e2c293041.jpg'].filename.values\n", - " \n", - " # Распознаем текст с текущими параметрами\n", - " final, norm, joined, conf, roi_name = ocr.run_on_image(str(IMG_PATH))\n", - " \n", - " # Вычисляем расстояния до всех реальных ID\n", - " distances = []\n", - " for real_id in real_ids:\n", - " distance = levenshtein_distance(str(real_id), final)\n", - " distances.append(distance)\n", - " \n", - " # Находим минимальное расстояние (наиболее близкий ID)\n", - " if distances:\n", - " min_distance = min(distances)\n", - " else:\n", - " min_distance = float('inf') # Если нет реальных ID для сравнения\n", - " \n", - " return min_distance\n", - "\n", - "# Создаем и запускаем исследование\n", - "study = optuna.create_study(direction='minimize')\n", - "study.optimize(objective, n_trials=100) # Можно указать количество trials\n", - "\n", - "# Выводим лучшие параметры\n", - "print(\"Лучшие параметры:\")\n", - "print(study.best_params)\n", - "print(f\"Лучшее расстояние: {study.best_value}\")" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "6f887d35", - "metadata": {}, - "outputs": [], - "source": [ - "best_params = study.best_params\n", - "\n", - "best_params.update(\n", - " langs=['en'], \n", - " gpu=True,\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "a549736d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'gap_mult': 0.1148899697656891,\n", - " 'canvas_size': 1800,\n", - " 'mag_ratio': 2.0909813860745077,\n", - " 'add_margin': 0.38880953861561235,\n", - " 'text_threshold': 0.5046870997550761,\n", - " 'low_text': 0.2758043304152779,\n", - " 'link_threshold': 0.4121455607297143,\n", - " 'langs': ['en'],\n", - " 'gpu': True}" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "best_params" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "id": "e0b6bb75", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Best ROI: left_bottom | conf=0.57\n", - "joined: DUN_Ka_Vao_2_50151\n", - "norm : DUN_Ka_Vao_2_50151\n", - "final : DUN_Ka_Vao_2_50151\n" - ] - } - ], - "source": [ - "IMG = r'/home/lizardapn/Hack_digital/hack_digital_transformation/data/raw_data/data/metadata/INC/united_image/ffeeecc1-407c-4976-a625-280e8c987f66.jpg'\n", - "\n", - "ocr = OverlayOCR(**best_params)\n", - "\n", - "final, norm, joined, conf, roi_name = ocr.run_on_image(IMG)\n", - "print(f\"Best ROI: {roi_name} | conf={conf:.2f}\")\n", - "print(\"joined:\", joined)\n", - "print(\"norm :\", norm)\n", - "print(\"final :\", final)\n" - ] } ], "metadata": { diff --git a/notebooks/1_data_exploration/1_3_download_moscow.ipynb b/notebooks/1_data_exploration/1_3_download_moscow.ipynb new file mode 100644 index 0000000..163f3d5 --- /dev/null +++ b/notebooks/1_data_exploration/1_3_download_moscow.ipynb @@ -0,0 +1,2961 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2f11dabb", + "metadata": {}, + "source": [ + "# Подготовка ноутбука " + ] + }, + { + "cell_type": "markdown", + "id": "85f07fbd", + "metadata": {}, + "source": [ + "## Пробрасываем magic methods" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "97feaebc", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "%reload_ext autoreload" + ] + }, + { + "cell_type": "markdown", + "id": "a5324521", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cd10fe31", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import numpy as np \n", + "from data.prepare_data import PrepareData\n", + "from dotenv import load_dotenv\n", + "import os \n", + "from pathlib import Path\n", + "from warnings import filterwarnings \n", + "import torch \n", + "import torchvision\n", + "from torch.utils.data import DataLoader\n", + "from IPython.display import display\n", + "import pytesseract\n", + "import shutil\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image\n", + "import cv2\n", + "import requests\n", + "import json\n", + "import os\n", + "from datetime import datetime\n", + "import csv\n", + "\n", + "\n", + "import pandas as pd \n", + "import numpy as np \n", + "from data.prepare_data import PrepareData\n", + "from dotenv import load_dotenv\n", + "import os \n", + "from pathlib import Path\n", + "from warnings import filterwarnings \n", + "import torch \n", + "import torchvision\n", + "from torch.utils.data import DataLoader\n", + "from IPython.display import display\n", + "import pytesseract\n", + "import shutil\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image\n", + "import cv2\n", + "import requests\n", + "import json\n", + "import os\n", + "from datetime import datetime\n", + "import csv\n", + "import time\n", + "from concurrent.futures import ThreadPoolExecutor, as_completed\n", + "from threading import Lock\n", + "import hashlib\n", + "from utils.s3_optimize import S3Manager\n", + "import logging\n", + "\n", + "from geo.download_images import MapillaryS3Client" + ] + }, + { + "cell_type": "markdown", + "id": "8f5e2582", + "metadata": {}, + "source": [ + "## Нужные переменные " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e7ef1558", + "metadata": {}, + "outputs": [], + "source": [ + "# Настройка логирования\n", + "logging.basicConfig(level=logging.INFO)\n", + "logger = logging.getLogger(__name__)\n", + "ROOT_DIR = Path('../../')\n", + "load_dotenv()\n", + "filterwarnings(action='ignore')" + ] + }, + { + "cell_type": "markdown", + "id": "6dee36be", + "metadata": {}, + "source": [ + "# Загрузка датафрейма" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d490117d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:__main__:=== Вариант 1: Автоматическое разбиение большого bbox ===\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:geo.download_images:Автоматически рассчитан размер сетки: 10x10\n", + "INFO:geo.download_images:Основной bbox разбит на 100 частей\n", + "INFO:geo.download_images: Часть 1: [37.366723, 55.57917, 37.4141811, 55.6120466]\n", + "INFO:geo.download_images: Часть 2: [37.366723, 55.6120466, 37.4141811, 55.6449232]\n", + "INFO:geo.download_images: Часть 3: [37.366723, 55.6449232, 37.4141811, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 4: [37.366723, 55.677799799999995, 37.4141811, 55.7106764]\n", + "INFO:geo.download_images: Часть 5: [37.366723, 55.7106764, 37.4141811, 55.743553]\n", + "INFO:geo.download_images: Часть 6: [37.366723, 55.743553, 37.4141811, 55.7764296]\n", + "INFO:geo.download_images: Часть 7: [37.366723, 55.7764296, 37.4141811, 55.8093062]\n", + "INFO:geo.download_images: Часть 8: [37.366723, 55.8093062, 37.4141811, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 9: [37.366723, 55.842182799999996, 37.4141811, 55.8750594]\n", + "INFO:geo.download_images: Часть 10: [37.366723, 55.8750594, 37.4141811, 55.907936]\n", + "INFO:geo.download_images: Часть 11: [37.4141811, 55.57917, 37.4616392, 55.6120466]\n", + "INFO:geo.download_images: Часть 12: [37.4141811, 55.6120466, 37.4616392, 55.6449232]\n", + "INFO:geo.download_images: Часть 13: [37.4141811, 55.6449232, 37.4616392, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 14: [37.4141811, 55.677799799999995, 37.4616392, 55.7106764]\n", + "INFO:geo.download_images: Часть 15: [37.4141811, 55.7106764, 37.4616392, 55.743553]\n", + "INFO:geo.download_images: Часть 16: [37.4141811, 55.743553, 37.4616392, 55.7764296]\n", + "INFO:geo.download_images: Часть 17: [37.4141811, 55.7764296, 37.4616392, 55.8093062]\n", + "INFO:geo.download_images: Часть 18: [37.4141811, 55.8093062, 37.4616392, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 19: [37.4141811, 55.842182799999996, 37.4616392, 55.8750594]\n", + "INFO:geo.download_images: Часть 20: [37.4141811, 55.8750594, 37.4616392, 55.907936]\n", + "INFO:geo.download_images: Часть 21: [37.4616392, 55.57917, 37.5090973, 55.6120466]\n", + "INFO:geo.download_images: Часть 22: [37.4616392, 55.6120466, 37.5090973, 55.6449232]\n", + "INFO:geo.download_images: Часть 23: [37.4616392, 55.6449232, 37.5090973, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 24: [37.4616392, 55.677799799999995, 37.5090973, 55.7106764]\n", + "INFO:geo.download_images: Часть 25: [37.4616392, 55.7106764, 37.5090973, 55.743553]\n", + "INFO:geo.download_images: Часть 26: [37.4616392, 55.743553, 37.5090973, 55.7764296]\n", + "INFO:geo.download_images: Часть 27: [37.4616392, 55.7764296, 37.5090973, 55.8093062]\n", + "INFO:geo.download_images: Часть 28: [37.4616392, 55.8093062, 37.5090973, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 29: [37.4616392, 55.842182799999996, 37.5090973, 55.8750594]\n", + "INFO:geo.download_images: Часть 30: [37.4616392, 55.8750594, 37.5090973, 55.907936]\n", + "INFO:geo.download_images: Часть 31: [37.5090973, 55.57917, 37.5565554, 55.6120466]\n", + "INFO:geo.download_images: Часть 32: [37.5090973, 55.6120466, 37.5565554, 55.6449232]\n", + "INFO:geo.download_images: Часть 33: [37.5090973, 55.6449232, 37.5565554, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 34: [37.5090973, 55.677799799999995, 37.5565554, 55.7106764]\n", + "INFO:geo.download_images: Часть 35: [37.5090973, 55.7106764, 37.5565554, 55.743553]\n", + "INFO:geo.download_images: Часть 36: [37.5090973, 55.743553, 37.5565554, 55.7764296]\n", + "INFO:geo.download_images: Часть 37: [37.5090973, 55.7764296, 37.5565554, 55.8093062]\n", + "INFO:geo.download_images: Часть 38: [37.5090973, 55.8093062, 37.5565554, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 39: [37.5090973, 55.842182799999996, 37.5565554, 55.8750594]\n", + "INFO:geo.download_images: Часть 40: [37.5090973, 55.8750594, 37.5565554, 55.907936]\n", + "INFO:geo.download_images: Часть 41: [37.5565554, 55.57917, 37.6040135, 55.6120466]\n", + "INFO:geo.download_images: Часть 42: [37.5565554, 55.6120466, 37.6040135, 55.6449232]\n", + "INFO:geo.download_images: Часть 43: [37.5565554, 55.6449232, 37.6040135, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 44: [37.5565554, 55.677799799999995, 37.6040135, 55.7106764]\n", + "INFO:geo.download_images: Часть 45: [37.5565554, 55.7106764, 37.6040135, 55.743553]\n", + "INFO:geo.download_images: Часть 46: [37.5565554, 55.743553, 37.6040135, 55.7764296]\n", + "INFO:geo.download_images: Часть 47: [37.5565554, 55.7764296, 37.6040135, 55.8093062]\n", + "INFO:geo.download_images: Часть 48: [37.5565554, 55.8093062, 37.6040135, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 49: [37.5565554, 55.842182799999996, 37.6040135, 55.8750594]\n", + "INFO:geo.download_images: Часть 50: [37.5565554, 55.8750594, 37.6040135, 55.907936]\n", + "INFO:geo.download_images: Часть 51: [37.6040135, 55.57917, 37.6514716, 55.6120466]\n", + "INFO:geo.download_images: Часть 52: [37.6040135, 55.6120466, 37.6514716, 55.6449232]\n", + "INFO:geo.download_images: Часть 53: [37.6040135, 55.6449232, 37.6514716, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 54: [37.6040135, 55.677799799999995, 37.6514716, 55.7106764]\n", + "INFO:geo.download_images: Часть 55: [37.6040135, 55.7106764, 37.6514716, 55.743553]\n", + "INFO:geo.download_images: Часть 56: [37.6040135, 55.743553, 37.6514716, 55.7764296]\n", + "INFO:geo.download_images: Часть 57: [37.6040135, 55.7764296, 37.6514716, 55.8093062]\n", + "INFO:geo.download_images: Часть 58: [37.6040135, 55.8093062, 37.6514716, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 59: [37.6040135, 55.842182799999996, 37.6514716, 55.8750594]\n", + "INFO:geo.download_images: Часть 60: [37.6040135, 55.8750594, 37.6514716, 55.907936]\n", + "INFO:geo.download_images: Часть 61: [37.6514716, 55.57917, 37.6989297, 55.6120466]\n", + "INFO:geo.download_images: Часть 62: [37.6514716, 55.6120466, 37.6989297, 55.6449232]\n", + "INFO:geo.download_images: Часть 63: [37.6514716, 55.6449232, 37.6989297, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 64: [37.6514716, 55.677799799999995, 37.6989297, 55.7106764]\n", + "INFO:geo.download_images: Часть 65: [37.6514716, 55.7106764, 37.6989297, 55.743553]\n", + "INFO:geo.download_images: Часть 66: [37.6514716, 55.743553, 37.6989297, 55.7764296]\n", + "INFO:geo.download_images: Часть 67: [37.6514716, 55.7764296, 37.6989297, 55.8093062]\n", + "INFO:geo.download_images: Часть 68: [37.6514716, 55.8093062, 37.6989297, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 69: [37.6514716, 55.842182799999996, 37.6989297, 55.8750594]\n", + "INFO:geo.download_images: Часть 70: [37.6514716, 55.8750594, 37.6989297, 55.907936]\n", + "INFO:geo.download_images: Часть 71: [37.6989297, 55.57917, 37.7463878, 55.6120466]\n", + "INFO:geo.download_images: Часть 72: [37.6989297, 55.6120466, 37.7463878, 55.6449232]\n", + "INFO:geo.download_images: Часть 73: [37.6989297, 55.6449232, 37.7463878, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 74: [37.6989297, 55.677799799999995, 37.7463878, 55.7106764]\n", + "INFO:geo.download_images: Часть 75: [37.6989297, 55.7106764, 37.7463878, 55.743553]\n", + "INFO:geo.download_images: Часть 76: [37.6989297, 55.743553, 37.7463878, 55.7764296]\n", + "INFO:geo.download_images: Часть 77: [37.6989297, 55.7764296, 37.7463878, 55.8093062]\n", + "INFO:geo.download_images: Часть 78: [37.6989297, 55.8093062, 37.7463878, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 79: [37.6989297, 55.842182799999996, 37.7463878, 55.8750594]\n", + "INFO:geo.download_images: Часть 80: [37.6989297, 55.8750594, 37.7463878, 55.907936]\n", + "INFO:geo.download_images: Часть 81: [37.7463878, 55.57917, 37.7938459, 55.6120466]\n", + "INFO:geo.download_images: Часть 82: [37.7463878, 55.6120466, 37.7938459, 55.6449232]\n", + "INFO:geo.download_images: Часть 83: [37.7463878, 55.6449232, 37.7938459, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 84: [37.7463878, 55.677799799999995, 37.7938459, 55.7106764]\n", + "INFO:geo.download_images: Часть 85: [37.7463878, 55.7106764, 37.7938459, 55.743553]\n", + "INFO:geo.download_images: Часть 86: [37.7463878, 55.743553, 37.7938459, 55.7764296]\n", + "INFO:geo.download_images: Часть 87: [37.7463878, 55.7764296, 37.7938459, 55.8093062]\n", + "INFO:geo.download_images: Часть 88: [37.7463878, 55.8093062, 37.7938459, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 89: [37.7463878, 55.842182799999996, 37.7938459, 55.8750594]\n", + "INFO:geo.download_images: Часть 90: [37.7463878, 55.8750594, 37.7938459, 55.907936]\n", + "INFO:geo.download_images: Часть 91: [37.7938459, 55.57917, 37.841304, 55.6120466]\n", + "INFO:geo.download_images: Часть 92: [37.7938459, 55.6120466, 37.841304, 55.6449232]\n", + "INFO:geo.download_images: Часть 93: [37.7938459, 55.6449232, 37.841304, 55.677799799999995]\n", + "INFO:geo.download_images: Часть 94: [37.7938459, 55.677799799999995, 37.841304, 55.7106764]\n", + "INFO:geo.download_images: Часть 95: [37.7938459, 55.7106764, 37.841304, 55.743553]\n", + "INFO:geo.download_images: Часть 96: [37.7938459, 55.743553, 37.841304, 55.7764296]\n", + "INFO:geo.download_images: Часть 97: [37.7938459, 55.7764296, 37.841304, 55.8093062]\n", + "INFO:geo.download_images: Часть 98: [37.7938459, 55.8093062, 37.841304, 55.842182799999996]\n", + "INFO:geo.download_images: Часть 99: [37.7938459, 55.842182799999996, 37.841304, 55.8750594]\n", + "INFO:geo.download_images: Часть 100: [37.7938459, 55.8750594, 37.841304, 55.907936]\n", + "INFO:geo.download_images:Начинаем обработку 100 bbox регионов...\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 1/100: [37.366723, 55.57917, 37.4141811, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 2/100: [37.366723, 55.6120466, 37.4141811, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 3/100: [37.366723, 55.7106764, 37.4141811, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 4/100: [37.366723, 55.743553, 37.4141811, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 5/100: [37.366723, 55.8093062, 37.4141811, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 6/100: [37.366723, 55.677799799999995, 37.4141811, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 7/100: [37.366723, 55.7764296, 37.4141811, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 8/100: [37.366723, 55.6449232, 37.4141811, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 9/100: [37.366723, 55.842182799999996, 37.4141811, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 10/100: [37.4141811, 55.6120466, 37.4616392, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 11/100: [37.4141811, 55.6449232, 37.4616392, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 12/100: [37.4141811, 55.57917, 37.4616392, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 13/100: [37.366723, 55.8750594, 37.4141811, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Используются кэшированные данные\n", + "INFO:geo.download_images:Обработан bbox 14/100: [37.4141811, 55.677799799999995, 37.4616392, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 15/100: [37.4141811, 55.7106764, 37.4616392, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 16/100: [37.4141811, 55.743553, 37.4616392, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 17/100: [37.4141811, 55.7764296, 37.4616392, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 18/100: [37.4141811, 55.842182799999996, 37.4616392, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 19/100: [37.4141811, 55.8750594, 37.4616392, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 20/100: [37.4141811, 55.8093062, 37.4616392, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 21/100: [37.4616392, 55.57917, 37.5090973, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 22/100: [37.4616392, 55.6120466, 37.5090973, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 23/100: [37.4616392, 55.6449232, 37.5090973, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 24/100: [37.4616392, 55.677799799999995, 37.5090973, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 25/100: [37.4616392, 55.7106764, 37.5090973, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 26/100: [37.4616392, 55.743553, 37.5090973, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 27/100: [37.4616392, 55.7764296, 37.5090973, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 28/100: [37.4616392, 55.8093062, 37.5090973, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 29/100: [37.4616392, 55.842182799999996, 37.5090973, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 30/100: [37.4616392, 55.8750594, 37.5090973, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 31/100: [37.5090973, 55.57917, 37.5565554, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 32/100: [37.5090973, 55.6449232, 37.5565554, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 33/100: [37.5090973, 55.6120466, 37.5565554, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 34/100: [37.5090973, 55.677799799999995, 37.5565554, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 35/100: [37.5090973, 55.7106764, 37.5565554, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 36/100: [37.5090973, 55.743553, 37.5565554, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 37/100: [37.5090973, 55.7764296, 37.5565554, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 38/100: [37.5090973, 55.8093062, 37.5565554, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 39/100: [37.5090973, 55.842182799999996, 37.5565554, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 40/100: [37.5090973, 55.8750594, 37.5565554, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 41/100: [37.5565554, 55.57917, 37.6040135, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 42/100: [37.5565554, 55.6120466, 37.6040135, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 43/100: [37.5565554, 55.6449232, 37.6040135, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 44/100: [37.5565554, 55.677799799999995, 37.6040135, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 45/100: [37.5565554, 55.7106764, 37.6040135, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 46/100: [37.5565554, 55.743553, 37.6040135, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 47/100: [37.5565554, 55.7764296, 37.6040135, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 48/100: [37.5565554, 55.8093062, 37.6040135, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 49/100: [37.5565554, 55.842182799999996, 37.6040135, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 50/100: [37.5565554, 55.8750594, 37.6040135, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 51/100: [37.6040135, 55.6120466, 37.6514716, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 52/100: [37.6040135, 55.57917, 37.6514716, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 53/100: [37.6040135, 55.6449232, 37.6514716, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 54/100: [37.6040135, 55.677799799999995, 37.6514716, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 55/100: [37.6040135, 55.7106764, 37.6514716, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 56/100: [37.6040135, 55.743553, 37.6514716, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 57/100: [37.6040135, 55.7764296, 37.6514716, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 58/100: [37.6040135, 55.8093062, 37.6514716, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 59/100: [37.6040135, 55.842182799999996, 37.6514716, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 60/100: [37.6040135, 55.8750594, 37.6514716, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 61/100: [37.6514716, 55.57917, 37.6989297, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 62/100: [37.6514716, 55.6120466, 37.6989297, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 63/100: [37.6514716, 55.6449232, 37.6989297, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 64/100: [37.6514716, 55.677799799999995, 37.6989297, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 65/100: [37.6514716, 55.7106764, 37.6989297, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 66/100: [37.6514716, 55.743553, 37.6989297, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 67/100: [37.6514716, 55.7764296, 37.6989297, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 68/100: [37.6514716, 55.8093062, 37.6989297, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 69/100: [37.6514716, 55.842182799999996, 37.6989297, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 70/100: [37.6514716, 55.8750594, 37.6989297, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 71/100: [37.6989297, 55.6120466, 37.7463878, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 72/100: [37.6989297, 55.57917, 37.7463878, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 73/100: [37.6989297, 55.6449232, 37.7463878, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 74/100: [37.6989297, 55.677799799999995, 37.7463878, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 75/100: [37.6989297, 55.7106764, 37.7463878, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 76/100: [37.6989297, 55.743553, 37.7463878, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 77/100: [37.6989297, 55.7764296, 37.7463878, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 78/100: [37.6989297, 55.8093062, 37.7463878, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 79/100: [37.6989297, 55.842182799999996, 37.7463878, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 80/100: [37.6989297, 55.8750594, 37.7463878, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 81/100: [37.7463878, 55.57917, 37.7938459, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 82/100: [37.7463878, 55.6120466, 37.7938459, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 83/100: [37.7463878, 55.6449232, 37.7938459, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 84/100: [37.7463878, 55.677799799999995, 37.7938459, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 85/100: [37.7463878, 55.7106764, 37.7938459, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 86/100: [37.7463878, 55.743553, 37.7938459, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 87/100: [37.7463878, 55.7764296, 37.7938459, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 88/100: [37.7463878, 55.8093062, 37.7938459, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 89/100: [37.7463878, 55.842182799999996, 37.7938459, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 90/100: [37.7463878, 55.8750594, 37.7938459, 55.907936] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 91/100: [37.7938459, 55.57917, 37.841304, 55.6120466] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 92/100: [37.7938459, 55.6120466, 37.841304, 55.6449232] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 93/100: [37.7938459, 55.6449232, 37.841304, 55.677799799999995] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 94/100: [37.7938459, 55.677799799999995, 37.841304, 55.7106764] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 95/100: [37.7938459, 55.7106764, 37.841304, 55.743553] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 96/100: [37.7938459, 55.743553, 37.841304, 55.7764296] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 97/100: [37.7938459, 55.7764296, 37.841304, 55.8093062] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 98/100: [37.7938459, 55.8093062, 37.841304, 55.842182799999996] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 99/100: [37.7938459, 55.842182799999996, 37.841304, 55.8750594] - найдено 500 изображений\n", + "INFO:geo.download_images:Обработан bbox 100/100: [37.7938459, 55.8750594, 37.841304, 55.907936] - найдено 32 изображений\n", + "INFO:geo.download_images:После объединения: 49529 уникальных изображений\n", + "INFO:__main__:Найдено 49529 изображений. Начинаем загрузку в S3...\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n", + "INFO:geo.download_images:Прогресс: 10/49529 | Успешно: 10 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20/49529 | Успешно: 20 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 30/49529 | Успешно: 30 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 40/49529 | Успешно: 40 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 50/49529 | Успешно: 50 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 60/49529 | Успешно: 60 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 70/49529 | Успешно: 70 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 80/49529 | Успешно: 80 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 90/49529 | Успешно: 90 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 100/49529 | Успешно: 100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 110/49529 | Успешно: 110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 120/49529 | Успешно: 120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 130/49529 | Успешно: 130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 140/49529 | Успешно: 140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 150/49529 | Успешно: 150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 160/49529 | Успешно: 160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 170/49529 | Успешно: 170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 180/49529 | Успешно: 180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 190/49529 | Успешно: 190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 200/49529 | Успешно: 200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 210/49529 | Успешно: 210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 220/49529 | Успешно: 220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 230/49529 | Успешно: 230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 240/49529 | Успешно: 240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 250/49529 | Успешно: 250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 260/49529 | Успешно: 260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 270/49529 | Успешно: 270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 280/49529 | Успешно: 280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 290/49529 | Успешно: 290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 300/49529 | Успешно: 300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 310/49529 | Успешно: 310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 320/49529 | Успешно: 320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 330/49529 | Успешно: 330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 340/49529 | Успешно: 340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 350/49529 | Успешно: 350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 360/49529 | Успешно: 360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 370/49529 | Успешно: 370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 380/49529 | Успешно: 380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 390/49529 | Успешно: 390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 400/49529 | Успешно: 400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 410/49529 | Успешно: 410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 420/49529 | Успешно: 420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 430/49529 | Успешно: 430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 440/49529 | Успешно: 440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 450/49529 | Успешно: 450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 460/49529 | Успешно: 460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 470/49529 | Успешно: 470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 480/49529 | Успешно: 480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 490/49529 | Успешно: 490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 500/49529 | Успешно: 500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 510/49529 | Успешно: 510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 520/49529 | Успешно: 520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 530/49529 | Успешно: 530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 540/49529 | Успешно: 540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 550/49529 | Успешно: 550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 560/49529 | Успешно: 560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 570/49529 | Успешно: 570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 580/49529 | Успешно: 580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 590/49529 | Успешно: 590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 600/49529 | Успешно: 600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 610/49529 | Успешно: 610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 620/49529 | Успешно: 620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 630/49529 | Успешно: 630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 640/49529 | Успешно: 640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 650/49529 | Успешно: 650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 660/49529 | Успешно: 660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 670/49529 | Успешно: 670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 680/49529 | Успешно: 680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 690/49529 | Успешно: 690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 700/49529 | Успешно: 700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 710/49529 | Успешно: 710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 720/49529 | Успешно: 720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 730/49529 | Успешно: 730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 740/49529 | Успешно: 740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 750/49529 | Успешно: 750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 760/49529 | Успешно: 760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 770/49529 | Успешно: 770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 780/49529 | Успешно: 780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 790/49529 | Успешно: 790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 800/49529 | Успешно: 800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 810/49529 | Успешно: 810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 820/49529 | Успешно: 820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 830/49529 | Успешно: 830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 840/49529 | Успешно: 840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 850/49529 | Успешно: 850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 860/49529 | Успешно: 860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 870/49529 | Успешно: 870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 880/49529 | Успешно: 880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 890/49529 | Успешно: 890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 900/49529 | Успешно: 900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 910/49529 | Успешно: 910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 920/49529 | Успешно: 920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 930/49529 | Успешно: 930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 940/49529 | Успешно: 940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 950/49529 | Успешно: 950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 960/49529 | Успешно: 960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 970/49529 | Успешно: 970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 980/49529 | Успешно: 980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 990/49529 | Успешно: 990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1000/49529 | Успешно: 1000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1010/49529 | Успешно: 1010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1020/49529 | Успешно: 1020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1030/49529 | Успешно: 1030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1040/49529 | Успешно: 1040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1050/49529 | Успешно: 1050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1060/49529 | Успешно: 1060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1070/49529 | Успешно: 1070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1080/49529 | Успешно: 1080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1090/49529 | Успешно: 1090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1100/49529 | Успешно: 1100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1110/49529 | Успешно: 1110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1120/49529 | Успешно: 1120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1130/49529 | Успешно: 1130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1140/49529 | Успешно: 1140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1150/49529 | Успешно: 1150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1160/49529 | Успешно: 1160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1170/49529 | Успешно: 1170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1180/49529 | Успешно: 1180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1190/49529 | Успешно: 1190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1200/49529 | Успешно: 1200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1210/49529 | Успешно: 1210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1220/49529 | Успешно: 1220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1230/49529 | Успешно: 1230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1240/49529 | Успешно: 1240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1250/49529 | Успешно: 1250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1260/49529 | Успешно: 1260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1270/49529 | Успешно: 1270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1280/49529 | Успешно: 1280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1290/49529 | Успешно: 1290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1300/49529 | Успешно: 1300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1310/49529 | Успешно: 1310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1320/49529 | Успешно: 1320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1330/49529 | Успешно: 1330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1340/49529 | Успешно: 1340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1350/49529 | Успешно: 1350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1360/49529 | Успешно: 1360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1370/49529 | Успешно: 1370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1380/49529 | Успешно: 1380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1390/49529 | Успешно: 1390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1400/49529 | Успешно: 1400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1410/49529 | Успешно: 1410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1420/49529 | Успешно: 1420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1430/49529 | Успешно: 1430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1440/49529 | Успешно: 1440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1450/49529 | Успешно: 1450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1460/49529 | Успешно: 1460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1470/49529 | Успешно: 1470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1480/49529 | Успешно: 1480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1490/49529 | Успешно: 1490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1500/49529 | Успешно: 1500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1510/49529 | Успешно: 1510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1520/49529 | Успешно: 1520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1530/49529 | Успешно: 1530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1540/49529 | Успешно: 1540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1550/49529 | Успешно: 1550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1560/49529 | Успешно: 1560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1570/49529 | Успешно: 1570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1580/49529 | Успешно: 1580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1590/49529 | Успешно: 1590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1600/49529 | Успешно: 1600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1610/49529 | Успешно: 1610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1620/49529 | Успешно: 1620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1630/49529 | Успешно: 1630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1640/49529 | Успешно: 1640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1650/49529 | Успешно: 1650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1660/49529 | Успешно: 1660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1670/49529 | Успешно: 1670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1680/49529 | Успешно: 1680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1690/49529 | Успешно: 1690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1700/49529 | Успешно: 1700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1710/49529 | Успешно: 1710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1720/49529 | Успешно: 1720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1730/49529 | Успешно: 1730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1740/49529 | Успешно: 1740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1750/49529 | Успешно: 1750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1760/49529 | Успешно: 1760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1770/49529 | Успешно: 1770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1780/49529 | Успешно: 1780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1790/49529 | Успешно: 1790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1800/49529 | Успешно: 1800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1810/49529 | Успешно: 1810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1820/49529 | Успешно: 1820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1830/49529 | Успешно: 1830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1840/49529 | Успешно: 1840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1850/49529 | Успешно: 1850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1860/49529 | Успешно: 1860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1870/49529 | Успешно: 1870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1880/49529 | Успешно: 1880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1890/49529 | Успешно: 1890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1900/49529 | Успешно: 1900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1910/49529 | Успешно: 1910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1920/49529 | Успешно: 1920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1930/49529 | Успешно: 1930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1940/49529 | Успешно: 1940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1950/49529 | Успешно: 1950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1960/49529 | Успешно: 1960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1970/49529 | Успешно: 1970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1980/49529 | Успешно: 1980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 1990/49529 | Успешно: 1990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2000/49529 | Успешно: 2000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2010/49529 | Успешно: 2010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2020/49529 | Успешно: 2020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2030/49529 | Успешно: 2030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2040/49529 | Успешно: 2040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2050/49529 | Успешно: 2050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2060/49529 | Успешно: 2060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2070/49529 | Успешно: 2070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2080/49529 | Успешно: 2080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2090/49529 | Успешно: 2090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2100/49529 | Успешно: 2100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2110/49529 | Успешно: 2110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2120/49529 | Успешно: 2120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2130/49529 | Успешно: 2130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2140/49529 | Успешно: 2140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2150/49529 | Успешно: 2150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2160/49529 | Успешно: 2160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2170/49529 | Успешно: 2170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2180/49529 | Успешно: 2180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2190/49529 | Успешно: 2190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2200/49529 | Успешно: 2200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2210/49529 | Успешно: 2210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2220/49529 | Успешно: 2220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2230/49529 | Успешно: 2230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2240/49529 | Успешно: 2240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2250/49529 | Успешно: 2250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2260/49529 | Успешно: 2260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2270/49529 | Успешно: 2270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2280/49529 | Успешно: 2280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2290/49529 | Успешно: 2290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2300/49529 | Успешно: 2300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2310/49529 | Успешно: 2310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2320/49529 | Успешно: 2320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2330/49529 | Успешно: 2330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2340/49529 | Успешно: 2340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2350/49529 | Успешно: 2350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2360/49529 | Успешно: 2360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2370/49529 | Успешно: 2370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2380/49529 | Успешно: 2380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2390/49529 | Успешно: 2390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2400/49529 | Успешно: 2400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2410/49529 | Успешно: 2410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2420/49529 | Успешно: 2420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2430/49529 | Успешно: 2430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2440/49529 | Успешно: 2440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2450/49529 | Успешно: 2450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2460/49529 | Успешно: 2460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2470/49529 | Успешно: 2470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2480/49529 | Успешно: 2480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2490/49529 | Успешно: 2490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2500/49529 | Успешно: 2500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2510/49529 | Успешно: 2510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2520/49529 | Успешно: 2520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2530/49529 | Успешно: 2530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2540/49529 | Успешно: 2540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2550/49529 | Успешно: 2550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2560/49529 | Успешно: 2560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2570/49529 | Успешно: 2570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2580/49529 | Успешно: 2580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2590/49529 | Успешно: 2590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2600/49529 | Успешно: 2600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2610/49529 | Успешно: 2610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2620/49529 | Успешно: 2620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2630/49529 | Успешно: 2630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2640/49529 | Успешно: 2640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2650/49529 | Успешно: 2650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2660/49529 | Успешно: 2660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2670/49529 | Успешно: 2670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2680/49529 | Успешно: 2680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2690/49529 | Успешно: 2690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2700/49529 | Успешно: 2700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2710/49529 | Успешно: 2710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2720/49529 | Успешно: 2720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2730/49529 | Успешно: 2730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2740/49529 | Успешно: 2740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2750/49529 | Успешно: 2750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2760/49529 | Успешно: 2760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2770/49529 | Успешно: 2770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2780/49529 | Успешно: 2780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2790/49529 | Успешно: 2790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2800/49529 | Успешно: 2800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2810/49529 | Успешно: 2810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2820/49529 | Успешно: 2820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2830/49529 | Успешно: 2830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2840/49529 | Успешно: 2840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2850/49529 | Успешно: 2850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2860/49529 | Успешно: 2860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2870/49529 | Успешно: 2870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2880/49529 | Успешно: 2880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2890/49529 | Успешно: 2890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2900/49529 | Успешно: 2900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2910/49529 | Успешно: 2910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2920/49529 | Успешно: 2920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2930/49529 | Успешно: 2930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2940/49529 | Успешно: 2940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2950/49529 | Успешно: 2950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2960/49529 | Успешно: 2960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2970/49529 | Успешно: 2970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2980/49529 | Успешно: 2980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 2990/49529 | Успешно: 2990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3000/49529 | Успешно: 3000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3010/49529 | Успешно: 3010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3020/49529 | Успешно: 3020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3030/49529 | Успешно: 3030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3040/49529 | Успешно: 3040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3050/49529 | Успешно: 3050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3060/49529 | Успешно: 3060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3070/49529 | Успешно: 3070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3080/49529 | Успешно: 3080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3090/49529 | Успешно: 3090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3100/49529 | Успешно: 3100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3110/49529 | Успешно: 3110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3120/49529 | Успешно: 3120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3130/49529 | Успешно: 3130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3140/49529 | Успешно: 3140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3150/49529 | Успешно: 3150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3160/49529 | Успешно: 3160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3170/49529 | Успешно: 3170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3180/49529 | Успешно: 3180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3190/49529 | Успешно: 3190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3200/49529 | Успешно: 3200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3210/49529 | Успешно: 3210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3220/49529 | Успешно: 3220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3230/49529 | Успешно: 3230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3240/49529 | Успешно: 3240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3250/49529 | Успешно: 3250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3260/49529 | Успешно: 3260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3270/49529 | Успешно: 3270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3280/49529 | Успешно: 3280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3290/49529 | Успешно: 3290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3300/49529 | Успешно: 3300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3310/49529 | Успешно: 3310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3320/49529 | Успешно: 3320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3330/49529 | Успешно: 3330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3340/49529 | Успешно: 3340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3350/49529 | Успешно: 3350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3360/49529 | Успешно: 3360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3370/49529 | Успешно: 3370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3380/49529 | Успешно: 3380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3390/49529 | Успешно: 3390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3400/49529 | Успешно: 3400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3410/49529 | Успешно: 3410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3420/49529 | Успешно: 3420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3430/49529 | Успешно: 3430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3440/49529 | Успешно: 3440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3450/49529 | Успешно: 3450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3460/49529 | Успешно: 3460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3470/49529 | Успешно: 3470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3480/49529 | Успешно: 3480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3490/49529 | Успешно: 3490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3500/49529 | Успешно: 3500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3510/49529 | Успешно: 3510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3520/49529 | Успешно: 3520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3530/49529 | Успешно: 3530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3540/49529 | Успешно: 3540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3550/49529 | Успешно: 3550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3560/49529 | Успешно: 3560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3570/49529 | Успешно: 3570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3580/49529 | Успешно: 3580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3590/49529 | Успешно: 3590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3600/49529 | Успешно: 3600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3610/49529 | Успешно: 3610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3620/49529 | Успешно: 3620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3630/49529 | Успешно: 3630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3640/49529 | Успешно: 3640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3650/49529 | Успешно: 3650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3660/49529 | Успешно: 3660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3670/49529 | Успешно: 3670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3680/49529 | Успешно: 3680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3690/49529 | Успешно: 3690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3700/49529 | Успешно: 3700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3710/49529 | Успешно: 3710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3720/49529 | Успешно: 3720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3730/49529 | Успешно: 3730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3740/49529 | Успешно: 3740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3750/49529 | Успешно: 3750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3760/49529 | Успешно: 3760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3770/49529 | Успешно: 3770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3780/49529 | Успешно: 3780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3790/49529 | Успешно: 3790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3800/49529 | Успешно: 3800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3810/49529 | Успешно: 3810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3820/49529 | Успешно: 3820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3830/49529 | Успешно: 3830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3840/49529 | Успешно: 3840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3850/49529 | Успешно: 3850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3860/49529 | Успешно: 3860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3870/49529 | Успешно: 3870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3880/49529 | Успешно: 3880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3890/49529 | Успешно: 3890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3900/49529 | Успешно: 3900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3910/49529 | Успешно: 3910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3920/49529 | Успешно: 3920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3930/49529 | Успешно: 3930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3940/49529 | Успешно: 3940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3950/49529 | Успешно: 3950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3960/49529 | Успешно: 3960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3970/49529 | Успешно: 3970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3980/49529 | Успешно: 3980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 3990/49529 | Успешно: 3990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4000/49529 | Успешно: 4000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4010/49529 | Успешно: 4010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4020/49529 | Успешно: 4020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4030/49529 | Успешно: 4030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4040/49529 | Успешно: 4040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4050/49529 | Успешно: 4050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4060/49529 | Успешно: 4060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4070/49529 | Успешно: 4070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4080/49529 | Успешно: 4080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4090/49529 | Успешно: 4090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4100/49529 | Успешно: 4100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4110/49529 | Успешно: 4110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4120/49529 | Успешно: 4120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4130/49529 | Успешно: 4130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4140/49529 | Успешно: 4140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4150/49529 | Успешно: 4150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4160/49529 | Успешно: 4160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4170/49529 | Успешно: 4170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4180/49529 | Успешно: 4180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4190/49529 | Успешно: 4190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4200/49529 | Успешно: 4200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4210/49529 | Успешно: 4210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4220/49529 | Успешно: 4220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4230/49529 | Успешно: 4230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4240/49529 | Успешно: 4240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4250/49529 | Успешно: 4250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4260/49529 | Успешно: 4260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4270/49529 | Успешно: 4270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4280/49529 | Успешно: 4280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4290/49529 | Успешно: 4290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4300/49529 | Успешно: 4300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4310/49529 | Успешно: 4310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4320/49529 | Успешно: 4320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4330/49529 | Успешно: 4330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4340/49529 | Успешно: 4340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4350/49529 | Успешно: 4350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4360/49529 | Успешно: 4360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4370/49529 | Успешно: 4370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4380/49529 | Успешно: 4380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4390/49529 | Успешно: 4390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4400/49529 | Успешно: 4400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4410/49529 | Успешно: 4410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4420/49529 | Успешно: 4420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4430/49529 | Успешно: 4430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4440/49529 | Успешно: 4440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4450/49529 | Успешно: 4450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4460/49529 | Успешно: 4460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4470/49529 | Успешно: 4470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4480/49529 | Успешно: 4480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4490/49529 | Успешно: 4490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4500/49529 | Успешно: 4500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4510/49529 | Успешно: 4510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4520/49529 | Успешно: 4520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4530/49529 | Успешно: 4530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4540/49529 | Успешно: 4540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4550/49529 | Успешно: 4550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4560/49529 | Успешно: 4560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4570/49529 | Успешно: 4570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4580/49529 | Успешно: 4580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4590/49529 | Успешно: 4590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4600/49529 | Успешно: 4600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4610/49529 | Успешно: 4610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4620/49529 | Успешно: 4620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4630/49529 | Успешно: 4630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4640/49529 | Успешно: 4640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4650/49529 | Успешно: 4650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4660/49529 | Успешно: 4660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4670/49529 | Успешно: 4670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4680/49529 | Успешно: 4680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4690/49529 | Успешно: 4690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4700/49529 | Успешно: 4700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4710/49529 | Успешно: 4710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4720/49529 | Успешно: 4720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4730/49529 | Успешно: 4730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4740/49529 | Успешно: 4740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4750/49529 | Успешно: 4750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4760/49529 | Успешно: 4760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4770/49529 | Успешно: 4770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4780/49529 | Успешно: 4780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4790/49529 | Успешно: 4790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4800/49529 | Успешно: 4800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4810/49529 | Успешно: 4810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4820/49529 | Успешно: 4820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4830/49529 | Успешно: 4830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4840/49529 | Успешно: 4840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4850/49529 | Успешно: 4850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4860/49529 | Успешно: 4860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4870/49529 | Успешно: 4870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4880/49529 | Успешно: 4880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4890/49529 | Успешно: 4890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4900/49529 | Успешно: 4900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4910/49529 | Успешно: 4910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4920/49529 | Успешно: 4920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4930/49529 | Успешно: 4930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4940/49529 | Успешно: 4940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4950/49529 | Успешно: 4950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4960/49529 | Успешно: 4960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4970/49529 | Успешно: 4970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4980/49529 | Успешно: 4980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 4990/49529 | Успешно: 4990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5000/49529 | Успешно: 5000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5010/49529 | Успешно: 5010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5020/49529 | Успешно: 5020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5030/49529 | Успешно: 5030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5040/49529 | Успешно: 5040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5050/49529 | Успешно: 5050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5060/49529 | Успешно: 5060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5070/49529 | Успешно: 5070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5080/49529 | Успешно: 5080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5090/49529 | Успешно: 5090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5100/49529 | Успешно: 5100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5110/49529 | Успешно: 5110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5120/49529 | Успешно: 5120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5130/49529 | Успешно: 5130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5140/49529 | Успешно: 5140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5150/49529 | Успешно: 5150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5160/49529 | Успешно: 5160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5170/49529 | Успешно: 5170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5180/49529 | Успешно: 5180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5190/49529 | Успешно: 5190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5200/49529 | Успешно: 5200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5210/49529 | Успешно: 5210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5220/49529 | Успешно: 5220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5230/49529 | Успешно: 5230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5240/49529 | Успешно: 5240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5250/49529 | Успешно: 5250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5260/49529 | Успешно: 5260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5270/49529 | Успешно: 5270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5280/49529 | Успешно: 5280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5290/49529 | Успешно: 5290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5300/49529 | Успешно: 5300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5310/49529 | Успешно: 5310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5320/49529 | Успешно: 5320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5330/49529 | Успешно: 5330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5340/49529 | Успешно: 5340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5350/49529 | Успешно: 5350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5360/49529 | Успешно: 5360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5370/49529 | Успешно: 5370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5380/49529 | Успешно: 5380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5390/49529 | Успешно: 5390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5400/49529 | Успешно: 5400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5410/49529 | Успешно: 5410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5420/49529 | Успешно: 5420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5430/49529 | Успешно: 5430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5440/49529 | Успешно: 5440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5450/49529 | Успешно: 5450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5460/49529 | Успешно: 5460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5470/49529 | Успешно: 5470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5480/49529 | Успешно: 5480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5490/49529 | Успешно: 5490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5500/49529 | Успешно: 5500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5510/49529 | Успешно: 5510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5520/49529 | Успешно: 5520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5530/49529 | Успешно: 5530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5540/49529 | Успешно: 5540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5550/49529 | Успешно: 5550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5560/49529 | Успешно: 5560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5570/49529 | Успешно: 5570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5580/49529 | Успешно: 5580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5590/49529 | Успешно: 5590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5600/49529 | Успешно: 5600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5610/49529 | Успешно: 5610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5620/49529 | Успешно: 5620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5630/49529 | Успешно: 5630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5640/49529 | Успешно: 5640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5650/49529 | Успешно: 5650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5660/49529 | Успешно: 5660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5670/49529 | Успешно: 5670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5680/49529 | Успешно: 5680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5690/49529 | Успешно: 5690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5700/49529 | Успешно: 5700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5710/49529 | Успешно: 5710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5720/49529 | Успешно: 5720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5730/49529 | Успешно: 5730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5740/49529 | Успешно: 5740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5750/49529 | Успешно: 5750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5760/49529 | Успешно: 5760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5770/49529 | Успешно: 5770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5780/49529 | Успешно: 5780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5790/49529 | Успешно: 5790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5800/49529 | Успешно: 5800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5810/49529 | Успешно: 5810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5820/49529 | Успешно: 5820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5830/49529 | Успешно: 5830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5840/49529 | Успешно: 5840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5850/49529 | Успешно: 5850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5860/49529 | Успешно: 5860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5870/49529 | Успешно: 5870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5880/49529 | Успешно: 5880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5890/49529 | Успешно: 5890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5900/49529 | Успешно: 5900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5910/49529 | Успешно: 5910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5920/49529 | Успешно: 5920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5930/49529 | Успешно: 5930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5940/49529 | Успешно: 5940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5950/49529 | Успешно: 5950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5960/49529 | Успешно: 5960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5970/49529 | Успешно: 5970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5980/49529 | Успешно: 5980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 5990/49529 | Успешно: 5990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6000/49529 | Успешно: 6000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6010/49529 | Успешно: 6010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6020/49529 | Успешно: 6020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6030/49529 | Успешно: 6030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6040/49529 | Успешно: 6040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6050/49529 | Успешно: 6050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6060/49529 | Успешно: 6060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6070/49529 | Успешно: 6070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6080/49529 | Успешно: 6080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6090/49529 | Успешно: 6090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6100/49529 | Успешно: 6100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6110/49529 | Успешно: 6110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6120/49529 | Успешно: 6120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6130/49529 | Успешно: 6130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6140/49529 | Успешно: 6140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6150/49529 | Успешно: 6150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6160/49529 | Успешно: 6160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6170/49529 | Успешно: 6170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6180/49529 | Успешно: 6180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6190/49529 | Успешно: 6190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6200/49529 | Успешно: 6200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6210/49529 | Успешно: 6210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6220/49529 | Успешно: 6220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6230/49529 | Успешно: 6230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6240/49529 | Успешно: 6240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6250/49529 | Успешно: 6250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6260/49529 | Успешно: 6260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6270/49529 | Успешно: 6270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6280/49529 | Успешно: 6280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6290/49529 | Успешно: 6290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6300/49529 | Успешно: 6300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6310/49529 | Успешно: 6310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6320/49529 | Успешно: 6320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6330/49529 | Успешно: 6330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6340/49529 | Успешно: 6340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6350/49529 | Успешно: 6350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6360/49529 | Успешно: 6360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6370/49529 | Успешно: 6370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6380/49529 | Успешно: 6380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6390/49529 | Успешно: 6390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6400/49529 | Успешно: 6400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6410/49529 | Успешно: 6410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6420/49529 | Успешно: 6420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6430/49529 | Успешно: 6430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6440/49529 | Успешно: 6440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6450/49529 | Успешно: 6450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6460/49529 | Успешно: 6460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6470/49529 | Успешно: 6470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6480/49529 | Успешно: 6480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6490/49529 | Успешно: 6490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6500/49529 | Успешно: 6500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6510/49529 | Успешно: 6510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6520/49529 | Успешно: 6520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6530/49529 | Успешно: 6530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6540/49529 | Успешно: 6540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6550/49529 | Успешно: 6550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6560/49529 | Успешно: 6560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6570/49529 | Успешно: 6570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6580/49529 | Успешно: 6580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6590/49529 | Успешно: 6590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6600/49529 | Успешно: 6600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6610/49529 | Успешно: 6610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6620/49529 | Успешно: 6620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6630/49529 | Успешно: 6630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6640/49529 | Успешно: 6640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6650/49529 | Успешно: 6650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6660/49529 | Успешно: 6660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6670/49529 | Успешно: 6670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6680/49529 | Успешно: 6680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6690/49529 | Успешно: 6690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6700/49529 | Успешно: 6700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6710/49529 | Успешно: 6710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6720/49529 | Успешно: 6720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6730/49529 | Успешно: 6730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6740/49529 | Успешно: 6740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6750/49529 | Успешно: 6750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6760/49529 | Успешно: 6760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6770/49529 | Успешно: 6770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6780/49529 | Успешно: 6780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6790/49529 | Успешно: 6790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6800/49529 | Успешно: 6800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6810/49529 | Успешно: 6810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6820/49529 | Успешно: 6820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6830/49529 | Успешно: 6830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6840/49529 | Успешно: 6840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6850/49529 | Успешно: 6850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6860/49529 | Успешно: 6860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6870/49529 | Успешно: 6870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6880/49529 | Успешно: 6880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6890/49529 | Успешно: 6890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6900/49529 | Успешно: 6900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6910/49529 | Успешно: 6910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6920/49529 | Успешно: 6920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6930/49529 | Успешно: 6930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6940/49529 | Успешно: 6940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6950/49529 | Успешно: 6950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6960/49529 | Успешно: 6960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6970/49529 | Успешно: 6970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6980/49529 | Успешно: 6980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 6990/49529 | Успешно: 6990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7000/49529 | Успешно: 7000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7010/49529 | Успешно: 7010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7020/49529 | Успешно: 7020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7030/49529 | Успешно: 7030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7040/49529 | Успешно: 7040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7050/49529 | Успешно: 7050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7060/49529 | Успешно: 7060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7070/49529 | Успешно: 7070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7080/49529 | Успешно: 7080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7090/49529 | Успешно: 7090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7100/49529 | Успешно: 7100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7110/49529 | Успешно: 7110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7120/49529 | Успешно: 7120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7130/49529 | Успешно: 7130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7140/49529 | Успешно: 7140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7150/49529 | Успешно: 7150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7160/49529 | Успешно: 7160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7170/49529 | Успешно: 7170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7180/49529 | Успешно: 7180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7190/49529 | Успешно: 7190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7200/49529 | Успешно: 7200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7210/49529 | Успешно: 7210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7220/49529 | Успешно: 7220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7230/49529 | Успешно: 7230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7240/49529 | Успешно: 7240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7250/49529 | Успешно: 7250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7260/49529 | Успешно: 7260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7270/49529 | Успешно: 7270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7280/49529 | Успешно: 7280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7290/49529 | Успешно: 7290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7300/49529 | Успешно: 7300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7310/49529 | Успешно: 7310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7320/49529 | Успешно: 7320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7330/49529 | Успешно: 7330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7340/49529 | Успешно: 7340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7350/49529 | Успешно: 7350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7360/49529 | Успешно: 7360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7370/49529 | Успешно: 7370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7380/49529 | Успешно: 7380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7390/49529 | Успешно: 7390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7400/49529 | Успешно: 7400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7410/49529 | Успешно: 7410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7420/49529 | Успешно: 7420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7430/49529 | Успешно: 7430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7440/49529 | Успешно: 7440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7450/49529 | Успешно: 7450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7460/49529 | Успешно: 7460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7470/49529 | Успешно: 7470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7480/49529 | Успешно: 7480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7490/49529 | Успешно: 7490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7500/49529 | Успешно: 7500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7510/49529 | Успешно: 7510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7520/49529 | Успешно: 7520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7530/49529 | Успешно: 7530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7540/49529 | Успешно: 7540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7550/49529 | Успешно: 7550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7560/49529 | Успешно: 7560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7570/49529 | Успешно: 7570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7580/49529 | Успешно: 7580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7590/49529 | Успешно: 7590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7600/49529 | Успешно: 7600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7610/49529 | Успешно: 7610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7620/49529 | Успешно: 7620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7630/49529 | Успешно: 7630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7640/49529 | Успешно: 7640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7650/49529 | Успешно: 7650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7660/49529 | Успешно: 7660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7670/49529 | Успешно: 7670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7680/49529 | Успешно: 7680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7690/49529 | Успешно: 7690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7700/49529 | Успешно: 7700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7710/49529 | Успешно: 7710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7720/49529 | Успешно: 7720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7730/49529 | Успешно: 7730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7740/49529 | Успешно: 7740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7750/49529 | Успешно: 7750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7760/49529 | Успешно: 7760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7770/49529 | Успешно: 7770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7780/49529 | Успешно: 7780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7790/49529 | Успешно: 7790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7800/49529 | Успешно: 7800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7810/49529 | Успешно: 7810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7820/49529 | Успешно: 7820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7830/49529 | Успешно: 7830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7840/49529 | Успешно: 7840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7850/49529 | Успешно: 7850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7860/49529 | Успешно: 7860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7870/49529 | Успешно: 7870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7880/49529 | Успешно: 7880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7890/49529 | Успешно: 7890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7900/49529 | Успешно: 7900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7910/49529 | Успешно: 7910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7920/49529 | Успешно: 7920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7930/49529 | Успешно: 7930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7940/49529 | Успешно: 7940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7950/49529 | Успешно: 7950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7960/49529 | Успешно: 7960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7970/49529 | Успешно: 7970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7980/49529 | Успешно: 7980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 7990/49529 | Успешно: 7990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8000/49529 | Успешно: 8000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8010/49529 | Успешно: 8010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8020/49529 | Успешно: 8020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8030/49529 | Успешно: 8030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8040/49529 | Успешно: 8040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8050/49529 | Успешно: 8050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8060/49529 | Успешно: 8060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8070/49529 | Успешно: 8070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8080/49529 | Успешно: 8080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8090/49529 | Успешно: 8090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8100/49529 | Успешно: 8100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8110/49529 | Успешно: 8110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8120/49529 | Успешно: 8120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8130/49529 | Успешно: 8130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8140/49529 | Успешно: 8140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8150/49529 | Успешно: 8150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8160/49529 | Успешно: 8160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8170/49529 | Успешно: 8170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8180/49529 | Успешно: 8180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8190/49529 | Успешно: 8190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8200/49529 | Успешно: 8200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8210/49529 | Успешно: 8210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8220/49529 | Успешно: 8220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8230/49529 | Успешно: 8230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8240/49529 | Успешно: 8240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8250/49529 | Успешно: 8250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8260/49529 | Успешно: 8260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8270/49529 | Успешно: 8270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8280/49529 | Успешно: 8280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8290/49529 | Успешно: 8290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8300/49529 | Успешно: 8300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8310/49529 | Успешно: 8310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8320/49529 | Успешно: 8320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8330/49529 | Успешно: 8330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8340/49529 | Успешно: 8340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8350/49529 | Успешно: 8350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8360/49529 | Успешно: 8360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8370/49529 | Успешно: 8370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8380/49529 | Успешно: 8380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8390/49529 | Успешно: 8390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8400/49529 | Успешно: 8400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8410/49529 | Успешно: 8410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8420/49529 | Успешно: 8420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8430/49529 | Успешно: 8430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8440/49529 | Успешно: 8440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8450/49529 | Успешно: 8450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8460/49529 | Успешно: 8460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8470/49529 | Успешно: 8470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8480/49529 | Успешно: 8480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8490/49529 | Успешно: 8490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8500/49529 | Успешно: 8500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8510/49529 | Успешно: 8510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8520/49529 | Успешно: 8520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8530/49529 | Успешно: 8530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8540/49529 | Успешно: 8540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8550/49529 | Успешно: 8550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8560/49529 | Успешно: 8560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8570/49529 | Успешно: 8570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8580/49529 | Успешно: 8580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8590/49529 | Успешно: 8590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8600/49529 | Успешно: 8600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8610/49529 | Успешно: 8610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8620/49529 | Успешно: 8620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8630/49529 | Успешно: 8630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8640/49529 | Успешно: 8640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8650/49529 | Успешно: 8650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8660/49529 | Успешно: 8660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8670/49529 | Успешно: 8670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8680/49529 | Успешно: 8680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8690/49529 | Успешно: 8690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8700/49529 | Успешно: 8700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8710/49529 | Успешно: 8710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8720/49529 | Успешно: 8720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8730/49529 | Успешно: 8730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8740/49529 | Успешно: 8740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8750/49529 | Успешно: 8750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8760/49529 | Успешно: 8760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8770/49529 | Успешно: 8770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8780/49529 | Успешно: 8780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8790/49529 | Успешно: 8790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8800/49529 | Успешно: 8800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8810/49529 | Успешно: 8810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8820/49529 | Успешно: 8820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8830/49529 | Успешно: 8830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8840/49529 | Успешно: 8840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8850/49529 | Успешно: 8850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8860/49529 | Успешно: 8860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8870/49529 | Успешно: 8870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8880/49529 | Успешно: 8880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8890/49529 | Успешно: 8890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8900/49529 | Успешно: 8900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8910/49529 | Успешно: 8910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8920/49529 | Успешно: 8920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8930/49529 | Успешно: 8930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8940/49529 | Успешно: 8940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8950/49529 | Успешно: 8950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8960/49529 | Успешно: 8960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8970/49529 | Успешно: 8970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8980/49529 | Успешно: 8980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 8990/49529 | Успешно: 8990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9000/49529 | Успешно: 9000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9010/49529 | Успешно: 9010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9020/49529 | Успешно: 9020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9030/49529 | Успешно: 9030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9040/49529 | Успешно: 9040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9050/49529 | Успешно: 9050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9060/49529 | Успешно: 9060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9070/49529 | Успешно: 9070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9080/49529 | Успешно: 9080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9090/49529 | Успешно: 9090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9100/49529 | Успешно: 9100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9110/49529 | Успешно: 9110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9120/49529 | Успешно: 9120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9130/49529 | Успешно: 9130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9140/49529 | Успешно: 9140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9150/49529 | Успешно: 9150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9160/49529 | Успешно: 9160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9170/49529 | Успешно: 9170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9180/49529 | Успешно: 9180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9190/49529 | Успешно: 9190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9200/49529 | Успешно: 9200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9210/49529 | Успешно: 9210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9220/49529 | Успешно: 9220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9230/49529 | Успешно: 9230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9240/49529 | Успешно: 9240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9250/49529 | Успешно: 9250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9260/49529 | Успешно: 9260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9270/49529 | Успешно: 9270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9280/49529 | Успешно: 9280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9290/49529 | Успешно: 9290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9300/49529 | Успешно: 9300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9310/49529 | Успешно: 9310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9320/49529 | Успешно: 9320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9330/49529 | Успешно: 9330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9340/49529 | Успешно: 9340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9350/49529 | Успешно: 9350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9360/49529 | Успешно: 9360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9370/49529 | Успешно: 9370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9380/49529 | Успешно: 9380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9390/49529 | Успешно: 9390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9400/49529 | Успешно: 9400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9410/49529 | Успешно: 9410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9420/49529 | Успешно: 9420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9430/49529 | Успешно: 9430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9440/49529 | Успешно: 9440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9450/49529 | Успешно: 9450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9460/49529 | Успешно: 9460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9470/49529 | Успешно: 9470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9480/49529 | Успешно: 9480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9490/49529 | Успешно: 9490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9500/49529 | Успешно: 9500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9510/49529 | Успешно: 9510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9520/49529 | Успешно: 9520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9530/49529 | Успешно: 9530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9540/49529 | Успешно: 9540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9550/49529 | Успешно: 9550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9560/49529 | Успешно: 9560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9570/49529 | Успешно: 9570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9580/49529 | Успешно: 9580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9590/49529 | Успешно: 9590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9600/49529 | Успешно: 9600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9610/49529 | Успешно: 9610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9620/49529 | Успешно: 9620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9630/49529 | Успешно: 9630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9640/49529 | Успешно: 9640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9650/49529 | Успешно: 9650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9660/49529 | Успешно: 9660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9670/49529 | Успешно: 9670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9680/49529 | Успешно: 9680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9690/49529 | Успешно: 9690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9700/49529 | Успешно: 9700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9710/49529 | Успешно: 9710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9720/49529 | Успешно: 9720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9730/49529 | Успешно: 9730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9740/49529 | Успешно: 9740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9750/49529 | Успешно: 9750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9760/49529 | Успешно: 9760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9770/49529 | Успешно: 9770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9780/49529 | Успешно: 9780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9790/49529 | Успешно: 9790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9800/49529 | Успешно: 9800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9810/49529 | Успешно: 9810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9820/49529 | Успешно: 9820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9830/49529 | Успешно: 9830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9840/49529 | Успешно: 9840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9850/49529 | Успешно: 9850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9860/49529 | Успешно: 9860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9870/49529 | Успешно: 9870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9880/49529 | Успешно: 9880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9890/49529 | Успешно: 9890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9900/49529 | Успешно: 9900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9910/49529 | Успешно: 9910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9920/49529 | Успешно: 9920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9930/49529 | Успешно: 9930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9940/49529 | Успешно: 9940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9950/49529 | Успешно: 9950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9960/49529 | Успешно: 9960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9970/49529 | Успешно: 9970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9980/49529 | Успешно: 9980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 9990/49529 | Успешно: 9990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10000/49529 | Успешно: 10000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10010/49529 | Успешно: 10010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10020/49529 | Успешно: 10020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10030/49529 | Успешно: 10030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10040/49529 | Успешно: 10040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10050/49529 | Успешно: 10050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10060/49529 | Успешно: 10060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10070/49529 | Успешно: 10070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10080/49529 | Успешно: 10080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10090/49529 | Успешно: 10090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10100/49529 | Успешно: 10100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10110/49529 | Успешно: 10110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10120/49529 | Успешно: 10120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10130/49529 | Успешно: 10130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10140/49529 | Успешно: 10140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10150/49529 | Успешно: 10150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10160/49529 | Успешно: 10160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10170/49529 | Успешно: 10170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10180/49529 | Успешно: 10180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10190/49529 | Успешно: 10190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10200/49529 | Успешно: 10200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10210/49529 | Успешно: 10210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10220/49529 | Успешно: 10220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10230/49529 | Успешно: 10230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10240/49529 | Успешно: 10240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10250/49529 | Успешно: 10250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10260/49529 | Успешно: 10260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10270/49529 | Успешно: 10270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10280/49529 | Успешно: 10280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10290/49529 | Успешно: 10290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10300/49529 | Успешно: 10300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10310/49529 | Успешно: 10310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10320/49529 | Успешно: 10320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10330/49529 | Успешно: 10330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10340/49529 | Успешно: 10340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10350/49529 | Успешно: 10350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10360/49529 | Успешно: 10360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10370/49529 | Успешно: 10370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10380/49529 | Успешно: 10380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10390/49529 | Успешно: 10390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10400/49529 | Успешно: 10400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10410/49529 | Успешно: 10410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10420/49529 | Успешно: 10420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10430/49529 | Успешно: 10430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10440/49529 | Успешно: 10440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10450/49529 | Успешно: 10450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10460/49529 | Успешно: 10460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10470/49529 | Успешно: 10470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10480/49529 | Успешно: 10480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10490/49529 | Успешно: 10490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10500/49529 | Успешно: 10500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10510/49529 | Успешно: 10510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10520/49529 | Успешно: 10520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10530/49529 | Успешно: 10530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10540/49529 | Успешно: 10540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10550/49529 | Успешно: 10550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10560/49529 | Успешно: 10560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10570/49529 | Успешно: 10570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10580/49529 | Успешно: 10580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10590/49529 | Успешно: 10590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10600/49529 | Успешно: 10600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10610/49529 | Успешно: 10610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10620/49529 | Успешно: 10620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10630/49529 | Успешно: 10630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10640/49529 | Успешно: 10640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10650/49529 | Успешно: 10650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10660/49529 | Успешно: 10660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10670/49529 | Успешно: 10670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10680/49529 | Успешно: 10680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10690/49529 | Успешно: 10690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10700/49529 | Успешно: 10700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10710/49529 | Успешно: 10710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10720/49529 | Успешно: 10720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10730/49529 | Успешно: 10730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10740/49529 | Успешно: 10740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10750/49529 | Успешно: 10750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10760/49529 | Успешно: 10760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10770/49529 | Успешно: 10770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10780/49529 | Успешно: 10780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10790/49529 | Успешно: 10790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10800/49529 | Успешно: 10800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10810/49529 | Успешно: 10810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10820/49529 | Успешно: 10820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10830/49529 | Успешно: 10830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10840/49529 | Успешно: 10840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10850/49529 | Успешно: 10850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10860/49529 | Успешно: 10860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10870/49529 | Успешно: 10870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10880/49529 | Успешно: 10880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10890/49529 | Успешно: 10890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10900/49529 | Успешно: 10900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10910/49529 | Успешно: 10910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10920/49529 | Успешно: 10920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10930/49529 | Успешно: 10930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10940/49529 | Успешно: 10940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10950/49529 | Успешно: 10950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10960/49529 | Успешно: 10960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10970/49529 | Успешно: 10970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10980/49529 | Успешно: 10980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 10990/49529 | Успешно: 10990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11000/49529 | Успешно: 11000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11010/49529 | Успешно: 11010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11020/49529 | Успешно: 11020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11030/49529 | Успешно: 11030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11040/49529 | Успешно: 11040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11050/49529 | Успешно: 11050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11060/49529 | Успешно: 11060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11070/49529 | Успешно: 11070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11080/49529 | Успешно: 11080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11090/49529 | Успешно: 11090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11100/49529 | Успешно: 11100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11110/49529 | Успешно: 11110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11120/49529 | Успешно: 11120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11130/49529 | Успешно: 11130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11140/49529 | Успешно: 11140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11150/49529 | Успешно: 11150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11160/49529 | Успешно: 11160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11170/49529 | Успешно: 11170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11180/49529 | Успешно: 11180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11190/49529 | Успешно: 11190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11200/49529 | Успешно: 11200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11210/49529 | Успешно: 11210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11220/49529 | Успешно: 11220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11230/49529 | Успешно: 11230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11240/49529 | Успешно: 11240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11250/49529 | Успешно: 11250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11260/49529 | Успешно: 11260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11270/49529 | Успешно: 11270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11280/49529 | Успешно: 11280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11290/49529 | Успешно: 11290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11300/49529 | Успешно: 11300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11310/49529 | Успешно: 11310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11320/49529 | Успешно: 11320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11330/49529 | Успешно: 11330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11340/49529 | Успешно: 11340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11350/49529 | Успешно: 11350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11360/49529 | Успешно: 11360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11370/49529 | Успешно: 11370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11380/49529 | Успешно: 11380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11390/49529 | Успешно: 11390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11400/49529 | Успешно: 11400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11410/49529 | Успешно: 11410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11420/49529 | Успешно: 11420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11430/49529 | Успешно: 11430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11440/49529 | Успешно: 11440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11450/49529 | Успешно: 11450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11460/49529 | Успешно: 11460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11470/49529 | Успешно: 11470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11480/49529 | Успешно: 11480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11490/49529 | Успешно: 11490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11500/49529 | Успешно: 11500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11510/49529 | Успешно: 11510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11520/49529 | Успешно: 11520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11530/49529 | Успешно: 11530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11540/49529 | Успешно: 11540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11550/49529 | Успешно: 11550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11560/49529 | Успешно: 11560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11570/49529 | Успешно: 11570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11580/49529 | Успешно: 11580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11590/49529 | Успешно: 11590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11600/49529 | Успешно: 11600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11610/49529 | Успешно: 11610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11620/49529 | Успешно: 11620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11630/49529 | Успешно: 11630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11640/49529 | Успешно: 11640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11650/49529 | Успешно: 11650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11660/49529 | Успешно: 11660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11670/49529 | Успешно: 11670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11680/49529 | Успешно: 11680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11690/49529 | Успешно: 11690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11700/49529 | Успешно: 11700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11710/49529 | Успешно: 11710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11720/49529 | Успешно: 11720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11730/49529 | Успешно: 11730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11740/49529 | Успешно: 11740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11750/49529 | Успешно: 11750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11760/49529 | Успешно: 11760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11770/49529 | Успешно: 11770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11780/49529 | Успешно: 11780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11790/49529 | Успешно: 11790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11800/49529 | Успешно: 11800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11810/49529 | Успешно: 11810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11820/49529 | Успешно: 11820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11830/49529 | Успешно: 11830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11840/49529 | Успешно: 11840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11850/49529 | Успешно: 11850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11860/49529 | Успешно: 11860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11870/49529 | Успешно: 11870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11880/49529 | Успешно: 11880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11890/49529 | Успешно: 11890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11900/49529 | Успешно: 11900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11910/49529 | Успешно: 11910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11920/49529 | Успешно: 11920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11930/49529 | Успешно: 11930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11940/49529 | Успешно: 11940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11950/49529 | Успешно: 11950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11960/49529 | Успешно: 11960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11970/49529 | Успешно: 11970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11980/49529 | Успешно: 11980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 11990/49529 | Успешно: 11990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12000/49529 | Успешно: 12000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12010/49529 | Успешно: 12010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12020/49529 | Успешно: 12020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12030/49529 | Успешно: 12030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12040/49529 | Успешно: 12040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12050/49529 | Успешно: 12050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12060/49529 | Успешно: 12060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12070/49529 | Успешно: 12070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12080/49529 | Успешно: 12080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12090/49529 | Успешно: 12090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12100/49529 | Успешно: 12100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12110/49529 | Успешно: 12110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12120/49529 | Успешно: 12120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12130/49529 | Успешно: 12130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12140/49529 | Успешно: 12140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12150/49529 | Успешно: 12150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12160/49529 | Успешно: 12160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12170/49529 | Успешно: 12170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12180/49529 | Успешно: 12180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12190/49529 | Успешно: 12190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12200/49529 | Успешно: 12200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12210/49529 | Успешно: 12210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12220/49529 | Успешно: 12220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12230/49529 | Успешно: 12230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12240/49529 | Успешно: 12240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12250/49529 | Успешно: 12250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12260/49529 | Успешно: 12260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12270/49529 | Успешно: 12270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12280/49529 | Успешно: 12280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12290/49529 | Успешно: 12290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12300/49529 | Успешно: 12300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12310/49529 | Успешно: 12310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12320/49529 | Успешно: 12320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12330/49529 | Успешно: 12330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12340/49529 | Успешно: 12340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12350/49529 | Успешно: 12350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12360/49529 | Успешно: 12360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12370/49529 | Успешно: 12370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12380/49529 | Успешно: 12380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12390/49529 | Успешно: 12390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12400/49529 | Успешно: 12400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12410/49529 | Успешно: 12410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12420/49529 | Успешно: 12420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12430/49529 | Успешно: 12430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12440/49529 | Успешно: 12440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12450/49529 | Успешно: 12450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12460/49529 | Успешно: 12460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12470/49529 | Успешно: 12470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12480/49529 | Успешно: 12480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12490/49529 | Успешно: 12490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12500/49529 | Успешно: 12500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12510/49529 | Успешно: 12510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12520/49529 | Успешно: 12520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12530/49529 | Успешно: 12530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12540/49529 | Успешно: 12540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12550/49529 | Успешно: 12550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12560/49529 | Успешно: 12560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12570/49529 | Успешно: 12570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12580/49529 | Успешно: 12580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12590/49529 | Успешно: 12590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12600/49529 | Успешно: 12600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12610/49529 | Успешно: 12610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12620/49529 | Успешно: 12620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12630/49529 | Успешно: 12630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12640/49529 | Успешно: 12640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12650/49529 | Успешно: 12650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12660/49529 | Успешно: 12660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12670/49529 | Успешно: 12670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12680/49529 | Успешно: 12680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12690/49529 | Успешно: 12690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12700/49529 | Успешно: 12700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12710/49529 | Успешно: 12710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12720/49529 | Успешно: 12720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12730/49529 | Успешно: 12730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12740/49529 | Успешно: 12740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12750/49529 | Успешно: 12750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12760/49529 | Успешно: 12760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12770/49529 | Успешно: 12770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12780/49529 | Успешно: 12780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12790/49529 | Успешно: 12790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12800/49529 | Успешно: 12800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12810/49529 | Успешно: 12810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12820/49529 | Успешно: 12820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12830/49529 | Успешно: 12830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12840/49529 | Успешно: 12840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12850/49529 | Успешно: 12850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12860/49529 | Успешно: 12860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12870/49529 | Успешно: 12870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12880/49529 | Успешно: 12880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12890/49529 | Успешно: 12890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12900/49529 | Успешно: 12900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12910/49529 | Успешно: 12910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12920/49529 | Успешно: 12920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12930/49529 | Успешно: 12930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12940/49529 | Успешно: 12940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12950/49529 | Успешно: 12950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12960/49529 | Успешно: 12960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12970/49529 | Успешно: 12970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12980/49529 | Успешно: 12980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 12990/49529 | Успешно: 12990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13000/49529 | Успешно: 13000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13010/49529 | Успешно: 13010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13020/49529 | Успешно: 13020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13030/49529 | Успешно: 13030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13040/49529 | Успешно: 13040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13050/49529 | Успешно: 13050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13060/49529 | Успешно: 13060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13070/49529 | Успешно: 13070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13080/49529 | Успешно: 13080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13090/49529 | Успешно: 13090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13100/49529 | Успешно: 13100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13110/49529 | Успешно: 13110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13120/49529 | Успешно: 13120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13130/49529 | Успешно: 13130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13140/49529 | Успешно: 13140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13150/49529 | Успешно: 13150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13160/49529 | Успешно: 13160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13170/49529 | Успешно: 13170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13180/49529 | Успешно: 13180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13190/49529 | Успешно: 13190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13200/49529 | Успешно: 13200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13210/49529 | Успешно: 13210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13220/49529 | Успешно: 13220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13230/49529 | Успешно: 13230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13240/49529 | Успешно: 13240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13250/49529 | Успешно: 13250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13260/49529 | Успешно: 13260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13270/49529 | Успешно: 13270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13280/49529 | Успешно: 13280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13290/49529 | Успешно: 13290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13300/49529 | Успешно: 13300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13310/49529 | Успешно: 13310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13320/49529 | Успешно: 13320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13330/49529 | Успешно: 13330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13340/49529 | Успешно: 13340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13350/49529 | Успешно: 13350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13360/49529 | Успешно: 13360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13370/49529 | Успешно: 13370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13380/49529 | Успешно: 13380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13390/49529 | Успешно: 13390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13400/49529 | Успешно: 13400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13410/49529 | Успешно: 13410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13420/49529 | Успешно: 13420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13430/49529 | Успешно: 13430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13440/49529 | Успешно: 13440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13450/49529 | Успешно: 13450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13460/49529 | Успешно: 13460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13470/49529 | Успешно: 13470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13480/49529 | Успешно: 13480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13490/49529 | Успешно: 13490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13500/49529 | Успешно: 13500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13510/49529 | Успешно: 13510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13520/49529 | Успешно: 13520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13530/49529 | Успешно: 13530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13540/49529 | Успешно: 13540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13550/49529 | Успешно: 13550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13560/49529 | Успешно: 13560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13570/49529 | Успешно: 13570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13580/49529 | Успешно: 13580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13590/49529 | Успешно: 13590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13600/49529 | Успешно: 13600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13610/49529 | Успешно: 13610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13620/49529 | Успешно: 13620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13630/49529 | Успешно: 13630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13640/49529 | Успешно: 13640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13650/49529 | Успешно: 13650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13660/49529 | Успешно: 13660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13670/49529 | Успешно: 13670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13680/49529 | Успешно: 13680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13690/49529 | Успешно: 13690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13700/49529 | Успешно: 13700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13710/49529 | Успешно: 13710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13720/49529 | Успешно: 13720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13730/49529 | Успешно: 13730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13740/49529 | Успешно: 13740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13750/49529 | Успешно: 13750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13760/49529 | Успешно: 13760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13770/49529 | Успешно: 13770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13780/49529 | Успешно: 13780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13790/49529 | Успешно: 13790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13800/49529 | Успешно: 13800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13810/49529 | Успешно: 13810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13820/49529 | Успешно: 13820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13830/49529 | Успешно: 13830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13840/49529 | Успешно: 13840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13850/49529 | Успешно: 13850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13860/49529 | Успешно: 13860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13870/49529 | Успешно: 13870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13880/49529 | Успешно: 13880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13890/49529 | Успешно: 13890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13900/49529 | Успешно: 13900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13910/49529 | Успешно: 13910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13920/49529 | Успешно: 13920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13930/49529 | Успешно: 13930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13940/49529 | Успешно: 13940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13950/49529 | Успешно: 13950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13960/49529 | Успешно: 13960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13970/49529 | Успешно: 13970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13980/49529 | Успешно: 13980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 13990/49529 | Успешно: 13990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14000/49529 | Успешно: 14000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14010/49529 | Успешно: 14010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14020/49529 | Успешно: 14020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14030/49529 | Успешно: 14030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14040/49529 | Успешно: 14040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14050/49529 | Успешно: 14050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14060/49529 | Успешно: 14060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14070/49529 | Успешно: 14070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14080/49529 | Успешно: 14080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14090/49529 | Успешно: 14090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14100/49529 | Успешно: 14100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14110/49529 | Успешно: 14110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14120/49529 | Успешно: 14120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14130/49529 | Успешно: 14130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14140/49529 | Успешно: 14140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14150/49529 | Успешно: 14150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14160/49529 | Успешно: 14160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14170/49529 | Успешно: 14170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14180/49529 | Успешно: 14180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14190/49529 | Успешно: 14190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14200/49529 | Успешно: 14200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14210/49529 | Успешно: 14210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14220/49529 | Успешно: 14220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14230/49529 | Успешно: 14230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14240/49529 | Успешно: 14240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14250/49529 | Успешно: 14250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14260/49529 | Успешно: 14260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14270/49529 | Успешно: 14270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14280/49529 | Успешно: 14280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14290/49529 | Успешно: 14290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14300/49529 | Успешно: 14300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14310/49529 | Успешно: 14310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14320/49529 | Успешно: 14320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14330/49529 | Успешно: 14330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14340/49529 | Успешно: 14340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14350/49529 | Успешно: 14350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14360/49529 | Успешно: 14360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14370/49529 | Успешно: 14370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14380/49529 | Успешно: 14380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14390/49529 | Успешно: 14390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14400/49529 | Успешно: 14400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14410/49529 | Успешно: 14410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14420/49529 | Успешно: 14420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14430/49529 | Успешно: 14430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14440/49529 | Успешно: 14440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14450/49529 | Успешно: 14450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14460/49529 | Успешно: 14460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14470/49529 | Успешно: 14470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14480/49529 | Успешно: 14480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14490/49529 | Успешно: 14490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14500/49529 | Успешно: 14500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14510/49529 | Успешно: 14510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14520/49529 | Успешно: 14520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14530/49529 | Успешно: 14530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14540/49529 | Успешно: 14540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14550/49529 | Успешно: 14550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14560/49529 | Успешно: 14560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14570/49529 | Успешно: 14570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14580/49529 | Успешно: 14580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14590/49529 | Успешно: 14590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14600/49529 | Успешно: 14600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14610/49529 | Успешно: 14610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14620/49529 | Успешно: 14620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14630/49529 | Успешно: 14630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14640/49529 | Успешно: 14640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14650/49529 | Успешно: 14650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14660/49529 | Успешно: 14660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14670/49529 | Успешно: 14670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14680/49529 | Успешно: 14680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14690/49529 | Успешно: 14690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14700/49529 | Успешно: 14700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14710/49529 | Успешно: 14710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14720/49529 | Успешно: 14720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14730/49529 | Успешно: 14730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14740/49529 | Успешно: 14740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14750/49529 | Успешно: 14750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14760/49529 | Успешно: 14760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14770/49529 | Успешно: 14770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14780/49529 | Успешно: 14780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14790/49529 | Успешно: 14790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14800/49529 | Успешно: 14800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14810/49529 | Успешно: 14810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14820/49529 | Успешно: 14820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14830/49529 | Успешно: 14830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14840/49529 | Успешно: 14840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14850/49529 | Успешно: 14850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14860/49529 | Успешно: 14860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14870/49529 | Успешно: 14870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14880/49529 | Успешно: 14880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14890/49529 | Успешно: 14890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14900/49529 | Успешно: 14900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14910/49529 | Успешно: 14910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14920/49529 | Успешно: 14920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14930/49529 | Успешно: 14930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14940/49529 | Успешно: 14940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14950/49529 | Успешно: 14950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14960/49529 | Успешно: 14960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14970/49529 | Успешно: 14970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14980/49529 | Успешно: 14980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 14990/49529 | Успешно: 14990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15000/49529 | Успешно: 15000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15010/49529 | Успешно: 15010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15020/49529 | Успешно: 15020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15030/49529 | Успешно: 15030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15040/49529 | Успешно: 15040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15050/49529 | Успешно: 15050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15060/49529 | Успешно: 15060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15070/49529 | Успешно: 15070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15080/49529 | Успешно: 15080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15090/49529 | Успешно: 15090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15100/49529 | Успешно: 15100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15110/49529 | Успешно: 15110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15120/49529 | Успешно: 15120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15130/49529 | Успешно: 15130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15140/49529 | Успешно: 15140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15150/49529 | Успешно: 15150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15160/49529 | Успешно: 15160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15170/49529 | Успешно: 15170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15180/49529 | Успешно: 15180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15190/49529 | Успешно: 15190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15200/49529 | Успешно: 15200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15210/49529 | Успешно: 15210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15220/49529 | Успешно: 15220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15230/49529 | Успешно: 15230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15240/49529 | Успешно: 15240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15250/49529 | Успешно: 15250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15260/49529 | Успешно: 15260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15270/49529 | Успешно: 15270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15280/49529 | Успешно: 15280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15290/49529 | Успешно: 15290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15300/49529 | Успешно: 15300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15310/49529 | Успешно: 15310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15320/49529 | Успешно: 15320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15330/49529 | Успешно: 15330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15340/49529 | Успешно: 15340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15350/49529 | Успешно: 15350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15360/49529 | Успешно: 15360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15370/49529 | Успешно: 15370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15380/49529 | Успешно: 15380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15390/49529 | Успешно: 15390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15400/49529 | Успешно: 15400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15410/49529 | Успешно: 15410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15420/49529 | Успешно: 15420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15430/49529 | Успешно: 15430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15440/49529 | Успешно: 15440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15450/49529 | Успешно: 15450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15460/49529 | Успешно: 15460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15470/49529 | Успешно: 15470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15480/49529 | Успешно: 15480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15490/49529 | Успешно: 15490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15500/49529 | Успешно: 15500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15510/49529 | Успешно: 15510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15520/49529 | Успешно: 15520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15530/49529 | Успешно: 15530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15540/49529 | Успешно: 15540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15550/49529 | Успешно: 15550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15560/49529 | Успешно: 15560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15570/49529 | Успешно: 15570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15580/49529 | Успешно: 15580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15590/49529 | Успешно: 15590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15600/49529 | Успешно: 15600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15610/49529 | Успешно: 15610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15620/49529 | Успешно: 15620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15630/49529 | Успешно: 15630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15640/49529 | Успешно: 15640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15650/49529 | Успешно: 15650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15660/49529 | Успешно: 15660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15670/49529 | Успешно: 15670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15680/49529 | Успешно: 15680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15690/49529 | Успешно: 15690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15700/49529 | Успешно: 15700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15710/49529 | Успешно: 15710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15720/49529 | Успешно: 15720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15730/49529 | Успешно: 15730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15740/49529 | Успешно: 15740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15750/49529 | Успешно: 15750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15760/49529 | Успешно: 15760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15770/49529 | Успешно: 15770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15780/49529 | Успешно: 15780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15790/49529 | Успешно: 15790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15800/49529 | Успешно: 15800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15810/49529 | Успешно: 15810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15820/49529 | Успешно: 15820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15830/49529 | Успешно: 15830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15840/49529 | Успешно: 15840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15850/49529 | Успешно: 15850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15860/49529 | Успешно: 15860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15870/49529 | Успешно: 15870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15880/49529 | Успешно: 15880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15890/49529 | Успешно: 15890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15900/49529 | Успешно: 15900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15910/49529 | Успешно: 15910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15920/49529 | Успешно: 15920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15930/49529 | Успешно: 15930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15940/49529 | Успешно: 15940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15950/49529 | Успешно: 15950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15960/49529 | Успешно: 15960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15970/49529 | Успешно: 15970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15980/49529 | Успешно: 15980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 15990/49529 | Успешно: 15990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16000/49529 | Успешно: 16000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16010/49529 | Успешно: 16010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16020/49529 | Успешно: 16020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16030/49529 | Успешно: 16030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16040/49529 | Успешно: 16040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16050/49529 | Успешно: 16050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16060/49529 | Успешно: 16060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16070/49529 | Успешно: 16070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16080/49529 | Успешно: 16080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16090/49529 | Успешно: 16090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16100/49529 | Успешно: 16100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16110/49529 | Успешно: 16110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16120/49529 | Успешно: 16120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16130/49529 | Успешно: 16130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16140/49529 | Успешно: 16140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16150/49529 | Успешно: 16150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16160/49529 | Успешно: 16160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16170/49529 | Успешно: 16170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16180/49529 | Успешно: 16180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16190/49529 | Успешно: 16190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16200/49529 | Успешно: 16200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16210/49529 | Успешно: 16210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16220/49529 | Успешно: 16220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16230/49529 | Успешно: 16230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16240/49529 | Успешно: 16240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16250/49529 | Успешно: 16250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16260/49529 | Успешно: 16260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16270/49529 | Успешно: 16270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16280/49529 | Успешно: 16280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16290/49529 | Успешно: 16290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16300/49529 | Успешно: 16300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16310/49529 | Успешно: 16310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16320/49529 | Успешно: 16320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16330/49529 | Успешно: 16330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16340/49529 | Успешно: 16340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16350/49529 | Успешно: 16350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16360/49529 | Успешно: 16360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16370/49529 | Успешно: 16370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16380/49529 | Успешно: 16380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16390/49529 | Успешно: 16390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16400/49529 | Успешно: 16400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16410/49529 | Успешно: 16410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16420/49529 | Успешно: 16420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16430/49529 | Успешно: 16430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16440/49529 | Успешно: 16440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16450/49529 | Успешно: 16450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16460/49529 | Успешно: 16460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16470/49529 | Успешно: 16470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16480/49529 | Успешно: 16480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16490/49529 | Успешно: 16490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16500/49529 | Успешно: 16500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16510/49529 | Успешно: 16510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16520/49529 | Успешно: 16520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16530/49529 | Успешно: 16530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16540/49529 | Успешно: 16540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16550/49529 | Успешно: 16550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16560/49529 | Успешно: 16560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16570/49529 | Успешно: 16570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16580/49529 | Успешно: 16580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16590/49529 | Успешно: 16590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16600/49529 | Успешно: 16600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16610/49529 | Успешно: 16610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16620/49529 | Успешно: 16620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16630/49529 | Успешно: 16630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16640/49529 | Успешно: 16640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16650/49529 | Успешно: 16650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16660/49529 | Успешно: 16660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16670/49529 | Успешно: 16670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16680/49529 | Успешно: 16680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16690/49529 | Успешно: 16690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16700/49529 | Успешно: 16700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16710/49529 | Успешно: 16710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16720/49529 | Успешно: 16720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16730/49529 | Успешно: 16730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16740/49529 | Успешно: 16740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16750/49529 | Успешно: 16750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16760/49529 | Успешно: 16760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16770/49529 | Успешно: 16770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16780/49529 | Успешно: 16780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16790/49529 | Успешно: 16790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16800/49529 | Успешно: 16800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16810/49529 | Успешно: 16810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16820/49529 | Успешно: 16820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16830/49529 | Успешно: 16830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16840/49529 | Успешно: 16840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16850/49529 | Успешно: 16850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16860/49529 | Успешно: 16860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16870/49529 | Успешно: 16870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16880/49529 | Успешно: 16880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16890/49529 | Успешно: 16890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16900/49529 | Успешно: 16900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16910/49529 | Успешно: 16910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16920/49529 | Успешно: 16920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16930/49529 | Успешно: 16930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16940/49529 | Успешно: 16940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16950/49529 | Успешно: 16950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16960/49529 | Успешно: 16960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16970/49529 | Успешно: 16970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16980/49529 | Успешно: 16980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 16990/49529 | Успешно: 16990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17000/49529 | Успешно: 17000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17010/49529 | Успешно: 17010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17020/49529 | Успешно: 17020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17030/49529 | Успешно: 17030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17040/49529 | Успешно: 17040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17050/49529 | Успешно: 17050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17060/49529 | Успешно: 17060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17070/49529 | Успешно: 17070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17080/49529 | Успешно: 17080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17090/49529 | Успешно: 17090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17100/49529 | Успешно: 17100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17110/49529 | Успешно: 17110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17120/49529 | Успешно: 17120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17130/49529 | Успешно: 17130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17140/49529 | Успешно: 17140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17150/49529 | Успешно: 17150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17160/49529 | Успешно: 17160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17170/49529 | Успешно: 17170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17180/49529 | Успешно: 17180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17190/49529 | Успешно: 17190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17200/49529 | Успешно: 17200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17210/49529 | Успешно: 17210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17220/49529 | Успешно: 17220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17230/49529 | Успешно: 17230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17240/49529 | Успешно: 17240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17250/49529 | Успешно: 17250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17260/49529 | Успешно: 17260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17270/49529 | Успешно: 17270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17280/49529 | Успешно: 17280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17290/49529 | Успешно: 17290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17300/49529 | Успешно: 17300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17310/49529 | Успешно: 17310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17320/49529 | Успешно: 17320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17330/49529 | Успешно: 17330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17340/49529 | Успешно: 17340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17350/49529 | Успешно: 17350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17360/49529 | Успешно: 17360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17370/49529 | Успешно: 17370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17380/49529 | Успешно: 17380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17390/49529 | Успешно: 17390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17400/49529 | Успешно: 17400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17410/49529 | Успешно: 17410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17420/49529 | Успешно: 17420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17430/49529 | Успешно: 17430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17440/49529 | Успешно: 17440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17450/49529 | Успешно: 17450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17460/49529 | Успешно: 17460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17470/49529 | Успешно: 17470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17480/49529 | Успешно: 17480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17490/49529 | Успешно: 17490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17500/49529 | Успешно: 17500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17510/49529 | Успешно: 17510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17520/49529 | Успешно: 17520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17530/49529 | Успешно: 17530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17540/49529 | Успешно: 17540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17550/49529 | Успешно: 17550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17560/49529 | Успешно: 17560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17570/49529 | Успешно: 17570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17580/49529 | Успешно: 17580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17590/49529 | Успешно: 17590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17600/49529 | Успешно: 17600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17610/49529 | Успешно: 17610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17620/49529 | Успешно: 17620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17630/49529 | Успешно: 17630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17640/49529 | Успешно: 17640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17650/49529 | Успешно: 17650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17660/49529 | Успешно: 17660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17670/49529 | Успешно: 17670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17680/49529 | Успешно: 17680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17690/49529 | Успешно: 17690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17700/49529 | Успешно: 17700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17710/49529 | Успешно: 17710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17720/49529 | Успешно: 17720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17730/49529 | Успешно: 17730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17740/49529 | Успешно: 17740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17750/49529 | Успешно: 17750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17760/49529 | Успешно: 17760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17770/49529 | Успешно: 17770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17780/49529 | Успешно: 17780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17790/49529 | Успешно: 17790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17800/49529 | Успешно: 17800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17810/49529 | Успешно: 17810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17820/49529 | Успешно: 17820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17830/49529 | Успешно: 17830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17840/49529 | Успешно: 17840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17850/49529 | Успешно: 17850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17860/49529 | Успешно: 17860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17870/49529 | Успешно: 17870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17880/49529 | Успешно: 17880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17890/49529 | Успешно: 17890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17900/49529 | Успешно: 17900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17910/49529 | Успешно: 17910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17920/49529 | Успешно: 17920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17930/49529 | Успешно: 17930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17940/49529 | Успешно: 17940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17950/49529 | Успешно: 17950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17960/49529 | Успешно: 17960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17970/49529 | Успешно: 17970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17980/49529 | Успешно: 17980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 17990/49529 | Успешно: 17990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18000/49529 | Успешно: 18000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18010/49529 | Успешно: 18010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18020/49529 | Успешно: 18020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18030/49529 | Успешно: 18030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18040/49529 | Успешно: 18040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18050/49529 | Успешно: 18050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18060/49529 | Успешно: 18060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18070/49529 | Успешно: 18070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18080/49529 | Успешно: 18080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18090/49529 | Успешно: 18090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18100/49529 | Успешно: 18100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18110/49529 | Успешно: 18110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18120/49529 | Успешно: 18120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18130/49529 | Успешно: 18130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18140/49529 | Успешно: 18140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18150/49529 | Успешно: 18150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18160/49529 | Успешно: 18160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18170/49529 | Успешно: 18170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18180/49529 | Успешно: 18180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18190/49529 | Успешно: 18190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18200/49529 | Успешно: 18200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18210/49529 | Успешно: 18210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18220/49529 | Успешно: 18220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18230/49529 | Успешно: 18230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18240/49529 | Успешно: 18240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18250/49529 | Успешно: 18250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18260/49529 | Успешно: 18260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18270/49529 | Успешно: 18270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18280/49529 | Успешно: 18280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18290/49529 | Успешно: 18290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18300/49529 | Успешно: 18300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18310/49529 | Успешно: 18310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18320/49529 | Успешно: 18320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18330/49529 | Успешно: 18330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18340/49529 | Успешно: 18340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18350/49529 | Успешно: 18350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18360/49529 | Успешно: 18360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18370/49529 | Успешно: 18370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18380/49529 | Успешно: 18380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18390/49529 | Успешно: 18390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18400/49529 | Успешно: 18400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18410/49529 | Успешно: 18410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18420/49529 | Успешно: 18420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18430/49529 | Успешно: 18430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18440/49529 | Успешно: 18440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18450/49529 | Успешно: 18450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18460/49529 | Успешно: 18460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18470/49529 | Успешно: 18470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18480/49529 | Успешно: 18480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18490/49529 | Успешно: 18490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18500/49529 | Успешно: 18500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18510/49529 | Успешно: 18510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18520/49529 | Успешно: 18520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18530/49529 | Успешно: 18530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18540/49529 | Успешно: 18540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18550/49529 | Успешно: 18550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18560/49529 | Успешно: 18560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18570/49529 | Успешно: 18570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18580/49529 | Успешно: 18580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18590/49529 | Успешно: 18590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18600/49529 | Успешно: 18600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18610/49529 | Успешно: 18610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18620/49529 | Успешно: 18620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18630/49529 | Успешно: 18630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18640/49529 | Успешно: 18640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18650/49529 | Успешно: 18650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18660/49529 | Успешно: 18660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18670/49529 | Успешно: 18670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18680/49529 | Успешно: 18680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18690/49529 | Успешно: 18690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18700/49529 | Успешно: 18700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18710/49529 | Успешно: 18710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18720/49529 | Успешно: 18720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18730/49529 | Успешно: 18730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18740/49529 | Успешно: 18740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18750/49529 | Успешно: 18750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18760/49529 | Успешно: 18760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18770/49529 | Успешно: 18770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18780/49529 | Успешно: 18780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18790/49529 | Успешно: 18790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18800/49529 | Успешно: 18800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18810/49529 | Успешно: 18810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18820/49529 | Успешно: 18820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18830/49529 | Успешно: 18830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18840/49529 | Успешно: 18840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18850/49529 | Успешно: 18850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18860/49529 | Успешно: 18860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18870/49529 | Успешно: 18870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18880/49529 | Успешно: 18880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18890/49529 | Успешно: 18890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18900/49529 | Успешно: 18900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18910/49529 | Успешно: 18910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18920/49529 | Успешно: 18920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18930/49529 | Успешно: 18930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18940/49529 | Успешно: 18940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18950/49529 | Успешно: 18950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18960/49529 | Успешно: 18960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18970/49529 | Успешно: 18970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18980/49529 | Успешно: 18980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 18990/49529 | Успешно: 18990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19000/49529 | Успешно: 19000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19010/49529 | Успешно: 19010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19020/49529 | Успешно: 19020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19030/49529 | Успешно: 19030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19040/49529 | Успешно: 19040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19050/49529 | Успешно: 19050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19060/49529 | Успешно: 19060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19070/49529 | Успешно: 19070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19080/49529 | Успешно: 19080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19090/49529 | Успешно: 19090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19100/49529 | Успешно: 19100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19110/49529 | Успешно: 19110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19120/49529 | Успешно: 19120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19130/49529 | Успешно: 19130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19140/49529 | Успешно: 19140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19150/49529 | Успешно: 19150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19160/49529 | Успешно: 19160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19170/49529 | Успешно: 19170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19180/49529 | Успешно: 19180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19190/49529 | Успешно: 19190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19200/49529 | Успешно: 19200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19210/49529 | Успешно: 19210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19220/49529 | Успешно: 19220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19230/49529 | Успешно: 19230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19240/49529 | Успешно: 19240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19250/49529 | Успешно: 19250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19260/49529 | Успешно: 19260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19270/49529 | Успешно: 19270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19280/49529 | Успешно: 19280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19290/49529 | Успешно: 19290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19300/49529 | Успешно: 19300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19310/49529 | Успешно: 19310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19320/49529 | Успешно: 19320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19330/49529 | Успешно: 19330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19340/49529 | Успешно: 19340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19350/49529 | Успешно: 19350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19360/49529 | Успешно: 19360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19370/49529 | Успешно: 19370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19380/49529 | Успешно: 19380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19390/49529 | Успешно: 19390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19400/49529 | Успешно: 19400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19410/49529 | Успешно: 19410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19420/49529 | Успешно: 19420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19430/49529 | Успешно: 19430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19440/49529 | Успешно: 19440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19450/49529 | Успешно: 19450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19460/49529 | Успешно: 19460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19470/49529 | Успешно: 19470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19480/49529 | Успешно: 19480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19490/49529 | Успешно: 19490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19500/49529 | Успешно: 19500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19510/49529 | Успешно: 19510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19520/49529 | Успешно: 19520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19530/49529 | Успешно: 19530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19540/49529 | Успешно: 19540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19550/49529 | Успешно: 19550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19560/49529 | Успешно: 19560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19570/49529 | Успешно: 19570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19580/49529 | Успешно: 19580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19590/49529 | Успешно: 19590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19600/49529 | Успешно: 19600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19610/49529 | Успешно: 19610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19620/49529 | Успешно: 19620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19630/49529 | Успешно: 19630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19640/49529 | Успешно: 19640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19650/49529 | Успешно: 19650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19660/49529 | Успешно: 19660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19670/49529 | Успешно: 19670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19680/49529 | Успешно: 19680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19690/49529 | Успешно: 19690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19700/49529 | Успешно: 19700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19710/49529 | Успешно: 19710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19720/49529 | Успешно: 19720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19730/49529 | Успешно: 19730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19740/49529 | Успешно: 19740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19750/49529 | Успешно: 19750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19760/49529 | Успешно: 19760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19770/49529 | Успешно: 19770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19780/49529 | Успешно: 19780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19790/49529 | Успешно: 19790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19800/49529 | Успешно: 19800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19810/49529 | Успешно: 19810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19820/49529 | Успешно: 19820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19830/49529 | Успешно: 19830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19840/49529 | Успешно: 19840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19850/49529 | Успешно: 19850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19860/49529 | Успешно: 19860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19870/49529 | Успешно: 19870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19880/49529 | Успешно: 19880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19890/49529 | Успешно: 19890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19900/49529 | Успешно: 19900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19910/49529 | Успешно: 19910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19920/49529 | Успешно: 19920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19930/49529 | Успешно: 19930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19940/49529 | Успешно: 19940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19950/49529 | Успешно: 19950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19960/49529 | Успешно: 19960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19970/49529 | Успешно: 19970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19980/49529 | Успешно: 19980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 19990/49529 | Успешно: 19990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20000/49529 | Успешно: 20000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20010/49529 | Успешно: 20010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20020/49529 | Успешно: 20020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20030/49529 | Успешно: 20030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20040/49529 | Успешно: 20040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20050/49529 | Успешно: 20050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20060/49529 | Успешно: 20060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20070/49529 | Успешно: 20070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20080/49529 | Успешно: 20080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20090/49529 | Успешно: 20090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20100/49529 | Успешно: 20100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20110/49529 | Успешно: 20110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20120/49529 | Успешно: 20120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20130/49529 | Успешно: 20130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20140/49529 | Успешно: 20140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20150/49529 | Успешно: 20150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20160/49529 | Успешно: 20160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20170/49529 | Успешно: 20170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20180/49529 | Успешно: 20180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20190/49529 | Успешно: 20190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20200/49529 | Успешно: 20200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20210/49529 | Успешно: 20210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20220/49529 | Успешно: 20220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20230/49529 | Успешно: 20230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20240/49529 | Успешно: 20240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20250/49529 | Успешно: 20250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20260/49529 | Успешно: 20260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20270/49529 | Успешно: 20270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20280/49529 | Успешно: 20280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20290/49529 | Успешно: 20290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20300/49529 | Успешно: 20300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20310/49529 | Успешно: 20310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20320/49529 | Успешно: 20320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20330/49529 | Успешно: 20330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20340/49529 | Успешно: 20340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20350/49529 | Успешно: 20350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20360/49529 | Успешно: 20360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20370/49529 | Успешно: 20370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20380/49529 | Успешно: 20380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20390/49529 | Успешно: 20390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20400/49529 | Успешно: 20400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20410/49529 | Успешно: 20410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20420/49529 | Успешно: 20420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20430/49529 | Успешно: 20430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20440/49529 | Успешно: 20440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20450/49529 | Успешно: 20450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20460/49529 | Успешно: 20460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20470/49529 | Успешно: 20470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20480/49529 | Успешно: 20480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20490/49529 | Успешно: 20490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20500/49529 | Успешно: 20500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20510/49529 | Успешно: 20510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20520/49529 | Успешно: 20520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20530/49529 | Успешно: 20530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20540/49529 | Успешно: 20540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20550/49529 | Успешно: 20550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20560/49529 | Успешно: 20560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20570/49529 | Успешно: 20570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20580/49529 | Успешно: 20580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20590/49529 | Успешно: 20590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20600/49529 | Успешно: 20600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20610/49529 | Успешно: 20610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20620/49529 | Успешно: 20620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20630/49529 | Успешно: 20630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20640/49529 | Успешно: 20640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20650/49529 | Успешно: 20650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20660/49529 | Успешно: 20660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20670/49529 | Успешно: 20670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20680/49529 | Успешно: 20680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20690/49529 | Успешно: 20690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20700/49529 | Успешно: 20700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20710/49529 | Успешно: 20710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20720/49529 | Успешно: 20720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20730/49529 | Успешно: 20730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20740/49529 | Успешно: 20740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20750/49529 | Успешно: 20750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20760/49529 | Успешно: 20760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20770/49529 | Успешно: 20770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20780/49529 | Успешно: 20780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20790/49529 | Успешно: 20790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20800/49529 | Успешно: 20800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20810/49529 | Успешно: 20810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20820/49529 | Успешно: 20820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20830/49529 | Успешно: 20830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20840/49529 | Успешно: 20840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20850/49529 | Успешно: 20850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20860/49529 | Успешно: 20860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20870/49529 | Успешно: 20870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20880/49529 | Успешно: 20880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20890/49529 | Успешно: 20890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20900/49529 | Успешно: 20900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20910/49529 | Успешно: 20910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20920/49529 | Успешно: 20920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20930/49529 | Успешно: 20930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20940/49529 | Успешно: 20940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20950/49529 | Успешно: 20950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20960/49529 | Успешно: 20960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20970/49529 | Успешно: 20970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20980/49529 | Успешно: 20980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 20990/49529 | Успешно: 20990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21000/49529 | Успешно: 21000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21010/49529 | Успешно: 21010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21020/49529 | Успешно: 21020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21030/49529 | Успешно: 21030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21040/49529 | Успешно: 21040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21050/49529 | Успешно: 21050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21060/49529 | Успешно: 21060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21070/49529 | Успешно: 21070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21080/49529 | Успешно: 21080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21090/49529 | Успешно: 21090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21100/49529 | Успешно: 21100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21110/49529 | Успешно: 21110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21120/49529 | Успешно: 21120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21130/49529 | Успешно: 21130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21140/49529 | Успешно: 21140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21150/49529 | Успешно: 21150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21160/49529 | Успешно: 21160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21170/49529 | Успешно: 21170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21180/49529 | Успешно: 21180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21190/49529 | Успешно: 21190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21200/49529 | Успешно: 21200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21210/49529 | Успешно: 21210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21220/49529 | Успешно: 21220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21230/49529 | Успешно: 21230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21240/49529 | Успешно: 21240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21250/49529 | Успешно: 21250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21260/49529 | Успешно: 21260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21270/49529 | Успешно: 21270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21280/49529 | Успешно: 21280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21290/49529 | Успешно: 21290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21300/49529 | Успешно: 21300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21310/49529 | Успешно: 21310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21320/49529 | Успешно: 21320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21330/49529 | Успешно: 21330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21340/49529 | Успешно: 21340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21350/49529 | Успешно: 21350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21360/49529 | Успешно: 21360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21370/49529 | Успешно: 21370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21380/49529 | Успешно: 21380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21390/49529 | Успешно: 21390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21400/49529 | Успешно: 21400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21410/49529 | Успешно: 21410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21420/49529 | Успешно: 21420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21430/49529 | Успешно: 21430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21440/49529 | Успешно: 21440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21450/49529 | Успешно: 21450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21460/49529 | Успешно: 21460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21470/49529 | Успешно: 21470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21480/49529 | Успешно: 21480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21490/49529 | Успешно: 21490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21500/49529 | Успешно: 21500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21510/49529 | Успешно: 21510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21520/49529 | Успешно: 21520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21530/49529 | Успешно: 21530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21540/49529 | Успешно: 21540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21550/49529 | Успешно: 21550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21560/49529 | Успешно: 21560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21570/49529 | Успешно: 21570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21580/49529 | Успешно: 21580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21590/49529 | Успешно: 21590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21600/49529 | Успешно: 21600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21610/49529 | Успешно: 21610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21620/49529 | Успешно: 21620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21630/49529 | Успешно: 21630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21640/49529 | Успешно: 21640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21650/49529 | Успешно: 21650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21660/49529 | Успешно: 21660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21670/49529 | Успешно: 21670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21680/49529 | Успешно: 21680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21690/49529 | Успешно: 21690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21700/49529 | Успешно: 21700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21710/49529 | Успешно: 21710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21720/49529 | Успешно: 21720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21730/49529 | Успешно: 21730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21740/49529 | Успешно: 21740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21750/49529 | Успешно: 21750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21760/49529 | Успешно: 21760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21770/49529 | Успешно: 21770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21780/49529 | Успешно: 21780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21790/49529 | Успешно: 21790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21800/49529 | Успешно: 21800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21810/49529 | Успешно: 21810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21820/49529 | Успешно: 21820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21830/49529 | Успешно: 21830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21840/49529 | Успешно: 21840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21850/49529 | Успешно: 21850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21860/49529 | Успешно: 21860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21870/49529 | Успешно: 21870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21880/49529 | Успешно: 21880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21890/49529 | Успешно: 21890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21900/49529 | Успешно: 21900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21910/49529 | Успешно: 21910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21920/49529 | Успешно: 21920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21930/49529 | Успешно: 21930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21940/49529 | Успешно: 21940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21950/49529 | Успешно: 21950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21960/49529 | Успешно: 21960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21970/49529 | Успешно: 21970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21980/49529 | Успешно: 21980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 21990/49529 | Успешно: 21990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22000/49529 | Успешно: 22000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22010/49529 | Успешно: 22010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22020/49529 | Успешно: 22020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22030/49529 | Успешно: 22030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22040/49529 | Успешно: 22040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22050/49529 | Успешно: 22050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22060/49529 | Успешно: 22060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22070/49529 | Успешно: 22070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22080/49529 | Успешно: 22080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22090/49529 | Успешно: 22090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22100/49529 | Успешно: 22100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22110/49529 | Успешно: 22110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22120/49529 | Успешно: 22120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22130/49529 | Успешно: 22130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22140/49529 | Успешно: 22140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22150/49529 | Успешно: 22150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22160/49529 | Успешно: 22160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22170/49529 | Успешно: 22170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22180/49529 | Успешно: 22180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22190/49529 | Успешно: 22190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22200/49529 | Успешно: 22200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22210/49529 | Успешно: 22210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22220/49529 | Успешно: 22220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22230/49529 | Успешно: 22230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22240/49529 | Успешно: 22240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22250/49529 | Успешно: 22250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22260/49529 | Успешно: 22260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22270/49529 | Успешно: 22270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22280/49529 | Успешно: 22280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22290/49529 | Успешно: 22290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22300/49529 | Успешно: 22300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22310/49529 | Успешно: 22310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22320/49529 | Успешно: 22320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22330/49529 | Успешно: 22330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22340/49529 | Успешно: 22340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22350/49529 | Успешно: 22350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22360/49529 | Успешно: 22360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22370/49529 | Успешно: 22370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22380/49529 | Успешно: 22380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22390/49529 | Успешно: 22390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22400/49529 | Успешно: 22400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22410/49529 | Успешно: 22410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22420/49529 | Успешно: 22420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22430/49529 | Успешно: 22430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22440/49529 | Успешно: 22440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22450/49529 | Успешно: 22450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22460/49529 | Успешно: 22460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22470/49529 | Успешно: 22470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22480/49529 | Успешно: 22480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22490/49529 | Успешно: 22490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22500/49529 | Успешно: 22500 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22510/49529 | Успешно: 22510 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22520/49529 | Успешно: 22520 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22530/49529 | Успешно: 22530 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22540/49529 | Успешно: 22540 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22550/49529 | Успешно: 22550 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22560/49529 | Успешно: 22560 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22570/49529 | Успешно: 22570 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22580/49529 | Успешно: 22580 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22590/49529 | Успешно: 22590 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22600/49529 | Успешно: 22600 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22610/49529 | Успешно: 22610 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22620/49529 | Успешно: 22620 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22630/49529 | Успешно: 22630 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22640/49529 | Успешно: 22640 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22650/49529 | Успешно: 22650 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22660/49529 | Успешно: 22660 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22670/49529 | Успешно: 22670 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22680/49529 | Успешно: 22680 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22690/49529 | Успешно: 22690 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22700/49529 | Успешно: 22700 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22710/49529 | Успешно: 22710 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22720/49529 | Успешно: 22720 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22730/49529 | Успешно: 22730 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22740/49529 | Успешно: 22740 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22750/49529 | Успешно: 22750 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22760/49529 | Успешно: 22760 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22770/49529 | Успешно: 22770 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22780/49529 | Успешно: 22780 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22790/49529 | Успешно: 22790 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22800/49529 | Успешно: 22800 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22810/49529 | Успешно: 22810 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22820/49529 | Успешно: 22820 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22830/49529 | Успешно: 22830 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22840/49529 | Успешно: 22840 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22850/49529 | Успешно: 22850 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22860/49529 | Успешно: 22860 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22870/49529 | Успешно: 22870 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22880/49529 | Успешно: 22880 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22890/49529 | Успешно: 22890 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22900/49529 | Успешно: 22900 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22910/49529 | Успешно: 22910 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22920/49529 | Успешно: 22920 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22930/49529 | Успешно: 22930 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22940/49529 | Успешно: 22940 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22950/49529 | Успешно: 22950 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22960/49529 | Успешно: 22960 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22970/49529 | Успешно: 22970 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22980/49529 | Успешно: 22980 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 22990/49529 | Успешно: 22990 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23000/49529 | Успешно: 23000 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23010/49529 | Успешно: 23010 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23020/49529 | Успешно: 23020 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23030/49529 | Успешно: 23030 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23040/49529 | Успешно: 23040 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23050/49529 | Успешно: 23050 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23060/49529 | Успешно: 23060 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23070/49529 | Успешно: 23070 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23080/49529 | Успешно: 23080 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23090/49529 | Успешно: 23090 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23100/49529 | Успешно: 23100 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23110/49529 | Успешно: 23110 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23120/49529 | Успешно: 23120 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23130/49529 | Успешно: 23130 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23140/49529 | Успешно: 23140 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23150/49529 | Успешно: 23150 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23160/49529 | Успешно: 23160 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23170/49529 | Успешно: 23170 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23180/49529 | Успешно: 23180 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23190/49529 | Успешно: 23190 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23200/49529 | Успешно: 23200 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23210/49529 | Успешно: 23210 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23220/49529 | Успешно: 23220 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23230/49529 | Успешно: 23230 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23240/49529 | Успешно: 23240 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23250/49529 | Успешно: 23250 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23260/49529 | Успешно: 23260 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23270/49529 | Успешно: 23270 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23280/49529 | Успешно: 23280 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23290/49529 | Успешно: 23290 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23300/49529 | Успешно: 23300 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23310/49529 | Успешно: 23310 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23320/49529 | Успешно: 23320 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23330/49529 | Успешно: 23330 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23340/49529 | Успешно: 23340 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23350/49529 | Успешно: 23350 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23360/49529 | Успешно: 23360 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23370/49529 | Успешно: 23370 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23380/49529 | Успешно: 23380 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23390/49529 | Успешно: 23390 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23400/49529 | Успешно: 23400 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23410/49529 | Успешно: 23410 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23420/49529 | Успешно: 23420 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23430/49529 | Успешно: 23430 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23440/49529 | Успешно: 23440 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23450/49529 | Успешно: 23450 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23460/49529 | Успешно: 23460 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23470/49529 | Успешно: 23470 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23480/49529 | Успешно: 23480 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23490/49529 | Успешно: 23490 | Ошибки: 0\n", + "INFO:geo.download_images:Прогресс: 23500/49529 | Успешно: 23500 | Ошибки: 0\n" + ] + } + ], + "source": [ + "def main():\n", + " \"\"\"Пример использования клиента с разбивкой bbox\"\"\"\n", + " load_dotenv()\n", + " \n", + " # Инициализация S3 менеджера\n", + " s3_manager = S3Manager(\n", + " max_workers=8,\n", + " chunk_size=16 * 1024 * 1024\n", + " )\n", + " \n", + " # Инициализация Mapillary клиента\n", + " mapillary_client = MapillaryS3Client(\n", + " access_token=os.getenv('API_MAPILLARY_KEY'),\n", + " s3_manager=s3_manager,\n", + " max_workers=8,\n", + " cache_dir=ROOT_DIR / 'logs/download_data/cache_moscow_images'\n", + " )\n", + " \n", + " # Основной bbox для Москвы\n", + " moscow_oblast_bbox = [36.866323, 55.334271, 38.564470, 56.191264]\n", + " moscow_bbox = [37.366723, 55.579170, 37.841304, 55.907936]\n", + " \n", + " # Вариант 1: Автоматическое разбиение большого bbox\n", + " logger.info(\"=== Вариант 1: Автоматическое разбиение большого bbox ===\")\n", + " images = mapillary_client.get_images_for_large_area(\n", + " bbox=moscow_bbox,\n", + " max_results_per_bbox=500,\n", + " use_cache=True\n", + " )\n", + " \n", + " # Вариант 2: Сетка вокруг центральной точки\n", + " # logger.info(\"=== Вариант 2: Сетка вокруг центральной точки ===\")\n", + " # moscow_center = (55.7558, 37.6173) # Кремль\n", + " # images = mapillary_client.get_images_around_point(\n", + " # center_lat=moscow_center[0],\n", + " # center_lon=moscow_center[1],\n", + " # grid_radius=3, # 7x7 = 49 bbox\n", + " # bbox_size=0.01, # Размер каждого bbox\n", + " # max_results_per_bbox=300\n", + " # )\n", + " \n", + " if images:\n", + " logger.info(f\"Найдено {len(images)} изображений. Начинаем загрузку в S3...\")\n", + " \n", + " # Загружаем в S3\n", + " start_time = time.time()\n", + " results = mapillary_client.download_and_upload_to_s3(\n", + " images=images,\n", + " s3_prefix=\"site/raw_data\",\n", + " image_format=\"JPEG\", \n", + " quality=80\n", + " )\n", + " \n", + " duration = time.time() - start_time\n", + " logger.info(f\"Загрузка завершена за {duration:.2f} секунд\")\n", + " \n", + " # Сохраняем метаданные\n", + " timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n", + " mapillary_client.save_metadata_to_csv(\n", + " images, \n", + " ROOT_DIR / 'data/processed_data/moscow_images.csv',\n", + " )\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebc61272", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:utils.s3_optimize:Успешно подключились к S3 бакету: s3-dvc\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Download progress: 10/50\n", + "Download progress: 20/50\n", + "Download progress: 30/50\n", + "Download progress: 40/50\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:utils.s3_optimize:Пакетная загрузка завершена: 50/50 успешно\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Download progress: 50/50\n" + ] + } + ], + "source": [ + "s3_manager = S3Manager(\n", + " max_workers=4,\n", + " chunk_size=16 * 1024 * 1024\n", + " )\n", + "\n", + "s3_files = s3_manager.list_files(prefix=\"site/raw_data/\", file_extensions=[\".jpg\", \".jpeg\", \".png\"])\n", + "download_results = s3_manager.batch_download_files(\n", + " s3_files,\n", + " local_dir=ROOT_DIR / 'data/processed_data/moscow_image',\n", + " progress_callback=lambda current, total: print(f\"Download progress: {current}/{total}\")\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "hack_digital_transformation", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/2_model_training/2_1_train_optuna.ipynb b/notebooks/2_model_training/2_1_train_optuna.ipynb new file mode 100644 index 0000000..7d93517 --- /dev/null +++ b/notebooks/2_model_training/2_1_train_optuna.ipynb @@ -0,0 +1,345 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2f11dabb", + "metadata": {}, + "source": [ + "# Подготовка ноутбука " + ] + }, + { + "cell_type": "markdown", + "id": "85f07fbd", + "metadata": {}, + "source": [ + "## Пробрасываем magic methods" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97feaebc", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "%reload_ext autoreload" + ] + }, + { + "cell_type": "markdown", + "id": "a5324521", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd10fe31", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import numpy as np \n", + "from data.prepare_data import PrepareData\n", + "from dotenv import load_dotenv\n", + "import os \n", + "from pathlib import Path\n", + "from warnings import filterwarnings \n", + "import torch \n", + "import torchvision\n", + "from torch.utils.data import DataLoader\n", + "from IPython.display import display\n", + "import pytesseract\n", + "import shutil\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image\n", + "import cv2" + ] + }, + { + "cell_type": "markdown", + "id": "8f5e2582", + "metadata": {}, + "source": [ + "## Нужные переменные " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7ef1558", + "metadata": {}, + "outputs": [], + "source": [ + "ROOT_DIR = Path('../../')\n", + "load_dotenv()\n", + "filterwarnings(action='ignore')" + ] + }, + { + "cell_type": "markdown", + "id": "6dee36be", + "metadata": {}, + "source": [ + "# Подбор параметров для модели " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fb26062", + "metadata": {}, + "outputs": [], + "source": [ + "import cv2\n", + "import numpy as np\n", + "import easyocr\n", + "import re\n", + "from typing import List, Tuple, Optional\n", + "\n", + "class OverlayOCR:\n", + " WHITELIST_RE = re.compile(r\"[A-Za-z0-9_]+\")\n", + "\n", + " def __init__(\n", + " self,\n", + " langs: Optional[List[str]] = None,\n", + " gpu: bool = False,\n", + " verbose: bool = False,\n", + " gap_mult: float = 1.6,\n", + " canvas_size: int = 3600,\n", + " mag_ratio: float = 3.0,\n", + " add_margin: float = 0.10,\n", + " text_threshold: float = 0.55,\n", + " low_text: float = 0.30,\n", + " link_threshold: float = 0.30,\n", + " ):\n", + " \"\"\"\n", + " langs: языки easyocr, напр. ['en'] или ['en','ru']\n", + " gap_mult: чувствительность к горизонтальным разрывам (меньше -> больше '_')\n", + " canvas_size/mag_ratio: масштабирование внутри easyocr\n", + " \"\"\"\n", + " self.langs = langs or ['en']\n", + " self.reader = easyocr.Reader(self.langs, gpu=gpu, verbose=verbose)\n", + " self.gap_mult = gap_mult\n", + " self.canvas_size = canvas_size\n", + " self.mag_ratio = mag_ratio\n", + " self.add_margin = add_margin\n", + " self.text_threshold = text_threshold\n", + " self.low_text = low_text\n", + " self.link_threshold = link_threshold\n", + "\n", + " # ---------- утилиты ----------\n", + " @staticmethod\n", + " def _clean_token(t: str) -> str:\n", + " return \"\".join(OverlayOCR.WHITELIST_RE.findall(t))\n", + "\n", + " @staticmethod\n", + " def _alnum_class(ch: str) -> str:\n", + " return 'D' if ch.isdigit() else ('A' if ch.isalpha() else '_')\n", + "\n", + " def _join_with_gaps(self, results, sep='_') -> Tuple[str, float, list]:\n", + " \"\"\"\n", + " Склейка токенов слева направо:\n", + " - '_' если горизонтальный зазор >> медианного,\n", + " - '_' на границах A<->D.\n", + " \"\"\"\n", + " items = []\n", + " for bbox, text, conf in results:\n", + " t = self._clean_token(text)\n", + " if not t:\n", + " continue\n", + " x0 = min(p[0] for p in bbox); x1 = max(p[0] for p in bbox)\n", + " items.append((x0, x1, t, float(conf)))\n", + " if not items:\n", + " return \"\", 0.0, []\n", + "\n", + " items.sort(key=lambda z: z[0])\n", + " gaps = []\n", + " for i in range(1, len(items)):\n", + " gaps.append(items[i][0] - items[i-1][1])\n", + " med_gap = np.median(gaps) if gaps else 0\n", + "\n", + " out = []\n", + " confs = []\n", + " prev = None\n", + " for i, (x0, x1, t, c) in enumerate(items):\n", + " if prev is not None:\n", + " gap = x0 - prev[1]\n", + " need_sep = (med_gap > 0 and gap > self.gap_mult * med_gap)\n", + " # буква↔️цифра – полезно отделить\n", + " if not need_sep:\n", + " prev_last = out[-1][-1] if out else ''\n", + " if prev_last and t:\n", + " need_sep = (self._alnum_class(prev_last) != self._alnum_class(t[0]))\n", + " if need_sep and (not out or out[-1] != sep):\n", + " out.append(sep)\n", + " out.append(t)\n", + " confs.append(c)\n", + " prev = (x0, x1)\n", + "\n", + " text = \"\".join(out)\n", + " text = re.sub(r\"_+\", \"_\", text).strip(\"_\")\n", + " avg_conf = float(sum(confs)/len(confs)) if confs else 0.0\n", + " return text, avg_conf, items\n", + "\n", + " @staticmethod\n", + " def _normalize_overlays(s: str) -> str:\n", + " \"\"\"Правки под формат MMC_hd_... и расстановка подчёркиваний.\"\"\"\n", + " s = re.sub(r\"^MMC(?:_)?h(?:d)?\", \"MMC_hd\", s, flags=re.IGNORECASE)\n", + " s = re.sub(r\"^MMC_?hd_?\", \"MMC_hd_\", s, flags=re.IGNORECASE)\n", + " s = re.sub(r\"([A-Za-z])([0-9])\", r\"\\1_\\2\", s)\n", + " s = re.sub(r\"([0-9])([A-Za-z])\", r\"\\1_\\2\", s)\n", + " s = re.sub(r\"_+\", \"_\", s).strip(\"_\")\n", + " return s\n", + "\n", + " @staticmethod\n", + " def _snap_digits_tail(s: str) -> str:\n", + " \"\"\"\n", + " Если хвост цифр склеен, режем на 4-1-1 (типичный случай).\n", + " Пример: ...229221 -> ...2292_2_1\n", + " \"\"\"\n", + " m = re.search(r\"^(.*?)(\\d{6,})$\", s)\n", + " if not m:\n", + " return s\n", + " head, digits = m.group(1), m.group(2)\n", + " if len(digits) >= 6:\n", + " s = f\"{head}{digits[:4]}_{digits[4:5]}_{digits[5:]}\"\n", + " return re.sub(r\"_+\", \"_\", s).strip(\"_\")\n", + "\n", + "\n", + " # ---------- EasyOCR запуск на ROI ----------\n", + " def run_on_roi(self, roi_bgr) -> Tuple[str, str, str, float]:\n", + " params = dict(\n", + " decoder='greedy',\n", + " detail=1,\n", + " paragraph=False,\n", + " contrast_ths=0.05,\n", + " adjust_contrast=0.7,\n", + " text_threshold=self.text_threshold,\n", + " low_text=self.low_text,\n", + " link_threshold=self.link_threshold,\n", + " canvas_size=self.canvas_size,\n", + " mag_ratio=self.mag_ratio,\n", + " add_margin=self.add_margin,\n", + " )\n", + " results = self.reader.readtext(roi_bgr, **params)\n", + " joined, conf, _ = self._join_with_gaps(results, sep=\"_\")\n", + " norm = self._normalize_overlays(joined)\n", + " final = self._snap_digits_tail(norm)\n", + " final = re.sub(r\"^MMC_?hd_?\", \"MMC_hd_\", final, flags=re.IGNORECASE)\n", + " final = re.sub(r\"_+\", \"_\", final).strip(\"_\")\n", + " return joined, norm, final, conf\n", + "\n", + " # ---------- ROI генераторы ----------\n", + " @staticmethod\n", + " def roi_left_bottom(img, w_frac=1/3, h_frac=1/4):\n", + " H, W = img.shape[:2]\n", + " return img[H - int(H*h_frac):H, 0:int(W*w_frac)]\n", + "\n", + " @staticmethod\n", + " def roi_bottom_band(img, h_frac=1/3):\n", + " H, _ = img.shape[:2]\n", + " y0 = H - int(H*h_frac)\n", + " return img[y0:H, :]\n", + "\n", + " @staticmethod\n", + " def roi_auto_band(img):\n", + " g = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", + " _, b = cv2.threshold(cv2.GaussianBlur(g, (5,5), 0), 0, 255,\n", + " cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)\n", + " row = (b > 0).sum(axis=1).astype(np.float32)\n", + " k = max(3, (img.shape[0]//100)*2+1)\n", + " row = cv2.GaussianBlur(row.reshape(-1,1),(1,k),0).ravel()\n", + " start = img.shape[0]//2\n", + " idx = start + int(np.argmax(row[start:]))\n", + " band_half = max(img.shape[0]//12, 20)\n", + " y0, y1 = max(0, idx-band_half), min(img.shape[0], idx+band_half)\n", + " return img[y0:y1, :]\n", + "\n", + " # ---------- главный метод ----------\n", + " def run_on_image(self, image_path: str) -> Tuple[str, str, str, float, str]:\n", + " \"\"\"\n", + " Возвращает:\n", + " final, norm, joined, conf, best_roi_name\n", + " \"\"\"\n", + " img = cv2.imread(image_path)\n", + " assert img is not None, f\"Не удалось загрузить изображение: {image_path}\"\n", + "\n", + " rois = [\n", + " (\"left_bottom\", self.roi_left_bottom(img, 1/3, 1/4)),\n", + " (\"bottom_band\", self.roi_bottom_band(img, 1/3)),\n", + " (\"auto_band\", self.roi_auto_band(img)),\n", + " ]\n", + "\n", + " best = None\n", + " best_name = \"\"\n", + " best_pack = (\"\", \"\", \"\", 0.0)\n", + "\n", + " for name, roi in rois:\n", + " joined, norm, final, conf = self.run_on_roi(roi)\n", + " cand = (conf, len(final), (final, norm, joined, conf), name)\n", + " if (best is None) or (cand > best):\n", + " best = cand\n", + " best_pack = (final, norm, joined, conf)\n", + " best_name = name\n", + "\n", + " final, norm, joined, conf = best_pack\n", + " return final, norm, joined, conf, best_name\n", + "\n", + "\n", + "# ===================== пример использования =====================\n", + "\n", + "if __name__ == \"__main__\":\n", + " IMG = r'/home/lizardapn/Hack_digital/hack_digital_transformation/data/raw_data/data/metadata/INC/united_image/0a0ee2fb-b7ad-4430-97d7-281e2c293041.jpg'\n", + "\n", + " best_params = {\n", + " 'gap_mult': 1.250390875206645, \n", + " 'canvas_size': 3600, \n", + " 'mag_ratio': 3.863566398112844,\n", + " 'add_margin': 0.11190211832680946, \n", + " 'text_threshold': 0.6521435262301017, \n", + " 'low_text': 0.21067288367279757, \n", + " 'link_threshold': 0.41883231108211494\n", + " }\n", + " \n", + " ocr = OverlayOCR(**best_params)\n", + "\n", + " final, norm, joined, conf, roi_name = ocr.run_on_image(IMG)\n", + " print(f\"Best ROI: {roi_name} | conf={conf:.2f}\")\n", + " print(\"joined:\", joined)\n", + " print(\"norm :\", norm)\n", + " print(\"final :\", final)\n", + "\n", + " \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "hack_digital_transformation", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/2_model_training/2_2_main_model.ipynb b/notebooks/2_model_training/2_2_main_model.ipynb new file mode 100644 index 0000000..3ce6765 --- /dev/null +++ b/notebooks/2_model_training/2_2_main_model.ipynb @@ -0,0 +1,124 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2f11dabb", + "metadata": {}, + "source": [ + "# Подготовка ноутбука " + ] + }, + { + "cell_type": "markdown", + "id": "85f07fbd", + "metadata": {}, + "source": [ + "## Пробрасываем magic methods" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "97feaebc", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "%reload_ext autoreload" + ] + }, + { + "cell_type": "markdown", + "id": "a5324521", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cd10fe31", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import numpy as np \n", + "from data.prepare_data import PrepareData\n", + "from dotenv import load_dotenv\n", + "import os \n", + "from pathlib import Path\n", + "from warnings import filterwarnings \n", + "import torch \n", + "import torchvision\n", + "from torch.utils.data import DataLoader\n", + "from IPython.display import display\n", + "import pytesseract\n", + "import shutil\n", + "try:\n", + " from PIL import Image\n", + "except ImportError:\n", + " import Image\n", + "import cv2" + ] + }, + { + "cell_type": "markdown", + "id": "8f5e2582", + "metadata": {}, + "source": [ + "## Нужные переменные " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e7ef1558", + "metadata": {}, + "outputs": [], + "source": [ + "ROOT_DIR = Path('../../')\n", + "load_dotenv()\n", + "filterwarnings(action='ignore')" + ] + }, + { + "cell_type": "markdown", + "id": "6dee36be", + "metadata": {}, + "source": [ + "# Загрузка датафрейма" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3fe3a4b5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "hack_digital_transformation", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml index 5bf7678..990756d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ dev = [ "flake8>=5.0.0", "black>=22.0.0", "isort>=5.10.0", + "ruff>=0.1.0", "jupyter>=1.0.0", ] production = [ @@ -37,7 +38,7 @@ production = [ ] [tool.uv] -dev-dependencies = ["pytest", "black", "isort", "jupyter"] +dev-dependencies = ["pytest", "black", "isort", "ruff", "jupyter"] [tool.black] line-length = 120 @@ -55,3 +56,32 @@ exclude = ''' [tool.isort] profile = "black" multi_line_output = 3 + +[tool.ruff] +line-length = 120 +select = [ + "E", "W", "F", "I", "C", "B", "N", "D", "UP", "YTT", "ANN", "S", "BLE", "FBT", "B0", "A", "C4", "T10", "EXE", "ISC", "ICN", "G", "INP", "PIE", "PYI", "PT", "RUF" +] +extend-ignore = [ + "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", # Missing docstrings +] +target-version = "py311" + +[tool.flake8] +max-line-length = 120 +ignore = [ + "E203", # Whitespace before ':' + "E266", # Too many leading '#' for block comment + "E501", # Line too long (handled by black) + "W503", # Line break occurred before a binary operator + "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", # Missing docstrings +] +exclude = [ + ".git", + "__pycache__", + ".venv", + "build", + "dist", + "node_modules", +] +max-complexity = 10 diff --git a/requirements.txt b/requirements.txt index 8784e57..b97433b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,47 +1,112 @@ -Mako==1.3.10 -MarkupSafe==3.0.2 -PyYAML==6.0.2 -Pygments==2.19.2 -SQLAlchemy==2.0.43 -alembic==1.16.5 -charset-normalizer==3.4.3 -cmaes==0.12.0 +arrow==1.2.3 +attrs==23.2.0 +Automat==22.10.0 +Babel==2.10.3 +bcrypt==3.2.2 +binaryornot==0.4.4 +blinker==1.7.0 +build==1.0.3 +CacheControl==0.14.0 +certifi==2023.11.17 +chardet==5.2.0 +cleo==2.1.0 +click==8.1.6 +cloud-init==25.1.4 colorama==0.4.6 -colorlog==6.9.0 -defusedxml==0.7.1 -easyocr==1.7.2 -googleapis-common-protos==1.70.0 -greenlet==3.2.4 -grpcio==1.75.0 -imageio==2.37.0 -importlib-metadata==6.11.0 -joblib==1.5.2 -mpmath==1.3.0 -networkx==3.5 +command-not-found==0.3 +configobj==5.0.8 +constantly==23.10.4 +cookiecutter==2.6.0 +crashtest==0.4.1 +cryptography==41.0.7 +dbus-python==1.3.2 +distlib==0.3.8 +distro==1.9.0 +distro-info==1.7+build1 +dulwich==0.21.6 +fastimport==0.9.14 +fastjsonschema==2.19.0 +filelock==3.13.1 +h11==0.14.0 +httplib2==0.20.4 +hyperlink==21.0.0 +idna==3.6 +importlib-metadata==4.12.0 +incremental==22.10.0 +installer==0.7.0 +jaraco.classes==3.2.1 +jeepney==0.8.0 +Jinja2==3.1.2 +jsonpatch==1.32 +jsonpointer==2.0 +jsonschema==4.10.3 +keyring==24.3.1 +launchpadlib==1.11.0 +lazr.restfulclient==0.14.6 +lazr.uri==1.0.6 +lockfile==0.12.2 +markdown-it-py==3.0.0 +MarkupSafe==2.1.5 +mdurl==0.1.2 +more-itertools==10.2.0 +msgpack==1.0.3 +netifaces==0.11.0 numpy==2.2.6 +oauthlib==3.2.2 opencv-python==4.12.0.88 -optuna==4.5.0 -packaging==23.2 -pandas==2.3.2 -pillow==11.3.0 -platformdirs==4.4.0 -protobuf==6.32.1 -psutil==7.1.0 -pyarrow==21.0.0 -pydot==4.0.1 -python-bidi==0.6.6 -python-dateutil==2.9.0.post0 -pytz==2025.2 -scikit-image==0.25.2 -scikit-learn==1.7.2 -scipy==1.16.2 -six==1.17.0 -sympy==1.14.0 -threadpoolctl==3.6.0 -tifffile==2025.9.20 -torch==2.8.0 -torchvision==0.23.0 -tqdm==4.67.1 -triton==3.4.0 -typing-extensions==4.15.0 -zipp==3.23.0 \ No newline at end of file +packaging==24.0 +pexpect==4.9.0 +pkginfo==1.9.6 +platformdirs==4.2.0 +poetry==1.8.2 +poetry-core==1.9.0 +poetry-plugin-export==1.6.0 +ptyprocess==0.7.0 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 +pycurl==7.45.3 +Pygments==2.17.2 +PyGObject==3.48.2 +PyHamcrest==2.1.0 +PyJWT==2.7.0 +pylev==1.4.0 +pyOpenSSL==23.2.0 +pyparsing==3.1.1 +pyproject_hooks==1.0.0 +pyrsistent==0.20.0 +pyserial==3.5 +python-apt==2.7.7+ubuntu5 +python-dateutil==2.8.2 +python-magic==0.4.27 +python-slugify==8.0.4 +pytz==2024.1 +PyYAML==6.0.1 +requests==2.31.0 +requests-toolbelt==1.0.0 +rich==13.7.1 +ruamel.yaml==0.17.21 +ruamel.yaml.clib==0.2.8 +s3cmd==2.4.0 +SecretStorage==3.3.3 +service-identity==24.1.0 +setuptools==68.1.2 +shellingham==1.5.4 +six==1.16.0 +systemd-python==235 +toml==0.10.2 +tomlkit==0.12.4 +trove-classifiers==2024.1.31 +Twisted==24.3.0 +typing_extensions==4.10.0 +ubuntu-pro-client==8001 +unattended-upgrades==0.1 +Unidecode==1.3.8 +urllib3==2.0.7 +uvicorn==0.27.1 +uvloop==0.19.0 +virtualenv==20.25.0+ds +wadllib==1.3.6 +wheel==0.42.0 +wsproto==1.2.0 +zipp==1.0.0 +zope.interface==6.1 diff --git a/src/__init__.py b/src/__init__.py index 076a757..03235a6 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,3 +1,3 @@ from . import utils -__all__ = ['utils'] \ No newline at end of file +__all__ = ["utils"] diff --git a/src/api/app.py b/src/api/app.py index 22daf12..da92f29 100644 --- a/src/api/app.py +++ b/src/api/app.py @@ -1,21 +1,39 @@ import os -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional +from datetime import datetime -import joblib -import numpy as np -import pandas as pd -import yaml from fastapi import FastAPI, HTTPException from pydantic import BaseModel +from sqlalchemy import create_engine, text +from sqlalchemy.orm import sessionmaker +import redis +import json + +# Импортируем CV модель +from src.models.cv_model import CVModel, create_cv_model +# Импортируем Celery задачи +from src.tasks.worker import process_image_task, batch_process_images_task # Инициализация FastAPI приложения app = FastAPI( - title="ML Model API", description="API для предоставления прогнозов модели машинного обучения", version="0.1.0" + title="Building Detector API", + description="API для детекции зданий и определения координат на изображениях", + version="1.0.0" ) # Глобальные переменные для модели и конфигурации model = None config = None +cv_model: Optional[CVModel] = None + +# Настройка подключения к базе данных +DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://postgres:postgres@localhost:5432/building_detector') +engine = create_engine(DATABASE_URL) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +# Настройка подключения к Redis +REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379/0') +redis_client = redis.Redis.from_url(REDIS_URL) class PredictionRequest(BaseModel): @@ -31,28 +49,98 @@ class PredictionResponse(BaseModel): probability: float +class ImageProcessRequest(BaseModel): + """Модель запроса для обработки изображения""" + + image_path: str + + +class AsyncImageProcessRequest(BaseModel): + """Модель запроса для асинхронной обработки изображения""" + + image_path: str + request_id: Optional[str] = None + + +class BatchImageProcessRequest(BaseModel): + """Модель запроса для пакетной обработки изображений""" + + image_paths: List[str] + request_id: Optional[str] = None + + +class BuildingDetection(BaseModel): + """Модель обнаруженного здания""" + + bbox: List[float] # [x1, y1, x2, y2] + confidence: float + area: Optional[float] = None + + +class CoordinateResult(BaseModel): + """Модель координат""" + + lat: Optional[float] = None + lon: Optional[float] = None + + +class OCRResult(BaseModel): + """Модель результата OCR""" + + final: Optional[str] = None + norm: Optional[str] = None + joined: Optional[str] = None + confidence: Optional[float] = None + roi_name: Optional[str] = None + + +class ImageProcessResponse(BaseModel): + """Модель ответа для обработки изображения""" + + image_path: str + processed_at: str + coordinates: Optional[CoordinateResult] = None + address: Optional[str] = None + buildings: List[BuildingDetection] + ocr_result: Optional[OCRResult] = None + + +class AsyncTaskResponse(BaseModel): + """Модель ответа для асинхронной задачи""" + + task_id: str + request_id: Optional[str] = None + status: str = "started" + message: str = "Задача принята в обработку" + + +class TaskStatusResponse(BaseModel): + """Модель ответа для статуса задачи""" + + task_id: str + request_id: Optional[str] = None + status: str + result: Optional[dict] = None + error: Optional[str] = None + progress: Optional[dict] = None + + def load_model_and_config(): """Загрузка обученной модели и конфигурации""" global model, config - # Загрузка конфигурации - config_path = "configs/config.yaml" - if os.path.exists(config_path): - with open(config_path, "r") as f: - config = yaml.safe_load(f) - - # Загрузка модели - model_path = "models/model.pkl" - if os.path.exists(model_path): - model = joblib.load(model_path) - else: - print(f"Предупреждение: Файл модели {model_path} не найден") + # В текущей архитектуре не используется загрузка модели ML + # Так как мы используем визуальный поиск по изображениям + model = None + config = None @app.on_event("startup") async def startup_event(): """Загрузка модели и конфигурации при запуске""" load_model_and_config() + global cv_model + cv_model = create_cv_model() @app.get("/") @@ -65,31 +153,172 @@ async def root(): async def health_check(): """Эндпоинт проверки состояния""" model_status = "загружена" if model is not None else "не загружена" - return {"status": "здоровая", "model_status": model_status} + cv_model_status = "загружена" if cv_model is not None else "не загружена" + return {"status": "здоровая", "model_status": model_status, "cv_model_status": cv_model_status} @app.post("/predict", response_model=PredictionResponse) async def predict(request: PredictionRequest): """Сделать прогноз с использованием обученной модели""" - if model is None: - raise HTTPException(status_code=500, detail="Модель не загружена") + # В текущей архитектуре не используется модель ML для прогнозирования + # Так как мы используем визуальный поиск по изображениям + raise HTTPException(status_code=501, detail="Эндпоинт не реализован в текущей архитектуре") + + +@app.post("/process_image", response_model=ImageProcessResponse) +async def process_image(request: ImageProcessRequest): + """Обработка изображения с помощью CV модели""" + global cv_model + if cv_model is None: + raise HTTPException(status_code=500, detail="CV модель не загружена") + + try: + # Обработка изображения + result = cv_model.process_image(request.image_path) + + # Преобразование результата в формат ответа + response = ImageProcessResponse( + image_path=result["image_path"], + processed_at=result["processed_at"], + buildings=[ + BuildingDetection(bbox=building["bbox"], confidence=building["confidence"], area=building.get("area")) + for building in result["buildings"] + ], + ) + + # Добавляем координаты, если есть + if result.get("coordinates"): + response.coordinates = CoordinateResult(lat=result["coordinates"]["lat"], lon=result["coordinates"]["lon"]) + + # Добавляем адрес, если есть + if result.get("address"): + response.address = result["address"] + + # Добавляем OCR результат, если есть + if result.get("ocr_result"): + ocr_data = result["ocr_result"] + response.ocr_result = OCRResult( + final=ocr_data["final"] if ocr_data["final"] else None, + norm=ocr_data["norm"] if ocr_data["norm"] else None, + joined=ocr_data["joined"] if ocr_data["joined"] else None, + confidence=ocr_data["confidence"] if ocr_data["confidence"] else None, + roi_name=ocr_data["roi_name"] if ocr_data["roi_name"] else None, + ) + + return response + except Exception as e: + raise HTTPException(status_code=400, detail=f"Ошибка обработки изображения: {str(e)}") + + +@app.post("/process_image_async", response_model=AsyncTaskResponse) +async def process_image_async(request: AsyncImageProcessRequest): + """Асинхронная обработка изображения с помощью Celery""" + try: + # Используем request_id если предоставлен, иначе None + request_id = request.request_id + + # Отправляем задачу в Celery + task = process_image_task.delay(request.image_path, request_id) + + return AsyncTaskResponse( + task_id=task.id, + request_id=request_id, + status="started", + message="Задача принята в обработку" + ) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Ошибка отправки задачи: {str(e)}") + + +@app.post("/process_images_batch", response_model=AsyncTaskResponse) +async def process_images_batch(request: BatchImageProcessRequest): + """Пакетная асинхронная обработка изображений с помощью Celery""" + try: + # Используем request_id если предоставлен, иначе None + request_id = request.request_id + + # Отправляем задачу в Celery + task = batch_process_images_task.delay(request.image_paths, request_id) + + return AsyncTaskResponse( + task_id=task.id, + request_id=request_id, + status="started", + message=f"Пакетная задача принята в обработку. Количество изображений: {len(request.image_paths)}" + ) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Ошибка отправки пакетной задачи: {str(e)}") + +@app.get("/task/{task_id}", response_model=TaskStatusResponse) +async def get_task_status(task_id: str): + """Получение статуса задачи по её ID""" try: - # Преобразование признаков в DataFrame - features_df = pd.DataFrame([request.features]) + # Проверяем статус задачи в Celery + from celery.result import AsyncResult + from src.tasks.worker import celery_app + + task_result = AsyncResult(task_id, app=celery_app) + + # Получаем прогресс задачи из Redis если она в процессе выполнения + progress = None + if task_result.state == 'PROGRESS': + progress = redis_client.get(f"task_progress:{task_id}") + if progress: + progress = json.loads(progress.decode('utf-8')) + + return TaskStatusResponse( + task_id=task_id, + status=task_result.state, + result=task_result.result if task_result.ready() else None, + error=str(task_result.info) if task_result.failed() else None, + progress=progress + ) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Ошибка получения статуса задачи: {str(e)}") + - # Сделать прогноз - prediction = model.predict(features_df)[0] +@app.get("/tasks/request/{request_id}") +async def get_tasks_by_request_id(request_id: str): + """Получение всех задач по request_id""" + try: + db = SessionLocal() + query = text(""" + SELECT task_id, status, progress, total, created_at, updated_at + FROM tasks + WHERE request_id = :request_id + ORDER BY created_at DESC + """) + + result = db.execute(query, {"request_id": request_id}) + tasks = result.fetchall() + db.close() + + return {"request_id": request_id, "tasks": [dict(task) for task in tasks]} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Ошибка получения задач: {str(e)}") - # Получить вероятность прогноза, если доступна - probability = 0.0 - if hasattr(model, "predict_proba"): - probabilities = model.predict_proba(features_df)[0] - probability = float(np.max(probabilities)) - return PredictionResponse(prediction=int(prediction), probability=probability) +@app.get("/results/latest") +async def get_latest_results(limit: int = 10): + """Получение последних результатов обработки""" + try: + db = SessionLocal() + query = text(""" + SELECT id, image_path, task_id, request_id, coordinates, address, + ocr_result, buildings, processed_at, error + FROM processing_results + ORDER BY processed_at DESC + LIMIT :limit + """) + + result = db.execute(query, {"limit": limit}) + results = result.fetchall() + db.close() + + return {"results": [dict(result) for result in results]} except Exception as e: - raise HTTPException(status_code=400, detail=f"Ошибка прогнозирования: {str(e)}") + raise HTTPException(status_code=500, detail=f"Ошибка получения результатов: {str(e)}") @app.get("/model/info") diff --git a/src/data/database_builder.py b/src/data/database_builder.py new file mode 100644 index 0000000..f2bfa45 --- /dev/null +++ b/src/data/database_builder.py @@ -0,0 +1,125 @@ +import json +import os +import pickle +import time + +import torch + +from data.faiss_indexer import FaissIndexer +from models.feature_extractor import FeatureExtractor +from utils.config import DATA_PATHS, s3_manager + + +def create_directories(): + """Создание необходимых директорий""" + os.makedirs("data/processed", exist_ok=True) + os.makedirs("data/index", exist_ok=True) + print("Директории созданы") + + +def validate_s3_connection(): + """Проверка подключения к S3""" + print("Проверка подключения к S3...") + try: + # Пробуем получить список файлов (ограничиваемся 1 для проверки) + connect = s3_manager + if connect is not None: + print("✓ Подключение к S3 успешно") + return True + else: + print("✗ Не удалось получить список файлов из S3") + return False + except Exception as e: + print(f"✗ Ошибка подключения к S3: {e}") + return False + + +def main(): + print("=== Фаза 1: Построение базы данных изображений Москвы ===") + print("Версия: PyTorch + S3Manager") + start_time = time.time() + + # Создаем директории + create_directories() + + # Проверяем подключение к S3 + if not validate_s3_connection(): + return + + # Очистка кэша CUDA если используется GPU + if torch.cuda.is_available(): + torch.cuda.empty_cache() + print("Кэш CUDA очищен") + + # 1. Извлечение признаков + print("\n" + "=" * 50) + print("1. Извлечение признаков из изображений в S3...") + + extractor = FeatureExtractor() + features_dict, failed_images = extractor.process_all_images(batch_size=64) + + if not features_dict: + print("Не удалось извлечь признаки ни из одного изображения") + return + + # Сохраняем сырые признаки (опционально, для отладки) + print("Сохранение сырых признаков...") + with open("data/processed/raw_features.pkl", "wb") as f: + pickle.dump(features_dict, f) + + # 2. Создание FAISS индекса + print("\n" + "=" * 50) + print("2. Создание поискового индекса FAISS...") + + indexer = FaissIndexer(dimension=2048) # ResNet50 features are 2048-dim + num_indexed = indexer.create_index(features_dict, index_type="IVF") + print(f"Проиндексировано изображений: {num_indexed}") + + # 3. Сохранение индекса + print("\n" + "=" * 50) + print("3. Сохранение индекса и метаданных...") + + indexer.save_index(DATA_PATHS["faiss_index"], DATA_PATHS["mapping_file"]) + + # 4. Сохранение метаданных сборки + processing_stats = extractor.get_processing_stats() + metadata = { + "total_images_processed": len(features_dict), + "failed_images": len(failed_images), + "index_size": num_indexed, + "model_used": "ResNet50_PyTorch", + "feature_dimension": 2048, + "device_used": extractor.device, + "build_time_seconds": time.time() - start_time, + "processing_stats": processing_stats, + "s3_bucket": s3_manager.bucket_name, + "build_date": time.strftime("%Y-%m-%d %H:%M:%S"), + "batch_size_used": 16, + } + + with open(DATA_PATHS["metadata_file"], "w") as f: + json.dump(metadata, f, indent=2) + + # 5. Статистика S3 + s3_upload_stats = s3_manager.get_upload_stats() + s3_download_stats = s3_manager.get_download_stats() + + print(f"\n" + "=" * 50) + print("=== СБОРКА ЗАВЕРШЕНА! ===") + print(f"Общее время: {time.time() - start_time:.2f} секунд") + print(f"Успешно обработано: {len(features_dict)} изображений") + print(f"Ошибки обработки: {len(failed_images)}") + print(f"Размер FAISS индекса: {num_indexed}") + print(f"\nСтатистика S3 (загрузка): {s3_upload_stats}") + print(f"Статистика S3 (скачивание): {s3_download_stats}") + + # Сохраняем список неудачных изображений + if failed_images: + with open("data/processed/failed_images.txt", "w") as f: + for img in failed_images: + f.write(f"{img}\n") + print(f"Список неудачных изображений сохранен: data/processed/failed_images.txt") + + +if __name__ == "__main__": + main() diff --git a/src/data/faiss_indexer.py b/src/data/faiss_indexer.py new file mode 100644 index 0000000..6ce3766 --- /dev/null +++ b/src/data/faiss_indexer.py @@ -0,0 +1,92 @@ +import os +import pickle + +import faiss +import numpy as np +from tqdm import tqdm + +from utils.config import FAISS_CONFIG + + +class FaissIndexer: + def __init__(self, dimension=2048): + self.dimension = dimension + self.index = None + self.image_mapping = {} + + def create_index(self, features_dict, index_type="IVF"): + """Создание FAISS индекса из признаков""" + s3_keys = [] + features_list = [] + + print("Подготовка данных для FAISS...") + for i, (s3_key, data) in enumerate(tqdm(features_dict.items())): + s3_keys.append(s3_key) + features_list.append(data["features"]) + + self.image_mapping[i] = {"s3_key": s3_key, "features": data["features"]} + + features_matrix = np.array(features_list).astype("float32") + print(f"Размер матрицы признаков: {features_matrix.shape}") + + # Создание индекса + if index_type == "Flat": + self.index = faiss.IndexFlatL2(self.dimension) + elif index_type == "IVF": + quantizer = faiss.IndexFlatL2(self.dimension) + self.index = faiss.IndexIVFFlat(quantizer, self.dimension, FAISS_CONFIG["nlist"], faiss.METRIC_L2) + + print("Обучение FAISS индекса...") + self.index.train(features_matrix) + + print("Добавление данных в индекс...") + self.index.add(features_matrix) + + return len(features_matrix) + + def search_similar(self, query_features, k=10): + """Поиск k наиболее похожих изображений""" + if self.index is None: + raise ValueError("Индекс не инициализирован") + + query_features = query_features.astype("float32").reshape(1, -1) + + distances, indices = self.index.search(query_features, k) + + results = [] + for i, (distance, idx) in enumerate(zip(distances[0], indices[0])): + if idx in self.image_mapping: + results.append( + { + "rank": i + 1, + "s3_key": self.image_mapping[idx]["s3_key"], + "distance": float(distance), + "similarity_score": 1 / (1 + distance), + "index_id": int(idx), + } + ) + + return results + + def save_index(self, index_path, mapping_path): + """Сохранение индекса и маппинга""" + os.makedirs(os.path.dirname(index_path), exist_ok=True) + os.makedirs(os.path.dirname(mapping_path), exist_ok=True) + + faiss.write_index(self.index, index_path) + + with open(mapping_path, "wb") as f: + pickle.dump(self.image_mapping, f) + + print(f"Индекс сохранен: {index_path}") + print(f"Маппинг сохранен: {mapping_path}") + + def load_index(self, index_path, mapping_path): + """Загрузка индекса и маппинга""" + self.index = faiss.read_index(index_path) + + with open(mapping_path, "rb") as f: + self.image_mapping = pickle.load(f) + + print(f"Индекс загружен: {index_path}") + print(f"Размер индекса: {self.index.ntotal}") diff --git a/src/engine/main.py b/src/engine/optuna_optimize.py similarity index 100% rename from src/engine/main.py rename to src/engine/optuna_optimize.py diff --git a/src/geo/__init__.py b/src/geo/__init__.py new file mode 100644 index 0000000..fd9ed12 --- /dev/null +++ b/src/geo/__init__.py @@ -0,0 +1,3 @@ +from .download_images import MapillaryS3Client + +__all__ = [MapillaryS3Client] diff --git a/src/geo/download_images.py b/src/geo/download_images.py new file mode 100644 index 0000000..12a3ee7 --- /dev/null +++ b/src/geo/download_images.py @@ -0,0 +1,510 @@ +import concurrent.futures +import csv +import hashlib +import json +import logging +import os +import time +from datetime import datetime +from threading import Lock +from typing import Dict, List, Optional, Tuple + +import requests +from dotenv import load_dotenv + +from utils.s3_optimize import S3Manager + +# Настройка логирования +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +load_dotenv() + + +class BBoxSplitter: + """Класс для разбивки bbox на части для лучшего покрытия""" + + @staticmethod + def split_bbox(bbox: List[float], grid_size: int = 2) -> List[List[float]]: + """ + Разбивает bbox на grid_size x grid_size частей + + Args: + bbox: [min_lon, min_lat, max_lon, max_lat] + grid_size: количество частей по каждой оси + + Returns: + Список под-bbox'ов + """ + min_lon, min_lat, max_lon, max_lat = bbox + + lon_step = (max_lon - min_lon) / grid_size + lat_step = (max_lat - min_lat) / grid_size + + sub_bboxes = [] + + for i in range(grid_size): + for j in range(grid_size): + sub_min_lon = min_lon + (i * lon_step) + sub_max_lon = min_lon + ((i + 1) * lon_step) + sub_min_lat = min_lat + (j * lat_step) + sub_max_lat = min_lat + ((j + 1) * lat_step) + + sub_bboxes.append([sub_min_lon, sub_min_lat, sub_max_lon, sub_max_lat]) + + return sub_bboxes + + @staticmethod + def create_bbox_grid( + center_lat: float, center_lon: float, grid_radius: int = 2, bbox_size: float = 0.02 + ) -> List[List[float]]: + """ + Создает сетку bbox вокруг центральной точки + + Args: + center_lat: широта центра + center_lon: долгота центра + grid_radius: радиус сетки (количество bbox в каждую сторону от центра) + bbox_size: размер каждого bbox в градусах + + Returns: + Список bbox'ов + """ + bboxes = [] + + for i in range(-grid_radius, grid_radius + 1): + for j in range(-grid_radius, grid_radius + 1): + min_lon = center_lon + (j * bbox_size) - (bbox_size / 2) + max_lon = center_lon + (j * bbox_size) + (bbox_size / 2) + min_lat = center_lat + (i * bbox_size) - (bbox_size / 2) + max_lat = center_lat + (i * bbox_size) + (bbox_size / 2) + + bboxes.append([min_lon, min_lat, max_lon, max_lat]) + + return bboxes + + @staticmethod + def calculate_optimal_grid_size(bbox: List[float], target_bbox_area: float = 0.0004) -> int: + """ + Рассчитывает оптимальный размер сетки на основе площади bbox + + Args: + bbox: [min_lon, min_lat, max_lon, max_lat] + target_bbox_area: целевая площадь каждого под-bbox (в квадратных градусах) + + Returns: + Оптимальный размер сетки + """ + min_lon, min_lat, max_lon, max_lat = bbox + bbox_area = (max_lon - min_lon) * (max_lat - min_lat) + + # Рассчитываем количество частей так, чтобы площадь каждого была около target_bbox_area + grid_size = max(1, int((bbox_area / target_bbox_area) ** 0.5)) + + # Ограничиваем максимальный размер сетки для избежания слишком маленьких bbox + return min(grid_size, 10) + + +class MapillaryS3Client: + """Mapillary клиент с прямой загрузкой в S3""" + + def __init__( + self, + access_token: str, + s3_manager: S3Manager, + max_workers: int = 10, + cache_dir: Optional[str] = None, + ): + self.access_token = access_token + self.s3_manager = s3_manager + self.max_workers = max_workers + self.cache_dir = cache_dir + self.base_url = "https://graph.mapillary.com" + self.request_lock = Lock() + self.bbox_splitter = BBoxSplitter() + + # Настройка HTTP сессии + self.session = requests.Session() + self.session.headers.update( + {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "application/json"} + ) + + if cache_dir: + os.makedirs(cache_dir, exist_ok=True) + + def _get_cached_data(self, key: str, expiry_hours: int = 24) -> Optional[dict]: + """Кэширование данных API запросов""" + if not self.cache_dir: + return None + + hash_key = hashlib.md5(key.encode()).hexdigest() + cache_file = os.path.join(self.cache_dir, f"{hash_key}.json") + + if os.path.exists(cache_file): + file_time = os.path.getmtime(cache_file) + if (time.time() - file_time) < (expiry_hours * 3600): + try: + with open(cache_file, "r", encoding="utf-8") as f: + return json.load(f) + except Exception as e: + logger.warning(f"Ошибка чтения кэша: {e}") + return None + return None + + def _set_cached_data(self, key: str, data: dict): + """Сохранение данных в кэш""" + if not self.cache_dir: + return + + hash_key = hashlib.md5(key.encode()).hexdigest() + cache_file = os.path.join(self.cache_dir, f"{hash_key}.json") + + try: + with open(cache_file, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + except Exception as e: + logger.warning(f"Не удалось сохранить кэш: {e}") + + def _rate_limited_request(self, url: str, params: dict = None) -> dict: + """HTTP запрос с ограничением скорости и повторными попытками""" + with self.request_lock: + time.sleep(0.1) # Базовая задержка между запросами + + for attempt in range(3): + try: + response = self.session.get(url, params=params, timeout=30) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + if attempt == 2: # Последняя попытка + raise e + time.sleep(2**attempt) # Экспоненциальная задержка + + def get_images_in_bbox(self, bbox: List[float], max_results: int = 1000, use_cache: bool = True) -> List[Dict]: + """ + Получение списка изображений в bounding box + bbox: [min_lon, min_lat, max_lon, max_lat] + """ + cache_key = f"bbox_{'_'.join(map(str, bbox))}_{max_results}" + + if use_cache: + cached_data = self._get_cached_data(cache_key) + if cached_data: + logger.info("Используются кэшированные данные") + return cached_data + + url = f"{self.base_url}/images" + params = { + "fields": "id,geometry,compass_angle,captured_at,altitude,sequence,creator,thumb_2048_url", + "access_token": self.access_token, + "limit": min(max_results, 2000), + "bbox": ",".join(map(str, bbox)), + } + + try: + data = self._rate_limited_request(url, params) + + if "data" in data: + self._set_cached_data(cache_key, data["data"]) + return data["data"] + else: + logger.error(f"Неожиданный формат ответа: {data.get('error', 'Unknown error')}") + return [] + + except requests.exceptions.RequestException as e: + logger.error(f"Ошибка запроса для bbox {bbox}: {e}") + return [] + + def get_images_in_bbox_batch( + self, bboxes: List[List[float]], max_results_per_bbox: int = 500, use_cache: bool = True + ) -> List[Dict]: + """ + Пакетное получение изображений для нескольких bbox + + Args: + bboxes: список bbox'ов + max_results_per_bbox: максимальное количество результатов на bbox + use_cache: использовать кэширование + + Returns: + Объединенный список уникальных изображений + """ + all_images = [] + + logger.info(f"Начинаем обработку {len(bboxes)} bbox регионов...") + + with concurrent.futures.ThreadPoolExecutor(max_workers=min(self.max_workers, len(bboxes))) as executor: + future_to_bbox = { + executor.submit(self.get_images_in_bbox, bbox, max_results_per_bbox, use_cache): bbox for bbox in bboxes + } + + for i, future in enumerate(concurrent.futures.as_completed(future_to_bbox)): + bbox = future_to_bbox[future] + try: + images = future.result() + all_images.extend(images) + logger.info(f"Обработан bbox {i+1}/{len(bboxes)}: {bbox} - найдено {len(images)} изображений") + except Exception as e: + logger.error(f"Ошибка для bbox {bbox}: {e}") + + # Удаляем дубликаты по ID + seen_ids = set() + unique_images = [] + + for img in all_images: + img_id = img.get("id") + if img_id and img_id not in seen_ids: + seen_ids.add(img_id) + unique_images.append(img) + + logger.info(f"После объединения: {len(unique_images)} уникальных изображений") + return unique_images + + def get_images_for_large_area( + self, + bbox: List[float], + grid_size: Optional[int] = None, + max_results_per_bbox: int = 500, + use_cache: bool = True, + ) -> List[Dict]: + """ + Получение изображений для большого региона с автоматическим разбиением на части + + Args: + bbox: основной bbox [min_lon, min_lat, max_lon, max_lat] + grid_size: размер сетки (если None, рассчитывается автоматически) + max_results_per_bbox: максимальное количество результатов на под-bbox + use_cache: использовать кэширование + + Returns: + Список уникальных изображений + """ + # Рассчитываем оптимальный размер сетки если не задан + if grid_size is None: + grid_size = self.bbox_splitter.calculate_optimal_grid_size(bbox) + logger.info(f"Автоматически рассчитан размер сетки: {grid_size}x{grid_size}") + + # Разбиваем основной bbox на части + sub_bboxes = self.bbox_splitter.split_bbox(bbox, grid_size) + + logger.info(f"Основной bbox разбит на {len(sub_bboxes)} частей") + for i, sub_bbox in enumerate(sub_bboxes): + logger.info(f" Часть {i+1}: {sub_bbox}") + + # Получаем изображения для всех частей + return self.get_images_in_bbox_batch(sub_bboxes, max_results_per_bbox, use_cache) + + def get_images_around_point( + self, + center_lat: float, + center_lon: float, + grid_radius: int = 2, + bbox_size: float = 0.02, + max_results_per_bbox: int = 500, + use_cache: bool = True, + ) -> List[Dict]: + """ + Получение изображений вокруг центральной точки + + Args: + center_lat: широта центра + center_lon: долгота центра + grid_radius: радиус сетки + bbox_size: размер каждого bbox в градусах + max_results_per_bbox: максимальное количество результатов на bbox + use_cache: использовать кэширование + + Returns: + Список уникальных изображений + """ + # Создаем сетку bbox вокруг точки + bboxes = self.bbox_splitter.create_bbox_grid(center_lat, center_lon, grid_radius, bbox_size) + + logger.info(f"Создана сетка из {len(bboxes)} bbox вокруг точки ({center_lat}, {center_lon})") + + # Получаем изображения для всех bbox + return self.get_images_in_bbox_batch(bboxes, max_results_per_bbox, use_cache) + + def _prepare_s3_metadata(self, image_info: Dict) -> Dict[str, str]: + """Подготовка метаданных для S3 (все значения должны быть строками)""" + geometry = image_info.get("geometry", {}) + coordinates = geometry.get("coordinates", [0, 0]) + + # ВАЖНО: Все значения должны быть строками для S3 metadata + metadata = { + "mapillary_id": str(image_info.get("id", "")), + "latitude": str(coordinates[1]) if coordinates else "0", + "longitude": str(coordinates[0]) if coordinates else "0", + "captured_at": str(image_info.get("captured_at", "")), + "compass_angle": str(image_info.get("compass_angle", "")), + "altitude": str(image_info.get("altitude", "")), + "upload_timestamp": datetime.now().isoformat(), + } + + # Добавляем опциональные поля + sequence = image_info.get("sequence") + if sequence and isinstance(sequence, dict): + metadata["sequence_id"] = str(sequence.get("id", "")) + + creator = image_info.get("creator") + if creator and isinstance(creator, dict): + metadata["creator_username"] = str(creator.get("username", "")) + + return metadata + + def download_and_upload_to_s3( + self, + images: List[Dict], + s3_prefix: str, + image_format: str = "JPEG", + quality: int = 85, + progress_callback: callable = None, + ) -> Dict: + """Прямая загрузка изображений с Mapillary в S3""" + results = {"successful": 0, "failed": 0, "skipped": 0, "errors": []} + + def _process_image(image_info: Dict) -> tuple: + """Обработка одного изображения""" + image_id = image_info.get("id") + s3_key = f"{s3_prefix}/{image_id}.{image_format.lower()}" + + try: + # Получаем URL изображения + image_url = image_info.get("thumb_2048_url") + if not image_url: + image_url = self._get_image_url(image_id) + + if not image_url: + return image_id, False, "URL изображения не найден" + + # Скачиваем изображение + response = self.session.get(image_url, timeout=30) + response.raise_for_status() + + # Подготавливаем метаданные для S3 + metadata = self._prepare_s3_metadata(image_info) + + # Загружаем напрямую в S3 + success = self.s3_manager.upload_image_data( + response.content, s3_key, image_format=image_format, quality=quality, metadata=metadata + ) + + if success: + return image_id, True, "Успешно" + else: + return image_id, False, "Ошибка загрузки в S3" + + except Exception as e: + return image_id, False, f"Ошибка: {str(e)}" + + # Многопоточная обработка изображений + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + future_to_image = {executor.submit(_process_image, img): img for img in images} + + for i, future in enumerate(concurrent.futures.as_completed(future_to_image)): + image_info = future_to_image[future] + image_id, success, message = future.result() + + if success: + results["successful"] += 1 + else: + results["failed"] += 1 + results["errors"].append(f"{image_id}: {message}") + + # Отчет о прогрессе + self._report_progress(i, len(images), results, progress_callback) + + # Добавляем статистику S3 + results["s3_stats"] = self.s3_manager.get_upload_stats() + + logger.info(f"Загрузка завершена. Успешно: {results['successful']}, " f"Ошибки: {results['failed']}") + + return results + + def _get_image_url(self, image_id: str) -> str: + """Получение URL изображения по ID""" + try: + url = f"{self.base_url}/{image_id}" + params = {"fields": "thumb_2048_url", "access_token": self.access_token} + + response = self.session.get(url, params=params, timeout=10) + data = response.json() + return data.get("thumb_2048_url", "") + except Exception as e: + logger.error(f"Ошибка получения URL для {image_id}: {e}") + return "" + + def _report_progress(self, current: int, total: int, results: Dict, progress_callback: callable = None): + """Отчет о прогрессе обработки""" + if (current + 1) % 10 == 0 or (current + 1) == total: + processed = results["successful"] + results["failed"] + results["skipped"] + logger.info( + f"Прогресс: {processed}/{total} | " + f"Успешно: {results['successful']} | " + f"Ошибки: {results['failed']}" + ) + + if progress_callback: + progress_callback(current + 1, total) + + def _safe_get(self, obj, key, default=""): + """Безопасное получение значения из объекта""" + if isinstance(obj, dict): + return obj.get(key, default) + return default + + def save_metadata_to_csv(self, images: List[Dict], filename: str, include_extended: bool = True): + """Сохранение метаданных в CSV файл""" + if not images: + logger.warning("Нет данных для сохранения") + return + + # Создаем директорию если нужно + os.makedirs(os.path.dirname(filename) if os.path.dirname(filename) else ".", exist_ok=True) + + # Определяем поля для CSV + fieldnames = ["id", "latitude", "longitude", "captured_at", "compass_angle"] + if include_extended: + fieldnames.extend(["sequence_id", "creator_username", "altitude"]) + + with open(filename, "w", newline="", encoding="utf-8") as csvfile: + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + + for img in images: + # Проверяем, что это словарь + if not isinstance(img, dict): + logger.warning(f"Пропущен некорректный элемент: {type(img)}") + continue + + # Безопасно извлекаем geometry + geometry = self._safe_get(img, "geometry", {}) + coordinates = self._safe_get(geometry, "coordinates", [0, 0]) + + # Безопасно извлекаем основные поля + row = { + "id": self._safe_get(img, "id"), + "latitude": coordinates[1] if isinstance(coordinates, list) and len(coordinates) > 1 else 0, + "longitude": coordinates[0] if isinstance(coordinates, list) and len(coordinates) > 0 else 0, + "captured_at": self._safe_get(img, "captured_at"), + "compass_angle": self._safe_get(img, "compass_angle"), + } + + if include_extended: + # Безопасно извлекаем расширенные поля + sequence = self._safe_get(img, "sequence") + creator = self._safe_get(img, "creator") + + row.update( + { + "sequence_id": self._safe_get(sequence, "id") if isinstance(sequence, dict) else "", + "creator_username": ( + self._safe_get(creator, "username") if isinstance(creator, dict) else "" + ), + "altitude": self._safe_get(img, "altitude"), + } + ) + + writer.writerow(row) + + logger.info(f"Метаданные сохранены в {filename} ({len(images)} записей)") diff --git a/src/geo/geocoder.py b/src/geo/geocoder.py new file mode 100644 index 0000000..74903bf --- /dev/null +++ b/src/geo/geocoder.py @@ -0,0 +1,197 @@ +import requests +import logging +from typing import Dict, Optional +import os + +logger = logging.getLogger(__name__) + + +class Geocoder: + """Класс для работы с геокодерами и получения адресов по координатам""" + + def __init__(self): + """Инициализация геокодера""" + self.yandex_api_key = os.getenv("YANDEX_GEOCODER_API_KEY") + self.google_api_key = os.getenv("GOOGLE_GEOCODER_API_KEY") + self.openstreetmap_enabled = True + + def geocode(self, lat: float, lon: float) -> Optional[str]: + """ + Получение адреса по координатам с использованием различных геокодеров + + Args: + lat: Широта + lon: Долгота + + Returns: + Адрес в виде строки или None + """ + # Пробуем различные геокодеры в порядке приоритета + geocoders = [ + self._yandex_geocode, + self._google_geocode, + self._openstreetmap_geocode + ] + + for geocoder_func in geocoders: + try: + address = geocoder_func(lat, lon) + if address: + return address + except Exception as e: + logger.warning(f"Ошибка геокодера {geocoder_func.__name__}: {e}") + continue + + return None + + def _yandex_geocode(self, lat: float, lon: float) -> Optional[str]: + """ + Геокодирование с помощью Yandex Geocoder API + + Args: + lat: Широта + lon: Долгота + + Returns: + Адрес в виде строки или None + """ + if not self.yandex_api_key: + logger.warning("Yandex API key не установлен") + return None + + try: + url = "https://geocode-maps.yandex.ru/1.x/" + params = { + "apikey": self.yandex_api_key, + "geocode": f"{lon},{lat}", + "format": "json", + "kind": "house", + "results": 1 + } + + response = requests.get(url, params=params, timeout=5) + response.raise_for_status() + + data = response.json() + + # Извлекаем адрес из ответа + feature_member = data.get("response", {}).get("GeoObjectCollection", {}).get("featureMember", []) + if feature_member: + address = feature_member[0].get("GeoObject", {}).get("metaDataProperty", {}).get("GeocoderMetaData", {}).get("text") + if address: + return address + + return None + except Exception as e: + logger.error(f"Ошибка Yandex геокодера: {e}") + return None + + def _google_geocode(self, lat: float, lon: float) -> Optional[str]: + """ + Геокодирование с помощью Google Geocoding API + + Args: + lat: Широта + lon: Долгота + + Returns: + Адрес в виде строки или None + """ + if not self.google_api_key: + logger.warning("Google API key не установлен") + return None + + try: + url = "https://maps.googleapis.com/maps/api/geocode/json" + params = { + "latlng": f"{lat},{lon}", + "key": self.google_api_key, + "language": "ru" + } + + response = requests.get(url, params=params, timeout=5) + response.raise_for_status() + + data = response.json() + + # Извлекаем адрес из ответа + results = data.get("results", []) + if results: + address = results[0].get("formatted_address") + if address: + return address + + return None + except Exception as e: + logger.error(f"Ошибка Google геокодера: {e}") + return None + + def _openstreetmap_geocode(self, lat: float, lon: float) -> Optional[str]: + """ + Геокодирование с помощью OpenStreetMap Nominatim + + Args: + lat: Широта + lon: Долгота + + Returns: + Адрес в виде строки или None + """ + if not self.openstreetmap_enabled: + return None + + try: + url = "https://nominatim.openstreetmap.org/reverse" + params = { + "lat": lat, + "lon": lon, + "format": "json", + "addressdetails": 1, + "accept-language": "ru" + } + + headers = { + "User-Agent": "BuildingDetector/1.0 (hackathon project)" + } + + response = requests.get(url, params=params, headers=headers, timeout=5) + response.raise_for_status() + + data = response.json() + + # Извлекаем адрес из ответа + address = data.get("display_name") + if address: + return address + + return None + except Exception as e: + logger.error(f"Ошибка OpenStreetMap геокодера: {e}") + return None + + +# Глобальный экземпляр геокодера +geocoder_instance = None + + +def get_geocoder() -> Geocoder: + """Получение глобального экземпляра геокодера""" + global geocoder_instance + if geocoder_instance is None: + geocoder_instance = Geocoder() + return geocoder_instance + + +def geocode_coordinates(lat: float, lon: float) -> Optional[str]: + """ + Получение адреса по координатам + + Args: + lat: Широта + lon: Долгота + + Returns: + Адрес в виде строки или None + """ + geocoder = get_geocoder() + return geocoder.geocode(lat, lon) diff --git a/src/models/cv_model.py b/src/models/cv_model.py new file mode 100644 index 0000000..a5f6185 --- /dev/null +++ b/src/models/cv_model.py @@ -0,0 +1,218 @@ +import numpy as np +from typing import Dict, List, Optional +import logging +from datetime import datetime +from PIL import Image + +# Импортируем существующие компоненты +from .feature_extractor import FeatureExtractor +from .OCR_model import OverlayOCR +from data.faiss_indexer import FaissIndexer +from utils.config import DATA_PATHS, s3_manager +from src.geo.geocoder import geocode_coordinates + +logger = logging.getLogger(__name__) + + +class CVModel: + """Модель компьютерного зрения для детекции зданий и определения координат""" + + def __init__(self): + """Инициализация модели CV""" + self.ocr_model = OverlayOCR() + self.feature_extractor = FeatureExtractor() + self.indexer = None + self._initialize_faiss_index() + + def _initialize_faiss_index(self): + """Инициализация FAISS индекса""" + try: + logger.info("Инициализация FAISS индекса...") + self.indexer = FaissIndexer(dimension=2048) + self.indexer.load_index(DATA_PATHS["faiss_index"], DATA_PATHS["mapping_file"]) + logger.info("FAISS индекс инициализирован") + except Exception as e: + logger.error(f"Ошибка инициализации FAISS индекса: {e}") + raise + + def process_image(self, image_path: str) -> Dict: + """ + Обработка изображения: детекция зданий, определение координат, OCR + + Args: + image_path: Путь к изображению + + Returns: + Словарь с результатами обработки + """ + try: + result = { + "image_path": image_path, + "processed_at": datetime.now().isoformat(), + "buildings": [], + "coordinates": None, + "address": None, + "ocr_result": None + } + + # Загружаем изображение + image = Image.open(image_path) + if image.mode != "RGB": + image = image.convert("RGB") + + # Извлекаем признаки изображения + features = self.feature_extractor.extract_features(image) + + if features is not None: + # Поиск похожих изображений в базе + similar_images = self.indexer.search_similar(features, k=5) + + # Определяем координаты на основе топ-N похожих изображений + coordinates = self._estimate_coordinates(similar_images) + result["coordinates"] = coordinates + + # Получаем адрес по координатам + if coordinates: + result["address"] = self._geocode_coordinates(coordinates) + + # Детектируем здания (заглушка, так как у нас визуальный поиск) + result["buildings"] = self._detect_buildings_placeholder(image_path) + + # Выполняем OCR + try: + final, norm, joined, conf, roi_name = self.ocr_model.run_on_image(image_path) + result["ocr_result"] = { + "final": final, + "norm": norm, + "joined": joined, + "confidence": conf, + "roi_name": roi_name + } + except Exception as e: + logger.warning(f"Ошибка OCR для {image_path}: {e}") + + return result + + except Exception as e: + logger.error(f"Ошибка обработки изображения {image_path}: {e}") + raise + + def _estimate_coordinates(self, similar_images: List[Dict]) -> Optional[Dict]: + """ + Оценка координат на основе похожих изображений + + Args: + similar_images: Список похожих изображений с результатами поиска + + Returns: + Словарь с координатами {lat, lon} или None + """ + if not similar_images: + return None + + try: + # Получаем координаты из метаданных похожих изображений + coordinates_list = [] + + for img_result in similar_images: + s3_key = img_result["s3_key"] + # Здесь нужно извлечь координаты из метаданных S3 объекта + # или из отдельной базы данных с координатами + coords = self._get_image_coordinates_from_metadata(s3_key) + if coords: + # Взвешиваем координаты по степени схожести + weight = 1.0 / (1.0 + img_result["distance"]) + coordinates_list.append({ + "lat": coords["lat"], + "lon": coords["lon"], + "weight": weight + }) + + if not coordinates_list: + return None + + # Вычисляем взвешенное среднее координат + total_weight = sum(coord["weight"] for coord in coordinates_list) + if total_weight == 0: + return None + + avg_lat = sum(coord["lat"] * coord["weight"] for coord in coordinates_list) / total_weight + avg_lon = sum(coord["lon"] * coord["weight"] for coord in coordinates_list) / total_weight + + return { + "lat": avg_lat, + "lon": avg_lon + } + + except Exception as e: + logger.error(f"Ошибка оценки координат: {e}") + return None + + def _get_image_coordinates_from_metadata(self, s3_key: str) -> Optional[Dict]: + """ + Получение координат изображения из метаданных S3 + + Args: + s3_key: Ключ объекта в S3 + + Returns: + Словарь с координатами {lat, lon} или None + """ + try: + # Получаем метаданные объекта из S3 + metadata = s3_manager.get_object_metadata(s3_key) + + if metadata and "latitude" in metadata and "longitude" in metadata: + lat = float(metadata["latitude"]) + lon = float(metadata["longitude"]) + return {"lat": lat, "lon": lon} + + return None + except Exception as e: + logger.warning(f"Не удалось получить координаты для {s3_key}: {e}") + return None + + def _geocode_coordinates(self, coordinates: Dict) -> Optional[str]: + """ + Получение адреса по координатам + + Args: + coordinates: Словарь с координатами {lat, lon} + + Returns: + Адрес в виде строки или None + """ + if coordinates and "lat" in coordinates and "lon" in coordinates: + try: + address = geocode_coordinates(coordinates["lat"], coordinates["lon"]) + return address + except Exception as e: + logger.warning(f"Ошибка геокодирования координат {coordinates}: {e}") + return None + return None + + def _detect_buildings_placeholder(self, image_path: str) -> List[Dict]: + """ + Заглушка для детекции зданий + В текущей архитектуре используется визуальный поиск, поэтому детекция не требуется + + Args: + image_path: Путь к изображению + + Returns: + Список обнаруженных зданий + """ + # В текущей архитектуре мы не детектируем здания напрямую, + # а находим похожие изображения в базе + return [ + { + "bbox": [0, 0, 100, 100], # Заглушка + "confidence": 1.0, + "area": 10000 + } + ] + + +def create_cv_model() -> CVModel: + """Фабричная функция для создания экземпляра CVModel""" + return CVModel() diff --git a/src/models/feature_extractor.py b/src/models/feature_extractor.py new file mode 100644 index 0000000..5d99c1a --- /dev/null +++ b/src/models/feature_extractor.py @@ -0,0 +1,159 @@ +import io +import pickle +import time + +import numpy as np +import torch +import torch.nn as nn +from PIL import Image +from torchvision import models, transforms +from torchvision.models import ResNet50_Weights +from tqdm import tqdm + +from utils.config import MODEL_CONFIG, s3_manager + + +class FeatureExtractor: + def __init__(self, device=None): + # Определяем устройство + self.device = device or ("cuda" if torch.cuda.is_available() else "cpu") + print(f"Используется устройство: {self.device}") + + # Загружаем предобученную ResNet50 + self.model = models.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2) + self.model = nn.Sequential(*list(self.model.children())[:-1]) + self.model.eval() + self.model.to(self.device) + + # Трансформации для изображений + self.transform = transforms.Compose( + [ + transforms.Resize(MODEL_CONFIG["input_size"]), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ) + + # Статистика обработки + self.stats = {"processed": 0, "failed": 0, "total_time": 0} + + def load_image_from_bytes(self, image_data: bytes) -> Image.Image: + """Загрузка изображения из байтов""" + try: + image = Image.open(io.BytesIO(image_data)) + if image.mode != "RGB": + image = image.convert("RGB") + return image + except Exception as e: + print(f"Ошибка загрузки изображения из байтов: {e}") + return None + + def extract_features(self, image: Image.Image) -> np.ndarray: + """Извлечение признаков из изображения""" + try: + # Применяем трансформации + image_tensor = self.transform(image).unsqueeze(0).to(self.device) + + # Извлекаем признаки + with torch.no_grad(): + features = self.model(image_tensor) + + # Преобразуем в numpy array и нормализуем + features = features.cpu().numpy().flatten() + features = features / np.linalg.norm(features) + + return features + + except Exception as e: + print(f"Ошибка извлечения признаков: {e}") + return None + + def process_image_batch(self, image_batch: dict) -> dict: + """Обработка батча изображений {s3_key: image_data}""" + start_time = time.time() + batch_results = {} + + for s3_key, image_data in image_batch.items(): + # Загружаем изображение из байтов + image = self.load_image_from_bytes(image_data) + if image is None: + self.stats["failed"] += 1 + continue + + # Извлекаем признаки + features = self.extract_features(image) + if features is not None: + batch_results[s3_key] = {"features": features, "s3_key": s3_key} + self.stats["processed"] += 1 + else: + self.stats["failed"] += 1 + + batch_time = time.time() - start_time + self.stats["total_time"] += batch_time + + return batch_results + + def get_all_s3_images(self, prefix: str = "") -> list: + """Получение списка всех изображений в S3 bucket""" + print("Получение списка изображений из S3...") + image_keys = s3_manager.list_files(prefix=prefix, file_extensions=[".jpg", ".jpeg", ".png", ".webp"]) + print(f"Найдено {len(image_keys)} изображений") + return image_keys + + def process_all_images(self, batch_size: int = 32) -> dict: + """Пакетная обработка всех изображений из S3""" + print("Начало обработки всех изображений...") + + # Получаем список всех изображений + image_keys = self.get_all_s3_images() + total_images = len(image_keys) + + if total_images == 0: + print("Не найдено изображений для обработки") + return {}, [] + + features_dict = {} + failed_images = [] + + # Обработка батчами + for i in tqdm(range(0, total_images, batch_size)): + batch_keys = image_keys[i : i + batch_size] + + # Загружаем батч изображений из S3 + print(f"Загрузка батча {i//batch_size + 1}...") + batch_data = s3_manager.batch_download_bytes(batch_keys) + + # Обрабатываем батч + batch_results = self.process_image_batch(batch_data) + features_dict.update(batch_results) + + # Определяем неудачные загрузки + for key in batch_keys: + if key not in batch_results and batch_data.get(key) is not None: + failed_images.append(key) + + # Очистка памяти CUDA если используется GPU + if torch.cuda.is_available(): + torch.cuda.empty_cache() + + # Прогресс + current_processed = len(features_dict) + print(f"Обработано: {current_processed}/{total_images} " f"({current_processed/total_images*100:.1f}%)") + + # Статистика + success_rate = self.stats["processed"] / total_images * 100 + avg_time_per_image = self.stats["total_time"] / max(1, self.stats["processed"]) + + print(f"\n=== СТАТИСТИКА ОБРАБОТКИ ===") + print(f"Всего изображений: {total_images}") + print(f"Успешно обработано: {self.stats['processed']}") + print(f"Ошибки обработки: {self.stats['failed']}") + print(f"Успешность: {success_rate:.1f}%") + print(f"Среднее время на изображение: {avg_time_per_image:.3f} сек") + print(f"Общее время обработки: {self.stats['total_time']:.2f} сек") + + return features_dict, failed_images + + def get_processing_stats(self) -> dict: + """Получение статистики обработки""" + return self.stats.copy() diff --git a/src/tasks/worker.py b/src/tasks/worker.py new file mode 100644 index 0000000..cea0140 --- /dev/null +++ b/src/tasks/worker.py @@ -0,0 +1,212 @@ +import os +import logging +from celery import Celery +from sqlalchemy import create_engine, text +from sqlalchemy.orm import sessionmaker +import json +from datetime import datetime + +# Импортируем модели и компоненты +from src.models.cv_model import CVModel + +# Настройка логирования +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Создание Celery приложения +celery_app = Celery('building_detector') +celery_app.conf.update( + broker_url=os.getenv('REDIS_URL', 'redis://localhost:6379/0'), + result_backend=os.getenv('REDIS_URL', 'redis://localhost:6379/0'), + task_serializer='json', + accept_content=['json'], + result_serializer='json', + timezone='UTC', + enable_utc=True, + # Настройки производительности + worker_prefetch_multiplier=1, + task_acks_late=True, + worker_max_tasks_per_child=1000, + worker_concurrency=int(os.getenv('CELERY_WORKER_CONCURRENCY', '4')), +) + +# Настройка подключения к базе данных +DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://postgres:postgres@localhost:5432/building_detector') +engine = create_engine(DATABASE_URL) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +# Глобальная модель CV +cv_model = None + + +def get_cv_model(): + """Получение глобального экземпляра CV модели""" + global cv_model + if cv_model is None: + cv_model = CVModel() + return cv_model + + +@celery_app.task(bind=True) +def process_image_task(self, image_path: str, request_id: str = None) -> dict: + """ + Асинхронная задача для обработки изображения + + Args: + image_path: Путь к изображению + request_id: Идентификатор запроса (для отслеживания) + + Returns: + Результат обработки изображения + """ + try: + logger.info(f"Начало обработки изображения: {image_path}") + + # Получаем модель CV + model = get_cv_model() + + # Обрабатываем изображение + result = model.process_image(image_path) + + # Добавляем информацию о задаче + result["task_id"] = self.request.id + result["request_id"] = request_id + result["processed_at"] = datetime.now().isoformat() + + # Сохраняем результат в базу данных + save_result_to_db(result) + + logger.info(f"Обработка изображения завершена: {image_path}") + return result + + except Exception as e: + logger.error(f"Ошибка обработки изображения {image_path}: {e}") + # Сохраняем информацию об ошибке + error_result = { + "image_path": image_path, + "task_id": self.request.id, + "request_id": request_id, + "error": str(e), + "processed_at": datetime.now().isoformat() + } + save_result_to_db(error_result) + raise + + +def save_result_to_db(result: dict): + """ + Сохранение результата обработки в базу данных + + Args: + result: Результат обработки изображения + """ + try: + db = SessionLocal() + + # Подготавливаем данные для сохранения + image_path = result.get("image_path", "") + task_id = result.get("task_id", "") + request_id = result.get("request_id", "") + coordinates = result.get("coordinates", {}) + address = result.get("address", "") + ocr_result = result.get("ocr_result", {}) + buildings = result.get("buildings", []) + processed_at = result.get("processed_at", "") + error = result.get("error", "") + + # Преобразуем сложные объекты в JSON + coordinates_json = json.dumps(coordinates) if coordinates else "{}" + ocr_result_json = json.dumps(ocr_result) if ocr_result else "{}" + buildings_json = json.dumps(buildings) if buildings else "[]" + + # Вставляем данные в таблицу + query = text(""" + INSERT INTO processing_results ( + image_path, task_id, request_id, coordinates, address, + ocr_result, buildings, processed_at, error + ) VALUES ( + :image_path, :task_id, :request_id, :coordinates, :address, + :ocr_result, :buildings, :processed_at, :error + ) + """) + + db.execute(query, { + "image_path": image_path, + "task_id": task_id, + "request_id": request_id, + "coordinates": coordinates_json, + "address": address, + "ocr_result": ocr_result_json, + "buildings": buildings_json, + "processed_at": processed_at, + "error": error + }) + + db.commit() + db.close() + + logger.info(f"Результат сохранен в БД для задачи {task_id}") + + except Exception as e: + logger.error(f"Ошибка сохранения результата в БД: {e}") + if 'db' in locals(): + db.rollback() + db.close() + + +@celery_app.task(bind=True) +def batch_process_images_task(self, image_paths: list, request_id: str = None) -> dict: + """ + Асинхронная задача для пакетной обработки изображений + + Args: + image_paths: Список путей к изображениям + request_id: Идентификатор запроса (для отслеживания) + + Returns: + Сводный результат обработки + """ + try: + logger.info(f"Начало пакетной обработки {len(image_paths)} изображений") + + results = [] + errors = [] + + # Обрабатываем изображения по одному + for i, image_path in enumerate(image_paths): + try: + # Обновляем прогресс задачи + self.update_state( + state='PROGRESS', + meta={'current': i, 'total': len(image_paths)} + ) + + # Обрабатываем изображение + result = process_image_task(image_path, request_id) + results.append(result) + + except Exception as e: + logger.error(f"Ошибка обработки изображения {image_path}: {e}") + errors.append({"image_path": image_path, "error": str(e)}) + + # Формируем сводный результат + summary = { + "task_id": self.request.id, + "request_id": request_id, + "total_processed": len(results), + "total_errors": len(errors), + "results": results, + "errors": errors, + "processed_at": datetime.now().isoformat() + } + + logger.info(f"Пакетная обработка завершена. Обработано: {len(results)}, Ошибок: {len(errors)}") + return summary + + except Exception as e: + logger.error(f"Ошибка пакетной обработки: {e}") + raise + + +if __name__ == '__main__': + celery_app.start() diff --git a/src/utils/__init__.py b/src/utils/__init__.py index 9690669..1a7d1a6 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -1,5 +1,9 @@ -from .useful_functions import extract_coordinates, move_and_remove_files, merge_tables_with_tolerance, levenshtein_distance -from .s3 import s3_download_file, get_s3_client, s3_list_files, s3_upload_file +from .useful_functions import ( + extract_coordinates, + levenshtein_distance, + merge_tables_with_tolerance, + move_and_remove_files, +) from .zip import extract_zip_advanced __all__ = [ diff --git a/src/utils/config.py b/src/utils/config.py new file mode 100644 index 0000000..9603060 --- /dev/null +++ b/src/utils/config.py @@ -0,0 +1,35 @@ +import os + +from utils.s3_optimize import S3Manager + +s3_manager = S3Manager( + key_id=os.getenv("AWS_ACCESS_KEY_ID"), + access_key=os.getenv("AWS_SECRET_ACCESS_KEY"), + endpoint_url=os.getenv("AWS_ENDPOINT_URL"), + bucket_name=os.getenv("AWS_BUCKET_NAME"), + max_workers=4, + chunk_size=8 * 1024 * 1024, +) + +# Настройки модели +MODEL_CONFIG = {"model_name": "ResNet50", "input_size": (224, 224), "pooling": "avg"} + +# Настройки FAISS +FAISS_CONFIG = {"index_type": "IVF2048,Flat", "nlist": 2048, "metric": "l2"} + +# Пути для сохранения индекса (локально) +DATA_PATHS = { + "faiss_index": "data/index/faiss_index.bin", + "mapping_file": "data/processed/image_mapping.pkl", + "metadata_file": "data/processed/metadata.json", +} + +# Настройки производительности +PERFORMANCE_CONFIG = { + "max_concurrent_tasks": 4, + "batch_size": 32, + "max_image_size": (1920, 1080), + "cache_features": True, + "enable_gpu": False, + "processing_timeout": 300, # 5 минут на обработку одного изображения +} diff --git a/src/utils/monitor_database.py b/src/utils/monitor_database.py new file mode 100644 index 0000000..2a9e768 --- /dev/null +++ b/src/utils/monitor_database.py @@ -0,0 +1,64 @@ +import json +import os +import pickle + +import faiss + +from utils.config import DATA_PATHS, s3_manager + + +def monitor_database(): + """Мониторинг состояния базы данных""" + print("=== МОНИТОРИНГ БАЗЫ ДАННЫХ ===") + + # Проверка FAISS индекса + if os.path.exists(DATA_PATHS["faiss_index"]): + try: + index = faiss.read_index(DATA_PATHS["faiss_index"]) + print(f"✓ FAISS индекс: {index.ntotal} изображений") + except Exception as e: + print(f"✗ Ошибка загрузки FAISS индекса: {e}") + else: + print("✗ FAISS индекс не найден") + + # Проверка маппинга + if os.path.exists(DATA_PATHS["mapping_file"]): + try: + with open(DATA_PATHS["mapping_file"], "rb") as f: + mapping = pickle.load(f) + print(f"✓ Маппинг: {len(mapping)} записей") + except Exception as e: + print(f"✗ Ошибка загрузки маппинга: {e}") + else: + print("✗ Файл маппинга не найден") + + # Проверка метаданных + if os.path.exists(DATA_PATHS["metadata_file"]): + try: + with open(DATA_PATHS["metadata_file"], "r") as f: + metadata = json.load(f) + print("✓ Метаданные сборки:") + for key, value in metadata.items(): + if key != "processing_stats": + print(f" {key}: {value}") + except Exception as e: + print(f"✗ Ошибка загрузки метаданных: {e}") + else: + print("✗ Метаданные не найдены") + + # Проверка S3 + try: + total_s3_files = len(s3_manager.list_files(prefix="")) + print(f"✓ S3 бакет: {total_s3_files} файлов") + + upload_stats = s3_manager.get_upload_stats() + download_stats = s3_manager.get_download_stats() + print(f"✓ Статистика S3 загрузки: {upload_stats}") + print(f"✓ Статистика S3 скачивания: {download_stats}") + + except Exception as e: + print(f"✗ Ошибка подключения к S3: {e}") + + +if __name__ == "__main__": + monitor_database() diff --git a/src/utils/s3.py b/src/utils/s3.py deleted file mode 100644 index db2f9af..0000000 --- a/src/utils/s3.py +++ /dev/null @@ -1,74 +0,0 @@ -import os -from typing import TYPE_CHECKING - -import boto3 -from dotenv import load_dotenv - -if TYPE_CHECKING: - from mypy_boto3_s3.client import S3Client -else: - S3Client = object - -load_dotenv() - - -def get_s3_client( - key_id: str | None = None, - access_key: str | None = None, - endpoint_url: str | None = None, -) -> S3Client: - if key_id is None: - key_id = os.environ["AWS_ACCESS_KEY_ID"] - if access_key is None: - access_key = os.environ["AWS_SECRET_ACCESS_KEY"] - if endpoint_url is None: - endpoint_url = os.environ.get("AWS_ENDPOINT_URL", "https://s3-msk.tinkoff.ru") - - client: S3Client = boto3.client( - "s3", - aws_access_key_id=key_id, - aws_secret_access_key=access_key, - endpoint_url=endpoint_url, - ) - return client - - -def s3_upload_file( - file_local_src: str, - file_s3_dst: str, - remove_src_file: bool = False, - bucket_name: str | None = None, -) -> None: - if bucket_name is None: - bucket_name = os.environ["AWS_BUCKET_NAME"] - s3_client = get_s3_client() - - s3_client.upload_file(file_local_src, bucket_name, file_s3_dst) - if remove_src_file: - os.remove(file_local_src) - - -def s3_download_file( - file_s3_src: str, - file_local_dst: str, - bucket_name: str | None = None, -) -> None: - if bucket_name is None: - bucket_name = os.environ["AWS_BUCKET_NAME"] - s3_client = get_s3_client() - - os.makedirs(os.path.dirname(file_local_dst), exist_ok=True) - - s3_client.download_file(bucket_name, file_s3_src, file_local_dst) - - -def s3_list_files( - prefix: str = "", - bucket_name: str | None = None, -) -> list[str]: - if bucket_name is None: - bucket_name = os.environ["AWS_BUCKET_NAME"] - s3_client = get_s3_client() - - files = s3_client.list_objects_v2(Bucket=bucket_name, Prefix=prefix).get("Contents") - return [file["Key"] for file in files] diff --git a/src/utils/s3_optimize.py b/src/utils/s3_optimize.py new file mode 100644 index 0000000..e6c4a54 --- /dev/null +++ b/src/utils/s3_optimize.py @@ -0,0 +1,581 @@ +import concurrent.futures +import io +import logging +import os +import threading +from datetime import datetime +from pathlib import Path +from typing import BinaryIO, Dict, List, Optional, Tuple, Union + +import boto3 +import requests +from botocore.exceptions import ClientError, NoCredentialsError +from dotenv import load_dotenv + +# Настройка логирования +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +load_dotenv() + + +class S3Manager: + """Менеджер для высокопроизводительной работы с S3 (загрузка и скачивание)""" + + def __init__( + self, + key_id: str | None = None, + access_key: str | None = None, + endpoint_url: str | None = None, + bucket_name: str | None = None, + max_workers: int = 10, + chunk_size: int = 8 * 1024 * 1024, # 8MB chunks for multipart + ): + self.key_id = key_id or os.getenv("AWS_ACCESS_KEY_ID") + self.access_key = access_key or os.getenv("AWS_SECRET_ACCESS_KEY") + self.endpoint_url = endpoint_url or os.getenv("AWS_ENDPOINT_URL", "https://s3-msk.tinkoff.ru") + self.bucket_name = bucket_name or os.getenv("AWS_BUCKET_NAME") + self.max_workers = max_workers + self.chunk_size = chunk_size + + if not all([self.key_id, self.access_key, self.bucket_name]): + raise ValueError("Missing required AWS credentials") + + self._client = None + self._upload_lock = threading.Lock() + self._download_lock = threading.Lock() + self._upload_stats = {"successful": 0, "failed": 0, "total_size": 0} + self._download_stats = {"successful": 0, "failed": 0, "total_size": 0} + + @property + def client(self): + """Ленивая инициализация S3 клиента""" + if self._client is None: + try: + self._client = boto3.client( + "s3", + aws_access_key_id=self.key_id, + aws_secret_access_key=self.access_key, + endpoint_url=self.endpoint_url, + ) + # Проверяем подключение + self.client.head_bucket(Bucket=self.bucket_name) + logger.info(f"Успешно подключились к S3 бакету: {self.bucket_name}") + except Exception as e: + logger.error(f"Ошибка при создании S3 клиента: {e}") + raise + return self._client + + # ========== МЕТОДЫ ДЛЯ ЗАГРУЗКИ В S3 ========== + + def upload_bytes_parallel( + self, data: bytes, s3_key: str, content_type: str = "application/octet-stream", metadata: Optional[Dict] = None + ) -> bool: + """Параллельная загрузка больших файлов с использованием multipart upload""" + try: + if len(data) <= self.chunk_size: + # Для маленьких файлов используем обычную загрузку + return self.upload_bytes(data, s3_key, content_type, metadata) + + # Создаем multipart upload + multipart_args = {"ContentType": content_type} + if metadata: + multipart_args["Metadata"] = metadata + + mpu = self.client.create_multipart_upload(Bucket=self.bucket_name, Key=s3_key, **multipart_args) + mpu_id = mpu["UploadId"] + + parts = [] + futures = [] + + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + # Разбиваем данные на части и загружаем параллельно + for i, start in enumerate(range(0, len(data), self.chunk_size)): + end = min(start + self.chunk_size, len(data)) + part_data = data[start:end] + + future = executor.submit(self._upload_part, mpu_id, s3_key, i + 1, part_data) + futures.append(future) + + # Собираем результаты + for future in concurrent.futures.as_completed(futures): + part_num, etag = future.result() + parts.append({"PartNumber": part_num, "ETag": etag}) + + # Завершаем multipart upload + parts.sort(key=lambda x: x["PartNumber"]) + self.client.complete_multipart_upload( + Bucket=self.bucket_name, Key=s3_key, UploadId=mpu_id, MultipartUpload={"Parts": parts} + ) + + with self._upload_lock: + self._upload_stats["successful"] += 1 + self._upload_stats["total_size"] += len(data) + + logger.info(f"Multipart upload завершен: {s3_key} ({len(data)} bytes)") + return True + + except Exception as e: + logger.error(f"Ошибка multipart upload для {s3_key}: {e}") + with self._upload_lock: + self._upload_stats["failed"] += 1 + return False + + def _upload_part(self, upload_id: str, s3_key: str, part_number: int, data: bytes) -> tuple: + """Загрузка одной части в multipart upload""" + try: + response = self.client.upload_part( + Bucket=self.bucket_name, Key=s3_key, PartNumber=part_number, UploadId=upload_id, Body=io.BytesIO(data) + ) + return part_number, response["ETag"] + except Exception as e: + logger.error(f"Ошибка загрузки части {part_number} для {s3_key}: {e}") + raise + + def upload_bytes( + self, data: bytes, s3_key: str, content_type: str = "application/octet-stream", metadata: Optional[Dict] = None + ) -> bool: + """Быстрая загрузка байтов в S3""" + try: + extra_args = {"ContentType": content_type} + if metadata: + extra_args["Metadata"] = metadata + + self.client.upload_fileobj(io.BytesIO(data), self.bucket_name, s3_key, ExtraArgs=extra_args) + + with self._upload_lock: + self._upload_stats["successful"] += 1 + self._upload_stats["total_size"] += len(data) + + logger.debug(f"Успешная загрузка: {s3_key} ({len(data)} bytes)") + return True + + except Exception as e: + logger.error(f"Ошибка загрузки байтов в {s3_key}: {e}") + with self._upload_lock: + self._upload_stats["failed"] += 1 + return False + + def upload_file_parallel( + self, file_path: str, s3_key: str, remove_source: bool = False, metadata: Optional[Dict] = None + ) -> bool: + """Параллельная загрузка файла с оптимизацией для больших файлов""" + try: + file_size = os.path.getsize(file_path) + content_type = self._get_content_type(file_path) + + if file_size > self.chunk_size: + # Для больших файлов читаем и загружаем через multipart + with open(file_path, "rb") as f: + data = f.read() + result = self.upload_bytes_parallel(data, s3_key, content_type, metadata) + else: + # Для маленьких файлов используем стандартную загрузку + extra_args = {"ContentType": content_type} + if metadata: + extra_args["Metadata"] = metadata + + self.client.upload_file(file_path, self.bucket_name, s3_key, ExtraArgs=extra_args) + result = True + with self._upload_lock: + self._upload_stats["successful"] += 1 + self._upload_stats["total_size"] += file_size + + if result and remove_source: + os.remove(file_path) + logger.debug(f"Исходный файл удален: {file_path}") + + return result + + except Exception as e: + logger.error(f"Ошибка загрузки файла {file_path} в {s3_key}: {e}") + with self._upload_lock: + self._upload_stats["failed"] += 1 + return False + + def batch_upload_files( + self, file_paths: List[str], s3_prefix: str = "", remove_source: bool = False, progress_callback=None + ) -> Dict: + """Пакетная загрузка файлов с многопоточностью""" + results = {"successful": [], "failed": [], "total": len(file_paths)} + + def _upload_file(file_path): + try: + filename = Path(file_path).name + s3_key = f"{s3_prefix}/{filename}" if s3_prefix else filename + + if self.upload_file_parallel(file_path, s3_key, remove_source): + return file_path, True, s3_key + else: + return file_path, False, s3_key + + except Exception as e: + return file_path, False, str(e) + + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + future_to_file = {executor.submit(_upload_file, file_path): file_path for file_path in file_paths} + + for i, future in enumerate(concurrent.futures.as_completed(future_to_file)): + file_path, success, message = future.result() + + if success: + results["successful"].append(file_path) + else: + results["failed"].append((file_path, message)) + + if progress_callback and (i + 1) % 10 == 0: + progress_callback(i + 1, len(file_paths)) + + logger.info(f"Пакетная загрузка завершена: {len(results['successful'])}/{len(file_paths)} успешно") + return results + + def upload_image_data( + self, + image_data: Union[bytes, BinaryIO], + s3_key: str, + image_format: str = "JPEG", + quality: int = 85, + optimize: bool = True, + metadata: Optional[Dict] = None, + ) -> bool: + """Оптимизированная загрузка изображений с возможностью сжатия""" + try: + import io + + from PIL import Image + + content_types = {"JPEG": "image/jpeg", "PNG": "image/png", "GIF": "image/gif", "WEBP": "image/webp"} + + content_type = content_types.get(image_format.upper(), "image/jpeg") + + # Если данные уже в bytes, оптимизируем их + if isinstance(image_data, bytes): + with Image.open(io.BytesIO(image_data)) as img: + output = io.BytesIO() + + # Конвертируем в RGB если нужно + if image_format.upper() == "JPEG" and img.mode in ("RGBA", "P"): + img = img.convert("RGB") + + save_args = {"format": image_format, "optimize": optimize} + if image_format.upper() == "JPEG": + save_args["quality"] = quality + elif image_format.upper() == "WEBP": + save_args["quality"] = quality + + img.save(output, **save_args) + processed_data = output.getvalue() + else: + # Если это файловый объект + image_data.seek(0) + with Image.open(image_data) as img: + output = io.BytesIO() + + if image_format.upper() == "JPEG" and img.mode in ("RGBA", "P"): + img = img.convert("RGB") + + save_args = {"format": image_format, "optimize": optimize} + if image_format.upper() == "JPEG": + save_args["quality"] = quality + + img.save(output, **save_args) + processed_data = output.getvalue() + + # Добавляем метаданные об оптимизации + if metadata is None: + metadata = {} + # Убедимся, что все значения метаданных - строки + safe_metadata = {} + for k, v in metadata.items(): + safe_metadata[k] = str(v) + + safe_metadata["image_optimized"] = "true" + safe_metadata["image_format"] = image_format + safe_metadata["image_quality"] = str(quality) + + return self.upload_bytes(processed_data, s3_key, content_type, safe_metadata) + + except ImportError: + logger.warning("PIL не установлен, используем базовую загрузку") + if hasattr(image_data, "read"): + image_data.seek(0) + data = image_data.read() + else: + data = image_data + + return self.upload_bytes(data, s3_key, "image/jpeg", metadata) + except Exception as e: + logger.error(f"Ошибка при загрузке изображения {s3_key}: {e}") + return False + + # ========== МЕТОДЫ ДЛЯ СКАЧИВАНИЯ ИЗ S3 ========== + + def download_bytes(self, s3_key: str) -> Optional[bytes]: + """Загрузка файла из S3 в виде байтов""" + try: + with io.BytesIO() as data_stream: + self.client.download_fileobj(self.bucket_name, s3_key, data_stream) + data = data_stream.getvalue() + + with self._download_lock: + self._download_stats["successful"] += 1 + self._download_stats["total_size"] += len(data) + + logger.debug(f"Успешная загрузка: {s3_key} ({len(data)} bytes)") + return data + + except Exception as e: + logger.error(f"Ошибка загрузки байтов из {s3_key}: {e}") + with self._download_lock: + self._download_stats["failed"] += 1 + return None + + def download_file(self, s3_key: str, local_path: str) -> bool: + """Загрузка файла из S3 в локальный файл""" + try: + # Создаем директории если нужно + os.makedirs(os.path.dirname(local_path), exist_ok=True) + + self.client.download_file(self.bucket_name, s3_key, local_path) + + file_size = os.path.getsize(local_path) + with self._download_lock: + self._download_stats["successful"] += 1 + self._download_stats["total_size"] += file_size + + logger.debug(f"Успешная загрузка: {s3_key} -> {local_path} ({file_size} bytes)") + return True + + except Exception as e: + logger.error(f"Ошибка загрузки файла {s3_key} в {local_path}: {e}") + with self._download_lock: + self._download_stats["failed"] += 1 + return False + + def download_bytes_parallel(self, s3_key: str) -> Optional[bytes]: + """Параллельная загрузка больших файлов с использованием multipart download""" + try: + # Получаем размер файла + head_response = self.client.head_object(Bucket=self.bucket_name, Key=s3_key) + file_size = head_response["ContentLength"] + + if file_size <= self.chunk_size: + # Для маленьких файлов используем обычную загрузку + return self.download_bytes(s3_key) + + futures = [] + parts = [] + + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + # Загружаем части файла параллельно + for i, start_byte in enumerate(range(0, file_size, self.chunk_size)): + end_byte = min(start_byte + self.chunk_size - 1, file_size - 1) + + future = executor.submit(self._download_part, s3_key, start_byte, end_byte, i) + futures.append(future) + + # Собираем результаты + for future in concurrent.futures.as_completed(futures): + part_data, part_num = future.result() + parts.append((part_num, part_data)) + + # Собираем файл из частей + parts.sort(key=lambda x: x[0]) + full_data = b"".join(part_data for _, part_data in parts) + + with self._download_lock: + self._download_stats["successful"] += 1 + self._download_stats["total_size"] += len(full_data) + + logger.info(f"Multipart download завершен: {s3_key} ({len(full_data)} bytes)") + return full_data + + except Exception as e: + logger.error(f"Ошибка multipart download для {s3_key}: {e}") + with self._download_lock: + self._download_stats["failed"] += 1 + return None + + def _download_part(self, s3_key: str, start_byte: int, end_byte: int, part_num: int) -> tuple: + """Загрузка одной части файла""" + try: + response = self.client.get_object( + Bucket=self.bucket_name, Key=s3_key, Range=f"bytes={start_byte}-{end_byte}" + ) + part_data = response["Body"].read() + return part_data, part_num + except Exception as e: + logger.error(f"Ошибка загрузки части {part_num} для {s3_key}: {e}") + raise + + def batch_download_files(self, s3_keys: List[str], local_dir: str = "", progress_callback=None) -> Dict: + """Пакетная загрузка файлов с многопоточностью""" + results = {"successful": [], "failed": [], "total": len(s3_keys)} + + def _download_file(s3_key): + try: + # Определяем локальный путь + if local_dir: + filename = Path(s3_key).name + local_path = os.path.join(local_dir, filename) + else: + local_path = Path(s3_key).name + + if self.download_file(s3_key, local_path): + return s3_key, True, local_path + else: + return s3_key, False, local_path + + except Exception as e: + return s3_key, False, str(e) + + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + future_to_key = {executor.submit(_download_file, s3_key): s3_key for s3_key in s3_keys} + + for i, future in enumerate(concurrent.futures.as_completed(future_to_key)): + s3_key, success, message = future.result() + + if success: + results["successful"].append(s3_key) + else: + results["failed"].append((s3_key, message)) + + if progress_callback and (i + 1) % 10 == 0: + progress_callback(i + 1, len(s3_keys)) + + logger.info(f"Пакетная загрузка завершена: {len(results['successful'])}/{len(s3_keys)} успешно") + return results + + def batch_download_bytes(self, s3_keys: List[str], progress_callback=None) -> Dict[str, Optional[bytes]]: + """Пакетная загрузка файлов в память с многопоточностью""" + results = {} + + def _download_bytes(s3_key): + try: + data = self.download_bytes(s3_key) + return s3_key, data, True, "Success" + except Exception as e: + return s3_key, None, False, str(e) + + with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor: + future_to_key = {executor.submit(_download_bytes, s3_key): s3_key for s3_key in s3_keys} + + for i, future in enumerate(concurrent.futures.as_completed(future_to_key)): + s3_key, data, success, message = future.result() + + if success and data is not None: + results[s3_key] = data + else: + results[s3_key] = None + logger.warning(f"Не удалось загрузить {s3_key}: {message}") + + if progress_callback and (i + 1) % 10 == 0: + progress_callback(i + 1, len(s3_keys)) + + successful_count = sum(1 for data in results.values() if data is not None) + logger.info(f"Пакетная загрузка в память завершена: {successful_count}/{len(s3_keys)} успешно") + return results + + def list_files( + self, prefix: str = "", max_keys: int = 1000, file_extensions: Optional[List[str]] = None + ) -> List[str]: + """Получение списка файлов в S3 с фильтрацией""" + try: + files = [] + continuation_token = None + + while True: + list_args = {"Bucket": self.bucket_name, "Prefix": prefix, "MaxKeys": max_keys} + + if continuation_token: + list_args["ContinuationToken"] = continuation_token + + response = self.client.list_objects_v2(**list_args) + + if "Contents" in response: + for file in response["Contents"]: + key = file["Key"] + # Фильтрация по расширению + if file_extensions: + file_ext = Path(key).suffix.lower() + if file_ext not in [ext.lower() for ext in file_extensions]: + continue + files.append(key) + + if not response.get("IsTruncated"): + break + + continuation_token = response.get("NextContinuationToken") + + return files + + except Exception as e: + logger.error(f"Ошибка при получении списка файлов: {e}") + return [] + + def get_file_info(self, s3_key: str) -> Optional[Dict]: + """Получение информации о файле (метаданные, размер и т.д.)""" + try: + response = self.client.head_object(Bucket=self.bucket_name, Key=s3_key) + return { + "size": response["ContentLength"], + "last_modified": response["LastModified"], + "content_type": response.get("ContentType", ""), + "metadata": response.get("Metadata", {}), + } + except Exception as e: + logger.error(f"Ошибка при получении информации о файле {s3_key}: {e}") + return None + + def file_exists(self, s3_key: str) -> bool: + """Проверка существования файла в S3""" + try: + self.client.head_object(Bucket=self.bucket_name, Key=s3_key) + return True + except ClientError as e: + if e.response["Error"]["Code"] == "404": + return False + raise + except Exception as e: + logger.error(f"Ошибка при проверке существования файла {s3_key}: {e}") + return False + + # ========== СТАТИСТИКА И УТИЛИТЫ ========== + + def get_upload_stats(self) -> Dict: + """Получение статистики загрузки""" + return self._upload_stats.copy() + + def get_download_stats(self) -> Dict: + """Получение статистики скачивания""" + return self._download_stats.copy() + + def reset_upload_stats(self): + """Сброс статистики загрузки""" + with self._upload_lock: + self._upload_stats = {"successful": 0, "failed": 0, "total_size": 0} + + def reset_download_stats(self): + """Сброс статистики скачивания""" + with self._download_lock: + self._download_stats = {"successful": 0, "failed": 0, "total_size": 0} + + def _get_content_type(self, file_path: str) -> str: + """Определение Content-Type по расширению файла""" + extension = Path(file_path).suffix.lower() + + content_types = { + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".png": "image/png", + ".gif": "image/gif", + ".webp": "image/webp", + ".pdf": "application/pdf", + ".txt": "text/plain", + ".csv": "text/csv", + ".json": "application/json", + ".xml": "application/xml", + ".zip": "application/zip", + } + + return content_types.get(extension, "application/octet-stream") diff --git a/tests/quick_test.py b/tests/quick_test.py new file mode 100644 index 0000000..c5e4a58 --- /dev/null +++ b/tests/quick_test.py @@ -0,0 +1,89 @@ +import time +from utils.config import s3_manager +from models.feature_extractor import FeatureExtractor +from data.faiss_indexer import FaissIndexer +import os +import json +import pickle + +def quick_build_test(max_files=50): + """Быстрое тестирование на небольшом подмножестве""" + print(f"=== БЫСТРОЕ ТЕСТИРОВАНИЕ НА {max_files} ФАЙЛАХ ===") + + # 1. Быстро получаем только несколько файлов + print("1. Получение списка файлов из S3...") + all_files = s3_manager.list_files(prefix="", file_extensions=[".jpg", ".jpeg", ".png", ".webp"]) + + if not all_files: + print("Не найдено файлов в S3!") + return + + # Фильтруем только изображения + image_files = [f for f in all_files if f.lower().endswith(('.jpg', '.jpeg', '.png'))] + image_files = image_files[:max_files] # Берем только первые N + + print(f"Будет обработано {len(image_files)} изображений") + + # 2. Создаем директории + os.makedirs('data_test/processed', exist_ok=True) + os.makedirs('data_test/index', exist_ok=True) + + # 3. Загружаем и обрабатываем изображения + print("2. Загрузка и обработка изображений...") + extractor = FeatureExtractor() + features_dict = {} + + for i, s3_key in enumerate(image_files): + print(f" Обработка {i+1}/{len(image_files)}: {s3_key}") + + # Загружаем одно изображение + image_data = s3_manager.download_bytes(s3_key) + if image_data: + # Преобразуем в изображение + from PIL import Image + import io + image = Image.open(io.BytesIO(image_data)) + if image.mode != 'RGB': + image = image.convert('RGB') + + # Извлекаем признаки + features = extractor.extract_features(image) + if features is not None: + features_dict[s3_key] = { + 'features': features, + 's3_key': s3_key + } + + print(f"Успешно обработано: {len(features_dict)}/{len(image_files)}") + + if not features_dict: + print("Не удалось обработать ни одного изображения!") + return + + # 4. Создаем FAISS индекс + print("3. Создание FAISS индекса...") + indexer = FaissIndexer(dimension=2048) + num_indexed = indexer.create_index(features_dict, index_type='Flat') # Используем простой индекс + + # 5. Сохраняем результаты + print("4. Сохранение результатов...") + indexer.save_index('data_test/index/faiss_index.bin', 'data_test/processed/image_mapping.pkl') + + # Сохраняем метаданные + metadata = { + 'test_files_processed': len(features_dict), + 'total_files_in_test': len(image_files), + 'model_used': 'ResNet50', + 'build_time': 'quick_test', + 'note': 'Быстрый тест на ограниченном наборе данных' + } + + with open('data_test/processed/metadata.json', 'w') as f: + json.dump(metadata, f, indent=2) + + print("=== ТЕСТИРОВАНИЕ ЗАВЕРШЕНО! ===") + print(f"Создана тестовая база с {num_indexed} изображениями") + print("Файлы сохранены в data_test/") + +if __name__ == "__main__": + quick_build_test(max_files=5000) # Обработаем только 20 файлов для теста \ No newline at end of file diff --git a/tests/test_data.py b/tests/test_data.py deleted file mode 100644 index f5575b1..0000000 --- a/tests/test_data.py +++ /dev/null @@ -1,112 +0,0 @@ -import os -import tempfile - -import numpy as np -import pandas as pd -import pytest -import yaml - -from src.data.make_dataset import load_data, preprocess_data, split_data - - -@pytest.fixture -def sample_data(): - """Создание примера данных для тестирования""" - data = { - "age": [25, 30, 35, 40, 45], - "income": [50000, 60000, 70000, 80000, 90000], - "gender": ["M", "F", "M", "F", "M"], - "education": ["Bachelor", "Master", "PhD", "Bachelor", "Master"], - "target": [0, 1, 1, 0, 1], - } - return pd.DataFrame(data) - - -@pytest.fixture -def config(): - """Пример конфигурации для тестирования""" - return { - "features": {"numeric_features": ["age", "income"], "categorical_features": ["gender", "education"]}, - "data": {"test_size": 0.2, "random_state": 42}, - } - - -def test_load_data(sample_data): - """Тест загрузки данных из CSV файла""" - # Создание временного CSV файла - with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f: - sample_data.to_csv(f.name, index=False) - temp_filename = f.name - - try: - # Тест загрузки данных - loaded_data = load_data(temp_filename) - assert isinstance(loaded_data, pd.DataFrame) - assert loaded_data.shape == sample_data.shape - assert list(loaded_data.columns) == list(sample_data.columns) - finally: - # Очистка временного файла - os.unlink(temp_filename) - - # Тест обработки ошибок для несуществующего файла - with pytest.raises(FileNotFoundError): - load_data("non_existent_file.csv") - - -def test_preprocess_data(sample_data, config): - """Тест предобработки данных""" - # Тест нормальной предобработки - processed_data = preprocess_data( - sample_data, config["features"]["numeric_features"], config["features"]["categorical_features"] - ) - - assert isinstance(processed_data, pd.DataFrame) - # Проверка, что категориальные переменные закодированы - assert "gender_M" in processed_data.columns - assert "education_Master" in processed_data.columns - # Проверка, что оригинальные категориальные столбцы удалены - assert "gender" not in processed_data.columns - assert "education" not in processed_data.columns - - # Тест обработки пропущенных значений - sample_data_with_nan = sample_data.copy() - sample_data_with_nan.loc[0, "age"] = np.nan - sample_data_with_nan.loc[1, "gender"] = np.nan - - processed_data_with_nan = preprocess_data( - sample_data_with_nan, config["features"]["numeric_features"], config["features"]["categorical_features"] - ) - - # Проверка, что пропущенные значения обработаны - assert not processed_data_with_nan.isnull().any().any() - - -def test_split_data(sample_data, config): - """Тест разделения данных на обучающую и тестовую выборки""" - # Тест нормального разделения - X_train, X_test, y_train, y_test = split_data( - sample_data, "target", config["data"]["test_size"], config["data"]["random_state"] - ) - - assert isinstance(X_train, pd.DataFrame) - assert isinstance(X_test, pd.DataFrame) - assert isinstance(y_train, pd.Series) - assert isinstance(y_test, pd.Series) - - # Проверка размеров - total_samples = len(sample_data) - test_samples = int(total_samples * config["data"]["test_size"]) - train_samples = total_samples - test_samples - - assert len(X_train) == train_samples - assert len(X_test) == test_samples - assert len(y_train) == train_samples - assert len(y_test) == test_samples - - # Тест обработки ошибок для несуществующего целевого столбца - with pytest.raises(ValueError): - split_data(sample_data, "non_existent_column") - - -if __name__ == "__main__": - pytest.main([__file__]) diff --git a/tests/test_functional.py b/tests/test_functional.py new file mode 100644 index 0000000..77123af --- /dev/null +++ b/tests/test_functional.py @@ -0,0 +1,117 @@ +import unittest +import os +import tempfile +import numpy as np +from PIL import Image +import sys +import logging + +# Добавляем путь к src для импорта модулей +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + +from src.models.cv_model import CVModel +from src.models.feature_extractor import FeatureExtractor +from src.data.faiss_indexer import FaissIndexer +from src.geo.geocoder import Geocoder + + +class TestFunctional(unittest.TestCase): + """Функциональные тесты для проверки работы системы""" + + @classmethod + def setUpClass(cls): + """Инициализация перед всеми тестами""" + # Настройка логирования + logging.basicConfig(level=logging.INFO) + cls.logger = logging.getLogger(__name__) + + def setUp(self): + """Инициализация перед каждым тестом""" + pass + + def tearDown(self): + """Очистка после каждого теста""" + pass + + def test_feature_extraction(self): + """Тест извлечения признаков из изображения""" + # Создаем тестовое изображение + test_image = Image.new('RGB', (224, 224), color='red') + + # Инициализируем экстрактор признаков + extractor = FeatureExtractor() + + # Извлекаем признаки + features = extractor.extract_features(test_image) + + # Проверяем, что признаки извлечены корректно + self.assertIsNotNone(features) + self.assertEqual(features.shape, (2048,)) # ResNet50 features + self.assertAlmostEqual(np.linalg.norm(features), 1.0, places=3) # Нормализованные признаки + + def test_faiss_index_operations(self): + """Тест операций с FAISS индексом""" + # Создаем тестовые признаки + features_dict = {} + for i in range(5): + features_dict[f"test_image_{i}.jpg"] = { + "features": np.random.rand(2048).astype('float32'), + "s3_key": f"test/test_image_{i}.jpg" + } + + # Создаем FAISS индекс + indexer = FaissIndexer(dimension=2048) + num_indexed = indexer.create_index(features_dict, index_type="Flat") + + # Проверяем, что индекс создан корректно + self.assertEqual(num_indexed, 5) + self.assertIsNotNone(indexer.index) + self.assertEqual(len(indexer.image_mapping), 5) + + # Тестируем поиск похожих изображений + query_features = np.random.rand(2048).astype('float32') + similar_images = indexer.search_similar(query_features, k=3) + + # Проверяем результаты поиска + self.assertEqual(len(similar_images), 3) + for result in similar_images: + self.assertIn("rank", result) + self.assertIn("s3_key", result) + self.assertIn("distance", result) + self.assertIn("similarity_score", result) + + def test_geocoder_initialization(self): + """Тест инициализации геокодера""" + geocoder = Geocoder() + + # Проверяем, что геокодер инициализирован корректно + self.assertIsNotNone(geocoder) + + def test_cv_model_initialization(self): + """Тест инициализации CV модели""" + try: + cv_model = CVModel() + + # Проверяем, что модель инициализирована корректно + self.assertIsNotNone(cv_model.feature_extractor) + self.assertIsNotNone(cv_model.ocr_model) + # Примечание: indexer может не быть инициализирован, если нет индекса + + except Exception as e: + # Разрешаем ошибку инициализации индекса, если индекс не существует + self.assertIn("FAISS", str(e)) + + def test_performance_requirements(self): + """Тест требований к производительности""" + # Проверяем, что система может обработать 1000 изображений за ≤3 часов + # Это тест производительности, который должен выполняться отдельно + max_processing_time = 3 * 60 * 60 # 3 часа в секундах + max_images = 1000 + max_time_per_image = max_processing_time / max_images # 10.8 секунд на изображение + + # Для демонстрации: проверяем, что максимальное время на изображение >= 1 секунды + self.assertGreaterEqual(max_time_per_image, 1.0) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_models.py b/tests/test_models.py deleted file mode 100644 index faa67b8..0000000 --- a/tests/test_models.py +++ /dev/null @@ -1,186 +0,0 @@ -import os -import tempfile -from unittest.mock import MagicMock, patch - -import joblib -import numpy as np -import pandas as pd -import pytest - -from src.models.evaluate import load_model, plot_confusion_matrix -from src.models.train import ( - evaluate_model, - get_model, - save_metrics, - save_model, - train_model, -) - - -@pytest.fixture -def sample_data(): - """Создание примера данных для тестирования""" - np.random.seed(42) - X = pd.DataFrame( - {"feature_1": np.random.randn(100), "feature_2": np.random.randn(100), "feature_3": np.random.randn(100)} - ) - y = pd.Series(np.random.randint(0, 2, 100)) - return X, y - - -@pytest.fixture -def trained_model(sample_data): - """Создание обученной модели для тестирования""" - X, y = sample_data - model = get_model("random_forest", {"n_estimators": 10, "random_state": 42}) - return train_model(model, X, y) - - -def test_get_model(): - """Тест инициализации модели""" - # Тест случайного леса - rf_model = get_model("random_forest", {"n_estimators": 10, "random_state": 42}) - assert rf_model.__class__.__name__ == "RandomForestClassifier" - - # Тест логистической регрессии - lr_model = get_model("logistic_regression", {"random_state": 42}) - assert lr_model.__class__.__name__ == "LogisticRegression" - - # Тест неподдерживаемой модели - with pytest.raises(ValueError): - get_model("unsupported_model", {}) - - -def test_train_model(sample_data): - """Тест обучения модели""" - X, y = sample_data - model = get_model("random_forest", {"n_estimators": 10, "random_state": 42}) - - # Обучение модели - trained_model = train_model(model, X, y) - - # Проверка, что модель обучена - assert hasattr(trained_model, "predict") - assert hasattr(trained_model, "feature_importances_") - - -def test_evaluate_model(sample_data, trained_model): - """Тест оценки модели""" - X, y = sample_data - - # Оценка модели - metrics = evaluate_model(trained_model, X, y) - - # Проверка структуры метрик - assert isinstance(metrics, dict) - assert "accuracy" in metrics - assert "precision" in metrics - assert "recall" in metrics - assert "f1_score" in metrics - - # Проверка, что значения метрик находятся в допустимом диапазоне - assert 0 <= metrics["accuracy"] <= 1 - assert 0 <= metrics["precision"] <= 1 - assert 0 <= metrics["recall"] <= 1 - assert 0 <= metrics["f1_score"] <= 1 - - -def test_save_model(trained_model): - """Тест сохранения модели на диск""" - # Создание временного файла - with tempfile.NamedTemporaryFile(suffix=".pkl", delete=False) as f: - model_path = f.name - - try: - # Сохранение модели - save_model(trained_model, model_path) - - # Проверка, что файл существует - assert os.path.exists(model_path) - - # Проверка, что модель может быть загружена - loaded_model = joblib.load(model_path) - assert hasattr(loaded_model, "predict") - finally: - # Очистка - if os.path.exists(model_path): - os.unlink(model_path) - - -def test_save_metrics(): - """Тест сохранения метрик в JSON файл""" - metrics = {"accuracy": 0.95, "precision": 0.93, "recall": 0.92, "f1_score": 0.925} - - # Создание временного файла - with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f: - metrics_path = f.name - - try: - # Сохранение метрик - save_metrics(metrics, metrics_path) - - # Проверка, что файл существует - assert os.path.exists(metrics_path) - - # Проверка, что метрики могут быть загружены - import json - - with open(metrics_path, "r") as f: - loaded_metrics = json.load(f) - - assert loaded_metrics == metrics - finally: - # Очистка - if os.path.exists(metrics_path): - os.unlink(metrics_path) - - -def test_load_model(trained_model): - """Тест загрузки модели с диска""" - # Создание временного файла - with tempfile.NamedTemporaryFile(suffix=".pkl", delete=False) as f: - model_path = f.name - - try: - # Сохранение модели - joblib.dump(trained_model, model_path) - - # Загрузка модели - loaded_model = load_model(model_path) - - # Проверка, что модель загружена правильно - assert hasattr(loaded_model, "predict") - assert hasattr(loaded_model, "feature_importances_") - - # Тест обработки ошибок для несуществующего файла - with pytest.raises(FileNotFoundError): - load_model("non_existent_file.pkl") - finally: - # Очистка - if os.path.exists(model_path): - os.unlink(model_path) - - -@patch("matplotlib.pyplot.savefig") -def test_plot_confusion_matrix(mock_savefig): - """Тест построения матрицы ошибок""" - # Создание примера данных - y_true = [0, 1, 0, 1, 0, 1] - y_pred = [0, 1, 1, 1, 0, 0] - - # Тест построения графика - plot_confusion_matrix(y_true, y_pred) - - # Проверка, что savefig был вызван - mock_savefig.assert_called_once() - - # Тест с пользовательским путем сохранения - custom_path = "custom/path/confusion_matrix.png" - plot_confusion_matrix(y_true, y_pred, save_path=custom_path) - - # Проверка, что savefig был вызван с пользовательским путем - mock_savefig.assert_called_with(custom_path) - - -if __name__ == "__main__": - pytest.main([__file__]) diff --git a/tests/test_search.py b/tests/test_search.py new file mode 100644 index 0000000..1f9c80a --- /dev/null +++ b/tests/test_search.py @@ -0,0 +1,115 @@ +import io + +import matplotlib.pyplot as plt +import torch +from PIL import Image + +from data.faiss_indexer import FaissIndexer +from models.feature_extractor import FeatureExtractor +from utils.config import DATA_PATHS, s3_manager + + +def test_search(): + """Тестирование поиска по базе""" + print("=== Тестирование поиска похожих изображений ===") + + # Загрузка индекса + print("Загрузка FAISS индекса...") + indexer = FaissIndexer() + indexer.load_index(DATA_PATHS["faiss_index"], DATA_PATHS["mapping_file"]) + + # Загрузка feature extractor + print("Инициализация feature extractor...") + extractor = FeatureExtractor() + + # Тестовое изображение (можно заменить на любой файл) + test_image_path = "/home/lizardapn/Hack_digital/hack_digital_transformation/data/processed_data/images_build/0a0b860f-bde7-42a6-9bc1-e8e0273fbdc8.jpg" + try: + test_image = Image.open(test_image_path) + if test_image.mode != "RGB": + test_image = test_image.convert("RGB") + print(f"Тестовое изображение загружено: {test_image_path}") + except Exception as e: + print(f"Ошибка загрузки тестового изображения: {e}") + # Альтернатива: использовать случайное изображение из базы + if indexer.image_mapping: + first_key = list(indexer.image_mapping.values())[0]["s3_key"] + image_data = s3_manager.download_bytes(first_key) + if image_data: + test_image = Image.open(io.BytesIO(image_data)) + print(f"Используется первое изображение из базы: {first_key}") + else: + print("Не удалось загрузить тестовое изображение") + return + else: + print("База данных пуста") + return + + # Извлечение признаков + print("Извлечение признаков из тестового изображения...") + features = extractor.extract_features(test_image) + + if features is None: + print("Не удалось извлечь признаки из тестового изображения") + return + + # Поиск похожих + print("Поиск похожих изображений...") + results = indexer.search_similar(features, k=5) + + print("\n" + "=" * 50) + print("ТОП-5 ПОХОЖИХ ИЗОБРАЖЕНИЙ:") + print("=" * 50) + + for i, result in enumerate(results): + print(f"{result['rank']}. {result['s3_key']}") + print(f" Схожесть: {result['similarity_score']:.3f}") + print(f" Расстояние: {result['distance']:.3f}") + print() + + # Визуализация результатов + try: + visualize_results(test_image, results, extractor) + except Exception as e: + print(f"Ошибка визуализации: {e}") + + +def visualize_results(query_image, results, extractor): + """Визуализация результатов поиска""" + fig, axes = plt.subplots(2, 3, figsize=(15, 10)) + axes = axes.flatten() + + # Запрос + axes[0].imshow(query_image) + axes[0].set_title("Запрос", fontsize=12, fontweight="bold") + axes[0].axis("off") + + # Результаты + for i, result in enumerate(results[:5]): + similar_image_data = s3_manager.download_bytes(result["s3_key"]) + if similar_image_data: + similar_image = Image.open(io.BytesIO(similar_image_data)) + axes[i + 1].imshow(similar_image) + axes[i + 1].set_title(f"#{i+1} Схожесть: {result['similarity_score']:.3f}\n{result['s3_key']}", fontsize=10) + axes[i + 1].axis("off") + else: + axes[i + 1].text( + 0.5, + 0.5, + f"Не удалось\nзагрузить\n{result['s3_key']}", + ha="center", + va="center", + transform=axes[i + 1].transAxes, + ) + axes[i + 1].axis("off") + + # Скрываем пустые subplots + for i in range(len(results) + 1, 6): + axes[i].axis("off") + + plt.tight_layout() + plt.show() + + +if __name__ == "__main__": + test_search()