[Python] Ich habe einen Bildbetrachter mit einer einfachen Sortierfunktion erstellt.

Hintergrund

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.

Fertiges Bild

Beispiel: Ein Hundebild, das in einem Katzenbild verwechselt wurde, wird mit der Bezeichnung "1" extrahiert. 仕分けツールデモ_.gif

  1. Geben Sie nach dem Klicken auf die Schaltfläche "Laden" den Ordner an. Anschließend werden alle Bilder unter dem Verzeichnis einschließlich des Unterverzeichnisses gelesen.
  2. Senden Sie das Bild mit "←" und "→" und drücken Sie die Zifferntasten, um die gedrückte Tastennummer auf dem angezeigten Bild zu kennzeichnen. (Beschriftung = Die eingegebene Taste (Nummer) wird unter dem Dateinamen angezeigt. Drücken Sie übrigens 0, um die Beschriftung abzubrechen.)
  3. Führen Sie die Ordnerteilung basierend auf dem Inhalt aus, der mit der Schaltfläche "Ausführung sortieren" gekennzeichnet ist.
  4. Danach können Sie den Ordner der geladenen Bilddateien öffnen, indem Sie auf die Schaltfläche "Ordner öffnen" klicken.

Vollständiger Code

Klicken Sie hier für den Hauptteil des Sortierwerkzeugs ↓

** Sortierwerkzeug ** (Klicken, um Code anzuzeigen)

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 ** (Klicken, um den Code anzuzeigen)

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 ** (Klicken, um den Code anzuzeigen)

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

Was ich studiert habe

Eltern-Kind-Beziehung des Tkinter-Fensters

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.

Das Konzept der Müllabfuhr

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/

Beachten Sie die Parameter des tkinter-Widgets

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.)

Eindrücke / Zukunft

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

[Python] Ich habe einen Bildbetrachter mit einer einfachen Sortierfunktion erstellt.
Ich habe mit Python einen einfachen Blackjack gemacht
Ich habe mit Python eine Lotterie gemacht.
Ich habe mit Python einen Daemon erstellt
Ich habe ein einfaches Tippspiel mit tkinter of Python gemacht
Ich habe eine einfache Buch-App mit Python + Flask ~ Introduction ~ erstellt
Ich habe mit Python einen Zeichenzähler erstellt
Ich habe mit Python eine Hex-Map erstellt
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Ich habe mit Python eine Einstellungsdatei erstellt
Ich habe mit Python einen Neuronensimulator erstellt
Ich habe eine einfache Schaltung mit Python gemacht (AND, OR, NOR, etc.)
Ich habe versucht, mit Python + OpenCV eine Bildähnlichkeitsfunktion zu erstellen
Ich habe mit Python eine Bot-Wettervorhersage gemacht.
Ich habe eine GUI-App mit Python + PyQt5 erstellt
Ich habe versucht, mit Python einen Twitter-Blocker für faule Mädchen zu machen
[Python] Ich habe mit Tkinter einen Youtube Downloader erstellt.
Ich habe eine einfache Brieftasche aus Bitcoin mit Pycoin gemacht
Ich habe mit Python ein Bin-Picking-Spiel gemacht
Mattermost Bot mit Python gemacht (+ Flask)
Ich habe einen Twitter BOT mit GAE (Python) gemacht (mit einer Referenz)
Ich habe mit Python ein Weihnachtsbaum-Beleuchtungsspiel gemacht
Ich habe einen Blackjack mit Python gemacht!
Ich habe mit Python eine App für die Benachrichtigung über Netznachrichten erstellt
Sortieren von Bilddateien mit Python (2)
Bilddateien mit Python sortieren
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
Ich habe einen Python-Text gemacht
Ich habe mit Python einen Blackjack gemacht.
Ich habe Wordcloud mit Python gemacht.
Ich habe ein Paket erstellt, um Zeitreihen mit Python zu filtern
Ich habe mit Tkinter of Python ein Puzzlespiel (wie) gemacht
Schneiden Sie ein Bild mit Python aus
Ich habe einen Line-Bot mit Python gemacht!
Ich habe eine SMS mit Python gesendet
[Python] Ich habe eine Funktion erstellt, die AES entschlüsselt und entschlüsselt, indem ich sie einfach mit pycrypto geworfen habe.
Ich habe eine Funktion zum Trimmen des Bildes von Python openCV erstellt. Verwenden Sie sie daher bitte.
Ich habe eine Bibliothek erstellt, die Konfigurationsdateien mit Python einfach lesen kann
Ich habe ein Paket erstellt, das morphologische Analysegeräte mit Python vergleichen kann
Versuchen Sie, mit Python3 eine Zeichenfolge aus einem Bild zu extrahieren
Ich habe mit Python, Flask und Heroku ein Nyanko-Tweet-Formular erstellt
Ich habe viele Dateien für die RDP-Verbindung mit Python erstellt
Ich habe ein Shuffle gemacht, das mit Python zurückgesetzt (zurückgesetzt) werden kann
Ich habe einen Pokerspielserver Chat-Holdem mit Websocket mit Python erstellt
Ich habe eine Python-Wrapper-Bibliothek für die Docomo-Bilderkennungs-API erstellt.
Erstellen Sie mit Class einen Python-Funktionsdekorator
Erstellen einer einfachen Power-Datei mit Python
Einfacher RSS-Reader mit Django
Erstellen Sie mit PySimpleGUI einen Bildverarbeitungs-Viewer
Ich habe ein Pay-Management-Programm in Python erstellt!
Einfacher Slack API-Client mit Python
Erstellen Sie mit Python + PIL ein Dummy-Image.
Ich habe eine Heatmap mit Seaborn [Python] gezeichnet.
Ich habe eine funktionale Sprache mit Python ausprobiert
Was ich mit Python-Arrays gemacht habe
Ich habe ein Lebensspiel mit Numpy gemacht