Bilder mit fortlaufender nummer

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Bencem
User
Beiträge: 3
Registriert: Samstag 23. Dezember 2017, 10:46

Hallo zusammen, ich bin neu in dem ganzen und möchte eine fotobox bauen.
Hab mir nen raspberry pi 3 besorgt mit ner camera.
Hab soweit das hier in python eingegeben. from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview
sleep(5)
camera.capture(ˋ/home/pi/image001.jpg´)
camera.stop_preview()

So kann ich ein foto machen was auch gespeichert wird als image1.jpg
Ich möchte aber bei dem nächsten foto einer 002 dahinter haben so das er mir das erste image nicht löscht
also image001.jpg, image002.jpg, image03.jpg usw

Kann mir jemand dabei behilflich sein?
Danke im vorraus
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Bencem: Du mußt schauen, ob die Datei schon existiert und wenn ja, die nächste Datei nehmen. Oder Du speichert Dir irgendwo einen Zähler. `start_preview` solltest Du auch aufrufen.
Bencem
User
Beiträge: 3
Registriert: Samstag 23. Dezember 2017, 10:46

Sirius3 hat geschrieben:@Bencem: Du mußt schauen, ob die Datei schon existiert und wenn ja, die nächste Datei nehmen. Oder Du speichert Dir irgendwo einen Zähler. `start_preview` solltest Du auch aufrufen.
Verstehe nicht was du damit meinst mit die nächste datei nehmen, er soll doch immer eine neue datei erstellen mit der endung 002,003 usw.
und was meinst du mit start_preview aufrufen, was hat das für ne auswirkung oder wofür ist das?
Ich kenne mich nicht so gut aus das ich da was reinschreiben kann brauche leider genaue angaben
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast beim abtippen des Programms einen Fehler gemacht und die Klammern () hinter start_preview vergessen.

Und „nächste“ bedeutet, das du nachschauen musst, welche Dateien schon existieren, bevor du eine neue schreibst. Denn das Skript hat beim Neustart Amnesie, und weiß nicht, was es schon mal geschrieben hat.

Das ist halt programmieren. Es wirkt so, als ob du das weder kannst noch willst. Das ist ok, nur solltest du dann eher nach einer kompletten Fotoboxlösung schauen, statt das zeilenweise zusammenzustoppeln.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hab mal was gebastelt:

Code: Alles auswählen

import glob
import os

def make_filename(prefix, suffix, path='.', num_digits=3):
    pattern = '{}*{}'.format(prefix, suffix)
    filenames = glob.iglob(os.path.join(path, pattern))
    try:
        count = int(max(filenames).lstrip(prefix).rstrip(suffix)) + 1
    except ValueError:
        # max() or int() failed (no filenames, no digits, ...)
        count = 0
    formatted_count = str(count).zfill(num_digits)
    return prefix + formatted_count + suffix
Ist recht viel Gefrickel, aber sofern ich kein Riesenbrett vorm Kopf hab, geht es nicht wirklich schöner. Sonst halt eine fertige Lösung nehmen...

EDIT:
Alternativ kann man das auch mit regulären Ausdrücken lösen. Wollte das hier nur erstmal mit Pythons str()-Methoden umsetzen. Prinzipiell lässt sich das noch robuster implementieren, womit der Code allerdings noch komplexer wäre. Oder man schreibt wie gesagt einen ausgeklügelten regulären Ausdruck dafür.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hier die Regex-Variante:

Code: Alles auswählen

import re
import os

def make_filename(prefix, suffix, path='.', num_digits=3):
    pattern = re.compile(prefix + r'(\d+)' + suffix)
    matches = map(pattern.match, os.listdir(path))
    counts = [int(m.group(1)) for m in matches if m]
    next_count = max(counts) + 1 if counts else 1
    formatted_count = str(next_count).zfill(num_digits)
    return prefix + formatted_count + suffix

if __name__ == '__main__':
    print(make_filename('image', '.jpg'))
Bencem
User
Beiträge: 3
Registriert: Samstag 23. Dezember 2017, 10:46

snafu hat geschrieben:Hier die Regex-Variante:

Code: Alles auswählen

import re
import os

def make_filename(prefix, suffix, path='.', num_digits=3):
    pattern = re.compile(prefix + r'(\d+)' + suffix)
    matches = map(pattern.match, os.listdir(path))
    counts = [int(m.group(1)) for m in matches if m]
    next_count = max(counts) + 1 if counts else 1
    formatted_count = str(next_count).zfill(num_digits)
    return prefix + formatted_count + suffix

if __name__ == '__main__':
    print(make_filename('image', '.jpg'))
Danke für eure mühe. Wo schrieb ich das rein unter meinen code oder dazwischen? Wie gesagt kenne mich nich so gut damit aus das heißt aber auch nich das ich nich lernen will wie manche sagen.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Na, du schreibst es an die Stelle, wo du den gewünschten Bildnamen einsetzen möchtest. Besser noch: Du belässt es als Funktion und rufst an der entsprechenden Stelle die Funktion auf.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Aus Spaß an der Freude hier noch etwas robuster und objektorientiert:

Code: Alles auswählen

import os
import re

class FileNumberer(object):
    def __init__(self, prefix, suffix, path='.', num_digits=3):
        self.prefix = prefix
        self.suffix = suffix
        self.path = path
        self.num_digits = num_digits

    @property
    def pattern(self):
        if self.num_digits is None:
            digit_re = r'(\d+)'
        elif self.num_digits <= 0:
            raise ValueError('num_digits must be >= 1')
        else:
            digit_re = r'(\d{%i})' % self.num_digits
        prefix = re.escape(self.prefix)
        suffix = re.escape(self.suffix)
        return re.compile(prefix + digit_re + suffix)

    @property
    def matching_files(self):
        filenames = os.listdir(self.path)
        return filter(self.pattern.match, filenames)

    @property
    def next_number(self):
        filenames = os.listdir(self.path)
        matches = map(self.pattern.match, filenames)
        numbers = [int(m.group(1)) for m in matches if m]
        return max(numbers) + 1 if numbers else 1

    @property
    def next_filename(self):
        formatted_number = str(self.next_number).zfill(self.num_digits)
        return self.prefix + formatted_number + self.suffix

def main():
    image_numberer = FileNumberer('image', '.jpg')
    print('Matching filenames:')
    print(list(image_numberer.matching_files))
    print('Next filename:', image_numberer.next_filename)

if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@snafu: zu Deiner nicht-RegEx-Lösung: `lstrip` und `rstrip` machen nicht das, was Du denkst, was sie machen, das kann zu bösen Überraschungen führen. Und statt str und zfill nimmt man besser .format:

Code: Alles auswählen

def make_filename(prefix, suffix, path='.', num_digits=3):
    pattern = '{}*{}'.format(prefix, suffix)
    filenames = glob.iglob(os.path.join(path, pattern))
    try:
        count = int(max(filenames)[len(prefix):-len(suffix)]) + 1
    except ValueError:
        # max() or int() failed (no filenames, no digits, ...)
        count = 1
    formatted_count = str(count).zfill(num_digits)
    return "{}{:0{}d}{}".format(prefix, count, num_digits, suffix)
Zu Deiner Klassenlösung: nicht alles ist sinnvollerweise ein Property. Zumindest next_number und next_filename sind eigentlich Funktionen, womit dann eigentlich die ganze Klasse wieder zu einer oder zwei Funktionen zusammengefasst werden kann. Warum verwendet next_number nicht matching_files? `pattern` kann zwar mit num_digits = None umgehen, next_filename aber nicht.
Antworten