Как векторизовать задачи в python? - PullRequest
0 голосов
/ 29 октября 2019

У меня (будет) список координат;используя модуль подушки Python, я хочу сохранить серию (обрезанных) небольших изображений на диск. В настоящее время я использую цикл for для определения одной координаты за раз, затем обрезаю / сохраняю изображение перед переходом к следующей координате.

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

Я уверен, что это возможно, но я не уверен, что это просто. Я слышал такие термины, как «векторизация» и «многопоточность», которые в некоторой степени соответствуют этой ситуации. Но эти темы выходят за рамки моего опыта.

Я приложил код для справки. Тем не менее, я просто пытаюсь запросить рекомендованные стратегии. (то есть, какие методы я должен изучить, чтобы лучше адаптировать мой подход, взять несколько культур одновременно и т. д.?)


def parse_image(source, square_size, count, captures, offset=0, offset_type=0, print_coords=False):
    """
    Starts at top left corner of image. Iterates through image by square_size (width = height)
    across x values and after exhausting the row, begins next row lower by function of 
    square_size. Offset parameter is available such that, with multiple function calls, 
    overlapping images could be generated.
    """
    src = Image.open(source)
    dimensions = src.size
    max_down = int(src.height/square_size) * square_size + square_size
    max_right = int(src.width/square_size) * square_size + square_size

    if offset_type == 1:
        tl_x = 0 + offset
        tl_y = 0
        br_x = square_size + offset 
        br_y = square_size

        for y in range(square_size,max_down,square_size):
            for x in range(square_size + offset,max_right - offset,square_size):
                if (tl_x,tl_y) not in captures:
                    sample = src.crop((tl_x,tl_y,br_x,br_y))
                    sample.save(f"{source[:-4]}_sample_{count}_x{tl_x}_y{tl_y}.jpg")
                    captures.append((tl_x,tl_y))

                    if print_coords == True: 
                        print(f"image {count}: top-left (x,y): {(tl_x,tl_y)}, bottom-right (x,y): {(br_x,br_y)}")
                    tl_x = x
                    br_x = x + square_size
                    count +=1                
                else:
                    continue
            tl_x = 0 + offset
            br_x = square_size + offset
            tl_y = y
            br_y = y + square_size
    else:
        tl_x = 0
        tl_y = 0 + offset
        br_x = square_size 
        br_y = square_size + offset

        for y in range(square_size + offset,max_down - offset,square_size):
            for x in range(square_size,max_right,square_size):
                if (tl_x,tl_y) not in captures:
                    sample = src.crop((tl_x,tl_y,br_x,br_y))
                    sample.save(f"{source[:-4]}_sample_{count}_x{tl_x}_y{tl_y}.jpg")
                    captures.append((tl_x,tl_y))

                    if print_coords == True: 
                        print(f"image {count}: top-left (x,y): {(tl_x,tl_y)}, bottom-right (x,y): {(br_x,br_y)}")
                    tl_x = x
                    br_x = x + square_size
                    count +=1
                else:
                    continue
            tl_x = 0
            br_x = square_size 
            tl_y = y + offset
            br_y = y + square_size + offset
    return count

1 Ответ

1 голос
/ 29 октября 2019

То, чего вы хотите достичь здесь, - это иметь более высокую степень параллелизма. Первое, что нужно сделать, это понять, какова минимальная задача, которую вам нужно здесь выполнить, и исходя из этого, подумать, как лучше ее распределить. .

Первое, на что следует обратить внимание, это то, что существует два поведения: первое, если у вас есть offset_type 0, и другое, если у вас есть offset_type 1, разделите его на две разные функции.

Второеis: для данного изображения вы берете культуры определенного размера с заданным смещением (x, y) для всего изображения. Вы можете, например, упростить эту функцию, чтобы взять одну обрезку изображения, учитывая смещение изображения (x, y). Затем вы можете вызвать эту функцию для всех x и y изображения параллельно. Это в значительной степени то, чего стремится достичь большинство сред обработки изображений, даже больше того, что выполняет код внутри графического процессора, небольшие блоки кода, которые работают локально в изображении.

Итак, допустим, ваше изображение имеет ширину = 100, высота = 100, и вы пытаетесь сделать урожай w = 10, h = 10. Учитывая упрощенную функцию, которую я описал, я назову ее crop(img, x, y, crop_size_x, crop_size_y) Все, что вам нужно сделать, это создать образ:

img = Image.open(source)
crop_size_x = 10
crop_size_y = 10
crops = [crop(img, x, y, crop_size_x, crop_size_y) for x, y in zip(range(img.width), range(img.height))]

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...