Skip to content

Commit

Permalink
Get a list of images that contains a GCP Point from a whole Project (#…
Browse files Browse the repository at this point in the history
…396)

* fix: calculate bbox for the drone image

* fix: calculate image footprints

* feat: get a list of images that contains a point
  • Loading branch information
nrjadkry authored Dec 12, 2024
1 parent a42c5d4 commit 4f30f16
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 8 deletions.
71 changes: 66 additions & 5 deletions src/backend/app/gcp/gcp_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from app.waypoints import waypoint_schemas
from app.config import settings
from pyproj import Transformer
from loguru import logger as log


async def calculate_bounding_box(
Expand Down Expand Up @@ -76,9 +77,13 @@ def fetch_json_from_presigned_url(url: str):
"""
Fetch a JSON file from an AWS presigned URL.
"""
response = requests.get(url)
response.raise_for_status() # Raise an exception for HTTP errors
return response.json()
try:
response = requests.get(url)
response.raise_for_status() # Raise an exception for HTTP errors
return response.json()
except Exception as e:
log.warning(f"Error fetching JSON file: {e}")
return None


async def find_matching_images_that_contains_point(bounding_boxes, gps_coordinate):
Expand Down Expand Up @@ -115,7 +120,7 @@ async def calculate_bbox_from_images_file(

# Calculate bounding boxes for each image
bounding_boxes = {}
for image in images:
for image in images or []:
filename = image["filename"]
lat = image["latitude"]
lon = image["longitude"]
Expand Down Expand Up @@ -274,7 +279,63 @@ def find_images_with_coordinate(
return matching_images


async def process_images_for_point(
async def find_images_in_a_project_for_point(
project_id: uuid.UUID,
task_id_list: List[uuid.UUID],
point: waypoint_schemas.PointField,
fov_degree: float,
altitude: float,
) -> List[str]:
"""
Process images to find those containing a specific point and return their pre-signed URLs.
Args:
project_id (uuid.UUID): The ID of the project.
task_id (uuid.UUID): The ID of the task.
point (waypoint_schemas.PointField): The point to check.
Returns:
List[str]: A list of pre-signed URLs for matching images.
"""

# Extract the longitude and latitude of the point
point_tuple = (point.longitude, point.latitude)

# Find the matching images from each task
images_list = []
for task_id in task_id_list:
task_id_str = str(task_id[0])
s3_images_json_path_for_task = (
f"dtm-data/projects/{project_id}/{task_id_str}/images.json"
)
s3_images_json_url = get_presigned_url(
settings.S3_BUCKET_NAME, s3_images_json_path_for_task
)

# Fetch bounding boxes from the `images.json` file
bbox_list = await calculate_bbox_from_images_file(
s3_images_json_url, fov_degree, altitude
)

# Find images whose bounding boxes contain the given point
matching_images = await find_matching_images_that_contains_point(
bbox_list, point_tuple
)
images_list += [f"{task_id_str}/images/{image}" for image in matching_images]

# Generate pre-signed URLs for the matching images
presigned_urls = [
get_presigned_url(
settings.S3_BUCKET_NAME,
f"dtm-data/projects/{project_id}/{image}",
)
for image in images_list
]

return presigned_urls


async def find_images_in_a_task_for_point(
project_id: uuid.UUID,
task_id: uuid.UUID,
point: waypoint_schemas.PointField,
Expand Down
29 changes: 26 additions & 3 deletions src/backend/app/gcp/gcp_routes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import uuid
from app.config import settings
from fastapi import APIRouter
from fastapi import APIRouter, Depends
from app.waypoints import waypoint_schemas
from app.gcp import gcp_crud
from typing import List
from psycopg import Connection
from app.db import database
from typing import Annotated
from app.tasks.task_logic import list_task_id_for_project


router = APIRouter(
Expand All @@ -13,7 +17,7 @@
)


@router.post("/find-images")
@router.post("/find-images/")
async def find_images(
project_id: uuid.UUID,
task_id: uuid.UUID,
Expand All @@ -24,6 +28,25 @@ async def find_images(
fov_degree = 82.1 # For DJI Mini 4 Pro
altitude = 100 # TODO: Get this from db

return await gcp_crud.process_images_for_point(
return await gcp_crud.find_images_in_a_task_for_point(
project_id, task_id, point, fov_degree, altitude
)


@router.post("/find-project-images/")
async def find_images_for_a_project(
project_id: uuid.UUID,
db: Annotated[Connection, Depends(database.get_db)],
point: waypoint_schemas.PointField = None,
) -> List[str]:
"""Find images that contain a specified point in a project."""

fov_degree = 82.1 # For DJI Mini 4 Pro
altitude = 100 # TODO: Get this from db

# Get all task IDs for the project from database
task_id_list = await list_task_id_for_project(db, project_id)

return await gcp_crud.find_images_in_a_project_for_point(
project_id, task_id_list, point, fov_degree, altitude
)
11 changes: 11 additions & 0 deletions src/backend/app/tasks/task_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
from app.config import settings


async def list_task_id_for_project(db: Connection, project_id: uuid.UUID):
query = """
SELECT id
FROM tasks
WHERE project_id = %(project_id)s;
"""
async with db.cursor() as cur:
await cur.execute(query, {"project_id": str(project_id)})
return await cur.fetchall()


async def get_task_stats(db: Connection, user_data: AuthUser):
try:
async with db.cursor(row_factory=class_row(TaskStats)) as cur:
Expand Down

0 comments on commit 4f30f16

Please sign in to comment.