2014-11-20 6 views
3

То, что я пытаюсь сделать: непрерывно изменять значение оттенок изображения, от 0 до 360, сохранив одно изображение для каждого Хюэ.RGB в HSV Python, изменить Hue непрерывно

Как я пытаюсь: Я начал с использования кода, который я нашел на this link, а затем изменил его, чтобы изменить оттенок и сохранить изображения.

чем проблема: Код по ссылке выше, по-видимому, не сохраняет изображения в качестве истинного HSV, потому что, когда она сливается образ он использует режим изображения RGB. Но я не могу найти способ сделать это HSV.

def hueChange(img, hue): 
    if isinstance(img, Image.Image): 
     img.load() 
     r, g, b = img.split() 
     h_data = [] 
     s_data = [] 
     v_data = [] 

     for rd, gr, bl in zip(r.getdata(), g.getdata(), b.getdata()): 
      h, s, v = colorsys.rgb_to_hsv(rd/255., bl/255., gr/255.) 
      h_data.append(int(hue)) 
      s_data.append(int(s * 255.)) 
      v_data.append(int(v * 255.)) 

     r.putdata(h_data) 
     g.putdata(s_data) 
     b.putdata(v_data) 
     return toRGB(Image.merge('RGB',(r,g,b))) 
    else: 
     return None 

# Don't care about the range indices, they are just for testing 
for hue in range(1, 255, 30): 
    in_name = '/Users/cgois/Dropbox/Python/fred/fred' + str(hue) + '.jpg' 
    img = Image.open(in_name) 
    img = hueChange(img, hue) 

    out_name = '/Users/cgois/Dropbox/Python/fred/hue/fred_hue' + str(hue) + '.png' 
    img.save(out_name) 

Последнее решение, которое я попробовал: было сделать преобразование, как описано выше, а затем преобразовать его обратно в RGB, используя аналогичный код для hueChange (...). Однако эффект заключался только в том, что на выходных изображениях поверх них было нанесено * (однократное) * цветное наложение.

Любые идеи? Спасибо за ваше время (:

+0

Просто удалите 'hue = 0',' hue + = 1' и т. Д.Если вы используете 'for', переменная' hue' изменяется автоматически. Также исправьте отступ на 'hueChange'. – parchment

ответ

3

Использование colorsys.hsv_to_rgb для преобразования (H, S, V) кортеж обратно в RGB:

import os 
import colorsys 
import Image 

def hueChange(img, hue): 
    # It's better to raise an exception than silently return None if img is not 
    # an Image. 
    img.load() 
    r, g, b = img.split() 
    r_data = [] 
    g_data = [] 
    b_data = [] 

    for rd, gr, bl in zip(r.getdata(), g.getdata(), b.getdata()): 
     h, s, v = colorsys.rgb_to_hsv(rd/255., bl/255., gr/255.) 
     rgb = colorsys.hsv_to_rgb(hue/360., s, v) 
     rd, gr, bl = [int(x*255.) for x in rgb] 
     r_data.append(rd) 
     g_data.append(gr) 
     b_data.append(bl) 

    r.putdata(r_data) 
    g.putdata(g_data) 
    b.putdata(b_data) 
    return Image.merge('RGB',(r,g,b)) 

filename = 'image.png' 
basename, ext = os.path.splitext(filename) 
img = Image.open(filename).convert('RGB') 
for hue in range(1, 360, 30): 
    img2 = hueChange(img, hue) 
    out_name = '{}_hue{:03d}.jpg'.format(basename, hue) 
    img2.save(out_name) 

Изменение значений попиксельно может быть очень медленным для больших . изображения Для лучшей производительности используйте NumPy (функции Numpy были взяты из here).

import os 
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 hueChange(img, hue): 
    arr = np.array(img) 
    hsv = rgb_to_hsv(arr) 
    hsv[..., 0] = hue 
    rgb = hsv_to_rgb(hsv) 
    return Image.fromarray(rgb, 'RGB') 

filename = 'image.png' 
basename, ext = os.path.splitext(filename) 
img = Image.open(filename).convert('RGB') 
for hue in np.linspace(0, 360, 8): 
    img2 = hueChange(img, hue/360.) 
    out_name = '{}_hue{:03d}.jpg'.format(basename, int(hue)) 
    img2.save(out_name) 

В соответствии с this page, , когда флажок «Раскрасить» Photoshop не установлен, оттенок каждого пикселя равен , сдвинутый на на ту же сумму. Когда флажок «Раскрасить» отмечен, оттенок каждого пикселя равен , установленному на ту же сумму.

Таким образом, чтобы сместить оттенок на фиксированную величину, использование:

def hueShift(img, amount): 
    arr = np.array(img) 
    hsv = rgb_to_hsv(arr) 
    hsv[..., 0] = (hsv[..., 0]+amount) % 1.0 
    rgb = hsv_to_rgb(hsv) 
    return Image.fromarray(rgb, 'RGB') 

filename = 'without_colorize.jpg' 
basename, ext = os.path.splitext(filename) 
img = Image.open(filename).convert('RGB') 
for amount in (50, 133): 
    img2 = hueShift(img, amount/360.) 
    out_name = '{}_hue{:+03d}.jpg'.format(basename, int(amount)) 
    img2.save(out_name) 

without_colorize.jpg:

enter image description here

оттенок + 50:

enter image description here

Оттенок + 133:

enter image description here

Примечание: При переключении оттенок определенного региона с волос и лица стали разного цвета с отчетливым, неестественным границы. Похоже, что мой код не точно воспроизводит то, что делает Photoshop ...

+0

Это работает, как я и пытался, но гораздо лучше кода. Спасибо. Тем не менее, это изменение оттенка, кажется, раскрашивает изображение, как цветное наложение поверх него. Есть ли способ изменить Hue без раскраски, например, программное обеспечение для редактирования фотографий? (edit: То, что я подразумеваю под некрасификацией, - это сделать что-то вроде изменения цвета, пикселя за пикселем, вместо цветного наложения) – ccln

+0

Я не совсем уверен, что вы имеете в виду. Можете ли вы привести пример? Может быть, сообщение или ссылка на некоторые изображения, которые показывают изменение цвета? – unutbu

+0

Да. [Это «с раскраски»,] (http://postimg.org/image/fwe9buair/), что делает текущий код. [Это то, что я намереваюсь сделать] (http://postimg.org/image/5kctjpiyt/). И [это то, как выглядит диалоговое окно Photoshop] (http://postimg.org/image/eaqy4jewd/) с флажком, который позволяет мне выбирать либо раскрасить, либо нет. Пс: Спасибо вам большое за помощь, особенно за нулевую часть. – ccln

Смежные вопросы