Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,7 +13,7 @@ st.markdown("### Search 11,500+ Cinematic AI-Tagged Comic Panels")
|
|
| 13 |
# ==========================================
|
| 14 |
# 2. DATA BUCKETING & CLEANING
|
| 15 |
# ==========================================
|
| 16 |
-
#
|
| 17 |
def categorize_camera(text):
|
| 18 |
text = str(text).lower()
|
| 19 |
if 'dutch' in text: return 'Dutch Angle'
|
|
@@ -44,16 +44,41 @@ def categorize_lighting(text):
|
|
| 44 |
elif 'flat' in text or 'even' in text: return 'Flat Lighting'
|
| 45 |
else: return 'Standard Lighting'
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
@st.cache_data
|
| 48 |
def load_data():
|
| 49 |
df = pd.read_csv("horror_shot_database.csv")
|
| 50 |
|
| 51 |
-
#
|
| 52 |
df['broad_camera'] = df['camera_angle'].apply(categorize_camera)
|
| 53 |
df['broad_mood'] = df['mood'].apply(categorize_mood)
|
| 54 |
-
# We search both mood and description to figure out the lighting
|
| 55 |
df['broad_lighting'] = (df['mood'].fillna('') + " " + df['description'].fillna('')).apply(categorize_lighting)
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
return df
|
| 58 |
|
| 59 |
try:
|
|
@@ -67,37 +92,51 @@ except Exception as e:
|
|
| 67 |
# ==========================================
|
| 68 |
st.sidebar.header("π Search Library")
|
| 69 |
|
| 70 |
-
|
| 71 |
-
search_query = st.sidebar.text_input("Keyword Search", placeholder="e.g., monster, running, eyes...")
|
| 72 |
st.sidebar.write("---")
|
| 73 |
|
| 74 |
st.sidebar.header("π Filter Categories")
|
| 75 |
|
| 76 |
-
#
|
| 77 |
-
with st.sidebar.expander("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
all_angles = ["Any"] + sorted(df['broad_camera'].unique().tolist())
|
| 79 |
selected_angle = st.selectbox("Shot Type", all_angles)
|
| 80 |
|
| 81 |
-
#
|
| 82 |
-
with st.sidebar.expander("
|
| 83 |
all_lighting = ["Any"] + sorted(df['broad_lighting'].unique().tolist())
|
| 84 |
-
selected_lighting = st.selectbox("Lighting
|
| 85 |
-
|
| 86 |
-
# Expandable Category: Mood
|
| 87 |
-
with st.sidebar.expander("π Scene Mood"):
|
| 88 |
all_moods = ["Any"] + sorted(df['broad_mood'].unique().tolist())
|
| 89 |
-
selected_mood = st.selectbox("
|
| 90 |
|
| 91 |
# ==========================================
|
| 92 |
# 4. FILTERING LOGIC
|
| 93 |
# ==========================================
|
| 94 |
results = df.copy()
|
| 95 |
|
| 96 |
-
# Apply the text search
|
| 97 |
if search_query:
|
| 98 |
results = results[results['description'].str.contains(search_query, case=False, na=False)]
|
| 99 |
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
if selected_angle != "Any":
|
| 102 |
results = results[results['broad_camera'] == selected_angle]
|
| 103 |
if selected_lighting != "Any":
|
|
|
|
| 13 |
# ==========================================
|
| 14 |
# 2. DATA BUCKETING & CLEANING
|
| 15 |
# ==========================================
|
| 16 |
+
# Camera, Mood, and Lighting Buckets
|
| 17 |
def categorize_camera(text):
|
| 18 |
text = str(text).lower()
|
| 19 |
if 'dutch' in text: return 'Dutch Angle'
|
|
|
|
| 44 |
elif 'flat' in text or 'even' in text: return 'Flat Lighting'
|
| 45 |
else: return 'Standard Lighting'
|
| 46 |
|
| 47 |
+
# NEW: Location, Subjects, and Action Buckets
|
| 48 |
+
def categorize_location(row):
|
| 49 |
+
text = str(row.get('location_setup', '')).lower() + " " + str(row.get('description', '')).lower()
|
| 50 |
+
if any(w in text for w in ['indoor', 'interior', 'room', 'house', 'building', 'office', 'corridor', 'hallway', 'wall', 'window', 'door', 'basement', 'stairs']): return 'Indoor'
|
| 51 |
+
if any(w in text for w in ['outdoor', 'exterior', 'street', 'sky', 'forest', 'mountain', 'landscape', 'city', 'outside', 'woods', 'road', 'night', 'moon', 'ocean']): return 'Outdoor'
|
| 52 |
+
return 'Unspecified / Mixed'
|
| 53 |
+
|
| 54 |
+
def categorize_subject(row):
|
| 55 |
+
text = str(row.get('staging', '')).lower() + " " + str(row.get('description', '')).lower()
|
| 56 |
+
if any(w in text for w in ['group', 'crowd', 'three', 'four', 'multiple', 'several', 'guests', 'army', 'mob', 'people']): return 'Group (3+ People)'
|
| 57 |
+
if any(w in text for w in ['two', 'couple', 'duo', 'both', 'pair']): return 'Two Characters'
|
| 58 |
+
if any(w in text for w in ['man', 'woman', 'boy', 'girl', 'figure', 'character', 'person', 'creature', 'monster']): return 'Single Subject'
|
| 59 |
+
return 'Object / Environment'
|
| 60 |
+
|
| 61 |
+
def categorize_action(row):
|
| 62 |
+
text = str(row.get('staging', '')).lower() + " " + str(row.get('description', '')).lower()
|
| 63 |
+
if any(w in text for w in ['action', 'fight', 'strike', 'combat', 'running', 'chasing', 'attack', 'lunging', 'falling', 'fleeing', 'struggle', 'violence', 'grab']): return 'Action Sequence'
|
| 64 |
+
if any(w in text for w in ['dialogue', 'talking', 'discussing', 'speaking', 'speech', 'conversation', 'yelling', 'screaming', 'whispering', 'saying']): return 'Dialogue / Conversation'
|
| 65 |
+
if any(w in text for w in ['reacts', 'reaction', 'looking', 'staring', 'observing', 'gazing', 'watching', 'shock', 'listening']): return 'Reaction / Observation'
|
| 66 |
+
return 'Static / Establishing'
|
| 67 |
+
|
| 68 |
@st.cache_data
|
| 69 |
def load_data():
|
| 70 |
df = pd.read_csv("horror_shot_database.csv")
|
| 71 |
|
| 72 |
+
# Apply standard categories
|
| 73 |
df['broad_camera'] = df['camera_angle'].apply(categorize_camera)
|
| 74 |
df['broad_mood'] = df['mood'].apply(categorize_mood)
|
|
|
|
| 75 |
df['broad_lighting'] = (df['mood'].fillna('') + " " + df['description'].fillna('')).apply(categorize_lighting)
|
| 76 |
|
| 77 |
+
# Apply new Storyboard categories
|
| 78 |
+
df['location_type'] = df.apply(categorize_location, axis=1)
|
| 79 |
+
df['subject_type'] = df.apply(categorize_subject, axis=1)
|
| 80 |
+
df['action_type'] = df.apply(categorize_action, axis=1)
|
| 81 |
+
|
| 82 |
return df
|
| 83 |
|
| 84 |
try:
|
|
|
|
| 92 |
# ==========================================
|
| 93 |
st.sidebar.header("π Search Library")
|
| 94 |
|
| 95 |
+
search_query = st.sidebar.text_input("Keyword Search", placeholder="e.g., monster, shadow, weapon...")
|
|
|
|
| 96 |
st.sidebar.write("---")
|
| 97 |
|
| 98 |
st.sidebar.header("π Filter Categories")
|
| 99 |
|
| 100 |
+
# Expander 1: Location & Subjects
|
| 101 |
+
with st.sidebar.expander("π Location & Subjects", expanded=True):
|
| 102 |
+
all_locations = ["Any"] + sorted(df['location_type'].unique().tolist())
|
| 103 |
+
selected_location = st.selectbox("Setting", all_locations)
|
| 104 |
+
|
| 105 |
+
all_subjects = ["Any"] + sorted(df['subject_type'].unique().tolist())
|
| 106 |
+
selected_subject = st.selectbox("Characters in Frame", all_subjects)
|
| 107 |
+
|
| 108 |
+
# Expander 2: Scene & Action
|
| 109 |
+
with st.sidebar.expander("π¬ Action & Scene Type", expanded=True):
|
| 110 |
+
all_actions = ["Any"] + sorted(df['action_type'].unique().tolist())
|
| 111 |
+
selected_action = st.selectbox("Scene Action", all_actions)
|
| 112 |
+
|
| 113 |
+
# Expander 3: Camera
|
| 114 |
+
with st.sidebar.expander("π₯ Camera & Framing"):
|
| 115 |
all_angles = ["Any"] + sorted(df['broad_camera'].unique().tolist())
|
| 116 |
selected_angle = st.selectbox("Shot Type", all_angles)
|
| 117 |
|
| 118 |
+
# Expander 4: Atmosphere
|
| 119 |
+
with st.sidebar.expander("π Atmosphere"):
|
| 120 |
all_lighting = ["Any"] + sorted(df['broad_lighting'].unique().tolist())
|
| 121 |
+
selected_lighting = st.selectbox("Lighting Style", all_lighting)
|
| 122 |
+
|
|
|
|
|
|
|
| 123 |
all_moods = ["Any"] + sorted(df['broad_mood'].unique().tolist())
|
| 124 |
+
selected_mood = st.selectbox("Mood", all_moods)
|
| 125 |
|
| 126 |
# ==========================================
|
| 127 |
# 4. FILTERING LOGIC
|
| 128 |
# ==========================================
|
| 129 |
results = df.copy()
|
| 130 |
|
|
|
|
| 131 |
if search_query:
|
| 132 |
results = results[results['description'].str.contains(search_query, case=False, na=False)]
|
| 133 |
|
| 134 |
+
if selected_location != "Any":
|
| 135 |
+
results = results[results['location_type'] == selected_location]
|
| 136 |
+
if selected_subject != "Any":
|
| 137 |
+
results = results[results['subject_type'] == selected_subject]
|
| 138 |
+
if selected_action != "Any":
|
| 139 |
+
results = results[results['action_type'] == selected_action]
|
| 140 |
if selected_angle != "Any":
|
| 141 |
results = results[results['broad_camera'] == selected_angle]
|
| 142 |
if selected_lighting != "Any":
|