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()