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, bodypart_names, x_max, y_max): self.bodypart_names = bodypart_names.split(',') self.x_max = x_max self.y_max = y_max self.output_folder = 'output_plots' def process_csv(self, file_path): df = pd.read_csv(file_path, header=[1, 2]) df_likelihood = self.extract_likelihood(df) df = self.remove_first_column_and_likelihood(df) df = self.rename_bodyparts(df) return df, df_likelihood 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 rename_bodyparts(self, df): current_names = df.columns.get_level_values(0).unique() if len(self.bodypart_names) != len(current_names): raise ValueError( "The length of bodypart_names must be equal to the number of bodyparts.") mapping = dict(zip(current_names, self.bodypart_names)) new_columns = [(mapping[col[0]], col[1]) if col[0] in mapping else col for col in df.columns] df.columns = pd.MultiIndex.from_tuples(new_columns) 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) current_names = df.columns.get_level_values(0).unique() mapping = dict(zip(current_names, self.bodypart_names)) new_columns = [(mapping[col[0]], col[1]) if col[0] in mapping else col for col in df.columns] df.columns = pd.MultiIndex.from_tuples(new_columns) 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.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'トラッキングの座標({bodypart})') plt.xlabel('Frames') plt.ylabel('Coordinate(pixel)') 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 # 以下のGradioInterfaceクラスとメイン実行部分は変更なし class GradioInterface: def __init__(self): self.interface = gr.Interface( fn=self.process_and_plot, inputs=[ gr.File(label="CSVファイルをドラッグ&ドロップ"), gr.Textbox(label="付属肢の名前(カンマ区切り)", value="指節1, 指節2, 指節3, 指節4, 指節5, 指節6, 指節7, 指節8, 指節9,指節10, 指節11, 指節12, 指節13, 指節14, 触角(左), 触角(右), 頭部, 腹尾節"), 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ダウンロード") ], title="DeepLabCutグラフ出力ツール", description="CSVファイルからグラフを作成します。" ) def process_and_plot(self, file, bodypart_names, x_max, y_max, graph_choices): processor = DataProcessor(bodypart_names, x_max, y_max) df, df_likelihood = 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) shutil.make_archive(processor.output_folder, 'zip', processor.output_folder) return all_image_paths, processor.output_folder + '.zip' def launch(self): self.interface.launch() if __name__ == "__main__": gradio_app = GradioInterface() gradio_app.launch()