Размывание изображения: как повысить эффективность массива пикселей в чистом питоне? - PullRequest
0 голосов
/ 08 апреля 2019

В настоящее время я работаю над сценарием Python 3.5 для преобразования изображения BMP (или любого пиксельного массива) в изображение GIF.Я хотел бы сделать это без использования тяжелых модулей Python, таких как Numpy или Pillow, я работаю в квази чистом Python.Чтобы добиться этого, мне нужно уменьшить количество цветов до 256 и применить дизеринг к пикселю.У меня уже есть полностью работающий скрипт, но он очень медленный (около 3 с для изображения 570x370 и около 30 с для изображения 1900x1100), и это недопустимо: -)

Вот код, который я сделал.«px» - это массив [высота] x [ширина] x [3 цвета], созданный следующим образом:

px = []
for i in range(height):
    px.append([[0,0,0]]*width)

и заполненный значениями bmp (например, px [10] [12] = [101,203,255)])

С помощью этого кода выполняется уменьшение цвета и сглаживание (с помощью Sierra Lite Dithering http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/):

data=bytearray(height*width) # Output data array
i = 0
for ligne in range(height):
    for col in range(width):
        [R,G,B] = px[ligne][col] # Get colors of pixel
        Idx = GetColorIdx(R,G,B) # Get table index of nearest color
        data[i] = Idx            # Store index
        i += 1
        [Rnew,Gnew,Bnew] = GetIdxColor(Idx) # Get colors of table index
        e = (R+G+B)/3-(Rnew+Gnew+Bnew)/3    # error between colors

        # Error diffusion on nearest pixels if available
        if col < width-1:
            [R,G,B] = px[ligne][col+1]
            px[ligne][col+1] = [clip(R+e/2),clip(G+e/2),clip(B+e/2)]
        if ligne < height-1:
            if col > 0:
                [R,G,B] = px[ligne+1][col-1]
                px[ligne+1][col-1] = [clip(R+e/4),clip(G+e/4),clip(B+e/4)]
            [R,G,B] = px[ligne+1][col]
            px[ligne+1][col] = [clip(R+e/4),clip(G+e/4),clip(B+e/4)]

Вот дополнительные функции:

# 256 8-8-4 color palette inspired from
# https://en.wikipedia.org/wiki/List_of_software_palettes#8-8-4_levels_RGB
def GetColorIdx(R,G,B): # Get color index from RGB colors
    return round(R/36.5)+round(G/36.5)*8+round(B/85)*64

def GetIdxColor(Idx): # Get RGB colors from table index
    R=int(Idx%8*36.5)
    G=int(Idx//8%8*36.5)
    B=int(Idx//64*85)
    return [R,G,B]

def clip(n): # Trim n between 0 and 255
    if n<0: return 0
    elif n>255: return 255
    return round(n)

Очень медленная часть - это двойная петля for вокруг ширины и высоты. Есть ли у вас какие-либо идеи, как улучшить это в чистом питоне? Я пробовал несколько вещей, таких как использование dict вместо list, кодирование цвета на 3байт вместо 3 значений, но это не имеет никакого реального эффекта ...

После этой части идет часть кодирования и записи gif. Я думаю, что это тоже можно улучшить, но это будет следующий шаг ^^

Спасибо !!

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