-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimage-fft-gui.py
234 lines (194 loc) · 11.4 KB
/
image-fft-gui.py
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk
from scipy.fft import fft2, ifft2
import numpy as np
import tkinter.filedialog as filedialog
class ImageProcessingApp:
def __init__(self, root):
self.root = root
self.root.title("FourierVision")
# 画像ファイルを選択する
file_path_in = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.bmp")])
if file_path_in:
self.image = Image.open(file_path_in)
#self.display_image(self.image)
# メインフレーム
main_frame = ttk.Frame(root)
main_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
# 操作フレーム
control_frame = ttk.Frame(main_frame, width=300)
control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10)
# 説明ラベル
explain_label = ttk.Label(control_frame,text="This is an app for performing Fourier transform on images.")
explain_label.pack(side=tk.TOP,pady=(10,5))
# 作成者情報ラベル
creator_label = ttk.Label(control_frame, text="Created by Hattori")
creator_label.pack(side=tk.TOP, pady=(10, 5))
# ボタンフレーム
button_frame = ttk.Frame(control_frame)
button_frame.pack(pady=(50,100),side=tk.BOTTOM)
# 説明ラベル
explain2_label = ttk.Label(button_frame,text="変換ボタンを押すまでは全てのタグは同じ写真です.\n変換ボタンを押すと画像が変換されます.\n選択した周波数範囲のみが残ります.")
explain2_label.pack(side=tk.TOP,pady=(10,5))
# 変換ボタン
self.convert_button = ttk.Button(button_frame, text="変換", command=self.apply_filter)
self.convert_button.pack(fill=tk.X,pady=(50,50))
# 保存ボタン
self.save_button = ttk.Button(button_frame, text="保存", command=self.save_image)
self.save_button.pack(fill=tk.X)
# フィルタ設定フレーム
filter_frame = ttk.LabelFrame(control_frame, text="フィルタ設定")
filter_frame.pack(pady=10, fill=tk.Y)
# 縦方向フィルタ設定
self.vertical_filter_frame = ttk.Frame(filter_frame)
self.vertical_filter_frame.pack(pady=5)
ttk.Label(self.vertical_filter_frame, text="縦方向バンドパスフィルタ").grid(row=0, column=0, columnspan=2)
ttk.Label(self.vertical_filter_frame, text="上限").grid(row=1, column=0, sticky=tk.E)
self.vertical_upper_slider = ttk.Scale(self.vertical_filter_frame, from_=0, to=2000, length=150)
self.vertical_upper_slider.grid(row=1, column=1)
self.vertical_upper_value_label = ttk.Label(self.vertical_filter_frame, text="0",width=4)
self.vertical_upper_value_label.grid(row=1, column=2, padx=(0,0))
ttk.Label(self.vertical_filter_frame, text="下限").grid(row=2, column=0, sticky=tk.E)
self.vertical_lower_slider = ttk.Scale(self.vertical_filter_frame, from_=0, to=2000, length=150)
self.vertical_lower_slider.grid(row=2, column=1)
self.vertical_lower_value_label = ttk.Label(self.vertical_filter_frame, text="0",width=4)
self.vertical_lower_value_label.grid(row=2, column=2, padx=(0,0))
# 横方向フィルタ設定
self.horizontal_filter_frame = ttk.Frame(filter_frame)
self.horizontal_filter_frame.pack(pady=5)
ttk.Label(self.horizontal_filter_frame, text="横方向バンドパスフィルタ").grid(row=0, column=0, columnspan=2)
ttk.Label(self.horizontal_filter_frame, text="上限").grid(row=1, column=0, sticky=tk.E)
self.horizontal_upper_slider = ttk.Scale(self.horizontal_filter_frame, from_=0, to=2000, length=150)
self.horizontal_upper_slider.grid(row=1, column=1)
self.horizontal_upper_value_label = ttk.Label(self.horizontal_filter_frame, text="0",width=4)
self.horizontal_upper_value_label.grid(row=1, column=2, padx=(0,0))
ttk.Label(self.horizontal_filter_frame, text="下限").grid(row=2, column=0, sticky=tk.E)
self.horizontal_lower_slider = ttk.Scale(self.horizontal_filter_frame, from_=0, to=2000, length=150)
self.horizontal_lower_slider.grid(row=2, column=1)
self.horizontal_lower_value_label = ttk.Label(self.horizontal_filter_frame, text="0",width=4)
self.horizontal_lower_value_label.grid(row=2, column=2, padx=(0,0))
# 二値化設定
ttk.Label(filter_frame, text="二値化設定").pack(pady=5)
ttk.Label(filter_frame, text="閾値").pack()
self.threshold_slider = ttk.Scale(filter_frame, from_=0, to=255, length=150)
self.threshold_slider.pack()
# 二値化の閾値スライダーの値を表示するラベル
self.threshold_value_label = ttk.Label(filter_frame, text="0")
self.threshold_value_label.pack(pady=5)
# 画像表示フレーム
self.image_frame = ttk.LabelFrame(main_frame, text="画像表示")
self.image_frame.pack(side=tk.LEFT, expand=True, fill=tk.BOTH, padx=10, pady=10)
# タブコンテナ
self.tab_control = ttk.Notebook(self.image_frame)
self.tab_control.pack(expand=True, fill=tk.BOTH)
# 元画像タブ
self.original_tab = ttk.Frame(self.tab_control)
self.tab_control.add(self.original_tab, text="元画像")
self.original_image_label = ttk.Label(self.original_tab)
self.original_image_label.pack(expand=True, fill=tk.BOTH)
# フーリエ変換タブ
self.fft_tab = ttk.Frame(self.tab_control)
self.tab_control.add(self.fft_tab, text="フーリエ変換")
self.fft_image_label = ttk.Label(self.fft_tab)
self.fft_image_label.pack(expand=True, fill=tk.BOTH)
self.fft_img_pil = None # フーリエ変換画像を格納する変数を追加
# 逆フーリエ変換タブ
self.ifft_tab = ttk.Frame(self.tab_control)
self.tab_control.add(self.ifft_tab, text="逆フーリエ変換")
self.ifft_image_label = ttk.Label(self.ifft_tab)
self.ifft_image_label.pack(expand=True, fill=tk.BOTH)
self.ifft_img_pil = None # フーリエ変換画像を格納する変数を追加
# 二値化タブ
self.binary_tab = ttk.Frame(self.tab_control)
self.tab_control.add(self.binary_tab, text="二値化")
self.binary_image_label = ttk.Label(self.binary_tab)
self.binary_image_label.pack(expand=True, fill=tk.BOTH)
self.binary_img_pil = None # フーリエ変換画像を格納する変数を追加
# 画像の読み込みと初期表示
#self.image = Image.open("img_origin.jpg")
self.display_image(self.image, self.original_image_label)
self.display_image(self.image, self.fft_image_label)
self.display_image(self.image, self.ifft_image_label)
self.display_image(self.image, self.binary_image_label)
# スライダーの値が変更されたときに更新関数を呼び出す
self.vertical_upper_slider.config(command=self.update_slider_value_labels)
self.vertical_lower_slider.config(command=self.update_slider_value_labels)
self.horizontal_upper_slider.config(command=self.update_slider_value_labels)
self.horizontal_lower_slider.config(command=self.update_slider_value_labels)
self.threshold_slider.config(command=self.update_slider_value_labels)
# 各スライダーの値が変更されたときに更新する関数
def update_slider_value_labels(self, *args):
self.vertical_upper_value_label["text"] = int(self.vertical_upper_slider.get())
self.vertical_lower_value_label["text"] = int(self.vertical_lower_slider.get())
self.horizontal_upper_value_label["text"] = int(self.horizontal_upper_slider.get())
self.horizontal_lower_value_label["text"] = int(self.horizontal_lower_slider.get())
self.threshold_value_label["text"] = int(self.threshold_slider.get())
def apply_filter(self):
# フィルタ設定の取得
vertical_upper = self.vertical_upper_slider.get()
vertical_lower = self.vertical_lower_slider.get()
horizontal_upper = self.horizontal_upper_slider.get()
horizontal_lower = self.horizontal_lower_slider.get()
threshold = self.threshold_slider.get()
# 画像をnumpy配列に変換
img_array = np.array(self.image)
# 画像をグレースケールに変換
gray_img_array = img_array.mean(axis=2)
# フーリエ変換
fft_img = fft2(gray_img_array)
# バンドパスフィルタ適用
fft_img_filtered = np.zeros_like(fft_img)
fft_img_filtered[int(vertical_lower):int(vertical_upper), int(horizontal_lower):int(horizontal_upper)] = fft_img[int(vertical_lower):int(vertical_upper), int(horizontal_lower):int(horizontal_upper)]
# 逆フーリエ変換
ifft_img = ifft2(fft_img_filtered).real
# 二値化
binary_img = np.where(ifft_img < threshold, 0, 255).astype(np.uint8)
# 画像をPIL形式に戻す
self.fft_img_pil = Image.fromarray(np.abs(fft_img_filtered).astype(np.uint8))
self.ifft_img_pil = Image.fromarray(ifft_img.astype(np.uint8))
self.binary_img_pil = Image.fromarray(binary_img.astype(np.uint8))
# 画像を表示
self.display_image(self.image, self.original_image_label)
self.display_image(self.fft_img_pil, self.fft_image_label)
self.display_image(self.ifft_img_pil, self.ifft_image_label)
self.display_image(self.binary_img_pil, self.binary_image_label)
# 画像をインスタンス変数に格納
#self.fft_image = fft_img_pil
#self.ifft_image = ifft_img_pil
#self.binary_image = binary_img_pil
def display_image(self, image, label):
# 画像をリサイズしてLabelに表示
image.thumbnail((700, 1200))
photo = ImageTk.PhotoImage(image)
label.configure(image=photo)
label.image = photo
def save_image(self):
# 保存する画像を選択
file_path = filedialog.asksaveasfilename(defaultextension=".jpg", filetypes=[("JPEG files", "*.jpg"), ("All files", "*.*")])
if file_path:
# 選択されたタブに応じて画像を取得
current_tab_index = self.tab_control.index("current")
if current_tab_index == 1:
image_pil = self.fft_img_pil
elif current_tab_index == 2:
image_pil = self.ifft_img_pil
elif current_tab_index == 3:
image_pil = self.binary_img_pil
else:
image_pil = None
if image_pil:
# 画像を取得して保存
#print(image_label.winfo_children())
image_pil.save(file_path)
#image_data = image_label.winfo_children()[0].cget("image")
#image_data.write(file_path)
print(f"画像を {file_path} に保存しました。")
else:
print("保存する画像がありません。")
def main():
root = tk.Tk()
app = ImageProcessingApp(root)
root.mainloop()
if __name__ == "__main__":
main()