Watershed segmentation — computer vision in the browser

The watershed algorithm treats pixel intensity as terrain and floods it from markers to split touching objects — the classic fix when contours merge two coins into one. This fetches a photo of objects and runs the full cv2.watershed pipeline. Run it live and tweak the foreground threshold.

Watershed segmentation — example output

Example code (Python / OpenCV)

"""
Watershed segmentation

The watershed algorithm treats pixel intensity as terrain and floods it from markers to split touching objects — the classic fix when contours merge two coins into one. This fetches a photo of objects and runs the full cv2.watershed pipeline. Run it live and tweak the foreground threshold.
"""

import cv2
import requests
import numpy as np

# A real photo, fetched live from the web — nothing is uploaded
url = "https://images.unsplash.com/photo-1589556763393-59ab0f56b811?w=480&q=70"
# no-cache: always fetch a fresh copy so a stale browser-cache entry can't break decoding
resp = requests.get(url, headers={"Cache-Control": "no-cache"})
img = cv2.imdecode(np.frombuffer(resp.content, np.uint8), cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thr = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
k = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thr, cv2.MORPH_OPEN, k, iterations=2)

sure_bg = cv2.dilate(opening, k, iterations=3)
dist = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist, 0.5 * dist.max(), 255, 0)   # tweak 0.5
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

_, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
markers = cv2.watershed(img, markers)
img[markers == -1] = (0, 0, 255)          # object boundaries
print(markers.max() - 1, "regions")
cv2.imshow("watershed", img)

More computer-vision techniques →