File size: 4,034 Bytes
61b3c2b
 
 
 
 
dd1d7f5
61b3c2b
 
dd1d7f5
61b3c2b
 
 
 
 
 
 
 
 
 
 
7613956
 
61b3c2b
e768711
 
 
 
dd1d7f5
 
 
 
 
 
61b3c2b
dd1d7f5
61b3c2b
dd1d7f5
7613956
61b3c2b
 
 
31ddfa7
 
 
 
 
 
 
 
 
61b3c2b
c170961
dd1d7f5
 
 
c170961
dd1d7f5
 
c170961
dd1d7f5
 
 
 
61b3c2b
e768711
 
 
5f6c42c
93d0941
 
e768711
 
 
 
5f6c42c
 
93d0941
 
 
 
e768711
 
 
 
 
 
 
 
c170961
e768711
 
 
 
93d0941
 
 
 
 
 
 
 
 
e768711
 
 
 
 
61b3c2b
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
from pathlib import Path
from typing import Dict
import shutil
from PIL import Image
import glob
import os

from sorghum_pipeline.pipeline import SorghumPipeline
from sorghum_pipeline.config import Config, Paths


def run_pipeline_on_image(input_image_path: str, work_dir: str, save_artifacts: bool = True) -> Dict[str, str]:
    """
    Run sorghum pipeline on a single image (no instance segmentation).
    Returns dict[label -> image_path] for gallery display.
    """

    work = Path(work_dir)
    work.mkdir(parents=True, exist_ok=True)

    # Use input path directly (already in work_dir from app.py)
    input_path = Path(input_image_path)

    # Ensure demo env vars are set before pipeline construction
    os.environ['MINIMAL_DEMO'] = '1'
    os.environ['FAST_OUTPUT'] = '1'

    # Build in-memory config pointing input/output to the working directory
    cfg = Config()
    cfg.paths = Paths(
        input_folder=str(work),
        output_folder=str(work),
        boundingbox_dir=str(work)
    )
    pipeline = SorghumPipeline(config=cfg)

    # Run the pipeline (single image minimal demo)
    results = pipeline.run(single_image_path=str(input_path))

    # Collect outputs
    outputs: Dict[str, str] = {}
    try:
        # Log immediate output directory contents for debugging
        for sub in ['results', 'Vegetation_indices_images', 'texture_output']:
            p = work / sub
            if p.exists():
                files = sorted([str(x.name) for x in p.iterdir() if x.is_file()])
                print(f"Artifacts in {sub}: {files}")
    except Exception:
        pass

    # Collect desired vegetation indices (replace ARI with SAVI)
    wanted = [
        work / 'Vegetation_indices_images/ndvi.png',
        work / 'Vegetation_indices_images/gndvi.png',
        work / 'Vegetation_indices_images/savi.png',
    ]
    labels = [
        'NDVI', 'GNDVI', 'SAVI',
    ]
    for label, path in zip(labels, wanted):
        if path.exists():
            outputs[label] = str(path)

    # Also include overlay and mask if present
    overlay_path = work / 'results/overlay.png'
    mask_path = work / 'results/mask.png'
    composite_path = work / 'results/composite.png'
    yolo_tips_path = work / 'results/yolo_tips.png'
    input_img_path = work / 'results/input_image.png'
    if overlay_path.exists():
        outputs['Overlay'] = str(overlay_path)
    if mask_path.exists():
        outputs['Mask'] = str(mask_path)
    if composite_path.exists():
        outputs['Composite'] = str(composite_path)
    if yolo_tips_path.exists():
        outputs['YOLOTips'] = str(yolo_tips_path)
    if input_img_path.exists():
        outputs['InputImage'] = str(input_img_path)

    # Extract simple stats for display if present in pipeline results
    try:
        plants = results.get('plants', {}) if isinstance(results, dict) else {}
        if plants:
            _, pdata = next(iter(plants.items()))
            veg = pdata.get('vegetation_indices', {})
            stats_lines = []
            for name in ['NDVI', 'GNDVI', 'SAVI']:
                entry = veg.get(name, {})
                st = entry.get('statistics', {}) if isinstance(entry, dict) else {}
                if st:
                    stats_lines.append(f"{name}: mean={st.get('mean', 0):.3f}, std={st.get('std', 0):.3f}")
            # Morphology stats (height, yolo tips)
            morph = pdata.get('morphology_features', {}) if isinstance(pdata, dict) else {}
            traits = morph.get('traits', {}) if isinstance(morph, dict) else {}
            height_cm = traits.get('plant_height_cm')
            if isinstance(height_cm, (int, float)):
                stats_lines.append(f"Plant height: {height_cm:.2f} cm")
            num_tips = traits.get('num_yolo_tips')
            if isinstance(num_tips, (int, float)):
                stats_lines.append(f"YOLO tips: {int(num_tips)}")
            if stats_lines:
                outputs['StatsText'] = "\n".join(stats_lines)
    except Exception:
        pass

    return outputs