Spezielle Dateinamen in eine Text-Datei schreiben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Hallo zusammen,

ich habe folgendes funktionsfähiges Skript, mit dem ich alle Dateinamen in einem Ordner durchlaufe und diese mit ein paar weiteren Angaben in eine Text-Datei schreibe.

Code: Alles auswählen

import os
import glob
import csv
from PIL import Image

basepath = "train_dataset/"
with open(os.path.join(basepath,'PETS09_train_dataset.txt')) as l:
    with open(os.path.join(basepath,'..','Dataset_train.txt'),'w') as t:
        trainwriter = csv.writer(t, delimiter=' ')
        csvreader = csv.reader(l, delimiter=',')
        imageID = None
        oldimageID = None
        bboxes = []
        numboxes = len(l.readlines())
        l.seek(0)
        for i, line in enumerate(csvreader):
            imageID = int(line[0])
            if not oldimageID is None and oldimageID != imageID or i == numboxes-1:
                trainwriter.writerow([os.path.join(basepath,"{:06d}".format(oldimageID)+".jpg")]+bboxes)
                bboxes = []
            img = Image.open(os.path.join(basepath,"{:06d}".format(imageID)+".jpg"))
            img_width, img_height = 768, 576
            x = float(line[2])
            y = float(line[3])
            w = float(line[4])
            h = float(line[5])
            bboxes.append(",".join([str(int(x)), str(int(y)), str(int(x+w)), str(int(y+h)),str(0)]))
            oldimageID = imageID
Die entsprechenden Dateinamen sehen so aus:

000191.jpg
000192.jpg
000193.jpg
...

Und hier zur Info noch die daraus entstehende Ausgabe:
train_dataset/000191.jpg 561,246,594,340,0 681,98,700,153,0 707,100,722,154,0 537,137,567,212,0 656,232,686,322,0 138,156,165,222,0 278,199,309,280,0
train_dataset/000192.jpg 567,248,601,343,0 681,98,700,153,0 707,100,723,154,0 532,138,563,214,0 662,234,691,324,0 132,156,159,222,0 270,199,301,280,0
train_dataset/000193.jpg 573,251,607,346,0 681,98,700,154,0 706,100,722,154,0 526,139,557,215,0 668,236,697,326,0 125,155,152,221,0 263,198,293,279,0
...

Jetzt habe ich die Dateinamen geändert und sie sehen so aus:

000191a.jpg
000192a.jpg
000193a.jpg
...

Ich schaffe es aber leider nicht das obige Skript so umzuschreiben, dass das "a" berücksichtigt wird.

Kann mir da jemand einen Tipp geben?

Viele Grüße
chris
Sirius3
User
Beiträge: 18240
Registriert: Sonntag 21. Oktober 2012, 17:20

l und t sind schlechte Variablennamen, weil nichtssagend.
csv-Dateien sollte man immer mit einem expliziten Encoding und newline="" öffnen.
`seek` sollte man bei Textdateien nicht benutzen. Wenn Du die Datei schon einmal gelesen hast, warum willst Du sie ein zweites Mal lesen?
`imageID = None` wird nie benutzt, sondern gleich durch einen neuen Wert überschrieben.
`not oldimageID is None` ist besser `oldimage_id is not None`.
img, img_width und img_height werden gar nicht benutzt.
Du mußt doch nur ein a einfügen.
Hast Du wirklich floats in der Datei stehen?
Das Dateiformat ist seltsam, mit den Leerzeichen-getrennten Komma-getrennten Zahlen.
Aber statt da händisch eine Gruppierung vorzunehmen, sollte man itertools.groupby verwenden:

Code: Alles auswählen

import os
import csv
from itertools import groupby
from PIL import Image

basepath = "train_dataset/"
with open(os.path.join(basepath,'PETS09_train_dataset.txt'), encoding="ASCII", newline="") as input:
    with open(os.path.join(basepath,'..','Dataset_train.txt'), encoding="ASCII", newline="", mode='w') as output:
        trainwriter = csv.writer(output, delimiter=' ')
        elements = csv.reader(input, delimiter=',')
        for image_id, boxes in groupby(elements, key=lambda row: row[0]):
            image_id = int(image_id)
            imgage_filename = os.path.join(basepath, f"{image_id:06d}a.jpg")
            # image = Image.open(image_filename)
            # img_width, img_height = 768, 576
            bounding_boxes = []
            for box in boxes:
                x, y, width, height = map(float, box[2:6])
                bounding_boxes.append(
                    f"{x:.0f},{y:.0f},{x+width:.0f},{y+width:.0f}"
                )
            trainwriter.writerow([image_filename] + bounding_boxes)
Antworten