Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -307,8 +307,8 @@ def create_summary_image(annotated_img, labels, objects, text):
|
|
| 307 |
font = ImageFont.load_default()
|
| 308 |
title_font = ImageFont.load_default()
|
| 309 |
|
| 310 |
-
# Draw title
|
| 311 |
-
draw.text((20, img_height + 20), "Cosmick Cloud AI Analyzer Results", fill=(
|
| 312 |
|
| 313 |
# Draw divider line
|
| 314 |
draw.line([(0, img_height + 50), (img_width, img_height + 50)], fill=(200, 200, 200), width=2)
|
|
@@ -344,18 +344,19 @@ def create_summary_image(annotated_img, labels, objects, text):
|
|
| 344 |
draw.text((mid_point + 20, y_pos), f"{obj}: {confidence}%", fill=(0, 0, 128), font=font)
|
| 345 |
y_pos += 25
|
| 346 |
|
| 347 |
-
# Add text detection summary at the bottom
|
| 348 |
if text:
|
| 349 |
bottom_y = img_height + result_height - 80
|
| 350 |
draw.text((20, bottom_y), "📝 Text Detected:", fill=(0, 0, 0), font=title_font)
|
| 351 |
# Truncate text if too long
|
| 352 |
display_text = text if len(text) < 100 else text[:97] + "..."
|
| 353 |
-
|
|
|
|
| 354 |
|
| 355 |
-
# Add timestamp
|
| 356 |
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 357 |
draw.text((img_width - 200, img_height + result_height - 30),
|
| 358 |
-
f"Generated: {timestamp}", fill=(
|
| 359 |
|
| 360 |
return summary_img
|
| 361 |
|
|
@@ -533,6 +534,18 @@ def analyze_document(file_content, processor_id, location="us"):
|
|
| 533 |
|
| 534 |
tables.append({"headers": headers, "data": table_data})
|
| 535 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 536 |
return text, entities, tables
|
| 537 |
|
| 538 |
def create_bigquery_table(dataset_id, table_id, schema=None):
|
|
@@ -609,11 +622,24 @@ def upload_csv_to_bigquery(file, dataset_id, table_id, append=False):
|
|
| 609 |
# Get the table
|
| 610 |
table = bq_client.get_table(table_ref)
|
| 611 |
|
| 612 |
-
|
| 613 |
"num_rows": table.num_rows,
|
| 614 |
"size_bytes": table.num_bytes,
|
| 615 |
"schema": [field.name for field in table.schema]
|
| 616 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 617 |
|
| 618 |
def run_bigquery(query):
|
| 619 |
"""Run a BigQuery query and return results"""
|
|
@@ -629,6 +655,16 @@ def run_bigquery(query):
|
|
| 629 |
# Convert to dataframe
|
| 630 |
df = results.to_dataframe()
|
| 631 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 632 |
return df
|
| 633 |
|
| 634 |
def list_bigquery_resources():
|
|
@@ -686,8 +722,19 @@ def process_video_file(video_file, analysis_types):
|
|
| 686 |
output_fps = fps * 0.6
|
| 687 |
st.info(f"Output video will be slowed down to {output_fps:.1f} FPS (60% of original speed) for better visualization.")
|
| 688 |
|
| 689 |
-
# Create video writer with
|
| 690 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
out = cv2.VideoWriter(output_path, fourcc, output_fps, (width, height), isColor=True)
|
| 692 |
|
| 693 |
# Process every Nth frame to reduce API calls but increase from 10 to 5 for more detail
|
|
@@ -887,7 +934,16 @@ def process_video_file(video_file, analysis_types):
|
|
| 887 |
os.unlink(output_path)
|
| 888 |
|
| 889 |
# Return both the video and the detection statistics
|
| 890 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 891 |
|
| 892 |
except Exception as e:
|
| 893 |
# Clean up on error
|
|
@@ -1026,36 +1082,86 @@ def update_vectorstore_with_results(results):
|
|
| 1026 |
return
|
| 1027 |
|
| 1028 |
try:
|
| 1029 |
-
# Convert results to document format
|
| 1030 |
-
results_text =
|
| 1031 |
-
|
| 1032 |
-
|
| 1033 |
-
|
| 1034 |
-
|
| 1035 |
-
|
| 1036 |
-
|
| 1037 |
-
|
| 1038 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1039 |
|
| 1040 |
# Create a document
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
|
| 1044 |
-
|
| 1045 |
-
|
| 1046 |
-
|
| 1047 |
-
|
| 1048 |
-
|
| 1049 |
-
|
| 1050 |
-
|
| 1051 |
-
|
| 1052 |
-
|
| 1053 |
-
|
| 1054 |
-
|
| 1055 |
-
|
| 1056 |
-
|
| 1057 |
-
|
| 1058 |
-
|
|
|
|
| 1059 |
except Exception as e:
|
| 1060 |
st.warning(f"Error updating vectorstore: {str(e)}")
|
| 1061 |
|
|
@@ -1585,8 +1691,14 @@ def main():
|
|
| 1585 |
mime="video/mp4"
|
| 1586 |
)
|
| 1587 |
|
| 1588 |
-
# Display processed video
|
| 1589 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1590 |
|
| 1591 |
# Show detailed analysis results
|
| 1592 |
st.markdown("### Detailed Analysis Results")
|
|
|
|
| 307 |
font = ImageFont.load_default()
|
| 308 |
title_font = ImageFont.load_default()
|
| 309 |
|
| 310 |
+
# Draw title - using dark blue color
|
| 311 |
+
draw.text((20, img_height + 20), "Cosmick Cloud AI Analyzer Results", fill=(0, 0, 139), font=title_font)
|
| 312 |
|
| 313 |
# Draw divider line
|
| 314 |
draw.line([(0, img_height + 50), (img_width, img_height + 50)], fill=(200, 200, 200), width=2)
|
|
|
|
| 344 |
draw.text((mid_point + 20, y_pos), f"{obj}: {confidence}%", fill=(0, 0, 128), font=font)
|
| 345 |
y_pos += 25
|
| 346 |
|
| 347 |
+
# Add text detection summary at the bottom with improved visibility
|
| 348 |
if text:
|
| 349 |
bottom_y = img_height + result_height - 80
|
| 350 |
draw.text((20, bottom_y), "📝 Text Detected:", fill=(0, 0, 0), font=title_font)
|
| 351 |
# Truncate text if too long
|
| 352 |
display_text = text if len(text) < 100 else text[:97] + "..."
|
| 353 |
+
# Change text color to dark red for better visibility
|
| 354 |
+
draw.text((20, bottom_y + 30), display_text, fill=(139, 0, 0), font=font)
|
| 355 |
|
| 356 |
+
# Add timestamp with darker color
|
| 357 |
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 358 |
draw.text((img_width - 200, img_height + result_height - 30),
|
| 359 |
+
f"Generated: {timestamp}", fill=(50, 50, 50), font=font)
|
| 360 |
|
| 361 |
return summary_img
|
| 362 |
|
|
|
|
| 534 |
|
| 535 |
tables.append({"headers": headers, "data": table_data})
|
| 536 |
|
| 537 |
+
# Store results in session state for chatbot context
|
| 538 |
+
results = (text, entities, tables)
|
| 539 |
+
st.session_state.analysis_results = {
|
| 540 |
+
"text": text,
|
| 541 |
+
"entities": entities,
|
| 542 |
+
"tables": tables,
|
| 543 |
+
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
# Update vectorstore with new results
|
| 547 |
+
update_vectorstore_with_results(results)
|
| 548 |
+
|
| 549 |
return text, entities, tables
|
| 550 |
|
| 551 |
def create_bigquery_table(dataset_id, table_id, schema=None):
|
|
|
|
| 622 |
# Get the table
|
| 623 |
table = bq_client.get_table(table_ref)
|
| 624 |
|
| 625 |
+
result = {
|
| 626 |
"num_rows": table.num_rows,
|
| 627 |
"size_bytes": table.num_bytes,
|
| 628 |
"schema": [field.name for field in table.schema]
|
| 629 |
}
|
| 630 |
+
|
| 631 |
+
# Store results in session state for chatbot context
|
| 632 |
+
st.session_state.analysis_results = {
|
| 633 |
+
"data_source": f"{dataset_id}.{table_id}",
|
| 634 |
+
"num_rows": table.num_rows,
|
| 635 |
+
"schema": [field.name for field in table.schema],
|
| 636 |
+
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
# Update vectorstore with new results
|
| 640 |
+
update_vectorstore_with_results(result)
|
| 641 |
+
|
| 642 |
+
return result
|
| 643 |
|
| 644 |
def run_bigquery(query):
|
| 645 |
"""Run a BigQuery query and return results"""
|
|
|
|
| 655 |
# Convert to dataframe
|
| 656 |
df = results.to_dataframe()
|
| 657 |
|
| 658 |
+
# Store results in session state for chatbot context
|
| 659 |
+
st.session_state.analysis_results = {
|
| 660 |
+
"query": query,
|
| 661 |
+
"results": df,
|
| 662 |
+
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
# Update vectorstore with new results
|
| 666 |
+
update_vectorstore_with_results(df)
|
| 667 |
+
|
| 668 |
return df
|
| 669 |
|
| 670 |
def list_bigquery_resources():
|
|
|
|
| 722 |
output_fps = fps * 0.6
|
| 723 |
st.info(f"Output video will be slowed down to {output_fps:.1f} FPS (60% of original speed) for better visualization.")
|
| 724 |
|
| 725 |
+
# Create video writer with H.264 codec for better compatibility
|
| 726 |
+
# Try different codec options based on platform compatibility
|
| 727 |
+
try:
|
| 728 |
+
# First try H.264 codec (most widely compatible)
|
| 729 |
+
if cv2.__version__.startswith('4'):
|
| 730 |
+
fourcc = cv2.VideoWriter_fourcc(*'avc1') # H.264 codec
|
| 731 |
+
else:
|
| 732 |
+
# Fallback to older codec naming
|
| 733 |
+
fourcc = cv2.VideoWriter_fourcc(*'H264')
|
| 734 |
+
except Exception:
|
| 735 |
+
# If H.264 isn't available, fall back to MP4V
|
| 736 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 737 |
+
|
| 738 |
out = cv2.VideoWriter(output_path, fourcc, output_fps, (width, height), isColor=True)
|
| 739 |
|
| 740 |
# Process every Nth frame to reduce API calls but increase from 10 to 5 for more detail
|
|
|
|
| 934 |
os.unlink(output_path)
|
| 935 |
|
| 936 |
# Return both the video and the detection statistics
|
| 937 |
+
processed_video_bytes = processed_video_bytes
|
| 938 |
+
results = {"detection_stats": detection_stats}
|
| 939 |
+
|
| 940 |
+
# Store results in session state for chatbot context
|
| 941 |
+
st.session_state.analysis_results = results
|
| 942 |
+
|
| 943 |
+
# Update vectorstore with new results
|
| 944 |
+
update_vectorstore_with_results(results)
|
| 945 |
+
|
| 946 |
+
return processed_video_bytes, results
|
| 947 |
|
| 948 |
except Exception as e:
|
| 949 |
# Clean up on error
|
|
|
|
| 1082 |
return
|
| 1083 |
|
| 1084 |
try:
|
| 1085 |
+
# Convert results to document format based on type
|
| 1086 |
+
results_text = ""
|
| 1087 |
+
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 1088 |
+
|
| 1089 |
+
# Check what type of results we have
|
| 1090 |
+
if isinstance(results, dict):
|
| 1091 |
+
if "labels" in results: # Image analysis results
|
| 1092 |
+
results_text = f"""
|
| 1093 |
+
Image Analysis Results at {results.get('timestamp', timestamp)}:
|
| 1094 |
+
|
| 1095 |
+
Labels detected: {', '.join(results.get('labels', {}).keys())}
|
| 1096 |
+
|
| 1097 |
+
Objects detected: {', '.join(results.get('objects', {}).keys())}
|
| 1098 |
+
|
| 1099 |
+
Text detected: {results.get('text', 'None')}
|
| 1100 |
+
"""
|
| 1101 |
+
elif "detection_stats" in results: # Video analysis results
|
| 1102 |
+
detection_stats = results.get("detection_stats", {})
|
| 1103 |
+
results_text = f"""
|
| 1104 |
+
Video Analysis Results at {timestamp}:
|
| 1105 |
+
|
| 1106 |
+
Objects detected: {', '.join(detection_stats.get('objects', {}).keys())}
|
| 1107 |
+
|
| 1108 |
+
Faces detected: {detection_stats.get('faces', 0)}
|
| 1109 |
+
|
| 1110 |
+
Text blocks detected: {detection_stats.get('text_blocks', 0)}
|
| 1111 |
+
|
| 1112 |
+
Labels detected: {', '.join(detection_stats.get('labels', {}).keys())}
|
| 1113 |
+
"""
|
| 1114 |
+
elif "data" in results: # Data analysis results
|
| 1115 |
+
results_text = f"""
|
| 1116 |
+
Data Analysis Results at {timestamp}:
|
| 1117 |
+
|
| 1118 |
+
Dataset loaded with {results.get('num_rows', 0)} rows
|
| 1119 |
+
|
| 1120 |
+
Columns: {', '.join(results.get('schema', []))}
|
| 1121 |
+
"""
|
| 1122 |
+
elif isinstance(results, tuple) and len(results) == 3: # Document analysis results
|
| 1123 |
+
text, entities, tables = results
|
| 1124 |
+
entities_text = ", ".join(f"{k}: {v}" for k, v in entities.items())
|
| 1125 |
+
tables_info = f"{len(tables)} tables extracted" if tables else "No tables extracted"
|
| 1126 |
+
|
| 1127 |
+
results_text = f"""
|
| 1128 |
+
Document Analysis Results at {timestamp}:
|
| 1129 |
+
|
| 1130 |
+
Extracted text length: {len(text)} characters
|
| 1131 |
+
|
| 1132 |
+
Entities detected: {entities_text}
|
| 1133 |
+
|
| 1134 |
+
Tables: {tables_info}
|
| 1135 |
+
"""
|
| 1136 |
+
elif isinstance(results, pd.DataFrame): # Query results
|
| 1137 |
+
results_text = f"""
|
| 1138 |
+
Query Results at {timestamp}:
|
| 1139 |
+
|
| 1140 |
+
Retrieved {len(results)} rows of data
|
| 1141 |
+
|
| 1142 |
+
Columns: {', '.join(results.columns)}
|
| 1143 |
+
"""
|
| 1144 |
|
| 1145 |
# Create a document
|
| 1146 |
+
if results_text:
|
| 1147 |
+
text_splitter = RecursiveCharacterTextSplitter(
|
| 1148 |
+
chunk_size=1000,
|
| 1149 |
+
chunk_overlap=200
|
| 1150 |
+
)
|
| 1151 |
+
docs = text_splitter.create_documents([results_text])
|
| 1152 |
+
|
| 1153 |
+
# Initialize vectorstore if it doesn't exist in session state
|
| 1154 |
+
if "vectorstore" not in st.session_state:
|
| 1155 |
+
docs_data = process_documents()
|
| 1156 |
+
st.session_state.vectorstore = create_vectorstore(docs_data)
|
| 1157 |
+
|
| 1158 |
+
# Add the new documents to the vectorstore
|
| 1159 |
+
if st.session_state.vectorstore and docs:
|
| 1160 |
+
api_key = os.environ.get("OPENAI_API_KEY")
|
| 1161 |
+
if api_key:
|
| 1162 |
+
embeddings = OpenAIEmbeddings(openai_api_key=api_key)
|
| 1163 |
+
st.session_state.vectorstore.add_documents(docs)
|
| 1164 |
+
st.session_state.vectorstore.save_local("vectorstore")
|
| 1165 |
except Exception as e:
|
| 1166 |
st.warning(f"Error updating vectorstore: {str(e)}")
|
| 1167 |
|
|
|
|
| 1691 |
mime="video/mp4"
|
| 1692 |
)
|
| 1693 |
|
| 1694 |
+
# Display processed video with fallback options
|
| 1695 |
+
st.markdown("### Processed Video")
|
| 1696 |
+
st.markdown("If the video below doesn't play correctly, please use the download button above to view it locally.")
|
| 1697 |
+
try:
|
| 1698 |
+
st.video(processed_video)
|
| 1699 |
+
except Exception as e:
|
| 1700 |
+
st.error(f"Error displaying video in browser: {str(e)}")
|
| 1701 |
+
st.info("Please download the video using the button above and play it in your local media player.")
|
| 1702 |
|
| 1703 |
# Show detailed analysis results
|
| 1704 |
st.markdown("### Detailed Analysis Results")
|