Friday, October 30, 2026

 DVSA-API Telemetry and Observability: Bringing AI-Agent Workloads to Enterprise-Grade Operations

Modern AI systems are no longer single-model applications. They are distributed pipelines composed of ingestion services, search indexes, vector stores, agent frameworks, vision models, orchestration layers, and user-facing APIs. As these systems grow, observability becomes as important as accuracy. A production platform must answer three questions at all times: What happened? Why did it happen? Can we reproduce it?

DVSA-API approaches these challenges using a layered observability model that combines pipeline traceability, structured telemetry, fault isolation, retrieval transparency, and experiment tracking. Although designed for drone-video intelligence workloads, its architecture aligns closely with established industry patterns found in Databricks Delta Lake medallion pipelines, Kubernetes Telegraf-Prometheus monitoring stacks, and Azure Monitor-based cloud observability solutions.

Observability Starts with the Data Pipeline

At the foundation of DVSA is a structured video-processing pipeline. Rather than treating AI inference as an opaque black box, the platform preserves the lineage of data as it flows from raw video frames through object tracking, feature extraction, retrieval, and inference.

The Databricks integration explicitly adopts a medallion-style progression:

Raw_frames → tracks → features → inference_results

This mirrors Databricks' Bronze-Silver-Gold tiering. Raw observations enter the system as extracted frames. Tracking and enrichment stages create structured representations. Feature generation adds analytical context. Finally, inference outputs are written into stable Delta tables for consumption by downstream applications and analytics workloads.

This separation provides an audit trail for every prediction. Engineers can trace any answer back through the intermediate stages that produced it, identify where an error entered the pipeline, and replay individual stages without reprocessing the entire workload.

Delta Lake as the System of Record

The inference_results table acts as the canonical record for AI outcomes. Every result is correlated with source identifiers such as video_id and frame_index. This creates deterministic links between source imagery and downstream conclusions.

From an observability perspective, this serves the same role that transaction logs serve in data engineering systems. Every prediction can be associated with:

• The originating video

• The specific frame

• The model version

• The generated result

• Detection counts

• Error status

Because failures are stored per row rather than terminating the entire batch, operators gain visibility into partial failures without losing successful results. This design is particularly valuable for large-scale video workloads where retrying an entire job for a handful of bad frames would be operationally expensive.

MLflow as Experiment Telemetry

DVSA records inference execution metadata into MLflow. Parameters such as model selection, batch size, output location, processed row counts, batch counts, detection statistics, and error metrics are persisted with each run.

This makes the platform resemble modern MLOps deployments in which model execution is fully observable and reproducible.

The result is operational telemetry at the machine-learning layer:

• Which model produced a result

• How many detections occurred

• How many errors were encountered

• Which configuration was used

• Which artifacts were generated

For data scientists, MLflow becomes the equivalent of application performance monitoring for AI workloads.

AI Agent Observability Through Explicit Orchestration

One of the most distinctive features of DVSA is that chat responses are not generated by a single AI model. Instead, a coordinated team of agents participates in every retrieval session.

The platform orchestrates:

1. A knowledge-search agent

2. A function-calling agent

3. A tool-enabled analysis agent

4. A Qwen vision agent

5. A consolidator agent

Each agent contributes a clearly labeled output section that is later merged into a final narrative answer.

This is significant from an observability standpoint because agent reasoning becomes inspectable. Rather than presenting only the final answer, the architecture preserves the intermediate contributions that produced that answer.

The design resembles distributed tracing in microservices. Each agent becomes a logical span in a larger workflow, and the final response becomes the assembled trace.

Bounded Execution and Reliability Controls

Production observability requires more than logging. It requires protection against runaway processes.

DVSA introduces several safeguards:

• Shared turn-level execution budgets

• Per-agent runtime limits

• Per-tool-call timeouts

• Maximum tool-round counts

• Repeated-failure detection

• Graceful cancellation

A single chat request receives a total execution budget, and participating agents operate within that shared window. If a budget is exhausted, lower-priority components are skipped rather than causing request failure.

This behavior is remarkably similar to timeout propagation in distributed cloud systems, where downstream services inherit the remaining latency budget of the parent operation.

Operationally, this prevents AI workloads from becoming unpredictable under load.

Fault Isolation and Partial Failure Handling

A core observability principle is that one failing component should not blind the entire system.

DVSA embraces this principle aggressively.

If a retrieval agent fails, execution continues.

If a tool times out, the timeout is recorded and execution proceeds.

If a vision model is unavailable, its contribution is omitted while the remaining agents continue working.

If search index provisioning encounters issues, warnings are emitted without terminating the request path.

This resembles resilient microservice architectures where degraded operation is preferred over total service failure.

The outcome is high service availability combined with visibility into what failed and why.

Alignment with Kubernetes Telegraf and Prometheus Architectures

The philosophy of DVSA closely matches Kubernetes observability stacks built around Telegraf and Prometheus.

In a traditional Kubernetes environment:

• Workloads emit metrics.

• Prometheus scrapes and stores them.

• Grafana visualizes them.

• Alerting systems react to anomalies.

DVSA applies the same mindset to AI workflows.

Instead of CPU metrics and container status, the platform surfaces:

• Agent execution outcomes

• Tool-call failures

• Timeout conditions

• Retrieval latency

• Batch-processing metrics

• Detection counts

• Error statistics

• Run-level metadata

The platform treats inference pipelines as observable systems rather than opaque model invocations.

Conceptually, MLflow metrics, Delta tables, structured logs, and agent outputs act as AI-native counterparts to Prometheus time-series telemetry.

Alignment with Azure Monitor Architectures

DVSA's Azure implementation also mirrors Azure Monitor design principles.

Azure Monitor is built on three pillars:

• Metrics

• Logs

• Distributed traces

DVSA naturally maps onto these concepts.

Metrics are represented through MLflow telemetry and batch statistics.

Logs are produced through structured agent execution records, timeout notifications, error reporting, Search interactions, and deployment diagnostics.

Traces emerge through the agent orchestration pipeline, where a single user request passes through retrieval, reasoning, tool execution, vision analysis, and synthesis stages.

The architecture's use of Azure AI Search, Azure AI Vision, Azure AI Foundry Agents, Azure OpenAI integrations, and per-account indexes provides natural boundaries for correlation and end-to-end diagnostics.

A future integration with Azure Monitor and Application Insights would require relatively little architectural change because the necessary correlation points already exist.

Retrieval Traceability and Explainability

Another important observability capability is retrieval transparency.

DVSA specifically records:

• Account scope

• Video scope

• Curated frame sets

• Search-index targeting

• Agent participation

• Tool invocation results

Curated frame collections are passed to participating agents rather than allowing unrestricted access to all imagery. This makes the evidence used during reasoning inspectable and reproducible.

From a governance perspective, this resembles the traceability requirements increasingly demanded of enterprise retrieval-augmented generation systems.

Infrastructure as Code and Operational Governance

DVSA extends observability into deployment itself.

Agents, search indexes, retrieval schemas, and configurations are managed as code and deployed using automated provisioning workflows.

Infrastructure changes can therefore be audited, reproduced, versioned, and validated.

This aligns with modern platform-engineering practices where operational observability is inseparable from deployment governance.

Conclusion

DVSA-API demonstrates an evolution from simple AI inference toward fully observable AI systems. Its architecture combines Delta-style data lineage, MLflow experiment tracking, fault-tolerant agent orchestration, structured retrieval, and deployment-as-code into a unified operating model.

The platform aligns with three mature patterns:

• Databricks Medallion Architecture through staged data refinement and lineage preservation.

• Kubernetes Telegraf-Prometheus ecosystems through systematic collection of operational metrics and failure signals.

• Azure Monitor architectures through correlation of metrics, logs, and distributed execution paths.

This AI platform can explain how an answer was produced, what evidence was used, which components participated, how long they took, and what happened when something went wrong. That capability is the essence of modern observability.



Thursday, October 29, 2026

 

A comparison of file-system and drone fleet software levels.

A software centric approach is required for the purpose of relaying commands and treating the drone formation as a single entity.  A multi-layer approach is helpful to articulate the logical high-level commands to actual unit movements. This is the same approach used for file systems where disk access is almost hidden from the user level file access. The management and access must be separated. It is helpful to organize this in multiple layers where the lower layers can be switched out with those applicable to specify types of drone units with restricted particle movements while the higher-level layers remain in place. The higher-level layers also describe manageability capabilities for drone unit and group such that they can be accessed interactively or programmatically. The following article compares the file-system organization levels with the drone fleet management software levels.

File-System organizational level

Drone Fleet organizational levels

Application Programs

-          These are the consumers of the file-system organization and access all its interfaces such as for create, update, delete of directories and files

Application Programs

-          These are the consumers of the fleet management organization and use all its interfaces such as for co-ordination of group and individual drones.

Logical File system

-          This manages metadata information about a file that helps with its bookkeeping as well as the file control block which records owner, size, permissions and locations

Logical Fleet system

-          This manages metadata information about a drone that helps with its bookkeeping as well as the capabilities of a drone such as in terms of its flexibility to perform 360-degree movement.

File Organizational module

-           This has information about the files, the location of the files and the logical and physical blocks. While logical blocks could be contiguous, the physical blocks may be scattered with free space between them.

Fleet organizational module

-          This has information about the drones, the hierarchical addressability of the drone and the logical and physical formations. The formations can vary independent of the fleet so that the same fleet can have different formations. One formation can transform to another with group commands.

Basic File system

-          This comprises of the general commands to the device drivers to read and write physical blocks on the disk. Blocks provide a convenient abstraction from user organizational primitives such as folder and files as well as a system defined data structure that can record information about the physical layout on disks

Basic fleet system

-          This comprises of the general command to state reconciliation and operations on the fleet which translate to physical commands to drones. Separation of drone commands in terms of system defined data structures and methods is beneficial to allowing a variety of drones as the individual units of the fleet even though the fleet may be homogenous.

I/O control

-          Device drivers act as an interface between the devices and the higher-level layers. With a block number and low-level hardware specific instruction, device-drivers facilitate compliance to a common programming interface.

I/O control

-          Drivers dedicated to the drone for its make and model such that it behaves consistently with the expectations of higher-level layers allow them to be switched one for another.

Devices

-          The ultimate store for the bits and bytes of the user-defined files and folders are the disks and they could comprise their own stack so long as the devices behave as a permanent store

Drones

-          The ultimate low-level for a fleet management comprises just the drones that can come with software stack dedicated to handling common commands for its movements.

 

The scheduling and control are handled at the fleet level as well as the drone level by modules at the corresponding levels. The generic displacement commands to a drone can be articulated in a sequence of motions to achieve that displacement by the drone level scheduling and control unit when it has multiple moving parts – each of which must be controlled with the precise positioning and orientation.

While autonomous decisions are made by individual drones, they must remain within the overall trajectory tolerance space for the entire fleet. This can be achieved with the popular neural net for softmax classification. The goodness of fit for a cluster or sum of squares of errors of F-score are other alternative measures.

#code

using System.Collections.Generic;

 

namespace SquadronFormation.Abstractions

{

    /// <summary>

    /// Represents a Formation

    /// </summary>

    public abstract class FormationBase : DroneFormationBase

    {

        /// <summary>

        /// Enumerates all units in the formation.

        /// </summary>

        /// <returns>Collection of Drones and Formations</returns>

        public abstract IEnumerable<DroneFormationBase> EnumerateDroneFormations();

 

        /// <summary>

        /// Returns an instance of <see cref="FormationBase" /> that represents a formation within the overall

        /// </summary>

        /// <param name="path">The Formation reference</param>

        /// <returns>Instance of <see cref="FormationBase" /> even if formation does not exist</returns>

        public abstract FormationBase? GetFormation(string path);

 

        /// <summary>

        /// Returns an instance of <see cref="DroneBase" /> that represents an atomic drone in the formation

        /// </summary>

        /// <param name="path">The drone qualifier</param>

        /// <returns>Instance of <see cref="DroneBase" /> even if drone does not exist</returns>

        public abstract DroneBase? GetDrone(string path);

    }

}

 

Wednesday, October 28, 2026

 Problem statement: Determine the maximum rectangle enclosed in a bar chart where the bars appear in a streaming manner.

Solution:

public static int getMaxRectangleStreaming(List<Integer> A) {

        int maxArea = Integer.MIN_VALUE;

        int maxHeight = Integer.MIN_VALUE;

        List<Integer> heights = new ArrayList<>();

        // parallel sums of unit-areas of bounding boxes with top-left at incremental heights of the current bar in a barchart

        List<Integer> areas = new ArrayList<>();

        int prev = 0;

        for (int i = 0; i < A.size(); i++) {

            if (A.get(i) > maxHeight) {

                maxHeight = A.get(i);

            }

            if (prev < A.get(i)) {

                for (int j = 0; j < A.get(i); j++) {

                    if (heights.size() < j+1) heights.add(0);

                    if (areas.size() < j+1) areas.add(0);

                    heights.set(j, (j+1) * 1);

                    if ( j < areas.size()) {

                        int newArea = areas.get(j) + (j + 1) * 1;

                        areas.set(j, newArea);

                        if (newArea > maxArea) {

                            maxArea = newArea;

                        }

                    } else {

                        areas.set(j, (j+1) * 1);

                    }

                }

            } else {

                for (int j = 0; j < A.get(i); j++) {

                    heights.set(j, (j+1) *1);

                    if ( j < areas.size()) {

                        int newArea = areas.get(j) + (j + 1) * 1;

                        areas.set(j, newArea);

                        if (newArea > maxArea) {

                            maxArea = newArea;

                        }

                    } else {

                        areas.set(j, (j+1) * 1);

                    }

                }

                for (int j = A.get(i); j < prev; j++){

                    heights.set(j, 0);

                    if (areas.size() > j && areas.get(j) > maxArea) {

                        maxArea = areas.get(j);

                    }

                    areas.set(j, 0);

                }

            }

            prev = A.get(i);

            System.out.println("heights:" + print(heights));

            System.out.println("areas:" + print(areas));

        }

        return maxArea;

    }

    public static String print(List<Integer> A){

        StringBuilder sb = new StringBuilder();

        for (Integer a : A) {

            sb.append(a + " ");

        }

        return sb.toString();

    };

}

 

//Output:

heights:1 2 3 4 

areas:1 2 3 4 

heights:1 2 3 4 5 6 

areas:2 4 6 8 5 6 

heights:1 2 0 0 0 0 

areas:3 6 0 0 0 0 

heights:1 2 3 4 0 0 

areas:4 8 3 4 0 0 

heights:1 2 3 4 5 6 7 8 9 10 11 12 

areas:5 10 6 8 5 6 7 8 9 10 11 12 

heights:1 2 3 4 5 6 7 0 0 0 0 0 

areas:6 12 9 12 10 12 14 0 0 0 0 0 

heights:1 2 3 4 0 0 0 0 0 0 0 0 

areas:7 14 12 16 0 0 0 0 0 0 0 0 

heights:1 2 0 0 0 0 0 0 0 0 0 0 

areas:8 16 0 0 0 0 0 0 0 0 0 0 

heights:1 2 0 0 0 0 0 0 0 0 0 0 

areas:9 18 0 0 0 0 0 0 0 0 0 0 

heights:1 2 0 0 0 0 0 0 0 0 0 0 

areas:10 20 0 0 0 0 0 0 0 0 0 0 

20


Tuesday, October 27, 2026

 Software-defined Infrastructure for Drone Analytics

With the widespread availability of AI and frontier models, more services in the UAV industry will gain acceptance and adoption. While the current drone applications are either boutique or in favor of delivery-fleet operators, it is becoming a fast-leveling field for technologists from diverse geographies and budgets. This predicts a fast-growing data collection of aerial drone images and videos and will require the same diligence in infrastructure planning, purview, auditing, and forensics as with any other data. Its access and interpretation will eventually point to operators, querying solutions, telemetry, and workflow automations that will become highly reusable across a wide range of players. 

Conventional data storage has benefited text but not images and videos even though fast-growing visual language models and agentic framework are making query analysis more natural and deep. Semantics, spatial and temporal interpretation of videos has not become as mainstream as text even with the narrow scope of nadir drone videos. Many businesses will incubate and re-invent these stacks comprising data, operators, language, workflows, visualizations, and analysis-breadth-and-depth. If the popularity of visual search on search portals versus chat-based searches is any precedence, the ratio is likely to stay small for a while longer. Yet the increased attention to drones and their autonomy is likely to increase the data tier so significantly that businesses will need to grapple with a storage-analytics-and-management platform sooner rather than later. And the long tail of data variety will continue to challenge the consolidation of these platforms both in terms of models/agents/capabilities and their storage, access, and retrieval.

It is in this emerging market of drones that software learning is more pertinent than ever. First, the data will continue to grow. Even if vision-language-models remain secondary to natural language models, more businesses are going to deploy stacks and services to manage the data, access, querying, and reporting. Third, cloud providers cannot dominate this sector alone just like they could not create a universal standard for other industries such as healthcare. Reusability for this primitive but consistent urban drone images and videos is going to be so high that there will be some players seizing the opportunity to bridge businesses and cloud providers. Further, they cannot just be solution-integrators and must become product-or-service providers. Governance and regulation for transportation industry is just waking up to the idea of manned and unmanned vehicles and footage of flights are going to become as relevant as the Blackbox for commercial planes. The low-altitude nature of drones is a physics factor forcing images and video captures. Software capabilities and conformance on this type of asset are going to be as popular as booking flights. Lastly, service management in terms of ticketing, incident, and change management as well as rigor to manage and present these are going to be of interest at various levels and scopes. 

In conclusion, a top-down planning of aerial drone image/video management platform with parallels to various document management platforms is going to become popular.


Monday, October 26, 2026

 Using VLMs requires correct model hyperparameters

For example

(vllm-env) PS C:\users\ravib\venv\Qwen> ollama pull qwen2.5vl:7b

pulling manifest

pulling a99b7f834d75: 100% ▕█████████████████████████████████████████████████████████ ▏ 6.0 GB/6.0 GB 62 MB/s 0s

verifying sha256 digest

writing manifest

success

(vllm-env) PS C:\users\ravib\venv\Qwen> ollama run qwen2.5vl:7b


>>> How many red cars are in the image at "C:\Users\ravib\Downloads\frames\frames\frame11.jpg"

Added image 'C:\Users\ravib\Downloads\frames\frames\frame11.jpg'

There are two red cars visible in the image. One is parked on the left side of the street, and the other is parked

on the right side of the street.


>>> /bye

This is the correct answer. 

Now with a python script:

import requests

import json

import base64

import os


url = "http://localhost:8848/v1/chat/completions"


# 1. Path to your local image

image_path = r"C:\Users\ravib\Downloads\frames\frames\frame11.jpg"


# 2. Open the image file and encode it to Base64

if os.path.exists(image_path):

    with open(image_path, "rb") as image_file:

        base64_image = base64.b64encode(image_file.read()).decode('utf-8')

else:

    print(f"Error: File not found at {image_path}")

    exit()


# 3. Construct the payload with the Base64 data URI format

payload = {

    "model": "qwen2.5vl:7b",

    "messages": [

        {

            "role": "user",

            "content": [

                {

                    "type": "text", 

                    "text": "How many red cars are in the image?"

                },

                {

                    "type": "image_url",

                    "image_url": {

                        "url": f"data:image/jpeg;base64,{base64_image}"

                    }

                }

            ]

        }

    ]

}


headers = {

    "Content-Type": "application/json"

}


response = requests.post(url, headers=headers, data=json.dumps(payload))


print("Status:", response.status_code)

print("Response:")

print(response.text)


## Response

# Status: 200

# Response:

#{"id":"chatcmpl-429","object":"chat.completion","created":1788656816,"model":"qwen2.5vl:7b","system_fingerprint":"fp_ollama","choices":[{"index":0,"message":{"role":"assistant","content":"There is one red car on the street in the image."},"finish_reason":"stop"}],"usage":{"prompt_tokens":1226,"prompt_tokens_details":{"cached_tokens":22},"completion_tokens":13,"total_tokens":1239}}


This is the incorrect answer.


Now, the fix that works:

import base64

from PIL import Image

import io

import ollama


# 1. Path to your image file

image_path = r"C:\Users\ravib\Downloads\frames\frames\frame11.jpg"


# 2. Open image with Pillow to ensure it passes cleanly as standard bytes

with Image.open(image_path) as img:

    if img.mode in ("RGBA", "P"):

        img = img.convert("RGB")

    

    # Optional: Keep resolution native but ensure metadata handles boundaries well

    buffer = io.BytesIO()

    img.save(buffer, format="JPEG", quality=100)

    image_bytes = buffer.getvalue()


# 3. Direct programmatic call to the Ollama server on your port

# (Point the client explicitly to your active instance)

client = ollama.Client(host="http://localhost:8848")


response = client.chat(

    model="qwen2.5vl:7b",

    messages=[

        {

            "role": "user",

            "content": "Look closely at the entire scene, including any cars parked down the sides of the street. How many red cars are visible in this image?",

            "images": [image_bytes] # Pass raw image bytes, avoiding Base64 URI scaling issues

        }

    ],

    options={

        "temperature": 0.0, # Eliminates random sampling path bias

        "num_predict": 100, # Gives the model breathing room to elaborate

        "num_ctx": 8192 # Expand context window to avoid aggressive clipping

    }

)


# Print the final result cleanly

print("Response:")

print(response['message']['content'])


Response:

In the image, there are two red cars visible. One is parked on the left side of the street near the tall building, and the other is parked further down the street on the right side.

Latest models of Qwen recommend:

• Thinking Mode: temperature=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0

• Instruct (or non-thinking) mode: temperature=0.7, top_p=0.80, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0



Sunday, October 25, 2026

 Drawing drone trajectory on an orthomosiac

We perform a trajectory estimation followed by projection into the mosaic’s coordinate system. From the previous implementation to generate an orthomosaic, one can derive an approximate path from the transformations it already computes—without adding DROID-SLAM or another reconstruction engine. Some of the criteria that this drawing must meet is that different routes even in the same drone tour over the same survey area must result in two shapes. For example, if the drone follows the same ground track twice, the two paths should overlap. If the actual routes differ or when they are deliberately displaced, the two paths are concentric. The follows steps explain the implementation followed by illustration of results.

1. Re-use the transformations already in the generate_orthomosaic script

The script already computes:

 A cumulative transformation for each sampled frame.

 A canvas translation that moves everything into positive image coordinates.

 The final mosaic using those same transformations.

So, a compatible method is:

 Take the center of each video frame.

 Transform that point into the mosaic canvas.

 Preserve chronological order.

 Draw a solid black polyline through those transformed points.

For frame i:



Here, Α_i is the cumulative frame-to-reference transformation, and Τ_canvas is the translation returned by compute_canvas_size(). These are the same coordinate mappings your code uses to warp the images. OpenCV supports applying those mappings to points as well as images.

For a stable, nearly nadir camera, this gives an approximate trace of the camera’s ground-view center. It should be labeled an image-derived ground-track estimate. Camera tilt, an off-center principal point, parallax, and alignment errors can move the trace away from the true vertically projected drone position.

Where to integrate it

In the stitch_frames() function, we draw the trajectory after this call:

mosaic = build_mosaic(

    frame_paths,

    transforms,

    width,

    height,

    translation

)

Drawing afterward prevents later frame warps from covering the black line. Our existing variables already provide the required coordinate mappings.

2. Fix rejected-frame handling before trusting the path

The current tracking code has one issue: when matching fails, it appends the previous cumulative transformation but advances prev_gray to the rejected frame. That can misplace the next successfully matched frame because the stored global transform and the matching reference no longer correspond to the same image. This is now changed to:

 Keeping the last successfully registered frame as the matching reference.

 Marking rejected frames as having no valid position.

 Matching subsequent frames against that last accepted reference, with appropriate quality checks.

 Breaking the displayed line across unresolved tracking gaps rather than drawing a misleadinging connection.

Otherwise, an attractive black path could conceal tracking failures already present in the mosaic.

3. Detecting two passes requires revisit detection

Drawing the path and identifying separate survey passes are different tasks.

To detect that the drone has returned to previously observed ground, we use:

 Nonadjacent frame matching to find candidate revisits.

 Geometric verification to reject look-alike roofs or roads.

 Loop-closure constraints connecting the revisited frames.

 Global optimization of frame transformations.

Loop closure uses revisited locations to reduce accumulated trajectory drift and improve map consistency. Simply chaining consecutive transformations provides no equivalent global correction.

This matters for our desired visualization: two separated loops could otherwise be tracking drift rather than two genuinely different routes.

Both the mosaic and the overlaid path should use optimized transformations. Correcting only the line would make it inconsistent with the imagery.

4. How to show repeated loops

Situation Appropriate display

Two genuinely different, nested routes Two nested black loops at their estimated positions

Same route flown twice Overlapping black lines

Same route, different altitude Generally overlapping ground-track lines; altitude needs another encoding

Both coincident passes visible Separate per-pass images, or individually labeled display offsets

If we deliberately offset coincident passes to show two concentric shapes, we must keep the original trajectory unchanged and label the result “offset for visibility.” It should not be presented as evidence that the drone flew two spatially separated routes.

A solid black line alone cannot preserve visit count at identical locations. Store the underlying samples with fields such as:

timestamp, frame_index, mosaic_x, mosaic_y, tracking_valid, pass_id

Final solution

What the replacement changes

The script:

 Transforms each accepted frame’s center using the same cumulative transformation and canvas translation used to place its imagery.

 Draws the black line after all mosaic images have been placed.

 Keeps the last successfully registered frame as the matching reference when a subsequent frame fails.

 Excludes rejected frames instead of assigning them fabricated repeated positions.

 Breaks the path across failed-tracking intervals rather than connecting across unknown positions.

 Exports coordinates, timestamps when available, registration status, inlier counts, and rejection reasons to CSV.



Saturday, October 24, 2026

 

Using VLMs requires correct model hyperparameters

For example

(vllm-env) PS C:\users\ravib\venv\Qwen> ollama pull qwen2.5vl:7b

pulling manifest

pulling a99b7f834d75: 100% ▕█████████████████████████████████████████████████████████ ▏ 6.0 GB/6.0 GB   62 MB/s      0s

verifying sha256 digest

writing manifest

success

(vllm-env) PS C:\users\ravib\venv\Qwen> ollama run qwen2.5vl:7b

 

>>> How many red cars are in the image at "C:\Users\ravib\Downloads\frames\frames\frame11.jpg"

Added image 'C:\Users\ravib\Downloads\frames\frames\frame11.jpg'

There are two red cars visible in the image. One is parked on the left side of the street, and the other is parked

on the right side of the street.

 

>>> /bye

This is the correct answer.

Now with a python script:

import requests

import json

import base64

import os

 

url = "http://localhost:8848/v1/chat/completions"

 

# 1. Path to your local image

image_path = r"C:\Users\ravib\Downloads\frames\frames\frame11.jpg"

 

# 2. Open the image file and encode it to Base64

if os.path.exists(image_path):

    with open(image_path, "rb") as image_file:

        base64_image = base64.b64encode(image_file.read()).decode('utf-8')

else:

    print(f"Error: File not found at {image_path}")

    exit()

 

# 3. Construct the payload with the Base64 data URI format

payload = {

    "model": "qwen2.5vl:7b",

    "messages": [

        {

            "role": "user",

            "content": [

                {

                    "type": "text",

                    "text": "How many red cars are in the image?"

                },

                {

                    "type": "image_url",

                    "image_url": {

                        "url": f"data:image/jpeg;base64,{base64_image}"

                    }

                }

            ]

        }

    ]

}

 

headers = {

    "Content-Type": "application/json"

}

 

response = requests.post(url, headers=headers, data=json.dumps(payload))

 

print("Status:", response.status_code)

print("Response:")

print(response.text)

 

## Response

# Status: 200

# Response:

#{"id":"chatcmpl-429","object":"chat.completion","created":1788656816,"model":"qwen2.5vl:7b","system_fingerprint":"fp_ollama","choices":[{"index":0,"message":{"role":"assistant","content":"There is one red car on the street in the image."},"finish_reason":"stop"}],"usage":{"prompt_tokens":1226,"prompt_tokens_details":{"cached_tokens":22},"completion_tokens":13,"total_tokens":1239}}

 

This is the incorrect answer.

Now, the fix that works:

import base64

from PIL import Image

import io

import ollama

 

# 1. Path to your image file

image_path = r"C:\Users\ravib\Downloads\frames\frames\frame11.jpg"

 

# 2. Open image with Pillow to ensure it passes cleanly as standard bytes

with Image.open(image_path) as img:

    if img.mode in ("RGBA", "P"):

        img = img.convert("RGB")

   

    # Optional: Keep resolution native but ensure metadata handles boundaries well

    buffer = io.BytesIO()

    img.save(buffer, format="JPEG", quality=100)

    image_bytes = buffer.getvalue()

 

# 3. Direct programmatic call to the Ollama server on your port

# (Point the client explicitly to your active instance)

client = ollama.Client(host="http://localhost:8848")

 

response = client.chat(

    model="qwen2.5vl:7b",

    messages=[

        {

            "role": "user",

            "content": "Look closely at the entire scene, including any cars parked down the sides of the street. How many red cars are visible in this image?",

            "images": [image_bytes]  # Pass raw image bytes, avoiding Base64 URI scaling issues

        }

    ],

    options={

        "temperature": 0.0,          # Eliminates random sampling path bias

        "num_predict": 100,          # Gives the model breathing room to elaborate

        "num_ctx": 8192              # Expand context window to avoid aggressive clipping

    }

)

 

# Print the final result cleanly

print("Response:")

print(response['message']['content'])

Response:

In the image, there are two red cars visible. One is parked on the left side of the street near the tall building, and the other is parked further down the street on the right side.

Latest models of Qwen recommend:

·        Thinking Mode: temperature=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0

·        Instruct (or non-thinking) mode: temperature=0.7, top_p=0.80, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0