File size: 4,557 Bytes
e7de063 ea28818 8d81a60 e7de063 ee53246 e7de063 1a558e0 e7de063 1a558e0 e7de063 24b2edd 1a558e0 e7de063 ee53246 1a558e0 7885fdc 75b7371 1a558e0 ee53246 1a558e0 46b8a2b 1a558e0 e7de063 1a558e0 e7de063 1a558e0 7885fdc dd9efb5 1a558e0 e7de063 1a558e0 e7de063 1a558e0 e7de063 1a558e0 ee53246 75b7371 ee53246 5d19c93 ee53246 5d19c93 ee53246 d514352 | 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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | import streamlit as st
from PIL import Image
import io
import requests
import os
from api_client import predict, health_check, get_all_cards, visualize_regions
from components.upload_section import render_upload_section
from components.display_structured_data import render_card_data
from components.similarity_grid import render_similarity_grid
BACKEND_URL = os.getenv("BACKEND_URL", "https://dcorcoran-pokemon-card-image-processor-api.hf.space")
# --------------------------------
# ----- PAGE CONFIG --------------
# --------------------------------
st.set_page_config(
page_title="Pokemon Card Image Processor",
page_icon="🃏",
layout="wide"
)
# --------------------------------
# ----- HEADER -------------------
# --------------------------------
st.title("Pokemon Card Image Processor")
st.badge("Upload a Pokémon card image to extract its data and find similar cards.", color = "blue")
# --------------------------------
# ----- BACKEND STATUS -----------
# --------------------------------
if not health_check():
st.error("⚠️ Backend is not reachable. Make sure the FastAPI Space is running.")
st.stop()
# --------------------------------
# ----- UPLOAD -------------------
# --------------------------------
tab1, tab2, tab3 = st.tabs(["Upload Pokemon Card", "Card Database", "OCR Card Visualizer"])
with tab1:
st.header("Card Optical Character Recognition (OCR)")
st.caption("Upload a Pokémon card image.")
uploaded_file = render_upload_section(key="upload_tab1")
# Check if file was uploaded
if uploaded_file:
# Reading Pokemon Card
image_bytes = uploaded_file.read()
image = Image.open(io.BytesIO(image_bytes))
# Separate page into two columns
col1, col2 = st.columns([1, 2])
with col1:
st.image(image, width="content")
with col2:
with st.spinner("Analyzing card..."):
result = predict(image_bytes, uploaded_file.name)
# Check if there was an error in the predict endpoint
if "error_type" in result:
st.error(f"Error ({result['error_type']}): {result.get('backend_response') or result.get('exception')}")
# Display the rendered card data if there is no error
else:
render_card_data(result)
# Add a divider between the uploaded card and the similar cards
st.divider()
# Add header for similar cards
st.header("Similar Cards")
if "error" not in result:
render_similarity_grid(result.get("similar_cards", []))
with tab2:
st.header("Card Database")
st.caption("Showing a sample of available cards in the database.")
with st.spinner("Loading cards..."):
try:
cards = get_all_cards()
except Exception as e:
st.error(f"Could not load card database: {e}")
cards = []
if cards:
cols_per_row = 5
rows = [cards[i:i+cols_per_row] for i in range(0, len(cards), cols_per_row)]
for row in rows:
cols = st.columns(cols_per_row)
for col, card in zip(cols, row):
with col:
if card.get("image_url"):
st.image(card["image_url"], width="content")
else:
st.markdown("🃏")
st.caption(card.get("name", "Unknown"))
else:
st.info("No cards to display.")
with tab3:
# Tab header and description
st.header("OCR Region Visualizer")
st.caption("Upload a card to see exactly which regions the OCR is scanning.")
# Reuse the shared upload component to accept a card image
vis_file = render_upload_section(key="upload_tab3")
if vis_file:
# Read the uploaded file bytes and decode into a Pillow Image for local display
image_bytes = vis_file.read()
image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
# Split the view into two side-by-side columns: original vs. annotated
col1, col2 = st.columns(2)
# Display the unmodified card image on the left
with col1:
st.subheader("Original")
st.image(image, width="content")
# Display the modified card image on the right
with col2:
st.subheader("OCR Regions")
annotated = visualize_regions(image_bytes, vis_file.name)
if annotated:
st.image(annotated, width="content")
st.divider() |