LambdaLabTM
Artificial Intelligence · Class 10 Project · Subject Code 417
Sample ProjectComputer VisionSDG 14 · SDG 13⏱️ 15 min read

Spotting Coral Bleaching

The curriculum's own Computer Vision project: reading reef photos pixel by pixel to tell healthy coral from bleached.

1Introduction

Divers and underwater drones take thousands of photos of a reef on every survey. A scientist then has to look at each one and decide: is this coral healthy or bleached?

That takes weeks, and by the time the photos are sorted the bleaching may have spread. The colour of the coral is the main clue, and colour is something a computer can measure exactly.

This is the Computer Vision sample project in the CBSE curriculum, which builds it in Orange Data Mining. Here it is built in Python, so that every step — from pixels to prediction — can be seen.

14SDG 14
Life below Water
13SDG 13
Climate Action
how it connects to the goal

Coral reefs are home to about a quarter of all sea life, though they cover a tiny part of the ocean. When the sea gets too warm, corals push out the tiny algae that live in them and give them colour, and turn white — this is bleaching. A bleached coral can recover if the water cools in time, but repeated bleaching kills reefs. Finding it early tells scientists where reefs need protection, which is SDG 14; the warming behind it is SDG 13.

The curriculum asks that the project be related to the Sustainable Development Goals. That link is the reason the problem is worth solving, so it belongs at the very start of the report, not tacked on at the end.

2Stage 1 — Problem Scoping

Problem scoping means understanding the problem properly before building anything. The tool for it is the 4Ws Problem Canvas: who has the problem, what the problem is, where it happens, and why solving it matters.

Who?the stakeholders
  • Marine scientists studying coral reefs
  • Divers and reef-protection groups who take the photos
What?the problem
  • Thousands of reef photos are too many to check by eye quickly
  • Bleaching found late may be too late to protect a reef
Where?the context
  • Coral reefs, such as Lakshadweep and the Gulf of Mannar
  • After each survey dive, especially in hot summers
Why?the benefit
  • Bleached areas can be found and protected sooner
  • Scientists' time goes to the reefs that need it

The problem statement

The four answers are then joined into one sentence, using the curriculum's problem statement template:

Our marine scientists have a problem of sorting thousands of reef photos into healthy and bleached coral when every survey brings back more photos than they can check quickly. An ideal solution would sort the photos automatically, so bleached areas are found early.
who would use it

Marine scientists and trained divers who photograph reefs, such as those around Lakshadweep, the Andaman and Nicobar Islands and the Gulf of Mannar.

How it is done today

Scientists checking every photo

Accurate, but very slow. A single survey can take weeks to sort.

Coral colour charts

Divers hold a card of coral colours up to the reef and note the closest match. Clever and cheap, but done by hand, one coral at a time.

Satellite sea-temperature alerts

Satellites warn when the sea is hot enough to cause bleaching. They predict the risk; they cannot see whether a particular coral has actually bleached.

Objectives

  1. To read reef photos into Python as arrays of pixel values
  2. To see how a colour photo is stored as red, green and blue layers
  3. To separate coral pixels from water pixels
  4. To measure two features of the coral — brightness and colourfulness — from every photo
  5. To build a model that learns the average healthy and bleached coral, and test it on unseen photos
  6. To look at the photos it got wrong and understand why
  7. To label new photos from a survey

📘 Revise: Stage 1 — Problem Scoping

3Stage 2 — Data Acquisition

The data is a folder of photos, one folder for each class: images/healthy/ and images/bleached/. This is the same layout that Teachable Machine and Orange use.

There are 160 photos, each 64 × 64 pixels. A second folder, new_photos/, holds four photos from a new survey that the model has never seen.

These pictures were drawn by a program, not taken in the sea, so that the project can be shared freely and run anywhere. The curriculum's own coral dataset (linked from the CBSE curriculum) uses real photos. For your project, use that dataset or another public one, and credit it — never present drawn pictures as real reef photos.

Watch Out
This dataset is a LambdaLab sample. A program made it to behave like the real thing, so the project can be run before you have collected anything. It is not real data. In your own report, use data you collected or a public dataset, and say where it came from.

Features and label

The features are what the model is given. The label is the answer it has to learn to give.

ColumnTypeWhat it holdsRole
brightnessdecimalAverage of the coral pixels' R, G and B values (0 = black, 255 = white)feature
colourfulnessdecimalAverage gap between each coral pixel's largest and smallest colour value (0 = grey or white)feature
labeltexthealthy or bleached — the folder the photo came fromlabel
photofileThe photo, read as a 64 × 64 × 3 array of numbersnot used
coral_pixelsintegerHow many pixels were counted as coralnot used

Inside the images/ folder

Reef photos sorted into a healthy folder and a bleached folder. Lighting and the blue cast of deep water change from photo to photo, and some corals are part-way, so the job is not trivially easy. There are 160 images, 1393.8 KB in all, one folder per class — the same layout Teachable Machine and Orange expect:

images/bleached/ · 80images/healthy/ · 80

The images come with the project download.

Inside the new_photos/ folder

Four photos from a new survey, used in the deployment stage. There are 4 images, 34.8 KB in all.

The images come with the project download.

📘 Revise: Stage 2 — Data Acquisition

4Stage 3 — Data Exploration

Data exploration means getting to know the data before trusting it: fixing what is wrong with it, then drawing it to see the patterns. The charts here are what decide what the model should be.

What was wrong with the data

Most of each photo is water, not coral
about 70% of the pixels

Averaging the whole photo would mostly measure the water. So the program first finds the coral: water has very little red, coral has a lot, so a pixel with red above 77 (out of 255) counts as coral. Deciding which pixels belong to the object is called segmentation.

Lighting changes from photo to photo
every photo

Deep or cloudy water makes everything darker and bluer. This is why the project measures colourfulness as well as brightness: a dim white coral is still grey, not brown.

A photo is 12,288 numbers
64 × 64 × 3

Too many for a simple model to use directly. Feature extraction turns each photo into just two numbers that describe what matters — how bright and how colourful the coral is.

1Eight photos of each kind
Images
Eight photos of each kind
how to read it

The top row is healthy coral; the bottom row is bleached. They were read from the folders with plt.imread() and shown with plt.imshow() — the practical-file program "read an image and display it using Python".

what it shows

To our eyes the difference is colour: healthy coral is brown, olive or orange, and bleached coral is white or grey. But some healthy corals are pale and some bleached ones still have a little colour, and dim lighting makes everything look darker. The model will find those photos hardest.

drawn by the program · saved as chart1_sample_photos.png
2One photo, split into red, green and blue
Images
One photo, split into red, green and blue
how to read it

The same photo four times: as we see it, then each of its three colour layers on its own. In each layer, a darker colour means a bigger number.

what it shows

This is how the computer stores a colour photo: three grids of numbers, one each for red, green and blue. The water is strong in blue and weak in red. The coral is strong in red. That one difference is what lets the program separate coral from water.

drawn by the program · saved as chart2_rgb_layers.png
3Two features measured from every photo
Scatter plot
Two features measured from every photo
how to read it

Each dot is one photo: how bright its coral is (across) and how colourful (up).

what it shows

The two kinds form two clouds. Healthy coral sits up and to the left — colourful and darker. Bleached coral sits low and to the right — grey or white, and brighter. Where they meet, dim bleached corals sit close to pale healthy ones. That overlap is where the mistakes will be.

drawn by the program · saved as chart3_features.png

📘 Revise: Stage 3 — Data Exploration

5Stage 4 — Modelling

Where this model sits in the family of AI models:

The answer is one of two classes — healthy or bleached — so this is classification. Every training photo comes from a labelled folder, so it is supervised learning. Because the input is images, it belongs to the Computer Vision domain.

How the model works

The photos are shuffled and split into 128 for training and 32 for testing.

Each photo has already been turned into two features. The model learns the average brightness and colourfulness of healthy coral, and the same for bleached coral, from the training photos. To label a new photo, it measures the photo's two features and picks whichever average is closer.

This is the classic way computer vision worked before deep learning: a person decides which features matter (here, colour) and writes code to measure them. A Convolutional Neural Network, from Unit 5, learns its own features from the pixels instead. That is what Teachable Machine and Orange's Image Embedding do behind the scenes.

📘 Revise: Stage 4 — Modelling

6Stage 5 — Evaluation

On 32 testing photos the model reached an accuracy of 84.4 %.

For bleaching, the costly mistake is a missed bleached coral (a false negative): a reef that needs help goes unnoticed. A false alarm only means a scientist looks at one extra photo. So recall matters most. The recall was 75.0 % and the precision 100.0 %.

That recall is the honest weak point of this model. The mistakes chart shows why: dimly lit bleached corals look darker and slightly coloured. A better feature — for example, comparing the coral's colour with the colour of the water around it, to cancel out the lighting — is the obvious next step.

4Confusion matrix
Confusion matrix
Confusion matrix
how to read it

Bleached is the positive class, because it is what the scientists are looking for. TP: bleached, and found. FN: bleached, but called healthy. FP: healthy, but called bleached. TN: healthy, and called healthy.

what it shows

On the testing photos the counts are 15 5 0 12 (TP, FN, FP, TN). The model never raised a false alarm, but it missed some bleached coral.

drawn by the program · saved as chart4_matrix.png
5The photos it got wrong
Images
The photos it got wrong
how to read it

Every testing photo the model labelled wrongly, with its true label.

what it shows

All the mistakes are bleached corals that it called healthy, and they have something in common: they are dimly lit, with brightness between about 115 and 130, and they still carry a little colour. In dark water, a bleached coral is not bright white any more. Looking at the mistakes tells you exactly what to fix next — which a single accuracy number never does.

drawn by the program · saved as chart5_mistakes.png

📘 Revise: The Confusion Matrix

7Stage 6 — Deployment

The program reads four new survey photos it has never seen, measures their features, and labels each one. It saves them with their labels as a picture.

In real use, a scientist would point the program at a whole folder of survey photos and get back a list of the ones labelled bleached, to check first. The program does the sorting; the scientist does the judging.

6Four photos from a new survey
Images
Four photos from a new survey
how to read it

The four new photos, each with the label the model gave it.

what it shows

Three are labelled correctly. The first was drawn as a healthy but very pale coral, and the model calls it bleached. That is a false alarm — but in a real reef, a coral that has gone pale is often starting to bleach, so it is exactly the photo a scientist would want to look at anyway.

drawn by the program · saved as chart6_new_photos.png

📘 Revise: Stage 6 — Deployment

8Ethical concerns

An AI project is not finished when the model works. The curriculum asks three questions of every model — is it fair (bias), can it explain itself (transparency), and who answers for its mistakes (accountability). For this project:

Where the photos come from

Real reef photos belong to the scientists or divers who took them. Use public datasets, credit them, and never present drawn or edited pictures as real survey photos.

Bias in the data

A model trained on one reef, in one kind of water, may fail on another — different coral species, different water colour. It must be tested on photos from the reef where it will be used.

Accountability

A missed bleaching event could mean a reef is not protected in time. The model should help scientists check faster, not replace their checking.

📘 Revise: Bias, Transparency, Accountability

9Source code

The whole program — it is also in the downloads at the top of this page — in Python with pandas, NumPy and matplotlib — the three libraries of Unit 7. It is laid out as the six stages of the AI Project Cycle, one after another. Every chart on this page was drawn by it, and every number came out of running it.

coral_bleaching.py
# ---------------------------------------------------------------------------
# coral_bleaching.py
#
# AI project on Computer Vision: telling healthy coral from bleached coral in
# underwater photographs, so that bleaching can be spotted early.
#
# CBSE Class X, Artificial Intelligence (417), Part C project work.
# SDG 14 (Life below Water) and SDG 13 (Climate Action).
#
# A computer sees a photo as a grid of pixels, and each pixel as three
# numbers from 0 to 255 - how much red, green and blue it holds. The program:
#   1. reads every photo into those numbers,
#   2. finds which pixels are coral and which are water (segmentation),
#   3. measures two FEATURES of the coral: how bright it is, and how
#      colourful it is, and
#   4. learns the average healthy coral and the average bleached coral from
#      the training photos, and labels a new photo by whichever it is closer to.
#
# Libraries: numpy (the pixel arithmetic), matplotlib (reading and showing
# images, and the charts), pandas (the table of features), os (the folders).
# ---------------------------------------------------------------------------

# %% Stage 1 - Problem scoping
print("=" * 60)
print("SPOTTING CORAL BLEACHING")
print("=" * 60)
print("Who   : marine scientists and reef divers")
print("What  : thousands of reef photos, too many to check by eye")
print("Where : coral reefs, such as those around Lakshadweep")
print("Why   : bleaching caught early shows where reefs need protection")
print()

# %% Stage 2 - Data acquisition
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

pd.set_option("display.width", 120)

classes = ["healthy", "bleached"]
paths = []
labels = []
for c in classes:
    for name in sorted(os.listdir(os.path.join("images", c))):
        paths.append(os.path.join("images", c, name))
        labels.append(c)

print("--- Stage 2: Data acquisition ---")
print("Healthy photos  :", labels.count("healthy"))
print("Bleached photos :", labels.count("bleached"))
print("Total photos    :", len(paths))

# Read one photo and look at what the computer actually sees.
first = plt.imread(paths[0])
print("One photo is stored as an array of shape :", first.shape)
print("Height x width x colours                 : 64 x 64 x 3 = 12288 numbers")
pixel = (first[40, 32] * 255).round()
print("The pixel at row 40, column 32 (R, G, B) :", int(pixel[0]), int(pixel[1]), int(pixel[2]))
print()

# Chart 1: eight photos of each kind, spread through each folder.
healthy_paths = []
bleached_paths = []
for i in range(len(paths)):
    if labels[i] == "healthy":
        healthy_paths.append(paths[i])
    else:
        bleached_paths.append(paths[i])
plt.figure(figsize=(9, 2.6))
for i in range(8):
    plt.subplot(2, 8, i + 1)
    plt.imshow(plt.imread(healthy_paths[i * len(healthy_paths) // 8]))
    plt.axis("off")
    if i == 0:
        plt.title("healthy", fontsize=9, loc="left")
    plt.subplot(2, 8, i + 9)
    plt.imshow(plt.imread(bleached_paths[i * len(bleached_paths) // 8]))
    plt.axis("off")
    if i == 0:
        plt.title("bleached", fontsize=9, loc="left")
plt.tight_layout()
plt.savefig("chart1_sample_photos.png")
plt.close()

# %% Stage 3 - Data exploration
print("--- Stage 3: Data exploration ---")

# Chart 2: one photo split into its red, green and blue layers.
plt.figure(figsize=(9, 2.8))
plt.subplot(1, 4, 1)
plt.imshow(first)
plt.title("Photo")
plt.axis("off")
channel_names = ["Red", "Green", "Blue"]
channel_maps = ["Reds", "Greens", "Blues"]
for ch in range(3):
    plt.subplot(1, 4, ch + 2)
    plt.imshow(first[:, :, ch], cmap=channel_maps[ch], vmin=0, vmax=1)
    plt.title(channel_names[ch])
    plt.axis("off")
plt.tight_layout()
plt.savefig("chart2_rgb_layers.png")
plt.close()

# Feature extraction. Water is blue-green with very little red, and coral -
# healthy or bleached - has a lot of red. So a pixel with red above 0.3
# (about 77 out of 255) is counted as coral. This is segmentation: deciding
# which pixels belong to the object.
rows = []
for i in range(len(paths)):
    img = plt.imread(paths[i])[:, :, :3].astype(float) * 255
    coral = img[:, :, 0] > 77
    pixels = img[coral]                                  # only the coral pixels
    brightness = pixels.mean()                            # 0 = black, 255 = white
    colourful = (pixels.max(axis=1) - pixels.min(axis=1)).mean()   # grey/white = 0
    rows.append([paths[i], labels[i], coral.sum(), round(brightness, 1), round(colourful, 1)])

features = pd.DataFrame(rows, columns=["photo", "label", "coral_pixels", "brightness", "colourfulness"])
print("Features measured from each photo (first 5 of each kind):")
print(features[features["label"] == "healthy"].head(5).to_string(index=False))
print(features[features["label"] == "bleached"].head(5).to_string(index=False))
print()
print("Average features of each kind:")
print(features.groupby("label")[["coral_pixels", "brightness", "colourfulness"]].mean().round(1))
print()

# Chart 3: the two features, one dot per photo.
plt.figure(figsize=(7, 5))
colours = ["#b5651d", "#7fb3d5"]
for k in range(2):
    part = features[features["label"] == classes[k]]
    plt.scatter(part["brightness"], part["colourfulness"], color=colours[k], label=classes[k], alpha=0.75)
plt.title("Two features measured from every photo")
plt.xlabel("Brightness of the coral (0-255)")
plt.ylabel("Colourfulness of the coral")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.4)
plt.tight_layout()
plt.savefig("chart3_features.png")
plt.close()

# %% Stage 4 - Modelling
print("--- Stage 4: Modelling ---")
use = ["brightness", "colourfulness"]

features = features.sample(frac=1, random_state=8)
cut = int(len(features) * 0.8)
train = features[:cut]
test = features[cut:]
print("Training photos :", len(train))
print("Testing photos  :", len(test))

low = train[use].min()
high = train[use].max()
averages = ((train[use] - low) / (high - low)).groupby(train["label"]).mean()
print()
print("What the model learned - the average of each kind (rescaled 0 to 1):")
print(averages.round(2))
print()

test_scaled = (test[use] - low) / (high - low)
predictions = []
for i in range(len(test)):
    distance = ((averages - test_scaled.iloc[i]) ** 2).sum(axis=1)
    predictions.append(distance.idxmin())

# %% Stage 5 - Evaluation
print("--- Stage 5: Evaluation ---")
actual = list(test["label"])

# "bleached" is the positive class: it is what the scientists are looking for.
tp = fn = fp = tn = 0
for i in range(len(actual)):
    if actual[i] == "bleached" and predictions[i] == "bleached":
        tp = tp + 1
    elif actual[i] == "bleached":
        fn = fn + 1
    elif predictions[i] == "bleached":
        fp = fp + 1
    else:
        tn = tn + 1
accuracy = (tp + tn) / len(actual) * 100
precision = 0
if tp + fp > 0:
    precision = tp / (tp + fp) * 100
recall = 0
if tp + fn > 0:
    recall = tp / (tp + fn) * 100
f1 = 0
if precision + recall > 0:
    f1 = 2 * precision * recall / (precision + recall)
print("TP, FN, FP, TN :", tp, fn, fp, tn)
print("Accuracy       :", round(accuracy, 1), "%")
print("Precision      :", round(precision, 1), "%")
print("Recall         :", round(recall, 1), "%")
print("F1 score       :", round(f1, 1), "%")
print()

# Looking at the mistakes is the most useful check in computer vision.
wrong = []
for i in range(len(actual)):
    if predictions[i] != actual[i]:
        wrong.append(i)
print("Photos the model got wrong :", len(wrong))
for i in wrong:
    row = test.iloc[i]
    print("  " + os.path.basename(row["photo"]).ljust(18), "really", row["label"].ljust(8),
          " brightness", row["brightness"], " colourfulness", row["colourfulness"])
print()

# Chart 5: the photos it got wrong.
if len(wrong) > 0:
    plt.figure(figsize=(1.8 * len(wrong) + 0.5, 2.4))
    for n in range(len(wrong)):
        row = test.iloc[wrong[n]]
        plt.subplot(1, len(wrong), n + 1)
        plt.imshow(plt.imread(row["photo"]))
        plt.title("really " + row["label"], fontsize=9)
        plt.axis("off")
    plt.tight_layout()
    plt.savefig("chart5_mistakes.png")
    plt.close()

# Chart 4: confusion matrix.
grid = [[tp, fn], [fp, tn]]
plt.figure(figsize=(5, 4.3))
plt.imshow(grid, cmap="Blues")
names = [["TP", "FN"], ["FP", "TN"]]
for r in range(2):
    for c in range(2):
        if grid[r][c] > max(max(grid)) / 2:
            ink = "white"
        else:
            ink = "black"
        plt.text(c, r, names[r][c] + "\n" + str(grid[r][c]), ha="center", va="center", fontsize=14, color=ink)
plt.xticks([0, 1], ["Said bleached", "Said healthy"])
plt.yticks([0, 1], ["Bleached", "Healthy"])
plt.xlabel("What the model said")
plt.ylabel("The truth")
plt.title("Confusion matrix (testing photos)")
plt.tight_layout()
plt.savefig("chart4_matrix.png")
plt.close()

# %% Stage 6 - Deployment
print("--- Stage 6: Deployment ---")
new_names = sorted(os.listdir("new_photos"))
plt.figure(figsize=(8, 2.6))
for i in range(len(new_names)):
    img = plt.imread(os.path.join("new_photos", new_names[i]))[:, :, :3].astype(float) * 255
    pixels = img[img[:, :, 0] > 77]
    point = pd.Series({
        "brightness": pixels.mean(),
        "colourfulness": (pixels.max(axis=1) - pixels.min(axis=1)).mean(),
    })
    distance = ((averages - (point - low) / (high - low)) ** 2).sum(axis=1)
    answer = distance.idxmin()
    print(new_names[i], "-> brightness", round(point["brightness"]), " colourfulness",
          round(point["colourfulness"]), "->", answer.upper())
    plt.subplot(1, len(new_names), i + 1)
    plt.imshow(img.astype("uint8"))
    plt.title(answer, fontsize=10)
    plt.axis("off")
plt.tight_layout()
plt.savefig("chart6_new_photos.png")
plt.close()

The library calls it is built from

CallWhereWhat it does
os.listdir()Stage 2Lists the photos in each folder
plt.imread()Stage 2Reads a photo into an array of numbers
img.shapeStage 2The size of the array: height, width, colours
img[40, 32]Stage 2One pixel's red, green and blue values
plt.imshow() / plt.subplot()Stages 2, 3, 5, 6Shows photos side by side
img[:, :, 0]Stage 3The red layer on its own
img[:, :, 0] > 77Stage 3Marks which pixels are coral (segmentation)
pixels.mean()Stage 3Brightness of the coral
pixels.max(axis=1) - pixels.min(axis=1)Stage 3How colourful each coral pixel is
groupby(...).mean()Stage 4The average healthy and bleached coral
idxmin()Stage 4The closer of the two averages

10Sample output

A real run, exactly as it appeared. Nothing below was typed by hand.

Output
============================================================
SPOTTING CORAL BLEACHING
============================================================
Who   : marine scientists and reef divers
What  : thousands of reef photos, too many to check by eye
Where : coral reefs, such as those around Lakshadweep
Why   : bleaching caught early shows where reefs need protection

--- Stage 2: Data acquisition ---
Healthy photos  : 80
Bleached photos : 80
Total photos    : 160
One photo is stored as an array of shape : (64, 64, 3)
Height x width x colours                 : 64 x 64 x 3 = 12288 numbers
The pixel at row 40, column 32 (R, G, B) : 30 81 139

--- Stage 3: Data exploration ---
Features measured from each photo (first 5 of each kind):
                         photo   label  coral_pixels  brightness  colourfulness
images/healthy/healthy_001.png healthy           866       151.0           48.2
images/healthy/healthy_002.png healthy          1414       117.0           21.5
images/healthy/healthy_003.png healthy          1074       123.1           35.6
images/healthy/healthy_004.png healthy           992        72.2           57.9
images/healthy/healthy_005.png healthy          1301       142.8           65.9
                           photo    label  coral_pixels  brightness  colourfulness
images/bleached/bleached_001.png bleached          1267       163.6            5.1
images/bleached/bleached_002.png bleached           813       113.0            4.6
images/bleached/bleached_003.png bleached          1448       144.4            4.6
images/bleached/bleached_004.png bleached           902       204.2           17.6
images/bleached/bleached_005.png bleached          1352       141.8            5.5

Average features of each kind:
          coral_pixels  brightness  colourfulness
label                                            
bleached        1178.8       164.8           15.3
healthy         1066.4       108.1           43.8

--- Stage 4: Modelling ---
Training photos : 128
Testing photos  : 32

What the model learned - the average of each kind (rescaled 0 to 1):
          brightness  colourfulness
label                              
bleached        0.58           0.09
healthy         0.24           0.35

--- Stage 5: Evaluation ---
TP, FN, FP, TN : 15 5 0 12
Accuracy       : 84.4 %
Precision      : 100.0 %
Recall         : 75.0 %
F1 score       : 85.7 %

Photos the model got wrong : 5
  bleached_079.png   really bleached  brightness 124.4  colourfulness 18.0
  bleached_019.png   really bleached  brightness 132.4  colourfulness 30.4
  bleached_036.png   really bleached  brightness 114.7  colourfulness 15.8
  bleached_006.png   really bleached  brightness 125.4  colourfulness 21.7
  bleached_057.png   really bleached  brightness 121.5  colourfulness 17.4

--- Stage 6: Deployment ---
photo_1.png -> brightness 127  colourfulness 17 -> BLEACHED
photo_2.png -> brightness 200  colourfulness 19 -> BLEACHED
photo_3.png -> brightness 76  colourfulness 38 -> HEALTHY
photo_4.png -> brightness 203  colourfulness 6 -> BLEACHED

11The same project without code

The curriculum names both tools for Computer Vision. Teachable Machine trains an image model in the browser; Orange does the same with widgets. The tool is Teachable Machine (or Orange with the Image Analytics add-on).

1
Teachable Machine: New Image Project

Open teachablemachine.withgoogle.com and choose an Image Project, standard image model.

2
Class 1 and Class 2

Rename them healthy and bleached, and upload the photos from each folder.

3
Train Model

Click Train. It learns its own features from the pixels, using a neural network.

4
Preview

Upload a photo from new_photos and read the confidence for each class.

5
Orange: Import Images

Point it at the images folder. The folder names become the class labels.

6
Orange: Image Embedding

Turns each photo into features, using a CNN (it needs an internet connection).

7
Orange: Test and Score + Logistic Regression

Train a model on the embeddings and read the accuracy, precision and recall.

8
Orange: Confusion Matrix → Image Viewer

Select the wrong cells in the matrix and view those photos — the same as chart 5.

Tip
Doing both is the strongest report. The no-code version shows you can use the curriculum's tool; the Python version shows you understand what the tool is doing underneath. If the numbers come out slightly different, that is expected — the tool picks its own training rows and its own model settings — and saying why in the report is worth marks.

📘 Revise: No-Code AI, and Orange

12Testing

Every case below was actually run, and the result is what came back. Each one gives the whole program a small input of its own.

Test caseExpectedActualResult
All 160 photos are readTotal photos : 160Total photos : 160Pass
A photo is a grid of numbersOne photo is stored as an array of shape : (64, 64, 3)One photo is stored as an array of shape : (64, 64, 3)Pass
Water pixels are dark red, not coralThe pixel at row 40, column 32 (R, G, B) : 30 81 139The pixel at row 40, column 32 (R, G, B) : 30 81 139Pass
Every bleached photo it calls bleached really is (no false alarms)Precision : 100.0 %Precision : 100.0 %Pass
Pure brown against pure white: no mistakesAccuracy : 100.0 %Accuracy : 100.0 %Pass
A new brown coral is called healthyphoto_1.png -> brightness 100 colourfulness 95 -> HEALTHYphoto_1.png -> brightness 100 colourfulness 95 -> HEALTHYPass
A new white coral is called bleachedphoto_2.png -> brightness 232 colourfulness 10 -> BLEACHEDphoto_2.png -> brightness 232 colourfulness 10 -> BLEACHEDPass
The images folder is missingFileNotFoundError: [Errno 2] No such file or directory: 'images/healthy'FileNotFoundError: [Errno 2] No such file or directory: 'images/healthy'Pass

13Results, limits and what next

what the project found
  • A colour photo is three grids of numbers; coral and water separate cleanly on the red layer.
  • Two features — brightness and colourfulness — are enough to tell most healthy and bleached coral apart.
  • On unseen photos the model reached an accuracy of 84.4 %, with no false alarms.
  • Its recall was 75.0 %: it misses some bleached coral, and every miss was a dimly lit photo.
  • Looking at the wrong photos showed the cause — lighting — which the accuracy figure alone could not.

What this model cannot do

  • Pictures drawn by a program, small (64 × 64) and simpler than real reef photos
  • Lighting still fools it: dim bleached coral looks healthy
  • The red-pixel rule for finding coral would fail on red sponges or a sandy sea floor
  • Only two classes; a real survey also needs "partly bleached" and "dead"

What to add next

This is where you make the project your own. Take one of these, or an idea of yours:

  • Compare the coral's colour with the water around it, to cancel out lighting
  • Train the same project in Teachable Machine and compare the results
  • Use the curriculum's real coral dataset
  • Add a third class for partly bleached coral

What you may have to learn on your own

  • How a colour image is stored as red, green and blue values from 0 to 255
  • Reading and showing images with plt.imread() and plt.imshow()
  • Feature extraction and segmentation
  • How a CNN differs from hand-made features — Unit 5

14Conclusion

The project turned reef photos into numbers, picked out the coral, measured its colour, and used that to tell healthy coral from bleached. On photos it had never seen, the model was right 84.4 % of the time and never raised a false alarm.

Its weak point is recall, and the project found out exactly why by looking at the mistakes: every missed coral was a bleached one photographed in dim light. That is the most valuable result, because it says what the next version must do.

Building the features by hand made it clear what a computer is actually measuring when it "sees" — and why a CNN, which learns its own features, is used for harder problems.

15Questions for the viva

The project carries a viva voce of its own, worth 5 marks. These are the questions it is most likely to ask about this project. Try answering each one aloud before opening it.

▸Which domain of AI is your project, and why?

Computer Vision, because the input is images.

▸How does a computer store a colour image?

As three grids of numbers, for red, green and blue. Each pixel has three values from 0 to 255.

▸What features did you extract from each photo?

The brightness of the coral and how colourful it is — the average gap between each pixel's largest and smallest colour value.

▸How did you separate coral from water?

Water has very little red, and coral has a lot, so pixels with red above 77 were counted as coral. This is segmentation.

▸Why did your model miss some bleached coral?

They were dimly lit, so they looked darker and a little coloured, like healthy coral.

▸Which matters more here, precision or recall?

Recall, because a missed bleached coral means a reef that needs help is not noticed.

▸How is a CNN different from your model?

My model uses features I chose and measured. A CNN learns its own features from the pixels using convolution.

▸Which SDG does it relate to?

SDG 14, Life below Water, and SDG 13, Climate Action.

16References

  • CBSE, Artificial Intelligence curriculum, Class X — Unit 5 practical: Build a real-world classification model: Coral Bleaching (use case walkthrough).
  • NOAA Coral Reef Watch — https://coralreefwatch.noaa.gov/
  • Teachable Machine — https://teachablemachine.withgoogle.com/
  • Orange Data Mining, Image Analytics add-on — https://orangedatamining.com/widget-catalog/image-analytics/
  • CBSE, Artificial Intelligence (Subject Code 417), Class X curriculum, 2026-27 — Part C, Practical and Project Work
  • CBSE, Artificial Intelligence Facilitator Handbook, Class X
  • pandas — https://pandas.pydata.org/docs/; NumPy — https://numpy.org/doc/; Matplotlib — https://matplotlib.org/stable/
  • LambdaLab — https://www.lambdalab.in
Key Takeaway
The PDF is the whole report — cover page, certificate, acknowledgement, index and every section on this page, ready to print. The cover, certificate and acknowledgement have blank lines where the names go: a certificate with somebody else's name printed on it is not a template. Fill those in, and build the project on data you collected yourself.