Spaces:
Configuration error
Configuration error
import streamlit as st | |
import cv2 | |
import requests | |
import base64 | |
import tempfile | |
import os | |
import time | |
from typing import Generator, Tuple | |
# -------------------------- | |
# Configuration | |
# -------------------------- | |
API_KEY = os.getenv("GEMINI_API_KEY") # Fetch API key from Hugging Face secrets | |
API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={API_KEY}" | |
SYSTEM_PROMPT = ''' | |
You are a next-generation AI-driven military surveillance officer, embedded in a real-time battlefield monitoring system. Your core function is to analyze live battlefield footage, identify threats, and provide precise, structured intelligence reports for tactical decision-making. | |
Your analysis must be accurate, number-driven, and predictive. Focus on exact troop counts, vehicle tracking, movement patterns, and enemy strategies. Every report must be structured, concise, and mission-critical. | |
🔴 Mission-Critical Intelligence Goals: | |
1️⃣ Enemy Force Tracking (Exact Numbers & Movements) | |
Identify and count enemy troops, vehicles, and support assets. | |
Categorize unit types (infantry, mechanized, special forces, UAVs, artillery). | |
Track movement direction, speed, formation type (spread-out, tight, advancing, retreating). | |
Detect supply chains, reinforcements, and potential weak points. | |
2️⃣ Strategic Threat Assessment | |
Assign a Threat Level (Low, Moderate, High, Critical) based on: | |
Numerical strength vs. friendly forces | |
Equipment capability (heavy weapons, drones, armored units) | |
Terrain control & tactical positioning | |
Identify sniper nests, ambush zones, flanking attempts. | |
Recognize enemy command centers & key leadership units. | |
3️⃣ Real-Time Vehicle & Artillery Monitoring | |
Detect and count tanks, armored personnel carriers (APCs), artillery, UAVs, supply trucks. | |
Differentiate between stationary vs. mobile units. | |
Identify heavy artillery positions and potential missile launch sites. | |
Track drones and air support operations. | |
4️⃣ Tactical Terrain Intelligence | |
Identify strategic high ground, choke points, supply routes. | |
Recognize defensive fortifications, trenches, camouflaged positions. | |
Determine obstacles affecting movement (bridges, rivers, urban zones, minefields). | |
5️⃣ Predictive Battlefield Analytics | |
Forecast enemy movements & possible attack vectors. | |
Detect supply vulnerabilities, reinforcements, and fallback positions. | |
Predict next-phase engagements based on movement patterns. | |
Provide recommended counter-maneuvers and precision strikes. | |
🟢 Tactical Intelligence Report Format (Example) | |
🛰️ SITUATION UPDATE: Enemy forces detected (450 infantry, 32 armored vehicles, 6 UAVs, 4 artillery units) advancing eastward at 8 km/h toward Hill 72. | |
⚠️ THREAT ASSESSMENT: High-risk engagement. Enemy equipped with anti-armor weaponry, air support. | |
📡 OPERATIONAL INTELLIGENCE: Flanking maneuver detected—50 soldiers moving through dense foliage to breach our western perimeter. | |
🚨 VEHICLE & ARTILLERY STATUS: | |
Tanks: 12 moving in formation | |
APCs: 20 transporting troops | |
UAVs: 6 scouting ahead | |
Artillery: 4 positioned near enemy HQ | |
🔺 COMMAND RECOMMENDATION: Deploy airstrikes on artillery, engage flanking troops with ambush teams, reposition anti-tank defenses along eastern approach. | |
🟠 Intelligence Prioritization | |
✅ Numbers First: Every report must include exact troop & vehicle counts. | |
✅ Tactical Clarity: No vague descriptions—only clear, structured battle intelligence. | |
✅ Predict & Neutralize: AI must anticipate enemy next moves and suggest counter-tactics. | |
✅ Mission-Focused Communication: Short, clear, actionable updates—no unnecessary details. | |
''' | |
# -------------------------- | |
# Gemini API Client | |
# -------------------------- | |
class GeminiClient: | |
def __init__(self, api_key: str, api_url: str): | |
self.api_key = api_key | |
self.api_url = api_url | |
self.session = requests.Session() | |
self.timeout = 30 | |
def analyze_frame(self, frame_b64: str, timestamp: int) -> str: | |
"""Send frame to Gemini API for analysis.""" | |
payload = { | |
"contents": [{ | |
"parts": [ | |
{"text": f"Analyze this battlefield image from {timestamp} seconds:"}, | |
{"inline_data": {"mime_type": "image/jpeg", "data": frame_b64}} | |
] | |
}], | |
"systemInstruction": { | |
"parts": [{"text": SYSTEM_PROMPT}] | |
} | |
} | |
try: | |
response = self.session.post( | |
self.api_url, | |
json=payload, | |
timeout=self.timeout, | |
headers={"Content-Type": "application/json"} | |
) | |
response.raise_for_status() | |
return self._parse_response(response.json()) | |
except requests.exceptions.RequestException as e: | |
return f"Analysis error: {str(e)}" | |
def _parse_response(response: dict) -> str: | |
"""Extract response text from Gemini API response.""" | |
try: | |
return response["candidates"][0]["content"]["parts"][0]["text"] | |
except (KeyError, IndexError): | |
return "No analysis available" | |
# -------------------------- | |
# Helper Functions | |
# -------------------------- | |
def frame_to_base64(frame): | |
"""Convert an image frame to base64 format.""" | |
_, buffer = cv2.imencode(".jpg", frame) | |
return base64.b64encode(buffer).decode("utf-8") | |
def extract_video_frame(video_path, timestamp): | |
"""Extract a frame at a specific timestamp from the video.""" | |
cap = cv2.VideoCapture(video_path) | |
cap.set(cv2.CAP_PROP_POS_MSEC, timestamp * 1000) | |
success, frame = cap.read() | |
cap.release() | |
return frame if success else None | |
def download_video(video_url): | |
"""Download video from URL to a temporary file.""" | |
try: | |
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_file: | |
response = requests.get(video_url, stream=True, timeout=30) | |
response.raise_for_status() | |
for chunk in response.iter_content(chunk_size=8192): | |
temp_file.write(chunk) | |
return temp_file.name | |
except Exception as e: | |
st.error(f"Video download failed: {str(e)}") | |
return None | |
# -------------------------- | |
# Streamlit App | |
# -------------------------- | |
st.title("🎥 Military Surveillance AI") | |
st.write("Upload a battlefield surveillance video to analyze.") | |
video_url = st.text_input("Enter Video URL:") | |
if st.button("Analyze Video") and video_url: | |
st.info("Downloading video...") | |
video_path = download_video(video_url) | |
if video_path: | |
client = GeminiClient(API_KEY, API_URL) | |
st.success("Video downloaded successfully!") | |
st.info("Processing video and analyzing frames...") | |
log = [] | |
# Extract frames and analyze | |
for timestamp in range(10, 40, 10): # Analyze at 10s, 20s, 30s | |
frame = extract_video_frame(video_path, timestamp) | |
if frame is None: | |
log.append(f"[{timestamp}s] Frame extraction failed ❌") | |
continue | |
analysis = client.analyze_frame(frame_to_base64(frame), timestamp) | |
log.append(f"[{timestamp}s] {analysis}") | |
st.write(f"### Timestamp: {timestamp}s") | |
st.image(frame, caption=f"Frame at {timestamp}s", use_column_width=True) | |
st.write(analysis) | |
time.sleep(2) # Simulate processing delay | |
st.success("Analysis complete! ✅") | |
st.text_area("Summary of Analysis:", "\n".join(log), height=200) | |