Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import os | |
| import shutil | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import japanize_matplotlib | |
| class DataProcessor: | |
| def __init__(self, x_max, y_max): | |
| self.x_max = x_max | |
| self.y_max = y_max | |
| self.output_folder = 'output_plots' | |
| self.bodypart_names = None # 初期化時にはNoneに設定 | |
| def process_csv(self, file_path): | |
| df = pd.read_csv(file_path, header=[1, 2]) | |
| # CSVから自動的に付属肢名を抽出 | |
| self.bodypart_names = df.columns.get_level_values(0).unique().tolist() | |
| # 最初の列(通常はscorerなど)を除外 | |
| if len(self.bodypart_names) > 0: | |
| self.bodypart_names = self.bodypart_names[1:] | |
| df_likelihood = self.extract_likelihood(df) | |
| df = self.remove_first_column_and_likelihood(df) | |
| return df, df_likelihood, self.bodypart_names # 抽出した付属肢名も返す | |
| def remove_first_column_and_likelihood(self, df): | |
| df = df.drop(df.columns[0], axis=1) | |
| df = df[df.columns.drop(list(df.filter(regex='likelihood')))] | |
| return df | |
| def extract_likelihood(self, df): | |
| # likelihood列のみを抽出する | |
| df = df[df.columns[df.columns.get_level_values(1) == 'likelihood']] | |
| df.drop(df.columns[0], axis=1) | |
| return df | |
| def plot_scatter(self, df): | |
| if not os.path.exists(self.output_folder): | |
| os.makedirs(self.output_folder) | |
| return self.plot_scatter_fixed(df, self.output_folder, self.x_max, self.y_max) | |
| def plot_scatter_fixed(self, df, output_folder, x_max, y_max): | |
| image_paths = [] | |
| bodyparts = df.columns.get_level_values(0).unique() | |
| colors = plt.cm.rainbow(np.linspace(0, 1, len(bodyparts))) | |
| for i, bodypart in enumerate(bodyparts): | |
| x = df[bodypart]['x'].values | |
| y = df[bodypart]['y'].values | |
| plt.figure(figsize=(8, 6)) | |
| plt.scatter(x, y, color=colors[i], label=bodypart) | |
| plt.scatter(x[0], y[0], color='black', marker='o', s=100) | |
| plt.text(x[0], y[0], ' Start', color='black', | |
| fontsize=12, verticalalignment='bottom') | |
| plt.xlim(0, x_max) | |
| plt.ylim(0, y_max) | |
| plt.gca().invert_yaxis() | |
| plt.title(f'トラッキングの座標({bodypart})') | |
| plt.xlabel('X Coordinate(pixel)') | |
| plt.ylabel('Y Coordinate(pixel)') | |
| plt.legend(loc='upper right') | |
| plt.savefig(f'{output_folder}/{bodypart}.png') | |
| image_paths.append(f'{output_folder}/{bodypart}.png') | |
| plt.close() | |
| plt.figure(figsize=(8, 6)) | |
| for i, bodypart in enumerate(bodyparts): | |
| x = df[bodypart]['x'].values | |
| y = df[bodypart]['y'].values | |
| plt.scatter(x, y, color=colors[i], label=bodypart) | |
| plt.xlim(0, x_max) | |
| plt.ylim(0, y_max) | |
| plt.gca().invert_yaxis() | |
| plt.title('トラッキングの座標(全付属肢)') | |
| plt.xlabel('X Coordinate(pixel)') | |
| plt.ylabel('Y Coordinate(pixel)') | |
| plt.legend(loc='upper right') | |
| plt.savefig(f'{output_folder}/all_plot.png') | |
| image_paths.append(f'{output_folder}/all_plot.png') | |
| plt.close() | |
| return image_paths | |
| def plot_trajectories(self, df): | |
| image_paths = [] | |
| bodyparts = df.columns.get_level_values(0).unique() | |
| colors = plt.cm.rainbow(np.linspace(0, 1, len(bodyparts))) | |
| for i, bodypart in enumerate(bodyparts): | |
| x = df[bodypart]['x'].values | |
| y = df[bodypart]['y'].values | |
| plt.figure(figsize=(8, 6)) | |
| plt.plot(x, color=colors[i], label=bodypart + | |
| "(x座標)", linestyle='dashed') | |
| plt.plot(y, color=colors[i], label=bodypart + "(y座標)") | |
| plt.title(f'トラッキングの座標({bodypart})') | |
| plt.xlabel('Frames') | |
| plt.ylabel('Coordinate(pixel)') | |
| plt.ylim(0, self.x_max) | |
| plt.legend(loc='upper right') | |
| plt.savefig(f'{self.output_folder}/{bodypart}_trajectories.png') | |
| image_paths.append( | |
| f'{self.output_folder}/{bodypart}_trajectories.png') | |
| plt.close() | |
| plt.figure(figsize=(8, 6)) | |
| for i, bodypart in enumerate(bodyparts): | |
| x = df[bodypart]['x'].values | |
| y = df[bodypart]['y'].values | |
| plt.plot(x, color=colors[i], label=bodypart + | |
| "(x座標)", linestyle='dashed') | |
| plt.plot(y, color=colors[i], label=bodypart + "(y座標)") | |
| plt.title(f'トラッキングの座標(全付属肢)') | |
| plt.xlabel('Frames') | |
| plt.ylabel('Coordinate(pixel)') | |
| plt.ylim(0, self.x_max) | |
| plt.legend(loc='upper right') | |
| plt.savefig(f'{self.output_folder}/all_trajectories.png') | |
| image_paths.append(f'{self.output_folder}/all_trajectories.png') | |
| plt.close() | |
| return image_paths | |
| def plot_likelihood(self, likelihood_df): | |
| image_paths = [] | |
| plt.ylim(0, 1.0) | |
| bodyparts = likelihood_df.columns.get_level_values(0).unique() | |
| colors = plt.cm.rainbow(np.linspace(0, 1, len(bodyparts))) | |
| # 付属肢ごとに尤度をプロット | |
| for i, bodypart in enumerate(bodyparts): | |
| plt.figure(figsize=(8, 6)) | |
| plt.ylim(0, 1.0) | |
| plt.plot(likelihood_df[bodypart], color=colors[i], label=bodypart) | |
| plt.xlabel('Frames') | |
| plt.ylabel('尤度') | |
| plt.title('フレーム別の尤度') | |
| # 凡例を右上の外側に表示 | |
| plt.legend(bbox_to_anchor=(1.05, 1), | |
| loc='upper left', borderaxespad=0) | |
| # 凡例がはみ出さないようにレイアウトを調整 | |
| plt.tight_layout() | |
| plt.savefig(f'{self.output_folder}/{bodypart}_likelihood.png') | |
| image_paths.append(f'{self.output_folder}/{bodypart}_likelihood.png') | |
| plt.close() | |
| # 全ての付属肢の尤度をプロット | |
| plt.figure(figsize=(8, 6)) | |
| plt.ylim(0, 1.0) | |
| for i, column in enumerate(likelihood_df.columns): | |
| plt.plot(likelihood_df[column], color=colors[i], label=column[0]) | |
| plt.xlabel('Frames') | |
| plt.ylabel('尤度') | |
| plt.title('フレーム別の尤度') | |
| # 凡例を右上の外側に表示 | |
| plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) | |
| # 凡例がはみ出さないようにレイアウトを調整 | |
| plt.tight_layout() | |
| plt.savefig(f'{self.output_folder}/likelihood_plot.png') | |
| plt.close() | |
| image_paths.append(f'{self.output_folder}/likelihood_plot.png') | |
| return image_paths | |
| class GradioInterface: | |
| def __init__(self): | |
| self.interface = gr.Interface( | |
| fn=self.process_and_plot, | |
| inputs=[ | |
| gr.File(label="CSVファイルをドラッグ&ドロップ"), | |
| gr.Number(label="X軸の最大値", value=1920), | |
| gr.Number(label="Y軸の最大値", value=1080), | |
| gr.CheckboxGroup( | |
| label="プロットするグラフを選択", | |
| choices=["散布図", "軌跡図", "尤度グラフ"], | |
| value=["散布図", "軌跡図", "尤度グラフ"], | |
| type="value" | |
| ) | |
| ], | |
| outputs=[ | |
| gr.Gallery(label="グラフ"), | |
| gr.File(label="ZIPダウンロード"), | |
| gr.Textbox(label="検出された付属肢") # 検出された付属肢を表示するための出力を追加 | |
| ], | |
| title="DeepLabCutグラフ出力ツール", | |
| description="CSVファイルからグラフを作成します。付属肢はCSVファイルから自動的に抽出されます。" | |
| ) | |
| def process_and_plot(self, file, x_max, y_max, graph_choices): | |
| processor = DataProcessor(x_max, y_max) | |
| df, df_likelihood, bodypart_names = processor.process_csv(file.name) | |
| all_image_paths = [] | |
| if "散布図" in graph_choices: | |
| all_image_paths += processor.plot_scatter(df) | |
| if "軌跡図" in graph_choices: | |
| all_image_paths += processor.plot_trajectories(df) | |
| if "尤度グラフ" in graph_choices: | |
| all_image_paths += processor.plot_likelihood(df_likelihood) | |
| # 付属肢の名前を表示用に結合 | |
| bodyparts_text = ", ".join(bodypart_names) | |
| shutil.make_archive(processor.output_folder, 'zip', processor.output_folder) | |
| return all_image_paths, processor.output_folder + '.zip', bodyparts_text | |
| def launch(self): | |
| self.interface.launch() | |
| if __name__ == "__main__": | |
| gradio_app = GradioInterface() | |
| gradio_app.launch() | |