самый быстрый способ найти количество цветов изображения в пикселях RGB

У меня есть случай использования, когда мне нужно найти последовательное количество цветов пикселей rgb для каждого кадра живого видео после поиска.Я нашел фрагмент кода, который делает то же самое, но с точки зрения производительности требуется около 3 секунд, чтобы дать мне результат, но в В моем случае я должен сделать этот расчет как можно быстрее, может быть 25 кадров за 1 секунду. Может ли кто-нибудь помочь мне понять, как это сделать, рефакторинг приведенного ниже кода

from PIL import Image
import timeit

starttime = timeit.default_timer()
with Image.open("netflix.png") as image:
    color_count = {}
    width, height = image.size
    print(width,height)
    rgb_image = image.convert('RGB')
    for x in range(width):
        for y in range(height):
            rgb = rgb_image.getpixel((x, y))
            if rgb in color_count:
                color_count[rgb] += 1
            else:
                color_count[rgb] = 1

    print('Pixel Count per Unique Color:')
    print('-' * 30)
    print(len(color_count.items()))
print("The time difference is :", timeit.default_timer() - starttime)

выход:

Количество пикселей на уникальный цвет: 130869

Разница во времени: 3.9660612


person user1891916    schedule 09.01.2020    source источник


Ответы (1)


Вам нужно использовать Numpy или OpenCV для быстрой обработки изображений в Python. Я сделал 9-цветную версию Паддингтона:

введите описание изображения здесь

from PIL import Image
import numpy as np

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

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

# Arrange all pixels into a tall column of 3 RGB values and find unique rows (colours)
colours, counts = np.unique(na.reshape(-1,3), axis=0, return_counts=1)

print(colours)
print(counts)

Результаты

[[ 14  48  84]
 [ 19  21  30]
 [ 33 108 163]
 [ 33 152 190]
 [ 72  58  58]
 [ 96 154 210]
 [180  89  64]
 [205 210 200]
 [208 151  99]]

[20389 40269 12820  1488 17185 25371 17050 16396  9032]

Это означает, что имеется 20 389 пикселей RGB (14,48,84) и так далее.

На моем Mac это занимает 125 мсек для изображения 400x400, что даст вам 8 кадров в секунду, поэтому вам лучше иметь как минимум 4 ядра процессора и использовать все их, чтобы получить 25+ кадров в секунду.


Обновить

Я думаю, что вы действительно можете пойти значительно быстрее, чем это. Если вы возьмете скалярное произведение каждого пикселя на [1,256,65536], вы получите одно 24-битное число для каждого пикселя, а не 3 8-битных числа. Тогда намного быстрее найти уникальные значения. Это выглядит так:

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

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

# Make a single 24-bit number for each pixel
f = np.dot(na.astype(np.uint32),[1,256,65536]) 

nColours = len(np.unique(f))     # prints 9

На моем Mac это занимает 4 мс, а не 125 мс :-)


Ключевые слова: Python, Numpy, PIL / Pillow, обработка изображений, подсчет уникальных цветов, подсчет цветов.

person Mark Setchell    schedule 09.01.2020
comment
Можно ли изменить приведенный выше код, чтобы перейти на Cython, чтобы он работал быстрее? - person user1891916; 10.01.2020
comment
@ user1891916 Может быть возможно. Он уже написан на оптимизированном C внизу, как есть. Что вы на самом деле пытаетесь делать со счетами? - person Mark Setchell; 10.01.2020
comment
Пожалуйста, посмотрите еще раз - мне удалось значительно ускорить этот процесс! - person Mark Setchell; 10.01.2020