CosmickVisions commited on
Commit
28ab601
·
verified ·
1 Parent(s): 8f167cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +340 -2
app.py CHANGED
@@ -1144,7 +1144,72 @@ def process_video_file(video_file, analysis_types, processing_mode="Hybrid (Goog
1144
  # Display mode being used
1145
  st.info(f"Processing with {processing_mode} mode")
1146
 
1147
- # The rest of the video processing code would follow...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1148
 
1149
  def load_bigquery_table(dataset_id, table_id, limit=1000):
1150
  """Load data directly from an existing BigQuery table"""
@@ -2273,4 +2338,277 @@ def main():
2273
  st.success(f"Successfully uploaded to {dataset_id}.{table_id}")
2274
  st.write(f"Rows: {result['num_rows']}")
2275
  st.write(f"Size: {result['size_bytes'] / 1024:.2f} KB")
2276
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1144
  # Display mode being used
1145
  st.info(f"Processing with {processing_mode} mode")
1146
 
1147
+ try:
1148
+ frame_count = 0
1149
+ while frame_count < max_frames: # Limit to 10 seconds
1150
+ ret, frame = cap.read()
1151
+ if not ret:
1152
+ break
1153
+
1154
+ frame_count += 1
1155
+
1156
+ # Update progress
1157
+ progress = int(frame_count / total_frames * 100)
1158
+ progress_bar.progress(progress)
1159
+ status_text.text(f"Processing frame {frame_count}/{total_frames} ({progress}%) - {frame_count/fps:.1f}s of 10s")
1160
+
1161
+ # Add timestamp to frame
1162
+ cv2.putText(frame, f"Time: {frame_count/fps:.2f}s",
1163
+ (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
1164
+
1165
+ # Add processing mode indicator
1166
+ cv2.putText(frame, f"Mode: {processing_mode}",
1167
+ (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
1168
+
1169
+ # ... rest of the processing code ...
1170
+
1171
+ # Write the frame to output video
1172
+ out.write(frame)
1173
+
1174
+ # Release resources
1175
+ cap.release()
1176
+ out.release()
1177
+
1178
+ # Clear progress indicators
1179
+ progress_bar.empty()
1180
+ status_text.empty()
1181
+
1182
+ # Read the processed video as bytes for download
1183
+ with open(output_path, 'rb') as file:
1184
+ processed_video_bytes = file.read()
1185
+
1186
+ # Clean up temporary files
1187
+ os.unlink(temp_video_path)
1188
+ os.unlink(output_path)
1189
+
1190
+ # Return results
1191
+ results = {"detection_stats": detection_stats}
1192
+
1193
+ # Store results in session state for chatbot context
1194
+ st.session_state.analysis_results = results
1195
+
1196
+ # Update vectorstore with new results
1197
+ update_vectorstore_with_results(results)
1198
+
1199
+ return processed_video_bytes, results
1200
+
1201
+ except Exception as e:
1202
+ # Clean up on error
1203
+ cap.release()
1204
+ if 'out' in locals():
1205
+ out.release()
1206
+ os.unlink(temp_video_path)
1207
+ if os.path.exists(output_path):
1208
+ os.unlink(output_path)
1209
+
1210
+ # Return error information
1211
+ st.error(f"Error processing video: {str(e)}")
1212
+ return None, None
1213
 
1214
  def load_bigquery_table(dataset_id, table_id, limit=1000):
1215
  """Load data directly from an existing BigQuery table"""
 
2338
  st.success(f"Successfully uploaded to {dataset_id}.{table_id}")
2339
  st.write(f"Rows: {result['num_rows']}")
2340
  st.write(f"Size: {result['size_bytes'] / 1024:.2f} KB")
2341
+ st.write(f"Schema: {', '.join(result['schema'])}")
2342
+
2343
+ # Store table info in session state
2344
+ st.session_state["table_info"] = {
2345
+ "dataset_id": dataset_id,
2346
+ "table_id": table_id,
2347
+ "schema": result["schema"]
2348
+ }
2349
+ except Exception as e:
2350
+ st.error(f"Error uploading to BigQuery: {str(e)}")
2351
+ except Exception as e:
2352
+ st.error(f"Error reading CSV file: {str(e)}")
2353
+ else:
2354
+ st.info("Upload a CSV file to load data into BigQuery")
2355
+
2356
+ with query_tab:
2357
+ st.markdown("### Query BigQuery Data")
2358
+
2359
+ if "query_results" in st.session_state and "table_info" in st.session_state:
2360
+ # Display info about the loaded data
2361
+ table_info = st.session_state["table_info"]
2362
+ st.write(f"Working with table: **{table_info['dataset_id']}.{table_info['table_id']}**")
2363
+
2364
+ # Query input
2365
+ default_query = f"SELECT * FROM `{credentials.project_id}.{table_info['dataset_id']}.{table_info['table_id']}` LIMIT 100"
2366
+ query = st.text_area("SQL Query", default_query, height=100)
2367
+
2368
+ # Execute query button
2369
+ if st.button("Run Query"):
2370
+ with st.spinner("Executing query..."):
2371
+ try:
2372
+ # Run the query
2373
+ results = run_bigquery(query)
2374
+
2375
+ # Store results in session state
2376
+ st.session_state["query_results"] = results
2377
+
2378
+ # Display results
2379
+ st.write("### Query Results")
2380
+ st.dataframe(results)
2381
+
2382
+ # Download button for results
2383
+ csv = results.to_csv(index=False)
2384
+ st.download_button(
2385
+ label="Download Results as CSV",
2386
+ data=csv,
2387
+ file_name="query_results.csv",
2388
+ mime="text/csv"
2389
+ )
2390
+ except Exception as e:
2391
+ st.error(f"Error executing query: {str(e)}")
2392
+ else:
2393
+ st.info("Load a table from BigQuery or upload a CSV file first")
2394
+
2395
+ with visualization_tab:
2396
+ st.markdown("### Visualize BigQuery Data")
2397
+
2398
+ if "query_results" in st.session_state and not st.session_state["query_results"].empty:
2399
+ df = st.session_state["query_results"]
2400
+
2401
+ # Chart type selection
2402
+ chart_type = st.selectbox(
2403
+ "Select Chart Type",
2404
+ ["Bar Chart", "Line Chart", "Scatter Plot", "Histogram", "Pie Chart"]
2405
+ )
2406
+
2407
+ # Column selection based on data types
2408
+ numeric_cols = df.select_dtypes(include=['int64', 'float64']).columns.tolist()
2409
+ all_cols = df.columns.tolist()
2410
+
2411
+ if len(numeric_cols) < 1:
2412
+ st.warning("No numeric columns available for visualization")
2413
+ else:
2414
+ if chart_type in ["Bar Chart", "Line Chart", "Scatter Plot"]:
2415
+ col1, col2 = st.columns(2)
2416
+
2417
+ with col1:
2418
+ x_axis = st.selectbox("X-axis", all_cols)
2419
+
2420
+ with col2:
2421
+ y_axis = st.selectbox("Y-axis", numeric_cols)
2422
+
2423
+ # Optional: Grouping/color dimension
2424
+ color_dim = st.selectbox("Color Dimension (Optional)", ["None"] + all_cols)
2425
+
2426
+ # Generate the visualization based on selection
2427
+ if st.button("Generate Visualization"):
2428
+ st.write(f"### {chart_type}: {y_axis} by {x_axis}")
2429
+
2430
+ if chart_type == "Bar Chart":
2431
+ if color_dim != "None":
2432
+ fig = px.bar(df, x=x_axis, y=y_axis, color=color_dim,
2433
+ title=f"{y_axis} by {x_axis}")
2434
+ else:
2435
+ fig = px.bar(df, x=x_axis, y=y_axis, title=f"{y_axis} by {x_axis}")
2436
+ st.plotly_chart(fig)
2437
+
2438
+ elif chart_type == "Line Chart":
2439
+ if color_dim != "None":
2440
+ fig = px.line(df, x=x_axis, y=y_axis, color=color_dim,
2441
+ title=f"{y_axis} by {x_axis}")
2442
+ else:
2443
+ fig = px.line(df, x=x_axis, y=y_axis, title=f"{y_axis} by {x_axis}")
2444
+ st.plotly_chart(fig)
2445
+
2446
+ elif chart_type == "Scatter Plot":
2447
+ if color_dim != "None":
2448
+ fig = px.scatter(df, x=x_axis, y=y_axis, color=color_dim,
2449
+ title=f"{y_axis} vs {x_axis}")
2450
+ else:
2451
+ fig = px.scatter(df, x=x_axis, y=y_axis, title=f"{y_axis} vs {x_axis}")
2452
+ st.plotly_chart(fig)
2453
+
2454
+ elif chart_type == "Histogram":
2455
+ column = st.selectbox("Select Column", numeric_cols)
2456
+ bins = st.slider("Number of Bins", min_value=5, max_value=100, value=20)
2457
+
2458
+ if st.button("Generate Visualization"):
2459
+ st.write(f"### Histogram of {column}")
2460
+ fig = px.histogram(df, x=column, nbins=bins, title=f"Distribution of {column}")
2461
+ st.plotly_chart(fig)
2462
+
2463
+ elif chart_type == "Pie Chart":
2464
+ column = st.selectbox("Category Column", all_cols)
2465
+ value_col = st.selectbox("Value Column", numeric_cols)
2466
+
2467
+ if st.button("Generate Visualization"):
2468
+ # Aggregate the data if needed
2469
+ pie_data = df.groupby(column)[value_col].sum().reset_index()
2470
+ st.write(f"### Pie Chart: {value_col} by {column}")
2471
+ fig = px.pie(pie_data, names=column, values=value_col,
2472
+ title=f"{value_col} by {column}")
2473
+ st.plotly_chart(fig)
2474
+ else:
2475
+ st.info("Load a table from BigQuery or upload a CSV file first")
2476
+
2477
+ elif selected == "About":
2478
+ st.markdown("## About This App")
2479
+ st.write("""
2480
+ This application uses Google Cloud Vision AI to analyze images and video streams. It can:
2481
+
2482
+ - **Detect labels** in images
2483
+ - **Identify objects** and their locations
2484
+ - **Extract text** from images
2485
+ - **Detect faces** and facial landmarks
2486
+ - **Analyze real-time video** from your camera
2487
+
2488
+ To use this app, you need to:
2489
+ 1. Set up Google Cloud Vision API credentials
2490
+ 2. Upload an image or use your camera
2491
+ 3. Select the types of analysis you want to perform
2492
+ 4. Click "Analyze Image" or start the video stream
2493
+
2494
+ The app is built with Streamlit and Google Cloud Vision API.
2495
+ """)
2496
+
2497
+ st.info("Note: Make sure your Google Cloud credentials are properly set up to use this application.")
2498
+
2499
+ # Add the chatbot interface at the bottom of the page
2500
+ chatbot_interface()
2501
+
2502
+ if __name__ == "__main__":
2503
+ # Use GOOGLE_CREDENTIALS directly - no need for file or GOOGLE_APPLICATION_CREDENTIALS
2504
+ try:
2505
+ if 'GOOGLE_CREDENTIALS' in os.environ:
2506
+ # Create credentials object directly from JSON string
2507
+ credentials_info = json.loads(os.environ['GOOGLE_CREDENTIALS'])
2508
+ credentials = service_account.Credentials.from_service_account_info(credentials_info)
2509
+
2510
+ # Initialize client with these credentials directly
2511
+ client = vision.ImageAnnotatorClient(credentials=credentials)
2512
+ else:
2513
+ st.sidebar.error("GOOGLE_CREDENTIALS environment variable not found")
2514
+ client = None
2515
+ except Exception as e:
2516
+ st.sidebar.error(f"Error with credentials: {str(e)}")
2517
+ client = None
2518
+
2519
+ main()
2520
+
2521
+ # Add this function to your app
2522
+ def extract_video_frames(video_bytes, num_frames=5):
2523
+ """Extract frames from video bytes for thumbnail display with improved key frame selection"""
2524
+ import cv2
2525
+ import numpy as np
2526
+ import tempfile
2527
+ from PIL import Image
2528
+ import io
2529
+
2530
+ # Save video bytes to a temporary file
2531
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as temp_file:
2532
+ temp_file.write(video_bytes)
2533
+ temp_video_path = temp_file.name
2534
+
2535
+ # Open the video file
2536
+ cap = cv2.VideoCapture(temp_video_path)
2537
+
2538
+ # Get video properties
2539
+ frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
2540
+ fps = cap.get(cv2.CAP_PROP_FPS)
2541
+
2542
+ # Use more sophisticated frame selection based on content analysis
2543
+ frames = []
2544
+ frame_scores = []
2545
+ sample_interval = max(1, frame_count // (num_frames * 3)) # Sample more frames than needed
2546
+
2547
+ # First pass: collect frame scores
2548
+ prev_frame = None
2549
+ frame_index = 0
2550
+
2551
+ while len(frame_scores) < num_frames * 3 and frame_index < frame_count:
2552
+ cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
2553
+ ret, frame = cap.read()
2554
+ if not ret:
2555
+ break
2556
+
2557
+ # Convert to grayscale for analysis
2558
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
2559
+ gray = cv2.GaussianBlur(gray, (21, 21), 0)
2560
+
2561
+ # Calculate frame score based on Laplacian variance (focus measure)
2562
+ focus_score = cv2.Laplacian(gray, cv2.CV_64F).var()
2563
+
2564
+ # Calculate frame difference if we have a previous frame
2565
+ diff_score = 0
2566
+ if prev_frame is not None:
2567
+ frame_diff = cv2.absdiff(gray, prev_frame)
2568
+ diff_score = np.mean(frame_diff)
2569
+
2570
+ # Combined score: favor sharp frames with significant changes
2571
+ combined_score = focus_score * 0.6 + diff_score * 0.4
2572
+ frame_scores.append((frame_index, combined_score))
2573
+
2574
+ # Store frame for next comparison
2575
+ prev_frame = gray
2576
+ frame_index += sample_interval
2577
+
2578
+ # Second pass: select the best frames based on scores
2579
+ # Sort by score and get top N frames
2580
+ sorted_frames = sorted(frame_scores, key=lambda x: x[1], reverse=True)
2581
+ best_frames = sorted_frames[:num_frames]
2582
+ # Sort back by frame index to maintain chronological order
2583
+ selected_frames = sorted(best_frames, key=lambda x: x[0])
2584
+
2585
+ # Extract the selected frames
2586
+ for idx, _ in selected_frames:
2587
+ cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
2588
+ ret, frame = cap.read()
2589
+ if ret:
2590
+ # Apply subtle enhancement to frames
2591
+ enhanced_frame = frame.copy()
2592
+ # Auto color balance
2593
+ lab = cv2.cvtColor(enhanced_frame, cv2.COLOR_BGR2LAB)
2594
+ l, a, b = cv2.split(lab)
2595
+ clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
2596
+ cl = clahe.apply(l)
2597
+ enhanced_lab = cv2.merge((cl, a, b))
2598
+ enhanced_frame = cv2.cvtColor(enhanced_lab, cv2.COLOR_LAB2BGR)
2599
+
2600
+ # Convert to RGB (from BGR)
2601
+ frame_rgb = cv2.cvtColor(enhanced_frame, cv2.COLOR_BGR2RGB)
2602
+ # Convert to PIL Image
2603
+ pil_img = Image.fromarray(frame_rgb)
2604
+ # Save to bytes
2605
+ img_byte_arr = io.BytesIO()
2606
+ pil_img.save(img_byte_arr, format='JPEG', quality=90)
2607
+ frames.append(img_byte_arr.getvalue())
2608
+
2609
+ # Clean up
2610
+ cap.release()
2611
+ import os
2612
+ os.unlink(temp_video_path)
2613
+
2614
+ return frames