Numpy массив - два неизвестных измерения - файлы png - PullRequest
1 голос
/ 26 марта 2020

У меня есть набор данных из множества файлов png с разными размерами в зависимости от их высоты и ширины.

Я читаю в этих файлах следующий код, чтобы получить массив numpy. В данном случае это 2D. Но на самом деле я хочу получить 3D-массив, который состоит из числа изображений n, высоты изображений h и ширины w.

import os.path
import glob
import numpy as np

def open_images(images_directory):
    pattern_to_match = os.path.join(images_directory, "*.png")
    png_files = (x for x in glob.iglob(pattern_to_match)
                 if os.path.isfile(x))
    for current_png_filename in png_files:
        print("Opening file", current_png_filename)
        with open(current_png_filename, "rb") as current_png_file:
            data = current_png_file.read()
            return np.frombuffer(data, dtype=np.uint8, offset=16)\
            .reshape(-1, 3)\
            .astype(np.float32)
            pass

directory_to_search = r"C:\Users\tobis\OneDrive\Desktop\Masterarbeit\data\2017-IWT4S-HDR_LP-dataset\crop_h1"
open_images(directory_to_search)

В данный момент я получаю массив с шаблоном типа это: (21559, 3). Я думаю, что первое число - это сочетание ширины и высоты, а последнее - это значение RGB. Я хотел бы получить массив, который выглядит следующим образом: (n, h, w).

Есть ли способ получить такой массив? К сожалению, у меня есть два неизвестных измерения. Кажется, это проблема ...

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Если у вас сглаженное изображение и вы хотите восстановить исходные размеры строки и столбца, вы можете применить heuristi c, который проверяет различные возможные комбинации и проверяет "гладкость" изображения вдоль оси строки. Эта гладкость может быть проверена, например, по среднеквадратичной ошибке последовательных строк. Это предполагает, что исходное изображение имеет некоторую структуру, также вдоль оси строки, и поэтому изменение последовательных пикселей в исходном изображении будет относительно небольшим по сравнению с другими возможными формами.

Например, скажем, исходное изображение составляет 155 x 79 пикселей, и оно было сведено в массив 155 * 79 == 12245. Основная факторизация этого 5, 31, 79. Таким образом, возможные размеры строк - это все уникальные комбинации этих простых факторов, т.е. 5, 31, 79, 155, 395, 2449. Теперь эти возможные измерения строк, в дальнейшем называемые оценками , могут быть отсортированы по двум различным категориям:

  1. Оценки, являющиеся делителем исходного измерения строки: 5, 31 и 155. Фактически это означает, что несколько пропущенных строк оригинального изображения располагаются рядом друг с другом. Таким образом, полученное изображение сохранит исходную группировку столбцов. Поскольку одинаковые столбцы остаются вместе, каждый элемент стека будет иметь примерно одинаковую гладкость. Например, если оценка равна 31, это означает, что исходная форма 31 x 5 , 79 преобразуется в 31 , 5 x 79, то есть рассматривается только каждая 5-я строка исходного изображения и пять таких копий располагаются рядом друг с другом. Для исходного изображения (т.е. оценки 155) рассматриваются корреляции длины-1 (т.е. сравнивается каждая пара последовательных строк), тогда как для оценки 31 рассматриваются корреляции длины-5 (т.е. сравниваются пары строк которые имеют еще 4 ряда между ними). Поскольку ожидается, что исходное изображение имеет некоторую гладкую структуру, плавность должна уменьшаться при сравнении более длинных диапазонов. Уменьшение сглаживания будет больше при увеличении диапазона пропусков, но оно также может полностью исчезнуть sh, если изображение содержит некоторую степень периодичности вдоль оси строки.
  2. Все остальные оценки: 79, 155, 395, 2449. Для оценки этой категории различные столбцы исходного изображения смешиваются в тестовом изображении, соответствующем оценке. Например, если оценка составляет 79, у нас есть 155 % 79 == 76, то есть каждая новая строка в тестовом изображении смещает исходные столбцы на 3 относительно предыдущей строки. Предполагая, что исходное изображение изменяется по размеру столбца, эти сдвиги будут представлять все более сильное отклонение для появляющихся последовательных строк. Поскольку этот сдвиг столбцов увеличивается от строки к строке, результирующее уменьшение сглаживания строк должно быть значительным, если только число строк не мало. Если исходное изображение столбца-periodi c с номером сдвига оценки, это может привести к идеальному согласию, однако. мы ожидаем, что гладкость уменьшится при неправильной оценке, и уменьшение будет небольшим, если оценка относится к категории (1), и больше, если оно относится к категории (2).

    Важно: Если изображения имеют период c вдоль измерения строки или столбца, это может привести к неверной оценке.

    Реализация должна охватывать следующие шаги:

    1. Вычислить простое число факторизация длины сглаженного изображения.
    2. Вычислите все уникальные оценки размера строки из комбинаций простых факторов.
    3. Для каждой оценки вычислите сглаживание строк полученного тестового изображения. Например, используйте среднеквадратичную ошибку последовательных строк (на самом деле это будет оценка неравномерности).
    4. Найдите наилучшую оценку по оценкам.

    Вот пример кода для реализации:

    import itertools as it
    import matplotlib.pyplot as plt
    import numpy as np
    from PIL import Image
    
    
    image = np.array(Image.open('example.jpg'))
    original_shape = image.shape[:2]
    image = image.reshape(-1, 3)
    
    
    def compute_prime_factors(n):
        i = 2
        while i <= n:
            if n % i == 0:
                n //= i
                yield i
            else:
                i += 1
    
    prime_factors = list(compute_prime_factors(len(image)))
    combinations = it.chain.from_iterable(it.combinations(prime_factors, r=i) for i in range(1, len(prime_factors)))
    row_dims = sorted({np.prod(x) for x in combinations})
    
    
    def test_row_dim(r):
        c = len(image) // r
        test = image.reshape(r, c, 3)
        return np.mean((test[1:] - test[:-1])**2)
    
    
    scores = [test_row_dim(r) for r in row_dims]
    best_estimate = row_dims[np.argmin(scores)]
    
    fig, ax = plt.subplots()
    ax.set(xlabel='row dimension', ylabel='score')
    ax.set_xscale('log')
    ax.plot(row_dims, scores, '-o', label='Estimations')
    ax.plot([best_estimate], [np.min(scores)], '*', ms=12, label=f'Best Estimate ({best_estimate})')
    ax.axvline(original_shape[0], label=f'Actual Dim ({original_shape[0]})', color='#2ca02c', zorder=-100, lw=1.5, ls='--')
    ax.legend()
    
    plt.figure()
    plt.imshow(image.reshape(205, -1, 3))  # second best score
    
    plt.show()
    

    Давайте проверим это на некотором изображении (H x W: 410 x 640):

    Example image
    Фото Камерона Венти на Unspla sh

    Это дает следующие оценочные баллы:

    Scores

    пики слева от наилучшей оценки - это оценки категории (1), которые имеют наименьший пропуск строки. Первичная факторизация 410 и 640 составляет 2*5*41 и 2**7 * 5 соответственно. Таким образом, оценки категории (1), наиболее близкие к исходному измерению строки, равны 205, 82 и 41 (боковые пики справа налево). Уменьшение оценки подразумевает увеличение диапазона пропуска строк и, следовательно, увеличение оценки MSE. Пик слева от наилучшей оценки соответствует оценке 205, то есть каждая вторая строка пропускается и, следовательно, две такие пропущенные строки располагаются рядом друг с другом:

    Second best score

    Как вы можете себе представить, пропуская каждую вторую строку, изображение не слишком сильно меняется, и изменение одинаково для двух параллельных версий. Отсюда и небольшая разница с оценкой MSE исходного изображения.

0 голосов
/ 26 марта 2020

Вы не можете просто прочитать такой файл изображения. Вам нужно использовать библиотеку, чтобы прочитать ее и интерпретировать высоту, ширину, цветное пространство, биты на пиксель, дату, данные GPS, марку и модель камеры и все сжатые, закодированные пиксели.

Например, с ПИЛОМ / Подушкой:

from PIL import Image 
import numpy as np 

# Open image and make sure it is RGB - not palette 
im = Image.open('image.png').convert('RGB') 

# Make into Numpy array 
na = np.array(im) 

# Check shape
print(na.shape)          # prints (480,640,3) for height, width, channels
...