Commit ·
343b0c3
1
Parent(s): 3e2fe96
feat: add AI detection overlay visualization with bounding boxes on extracted entities
Browse files- README.md +1 -1
- app.py +23 -1
- src/ml_extraction.py +2 -1
- src/pipeline.py +6 -0
README.md
CHANGED
|
@@ -432,7 +432,7 @@ MIT License - See LICENSE file for details
|
|
| 432 |
**Soumyajit Ghosh** - 3rd Year BTech Student
|
| 433 |
|
| 434 |
- Exploring AI/ML and practical applications
|
| 435 |
-
- [LinkedIn](https://www.linkedin.com/in/soumyajit-ghosh-tech) | [GitHub](https://github.com/GSoumyajit2005) | [Portfolio](
|
| 436 |
|
| 437 |
---
|
| 438 |
|
|
|
|
| 432 |
**Soumyajit Ghosh** - 3rd Year BTech Student
|
| 433 |
|
| 434 |
- Exploring AI/ML and practical applications
|
| 435 |
+
- [LinkedIn](https://www.linkedin.com/in/soumyajit-ghosh-tech) | [GitHub](https://github.com/GSoumyajit2005) | [Portfolio](https://soumyajitghosh.vercel.app)
|
| 436 |
|
| 437 |
---
|
| 438 |
|
app.py
CHANGED
|
@@ -3,7 +3,7 @@ import os
|
|
| 3 |
import json
|
| 4 |
from datetime import datetime
|
| 5 |
from pathlib import Path
|
| 6 |
-
from PIL import Image
|
| 7 |
import pandas as pd
|
| 8 |
import sys
|
| 9 |
|
|
@@ -147,6 +147,28 @@ with tab1:
|
|
| 147 |
|
| 148 |
st.success("Extraction Complete")
|
| 149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
except Exception as e:
|
| 151 |
st.error(f"Pipeline error: {e}")
|
| 152 |
|
|
|
|
| 3 |
import json
|
| 4 |
from datetime import datetime
|
| 5 |
from pathlib import Path
|
| 6 |
+
from PIL import Image, ImageDraw
|
| 7 |
import pandas as pd
|
| 8 |
import sys
|
| 9 |
|
|
|
|
| 147 |
|
| 148 |
st.success("Extraction Complete")
|
| 149 |
|
| 150 |
+
# --- AI Detection Overlay Visualization ---
|
| 151 |
+
raw_predictions = result.get("raw_predictions")
|
| 152 |
+
if raw_predictions and uploaded_file.type != "application/pdf":
|
| 153 |
+
# Reload the original image for annotation
|
| 154 |
+
uploaded_file.seek(0)
|
| 155 |
+
overlay_image = Image.open(uploaded_file).convert("RGB")
|
| 156 |
+
draw = ImageDraw.Draw(overlay_image)
|
| 157 |
+
|
| 158 |
+
# Draw red rectangles around each detected entity's bounding boxes
|
| 159 |
+
for entity_name, entity_data in raw_predictions.items():
|
| 160 |
+
bboxes = entity_data.get("bbox", [])
|
| 161 |
+
for box in bboxes:
|
| 162 |
+
# bbox format: [x, y, width, height]
|
| 163 |
+
x, y, w, h = box
|
| 164 |
+
draw.rectangle(
|
| 165 |
+
[x, y, x + w, y + h],
|
| 166 |
+
outline="red",
|
| 167 |
+
width=2
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
st.image(overlay_image, caption="AI Detection Overlay", use_container_width=True)
|
| 171 |
+
|
| 172 |
except Exception as e:
|
| 173 |
st.error(f"Pipeline error: {e}")
|
| 174 |
|
src/ml_extraction.py
CHANGED
|
@@ -126,7 +126,8 @@ def extract_ml_based(image_path: str) -> Dict[str, Any]:
|
|
| 126 |
"bill_to": extracted_entities.get("BILL_TO", {}).get("text"),
|
| 127 |
"total_amount": None,
|
| 128 |
"items": [],
|
| 129 |
-
"raw_text": raw_text
|
|
|
|
| 130 |
}
|
| 131 |
|
| 132 |
# Fallbacks
|
|
|
|
| 126 |
"bill_to": extracted_entities.get("BILL_TO", {}).get("text"),
|
| 127 |
"total_amount": None,
|
| 128 |
"items": [],
|
| 129 |
+
"raw_text": raw_text,
|
| 130 |
+
"raw_predictions": extracted_entities # Contains text and bbox data for each entity
|
| 131 |
}
|
| 132 |
|
| 133 |
# Fallbacks
|
src/pipeline.py
CHANGED
|
@@ -129,6 +129,12 @@ def process_invoice(image_path: str,
|
|
| 129 |
error_list.append(f"{field}: {msg}")
|
| 130 |
|
| 131 |
final_data['validation_errors'] = error_list
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
|
| 133 |
# --- DUPLICATE DETECTION ---
|
| 134 |
# We calculate the hash based on the final (or raw) data.
|
|
|
|
| 129 |
error_list.append(f"{field}: {msg}")
|
| 130 |
|
| 131 |
final_data['validation_errors'] = error_list
|
| 132 |
+
|
| 133 |
+
# Preserve raw_predictions and raw_text for UI visualization (not in schema)
|
| 134 |
+
if 'raw_predictions' in raw_result:
|
| 135 |
+
final_data['raw_predictions'] = raw_result['raw_predictions']
|
| 136 |
+
if 'raw_text' in raw_result:
|
| 137 |
+
final_data['raw_text'] = raw_result['raw_text']
|
| 138 |
|
| 139 |
# --- DUPLICATE DETECTION ---
|
| 140 |
# We calculate the hash based on the final (or raw) data.
|