Python Photoshop'背后的算法是什么;s&x201C;黑白”;调整层?

Python Photoshop'背后的算法是什么;s&x201C;黑白”;调整层?,python,image-processing,colors,reverse-engineering,photoshop,Python,Image Processing,Colors,Reverse Engineering,Photoshop,我做了很多研究,但没有发现任何东西(但我也不知道到底要搜索什么样的关键字)。我希望能够将输入的RGB图像转换为灰度,但我希望能够添加或多或少的红色/黄色/绿色/青色/蓝色/品红,就像在Photoshop中一样。你知道方程式是什么,或者我在哪里可以找到这些方程式,这样我就可以实现我自己的优化RGB到灰度转换了吗 编辑: 在Photoshop中,它被称为黑白调整层。我发现了一些东西,但实际上似乎不起作用。以下是我的实现(注释中是理解算法所需的资源): 将numpy导入为np 导入scipy.misc

我做了很多研究,但没有发现任何东西(但我也不知道到底要搜索什么样的关键字)。我希望能够将输入的RGB图像转换为灰度,但我希望能够添加或多或少的红色/黄色/绿色/青色/蓝色/品红,就像在Photoshop中一样。你知道方程式是什么,或者我在哪里可以找到这些方程式,这样我就可以实现我自己的优化RGB到灰度转换了吗

编辑: 在Photoshop中,它被称为黑白调整层。我发现了一些东西,但实际上似乎不起作用。以下是我的实现(注释中是理解算法所需的资源):

将numpy导入为np
导入scipy.misc
将matplotlib.pyplot作为plt导入
%matplotlib内联
#根据Ivan Kuckir和Royi的回答改编:
# https://dsp.stackexchange.com/questions/688/what-is-the-algorithm-behind-photoshops-black-and-white-adjustment-layer?newreg=77420cc185fd44099d8be961e736eb0c
def rgb2hls(img):
“”“已调整为从中使用numpy”
https://github.com/python/cpython/blob/2.7/Lib/colorsys.py"""
r、 g,b=img[:,:,0],img[:,:,1],img[:,:,2]
maxc=np.max(img,轴=-1)
minc=np.min(img,轴=-1)
l=(最小值+最大值)/2
蒙版=np.类蒙版(r)
掩码[np.where(minc==maxc)]=0
mask=mask.astype(np.bool)
smask=np.更大(l,0.5).aType(np.32)
s=(1.0-smask)*((maxc-minc)/(maxc+minc))+smask*((maxc-minc)/(2.0-maxc-minc))
s[~mask]=0
rc=np.其中(掩码,(maxc-r)/(maxc-minc),0)
gc=np,其中(掩码,(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_或(rmask,gmask).astype(np.float32)
h=rmask*(bc-gc)+gmask*(2.0+rc-bc)+(1.0-rgmask)*(4.0+gc-rc)
h=np.余数(h/6.0,1.0)
h[~mask]=0
返回np.stack([h,l,s],轴=-1)
def黑白调整(图像、重量):
#如果uint8,则将输入图像规格化为(0,1)
如果(image).dtype.name中的“uint8”:
image=image/255
#线性地将输入系数[-200300]重新映射到[-2.5,2.5]
权重=(权重-50)/100
n_权重=len(权重)
h、 w=图像.形状[:2]
#将rgb转换为hls
hls_img=rgb2hls(图像)
输出=np.zero((h,w),数据类型=np.float32)
#见图9https://en.wikipedia.org/wiki/HSL_and_HSV
#了解算法
对于范围(h)内的y:
对于范围(w)内的x:
色调=6*hls\U图像[y,x,0]
#在六边形上使用距离(也许圆形距离更好?)
差异值=最小值(绝对值(0-色调值),绝对值(1-(0-色调值)))
亮度系数=权重[0]*最大值(0,1-差异值)
对于范围内的k(1,n_权重):
亮度系数+=权重[k]*max(0,1-abs(k-色调值))
#输出[y,x]=最小值(最大值(hls_img[y,x,1]*(1+亮度系数),0),1)
输出[y,x]=hls_img[y,x,1]*(1+亮度系数)
返回输出
image=scipy.misc.imread(“your\u image\u here.png”)
w=np.数组([40,85,204,60,20,80])
out=黑色和白色调整(图,w)
plt.图(figsize=(15,20))
plt.imshow(out,cmap='gray')

谢谢

这里尝试使用
PIL
而不是
numpy
。它应该很容易转换。如果没有Photoshop的副本可供比较,我不能保证它与输出完全匹配,但它确实为链接中显示的示例生成了精确的值。值
r_w、y_w、g_w、c_w、b_w、m_w
是应用于每种颜色的权重,在相应的Photoshop滑块中,1.0等于100%。当然,它们也可能是消极的

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
使用此提供的测试图像,下面是一些示例结果


这里尝试使用
PIL
而不是
numpy
。它应该很容易转换。如果没有Photoshop的副本可供比较,我不能保证它与输出完全匹配,但它确实为链接中显示的示例生成了精确的值。值
r_w、y_w、g_w、c_w、b_w、m_w
是应用于每种颜色的权重,在相应的Photoshop滑块中,1.0等于100%。当然,它们也可能是消极的

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
使用此提供的测试图像,下面是一些示例结果


我通过添加numpy/scipy版本的代码来回答我自己的问题,如果将来任何人对它感兴趣的话如果你想投票表决一个答案,你应该投票表决Mark Ransom的答案

将numpy导入为np
导入scipy.misc
将matplotlib.pyplot作为plt导入
%matplotlib内联
def黑色和白色调整(img、重量):
rw、yw、gw、cw、bw、mw=重量/100
h、 w=图像形状[:2]
min_c=np.min(img,axis=-1).aType(np.float)
#max_c=np.max(img,axis=-1).astype(np.float)
#可以尝试不同的定义,如
# https://en.wikipedia.org/wiki/HSL_and_HSV
#比如:亮度=(最小值+最大值)/2。。。
亮度=最小值
diff=img-min_c[:,:,无]
红色遮罩=(差异[:,:,0]==0)
绿色掩码=np.逻辑掩码和((diff[:,:,1]==0),~red\u掩码)
蓝色屏蔽=~np.逻辑屏蔽或(红色屏蔽、绿色屏蔽)
c=np.min(差[:,:,1:,轴=-1)
m=np.min(差[:,[0,2]],轴=-1)
yel=np.min(差[:,:2],轴=-1)
亮度=亮度+红色遮罩*(c*cw+(差值[:,:,1]-c)*gw+(差值[:,:,2]-c)*bw)\
+绿色遮罩*(m*mw+(差异[:,:,0]-m)*rw+(差异[:,:,2]-m)*bw)\
+蓝色遮罩*(yel*yw+(差异[:,:,0
ps_black_and_white(im, [40, 60, 40, 60, 20, 80])
ps_black_and_white(im, [106, 65, 17, 17, 104, 19])