Numpy Uint8 решение для упаковки пикселей - PullRequest
26 голосов
/ 25 сентября 2011

Для класса обработки изображений я делаю точечные операции на монохромных изображениях.Пиксели uint8 [0,255].

numpy uint8 обернет.Например, 235 + 30 = 9. Мне нужно пиксели для насыщения (max = 255) или усечения (min = 0) вместо переноса.

Мое решение использует int32 пикселей для точечной математики, а затем преобразует в uint8сохранить изображение.

Это лучший способ?Или есть более быстрый способ?

#!/usr/bin/python

import sys
import numpy as np
import Image

def to_uint8( data ) :
    # maximum pixel
    latch = np.zeros_like( data )
    latch[:] = 255
    # minimum pixel
    zeros = np.zeros_like( data )

    # unrolled to illustrate steps
    d = np.maximum( zeros, data )
    d = np.minimum( latch, d )

    # cast to uint8
    return np.asarray( d, dtype="uint8" )

infilename=sys.argv[1]
img = Image.open(infilename)
data32 = np.asarray( img, dtype="int32")
data32 += 30
data_u8 = to_uint8( data32 )
outimg = Image.fromarray( data_u8, "L" )
outimg.save( "out.png" )

Входное изображение:Riemann

Выходное изображение:Output

Ответы [ 3 ]

34 голосов
/ 25 сентября 2011

Использование numpy.clip :

import numpy as np
np.clip(data32, 0, 255, out=data32)
data_u8 = data32.astype('uint8')

Обратите внимание, что вы также можете сделать изображения ярче, не используя numpy:

import ImageEnhance
enhancer = ImageEnhance.Brightness(img)
outimg = enhancer.enhance(1.2)
outimg.save('out.png')
5 голосов
/ 22 сентября 2014

Вы можете использовать функции OpenCV add или subtract (дополнительное объяснение здесь ).

>>> import numpy as np
>>> import cv2
>>> arr = np.array([100, 250, 255], dtype=np.uint8)
>>> arr
Out[1]: array([100, 250, 255], dtype=uint8)
>>> cv2.add(arr, 10, arr)  # Inplace
Out[2]: array([110, 255, 255], dtype=uint8)  # Saturated!
>>> cv2.subtract(arr, 150, arr)
Out[3]: array([  0, 105, 105], dtype=uint8)  # Truncated!

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

arr[..., channel] = cv2.add(arr[..., channel], 40)
1 голос
/ 25 сентября 2011

По сути, все сводится к проверке перед добавлением. Например, вы можете определить функцию следующим образом:

def clip_add(arr, amt):
    if amt > 0:
        cutoff = 255 - amt
        arr[arr > cutoff] = 255
        arr[arr <= cutoff] += amt
    else:
        cutoff = -amt
        arr[arr < cutoff] = 0
        arr[arr >= cutoff] += amt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...