File size: 4,700 Bytes
d72a22b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""

Coffee Leaf Rust Severity Estimation

====================================



This script calculates the severity of Coffee Leaf Rust (CLR) for individual leaf images.

It processes a directory of leaf images and their corresponding binary masks (representing diseased areas).



Methodology:

    1. Load the original leaf image to determine total leaf area.

    2. Load the corresponding disease mask (generated by SAM or other segmentation models).

    3. Calculate Severity (%) = (Diseased Area / Total Leaf Area) * 100.

    4. Export results to CSV and Excel.



Filename Convention:

    The script expects a naming convention like: "set_<id>_<image_id>_obj<leaf_id>"

    Example: "set_16_123_obj1.jpg"

"""

import os
import cv2
import numpy as np
import pandas as pd
import re

# ================= Configuration =================
# Directory containing individual leaf images (cropped from original)
LEAF_FOLDER = "./data/leaves"

# Directory containing disease masks (binary images: white=disease, black=background)
MASK_FOLDER = "./data/masks"

# Output file paths
OUTPUT_DIR = "./results"
OUTPUT_CSV_NAME = "severity_results.csv"
OUTPUT_EXCEL_NAME = "severity_results.xlsx"

# Regex pattern to parse filename metadata
# Adjust this pattern if your filenames follow a different structure
FILE_PATTERN = r"set_\d+_(\d+)_obj(\d+)"
# =================================================

def calculate_severity():
    # Ensure output directory exists
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    
    output_csv = os.path.join(OUTPUT_DIR, OUTPUT_CSV_NAME)
    output_excel = os.path.join(OUTPUT_DIR, OUTPUT_EXCEL_NAME)

    results = []
    
    print(f"Processing images from: {LEAF_FOLDER}")
    
    # Iterate through all files in the leaf folder
    for filename in os.listdir(LEAF_FOLDER):
        if not filename.lower().endswith((".jpg", ".png", ".jpeg", ".tif")):
            continue

        # Parse filename to extract Image ID and Leaf ID
        match = re.match(FILE_PATTERN, filename)
        if not match:
            print(f"⚠️ Skipping file with non-compliant name: {filename}")
            continue

        image_id, leaf_id = match.groups()

        leaf_path = os.path.join(LEAF_FOLDER, filename)
        mask_path = os.path.join(MASK_FOLDER, filename)

        # --- 1. Calculate Total Leaf Area ---
        # Read image to determine the leaf area. 
        # Assuming the leaf is segmented against a black/white background or we threshold it.
        leaf_img = cv2.imread(leaf_path)
        if leaf_img is None:
            print(f"Error reading image: {leaf_path}")
            continue
            
        gray_leaf = cv2.cvtColor(leaf_img, cv2.COLOR_BGR2GRAY)
        
        # Simple thresholding to separate leaf from background
        # Adjust threshold value (10) as needed based on background color
        _, leaf_binary = cv2.threshold(gray_leaf, 10, 255, cv2.THRESH_BINARY)
        total_leaf_pixels = cv2.countNonZero(leaf_binary)

        # --- 2. Calculate Diseased Area ---
        if os.path.exists(mask_path):
            mask_img = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
            if mask_img is not None:
                diseased_pixels = cv2.countNonZero(mask_img)
            else:
                print(f"Warning: Mask found but unreadable for {filename}")
                diseased_pixels = 0
        else:
            # If no mask exists, assume 0% severity (healthy leaf)
            diseased_pixels = 0  

        # --- 3. Compute Severity ---
        if total_leaf_pixels > 0:
            severity = (diseased_pixels / total_leaf_pixels) * 100
        else:
            severity = 0

        results.append({
            "Image_ID": int(image_id),
            "Leaf_ID": int(leaf_id),
            "Total_Pixels": total_leaf_pixels,
            "Diseased_Pixels": diseased_pixels,
            "Severity_Percent": round(severity, 2)
        })

    # --- 4. Save Outputs ---
    if results:
        df = pd.DataFrame(results).sort_values(["Image_ID", "Leaf_ID"])
        
        df.to_csv(output_csv, index=False)
        print(f"CSV saved to: {output_csv}")
        
        try:
            df.to_excel(output_excel, index=False)
            print(f"Excel saved to: {output_excel}")
        except ImportError:
            print("To save as Excel, please install openpyxl: pip install openpyxl")
        
        print(f"✅ Processing complete. Computed severity for {len(results)} leaves.")
    else:
        print("No valid images found to process.")

if __name__ == "__main__":
    calculate_severity()