DucHaiten commited on
Commit
fab4bb6
·
verified ·
1 Parent(s): 21648ed

Update shuffle_image.py

Browse files
Files changed (1) hide show
  1. shuffle_image.py +285 -285
shuffle_image.py CHANGED
@@ -1,285 +1,285 @@
1
- import tkinter as tk
2
- from tkinter import filedialog, ttk, messagebox
3
- import os
4
- import threading
5
- import queue
6
- import random
7
- import shutil
8
-
9
- # Biến toàn cục để điều khiển việc dừng và lưu lỗi
10
- stop_processing = False
11
- error_messages = []
12
- error_window = None
13
- selected_files = []
14
- save_directory = ""
15
- random_selected_files = []
16
- shuffle_enabled = True # Biến để lưu trạng thái xáo trộn
17
-
18
- def open_image_shuffle():
19
- global stop_processing, error_messages, error_window, selected_files, save_dir_var, status_var, num_files_var, errors_var, thread_count_var, progress, q, random_selected_files, random_file_count_var, shuffle_enabled
20
-
21
- # Tạo cửa sổ Tkinter
22
- root = tk.Tk()
23
- root.title("Image Shuffle")
24
-
25
- # Khởi tạo các biến Tkinter
26
- save_dir_var = tk.StringVar()
27
- status_var = tk.StringVar()
28
- num_files_var = tk.StringVar()
29
- errors_var = tk.StringVar(value="Errors: 0")
30
- thread_count_var = tk.StringVar(value="4")
31
- random_file_count_var = tk.StringVar(value="0")
32
- progress = tk.IntVar()
33
- q = queue.Queue()
34
-
35
- def center_window(window):
36
- window.update_idletasks()
37
- width = window.winfo_width() + 120
38
- height = window.winfo_height()
39
- x = (window.winfo_screenwidth() // 2) - (width // 2)
40
- y = (window.winfo_screenheight() // 2) - (height // 2)
41
- window.geometry(f'{width}x{height}+{x}+{y}')
42
-
43
- def select_files():
44
- global selected_files
45
- filetypes = [
46
- ("All Image files", "*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tiff;*.tif;*.svg;*.webp"),
47
- ("JPEG files", "*.jpg;*.jpeg"),
48
- ("PNG files", "*.png"),
49
- ("GIF files", "*.gif"),
50
- ("BMP files", "*.bmp"),
51
- ("TIFF files", "*.tiff;*.tif"),
52
- ("SVG files", "*.svg"),
53
- ("WEBP files", "*.webp")
54
- ]
55
- filepaths = filedialog.askopenfilenames(title="Select Image Files", filetypes=filetypes)
56
- if filepaths:
57
- selected_files.clear()
58
- selected_files.extend(filepaths)
59
- num_files_var.set(f"{len(selected_files)} files selected.")
60
-
61
- def choose_directory():
62
- global save_directory
63
- directory = filedialog.askdirectory()
64
- if directory:
65
- save_directory = directory
66
- save_dir_var.set(directory)
67
-
68
- def shuffle_and_save_images(num_random):
69
- """Chọn ngẫu nhiên và lưu ảnh."""
70
- try:
71
- if num_random > len(selected_files):
72
- messagebox.showerror("Error", "Not enough images to select.")
73
- return
74
-
75
- random_selected_files = random.sample(selected_files, num_random)
76
- if shuffle_enabled:
77
- random.shuffle(random_selected_files) # Xáo trộn danh sách file nếu được bật
78
-
79
- for i, original_path in enumerate(random_selected_files):
80
- filename = os.path.basename(original_path)
81
- new_filename = f"shuffled_{i+1:03d}_{filename}" # Tạo tên file mới với tiền tố shuffled và số thứ tự
82
- new_path = os.path.join(save_directory, new_filename)
83
- shutil.copy(original_path, new_path)
84
- q.put(i + 1) # Gửi tiến trình hoàn thành cho hàng đợi
85
-
86
- q.put(None) # Thông báo hoàn thành
87
- except Exception as e:
88
- q.put(e) # Gửi lỗi vào hàng đợi
89
-
90
- def select_and_save_sequentially(num_random):
91
- """Chọn và lưu ảnh theo thứ tự."""
92
- try:
93
- if num_random > len(selected_files):
94
- messagebox.showerror("Error", "Not enough images to select.")
95
- return
96
-
97
- step = len(selected_files) // num_random
98
- sequential_selected_files = selected_files[::step]
99
-
100
- for i, original_path in enumerate(sequential_selected_files[:num_random]):
101
- filename = os.path.basename(original_path)
102
- new_filename = f"sequential_{i+1:03d}_{filename}" # Tạo tên file mới với tiền tố sequential và số thứ tự
103
- new_path = os.path.join(save_directory, new_filename)
104
- shutil.copy(original_path, new_path)
105
- q.put(i + 1) # Gửi tiến trình hoàn thành cho hàng đợi
106
-
107
- q.put(None) # Thông báo hoàn thành
108
- except Exception as e:
109
- q.put(e) # Gửi lỗi vào hàng đợi
110
-
111
- def worker(num_random):
112
- try:
113
- progress.set(0)
114
- if shuffle_enabled:
115
- shuffle_and_save_images(num_random)
116
- else:
117
- select_and_save_sequentially(num_random)
118
- except Exception as e:
119
- q.put(e) # Gửi lỗi vào hàng đợi
120
-
121
- def update_progress():
122
- try:
123
- completed = 0
124
- total_files = int(random_file_count_var.get())
125
- while True:
126
- item = q.get()
127
- if item is None:
128
- break
129
- if isinstance(item, Exception):
130
- raise item
131
- completed = item
132
- progress.set(int((completed / total_files) * 100))
133
- if not stop_processing:
134
- root.after(0, status_var.set, f"Processed {completed} of {total_files} files")
135
- root.after(0, root.update_idletasks)
136
- if not stop_processing:
137
- root.after(0, progress.set(100))
138
- show_completion_message(completed)
139
- except Exception as e:
140
- root.after(0, status_var.set, f"Error: {e}")
141
-
142
- def show_completion_message(completed):
143
- message = f"Processing complete. {completed} files processed."
144
- if error_messages:
145
- message += f" {len(error_messages)} errors occurred."
146
- messagebox.showinfo("Process Complete", message)
147
-
148
- def validate_and_process():
149
- global stop_processing, error_messages
150
- stop_processing = False
151
- error_messages.clear()
152
- errors_var.set("Errors: 0")
153
- if not selected_files or not save_directory:
154
- status_var.set("Please select images and save location.")
155
- return
156
-
157
- num_random = int(random_file_count_var.get())
158
-
159
- threading.Thread(target=worker, args=(num_random,)).start()
160
- threading.Thread(target=update_progress).start()
161
-
162
- def validate_number(P):
163
- return P.isdigit() or P == ""
164
-
165
- def toggle_shuffle():
166
- global shuffle_enabled
167
- shuffle_enabled = shuffle_var.get() == 1
168
- if shuffle_enabled:
169
- shuffle_and_save_button.config(text="Shuffle")
170
- random_file_count_label.config(text="Number of Random Files:")
171
- else:
172
- shuffle_and_save_button.config(text="Sequentially")
173
- random_file_count_label.config(text="Number of Files to Select:")
174
-
175
- def stop_processing_func():
176
- global stop_processing
177
- stop_processing = True
178
- status_var.set("Processing stopped.")
179
-
180
- def return_to_menu():
181
- stop_processing_func()
182
- root.destroy()
183
- import main
184
- main.open_main_menu()
185
-
186
- def on_closing():
187
- return_to_menu()
188
-
189
- def show_errors():
190
- global error_window
191
- if error_window is not None:
192
- return
193
-
194
- error_window = tk.Toplevel(root)
195
- error_window.title("Error Details")
196
- error_window.geometry("500x400")
197
-
198
- error_text = tk.Text(error_window, wrap='word')
199
- error_text.pack(expand=True, fill='both')
200
-
201
- if error_messages:
202
- for error in error_messages:
203
- error_text.insert('end', error + '\n')
204
- else:
205
- error_text.insert('end', "No errors recorded.")
206
-
207
- error_text.config(state='disabled')
208
-
209
- def on_close_error_window():
210
- global error_window
211
- error_window.destroy()
212
- error_window = None
213
-
214
- error_window.protocol("WM_DELETE_WINDOW", on_close_error_window)
215
-
216
- # Tạo các thành phần giao diện
217
- validate_command = root.register(validate_number)
218
-
219
- back_button = tk.Button(root, text="<-", font=('Helvetica', 14), command=return_to_menu)
220
- back_button.pack(anchor='nw', padx=10, pady=10)
221
-
222
- title_label = tk.Label(root, text="Image Shuffle", font=('Helvetica', 16))
223
- title_label.pack(pady=10)
224
-
225
- select_files_button = tk.Button(root, text="Select Files", command=select_files)
226
- select_files_button.pack(pady=5)
227
-
228
- num_files_label = tk.Label(root, textvariable=num_files_var)
229
- num_files_label.pack(pady=5)
230
-
231
- choose_dir_button = tk.Button(root, text="Choose Save Directory", command=choose_directory)
232
- choose_dir_button.pack(pady=10)
233
-
234
- save_dir_entry = tk.Entry(root, textvariable=save_dir_var, state='readonly', justify='center')
235
- save_dir_entry.pack(pady=5, fill=tk.X)
236
-
237
- # Mô tả về các lựa chọn Shuffle và Sequential
238
- description_label = tk.Label(root, text="Choose to shuffle or select sequentially the images before saving them:", font=('Helvetica', 10))
239
- description_label.pack(pady=5)
240
-
241
- # Khung cho hai lựa chọn Shuffle và Sequential
242
- option_frame = tk.Frame(root)
243
- option_frame.pack(pady=5)
244
-
245
- shuffle_var = tk.IntVar(value=1) # Biến để lưu trạng thái xáo trộn
246
-
247
- shuffle_radio_button = tk.Radiobutton(option_frame, text="Shuffle", variable=shuffle_var, value=1, command=toggle_shuffle)
248
- shuffle_radio_button.pack(side='left', padx=5)
249
-
250
- sequential_radio_button = tk.Radiobutton(option_frame, text="Sequential", variable=shuffle_var, value=0, command=toggle_shuffle)
251
- sequential_radio_button.pack(side='left', padx=5)
252
-
253
- random_file_count_label = tk.Label(root, text="Number of Random Files:")
254
- random_file_count_label.pack(pady=5)
255
-
256
- random_file_count_entry = tk.Entry(root, textvariable=random_file_count_var, width=10, justify='center', validate="key", validatecommand=(validate_command, '%P'))
257
- random_file_count_entry.pack(pady=5)
258
-
259
- shuffle_and_save_button = tk.Button(root, text="Shuffle", command=validate_and_process)
260
- shuffle_and_save_button.pack(pady=10)
261
-
262
- thread_count_label = tk.Label(root, text="Number of Threads:")
263
- thread_count_label.pack(pady=5)
264
-
265
- thread_count_entry = tk.Entry(root, textvariable=thread_count_var, width=5, justify='center', validate="key", validatecommand=(validate_command, '%P'))
266
- thread_count_entry.pack(pady=5)
267
-
268
- stop_button = tk.Button(root, text="Stop", command=stop_processing_func)
269
- stop_button.pack(pady=5)
270
-
271
- errors_button = tk.Button(root, textvariable=errors_var, command=show_errors)
272
- errors_button.pack(pady=5)
273
-
274
- progress_bar = ttk.Progressbar(root, variable=progress, maximum=100)
275
- progress_bar.pack(pady=5, fill=tk.X)
276
-
277
- status_label = tk.Label(root, textvariable=status_var, fg="green")
278
- status_label.pack(pady=5)
279
-
280
- center_window(root)
281
- root.protocol("WM_DELETE_WINDOW", on_closing)
282
- root.mainloop()
283
-
284
- if __name__ == "__main__":
285
- open_image_shuffle()
 
1
+ import tkinter as tk
2
+ from tkinter import filedialog, ttk, messagebox
3
+ import os
4
+ import threading
5
+ import queue
6
+ import random
7
+ import shutil
8
+
9
+ # Biến toàn cục để điều khiển việc dừng và lưu lỗi
10
+ stop_processing = False
11
+ error_messages = []
12
+ error_window = None
13
+ selected_files = []
14
+ save_directory = ""
15
+ random_selected_files = []
16
+ shuffle_enabled = True # Biến để lưu trạng thái xáo trộn
17
+
18
+ def open_image_shuffle():
19
+ global stop_processing, error_messages, error_window, selected_files, save_dir_var, status_var, num_files_var, errors_var, thread_count_var, progress, q, random_selected_files, random_file_count_var, shuffle_enabled
20
+
21
+ # Tạo cửa sổ Tkinter
22
+ root = tk.Tk()
23
+ root.title("Image Shuffle")
24
+
25
+ # Khởi tạo các biến Tkinter
26
+ save_dir_var = tk.StringVar()
27
+ status_var = tk.StringVar()
28
+ num_files_var = tk.StringVar()
29
+ errors_var = tk.StringVar(value="Errors: 0")
30
+ thread_count_var = tk.StringVar(value="1")
31
+ random_file_count_var = tk.StringVar(value="0")
32
+ progress = tk.IntVar()
33
+ q = queue.Queue()
34
+
35
+ def center_window(window):
36
+ window.update_idletasks()
37
+ width = window.winfo_width() + 120
38
+ height = window.winfo_height()
39
+ x = (window.winfo_screenwidth() // 2) - (width // 2)
40
+ y = (window.winfo_screenheight() // 2) - (height // 2)
41
+ window.geometry(f'{width}x{height}+{x}+{y}')
42
+
43
+ def select_files():
44
+ global selected_files
45
+ filetypes = [
46
+ ("All Image files", "*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.tiff;*.tif;*.svg;*.webp"),
47
+ ("JPEG files", "*.jpg;*.jpeg"),
48
+ ("PNG files", "*.png"),
49
+ ("GIF files", "*.gif"),
50
+ ("BMP files", "*.bmp"),
51
+ ("TIFF files", "*.tiff;*.tif"),
52
+ ("SVG files", "*.svg"),
53
+ ("WEBP files", "*.webp")
54
+ ]
55
+ filepaths = filedialog.askopenfilenames(title="Select Image Files", filetypes=filetypes)
56
+ if filepaths:
57
+ selected_files.clear()
58
+ selected_files.extend(filepaths)
59
+ num_files_var.set(f"{len(selected_files)} files selected.")
60
+
61
+ def choose_directory():
62
+ global save_directory
63
+ directory = filedialog.askdirectory()
64
+ if directory:
65
+ save_directory = directory
66
+ save_dir_var.set(directory)
67
+
68
+ def shuffle_and_save_images(num_random):
69
+ """Chọn ngẫu nhiên và lưu ảnh."""
70
+ try:
71
+ if num_random > len(selected_files):
72
+ messagebox.showerror("Error", "Not enough images to select.")
73
+ return
74
+
75
+ random_selected_files = random.sample(selected_files, num_random)
76
+ if shuffle_enabled:
77
+ random.shuffle(random_selected_files) # Xáo trộn danh sách file nếu được bật
78
+
79
+ for i, original_path in enumerate(random_selected_files):
80
+ filename = os.path.basename(original_path)
81
+ new_filename = f"shuffled_{i+1:03d}_{filename}" # Tạo tên file mới với tiền tố shuffled và số thứ tự
82
+ new_path = os.path.join(save_directory, new_filename)
83
+ shutil.copy(original_path, new_path)
84
+ q.put(i + 1) # Gửi tiến trình hoàn thành cho hàng đợi
85
+
86
+ q.put(None) # Thông báo hoàn thành
87
+ except Exception as e:
88
+ q.put(e) # Gửi lỗi vào hàng đợi
89
+
90
+ def select_and_save_sequentially(num_random):
91
+ """Chọn và lưu ảnh theo thứ tự."""
92
+ try:
93
+ if num_random > len(selected_files):
94
+ messagebox.showerror("Error", "Not enough images to select.")
95
+ return
96
+
97
+ step = len(selected_files) // num_random
98
+ sequential_selected_files = selected_files[::step]
99
+
100
+ for i, original_path in enumerate(sequential_selected_files[:num_random]):
101
+ filename = os.path.basename(original_path)
102
+ new_filename = f"sequential_{i+1:03d}_{filename}" # Tạo tên file mới với tiền tố sequential và số thứ tự
103
+ new_path = os.path.join(save_directory, new_filename)
104
+ shutil.copy(original_path, new_path)
105
+ q.put(i + 1) # Gửi tiến trình hoàn thành cho hàng đợi
106
+
107
+ q.put(None) # Thông báo hoàn thành
108
+ except Exception as e:
109
+ q.put(e) # Gửi lỗi vào hàng đợi
110
+
111
+ def worker(num_random):
112
+ try:
113
+ progress.set(0)
114
+ if shuffle_enabled:
115
+ shuffle_and_save_images(num_random)
116
+ else:
117
+ select_and_save_sequentially(num_random)
118
+ except Exception as e:
119
+ q.put(e) # Gửi lỗi vào hàng đợi
120
+
121
+ def update_progress():
122
+ try:
123
+ completed = 0
124
+ total_files = int(random_file_count_var.get())
125
+ while True:
126
+ item = q.get()
127
+ if item is None:
128
+ break
129
+ if isinstance(item, Exception):
130
+ raise item
131
+ completed = item
132
+ progress.set(int((completed / total_files) * 100))
133
+ if not stop_processing:
134
+ root.after(0, status_var.set, f"Processed {completed} of {total_files} files")
135
+ root.after(0, root.update_idletasks)
136
+ if not stop_processing:
137
+ root.after(0, progress.set(100))
138
+ show_completion_message(completed)
139
+ except Exception as e:
140
+ root.after(0, status_var.set, f"Error: {e}")
141
+
142
+ def show_completion_message(completed):
143
+ message = f"Processing complete. {completed} files processed."
144
+ if error_messages:
145
+ message += f" {len(error_messages)} errors occurred."
146
+ messagebox.showinfo("Process Complete", message)
147
+
148
+ def validate_and_process():
149
+ global stop_processing, error_messages
150
+ stop_processing = False
151
+ error_messages.clear()
152
+ errors_var.set("Errors: 0")
153
+ if not selected_files or not save_directory:
154
+ status_var.set("Please select images and save location.")
155
+ return
156
+
157
+ num_random = int(random_file_count_var.get())
158
+
159
+ threading.Thread(target=worker, args=(num_random,)).start()
160
+ threading.Thread(target=update_progress).start()
161
+
162
+ def validate_number(P):
163
+ return P.isdigit() or P == ""
164
+
165
+ def toggle_shuffle():
166
+ global shuffle_enabled
167
+ shuffle_enabled = shuffle_var.get() == 1
168
+ if shuffle_enabled:
169
+ shuffle_and_save_button.config(text="Shuffle")
170
+ random_file_count_label.config(text="Number of Random Files:")
171
+ else:
172
+ shuffle_and_save_button.config(text="Sequentially")
173
+ random_file_count_label.config(text="Number of Files to Select:")
174
+
175
+ def stop_processing_func():
176
+ global stop_processing
177
+ stop_processing = True
178
+ status_var.set("Processing stopped.")
179
+
180
+ def return_to_menu():
181
+ stop_processing_func()
182
+ root.destroy()
183
+ import main
184
+ main.open_main_menu()
185
+
186
+ def on_closing():
187
+ return_to_menu()
188
+
189
+ def show_errors():
190
+ global error_window
191
+ if error_window is not None:
192
+ return
193
+
194
+ error_window = tk.Toplevel(root)
195
+ error_window.title("Error Details")
196
+ error_window.geometry("500x400")
197
+
198
+ error_text = tk.Text(error_window, wrap='word')
199
+ error_text.pack(expand=True, fill='both')
200
+
201
+ if error_messages:
202
+ for error in error_messages:
203
+ error_text.insert('end', error + '\n')
204
+ else:
205
+ error_text.insert('end', "No errors recorded.")
206
+
207
+ error_text.config(state='disabled')
208
+
209
+ def on_close_error_window():
210
+ global error_window
211
+ error_window.destroy()
212
+ error_window = None
213
+
214
+ error_window.protocol("WM_DELETE_WINDOW", on_close_error_window)
215
+
216
+ # Tạo các thành phần giao diện
217
+ validate_command = root.register(validate_number)
218
+
219
+ back_button = tk.Button(root, text="<-", font=('Helvetica', 14), command=return_to_menu)
220
+ back_button.pack(anchor='nw', padx=10, pady=10)
221
+
222
+ title_label = tk.Label(root, text="Image Shuffle", font=('Helvetica', 16))
223
+ title_label.pack(pady=10)
224
+
225
+ select_files_button = tk.Button(root, text="Select Files", command=select_files)
226
+ select_files_button.pack(pady=5)
227
+
228
+ num_files_label = tk.Label(root, textvariable=num_files_var)
229
+ num_files_label.pack(pady=5)
230
+
231
+ choose_dir_button = tk.Button(root, text="Choose Save Directory", command=choose_directory)
232
+ choose_dir_button.pack(pady=10)
233
+
234
+ save_dir_entry = tk.Entry(root, textvariable=save_dir_var, state='readonly', justify='center')
235
+ save_dir_entry.pack(pady=5, fill=tk.X)
236
+
237
+ # Mô tả về các lựa chọn Shuffle và Sequential
238
+ description_label = tk.Label(root, text="Choose to shuffle or select sequentially the images before saving them:", font=('Helvetica', 10))
239
+ description_label.pack(pady=5)
240
+
241
+ # Khung cho hai lựa chọn Shuffle và Sequential
242
+ option_frame = tk.Frame(root)
243
+ option_frame.pack(pady=5)
244
+
245
+ shuffle_var = tk.IntVar(value=1) # Biến để lưu trạng thái xáo trộn
246
+
247
+ shuffle_radio_button = tk.Radiobutton(option_frame, text="Shuffle", variable=shuffle_var, value=1, command=toggle_shuffle)
248
+ shuffle_radio_button.pack(side='left', padx=5)
249
+
250
+ sequential_radio_button = tk.Radiobutton(option_frame, text="Sequential", variable=shuffle_var, value=0, command=toggle_shuffle)
251
+ sequential_radio_button.pack(side='left', padx=5)
252
+
253
+ random_file_count_label = tk.Label(root, text="Number of Random Files:")
254
+ random_file_count_label.pack(pady=5)
255
+
256
+ random_file_count_entry = tk.Entry(root, textvariable=random_file_count_var, width=10, justify='center', validate="key", validatecommand=(validate_command, '%P'))
257
+ random_file_count_entry.pack(pady=5)
258
+
259
+ shuffle_and_save_button = tk.Button(root, text="Shuffle", command=validate_and_process)
260
+ shuffle_and_save_button.pack(pady=10)
261
+
262
+ thread_count_label = tk.Label(root, text="Number of Threads:")
263
+ thread_count_label.pack(pady=5)
264
+
265
+ thread_count_entry = tk.Entry(root, textvariable=thread_count_var, width=5, justify='center', validate="key", validatecommand=(validate_command, '%P'))
266
+ thread_count_entry.pack(pady=5)
267
+
268
+ stop_button = tk.Button(root, text="Stop", command=stop_processing_func)
269
+ stop_button.pack(pady=5)
270
+
271
+ errors_button = tk.Button(root, textvariable=errors_var, command=show_errors)
272
+ errors_button.pack(pady=5)
273
+
274
+ progress_bar = ttk.Progressbar(root, variable=progress, maximum=100)
275
+ progress_bar.pack(pady=5, fill=tk.X)
276
+
277
+ status_label = tk.Label(root, textvariable=status_var, fg="green")
278
+ status_label.pack(pady=5)
279
+
280
+ center_window(root)
281
+ root.protocol("WM_DELETE_WINDOW", on_closing)
282
+ root.mainloop()
283
+
284
+ if __name__ == "__main__":
285
+ open_image_shuffle()