Эффективная вставка / составное замаскированное изображение в подушке / Numpy - PullRequest
0 голосов
/ 05 октября 2018

У меня есть два изображения PNG:

heart40.png (40x40 с прозрачным фоном) - https://imgur.com/27qbUw2

background40.png (40x40) - https://imgur.com/pxF5u62

Изображение разделено на сетки 8x8 пикселей и пронумеровано от 1 -

---------------------
| 1 | 2 | 3 | 4 | 5 |
---------------------
| 6 |    ...    |10 |

...

|21 |    ...    |25 |
---------------------

Я хочу только выбранные сетки, например, (1, 5, 8, 13, 23), от heart40.pngчтобы наложить на background40.png, результат - https://imgur.com/NLq5pKH

Я использую Подушку (на самом деле не хочу переключаться на другую библиотеку изображений, если нет ограничителя показа).Следующий код работает -

import numpy as np
from math import ceil
from PIL import Image, ImageDraw


def square_id_to_xy(square_id):
    grid_count = int(40 / 8)
    y_id = ceil(square_id / grid_count)
    x_id = square_id - (grid_count * (y_id-1))
    return (x_id-1) * 8, (y_id-1) * 8


if __name__ == '__main__':
    im = Image.open("heart40.png").convert("RGBA")
    background_im = Image.open("background40.png").convert("RGBA")
    mask_im = Image.alpha_composite(background_im, im)
    show_square_ids = (1, 5, 8, 13, 23)
    for square_id in range(1, 26):
        if square_id in show_square_ids:
            continue
        x, y = square_id_to_xy(square_id)
        ImageDraw.Draw(mask_im).rectangle([(x, y), (x+7, y+7)], outline=0, fill=1)
    background_im.paste(mask_im, (0, 0), mask_im)
    background_im.save("background_pasted.png")

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

Итак, вопрос: есть ли более эффективный способ?

1 Ответ

0 голосов
/ 05 октября 2018

Я спешу, но у меня есть идея, которую вы можете использовать, даже если я не пишу и не тестирую весь код ...

grid=np.arange(1,26).reshape(5,5)

даст вам следующее:

array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10],
       [11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20],
       [21, 22, 23, 24, 25]])

Затем определите, что вы хотите:

wanted=[1,5,8,13,23]

и используйте numpy.isin(), чтобы проверить, нужна ли каждая сетка:

mask=np.isin(grid,wanted)

, что дает вам:

array([[ True, False, False, False,  True],
       [False, False,  True, False, False],
       [False, False,  True, False, False],
       [False, False, False, False, False],
       [False, False,  True, False, False]])

Теперь вы можете умножить это на 255, что даст вам черно-белую маску.Вы можете превратить маску в изображение и увеличить его в 5 раз с помощью повторной выборки NEAREST_NEIGHBOUR, чтобы получить правильный размер.

...