dcorcoran commited on
Commit
ee53246
Β·
1 Parent(s): 314c013

Added OCR region drawing tab to visualize what the OCR is looking at

Browse files
Files changed (2) hide show
  1. api_client.py +28 -0
  2. app.py +41 -4
api_client.py CHANGED
@@ -3,6 +3,8 @@ import os
3
  import requests
4
  import base64
5
  import streamlit as st
 
 
6
 
7
  #BACKEND_URL = "http://localhost:8000"
8
  BACKEND_URL = os.getenv("BACKEND_URL", "https://dcorcoran-pokemon-card-image-processor-api.hf.space")
@@ -55,3 +57,29 @@ def get_all_cards(limit: int = 100) -> list:
55
  return response.json()
56
  except Exception as e:
57
  raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import requests
4
  import base64
5
  import streamlit as st
6
+ import io
7
+ from PIL import Image
8
 
9
  #BACKEND_URL = "http://localhost:8000"
10
  BACKEND_URL = os.getenv("BACKEND_URL", "https://dcorcoran-pokemon-card-image-processor-api.hf.space")
 
57
  return response.json()
58
  except Exception as e:
59
  raise
60
+
61
+
62
+ def visualize_regions(image_bytes: bytes, filename: str) -> Image.Image | None:
63
+ try:
64
+ response = requests.post(
65
+ f"{BACKEND_URL}/visualize",
66
+ files={"file": (filename, image_bytes, "image/jpeg")},
67
+ timeout=30
68
+ )
69
+ response.raise_for_status()
70
+
71
+ # Decode the returned PNG bytes into a Pillow Image
72
+ return Image.open(io.BytesIO(response.content))
73
+
74
+ except requests.exceptions.HTTPError as http_err:
75
+ st.error(f"Visualization failed (HTTP {response.status_code}): {http_err}")
76
+ return None
77
+ except requests.exceptions.ConnectionError as conn_err:
78
+ st.error(f"Connection error during visualization: {conn_err}")
79
+ return None
80
+ except requests.exceptions.Timeout:
81
+ st.error("Visualization request timed out.")
82
+ return None
83
+ except Exception as e:
84
+ st.error(f"Unexpected error during visualization: {e}")
85
+ return None
app.py CHANGED
@@ -4,7 +4,7 @@ import io
4
  import requests
5
  import os
6
 
7
- from api_client import predict, health_check, get_all_cards
8
  from components.upload_section import render_upload_section
9
  from components.display_structured_data import render_card_data
10
  from components.similarity_grid import render_similarity_grid
@@ -42,7 +42,7 @@ if not health_check():
42
  # ----- UPLOAD -------------------
43
  # --------------------------------
44
 
45
- tab1, tab2 = st.tabs(["Upload Pokemon Card", "Card Database"])
46
 
47
 
48
  with tab1:
@@ -62,7 +62,7 @@ with tab1:
62
 
63
  with col2:
64
  with st.spinner("Analyzing card..."):
65
- result = predict(image_bytes, uploaded_file.name)
66
 
67
  # Check if there was an error in the predict endpoint
68
  if "error_type" in result:
@@ -107,4 +107,41 @@ with tab2:
107
  st.markdown("πŸƒ")
108
  st.caption(card.get("name", "Unknown"))
109
  else:
110
- st.info("No cards to display.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import requests
5
  import os
6
 
7
+ from api_client import predict, health_check, get_all_cards, visualize_regions
8
  from components.upload_section import render_upload_section
9
  from components.display_structured_data import render_card_data
10
  from components.similarity_grid import render_similarity_grid
 
42
  # ----- UPLOAD -------------------
43
  # --------------------------------
44
 
45
+ tab1, tab2, tab3 = st.tabs(["Upload Pokemon Card", "Card Database", "OCR Card Visualizer"])
46
 
47
 
48
  with tab1:
 
62
 
63
  with col2:
64
  with st.spinner("Analyzing card..."):
65
+ result = predict(image_bytes, uploaded_file.name)
66
 
67
  # Check if there was an error in the predict endpoint
68
  if "error_type" in result:
 
107
  st.markdown("πŸƒ")
108
  st.caption(card.get("name", "Unknown"))
109
  else:
110
+ st.info("No cards to display.")
111
+
112
+ with tab3:
113
+ # Tab header and description
114
+ st.header("OCR Region Visualizer")
115
+ st.caption("Upload a card to see exactly which regions the OCR is scanning.")
116
+
117
+ # Reuse the shared upload component to accept a card image
118
+ vis_file = render_upload_section()
119
+
120
+ if vis_file:
121
+ # Read the uploaded file bytes and decode into a Pillow Image for local display
122
+ image_bytes = vis_file.read()
123
+ image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
124
+
125
+ # Split the view into two side-by-side columns: original vs. annotated
126
+ col1, col2 = st.columns(2)
127
+
128
+ # Display the unmodified card image on the left
129
+ with col1:
130
+ st.subheader("Original")
131
+ st.image(image, use_container_width=True)
132
+
133
+ # Display the modified card image on the right
134
+ with col2:
135
+ st.subheader("OCR Regions")
136
+ annotated = visualize_regions(image_bytes, vis_file.name)
137
+ if annotated:
138
+ st.image(annotated, use_container_width=True)
139
+
140
+ st.divider()
141
+
142
+ # Color legend mapping each box color to its corresponding OCR region
143
+ st.markdown("**Legend**")
144
+ cols = st.columns(3)
145
+ cols[0].markdown("πŸ”΄ **Name**")
146
+ cols[1].markdown("πŸ”΅ **HP**")
147
+ cols[2].markdown("🟒 **Moves**")