AI-Manith commited on
Commit
953d9b1
·
verified ·
1 Parent(s): 59a640f

Update src/mango_disease_ontology.py

Browse files
Files changed (1) hide show
  1. src/mango_disease_ontology.py +624 -624
src/mango_disease_ontology.py CHANGED
@@ -1,625 +1,625 @@
1
- """
2
- Mango Disease Detection Semantic Web Ontology
3
- Integrates OWL-RL reasoning with computer vision disease detection
4
- """
5
-
6
- import os
7
- import json
8
- from datetime import datetime
9
- from typing import Dict, List, Tuple, Optional, Any
10
- import cv2
11
- import numpy as np
12
-
13
- # RDF and OWL libraries
14
- from rdflib import Graph, Namespace, Literal, URIRef, BNode
15
- from rdflib.namespace import RDF, RDFS, OWL, XSD
16
- import owlrl
17
-
18
- # Import our disease detection algorithm
19
- from app import FruitDiseaseDetector
20
-
21
- class MangoOntologyManager:
22
- """
23
- Semantic Web Ontology Manager for Mango Disease Detection
24
- Uses OWL-RL reasoning to enhance disease detection with domain knowledge
25
- """
26
-
27
- def __init__(self):
28
- # Initialize RDF graph and namespaces
29
- self.graph = Graph()
30
-
31
- # Define namespaces for our ontology
32
- self.MANGO = Namespace("http://spotradar.org/mango-disease#")
33
- self.DISEASE = Namespace("http://spotradar.org/disease#")
34
- self.DETECTION = Namespace("http://spotradar.org/detection#")
35
- self.VISUAL = Namespace("http://spotradar.org/visual#")
36
- self.AGRI = Namespace("http://spotradar.org/agriculture#")
37
-
38
- # Bind namespaces to graph
39
- self.graph.bind("mango", self.MANGO)
40
- self.graph.bind("disease", self.DISEASE)
41
- self.graph.bind("detection", self.DETECTION)
42
- self.graph.bind("visual", self.VISUAL)
43
- self.graph.bind("agri", self.AGRI)
44
- self.graph.bind("owl", OWL)
45
- self.graph.bind("rdfs", RDFS)
46
-
47
- # Initialize disease detector
48
- self.detector = FruitDiseaseDetector()
49
-
50
- # Build the ontology
51
- self._build_ontology()
52
-
53
- # Apply OWL-RL reasoning
54
- self._apply_reasoning()
55
-
56
- def _build_ontology(self):
57
- """Build the complete mango disease ontology"""
58
- print("Building mango disease ontology...")
59
-
60
- # 1. Define top-level classes
61
- self._define_core_classes()
62
-
63
- # 2. Define mango disease classes
64
- self._define_disease_classes()
65
-
66
- # 3. Define visual characteristics
67
- self._define_visual_properties()
68
-
69
- # 4. Define detection properties
70
- self._define_detection_properties()
71
-
72
- # 5. Define severity levels
73
- self._define_severity_levels()
74
-
75
- # 6. Define causal relationships
76
- self._define_causal_relationships()
77
-
78
- # 7. Define temporal aspects
79
- self._define_temporal_aspects()
80
-
81
- # 8. Define economic impact
82
- self._define_economic_impact()
83
-
84
- print("Ontology structure built successfully!")
85
-
86
- def _define_core_classes(self):
87
- """Define fundamental classes in the ontology"""
88
- # Core classes
89
- classes = [
90
- (self.MANGO.Fruit, "Fruit"),
91
- (self.MANGO.MangoFruit, "Mango Fruit"),
92
- (self.DISEASE.Disease, "Disease"),
93
- (self.DISEASE.FungalDisease, "Fungal Disease"),
94
- (self.DISEASE.BacterialDisease, "Bacterial Disease"),
95
- (self.VISUAL.VisualCharacteristic, "Visual Characteristic"),
96
- (self.VISUAL.ColorCharacteristic, "Color Characteristic"),
97
- (self.VISUAL.TextureCharacteristic, "Texture Characteristic"),
98
- (self.VISUAL.ShapeCharacteristic, "Shape Characteristic"),
99
- (self.DETECTION.DetectionResult, "Detection Result"),
100
- (self.DETECTION.ImageAnalysis, "Image Analysis"),
101
- (self.AGRI.SeverityLevel, "Severity Level"),
102
- (self.AGRI.EconomicImpact, "Economic Impact"),
103
- ]
104
-
105
- for class_uri, label in classes:
106
- self.graph.add((class_uri, RDF.type, OWL.Class))
107
- self.graph.add((class_uri, RDFS.label, Literal(label)))
108
-
109
- def _define_disease_classes(self):
110
- """Define specific mango disease classes"""
111
- # Mango is a subclass of Fruit
112
- self.graph.add((self.MANGO.MangoFruit, RDFS.subClassOf, self.MANGO.Fruit))
113
-
114
- # Disease taxonomy
115
- self.graph.add((self.DISEASE.FungalDisease, RDFS.subClassOf, self.DISEASE.Disease))
116
- self.graph.add((self.DISEASE.BacterialDisease, RDFS.subClassOf, self.DISEASE.Disease))
117
-
118
- # Specific mango diseases
119
- diseases = [
120
- (self.DISEASE.Alternaria, "Alternaria", self.DISEASE.FungalDisease),
121
- (self.DISEASE.Anthracnose, "Anthracnose", self.DISEASE.FungalDisease),
122
- (self.DISEASE.Aspergillus, "Aspergillus (Black Mould Rot)", self.DISEASE.FungalDisease),
123
- (self.DISEASE.Lasiodiplodia, "Lasiodiplodia (Stem and Rot)", self.DISEASE.FungalDisease),
124
- ]
125
-
126
- for disease_uri, label, parent_class in diseases:
127
- self.graph.add((disease_uri, RDF.type, OWL.Class))
128
- self.graph.add((disease_uri, RDFS.label, Literal(label)))
129
- self.graph.add((disease_uri, RDFS.subClassOf, parent_class))
130
-
131
- def _define_visual_properties(self):
132
- """Define visual characteristics and properties"""
133
- # Color properties
134
- color_chars = [
135
- (self.VISUAL.DarkBrown, "Dark Brown Color"),
136
- (self.VISUAL.Black, "Black Color"),
137
- (self.VISUAL.Orange, "Orange Color"),
138
- (self.VISUAL.Pink, "Pink Color"),
139
- (self.VISUAL.Green, "Green Color"),
140
- (self.VISUAL.Yellow, "Yellow Color"),
141
- (self.VISUAL.Red, "Red Color"),
142
- ]
143
-
144
- for color_uri, label in color_chars:
145
- self.graph.add((color_uri, RDF.type, OWL.Class))
146
- self.graph.add((color_uri, RDFS.label, Literal(label)))
147
- self.graph.add((color_uri, RDFS.subClassOf, self.VISUAL.ColorCharacteristic))
148
-
149
- # Texture properties
150
- texture_chars = [
151
- (self.VISUAL.Smooth, "Smooth Texture"),
152
- (self.VISUAL.Rough, "Rough Texture"),
153
- (self.VISUAL.Fuzzy, "Fuzzy Texture"),
154
- (self.VISUAL.Irregular, "Irregular Texture"),
155
- (self.VISUAL.Concentric, "Concentric Pattern"),
156
- ]
157
-
158
- for texture_uri, label in texture_chars:
159
- self.graph.add((texture_uri, RDF.type, OWL.Class))
160
- self.graph.add((texture_uri, RDFS.label, Literal(label)))
161
- self.graph.add((texture_uri, RDFS.subClassOf, self.VISUAL.TextureCharacteristic))
162
-
163
- # Shape properties
164
- shape_chars = [
165
- (self.VISUAL.Circular, "Circular Shape"),
166
- (self.VISUAL.Irregular, "Irregular Shape"),
167
- (self.VISUAL.Oval, "Oval Shape"),
168
- (self.VISUAL.Elongated, "Elongated Shape"),
169
- ]
170
-
171
- for shape_uri, label in shape_chars:
172
- self.graph.add((shape_uri, RDF.type, OWL.Class))
173
- self.graph.add((shape_uri, RDFS.label, Literal(label)))
174
- self.graph.add((shape_uri, RDFS.subClassOf, self.VISUAL.ShapeCharacteristic))
175
-
176
- def _define_detection_properties(self):
177
- """Define object and data properties for detection"""
178
- # Object properties
179
- properties = [
180
- (self.DETECTION.hasDisease, "has disease"),
181
- (self.DETECTION.hasVisualCharacteristic, "has visual characteristic"),
182
- (self.DETECTION.hasSeverityLevel, "has severity level"),
183
- (self.DETECTION.detectedIn, "detected in"),
184
- (self.DETECTION.causedBy, "caused by"),
185
- (self.DETECTION.affects, "affects"),
186
- (self.DETECTION.hasSymptom, "has symptom"),
187
- (self.AGRI.hasEconomicImpact, "has economic impact"),
188
- ]
189
-
190
- for prop_uri, label in properties:
191
- self.graph.add((prop_uri, RDF.type, OWL.ObjectProperty))
192
- self.graph.add((prop_uri, RDFS.label, Literal(label)))
193
-
194
- # Data properties
195
- data_properties = [
196
- (self.DETECTION.severityPercentage, "severity percentage", XSD.float),
197
- (self.DETECTION.numberOfRegions, "number of regions", XSD.integer),
198
- (self.DETECTION.detectionConfidence, "detection confidence", XSD.float),
199
- (self.DETECTION.imageWidth, "image width", XSD.integer),
200
- (self.DETECTION.imageHeight, "image height", XSD.integer),
201
- (self.DETECTION.detectionTimestamp, "detection timestamp", XSD.dateTime),
202
- (self.VISUAL.hueValue, "hue value", XSD.integer),
203
- (self.VISUAL.saturationValue, "saturation value", XSD.integer),
204
- (self.VISUAL.brightnessValue, "brightness value", XSD.integer),
205
- (self.AGRI.marketabilityScore, "marketability score", XSD.float),
206
- ]
207
-
208
- for prop_uri, label, datatype in data_properties:
209
- self.graph.add((prop_uri, RDF.type, OWL.DatatypeProperty))
210
- self.graph.add((prop_uri, RDFS.label, Literal(label)))
211
- self.graph.add((prop_uri, RDFS.range, datatype))
212
-
213
- def _define_severity_levels(self):
214
- """Define severity level instances"""
215
- severity_levels = [
216
- (self.AGRI.Healthy, "Healthy", 0, 2),
217
- (self.AGRI.EarlyDisease, "Early Disease", 2, 8),
218
- (self.AGRI.ModerateDisease, "Moderate Disease", 8, 20),
219
- (self.AGRI.SevereDisease, "Severe Disease", 20, 40),
220
- (self.AGRI.CriticalDisease, "Critical Disease", 40, 100),
221
- ]
222
-
223
- for level_uri, label, min_percent, max_percent in severity_levels:
224
- self.graph.add((level_uri, RDF.type, self.AGRI.SeverityLevel))
225
- self.graph.add((level_uri, RDFS.label, Literal(label)))
226
- self.graph.add((level_uri, self.DETECTION.severityPercentage, Literal(min_percent, datatype=XSD.float)))
227
- self.graph.add((level_uri, self.DETECTION.severityPercentage, Literal(max_percent, datatype=XSD.float)))
228
-
229
- def _define_causal_relationships(self):
230
- """Define disease characteristics and causal relationships"""
231
- # Alternaria characteristics
232
- alternaria_symptoms = [
233
- (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.DarkBrown),
234
- (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Black),
235
- (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
236
- (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Concentric),
237
- ]
238
-
239
- # Anthracnose characteristics
240
- anthracnose_symptoms = [
241
- (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Black),
242
- (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Orange),
243
- (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Pink),
244
- (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Circular),
245
- ]
246
-
247
- # Aspergillus characteristics
248
- aspergillus_symptoms = [
249
- (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Black),
250
- (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Green),
251
- (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Fuzzy),
252
- (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
253
- ]
254
-
255
- # Lasiodiplodia characteristics
256
- lasiodiplodia_symptoms = [
257
- (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.DarkBrown),
258
- (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.Black),
259
- (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
260
- ]
261
-
262
- all_symptoms = alternaria_symptoms + anthracnose_symptoms + aspergillus_symptoms + lasiodiplodia_symptoms
263
-
264
- for subject, predicate, obj in all_symptoms:
265
- self.graph.add((subject, predicate, obj))
266
-
267
- def _define_temporal_aspects(self):
268
- """Define temporal progression of diseases"""
269
- # Disease progression stages
270
- stages = [
271
- (self.DISEASE.EarlyStage, "Early Stage"),
272
- (self.DISEASE.DevelopingStage, "Developing Stage"),
273
- (self.DISEASE.AdvancedStage, "Advanced Stage"),
274
- (self.DISEASE.CriticalStage, "Critical Stage"),
275
- ]
276
-
277
- for stage_uri, label in stages:
278
- self.graph.add((stage_uri, RDF.type, OWL.Class))
279
- self.graph.add((stage_uri, RDFS.label, Literal(label)))
280
- self.graph.add((stage_uri, RDFS.subClassOf, self.DISEASE.Disease))
281
-
282
- def _define_economic_impact(self):
283
- """Define economic impact levels"""
284
- impact_levels = [
285
- (self.AGRI.NoImpact, "No Economic Impact", 100),
286
- (self.AGRI.MinimalImpact, "Minimal Impact", 85),
287
- (self.AGRI.ModerateImpact, "Moderate Impact", 60),
288
- (self.AGRI.SevereImpact, "Severe Impact", 30),
289
- (self.AGRI.CriticalImpact, "Critical Impact", 0),
290
- ]
291
-
292
- for impact_uri, label, marketability in impact_levels:
293
- self.graph.add((impact_uri, RDF.type, self.AGRI.EconomicImpact))
294
- self.graph.add((impact_uri, RDFS.label, Literal(label)))
295
- self.graph.add((impact_uri, self.AGRI.marketabilityScore, Literal(marketability, datatype=XSD.float)))
296
-
297
- def _apply_reasoning(self):
298
- """Apply OWL-RL reasoning to the ontology"""
299
- print("Applying OWL-RL reasoning...")
300
-
301
- # Apply OWL-RL inference rules
302
- owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(self.graph)
303
-
304
- print(f"Ontology size after reasoning: {len(self.graph)} triples")
305
-
306
- def create_detection_instance(self, image_path: str, detection_results: Dict) -> URIRef:
307
- """Create a semantic instance of a disease detection result"""
308
- # Create unique URI for this detection
309
- detection_id = f"detection_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{hash(image_path) % 10000}"
310
- detection_uri = self.DETECTION[detection_id]
311
-
312
- # Add basic detection information
313
- self.graph.add((detection_uri, RDF.type, self.DETECTION.DetectionResult))
314
- self.graph.add((detection_uri, RDFS.label, Literal(f"Detection of {os.path.basename(image_path)}")))
315
- self.graph.add((detection_uri, self.DETECTION.detectionTimestamp,
316
- Literal(datetime.now(), datatype=XSD.dateTime)))
317
-
318
- # Add image properties
319
- if 'image_properties' in detection_results:
320
- props = detection_results['image_properties']
321
- if 'width' in props:
322
- self.graph.add((detection_uri, self.DETECTION.imageWidth,
323
- Literal(props['width'], datatype=XSD.integer)))
324
- if 'height' in props:
325
- self.graph.add((detection_uri, self.DETECTION.imageHeight,
326
- Literal(props['height'], datatype=XSD.integer)))
327
-
328
- # Add detection results
329
- self.graph.add((detection_uri, self.DETECTION.severityPercentage,
330
- Literal(detection_results['severity_percentage'], datatype=XSD.float)))
331
- self.graph.add((detection_uri, self.DETECTION.numberOfRegions,
332
- Literal(detection_results['num_diseased_regions'], datatype=XSD.integer)))
333
-
334
- # Map disease level to semantic class
335
- disease_level = detection_results['disease_level']
336
- severity_uri = self._map_severity_to_uri(disease_level)
337
- if severity_uri:
338
- self.graph.add((detection_uri, self.DETECTION.hasSeverityLevel, severity_uri))
339
-
340
- # Infer likely diseases based on detection patterns
341
- inferred_diseases = self._infer_diseases(detection_results)
342
- for disease_uri in inferred_diseases:
343
- self.graph.add((detection_uri, self.DETECTION.hasDisease, disease_uri))
344
-
345
- # Calculate economic impact
346
- economic_impact = self._calculate_economic_impact(detection_results['severity_percentage'])
347
- self.graph.add((detection_uri, self.AGRI.hasEconomicImpact, economic_impact))
348
-
349
- return detection_uri
350
-
351
- def _map_severity_to_uri(self, disease_level: str) -> Optional[URIRef]:
352
- """Map disease level string to severity URI"""
353
- mapping = {
354
- "Healthy": self.AGRI.Healthy,
355
- "Early Disease": self.AGRI.EarlyDisease,
356
- "Moderate Disease": self.AGRI.ModerateDisease,
357
- "Severe Disease": self.AGRI.SevereDisease,
358
- "Critical Disease": self.AGRI.CriticalDisease,
359
- }
360
- return mapping.get(disease_level)
361
-
362
- def _infer_diseases(self, detection_results: Dict) -> List[URIRef]:
363
- """Infer likely diseases based on detection characteristics"""
364
- inferred = []
365
- severity = detection_results['severity_percentage']
366
-
367
- # Simple inference based on severity and patterns
368
- # In a real system, this would use more sophisticated visual analysis
369
- if severity > 5: # If disease detected
370
- # For demonstration, we'll use basic heuristics
371
- # In practice, this would analyze color, texture, shape patterns
372
- if severity < 15:
373
- # Early stage diseases - could be multiple
374
- inferred.extend([self.DISEASE.Alternaria, self.DISEASE.Anthracnose])
375
- elif severity < 30:
376
- # Moderate stage - more specific inference needed
377
- inferred.append(self.DISEASE.Anthracnose)
378
- else:
379
- # Severe cases - possibly aggressive diseases
380
- inferred.extend([self.DISEASE.Aspergillus, self.DISEASE.Lasiodiplodia])
381
-
382
- return inferred
383
-
384
- def _calculate_economic_impact(self, severity: float) -> URIRef:
385
- """Calculate economic impact based on severity"""
386
- if severity < 2:
387
- return self.AGRI.NoImpact
388
- elif severity < 8:
389
- return self.AGRI.MinimalImpact
390
- elif severity < 20:
391
- return self.AGRI.ModerateImpact
392
- elif severity < 40:
393
- return self.AGRI.SevereImpact
394
- else:
395
- return self.AGRI.CriticalImpact
396
-
397
- def process_image_with_semantics(self, image_path: str) -> Dict[str, Any]:
398
- """Process image with disease detection and create semantic annotations"""
399
- print(f"Processing image with semantic analysis: {image_path}")
400
-
401
- # Run disease detection
402
- detection_results = self.detector.process_image(image_path)
403
-
404
- # Add image properties
405
- image = cv2.imread(image_path)
406
- if image is not None:
407
- detection_results['image_properties'] = {
408
- 'width': image.shape[1],
409
- 'height': image.shape[0],
410
- 'channels': image.shape[2] if len(image.shape) > 2 else 1
411
- }
412
-
413
- # Create semantic instance
414
- detection_uri = self.create_detection_instance(image_path, detection_results)
415
-
416
- # Query related semantic information
417
- semantic_info = self.query_detection_semantics(detection_uri)
418
-
419
- # Combine results
420
- enhanced_results = {
421
- **detection_results,
422
- 'semantic_uri': str(detection_uri),
423
- 'semantic_info': semantic_info,
424
- 'ontology_inferences': self._get_ontology_inferences(detection_uri)
425
- }
426
-
427
- return enhanced_results
428
-
429
- def query_detection_semantics(self, detection_uri: URIRef) -> Dict[str, Any]:
430
- """Query semantic information about a detection"""
431
- semantic_info = {
432
- 'diseases': [],
433
- 'severity_level': None,
434
- 'economic_impact': None,
435
- 'symptoms': [],
436
- 'recommendations': []
437
- }
438
-
439
- # Query diseases
440
- query = f"""
441
- PREFIX detection: <{self.DETECTION}>
442
- PREFIX disease: <{self.DISEASE}>
443
- PREFIX rdfs: <{RDFS}>
444
-
445
- SELECT ?disease ?diseaseLabel WHERE {{
446
- <{detection_uri}> detection:hasDisease ?disease .
447
- ?disease rdfs:label ?diseaseLabel .
448
- }}
449
- """
450
-
451
- for row in self.graph.query(query):
452
- semantic_info['diseases'].append({
453
- 'uri': str(row.disease),
454
- 'label': str(row.diseaseLabel)
455
- })
456
-
457
- # Query severity level
458
- query = f"""
459
- PREFIX detection: <{self.DETECTION}>
460
- PREFIX agri: <{self.AGRI}>
461
- PREFIX rdfs: <{RDFS}>
462
-
463
- SELECT ?severityLevel ?severityLabel WHERE {{
464
- <{detection_uri}> detection:hasSeverityLevel ?severityLevel .
465
- ?severityLevel rdfs:label ?severityLabel .
466
- }}
467
- """
468
-
469
- for row in self.graph.query(query):
470
- semantic_info['severity_level'] = {
471
- 'uri': str(row.severityLevel),
472
- 'label': str(row.severityLabel)
473
- }
474
- break
475
-
476
- # Query economic impact
477
- query = f"""
478
- PREFIX agri: <{self.AGRI}>
479
- PREFIX rdfs: <{RDFS}>
480
-
481
- SELECT ?impact ?impactLabel ?marketability WHERE {{
482
- <{detection_uri}> agri:hasEconomicImpact ?impact .
483
- ?impact rdfs:label ?impactLabel .
484
- ?impact agri:marketabilityScore ?marketability .
485
- }}
486
- """
487
-
488
- for row in self.graph.query(query):
489
- semantic_info['economic_impact'] = {
490
- 'uri': str(row.impact),
491
- 'label': str(row.impactLabel),
492
- 'marketability_score': float(row.marketability)
493
- }
494
- break
495
-
496
- return semantic_info
497
-
498
- def _get_ontology_inferences(self, detection_uri: URIRef) -> List[str]:
499
- """Get ontology-based inferences and recommendations"""
500
- inferences = []
501
-
502
- # Query for related information using SPARQL
503
- query = f"""
504
- PREFIX detection: <{self.DETECTION}>
505
- PREFIX disease: <{self.DISEASE}>
506
- PREFIX visual: <{self.VISUAL}>
507
- PREFIX rdfs: <{RDFS}>
508
-
509
- SELECT ?disease ?symptom ?symptomLabel WHERE {{
510
- <{detection_uri}> detection:hasDisease ?disease .
511
- ?disease detection:hasSymptom ?symptom .
512
- ?symptom rdfs:label ?symptomLabel .
513
- }}
514
- """
515
-
516
- symptoms = []
517
- for row in self.graph.query(query):
518
- symptoms.append(str(row.symptomLabel))
519
-
520
- if symptoms:
521
- inferences.append(f"Detected visual symptoms: {', '.join(symptoms)}")
522
-
523
- # Add treatment recommendations based on ontology
524
- inferences.extend(self._get_treatment_recommendations(detection_uri))
525
-
526
- return inferences
527
-
528
- def _get_treatment_recommendations(self, detection_uri: URIRef) -> List[str]:
529
- """Get treatment recommendations based on detected diseases"""
530
- recommendations = []
531
-
532
- # Query detected diseases
533
- query = f"""
534
- PREFIX detection: <{self.DETECTION}>
535
- PREFIX disease: <{self.DISEASE}>
536
- PREFIX rdfs: <{RDFS}>
537
-
538
- SELECT ?disease ?diseaseLabel WHERE {{
539
- <{detection_uri}> detection:hasDisease ?disease .
540
- ?disease rdfs:label ?diseaseLabel .
541
- }}
542
- """
543
-
544
- disease_labels = []
545
- for row in self.graph.query(query):
546
- disease_labels.append(str(row.diseaseLabel))
547
-
548
- # Provide recommendations based on diseases
549
- if "Alternaria" in disease_labels:
550
- recommendations.append("Apply copper-based fungicide for Alternaria control")
551
- recommendations.append("Improve air circulation and reduce humidity")
552
-
553
- if "Anthracnose" in disease_labels:
554
- recommendations.append("Use preventive fungicide sprays for Anthracnose")
555
- recommendations.append("Remove infected fruits and debris")
556
-
557
- if "Aspergillus" in disease_labels:
558
- recommendations.append("Improve storage conditions to prevent Aspergillus")
559
- recommendations.append("Reduce moisture and temperature in storage")
560
-
561
- if "Lasiodiplodia" in disease_labels:
562
- recommendations.append("Improve field sanitation for Lasiodiplodia control")
563
- recommendations.append("Avoid mechanical damage during harvest")
564
-
565
- return recommendations
566
-
567
- def export_ontology(self, output_path: str, format: str = "turtle"):
568
- """Export the ontology to a file"""
569
- print(f"Exporting ontology to {output_path} in {format} format...")
570
-
571
- with open(output_path, 'w', encoding='utf-8') as f:
572
- f.write(self.graph.serialize(format=format))
573
-
574
- print(f"Ontology exported successfully!")
575
-
576
- def get_ontology_statistics(self) -> Dict[str, int]:
577
- """Get statistics about the ontology"""
578
- stats = {
579
- 'total_triples': len(self.graph),
580
- 'classes': len(list(self.graph.subjects(RDF.type, OWL.Class))),
581
- 'object_properties': len(list(self.graph.subjects(RDF.type, OWL.ObjectProperty))),
582
- 'datatype_properties': len(list(self.graph.subjects(RDF.type, OWL.DatatypeProperty))),
583
- 'individuals': len(list(self.graph.subjects(RDF.type, self.DETECTION.DetectionResult))),
584
- }
585
- return stats
586
-
587
- def query_ontology(self, sparql_query: str) -> List[Dict]:
588
- """Execute a SPARQL query on the ontology"""
589
- results = []
590
- for row in self.graph.query(sparql_query):
591
- result_dict = {}
592
- for var in row.labels:
593
- result_dict[var] = str(row[var])
594
- results.append(result_dict)
595
- return results
596
-
597
- def demonstrate_semantic_detection():
598
- """Demonstrate the semantic mango disease detection system"""
599
- print("=" * 80)
600
- print("SEMANTIC WEB ONTOLOGY FOR MANGO DISEASE DETECTION")
601
- print("=" * 80)
602
- print("Features:")
603
- print("- OWL-RL reasoning for enhanced disease inference")
604
- print("- Semantic annotation of detection results")
605
- print("- Economic impact assessment")
606
- print("- Treatment recommendations")
607
- print("- SPARQL queries for knowledge discovery")
608
- print()
609
-
610
- # Initialize semantic system
611
- print("Initializing semantic ontology manager...")
612
- ontology_manager = MangoOntologyManager()
613
-
614
- # Show ontology statistics
615
- stats = ontology_manager.get_ontology_statistics()
616
- print(f"Ontology Statistics:")
617
- for key, value in stats.items():
618
- print(f" {key.replace('_', ' ').title()}: {value}")
619
- print()
620
-
621
- return ontology_manager
622
-
623
- if __name__ == "__main__":
624
- # Demonstrate the system
625
  demonstrate_semantic_detection()
 
1
+ """
2
+ Mango Disease Detection Semantic Web Ontology
3
+ Integrates OWL-RL reasoning with computer vision disease detection
4
+ """
5
+
6
+ import os
7
+ import json
8
+ from datetime import datetime
9
+ from typing import Dict, List, Tuple, Optional, Any
10
+ import cv2
11
+ import numpy as np
12
+
13
+ # RDF and OWL libraries
14
+ from rdflib import Graph, Namespace, Literal, URIRef, BNode
15
+ from rdflib.namespace import RDF, RDFS, OWL, XSD
16
+ import owlrl
17
+
18
+ # Import our disease detection algorithm
19
+ from src/app import FruitDiseaseDetector
20
+
21
+ class MangoOntologyManager:
22
+ """
23
+ Semantic Web Ontology Manager for Mango Disease Detection
24
+ Uses OWL-RL reasoning to enhance disease detection with domain knowledge
25
+ """
26
+
27
+ def __init__(self):
28
+ # Initialize RDF graph and namespaces
29
+ self.graph = Graph()
30
+
31
+ # Define namespaces for our ontology
32
+ self.MANGO = Namespace("http://spotradar.org/mango-disease#")
33
+ self.DISEASE = Namespace("http://spotradar.org/disease#")
34
+ self.DETECTION = Namespace("http://spotradar.org/detection#")
35
+ self.VISUAL = Namespace("http://spotradar.org/visual#")
36
+ self.AGRI = Namespace("http://spotradar.org/agriculture#")
37
+
38
+ # Bind namespaces to graph
39
+ self.graph.bind("mango", self.MANGO)
40
+ self.graph.bind("disease", self.DISEASE)
41
+ self.graph.bind("detection", self.DETECTION)
42
+ self.graph.bind("visual", self.VISUAL)
43
+ self.graph.bind("agri", self.AGRI)
44
+ self.graph.bind("owl", OWL)
45
+ self.graph.bind("rdfs", RDFS)
46
+
47
+ # Initialize disease detector
48
+ self.detector = FruitDiseaseDetector()
49
+
50
+ # Build the ontology
51
+ self._build_ontology()
52
+
53
+ # Apply OWL-RL reasoning
54
+ self._apply_reasoning()
55
+
56
+ def _build_ontology(self):
57
+ """Build the complete mango disease ontology"""
58
+ print("Building mango disease ontology...")
59
+
60
+ # 1. Define top-level classes
61
+ self._define_core_classes()
62
+
63
+ # 2. Define mango disease classes
64
+ self._define_disease_classes()
65
+
66
+ # 3. Define visual characteristics
67
+ self._define_visual_properties()
68
+
69
+ # 4. Define detection properties
70
+ self._define_detection_properties()
71
+
72
+ # 5. Define severity levels
73
+ self._define_severity_levels()
74
+
75
+ # 6. Define causal relationships
76
+ self._define_causal_relationships()
77
+
78
+ # 7. Define temporal aspects
79
+ self._define_temporal_aspects()
80
+
81
+ # 8. Define economic impact
82
+ self._define_economic_impact()
83
+
84
+ print("Ontology structure built successfully!")
85
+
86
+ def _define_core_classes(self):
87
+ """Define fundamental classes in the ontology"""
88
+ # Core classes
89
+ classes = [
90
+ (self.MANGO.Fruit, "Fruit"),
91
+ (self.MANGO.MangoFruit, "Mango Fruit"),
92
+ (self.DISEASE.Disease, "Disease"),
93
+ (self.DISEASE.FungalDisease, "Fungal Disease"),
94
+ (self.DISEASE.BacterialDisease, "Bacterial Disease"),
95
+ (self.VISUAL.VisualCharacteristic, "Visual Characteristic"),
96
+ (self.VISUAL.ColorCharacteristic, "Color Characteristic"),
97
+ (self.VISUAL.TextureCharacteristic, "Texture Characteristic"),
98
+ (self.VISUAL.ShapeCharacteristic, "Shape Characteristic"),
99
+ (self.DETECTION.DetectionResult, "Detection Result"),
100
+ (self.DETECTION.ImageAnalysis, "Image Analysis"),
101
+ (self.AGRI.SeverityLevel, "Severity Level"),
102
+ (self.AGRI.EconomicImpact, "Economic Impact"),
103
+ ]
104
+
105
+ for class_uri, label in classes:
106
+ self.graph.add((class_uri, RDF.type, OWL.Class))
107
+ self.graph.add((class_uri, RDFS.label, Literal(label)))
108
+
109
+ def _define_disease_classes(self):
110
+ """Define specific mango disease classes"""
111
+ # Mango is a subclass of Fruit
112
+ self.graph.add((self.MANGO.MangoFruit, RDFS.subClassOf, self.MANGO.Fruit))
113
+
114
+ # Disease taxonomy
115
+ self.graph.add((self.DISEASE.FungalDisease, RDFS.subClassOf, self.DISEASE.Disease))
116
+ self.graph.add((self.DISEASE.BacterialDisease, RDFS.subClassOf, self.DISEASE.Disease))
117
+
118
+ # Specific mango diseases
119
+ diseases = [
120
+ (self.DISEASE.Alternaria, "Alternaria", self.DISEASE.FungalDisease),
121
+ (self.DISEASE.Anthracnose, "Anthracnose", self.DISEASE.FungalDisease),
122
+ (self.DISEASE.Aspergillus, "Aspergillus (Black Mould Rot)", self.DISEASE.FungalDisease),
123
+ (self.DISEASE.Lasiodiplodia, "Lasiodiplodia (Stem and Rot)", self.DISEASE.FungalDisease),
124
+ ]
125
+
126
+ for disease_uri, label, parent_class in diseases:
127
+ self.graph.add((disease_uri, RDF.type, OWL.Class))
128
+ self.graph.add((disease_uri, RDFS.label, Literal(label)))
129
+ self.graph.add((disease_uri, RDFS.subClassOf, parent_class))
130
+
131
+ def _define_visual_properties(self):
132
+ """Define visual characteristics and properties"""
133
+ # Color properties
134
+ color_chars = [
135
+ (self.VISUAL.DarkBrown, "Dark Brown Color"),
136
+ (self.VISUAL.Black, "Black Color"),
137
+ (self.VISUAL.Orange, "Orange Color"),
138
+ (self.VISUAL.Pink, "Pink Color"),
139
+ (self.VISUAL.Green, "Green Color"),
140
+ (self.VISUAL.Yellow, "Yellow Color"),
141
+ (self.VISUAL.Red, "Red Color"),
142
+ ]
143
+
144
+ for color_uri, label in color_chars:
145
+ self.graph.add((color_uri, RDF.type, OWL.Class))
146
+ self.graph.add((color_uri, RDFS.label, Literal(label)))
147
+ self.graph.add((color_uri, RDFS.subClassOf, self.VISUAL.ColorCharacteristic))
148
+
149
+ # Texture properties
150
+ texture_chars = [
151
+ (self.VISUAL.Smooth, "Smooth Texture"),
152
+ (self.VISUAL.Rough, "Rough Texture"),
153
+ (self.VISUAL.Fuzzy, "Fuzzy Texture"),
154
+ (self.VISUAL.Irregular, "Irregular Texture"),
155
+ (self.VISUAL.Concentric, "Concentric Pattern"),
156
+ ]
157
+
158
+ for texture_uri, label in texture_chars:
159
+ self.graph.add((texture_uri, RDF.type, OWL.Class))
160
+ self.graph.add((texture_uri, RDFS.label, Literal(label)))
161
+ self.graph.add((texture_uri, RDFS.subClassOf, self.VISUAL.TextureCharacteristic))
162
+
163
+ # Shape properties
164
+ shape_chars = [
165
+ (self.VISUAL.Circular, "Circular Shape"),
166
+ (self.VISUAL.Irregular, "Irregular Shape"),
167
+ (self.VISUAL.Oval, "Oval Shape"),
168
+ (self.VISUAL.Elongated, "Elongated Shape"),
169
+ ]
170
+
171
+ for shape_uri, label in shape_chars:
172
+ self.graph.add((shape_uri, RDF.type, OWL.Class))
173
+ self.graph.add((shape_uri, RDFS.label, Literal(label)))
174
+ self.graph.add((shape_uri, RDFS.subClassOf, self.VISUAL.ShapeCharacteristic))
175
+
176
+ def _define_detection_properties(self):
177
+ """Define object and data properties for detection"""
178
+ # Object properties
179
+ properties = [
180
+ (self.DETECTION.hasDisease, "has disease"),
181
+ (self.DETECTION.hasVisualCharacteristic, "has visual characteristic"),
182
+ (self.DETECTION.hasSeverityLevel, "has severity level"),
183
+ (self.DETECTION.detectedIn, "detected in"),
184
+ (self.DETECTION.causedBy, "caused by"),
185
+ (self.DETECTION.affects, "affects"),
186
+ (self.DETECTION.hasSymptom, "has symptom"),
187
+ (self.AGRI.hasEconomicImpact, "has economic impact"),
188
+ ]
189
+
190
+ for prop_uri, label in properties:
191
+ self.graph.add((prop_uri, RDF.type, OWL.ObjectProperty))
192
+ self.graph.add((prop_uri, RDFS.label, Literal(label)))
193
+
194
+ # Data properties
195
+ data_properties = [
196
+ (self.DETECTION.severityPercentage, "severity percentage", XSD.float),
197
+ (self.DETECTION.numberOfRegions, "number of regions", XSD.integer),
198
+ (self.DETECTION.detectionConfidence, "detection confidence", XSD.float),
199
+ (self.DETECTION.imageWidth, "image width", XSD.integer),
200
+ (self.DETECTION.imageHeight, "image height", XSD.integer),
201
+ (self.DETECTION.detectionTimestamp, "detection timestamp", XSD.dateTime),
202
+ (self.VISUAL.hueValue, "hue value", XSD.integer),
203
+ (self.VISUAL.saturationValue, "saturation value", XSD.integer),
204
+ (self.VISUAL.brightnessValue, "brightness value", XSD.integer),
205
+ (self.AGRI.marketabilityScore, "marketability score", XSD.float),
206
+ ]
207
+
208
+ for prop_uri, label, datatype in data_properties:
209
+ self.graph.add((prop_uri, RDF.type, OWL.DatatypeProperty))
210
+ self.graph.add((prop_uri, RDFS.label, Literal(label)))
211
+ self.graph.add((prop_uri, RDFS.range, datatype))
212
+
213
+ def _define_severity_levels(self):
214
+ """Define severity level instances"""
215
+ severity_levels = [
216
+ (self.AGRI.Healthy, "Healthy", 0, 2),
217
+ (self.AGRI.EarlyDisease, "Early Disease", 2, 8),
218
+ (self.AGRI.ModerateDisease, "Moderate Disease", 8, 20),
219
+ (self.AGRI.SevereDisease, "Severe Disease", 20, 40),
220
+ (self.AGRI.CriticalDisease, "Critical Disease", 40, 100),
221
+ ]
222
+
223
+ for level_uri, label, min_percent, max_percent in severity_levels:
224
+ self.graph.add((level_uri, RDF.type, self.AGRI.SeverityLevel))
225
+ self.graph.add((level_uri, RDFS.label, Literal(label)))
226
+ self.graph.add((level_uri, self.DETECTION.severityPercentage, Literal(min_percent, datatype=XSD.float)))
227
+ self.graph.add((level_uri, self.DETECTION.severityPercentage, Literal(max_percent, datatype=XSD.float)))
228
+
229
+ def _define_causal_relationships(self):
230
+ """Define disease characteristics and causal relationships"""
231
+ # Alternaria characteristics
232
+ alternaria_symptoms = [
233
+ (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.DarkBrown),
234
+ (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Black),
235
+ (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
236
+ (self.DISEASE.Alternaria, self.DETECTION.hasSymptom, self.VISUAL.Concentric),
237
+ ]
238
+
239
+ # Anthracnose characteristics
240
+ anthracnose_symptoms = [
241
+ (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Black),
242
+ (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Orange),
243
+ (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Pink),
244
+ (self.DISEASE.Anthracnose, self.DETECTION.hasSymptom, self.VISUAL.Circular),
245
+ ]
246
+
247
+ # Aspergillus characteristics
248
+ aspergillus_symptoms = [
249
+ (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Black),
250
+ (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Green),
251
+ (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Fuzzy),
252
+ (self.DISEASE.Aspergillus, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
253
+ ]
254
+
255
+ # Lasiodiplodia characteristics
256
+ lasiodiplodia_symptoms = [
257
+ (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.DarkBrown),
258
+ (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.Black),
259
+ (self.DISEASE.Lasiodiplodia, self.DETECTION.hasSymptom, self.VISUAL.Irregular),
260
+ ]
261
+
262
+ all_symptoms = alternaria_symptoms + anthracnose_symptoms + aspergillus_symptoms + lasiodiplodia_symptoms
263
+
264
+ for subject, predicate, obj in all_symptoms:
265
+ self.graph.add((subject, predicate, obj))
266
+
267
+ def _define_temporal_aspects(self):
268
+ """Define temporal progression of diseases"""
269
+ # Disease progression stages
270
+ stages = [
271
+ (self.DISEASE.EarlyStage, "Early Stage"),
272
+ (self.DISEASE.DevelopingStage, "Developing Stage"),
273
+ (self.DISEASE.AdvancedStage, "Advanced Stage"),
274
+ (self.DISEASE.CriticalStage, "Critical Stage"),
275
+ ]
276
+
277
+ for stage_uri, label in stages:
278
+ self.graph.add((stage_uri, RDF.type, OWL.Class))
279
+ self.graph.add((stage_uri, RDFS.label, Literal(label)))
280
+ self.graph.add((stage_uri, RDFS.subClassOf, self.DISEASE.Disease))
281
+
282
+ def _define_economic_impact(self):
283
+ """Define economic impact levels"""
284
+ impact_levels = [
285
+ (self.AGRI.NoImpact, "No Economic Impact", 100),
286
+ (self.AGRI.MinimalImpact, "Minimal Impact", 85),
287
+ (self.AGRI.ModerateImpact, "Moderate Impact", 60),
288
+ (self.AGRI.SevereImpact, "Severe Impact", 30),
289
+ (self.AGRI.CriticalImpact, "Critical Impact", 0),
290
+ ]
291
+
292
+ for impact_uri, label, marketability in impact_levels:
293
+ self.graph.add((impact_uri, RDF.type, self.AGRI.EconomicImpact))
294
+ self.graph.add((impact_uri, RDFS.label, Literal(label)))
295
+ self.graph.add((impact_uri, self.AGRI.marketabilityScore, Literal(marketability, datatype=XSD.float)))
296
+
297
+ def _apply_reasoning(self):
298
+ """Apply OWL-RL reasoning to the ontology"""
299
+ print("Applying OWL-RL reasoning...")
300
+
301
+ # Apply OWL-RL inference rules
302
+ owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(self.graph)
303
+
304
+ print(f"Ontology size after reasoning: {len(self.graph)} triples")
305
+
306
+ def create_detection_instance(self, image_path: str, detection_results: Dict) -> URIRef:
307
+ """Create a semantic instance of a disease detection result"""
308
+ # Create unique URI for this detection
309
+ detection_id = f"detection_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{hash(image_path) % 10000}"
310
+ detection_uri = self.DETECTION[detection_id]
311
+
312
+ # Add basic detection information
313
+ self.graph.add((detection_uri, RDF.type, self.DETECTION.DetectionResult))
314
+ self.graph.add((detection_uri, RDFS.label, Literal(f"Detection of {os.path.basename(image_path)}")))
315
+ self.graph.add((detection_uri, self.DETECTION.detectionTimestamp,
316
+ Literal(datetime.now(), datatype=XSD.dateTime)))
317
+
318
+ # Add image properties
319
+ if 'image_properties' in detection_results:
320
+ props = detection_results['image_properties']
321
+ if 'width' in props:
322
+ self.graph.add((detection_uri, self.DETECTION.imageWidth,
323
+ Literal(props['width'], datatype=XSD.integer)))
324
+ if 'height' in props:
325
+ self.graph.add((detection_uri, self.DETECTION.imageHeight,
326
+ Literal(props['height'], datatype=XSD.integer)))
327
+
328
+ # Add detection results
329
+ self.graph.add((detection_uri, self.DETECTION.severityPercentage,
330
+ Literal(detection_results['severity_percentage'], datatype=XSD.float)))
331
+ self.graph.add((detection_uri, self.DETECTION.numberOfRegions,
332
+ Literal(detection_results['num_diseased_regions'], datatype=XSD.integer)))
333
+
334
+ # Map disease level to semantic class
335
+ disease_level = detection_results['disease_level']
336
+ severity_uri = self._map_severity_to_uri(disease_level)
337
+ if severity_uri:
338
+ self.graph.add((detection_uri, self.DETECTION.hasSeverityLevel, severity_uri))
339
+
340
+ # Infer likely diseases based on detection patterns
341
+ inferred_diseases = self._infer_diseases(detection_results)
342
+ for disease_uri in inferred_diseases:
343
+ self.graph.add((detection_uri, self.DETECTION.hasDisease, disease_uri))
344
+
345
+ # Calculate economic impact
346
+ economic_impact = self._calculate_economic_impact(detection_results['severity_percentage'])
347
+ self.graph.add((detection_uri, self.AGRI.hasEconomicImpact, economic_impact))
348
+
349
+ return detection_uri
350
+
351
+ def _map_severity_to_uri(self, disease_level: str) -> Optional[URIRef]:
352
+ """Map disease level string to severity URI"""
353
+ mapping = {
354
+ "Healthy": self.AGRI.Healthy,
355
+ "Early Disease": self.AGRI.EarlyDisease,
356
+ "Moderate Disease": self.AGRI.ModerateDisease,
357
+ "Severe Disease": self.AGRI.SevereDisease,
358
+ "Critical Disease": self.AGRI.CriticalDisease,
359
+ }
360
+ return mapping.get(disease_level)
361
+
362
+ def _infer_diseases(self, detection_results: Dict) -> List[URIRef]:
363
+ """Infer likely diseases based on detection characteristics"""
364
+ inferred = []
365
+ severity = detection_results['severity_percentage']
366
+
367
+ # Simple inference based on severity and patterns
368
+ # In a real system, this would use more sophisticated visual analysis
369
+ if severity > 5: # If disease detected
370
+ # For demonstration, we'll use basic heuristics
371
+ # In practice, this would analyze color, texture, shape patterns
372
+ if severity < 15:
373
+ # Early stage diseases - could be multiple
374
+ inferred.extend([self.DISEASE.Alternaria, self.DISEASE.Anthracnose])
375
+ elif severity < 30:
376
+ # Moderate stage - more specific inference needed
377
+ inferred.append(self.DISEASE.Anthracnose)
378
+ else:
379
+ # Severe cases - possibly aggressive diseases
380
+ inferred.extend([self.DISEASE.Aspergillus, self.DISEASE.Lasiodiplodia])
381
+
382
+ return inferred
383
+
384
+ def _calculate_economic_impact(self, severity: float) -> URIRef:
385
+ """Calculate economic impact based on severity"""
386
+ if severity < 2:
387
+ return self.AGRI.NoImpact
388
+ elif severity < 8:
389
+ return self.AGRI.MinimalImpact
390
+ elif severity < 20:
391
+ return self.AGRI.ModerateImpact
392
+ elif severity < 40:
393
+ return self.AGRI.SevereImpact
394
+ else:
395
+ return self.AGRI.CriticalImpact
396
+
397
+ def process_image_with_semantics(self, image_path: str) -> Dict[str, Any]:
398
+ """Process image with disease detection and create semantic annotations"""
399
+ print(f"Processing image with semantic analysis: {image_path}")
400
+
401
+ # Run disease detection
402
+ detection_results = self.detector.process_image(image_path)
403
+
404
+ # Add image properties
405
+ image = cv2.imread(image_path)
406
+ if image is not None:
407
+ detection_results['image_properties'] = {
408
+ 'width': image.shape[1],
409
+ 'height': image.shape[0],
410
+ 'channels': image.shape[2] if len(image.shape) > 2 else 1
411
+ }
412
+
413
+ # Create semantic instance
414
+ detection_uri = self.create_detection_instance(image_path, detection_results)
415
+
416
+ # Query related semantic information
417
+ semantic_info = self.query_detection_semantics(detection_uri)
418
+
419
+ # Combine results
420
+ enhanced_results = {
421
+ **detection_results,
422
+ 'semantic_uri': str(detection_uri),
423
+ 'semantic_info': semantic_info,
424
+ 'ontology_inferences': self._get_ontology_inferences(detection_uri)
425
+ }
426
+
427
+ return enhanced_results
428
+
429
+ def query_detection_semantics(self, detection_uri: URIRef) -> Dict[str, Any]:
430
+ """Query semantic information about a detection"""
431
+ semantic_info = {
432
+ 'diseases': [],
433
+ 'severity_level': None,
434
+ 'economic_impact': None,
435
+ 'symptoms': [],
436
+ 'recommendations': []
437
+ }
438
+
439
+ # Query diseases
440
+ query = f"""
441
+ PREFIX detection: <{self.DETECTION}>
442
+ PREFIX disease: <{self.DISEASE}>
443
+ PREFIX rdfs: <{RDFS}>
444
+
445
+ SELECT ?disease ?diseaseLabel WHERE {{
446
+ <{detection_uri}> detection:hasDisease ?disease .
447
+ ?disease rdfs:label ?diseaseLabel .
448
+ }}
449
+ """
450
+
451
+ for row in self.graph.query(query):
452
+ semantic_info['diseases'].append({
453
+ 'uri': str(row.disease),
454
+ 'label': str(row.diseaseLabel)
455
+ })
456
+
457
+ # Query severity level
458
+ query = f"""
459
+ PREFIX detection: <{self.DETECTION}>
460
+ PREFIX agri: <{self.AGRI}>
461
+ PREFIX rdfs: <{RDFS}>
462
+
463
+ SELECT ?severityLevel ?severityLabel WHERE {{
464
+ <{detection_uri}> detection:hasSeverityLevel ?severityLevel .
465
+ ?severityLevel rdfs:label ?severityLabel .
466
+ }}
467
+ """
468
+
469
+ for row in self.graph.query(query):
470
+ semantic_info['severity_level'] = {
471
+ 'uri': str(row.severityLevel),
472
+ 'label': str(row.severityLabel)
473
+ }
474
+ break
475
+
476
+ # Query economic impact
477
+ query = f"""
478
+ PREFIX agri: <{self.AGRI}>
479
+ PREFIX rdfs: <{RDFS}>
480
+
481
+ SELECT ?impact ?impactLabel ?marketability WHERE {{
482
+ <{detection_uri}> agri:hasEconomicImpact ?impact .
483
+ ?impact rdfs:label ?impactLabel .
484
+ ?impact agri:marketabilityScore ?marketability .
485
+ }}
486
+ """
487
+
488
+ for row in self.graph.query(query):
489
+ semantic_info['economic_impact'] = {
490
+ 'uri': str(row.impact),
491
+ 'label': str(row.impactLabel),
492
+ 'marketability_score': float(row.marketability)
493
+ }
494
+ break
495
+
496
+ return semantic_info
497
+
498
+ def _get_ontology_inferences(self, detection_uri: URIRef) -> List[str]:
499
+ """Get ontology-based inferences and recommendations"""
500
+ inferences = []
501
+
502
+ # Query for related information using SPARQL
503
+ query = f"""
504
+ PREFIX detection: <{self.DETECTION}>
505
+ PREFIX disease: <{self.DISEASE}>
506
+ PREFIX visual: <{self.VISUAL}>
507
+ PREFIX rdfs: <{RDFS}>
508
+
509
+ SELECT ?disease ?symptom ?symptomLabel WHERE {{
510
+ <{detection_uri}> detection:hasDisease ?disease .
511
+ ?disease detection:hasSymptom ?symptom .
512
+ ?symptom rdfs:label ?symptomLabel .
513
+ }}
514
+ """
515
+
516
+ symptoms = []
517
+ for row in self.graph.query(query):
518
+ symptoms.append(str(row.symptomLabel))
519
+
520
+ if symptoms:
521
+ inferences.append(f"Detected visual symptoms: {', '.join(symptoms)}")
522
+
523
+ # Add treatment recommendations based on ontology
524
+ inferences.extend(self._get_treatment_recommendations(detection_uri))
525
+
526
+ return inferences
527
+
528
+ def _get_treatment_recommendations(self, detection_uri: URIRef) -> List[str]:
529
+ """Get treatment recommendations based on detected diseases"""
530
+ recommendations = []
531
+
532
+ # Query detected diseases
533
+ query = f"""
534
+ PREFIX detection: <{self.DETECTION}>
535
+ PREFIX disease: <{self.DISEASE}>
536
+ PREFIX rdfs: <{RDFS}>
537
+
538
+ SELECT ?disease ?diseaseLabel WHERE {{
539
+ <{detection_uri}> detection:hasDisease ?disease .
540
+ ?disease rdfs:label ?diseaseLabel .
541
+ }}
542
+ """
543
+
544
+ disease_labels = []
545
+ for row in self.graph.query(query):
546
+ disease_labels.append(str(row.diseaseLabel))
547
+
548
+ # Provide recommendations based on diseases
549
+ if "Alternaria" in disease_labels:
550
+ recommendations.append("Apply copper-based fungicide for Alternaria control")
551
+ recommendations.append("Improve air circulation and reduce humidity")
552
+
553
+ if "Anthracnose" in disease_labels:
554
+ recommendations.append("Use preventive fungicide sprays for Anthracnose")
555
+ recommendations.append("Remove infected fruits and debris")
556
+
557
+ if "Aspergillus" in disease_labels:
558
+ recommendations.append("Improve storage conditions to prevent Aspergillus")
559
+ recommendations.append("Reduce moisture and temperature in storage")
560
+
561
+ if "Lasiodiplodia" in disease_labels:
562
+ recommendations.append("Improve field sanitation for Lasiodiplodia control")
563
+ recommendations.append("Avoid mechanical damage during harvest")
564
+
565
+ return recommendations
566
+
567
+ def export_ontology(self, output_path: str, format: str = "turtle"):
568
+ """Export the ontology to a file"""
569
+ print(f"Exporting ontology to {output_path} in {format} format...")
570
+
571
+ with open(output_path, 'w', encoding='utf-8') as f:
572
+ f.write(self.graph.serialize(format=format))
573
+
574
+ print(f"Ontology exported successfully!")
575
+
576
+ def get_ontology_statistics(self) -> Dict[str, int]:
577
+ """Get statistics about the ontology"""
578
+ stats = {
579
+ 'total_triples': len(self.graph),
580
+ 'classes': len(list(self.graph.subjects(RDF.type, OWL.Class))),
581
+ 'object_properties': len(list(self.graph.subjects(RDF.type, OWL.ObjectProperty))),
582
+ 'datatype_properties': len(list(self.graph.subjects(RDF.type, OWL.DatatypeProperty))),
583
+ 'individuals': len(list(self.graph.subjects(RDF.type, self.DETECTION.DetectionResult))),
584
+ }
585
+ return stats
586
+
587
+ def query_ontology(self, sparql_query: str) -> List[Dict]:
588
+ """Execute a SPARQL query on the ontology"""
589
+ results = []
590
+ for row in self.graph.query(sparql_query):
591
+ result_dict = {}
592
+ for var in row.labels:
593
+ result_dict[var] = str(row[var])
594
+ results.append(result_dict)
595
+ return results
596
+
597
+ def demonstrate_semantic_detection():
598
+ """Demonstrate the semantic mango disease detection system"""
599
+ print("=" * 80)
600
+ print("SEMANTIC WEB ONTOLOGY FOR MANGO DISEASE DETECTION")
601
+ print("=" * 80)
602
+ print("Features:")
603
+ print("- OWL-RL reasoning for enhanced disease inference")
604
+ print("- Semantic annotation of detection results")
605
+ print("- Economic impact assessment")
606
+ print("- Treatment recommendations")
607
+ print("- SPARQL queries for knowledge discovery")
608
+ print()
609
+
610
+ # Initialize semantic system
611
+ print("Initializing semantic ontology manager...")
612
+ ontology_manager = MangoOntologyManager()
613
+
614
+ # Show ontology statistics
615
+ stats = ontology_manager.get_ontology_statistics()
616
+ print(f"Ontology Statistics:")
617
+ for key, value in stats.items():
618
+ print(f" {key.replace('_', ' ').title()}: {value}")
619
+ print()
620
+
621
+ return ontology_manager
622
+
623
+ if __name__ == "__main__":
624
+ # Demonstrate the system
625
  demonstrate_semantic_detection()