AI drone imagery analysis: object detection and counting

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
AI drone imagery analysis: object detection and counting
Complex
~1-2 weeks
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1319
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    927
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1161
  • image_logo-advance_0.webp
    B2B Advance company logo design
    621
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    897

AI Analysis of Drone Aerial Images

Engineers working with aerial images often face a problem: standard computer vision models on orthophoto maps yield mAP 20–30% lower than on ground-level data. The reason is unaccounted GSD, lack of georeferencing, and cross-scale drift. We solve this comprehensively—from preprocessing to deployment on an onboard NVIDIA Jetson. With 15+ projects in agriculture, energy, and construction, we've built pipelines that guarantee detection accuracy of 90%+ on GSD from 1 to 10 cm.

Why Standard YOLO Doesn't Work on Orthophotos

Analysis of UAV data differs fundamentally from ordinary photos: large orthophoto maps (5–20 GPx), non-standard GSD, multispectral and thermal channels, and the need to georeference results in WGS-84 or local CRS. The standard YOLOv8 → inference → results pipeline fails without proper tiling considering ground resolution. Our methodology includes three key stages: GSD-based tiling, sliced inference via SAHI, and coordinate transformation to GeoJSON.

Tiling and Georeferencing—The Key Step

A typical mistake: tiling orthophotos in pixels without accounting for GSD. At GSD 2 cm, a 640×640 pixel tile = 12.8×12.8 m ground area. At GSD 8 cm, the same tile is 51×51 m. A model trained on one scale will deliver mAP 15–25% lower on another.

import rasterio
from rasterio.windows import Window
from pathlib import Path

def tile_ortho_by_ground_size(
    ortho_path: str,
    tile_ground_m: float = 50.0,
    overlap_ground_m: float = 10.0
) -> list[dict]:
    """
    Tiling orthophoto by ground tile size.
    Guarantees constant scale regardless of GSD.
    """
    with rasterio.open(ortho_path) as src:
        gsd = abs(src.transform.a)          # meters/pixel
        tile_px = int(tile_ground_m / gsd)
        overlap_px = int(overlap_ground_m / gsd)
        stride = tile_px - overlap_px

        tiles = []
        for row in range(0, src.height - tile_px + 1, stride):
            for col in range(0, src.width - tile_px + 1, stride):
                win = Window(col, row, tile_px, tile_px)
                data = src.read(window=win)          # (C, H, W)
                bounds = rasterio.windows.bounds(win, src.transform)
                tiles.append({
                    'data': data,
                    'bounds': bounds,
                    'gsd_m': gsd,
                    'window': win
                })
    return tiles

Overlap overlap_ground_m=10 is critical: objects on tile edges are detected in both, then NMS by IoU removes duplicates. Without overlap, ~12% of objects at seams are lost. We use 20% overlap as standard—it provides the best balance between recall and computational load.

SAHI for Small Objects—Comparison with Naive Approach

When detecting people or cars on orthophotos with GSD 3–5 cm, the object occupies 30–80 pixels—much smaller than the receptive field of YOLO optimized for 640px. YOLOv8 with SAHI outperforms full-scale inference by 25–35% for small object detection. SAHI solves this by slicing with overlap and NMS across all predictions:

from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction

model = AutoDetectionModel.from_pretrained(
    model_type='yolov8',
    model_path='drone_people_v2.pt',
    confidence_threshold=0.35,
    device='cuda:0'
)

result = get_sliced_prediction(
    image=tile_array,           # np.ndarray (H, W, 3)
    detection_model=model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2
)
# result.object_prediction_list → coordinates in tile pixels

On a construction site people counting dataset (5000 annotated images, GSD 4 cm): without SAHI [email protected] = 0.61, with SAHI—0.84. The difference is fundamental.

How We Process Multispectral and Thermal Images?

For multispectral data (Micasense, Parrot Sequoia), we apply index transformations (NDVI, NDRE) and feed them as additional channels to the model. The thermal channel (FLIR) requires a separate pipeline:

import numpy as np

def detect_pv_hotspots(
    thermal_kelvin: np.ndarray,    # (H, W), values in 0.01K
    panel_mask: np.ndarray,        # binary mask of panels
    delta_threshold: float = 10.0  # °C above panel median
) -> list:
    """
    Hotspot detection on solar panels.
    IEC 62446-3: defect when ΔT > 10°C from reference.
    """
    temp_celsius = thermal_kelvin * 0.01 - 273.15
    panel_temps = temp_celsius[panel_mask > 0]
    reference_temp = float(np.median(panel_temps))

    hot_mask = (
        (temp_celsius > reference_temp + delta_threshold) &
        (panel_mask > 0)
    ).astype(np.uint8)

    import cv2
    contours, _ = cv2.findContours(
        hot_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
    hotspots = []
    for c in contours:
        x, y, w, h = cv2.boundingRect(c)
        roi = temp_celsius[y:y+h, x:x+w]
        delta = float(roi.max() - reference_temp)
        hotspots.append({
            'bbox': [x, y, x+w, y+h],
            'max_temp_c': round(float(roi.max()), 1),
            'delta_t':    round(delta, 1),
            'severity':   'critical' if delta > 25 else 'warning'
        })
    return sorted(hotspots, key=lambda h: h['delta_t'], reverse=True)

On a real solar farm inspection project (142 panels, 3 flights), the system identified 17 defective panels with ΔT > 15°C that manual visual inspection missed. ROI paid off in one season. We guarantee recall not lower than 95% for hot-spot detection.

Coordinate Transformation and GeoJSON Output

Analysis results must be in geographic coordinates—otherwise they're just pictures, not integrable into GIS systems.

import pyproj
from shapely.geometry import box, mapping
import json

def detections_to_geojson(
    detections: list,
    tile_bounds: tuple,           # (left, bottom, right, top) in CRS
    tile_px_size: tuple,          # (width, height) in pixels
    src_crs: str = 'EPSG:32637'   # UTM zone for project
) -> dict:
    transformer = pyproj.Transformer.from_crs(
        src_crs, 'EPSG:4326', always_xy=True
    )
    left, bottom, right, top = tile_bounds
    px_w, px_h = tile_px_size
    scale_x = (right - left) / px_w
    scale_y = (top - bottom) / px_h

    features = []
    for det in detections:
        x1, y1, x2, y2 = det['bbox']
        # Pixels to projection coordinates
        geo_left   = left + x1 * scale_x
        geo_right  = left + x2 * scale_x
        geo_top    = top  - y1 * scale_y
        geo_bottom = top  - y2 * scale_y
        # Projection to WGS-84
        lon1, lat1 = transformer.transform(geo_left, geo_top)
        lon2, lat2 = transformer.transform(geo_right, geo_bottom)

        features.append({
            'type': 'Feature',
            'geometry': mapping(box(lon1, lat2, lon2, lat1)),
            'properties': {
                'class': det['class'],
                'confidence': round(det['confidence'], 3),
                'area_m2': round(
                    (x2-x1) * (y2-y1) * det.get('gsd_m', 0.05)**2, 2
                )
            }
        })

    return {'type': 'FeatureCollection', 'features': features}

This module is included in every project—it generates GeoJSON files ready for QGIS or ArcGIS.

Metrics by Task Type

Task GSD Model Typical [email protected]
Tree counting 3–5 cm YOLOv8m + SAHI 0.88–0.93
People detection on construction site 4–6 cm YOLOv8l + SAHI 0.81–0.87
Power line defects 1–2 cm RT-DETR-L 0.79–0.85
Solar farm inspection (thermal) 5–10 cm threshold + SAM 95%+ recall
Construction progress 5–10 cm SegFormer-B4 IoU 0.84–0.91

What's Included in the Work

We provide:

  • Pipeline documentation (architecture, deployment instructions).
  • Trained model with MLflow logs and validation metrics.
  • Source code for all modules (Rasterio, SAHI, transformation, web interface).
  • Integration with GIS systems via GeoJSON / Shapefile.
  • Training of your team (2–3 days remote or on-site).
  • Model warranty for 6 months (adjustments for data drift).

Timelines

Task Duration
One-class detector (ready data) 3–5 weeks
Full inspection system + GIS integration 8–14 weeks
Multi-sensor platform RGB + thermal 14–22 weeks

Order AI system development for your UAVs—we'll evaluate the project in 2 business days. Contact us to discuss your task and provide sample images.