【发布时间】:2019-10-18 06:43:14
【问题描述】:
我做了很多研究,但没有找到任何东西(但我也不知道要准确搜索什么样的关键字)。我希望能够将输入的 RGB 图像转换为 灰度,但我希望能够添加更多或更少的 Reds/Yellows/Greens/Cyans/Blues /Magentas 就像在 Photoshop 中一样。你知道方程是什么吗?或者我在哪里可以找到这些方程,以便我可以实现自己优化的 RGB 到灰度的转换?
编辑: 在 Photoshop 中称为黑白调整图层。我发现了一些东西,但实际上它似乎不起作用。这是我的实现(在 cmets 中是理解算法所需的资源):
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')
谢谢
【问题讨论】:
-
作为选择性颜色或混合成一系列像素?
-
作为一个例子来更准确地理解问题。您可以使用 photopea。一个免费的在线Photoshop工具。您加载一张图片,然后转到 Image -> Adjustment -> Black/White。那里有 6 个光标,您可以调整青色/蓝色/品红色/黄色/... 我想知道如何编写这样的代码?我不知道从什么开始
-
抱歉,回复晚了,这应该可以通过 PILLOW 分叉的 Python Imaging Library 实现。我正在研究一个示例,并在完成后将其作为答案发布。同时here 是文档,如果你想看看自己
-
我发现有人问了同样的问题。显然,Photopea 的开发者回答了这个问题(dsp.stackexchange.com/questions/688/…)。我已经重新实现了他在python中所说的(我也使用了Royi和matlab的答案)但是输出与photopea的输出不匹配
-
你能把你的适应添加到你的答案中吗?
标签: python image-processing colors reverse-engineering photoshop