Spaces:
Sleeping
Sleeping
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
from sklearn.cluster import KMeans | |
import gradio as gr | |
from gradio.components import Slider, Number, Image, Dataframe | |
import matplotlib | |
matplotlib.use('Agg') | |
def generate_random_points_in_circle(center_x, center_y, radius, num_points): | |
angles = np.random.uniform(0, 2 * np.pi, num_points) | |
radii = np.sqrt(np.random.uniform(0, radius**2, num_points)) | |
x_values = center_x + radii * np.cos(angles) | |
y_values = center_y + radii * np.sin(angles) | |
points = np.column_stack((x_values, y_values)) | |
return points | |
def generate_random_points_in_line_between_bounds_and_with_noise(slope, intercept, mean, std, num_points, x_min, x_max): | |
x_values = np.linspace(x_min, x_max, num_points) | |
noise = np.random.normal(mean, std, num_points) | |
y_values = slope * x_values + intercept + noise | |
points = np.column_stack((x_values, y_values)) | |
return points | |
def generate_all_points(line_num_points, circle_num_points, center_x, center_y, radius, slope, intercept, mean, std, x_min, x_max): | |
circle_points = generate_random_points_in_circle(center_x, center_y, radius, circle_num_points) | |
line_points = generate_random_points_in_line_between_bounds_and_with_noise(slope, intercept, mean, std, line_num_points, x_min, x_max) | |
all_points = np.concatenate((circle_points, line_points), axis=0) | |
return line_points, circle_points, all_points | |
def create_points_plot(line_points, circle_points): | |
fig, ax = plt.subplots() | |
x_values = line_points[:, 0] | |
y_values = line_points[:, 1] | |
ax.scatter(x_values, y_values, alpha=0.2, color="blue") | |
ax.scatter(circle_points[:, 0], circle_points[:, 1], alpha=0.2, color='red') | |
fig.canvas.draw() | |
img = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) | |
img = img.reshape(fig.canvas.get_width_height()[::-1] + (3,)) | |
plt.close(fig) | |
return img | |
def create_points_lines_plot(line_points, line_parameters): | |
fig, ax = plt.subplots() | |
x_values = line_points[:, 0] | |
y_values = line_points[:, 1] | |
ax.scatter(x_values, y_values, alpha=0.2) | |
for slope, intercept in line_parameters: | |
ax.plot(x_values, slope * x_values + intercept, alpha=0.5) | |
fig.canvas.draw() | |
img = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) | |
img = img.reshape(fig.canvas.get_width_height()[::-1] + (3,)) | |
plt.close(fig) | |
return img | |
def create_cluster_plot(line_parameters, labels, centroids): | |
fig, ax = plt.subplots() | |
ax.scatter(line_parameters[:, 0], line_parameters[:, 1], c=labels, cmap='viridis') | |
ax.set_xlabel('Slope') | |
ax.set_ylabel('Intercept') | |
fig.canvas.draw() | |
img = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) | |
img = img.reshape(fig.canvas.get_width_height()[::-1] + (3,)) | |
plt.close(fig) | |
return img | |
# Modify the compute_line_parameters function | |
def compute_line_parameters(num_iterations, all_points): | |
line_parameters = np.zeros((num_iterations, 2)) | |
for i in range(num_iterations): | |
idx = np.random.choice(all_points.shape[0], 2, replace=False) | |
x1, y1 = all_points[idx[0], 0], all_points[idx[0], 1] | |
x2, y2 = all_points[idx[1], 0], all_points[idx[1], 1] | |
line_slope = (y2 - y1) / (x2 - x1) | |
line_intercept = y1 - line_slope * x1 | |
line_parameters[i, 0] = line_slope | |
line_parameters[i, 1] = line_intercept | |
return line_parameters | |
def cluster_line_parameters(line_parameters, num_clusters, all_points, circle_points): | |
kmeans = KMeans(n_clusters=num_clusters) | |
kmeans.fit(line_parameters) | |
labels = kmeans.labels_ | |
centroids = kmeans.cluster_centers_ | |
counts = np.bincount(labels) | |
points_img = create_points_plot(all_points, circle_points) | |
points_lines_img = create_points_lines_plot(all_points, line_parameters) | |
cluster_img = create_cluster_plot(line_parameters, labels, centroids) | |
return labels, centroids, counts, points_img, points_lines_img, cluster_img | |
# Update the cluster_line_params function | |
def cluster_line_params(slope, intercept, mean, std, line_num_points, x_min, x_max, num_iterations, num_clusters, center_x, center_y, radius, circle_num_points, random_seed): | |
np.random.seed(random_seed) | |
num_iterations = int(num_iterations) | |
num_clusters = int(num_clusters) | |
line_points, circle_points, all_points = generate_all_points(line_num_points, circle_num_points, center_x, center_y, radius, slope, intercept, mean, std, x_min, x_max) | |
line_parameters = compute_line_parameters(num_iterations, all_points) | |
labels, centroids, counts, points_img, points_lines_img, cluster_img = cluster_line_parameters(line_parameters, num_clusters, all_points, circle_points) | |
centroids = np.c_[centroids, counts] | |
df = pd.DataFrame(centroids, columns=["Slope", "Intercept", "Count"]) | |
return points_img, points_lines_img, cluster_img, df | |
# Define input and output components | |
inputs = [ | |
Slider(minimum=-5.0, maximum=5.0, value=1.0, label="Line Slope"), | |
Slider(minimum=-10.0, maximum=10.0, value=0.0, label="Line Intercept"), | |
Slider(minimum=0.0, maximum=5.0, value=1.0, label="Line Error Mean"), | |
Slider(minimum=0.0, maximum=5.0, value=1.0, label="Line Error Standard Deviation"), | |
Number(value=100, precision=0, label="Number of Points Sampled from the Line"), | |
Number(value=-5, label="Minimum Value of x for Sampling"), | |
Number(value=5, label="Maximum Value of x for Sampling"), | |
Number(value=100, label="Number of Iterations for RANSAC-like Line Parameter Estimation"), | |
Number(value=3, label="Number of Clusters of Line Parameters"), | |
Number(value=0, label="X Value Center of the Circle"), | |
Number(value=0, label="Y Value Center of the Circle"), | |
Number(value=1, label="Radius of the Circle"), | |
Number(value=100, precision=0, label="Number of Points Sampled from the Circle"), | |
Number(value=0, precision=0, label="Random Seed") | |
] | |
outputs = [ | |
Image(label="Points", type="pil"), | |
Image(label="Points and Lines", type="pil"), | |
Image(label="Clustering of the line parameters", type="pil"), | |
Dataframe(label="Centroids and Counts", type="pandas") | |
] | |
# Create the Gradio interface | |
interface = gr.Interface( | |
fn=cluster_line_params, | |
inputs=inputs, | |
# outputs=["numpy", "numpy", "image"], | |
outputs=outputs, | |
title="Line Parameter Clustering", | |
description="Cluster line parameters with Gaussian noise", | |
allow_flagging="never" | |
) | |
# Launch the interface | |
interface.launch() |