Как лучше всего определить, является ли изображение частью последовательности

У меня есть файл изображения, и я хотел бы проверить, является ли он частью последовательности изображений с помощью python.

Например, я начинаю с этого файла:

/projects/image_0001.jpg

и я хочу проверить, является ли файл частью последовательности, т.е.

/projects/image_0001.jpg
/projects/image_0002.jpg
/projects/image_0003.jpg
...

Проверка наличия последовательности изображений кажется простой, если я могу определить, может ли имя файла быть искусством последовательности, т.е. существует ли последовательность чисел имени файла

Сначала я попросил пользователя добавить #### к пути к файлу, где должны быть числа, и ввести начальный и конечный номер кадра для замены хэшей, но это, очевидно, не очень удобно для пользователя. Есть ли способ проверить последовательность чисел в строке с помощью регулярных выражений или чего-то подобного?


person jonathan topf    schedule 07.08.2012    source источник
comment
Что такое последовательность изображений? Можете ли вы привести пример?   -  person Blender    schedule 08.08.2012
comment
Являются ли все имена файлов в той или иной форме picture_xxxx или могут быть смешаны какие-либо старые имена файлов?   -  person Justin Blank    schedule 08.08.2012
comment
это может быть pic.xxxx.jpg или pic-xxx.jpg и т. д. Я хочу сделать сценарий как можно более гибким, чтобы учитывать предпочтения разных людей.   -  person jonathan topf    schedule 08.08.2012


Ответы (2)


Я предполагаю, что проблема больше в том, чтобы различать упорядоченные файлы на диске, чем в знании какой-либо конкретной информации о самих именах файлов.

Если это так, и вы ищете что-то достаточно умное, чтобы составить список вроде:

  • /путь/к/file_1.png
  • /путь/к/file_2.png
  • /путь/к/file_3.png
  • ...
  • /путь/к/file_10.png
  • /путь/к/image_1.png
  • /путь/к/image_2.png
  • ...
  • /путь/к/image_10.png

И получите результат: у меня есть 2 последовательности файлов: /path/to/file_#.png и /path/to/image_#.png, вам понадобится 2 прохода — 1-й проход для определения допустимых выражений для файлов, 2-й проход, чтобы выяснить, какие все остальные файлы соответствуют этому требованию.

Вам также необходимо знать, собираетесь ли вы поддерживать гэпы (должны ли они быть последовательными)

  • /путь/к/file_1.png
  • /путь/к/file_2.png
  • /путь/к/file_3.png
  • /путь/к/file_5.png
  • /путь/к/file_6.png
  • /путь/к/file_7.png

Это 1 последовательность (/path/to/file_#.png) или 2 последовательности (/path/to/file_1-3.png, /path/to/file_5-7.png)

Кроме того, как вы хотите обрабатывать числовые файлы в последовательностях?

  • /путь/к/file2_1.png
  • /путь/к/file2_2.png
  • /путь/к/file2_3.png

и т. д.

Имея это в виду, я бы сделал это следующим образом:

    import os.path
    import projex.sorting
    import re

    def find_sequences( filenames ):
        """
        Parse a list of filenames into a dictionary of sequences.  Filenames not
        part of a sequence are returned in the None key

        :param      filenames | [<str>, ..]

        :return     {<str> sequence: [<str> filename, ..], ..}
        """
        local_filenames   = filenames[:]
        sequence_patterns = {}
        sequences         = {None: []}

        # sort the files (by natural order) so we always generate a pattern
        # based on the first potential file in a sequence
        local_filenames.sort(projex.sorting.natural)

        # create the expression to determine if a sequence is possible
        # we are going to assume that its always going to be the 
        # last set of digits that makes a sequence, i.e.
        #
        #    test2_1.png
        #    test2_2.png
        #
        # test2 will be treated as part of the name
        # 
        #    test1.png
        #    test2.png
        #
        # whereas here the 1 and 2 are part of the sequence
        #
        # more advanced expressions would be needed to support
        # 
        #    test_01_2.png
        #    test_02_2.png
        #    test_03_2.png

        pattern_expr = re.compile('^(.*)(\d+)([^\d]*)$')

        # process the inputed files for sequences
        for filename in filenames:
            # first, check to see if this filename matches a sequence
            found = False
            for key, pattern in sequence_patterns.items():
                match = pattern.match(filename)
                if ( not match ):
                    continue

                sequences[key].append(filename)
                found = True
                break

            # if we've already been matched, then continue on
            if ( found ):
                continue

            # next, see if this filename should start a new sequence
            basename      = os.path.basename(filename)
            pattern_match = pattern_expr.match(basename)
            if ( pattern_match ):
                opts = (pattern_match.group(1), pattern_match.group(3))
                key  = '%s#%s' % opts

                # create a new pattern based on the filename
                sequence_pattern = re.compile('^%s\d+%s$' % opts)

                sequence_patterns[key] = sequence_pattern
                sequences[key] = [filename]
                continue

            # otherwise, add it to the list of non-sequences
            sequences[None].append(filename)

        # now that we have grouped everything, we'll merge back filenames
        # that were potential sequences, but only contain a single file to the
        # non-sequential list
        for key, filenames in sequences.items():
            if ( key is None or len(filenames) > 1 ):
                continue

            sequences.pop(key)
            sequences[None] += filenames

        return sequences

И пример использования:

>>> test =   ['test1.png','test2.png','test3.png','test4.png','test2_1.png','test2_2.png','test2_3.png','test2_4.png']
>>> results = find_sequences(test)
>>> results.keys()
[None, 'test#.png', 'test2_#.png']

Там есть метод, который ссылается на естественную сортировку, что является отдельной темой. Я просто использовал свой естественный метод сортировки из моей библиотеки projex. Он с открытым исходным кодом, поэтому, если вы хотите его использовать или увидеть, он находится здесь: http://dev.projexsoftware.com/projects/projex

Но эта тема уже обсуждалась на других форумах, поэтому просто воспользовался методом из библиотеки.

person Eric Hulser    schedule 08.08.2012

Относительно легко использовать модуль Python re, чтобы увидеть, содержит ли строка последовательность цифр. Вы можете сделать что-то вроде этого:

mo = re.findall('\d+', filename)

Это вернет список всех последовательностей цифр в filename. Если:

  • Имеется единственный результат (то есть имя файла содержит только одну последовательность цифр), И
  • Последующее имя файла имеет последовательность из одной цифры той же длины, И
  • Вторая последовательность цифр на 1 больше, чем предыдущая

... тогда, возможно, они являются частью последовательности.

person ldx.a.ldy.c    schedule 08.08.2012
comment
Если вам нужно знать, где в строке встречаются цифры, вы можете использовать: mo=list(re.finditer('\d+',filename)), который вернет список объектов соответствия, каждый из которых определяет методы mo[i].start() и mo[i].end(). Чтобы получить текст для одного из объектов соответствия, используйте mo[i].group(). См. docs.python.org/library/re.html#match-objects для получения дополнительной информации о соответствующих объектах. - person Edward Loper; 08.08.2012