Crop Health From Orbit, Checked to a 25th of a Pixel
Draw a field, pick a satellite pass, get NDVI, NDWI or EVI you can walk to. Alignment proven to a 25th of a pixel.
Draw a polygon on a map, pick a Sentinel-2 pass, and get a georectified crop health overlay with stats and a GeoTIFF. The same window now computes NDVI, NDRE, NDWI and EVI — vegetation, red-edge, water, and the index that still has a slope when NDVI has saturated. From there it ranks the field into five to ten walking waypoints, tracks which weak spots keep coming back, and exports a single-file report that works in aeroplane mode.
Try the browser preview — no install, no account. It does the same work your desktop copy would. On real scenes 6,970,025 pixels come out identical, 52 statistics identical, and the ten ranked problem areas in the same order with the same acreages. Your browser reads the imagery straight from the archive and never tells my server where you looked. The desktop tool adds change maps, season curves, persistence across passes and whole-farm checks.

Runs on your own machine. The satellite archive reads anonymously, so there is no account anywhere.
Desktop Farmer view (the Mac app / local Python tool) now walks outline → fields → plain-English map → KMZ / KML / shapefile, with vigorous / watch / bare counts and a Clear all reset. On a pecan orchard that same desktop view can place soil-sample pins from a multi-year May–September NDVI stack — why, and what that is not. The browser preview below stays the lighter client-only pass picker.
Four indexes, one window
NDVI is the one everyone names. It is also the wrong tool for two questions that come up on the same pass.
NDWI — (green − NIR) / (green + NIR) — lights up water and wet soil. A pivot that looks healthy on NDVI can be standing water; NDWI says so. Same cloud mask, same scout, different ratio.
EVI uses blue as well as red and NIR, and it does not saturate as hard in dense canopy. Mid-season corn at NDVI 0.85 is a wall of green. EVI still has a slope, which is the only reason a mid-season change map is worth drawing.
NDRE stays on the red edge at 20 m, the band that moves before the canopy looks tired in true colour. All four share the window, the offset-already- applied flag, and the 30 m cloud dilation. Switching the index does not get a second download.
One fact shapes the whole tool
Sentinel-2 arrives as 10 metre pixels inside 110 km granules on a public bucket, readable by HTTP range requests. So the tool never downloads a scene: it reprojects your polygon into the scene's UTM zone, reads only the pixel window that polygon covers, computes the index in native UTM at native resolution, masks cloud, and only then warps the finished picture for display.
The order matters twice over. Computing before warping, because resampling reflectance and then dividing is not the same as dividing and then resampling. And the window is why the AOI has a floor and a ceiling: below 5 km² a STAC query plus two COG opens buys a few hundred pixels, and above 1,500 km² the window stops fitting in memory at native resolution, about 0.4 GB there and 9.6 GB at the 40,000 km² some services advertise. Those services cap pixels too; they just spend them on coverage and hand you 80 m pixels. This tool keeps 10 m and says no instead.
Trust nothing that looks right
Every bug worth writing down here produced output that looked correct.
- The archive's metadata publishes a reflectance offset of -0.1 and, in a separate field, a flag saying the offset is already applied. Applying the published offset, the obvious reading, double-corrected every pixel: 26.8% went out of range and a healthy field's median NDVI read 0.000. The flag wins.
- The first ever run returned 4.9% valid pixels on a scene advertising 0.0% cloud. A STAC intersects query happily returns a granule that clips one corner of your area; everything outside its footprint reads as nodata while the cloud figure stays perfect. Coverage under 99% is now dropped before cloud is even consulted.
- Sen2Cor draws its cloud edge tight, and the ring just outside it measured NDVI 0.471 against 0.530 for clear field. Low, compact, clustered, exactly what the scout hunts, so an unbuffered mask manufactures scouting targets out of haze. The mask is dilated 30 metres.
The georectification itself is guarded by six numbered checks in one script, because a subtly misplaced overlay is invisible in a screenshot. Output GeoTIFF against source COGs at 400 points: max difference 9.7e-08. PNG footprint against the drawn polygon: IoU 0.998, centroid shift 0.39 metres, a 25th of a pixel. The same checks caught the upload path and the satellite path disagreeing by 10 pixels out of 341,254, an off-by-one window pad that no screenshot would ever show. The app also opens on Garden City, Kansas deliberately: centre-pivot circles in a square-mile grid make any alignment error obvious to the naked eye.
Two gotchas from the desktop launcher, both of which look like network failures: a process launched from Finder inherits a 256 open-file limit where a shell gets over a million, and panning the map fires about a hundred tile requests, so the app raises its own limit at startup. And quitting the app does not stop the server, deliberately; a PID file does.
Scouting that respects the farmer
Ranking weak areas by area times deficit is the honest metric, and its first run filled all ten stops with the farmstead, the roads, and a fallow quarter the farmer already knows about. Bare ground is off by default now and reported as a fraction instead. Thresholds are relative to the field's own 90th percentile, never absolute, and cropping to a named field first matters: scouting a 1,535 hectare window found ten stops, none in the field of interest; cropping to the 73 hectare field surfaced a 37-acre patch sitting 52% down that the wide scan never listed. Your problem loses to your neighbour's bigger one unless you crop.
Change detection between passes more than 30 days apart gets a warning, because winter wheat being harvested reads as a 0.6 NDVI collapse across a hundred acres and drowns every real problem.
What I would tell you before you start
Build the alignment checks before the features. Every feature on top of a raster, scouting, persistence, change, inherits the raster's honesty, and a georectification bug passes every unit test while lying to everyone.

Comments