Ich muss bei der Arbeit viele Bilder sortieren. Ich bin der Meinung, dass Sie mit freier Software effizient sortieren können, aber leider verbieten wir freie Software grundsätzlich. Dann habe ich im Geiste der Erstellung einen Bildbetrachter mit einer einfachen Sortierfunktion erstellt.
Beispiel: Ein Hundebild, das in einem Katzenbild verwechselt wurde, wird mit der Bezeichnung "1" extrahiert.
Klicken Sie hier für den Hauptteil des Sortierwerkzeugs ↓
Sortierwerkzeug.py
from file_walker import folder_walker #Selbstgemachte Funktion
from folder_selecter import file_selecter #Selbstgemachte Funktion
import os
import shutil
import subprocess
import tkinter as tk
from tkinter import Label, Tk, StringVar
from PIL import Image, ImageTk #Externe Bibliothek
#Datei lesen- - - - - - - - - - - - - - - - - - - - - - - -
def load_file(event):
global img_num, item, dir_name
#Lesen Sie die Datei
tex_var.set("Datei wird geladen...")
dir_name = file_selecter(dir_select=True)
if not dir_name == None:
file_list = folder_walker(dir_name)
#Listen Sie die Bilder auf, die aus der Datei gelesen werden können
for f in file_list:
try:
img_lst.append(Image.open(f))
filename_lst.append(f)
except:
pass
#Definieren Sie die Leinwandgröße neu, um sie an die Fenstergröße anzupassen
window_resize()
#Bildkonvertierung
for f in img_lst:
#Größe angepasst, um in die Leinwand zu passen
resized_img = img_resize_for_canvas(f, image_canvas)
#Bildkonvertierung, damit sie mit tkinter angezeigt werden kann
tk_img_lst.append(ImageTk.PhotoImage(
image=resized_img, master=image_canvas))
#Holen Sie sich die Mitte der Leinwand
c_width_half = round(int(image_canvas["width"]) / 2)
c_height_half = round(int(image_canvas["height"]) / 2)
#Anzeige auf Leinwand
img_num = 0
item = image_canvas.create_image(
c_width_half, c_height_half, image=tk_img_lst[0], anchor=tk.CENTER)
#Umschreiben des Etiketts
tex_var.set(filename_lst[img_num])
#Verstecken Sie die Ladetaste
load_btn.pack_forget()
#Anordnung der Sortierausführungsschaltflächen
assort_btn.pack()
#Zum nächsten Bild- - - - - - - - - - - - - - - - - - - - - - - -
def next_img(event):
global img_num
#Ermitteln Sie die Anzahl der geladenen Bilder
img_count = len(tk_img_lst)
#Stellen Sie fest, ob das Bild nicht das letzte ist
if img_num >= img_count - 1:
pass
else:
#Bildnummer wird angezeigt.Aktualisieren und anzeigen
img_num += 1
image_canvas.itemconfig(item, image=tk_img_lst[img_num])
#Umschreiben des Etiketts
tex_var.set(filename_lst[img_num])
#Beschriftung anzeigen
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
#Zum vorherigen Bild- - - - - - - - - - - - - - - - - - - - - - - -
def prev_img(event):
global img_num
#Stellen Sie fest, ob das Bild nicht das erste ist
if img_num <= 0:
pass
else:
#Bildnummer wird angezeigt.Aktualisieren und anzeigen
img_num -= 1
image_canvas.itemconfig(item, image=tk_img_lst[img_num])
#Umschreiben des Etiketts
tex_var.set(filename_lst[img_num])
#Beschriftung anzeigen
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
#Definieren Sie die Leinwandgröße neu aus der Fenstergröße- - - - - - - - - - - - - - - - -
def window_resize():
image_canvas["width"] = image_canvas.winfo_width()
image_canvas["height"] = image_canvas.winfo_height()
#Verkleinern Sie das Bild, um es an die Leinwandgröße anzupassen- - - - - - - - - - - - - - - - - - - -
def img_resize_for_canvas(img, canvas, expand=False):
size_retio_w = int(canvas["width"]) / img.width
size_retio_h = int(canvas["height"]) / img.height
if expand == True:
size_retio = min(size_retio_w, size_retio_h)
else:
size_retio = min(size_retio_w, size_retio_h, 1)
resized_img = img.resize((round(img.width * size_retio),
round(img.height * size_retio)))
return resized_img
#Bildschirm- - - - - - - - - - - - - - - - - - - - - - - -
def image_show(event):
img_lst[img_num].show()
#Beschriftung für Bilder- - - - - - - - - - - - - - - - - - - - - - - -
def file_assort(event):
if str(event.keysym) in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
assort_dict[filename_lst[img_num]] = str(event.keysym)
elif str(event.keysym) == "0":
del assort_dict[filename_lst[img_num]]
#Beschriftung anzeigen
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
print(assort_dict[filename_lst[img_num]])
#Ausführung der Ordnerteilung- - - - - - - - - - - - - - - - - - - - - - - -
def assort_go(event):
global f_dir
for f in assort_dict:
#Holen Sie sich den Dateinamen / Ordnernamen vor und nach dem Sortieren
f_dir = os.path.dirname(f)
f_basename = os.path.basename(f)
new_dir = os.path.join(f_dir, assort_dict[f])
new_path = os.path.join(new_dir, f_basename)
#Verzeichnis-Existenzprüfung
if not os.path.exists(new_dir):
os.mkdir(new_dir)
#Datei bewegen
shutil.move(f, new_path)
#Verschiedene Schaltflächen ein- / ausblenden
assort_btn.pack_forget()
open_folder_btn.pack()
print(new_path)
#Ordner öffnen- - - - - - - - - - - - - - - - - - - - - - - -
def folder_open(event):
#Konvertieren Sie den Pfad zum Öffnen im Explorer
open_dir_name = f_dir.replace("/", "\\")
#Öffnen Sie im Explorer
subprocess.Popen(['explorer', open_dir_name])
#Schließen Sie das tkinter-Fenster
root.destroy()
print(open_dir_name)
#Hauptverarbeitung-------------------------------------------------------
if __name__ == "__main__":
#Globale Variablen
img_lst, tk_img_lst = [], []
filename_lst = []
assort_file_list = []
assort_dict = {}
img_num = 0
f_basename = ""
#tkinter Zeichnungseinstellungen
root = tk.Tk()
root.title(u"Anzeige- / Sortierwerkzeug")
root.option_add("*font", ("Meiryo UI", 11))
#Einstellungen für das Zeichnen von Schaltflächen laden
load_btn = tk.Button(root, text="Lesen")
load_btn.bind("<Button-1>", load_file)
load_btn.pack()
#Einstellungen für Leinwandzeichnungen
image_canvas = tk.Canvas(root,
width=640,
height=480)
image_canvas.pack(expand=True, fill="both")
#Ergebnisanzeige sortieren
assort_t_var = tk.StringVar()
assort_label = tk.Label(
root, textvariable=assort_t_var, font=("Meiryo UI", 14))
assort_label.pack()
#Einstellungen für das Zeichnen von Dateinamenbeschriftungen
tex_var = tk.StringVar()
tex_var.set("Dateiname")
lbl = tk.Label(root, textvariable=tex_var, font=("Meiryo UI", 8))
lbl["foreground"] = "gray"
lbl.pack()
#Betriebseinstellung zum Zuführen von Bildern mit der rechten und linken Taste
root.bind("<Key-Right>", next_img)
root.bind("<Key-Left>", prev_img)
# 「Ctrl」+Bildanzeige mit "P"
root.bind("<Control-Key-p>", image_show)
#Zieleinstellung mit Zifferntasten sortieren
root.bind("<Key>", file_assort)
#Schaltfläche "Ausführung ausführen"
assort_btn = tk.Button(root, text="Ausführung sortieren")
assort_btn.bind("<Button-1>", assort_go)
#Schaltfläche zum Öffnen des Ordners
open_folder_btn = tk.Button(root,text="Ordner öffnen")
open_folder_btn.bind("<Button-1>", folder_open)
root.mainloop()
Die erstellte selbst erstellte Funktion wurde zum Angeben des Ordners und zum Abrufen der Dateiliste aus dem angegebenen Ordner verwendet. Speichern Sie die folgende .py-Datei im selben Ordner wie das obige Sortierwerkzeug .py.
file_selector.py
import os
import sys
import tkinter as f_tk
from tkinter import filedialog
def file_selecter(ini_folder_path = str(os.path.dirname(sys.argv[0])),
multiple= False, dir_select = False):
"""
Öffnen Sie einen Dialog und wählen Sie eine Datei oder einen Ordner aus.
Wenn Sie den ursprünglichen Ordner nicht angeben, wird der Ordner der Datei selbst geöffnet.
Sie können die Ordnerauswahl und die Dateiauswahl (mehrfach / einzeln) als Optionen auswählen.
Parameters
----------
ini_folder_path : str
Der Ordner, der zunächst geöffnet werden soll. Der Standardwert ist der Ordnerpfad der ausführbaren Datei
multiple : bool
Gibt an, ob mehrere Dateien ausgewählt werden sollen. Der Standardwert ist False. Dies ist eine einzelne Auswahl.
dir_select : bool
Ordnerauswahlmodus. Der Standardwert ist False, der sich im Dateiauswahlmodus befindet.
"""
root_fileselect=f_tk.Tk()
root_fileselect.withdraw() #Fenster ausblenden
if os.path.isfile(ini_folder_path):
ini_folder_path = os.path.dirname(ini_folder_path) #Wenn der Dateiname in der ursprünglichen Ordnerspezifikation enthalten ist, wird der Ordner der Datei zurückgegeben.
if dir_select:
select_item = f_tk.filedialog.askdirectory(initialdir=ini_folder_path) #Verzeichnisauswahlmodus
elif multiple:
select_item = f_tk.filedialog.askopenfilenames(initialdir=ini_folder_path) #Datei (Mehrfach) Auswahlmodus
else:
select_item = f_tk.filedialog.askopenfilename(initialdir=ini_folder_path) #Datei (Einzel) Auswahlmodus
root_fileselect.destroy()
if not select_item =="":
return select_item
file_walker.py
import os
import pathlib
def folder_walker(folder_path, recursive = True, file_ext = ".*"):
"""
Rufen Sie eine Liste der Dateien im angegebenen Ordner ab.
Es kann rekursiv oder nicht rekursiv durch Angabe eines Arguments erhalten werden.
Parameters
----------
folder_path : str
Zielordnerpfad
recursive : bool
Ob es rekursiv zu bekommen ist. Der Standardwert ist True, der rekursiv erfasst wird.
file_ext : str
Geben Sie die Erweiterung der zu lesenden Datei an. Beispiel:".jpg "Brauchen Sie eine Periode wie. Der Standardwert ist".*"Nicht angegeben in
"""
p = pathlib.Path(folder_path)
if recursive:
return list(p.glob("**/*" + file_ext)) # **/*Holen Sie sich Dateien rekursiv mit
else:
return list(p.glob("*" + file_ext)) #Dateien nicht rekursiv abrufen
Ich benutze auch Tkinters "Filedialog", um den Ordner auszuwählen, aber zuerst habe ich versucht, das Stammverzeichnis des Hauptfensters zu zeichnen, nachdem ich den Ordner ausgewählt habe. Dann hatte ich es schwer, weil die Hauptwurzel nicht gut angezeigt wurde oder inaktiv wurde, wahrscheinlich aufgrund der Vererbung. Wenn ich nach dem Zeichnen der Hauptwurzel den Dateidialog aufrufe, kann ich die Wurzel problemlos zeichnen.
Zuerst war ich ungeduldig, weil der Inhalt der Leinwand und des Labels mit eingebettetem tk.StringVar ()
überhaupt nicht angezeigt wurden.
Aufgrund verschiedener Untersuchungen verfügt Python über ein Konzept namens Garbage Collection, und der Inhalt von Variablen, die als unnötig (= nicht zugänglich) eingestuft werden, wird automatisch gelöscht. Als die Leinwand versuchte, auf das Objekt zu verweisen, konnte sie daher nicht gezeichnet werden, da ihr Inhalt verloren ging.
Um dies zu vermeiden, können Sie es entweder im Voraus als globale Variable laden oder eine Instanz der Klasse das Objekt laden lassen. Siehe unten für Details.
Referenzseite: [Python] Was tun, wenn Objekte wie Bilder nicht mit Tkinter gezeichnet werden können?
https://daeudaeu.com/create_image_problem/
Es fiel mir schwer, einen Weg zu finden, um auf die Parameter des Widgets zu verweisen. Schließlich musste ich es nur mit ** Widget-Name ["Parametername"] ** abrufen, wie unten gezeigt.
canvas_w = int(image_canvas["width"])
(In diesem Fall war es notwendig, die Leinwandgröße zu ermitteln, da die Fenstergröße variabel gemacht wurde, damit die Mitte der Leinwand bestimmt werden konnte.)
Ich dachte, es wäre einfach zu machen, weil es eine einfache Operation war, aber ich hatte es aufgrund mangelnden Wissens unerwartet schwer. In Zukunft möchte ich verschiedene Änderungen vornehmen, die auf der diesmal erstellten basieren, um sie benutzerfreundlicher zu gestalten. Speziell,
etc.
Recommended Posts