Среднее значение PIL для всех непрозрачных / черных пикселей в изображении RGBA - PullRequest
0 голосов
/ 17 октября 2019

Я хочу добиться того же эффекта, что и в: cv :: среднее для не черного пикселя

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

Я пытался использовать mean_color = ImageStat.Stat(img).mean, чтобы получить средний цвет. Однако это будет включать и все прозрачные пиксели. Я хотел бы рассчитать среднее значение для всех пикселей с альфа-значением, превышающим 0. Таким образом, среднее значение для всех не полностью прозрачных пикселей.

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

1 Ответ

0 голосов
/ 17 октября 2019

Возможно, это не самое чистое решение, но я заставил его работать.

def mean(rgb, a):
    """
    Supply with an RGB PIL Image and Alpha Channel PIL Image.
    Calculates the mean over all non-fully-transparent pixels in rgb.
    """

    a_arr = np.array(a)       # Convert Alpha values Image to array.
    img_arr = np.array(rgb)   # Convert Image RGB values to array.
    mask = (a_arr > 0)        # Create mask from all non-transparent pixels
    stuff = img_arr[mask]     # Array containing all pixels that aren't transparent

    rows = len(stuff)         # Get the row size.
    if rows < 1:              # If all pixels are transparent:
        return (0, 0, 0)      # The mean is simply black
    cols = len(stuff[0])      # Else, continue with the size of cols

    data = np.zeros([cols, rows, 3], dtype = np.uint8) # Create an array to contain the pixels
    data[:] = stuff           # Put the pixels with at least a > 0 into the created array.

    c_img = Image.fromarray(data, 'RGB') # Convert back to RGB PIL Image
    return ImageStat.Stat(c_img).mean # Calculate the mean over all pixels

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

Примерно 3,44 секунды для преобразования примернотысяча 16x16 файлов изображений. Процесс был:

Взяв среднее значение, затем сохранив Image.new('RGB', (16, 16), mean).

...