Dhiryashil commited on
Commit
01ef086
Β·
verified Β·
1 Parent(s): f2c5657

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +80 -12
  2. app.py +287 -0
  3. requirements.txt +8 -0
README.md CHANGED
@@ -1,12 +1,80 @@
1
- ---
2
- title: Farm Segmentation
3
- emoji: 🏒
4
- colorFrom: green
5
- colorTo: indigo
6
- sdk: gradio
7
- sdk_version: 5.49.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Farm Segmentation API
3
+ emoji: 🏞️
4
+ colorFrom: green
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 4.28.3
8
+ app_file: app.py
9
+ pinned: false
10
+ license: apache-2.0
11
+ short_description: AI-powered agricultural image segmentation and land analysis
12
+ ---
13
+
14
+ # 🏞️ Farm Segmentation API
15
+
16
+ Advanced agricultural image segmentation using SegFormer models for precise field and crop analysis.
17
+
18
+ ## 🎯 Capabilities
19
+ - **Semantic Segmentation**: Pixel-level classification of agricultural scenes
20
+ - **Agricultural Categories**: Soil, vegetation, water, buildings, equipment
21
+ - **Composition Analysis**: Percentage breakdown of field components
22
+ - **Multi-Resolution**: Support for different accuracy/speed tradeoffs
23
+
24
+ ## πŸ€– Models
25
+ - **SegFormer B0**: Fastest processing, basic accuracy
26
+ - **SegFormer B1**: Balanced performance (recommended)
27
+ - **SegFormer B2**: Highest accuracy, slower processing
28
+
29
+ ## πŸ“‘ API Usage
30
+
31
+ ### Python
32
+ ```python
33
+ import requests
34
+ import base64
35
+
36
+ def segment_farm_image(image_path, model="segformer_b1"):
37
+ with open(image_path, "rb") as f:
38
+ image_b64 = base64.b64encode(f.read()).decode()
39
+
40
+ response = requests.post(
41
+ "https://YOUR-USERNAME-farm-segmentation.hf.space/api/predict",
42
+ json={"data": [image_b64, model]}
43
+ )
44
+ return response.json()
45
+
46
+ result = segment_farm_image("field_image.jpg")
47
+ print(result)
48
+ ```
49
+
50
+ ## πŸ“Š Response Format
51
+ ```json
52
+ {
53
+ "segments_detected": 8,
54
+ "segments": [
55
+ {
56
+ "class": "grass",
57
+ "agricultural_category": "vegetation",
58
+ "pixel_count": 145632,
59
+ "percentage": 35.2,
60
+ "label_id": 9
61
+ },
62
+ {
63
+ "class": "soil",
64
+ "agricultural_category": "soil",
65
+ "pixel_count": 98234,
66
+ "percentage": 23.7,
67
+ "label_id": 12
68
+ }
69
+ ],
70
+ "processing_time": 2.1
71
+ }
72
+ ```
73
+
74
+ ## 🌾 Agricultural Categories
75
+ - **soil**: Ground, dirt, earth, mud
76
+ - **vegetation**: Crops, grass, trees, plants
77
+ - **water**: Irrigation channels, ponds, rivers
78
+ - **building**: Barns, greenhouses, structures
79
+ - **equipment**: Tractors, machinery, tools
80
+ - **other**: Roads, sky, uncategorized objects
app.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Farm Segmentation API - Gradio Interface
3
+ SegFormer and UNet models for agricultural image segmentation
4
+ """
5
+
6
+ import gradio as gr
7
+ import torch
8
+ import cv2
9
+ import numpy as np
10
+ from PIL import Image
11
+ import json
12
+ import base64
13
+ import io
14
+ import time
15
+ from typing import List, Dict, Any
16
+
17
+ # Import segmentation models
18
+ try:
19
+ from transformers import SegformerImageProcessor, SegformerForSemanticSegmentation
20
+ MODELS_AVAILABLE = True
21
+ except ImportError:
22
+ MODELS_AVAILABLE = False
23
+
24
+ class SegmentationAPI:
25
+ def __init__(self):
26
+ self.models = {}
27
+ self.processors = {}
28
+ self.model_configs = {
29
+ "segformer_b0": "nvidia/segformer-b0-finetuned-ade-512-512",
30
+ "segformer_b1": "nvidia/segformer-b1-finetuned-ade-512-512",
31
+ "segformer_b2": "nvidia/segformer-b2-finetuned-ade-512-512"
32
+ }
33
+
34
+ # Segmentation classes relevant to agriculture
35
+ self.ag_classes = {
36
+ "soil": ["dirt", "earth", "ground", "soil", "mud"],
37
+ "vegetation": ["grass", "tree", "plant", "leaf", "crop", "vegetation"],
38
+ "water": ["water", "river", "pond", "irrigation"],
39
+ "sky": ["sky", "cloud"],
40
+ "building": ["building", "structure", "barn", "greenhouse"],
41
+ "road": ["road", "path", "walkway"],
42
+ "equipment": ["machine", "tractor", "equipment"]
43
+ }
44
+
45
+ if MODELS_AVAILABLE:
46
+ self.load_models()
47
+
48
+ def load_models(self):
49
+ """Load segmentation models"""
50
+ for model_key, model_name in self.model_configs.items():
51
+ try:
52
+ print(f"Loading {model_name}...")
53
+ processor = SegformerImageProcessor.from_pretrained(model_name)
54
+ model = SegformerForSemanticSegmentation.from_pretrained(model_name)
55
+
56
+ self.processors[model_key] = processor
57
+ self.models[model_key] = model
58
+ print(f"βœ… {model_name} loaded successfully")
59
+ except Exception as e:
60
+ print(f"❌ Failed to load {model_name}: {e}")
61
+
62
+ def segment_image(self, image: Image.Image, model_key: str = "segformer_b1") -> Dict[str, Any]:
63
+ """Segment agricultural image"""
64
+ if not MODELS_AVAILABLE or model_key not in self.models:
65
+ return {"error": "Model not available"}
66
+
67
+ start_time = time.time()
68
+
69
+ try:
70
+ # Preprocess image
71
+ processor = self.processors[model_key]
72
+ model = self.models[model_key]
73
+
74
+ inputs = processor(images=image, return_tensors="pt")
75
+
76
+ # Run inference
77
+ with torch.no_grad():
78
+ outputs = model(**inputs)
79
+
80
+ # Post-process segmentation
81
+ logits = outputs.logits
82
+ upsampled_logits = torch.nn.functional.interpolate(
83
+ logits,
84
+ size=image.size[::-1],
85
+ mode="bilinear",
86
+ align_corners=False,
87
+ )
88
+
89
+ predicted_segmentation = upsampled_logits.argmax(dim=1).squeeze().cpu().numpy()
90
+
91
+ # Analyze segments
92
+ segments_info = self.analyze_segments(predicted_segmentation, model)
93
+
94
+ # Create colored segmentation map
95
+ colored_segmentation = self.create_colored_segmentation(predicted_segmentation, model)
96
+
97
+ processing_time = time.time() - start_time
98
+
99
+ return {
100
+ "segments_detected": len(segments_info),
101
+ "segments": segments_info,
102
+ "segmentation_map": colored_segmentation,
103
+ "processing_time": round(processing_time, 2),
104
+ "model_used": model_key
105
+ }
106
+
107
+ except Exception as e:
108
+ return {"error": str(e)}
109
+
110
+ def analyze_segments(self, segmentation: np.ndarray, model) -> List[Dict[str, Any]]:
111
+ """Analyze segmentation results"""
112
+ unique_labels = np.unique(segmentation)
113
+ segments_info = []
114
+
115
+ total_pixels = segmentation.size
116
+
117
+ for label in unique_labels:
118
+ mask = segmentation == label
119
+ pixel_count = np.sum(mask)
120
+ percentage = (pixel_count / total_pixels) * 100
121
+
122
+ if percentage > 1.0: # Only include segments > 1%
123
+ class_name = model.config.id2label.get(label, f"class_{label}")
124
+ ag_category = self.classify_agricultural_segment(class_name)
125
+
126
+ segments_info.append({
127
+ "class": class_name,
128
+ "agricultural_category": ag_category,
129
+ "pixel_count": int(pixel_count),
130
+ "percentage": round(percentage, 2),
131
+ "label_id": int(label)
132
+ })
133
+
134
+ return sorted(segments_info, key=lambda x: x["percentage"], reverse=True)
135
+
136
+ def classify_agricultural_segment(self, class_name: str) -> str:
137
+ """Classify segment into agricultural categories"""
138
+ class_lower = class_name.lower()
139
+
140
+ for ag_category, keywords in self.ag_classes.items():
141
+ if any(keyword in class_lower for keyword in keywords):
142
+ return ag_category
143
+
144
+ return "other"
145
+
146
+ def create_colored_segmentation(self, segmentation: np.ndarray, model) -> np.ndarray:
147
+ """Create colored segmentation visualization"""
148
+ # Create color palette
149
+ num_classes = len(model.config.id2label)
150
+ colors = self.generate_colors(num_classes)
151
+
152
+ # Create colored image
153
+ h, w = segmentation.shape
154
+ colored = np.zeros((h, w, 3), dtype=np.uint8)
155
+
156
+ for label in np.unique(segmentation):
157
+ mask = segmentation == label
158
+ colored[mask] = colors[label % len(colors)]
159
+
160
+ return colored
161
+
162
+ def generate_colors(self, num_colors: int) -> List[List[int]]:
163
+ """Generate distinct colors for segmentation classes"""
164
+ import random
165
+ random.seed(42) # For consistent colors
166
+
167
+ colors = []
168
+ for i in range(num_colors):
169
+ colors.append([
170
+ random.randint(50, 255),
171
+ random.randint(50, 255),
172
+ random.randint(50, 255)
173
+ ])
174
+
175
+ return colors
176
+
177
+ # Initialize API
178
+ api = SegmentationAPI()
179
+
180
+ def predict_segmentation(image, model_choice):
181
+ """Gradio prediction function"""
182
+ if image is None:
183
+ return None, None, "Please upload an image"
184
+
185
+ # Convert to PIL Image
186
+ if isinstance(image, np.ndarray):
187
+ image = Image.fromarray(image)
188
+
189
+ # Run segmentation
190
+ results = api.segment_image(image, model_choice)
191
+
192
+ if "error" in results:
193
+ return None, None, f"Error: {results['error']}"
194
+
195
+ # Create visualization
196
+ segmentation_img = Image.fromarray(results["segmentation_map"])
197
+
198
+ # Format results text
199
+ results_text = f"""
200
+ 🏞️ **Agricultural Segmentation Analysis**
201
+
202
+ πŸ“Š **Segments Detected**: {results['segments_detected']}
203
+ ⏱️ **Processing Time**: {results['processing_time']}s
204
+ πŸ€– **Model**: {results['model_used']}
205
+
206
+ **🌾 Agricultural Composition**:
207
+ """
208
+
209
+ for segment in results["segments"][:10]: # Top 10 segments
210
+ results_text += f"\nβ€’ **{segment['class']}** ({segment['agricultural_category']}): {segment['percentage']:.1f}%"
211
+
212
+ return image, segmentation_img, results_text
213
+
214
+ # Gradio Interface
215
+ with gr.Blocks(title="🏞️ Farm Segmentation API") as app:
216
+ gr.Markdown("# 🏞️ Farm Segmentation API")
217
+ gr.Markdown("AI-powered agricultural image segmentation and land analysis")
218
+
219
+ with gr.Tab("🌾 Field Analysis"):
220
+ with gr.Row():
221
+ with gr.Column():
222
+ image_input = gr.Image(type="pil", label="Upload Farm Image")
223
+ model_choice = gr.Dropdown(
224
+ choices=["segformer_b0", "segformer_b1", "segformer_b2"],
225
+ value="segformer_b1",
226
+ label="Select Model"
227
+ )
228
+ segment_btn = gr.Button("πŸ” Analyze Segments", variant="primary")
229
+
230
+ with gr.Column():
231
+ original_image = gr.Image(label="Original Image")
232
+ segmented_image = gr.Image(label="Segmentation Map")
233
+
234
+ results_text = gr.Textbox(label="Segmentation Analysis", lines=15)
235
+
236
+ segment_btn.click(
237
+ predict_segmentation,
238
+ inputs=[image_input, model_choice],
239
+ outputs=[original_image, segmented_image, results_text]
240
+ )
241
+
242
+ with gr.Tab("πŸ“‘ API Documentation"):
243
+ gr.Markdown("""
244
+ ## πŸš€ API Endpoint
245
+
246
+ **POST** `/api/predict`
247
+
248
+ ### Request Format
249
+ ```json
250
+ {
251
+ "data": ["<base64_image>", "<model_choice>"]
252
+ }
253
+ ```
254
+
255
+ ### Model Options
256
+ - **segformer_b0**: Fastest, basic segmentation
257
+ - **segformer_b1**: Balanced speed and accuracy (recommended)
258
+ - **segformer_b2**: Higher accuracy, slower processing
259
+
260
+ ### Response Format
261
+ ```json
262
+ {
263
+ "segments_detected": 8,
264
+ "segments": [
265
+ {
266
+ "class": "grass",
267
+ "agricultural_category": "vegetation",
268
+ "pixel_count": 145632,
269
+ "percentage": 35.2,
270
+ "label_id": 9
271
+ }
272
+ ],
273
+ "processing_time": 2.1
274
+ }
275
+ ```
276
+
277
+ ### Agricultural Categories
278
+ - **soil**: Ground, dirt, earth
279
+ - **vegetation**: Crops, grass, trees
280
+ - **water**: Irrigation, ponds, rivers
281
+ - **building**: Barns, greenhouses, structures
282
+ - **equipment**: Tractors, machinery
283
+ - **other**: Uncategorized segments
284
+ """)
285
+
286
+ if __name__ == "__main__":
287
+ app.launch()
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ torch>=2.0.0
2
+ torchvision>=0.15.0
3
+ transformers>=4.30.0
4
+ gradio>=4.28.3
5
+ Pillow>=9.0.0
6
+ opencv-python>=4.8.0
7
+ numpy>=1.21.0
8
+ huggingface-hub>=0.15.0