
Detecting soccer field
The first weeks of learning computer vision felt like discovering a new pair of eyes. Even the simplest exercises, those that ask you to isolate a color, or clean up a noisy mask, teach you habits that stay with you when the problems get bigger. This small project was one of those: find the grass on a soccer field using nothing more than color, a couple of morphological operations, and patience.
It starts with a single image and two familiar libraries.
import cv2
import numpy as np
# read image
image = cv2.imread('stadium1/Stadium1.jpg')
# split channels
b, g, r = cv2.split(image)
The idea is to turn the image into a clean, binary map where the grass is white and everything else is black. Grass is “green” not just because the green channel is high, but because it’s high relative to red and blue. So for each pixel, compute g / (r + g + b) and keep it if the ratio crosses a threshold. The threshold (0.40 here) isn’t magic, it’s empirical. You adjust, you squint, you rerun.
final = np.zeros_like(g, dtype=np.uint8)
for i in range(len(b)):
for j in range(len(b[i])):
if g[i][j] > 0:
a = float(g[i][j]) / (float(r[i][j]) + float(b[i][j]) + float(g[i][j]))
else:
a = 0.0
final[i][j] = 255 if a > 0.40 else 0

Binary “greenness” mask from a simple ratio test.
A raw threshold is rarely the end. Small bright specks outside the field and tiny holes inside it distract from the goal. A quick opening clears the salt-and-pepper noise; a closing stitches the white regions together into a field-shaped whole.
kernel = np.ones((5, 5), np.uint8)
# remove small noise
opening = cv2.morphologyEx(final, cv2.MORPH_OPEN, kernel)
# fill gaps and smooth the field region
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=5)

After opening: fewer stray specks.

After closing: a coherent field mask.
With a clean mask in hand, the last step is to let the image speak for itself. Merge the binary mask into three channels, and wherever it is white, paint the original image; wherever it is black, keep the background dark. It’s a simple reveal: the field stands out; the rest steps back.
img = cv2.merge((closing, closing, closing))
final_image = image.copy()
for i in range(len(img)):
for j in range(len(img[i])):
if np.all(img[i][j] == 0):
final_image[i][j] = image[i][j]
else:
final_image[i][j] = img[i][j]
cv2.imwrite("stadium1/Stadium1_result.jpg", final_image)

Field isolated: the quiet satisfaction of a good mask.
There’s nothing flashy here, no deep nets, no clever tricks, just the quiet rhythm of preprocessing: choose a cue, test a threshold, clean the result, and reveal the part of the world you care about. Exercises like this don’t just teach syntax; they teach attention. And that habit, once learned, scales.