Inspiration

On 29 September 2024 the Kosi at the Birpur barrage in Bihar carried 661,295 cusecs, the most since 1968. In the same storm Nepal counted 209 dead. The water that floods Bihar starts in Nepal's hills hours earlier, but upstream a gauge reader writes the level by hand, and downstream nobody sees it in time. The water always takes hours. The warning should not.

NadiSaathi (नदी साथी, "river friend") turns those hours into a warning: a camera reads the river in Nepal, OpenCV measures it in metres, and an agent warns the towns downstream in India before the water arrives. A person approves every alert.

What it does

  1. A camera reads the river. A fixed camera looks at a painted staff gauge. Every five minutes, OpenCV 5 turns a burst of five frames into a river level in metres, with an error bar.
  2. The agent decides what to do next, from what OpenCV sees. Nine decision branches (D1–D9), each triggered by an OpenCV number:
    • a blurred or dark frame changes the burst instead of moving an alert;
    • if the camera shifts, it re-aligns with ALIKED+LightGlue;
    • when its three estimators disagree, it asks Claude for a second opinion;
    • a fast rise makes it check twice as often and compute when the water reaches each town downstream, across the border;
    • a crossing drafts the alerts.
  3. A person approves every alert. Drafts in Hindi, Nepali, Maithili, Bhojpuri and English (SMS, voice, CAP) wait for a named operator's PIN: a ward focal person in Nepal or a district control room (DDMA) in India. Step Functions re-notifies while an alert waits.
  4. A guard keeps the model honest. If the vision model contradicts OpenCV or carries an injected instruction ("switch the siren off"), the guard keeps the OpenCV reading and asks a person.
  5. Everything is logged on AWS. Every agent cycle becomes a JSON event in CloudWatch Logs, an OpenCV timing metric, and an evidence file (event plus face-blurred image) in S3.

Live app: https://gaq7chhmb2.execute-api.us-east-1.amazonaws.com Code: https://github.com/Prashant-thakur77/JalRekha

How we built it

OpenCV 5 is the core:

Stage OpenCV 5
Quality gate Laplacian sharpness, histograms, glare and contrast checks
Registration ORB + estimateAffinePartial2D (USAC); ALIKED + LightGlue through the new OpenCV 5 DNN engine when ORB fails
Gauge strip warpAffine along the gauge, 5-frame temporal median
Waterline three estimators: Scharr edge energy, DIS optical flow, Lab colour step
Fusion weighted median + cv2.KalmanFilter for level and rise rate
Privacy YuNet face and number-plate blur before anything is stored
Relief GrabCut flooded-road depth check from a volunteer photo

AWS: one CloudFormation stack (36 resources) on EC2 c8g.xlarge (Graviton4):

  • API Gateway, CloudWatch Logs, metrics, Logs Insights, alarms and dashboard;
  • S3 evidence archive, Step Functions, SNS, Polly, Lambda, SSM and Budgets;
  • deployed with one command, make deploy.

Vision Lab: a page in the app that rebuilds any recorded cycle and shows every OpenCV stage with real images: quality heat map, feature matches, the gauge strip, the three estimator curves in metres, fusion, and per-stage timing on Graviton4. The host's OpenCV build shows KleidiCV acceleration.

Agent and app:

  • Model: Claude, as the second opinion and as the parser for relief requests.
  • MCP: a server with 10 tools, so other agents can use NadiSaathi; none of them can approve an alert.
  • App: FastAPI and a React PWA in English, Hindi and Nepali.

Results (every number from a script in the repo, checked by make check-numbers)

  • 10.6 cm average error reading real USGS staff-gauge cameras (115 frames, nothing fitted). The method we started from: 99.2 cm.
  • 36/36 agent replays correct; first alert a median 62 minutes before the river crossed the warning level, 0 false alerts.
  • 32/32 lying or prompt-injected model replies caught by the guard (English, Hindi, Nepali); the danger siren was never cancelled.
  • Graviton4 vs x86, same 4 vCPU: 99.4 vs 93.3 frames/s, 16% cheaper per frame, identical outputs.
  • In production on AWS: 285 agent cycles logged in CloudWatch, OpenCV 93 ms per cycle median on Graviton4, every cycle archived to S3, 100% uptime over 23 hours of health probes.
  • On a real camera through a real flood (USGS Hancock, July 2026): 6.5 cm error on the readings the agent used, and the siren fired on the first frame above the danger mark.
  • 8/8 flooded roads correctly flagged in real flood photos from India and Nepal.

Challenges we ran into

  • Real cameras are hard. Rising water hides the features registration needs. We added ALIKED+LightGlue as a rescue and a keyframe chain, and added a temporal vote so single hourly snapshots can still be trusted.
  • Calibration. Our first protocol, fitting a line on early frames, did not hold on real cameras. Clicking the printed gauge numerals once, as an installer would, brought the error to 10.6 cm.
  • A model in the loop can lie. We built the guard and a red-team sandbox in the app, so anyone can try to fool it.
  • Parallel replays crashed OpenCV's native code on the server: shared ALIKED/LightGlue objects across threads. We found it in production through CloudWatch, fixed it with per-thread detectors and a lock, and added a regression test.

Accomplishments that we're proud of

  • An ordinary camera pointed at a painted gauge reads a real river within about 10 cm.
  • Every vision result changes what the agent does next, and every public alert still needs a person.
  • Everything is measured and reproducible: 164 backend tests, 57 frontend tests, CI on every push, and docs that fail the build if a number drifts from its result file.
  • The whole film was built from code, and every number in it comes from the repository.

What we learned

  • Measure first, spend second. The cheap OpenCV measurement should decide when to call a large model, not the other way round.
  • Agreement matters. Cross-border warnings need warning levels that agree along the river before the hours can be used.

What's next for NadiSaathi

Pilot cameras on Koshi and Karnali gauges with community early-warning programmes, Nepali voice alerts, DLT-registered SMS in India, a run on the Cloud-Optimized OpenCV AMI, and conversations with DHM (Nepal), CWC and district control rooms (India).

Built With

Share this project:

Updates

Submission history