segmentacion ruido procesar pil para negro matriz libreria imagenes imagen gaussiano filtros convertir blanco python image python-imaging-library hue

ruido - Cambiar el tono de la imagen con Python PIL



ruido gaussiano python (3)

Usando Python PIL, estoy tratando de ajustar el tono de una imagen dada.

No estoy muy cómodo con la jerga de los gráficos, entonces lo que quiero decir con "ajustar el tono" es hacer la operación de Photoshop llamada “Hue/saturation” : esto es para cambiar el color de la imagen uniformemente como se muestra a continuación:

  • Original:
  • Con tono ajustado a +180 (rojo):
  • Con matiz ajustado a -78 (verde):

FYI, Photoshop usa una escala de -180 a +180 para este ajuste de matiz (donde -180 es igual a +180), que puede representar la escala de matiz HSL (expresada en 0-360 grados).

Lo que estoy buscando es una función que, dada una imagen PIL y un tono de flotación dentro de [0, 1] (o int dentro de [0, 360], no importa), devuelve la imagen con su matiz desplazado por tono como en el ejemplo anterior.

Lo que he hecho hasta ahora es ridículo y obviamente no da el resultado deseado. Simplemente mezcla a medias mi imagen original con una capa llena de color.

import Image im = Image.open(''tweeter.png'') layer = Image.new(''RGB'', im.size, ''red'') # "hue" selection is done by choosing a color... output = Image.blend(im, layer, 0.5) output.save(''output.png'', ''PNG'')

(Por favor, no te rías de) resultado:

¡Gracias por adelantado!

Solución : aquí está el código unutbu actualizado para que encaje exactamente con lo que describí.

import Image import numpy as np import colorsys rgb_to_hsv = np.vectorize(colorsys.rgb_to_hsv) hsv_to_rgb = np.vectorize(colorsys.hsv_to_rgb) def shift_hue(arr, hout): r, g, b, a = np.rollaxis(arr, axis=-1) h, s, v = rgb_to_hsv(r, g, b) h = hout r, g, b = hsv_to_rgb(h, s, v) arr = np.dstack((r, g, b, a)) return arr def colorize(image, hue): """ Colorize PIL image `original` with the given `hue` (hue within 0-360); returns another PIL image. """ img = image.convert(''RGBA'') arr = np.array(np.asarray(img).astype(''float'')) new_img = Image.fromarray(shift_hue(arr, hue/360.).astype(''uint8''), ''RGBA'') return new_img


Buena pregunta. PIL no se convierte a un espacio de color HSV o HSL, pero esta es la conversión que necesita hacer para alterar el tono sin ningún cambio en la claridad y saturación de la imagen.

Lo que necesita hacer es convertir a HSV, luego incrementar todos los valores de H en cierto grado, luego convertir de nuevo a RGB.

La mitad del trabajo está hecho para ti en una answer (por mí) hace algún tiempo. Emplea otro módulo de python llamado NumPy y convierte el espacio de color RGB en HSV. No sería demasiado problema escribir la conversión inversa.


Con una copia reciente de Pillow, probablemente uno debería usar

def rgb2hsv(image): return image.convert(''HSV'')


Existe un código Python para convertir RGB a HSV (y viceversa) en el módulo colorsys en la biblioteca estándar . Mi primer intento usado

rgb_to_hsv=np.vectorize(colorsys.rgb_to_hsv) hsv_to_rgb=np.vectorize(colorsys.hsv_to_rgb)

para vectorizar esas funciones. Lamentablemente, el uso de np.vectorize da np.vectorize resultado un código bastante lento.

Pude obtener aproximadamente 5 veces más velocidad traduciendo colorsys.rgb_to_hsv y colorsys.hsv_to_rgb en operaciones numpy nativas.

import Image import numpy as np def rgb_to_hsv(rgb): # Translated from source of colorsys.rgb_to_hsv # r,g,b should be a numpy arrays with values between 0 and 255 # rgb_to_hsv returns an array of floats between 0.0 and 1.0. rgb = rgb.astype(''float'') hsv = np.zeros_like(rgb) # in case an RGBA array was passed, just copy the A channel hsv[..., 3:] = rgb[..., 3:] r, g, b = rgb[..., 0], rgb[..., 1], rgb[..., 2] maxc = np.max(rgb[..., :3], axis=-1) minc = np.min(rgb[..., :3], axis=-1) hsv[..., 2] = maxc mask = maxc != minc hsv[mask, 1] = (maxc - minc)[mask] / maxc[mask] rc = np.zeros_like(r) gc = np.zeros_like(g) bc = np.zeros_like(b) rc[mask] = (maxc - r)[mask] / (maxc - minc)[mask] gc[mask] = (maxc - g)[mask] / (maxc - minc)[mask] bc[mask] = (maxc - b)[mask] / (maxc - minc)[mask] hsv[..., 0] = np.select( [r == maxc, g == maxc], [bc - gc, 2.0 + rc - bc], default=4.0 + gc - rc) hsv[..., 0] = (hsv[..., 0] / 6.0) % 1.0 return hsv def hsv_to_rgb(hsv): # Translated from source of colorsys.hsv_to_rgb # h,s should be a numpy arrays with values between 0.0 and 1.0 # v should be a numpy array with values between 0.0 and 255.0 # hsv_to_rgb returns an array of uints between 0 and 255. rgb = np.empty_like(hsv) rgb[..., 3:] = hsv[..., 3:] h, s, v = hsv[..., 0], hsv[..., 1], hsv[..., 2] i = (h * 6.0).astype(''uint8'') f = (h * 6.0) - i p = v * (1.0 - s) q = v * (1.0 - s * f) t = v * (1.0 - s * (1.0 - f)) i = i % 6 conditions = [s == 0.0, i == 1, i == 2, i == 3, i == 4, i == 5] rgb[..., 0] = np.select(conditions, [v, q, p, p, t, v], default=v) rgb[..., 1] = np.select(conditions, [v, v, v, q, p, p], default=t) rgb[..., 2] = np.select(conditions, [v, p, t, v, v, q], default=p) return rgb.astype(''uint8'') def shift_hue(arr,hout): hsv=rgb_to_hsv(arr) hsv[...,0]=hout rgb=hsv_to_rgb(hsv) return rgb img = Image.open(''tweeter.png'').convert(''RGBA'') arr = np.array(img) if __name__==''__main__'': green_hue = (180-78)/360.0 red_hue = (180-180)/360.0 new_img = Image.fromarray(shift_hue(arr,red_hue), ''RGBA'') new_img.save(''tweeter_red.png'') new_img = Image.fromarray(shift_hue(arr,green_hue), ''RGBA'') new_img.save(''tweeter_green.png'')

rendimientos

y