File size: 8,551 Bytes
61a6540
fff4aca
61a6540
 
fff4aca
61a6540
fff4aca
71132b0
 
fff4aca
dc16bdc
fff4aca
 
 
dc16bdc
fff4aca
 
 
dc16bdc
 
 
 
 
 
 
fff4aca
 
dc16bdc
fff4aca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cede2ca
fff4aca
 
 
 
 
 
 
 
 
 
 
 
 
cede2ca
fff4aca
 
cede2ca
fff4aca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61a6540
fff4aca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc16bdc
 
 
fff4aca
 
dc16bdc
fff4aca
 
dc16bdc
 
 
fff4aca
 
 
 
 
 
 
 
 
dc16bdc
 
 
 
 
fff4aca
 
 
71132b0
 
61a6540
fff4aca
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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()