Spaces:
Sleeping
Sleeping
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")
|