Skip to content

Conversation

@FeezyHendrix
Copy link
Collaborator

What type of PR is this? (check all applicable)

  • πŸ• Feature
  • πŸ› Bug Fix
  • πŸ“ Documentation
  • πŸ§‘β€πŸ’» Refactor
  • βœ… Test
  • πŸ€– Build or CI
  • ❓ Other (please specify)

Related Issue

Implements the batch processing step (Step 4) of the drone image processing workflow.

Describe this PR

This PR adds the final processing step to the drone image workflow, enabling batch processing of classified and reviewed images.

Key Features:

Batch Processing (Step 4)

  • Summary view showing tasks and image counts ready for ODM processing
  • Background job to move images from staging (user-uploads/) to task folders ({task_id}/images/)
  • Triggers ODM processing jobs for each task with assigned images
  • Real-time status updates during processing

Backend Changes:

  • move_batch_images_to_tasks() in ImageClassifier - copies images from staging to task folders in S3
  • get_batch_processing_summary() - returns task-grouped summary for the UI
  • New API endpoints:
    • GET /api/projects/{id}/batch/{batch_id}/processing-summary/ - Get processing summary
    • POST /api/projects/{id}/batch/{batch_id}/process/ - Start batch processing
  • process_batch_images ARQ background task that moves images and triggers ODM jobs

Frontend Changes:

  • ImageProcessing.tsx component with task list and processing controls
  • Service functions: getProcessingSummary(), startBatchProcessing()
  • Processing status display with job tracking

Screenshots

Screenshot 2025-12-22 at 13 38 32

Review Guide

  1. Navigate to Step 4 (Processing) in the drone image workflow
  2. Verify the task list shows correct image counts per task
  3. Click "Start Processing" to trigger the batch job
  4. Check backend logs to confirm images are moved to task folders and ODM jobs are queued

API Endpoints to test:

  • GET /api/projects/{id}/batch/{batch_id}/processing-summary/
  • POST /api/projects/{id}/batch/{batch_id}/process/

Checklist before requesting a review

  • πŸ“– Read the HOT Code of Conduct: https://docs.hotosm.org/code-of-conduct
  • πŸ‘·β€β™€οΈ Create small PRs. In most cases, this will be possible.
  • βœ… Provide tests for your changes.
  • πŸ“ Use descriptive commit messages.
  • πŸ“— Update any related documentation and include any relevant screenshots.

AbdulHafeez AbdulRaheem and others added 30 commits October 7, 2025 09:07
…le handling

- Added Uppy instance to the global App component for shared file upload functionality.
- Implemented UppyImageUploader component to utilize Uppy for image uploads with AWS S3 integration.
- Refactored file handling to extract EXIF data upon file addition and display upload progress.
- Updated Vite configuration to target 'esnext' for improved compatibility
…inIO

- Replaced MinIO client with boto3 for S3 operations in s3.py.
- Updated methods for file upload, download, and presigned URL generation to align with boto3 API.
- Adjusted error handling to use ClientError from botocore.
- Modified user_schemas.py to generate presigned URLs using boto3.
- Updated dependencies in pyproject.toml to include boto3 and remove MinIO.
- Ensured compatibility with existing code by stripping leading slashes from S3 paths.
- Added content type headers for multipart upload requests in the frontend UppyImageUploader component
…w UI with upload, classification, review, and processing steps
…ance upload functionality

- Replaced UppyImageUploader with UppyFileUploader for consistency across components.
- Improved ImageUpload component to track upload progress and display upload queue.
- Added support for staging uploads in UppyFileUploader.
- Updated DroneImageProcessingWorkflow to adjust modal dimensions for better usability.
- Removed unused UppyImageUploader component and its related code

BREAKING CHANGE: Switch from minio to boto3
…ance upload functionality

- Replaced UppyImageUploader with UppyFileUploader for consistency across components.
- Improved ImageUpload component to track upload progress and display upload queue.
- Added support for staging uploads in UppyFileUploader.
- Updated DroneImageProcessingWorkflow to adjust modal dimensions for better usability.
- Removed unused UppyImageUploader component and its related code
… table migration with conditional enum creation and improved index handling
…epSwitcher component for project steps navigation
…l for managing project images with relationships and indexing
… code formatting in image logic and migration files
… with generate_presigned_download_url across the codebase; add new migration script for images from S3
…migration with conflict handling and improved logging
* feat: added multipart initate upload route

* feat: added all multipart upload functions

* feat(UploadBox): Swapped upload from single to multipart upload using uppy

* feat(frontend): add @uppy/drag-drop and @uppy/progress-bar dependencies; update moduleResolution to bundler

* feat(frontend): feat: integrate Uppy for image uploads and enhance file handling

- Added Uppy instance to the global App component for shared file upload functionality.
- Implemented UppyImageUploader component to utilize Uppy for image uploads with AWS S3 integration.
- Refactored file handling to extract EXIF data upon file addition and display upload progress.
- Updated Vite configuration to target 'esnext' for improved compatibility

* feat(image-upload): Refactor S3 integration to use boto3 instead of MinIO

- Replaced MinIO client with boto3 for S3 operations in s3.py.
- Updated methods for file upload, download, and presigned URL generation to align with boto3 API.
- Adjusted error handling to use ClientError from botocore.
- Modified user_schemas.py to generate presigned URLs using boto3.
- Updated dependencies in pyproject.toml to include boto3 and remove MinIO.
- Ensured compatibility with existing code by stripping leading slashes from S3 paths.
- Added content type headers for multipart upload requests in the frontend UppyImageUploader component

* feat(image-upload-workflow): Refactor code structure for improved readability and maintainability

* feat(image-upload-workflow): Implement drone image processing workflow UI with upload, classification, review, and processing steps

* feat(image-upload-workflow): Refactor image upload components and enhance upload functionality

- Replaced UppyImageUploader with UppyFileUploader for consistency across components.
- Improved ImageUpload component to track upload progress and display upload queue.
- Added support for staging uploads in UppyFileUploader.
- Updated DroneImageProcessingWorkflow to adjust modal dimensions for better usability.
- Removed unused UppyImageUploader component and its related code

BREAKING CHANGE: Switch from minio to boto3

* feat(image-upload-workflow): Refactor image upload components and enhance upload functionality

- Replaced UppyImageUploader with UppyFileUploader for consistency across components.
- Improved ImageUpload component to track upload progress and display upload queue.
- Added support for staging uploads in UppyFileUploader.
- Updated DroneImageProcessingWorkflow to adjust modal dimensions for better usability.
- Removed unused UppyImageUploader component and its related code

* fixed with minio

* feat(image-upload-workflow): Add project_id and filename to the upload request in UppyFileUploader

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* feat(image-upload-workflow): feat(migrations): Enhance project_images table migration with conditional enum creation and improved index handling

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(image-upload-workflow): feat(step-switcher): Implement generic StepSwitcher component for project steps navigation

* feat(image-upload-workflow): feat(db-models): Add DbProjectImage model for managing project images with relationships and indexing

* feat(image-upload-workflow): Enhance image processing with new database save function and EXIF handling

* refactor(image-upload-workflow): Replace deprecated get_presigned_url with generate_presigned_download_url across the codebase; add new migration script for images from S3

* fix(image-upload-workflow): Implement upsert functionality for image migration with conflict handling and improved logging

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: AbdulHafeez AbdulRaheem <aabdulraheem@joinernest.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Added new hooks for starting classification, fetching batch status, and retrieving batch images in the projects API.
- Enhanced the ImageClassification component to handle classification processes, including polling for updates and displaying status.
- Updated the DroneImageProcessingWorkflow to manage batch ID and transition between upload and classification steps.
- Modified UppyFileUploader to support batch ID generation and pass it upon upload completion.
- Created a new migration to add classification-related fields to the project_images table.
- Developed new classification routes for starting batch classification and retrieving batch status and images.
- Implemented the ImageClassifier class to handle image classification logic, including quality checks and task matching.
- Added service functions for interacting with the classification API, including starting classification and fetching batch details
…ges and implement sharpness calculation in image classification
…oaded' to 'staged' and enhance upload notifications
…th accept/reject functionality

- Updated `useGetBatchImagesQuery` to specify query options for image classification results.
- Implemented image acceptance mutation in `ImageClassification` component to handle rejected images.
- Added warning for high issue rates in classified images.
- Introduced a button to mark rejected images as good in `ImageClassification`.
- Enhanced `ImageReview` component with map integration and improved image handling.
- Added batch deletion functionality with confirmation dialog in `DroneImageProcessingWorkflow`.
- Refactored `Accordion` component to support dynamic content and improved styling.
- Updated classification service to include image acceptance and batch deletion methods
…k waypoint query

- Added dotenv package version 16.4.7 to pnpm-lock.yaml.
- Modified useGetTaskWaypointQuery to include projectId and taskId in queryKey for better cache management.
- Updated LocateUser component usage in MapSection to remove unnecessary isMapLoaded prop.
- Enhanced DescriptionBox to indicate estimated flight time with an asterisk and added explanatory note.
- Improved MapSection to handle battery warnings and waypoint limits, including user notifications for excessive waypoints.
- Added a basic OSM raster basemap to VectorLayerWithCluster to prevent blank maps when vector tiles fail to load.
- Refactored ToolTip component styles for better readability.
- Introduced waypointUpperLimit constant to manage waypoint limits in task descriptions.
- Created a Justfile for backend testing setup and execution
@github-actions github-actions bot added enhancement New feature or request backend Related to backend code migration frontend labels Dec 22, 2025
@spwoodcock
Copy link
Member

spwoodcock commented Dec 22, 2025

This is a good improvement I think!
I actually quite like that the user can trigger the processing of all the task areas they flew in one go.

Comments / user story:

  • Create a project in DroneTM.
  • Divide the area into tasks.
  • Multiple operators go out and assign themselves tasks for collecting imagery.
  • Users go to the field, fly perhaps 4-12 task areas each, then return to base.
  • In the evening, they upload their task area imagery (4-12 tasks worth of imagery in one go if that want, via the new uploader approach).
  • They click on a task area
  • [where the workflow diverges]
    • Existing worflow:
      • The user was uploading imagery for a specific task area.
      • This made it obvious to them when to mark the task as 'complete'.
      • Once marked 'complete', they started processing the intermediate products for the task area - START PROCESSING.
    • New workflow
      • The user uploads all of their photos for all tasks.
      • Now they need to them click on each task individually and mark it 'complete'.
      • [bonus] It would be great if we could do an automated check here to determine the task area coverage from the imagery provided. If the user uploaded imagery that covers the entire area, then can we mark it as complete automatically? Perhaps we already do this to determine if the task is ready to process - I forgot - please clarify πŸ™
      • [question 1]: if processing fails, or the pipeline misses a task to process, can the user still trigger the task-level processing on the task page? Using the previous functionality?
      • [question 2]: do we still utilise the task statuses here? Once all imagery is uploaded, the task status should change to 'complete. This could be automated as mentioned above, but as part of the new workflow this step appears to be skipped? Ideally we only trigger processing for task areas that are marked as status='complete'.

[question 3]: this triggers the processing of the intermediate products for task areas. These 'fast orthophotos' are simply used for visual inspection of the task area, to assess the imagery looks good enough (coverage, quality, etc). Once all of the task areas are processed, how do we go about triggering the full 'final orthomosaic' processing for the project?

p.s.

How come every PR has pre-commit issues & merge conflicts? πŸ˜†

Nothing should have changed on dev since your last work, so I think you may accidentally be pulling in commits from other PRs or something?

@spwoodcock
Copy link
Member

spwoodcock commented Dec 22, 2025

Can we have some tests on https://dev.dronetm.org of this workflow too? πŸ™

@spwoodcock
Copy link
Member

spwoodcock commented Dec 22, 2025

Also, for users that expect imagery to be uploaded on the task page, we should probably add a prompt to say 'To upload imagery, please go to the main [project page](link)'

@spwoodcock
Copy link
Member

TODO (copied from Slack):

  • Ensure visual inspection for each tasks in the review, by showing the images on the map.
  • Ensure percentage of coverage is shown and flagged to the user, when the image coverage is less than 100%
  • Remove the upload image area on the Task Details page (and redirect the user to the Project Details page via a helpful prompt).
  • Ensure the task status is not updated to IMAGE_UPLOADED when a set of imagery is uploaded, but instead from the user manually verifying all the imagery is there with 'Mark Fully Flown' button.
  • Fix the 500 error on dev server for project creation (I think it was introduced by latest changed).
  • On image upload, it shouldn't be possible to add duplicates as new images (I think if images are already classified then we don't compare the hash of the newly uploaded images against them? If the user uploaded imagery, they are classified, but not enough coverage for processing, then the user will upload more images - these shouldn't clash / duplicate).
  • Ensure code is cleaned up & that all replaced endpoints are removed (to avoid confusion).

…ask selection and verification

- Added task selection functionality in ImageProcessing component, allowing users to select multiple tasks for processing.
- Implemented a warning for tasks with insufficient images for ODM processing.
- Updated processing start message to reflect the number of selected tasks.
- Introduced a new TaskVerificationModal for verifying tasks on the map, including image previews and deletion options.
- Enhanced ImageReview component to support task verification and display duplicate image status.
- Updated classification service to handle task verification data and image deletion.
- Added new status 'duplicate' for task images to indicate duplicate entries
@FeezyHendrix
Copy link
Collaborator Author

Sam, The above comments has been looked into.

@spwoodcock
Copy link
Member

spwoodcock commented Jan 4, 2026

Thanks! Looking forward to seeing the changes 😁

The branch has merge conflicts though & pre-commit issues not solved.

I'll wait until they are solved before I review πŸ‘

@spwoodcock
Copy link
Member

Installing pre-commit hooks are useful, as they help catch simple issues like this πŸ˜„

F821 Undefined name `log`
   --> src/backend/app/tasks/task_logic.py:592:13
    |
590 |             #
591 |             # Keeping this case to avoid breaking existing API calls, but it now does nothing.
592 |             log.warning(
    |             ^^^
593 |                 f"Deprecated IMAGE_UPLOAD event received for project {project_id}, "
594 |                 f"task {task_id}. This event no longer updates task status."
    |

Found 1 error.

@spwoodcock
Copy link
Member

spwoodcock commented Jan 6, 2026

Also

error: Failed to parse `uv.lock`
  Caused by: Dependency `opencv-python-headless` has missing `source` field but has more than one matching package

was the uv lock updated using uv, or using another tool?

@spwoodcock
Copy link
Member

I fixed the uv lock file issues and pre-commit issue πŸ‘

Could you possibly provide a video of the latest functionality in action before we sign off? πŸ™

@FeezyHendrix
Copy link
Collaborator Author

@spwoodcock Thanks! I would provide the video to you by tomorrow.

@spwoodcock spwoodcock changed the title Feat/resumable uploads Triggering processing workflow after new photo upload method Jan 7, 2026
…sk management

- Update task state to IMAGE_PROCESSING_STARTED when processing begins.
- Modify webhook handling to use system-level updates for task states.
- Introduce internal S3 client for Docker network operations.
- Add functionality to generate presigned URLs for internal S3 access.
- Implement new task state update function for system processes.
- Improve frontend components to reflect processing status and task states.
- Add polling mechanism for task processing status updates.
- Update UI to provide better feedback on task processing and completion.
- Disable old image upload component and guide users to the new workflow.
- Adjust styling and layout for better user experience in task management
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Related to backend code enhancement New feature or request frontend migration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants