Ausgabe
Ich habe viel recherchiert, aber nichts gefunden (aber ich weiß auch nicht, nach welchen Schlüsselwörtern ich genau suchen soll). Ich möchte in der Lage sein, ein RGB -Eingabebild in Graustufen umzuwandeln , aber ich möchte in der Lage sein, mehr oder weniger Rot/Gelb/Grün/Cyan/Blau/Magenta wie in Photoshop hinzuzufügen . Wissen Sie, was die Gleichung ist oder wo ich diese Gleichungen finden kann, damit ich meine eigene optimierte RGB-zu-Graustufen-Konvertierung implementieren kann?
Bearbeiten : In Photoshop heißt es Schwarz/Weiß-Einstellungsebene . Ich habe etwas gefunden, aber tatsächlich scheint es nicht zu funktionieren. Hier ist meine Implementierung (in Kommentaren sind die Ressourcen aufgeführt, die zum Verständnis des Algorithmus erforderlich sind):
import numpy as np
import scipy.misc
import matplotlib.pyplot as plt
%matplotlib inline
# Adapted from the answers of Ivan Kuckir and Royi here:
# https://dsp.stackexchange.com/questions/688/what-is-the-algorithm-behind-photoshops-black-and-white-adjustment-layer?newreg=77420cc185fd44099d8be961e736eb0c
def rgb2hls(img):
"""Adapted to use numpy from
https://github.com/python/cpython/blob/2.7/Lib/colorsys.py"""
r, g, b = img[:, :, 0], img[:, :, 1], img[:, :, 2]
maxc = np.max(img, axis=-1)
minc = np.min(img, axis=-1)
l = (minc + maxc) / 2
mask = np.ones_like(r)
mask[np.where(minc == maxc)] = 0
mask = mask.astype(np.bool)
smask = np.greater(l, 0.5).astype(np.float32)
s = (1.0 - smask) * ((maxc - minc) / (maxc + minc)) + smask * ((maxc - minc) / (2.0 - maxc - minc))
s[~mask] = 0
rc = np.where(mask, (maxc - r) / (maxc - minc), 0)
gc = np.where(mask, (maxc - g) / (maxc - minc), 0)
bc = np.where(mask, (maxc - b) / (maxc - minc), 0)
rmask = np.equal(r, maxc).astype(np.float32)
gmask = np.equal(g, maxc).astype(np.float32)
rgmask = np.logical_or(rmask, gmask).astype(np.float32)
h = rmask * (bc - gc) + gmask * (2.0 + rc - bc) + (1.0 - rgmask) * (4.0 + gc - rc)
h = np.remainder(h / 6.0, 1.0)
h[~mask] = 0
return np.stack([h, l, s], axis=-1)
def black_and_white_adjustment(image, weights):
# normalize input image to (0, 1) if uint8
if 'uint8' in (image).dtype.name:
image = image / 255
# linearly remap input coeff [-200, 300] to [-2.5, 2.5]
weights = (weights - 50) / 100
n_weights = len(weights)
h, w = image.shape[:2]
# convert rgb to hls
hls_img = rgb2hls(image)
output = np.zeros((h, w), dtype=np.float32)
# see figure 9 of https://en.wikipedia.org/wiki/HSL_and_HSV
# to understand the algorithm
for y in range(h):
for x in range(w):
hue_val = 6 * hls_img[y, x, 0]
# Use distance on a hexagone (maybe circular distance is better?)
diff_val = min(abs(0 - hue_val), abs(1 - (0 - hue_val)))
luminance_coeff = weights[0] * max(0, 1 - diff_val)
for k in range(1, n_weights):
luminance_coeff += weights[k] * max(0, 1 - abs(k - hue_val))
# output[y, x] = min(max(hls_img[y, x, 1] * (1 + luminance_coeff), 0), 1)
output[y, x] = hls_img[y, x, 1] * (1 + luminance_coeff)
return output
image = scipy.misc.imread("your_image_here.png")
w = np.array([40, 85, 204, 60, 20, 80])
out = black_and_white_adjustment(image, w)
plt.figure(figsize=(15, 20))
plt.imshow(out, cmap='gray')
Vielen Dank
Lösung
Hier ist ein Versuch mit PIL
statt numpy
. Es sollte einfach zu konvertieren sein. Ohne eine Kopie von Photoshop zum Vergleichen kann ich nicht garantieren, dass sie genau mit der Ausgabe übereinstimmt, aber sie erzeugt die genauen Werte für das in Ihrem Link gezeigte Beispiel. Die Werte r_w, y_w, g_w, c_w, b_w, m_w
sind die auf jede Farbe anzuwendenden Gewichtungen, wobei 1,0 im entsprechenden Photoshop-Schieberegler 100 % entspricht. Sie können natürlich auch negativ sein.
from PIL import Image
im = Image.open(r'c:\temp\temp.png')
def ps_black_and_white(im, weights):
r_w, y_w, g_w, c_w, b_w, m_w = [w/100 for w in weights]
im = im.convert('RGB')
pix = im.load()
for y in range(im.size[1]):
for x in range(im.size[0]):
r, g, b = pix[x, y]
gray = min([r, g, b])
r -= gray
g -= gray
b -= gray
if r == 0:
cyan = min(g, b)
g -= cyan
b -= cyan
gray += cyan * c_w + g * g_w + b * b_w
elif g == 0:
magenta = min(r, b)
r -= magenta
b -= magenta
gray += magenta * m_w + r * r_w + b * b_w
else:
yellow = min(r, g)
r -= yellow
g -= yellow
gray += yellow * y_w + r * r_w + g * g_w
gray = max(0, min(255, int(round(gray))))
pix[x, y] = (gray, gray, gray)
return im
Unter Verwendung dieses bereitgestellten Testbilds finden Sie hier einige Beispielergebnisse.
ps_black_and_white(im, [-17, 300, -100, 300, -200, 300])
ps_black_and_white(im, [40, 60, 40, 60, 20, 80])
ps_black_and_white(im, [106, 65, 17, 17, 104, 19])
Beantwortet von – Mark Ransom
Antwort geprüft von – Senaida (FixError Volunteer)