Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,7 +2,6 @@ import gradio as gr
|
|
| 2 |
import numpy as np
|
| 3 |
import cv2
|
| 4 |
from PIL import Image
|
| 5 |
-
import io
|
| 6 |
import matplotlib.pyplot as plt
|
| 7 |
|
| 8 |
def extract_frames(gif_path):
|
|
@@ -22,27 +21,44 @@ def extract_frames(gif_path):
|
|
| 22 |
return None, f"Error loading GIF: {str(e)}"
|
| 23 |
|
| 24 |
def preprocess_frame(frame):
|
| 25 |
-
"""Preprocess a frame: apply Gaussian blur
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
def detect_circles(frame_diff, min_radius=20, max_radius=200):
|
| 29 |
-
"""Detect circles in a frame difference image
|
| 30 |
circles = cv2.HoughCircles(
|
| 31 |
frame_diff,
|
| 32 |
cv2.HOUGH_GRADIENT,
|
| 33 |
-
dp=1.
|
| 34 |
-
minDist=
|
| 35 |
-
param1=
|
| 36 |
-
param2=
|
| 37 |
minRadius=min_radius,
|
| 38 |
maxRadius=max_radius
|
| 39 |
)
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
def analyze_gif(gif_file):
|
| 43 |
-
"""Analyze a GIF for growing concentric circles."""
|
| 44 |
try:
|
| 45 |
-
#
|
| 46 |
gif_path = gif_file.name if hasattr(gif_file, 'name') else gif_file
|
| 47 |
|
| 48 |
# Extract frames
|
|
@@ -53,11 +69,15 @@ def analyze_gif(gif_file):
|
|
| 53 |
if len(frames) < 2:
|
| 54 |
return "GIF must have at least 2 frames for analysis.", []
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
# Initialize results
|
| 57 |
results = []
|
| 58 |
circle_data = []
|
| 59 |
min_radius = 20
|
| 60 |
-
max_radius = min(
|
| 61 |
|
| 62 |
# Process frames
|
| 63 |
for i in range(len(frames) - 1):
|
|
@@ -67,25 +87,26 @@ def analyze_gif(gif_file):
|
|
| 67 |
# Compute absolute difference between consecutive frames
|
| 68 |
frame_diff = cv2.absdiff(frame2, frame1)
|
| 69 |
# Enhance contrast for lighter pixels
|
| 70 |
-
frame_diff = cv2.convertScaleAbs(frame_diff, alpha=
|
| 71 |
-
|
| 72 |
-
# Detect circles
|
| 73 |
-
circles = detect_circles(frame_diff, min_radius, max_radius)
|
| 74 |
-
|
| 75 |
-
if circles
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
|
|
|
| 85 |
output_frame = cv2.cvtColor(frames[i + 1], cv2.COLOR_GRAY2RGB)
|
| 86 |
-
if circles
|
| 87 |
-
|
| 88 |
-
|
| 89 |
# Convert to PIL Image for Gradio
|
| 90 |
output_frame = Image.fromarray(output_frame)
|
| 91 |
results.append(output_frame)
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
import cv2
|
| 4 |
from PIL import Image
|
|
|
|
| 5 |
import matplotlib.pyplot as plt
|
| 6 |
|
| 7 |
def extract_frames(gif_path):
|
|
|
|
| 21 |
return None, f"Error loading GIF: {str(e)}"
|
| 22 |
|
| 23 |
def preprocess_frame(frame):
|
| 24 |
+
"""Preprocess a frame: apply Gaussian blur and adaptive thresholding."""
|
| 25 |
+
# Apply Gaussian blur to reduce noise
|
| 26 |
+
blurred = cv2.GaussianBlur(frame, (9, 9), 0)
|
| 27 |
+
# Adaptive thresholding to enhance lighter regions (CME features)
|
| 28 |
+
thresh = cv2.adaptiveThreshold(
|
| 29 |
+
blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
|
| 30 |
+
)
|
| 31 |
+
return thresh
|
| 32 |
|
| 33 |
+
def detect_circles(frame_diff, image_center, min_radius=20, max_radius=200):
|
| 34 |
+
"""Detect circles in a frame difference image, centered at the Sun."""
|
| 35 |
circles = cv2.HoughCircles(
|
| 36 |
frame_diff,
|
| 37 |
cv2.HOUGH_GRADIENT,
|
| 38 |
+
dp=1.5, # Increase resolution for better detection
|
| 39 |
+
minDist=100, # Prevent overlapping circles
|
| 40 |
+
param1=100, # Higher edge threshold to reduce noise
|
| 41 |
+
param2=20, # Lower accumulator threshold to detect faint circles
|
| 42 |
minRadius=min_radius,
|
| 43 |
maxRadius=max_radius
|
| 44 |
)
|
| 45 |
+
|
| 46 |
+
if circles is not None:
|
| 47 |
+
circles = np.round(circles[0, :]).astype("int")
|
| 48 |
+
# Filter circles: only keep those centered near the image center
|
| 49 |
+
filtered_circles = []
|
| 50 |
+
center_tolerance = 30 # Allow 30-pixel deviation from the center
|
| 51 |
+
for (x, y, r) in circles:
|
| 52 |
+
if (abs(x - image_center[0]) < center_tolerance and
|
| 53 |
+
abs(y - image_center[1]) < center_tolerance):
|
| 54 |
+
filtered_circles.append((x, y, r))
|
| 55 |
+
return filtered_circles if filtered_circles else None
|
| 56 |
+
return None
|
| 57 |
|
| 58 |
def analyze_gif(gif_file):
|
| 59 |
+
"""Analyze a GIF for growing concentric circles centered at the Sun."""
|
| 60 |
try:
|
| 61 |
+
# Handle Gradio file input
|
| 62 |
gif_path = gif_file.name if hasattr(gif_file, 'name') else gif_file
|
| 63 |
|
| 64 |
# Extract frames
|
|
|
|
| 69 |
if len(frames) < 2:
|
| 70 |
return "GIF must have at least 2 frames for analysis.", []
|
| 71 |
|
| 72 |
+
# Determine the image center (Sun's position)
|
| 73 |
+
height, width = frames[0].shape
|
| 74 |
+
image_center = (width // 2, height // 2) # Assume Sun is at the center
|
| 75 |
+
|
| 76 |
# Initialize results
|
| 77 |
results = []
|
| 78 |
circle_data = []
|
| 79 |
min_radius = 20
|
| 80 |
+
max_radius = min(height, width) // 2 # Limit max radius to half the image size
|
| 81 |
|
| 82 |
# Process frames
|
| 83 |
for i in range(len(frames) - 1):
|
|
|
|
| 87 |
# Compute absolute difference between consecutive frames
|
| 88 |
frame_diff = cv2.absdiff(frame2, frame1)
|
| 89 |
# Enhance contrast for lighter pixels
|
| 90 |
+
frame_diff = cv2.convertScaleAbs(frame_diff, alpha=3.0, beta=0)
|
| 91 |
+
|
| 92 |
+
# Detect circles centered at the Sun
|
| 93 |
+
circles = detect_circles(frame_diff, image_center, min_radius, max_radius)
|
| 94 |
+
|
| 95 |
+
if circles:
|
| 96 |
+
# Take the largest circle (most prominent CME feature)
|
| 97 |
+
largest_circle = max(circles, key=lambda c: c[2]) # Sort by radius
|
| 98 |
+
x, y, r = largest_circle
|
| 99 |
+
circle_data.append({
|
| 100 |
+
"frame": i + 1,
|
| 101 |
+
"center": (x, y),
|
| 102 |
+
"radius": r
|
| 103 |
+
})
|
| 104 |
+
|
| 105 |
+
# Visualize the frame with detected circle
|
| 106 |
output_frame = cv2.cvtColor(frames[i + 1], cv2.COLOR_GRAY2RGB)
|
| 107 |
+
if circles:
|
| 108 |
+
x, y, r = largest_circle
|
| 109 |
+
cv2.circle(output_frame, (x, y), r, (0, 255, 0), 2)
|
| 110 |
# Convert to PIL Image for Gradio
|
| 111 |
output_frame = Image.fromarray(output_frame)
|
| 112 |
results.append(output_frame)
|