大多数图像编辑软件都具有渐变图功能。渐变贴图采用给定像素的亮度并根据亮度应用颜色渐变。 Photoshop 和其他软件有办法自动执行此操作,但它们不能完全满足我的要求,所以我认为 Python 可能可以解决这个问题。不幸的是,当我使用 Python 搜索渐变图或颜色图时,我很难理解或应用出现的任何结果。
我发现的所有潜在解决方案线程都使用了 numpy 或 matplotlib,其中有很多数学线超出了我的想象......我希望得到一些帮助。最初我对处理有一些了解,但我发现使用处理导出大量图像的任务很奇怪而且很棘手。另外,我喜欢 Python,并且想学习如何用它编辑和生成艺术作品。
这就是我现在正在做的事情。
from PIL import Image
myPalette = ['#1A1423', '#684756', '#AB8476']
def colorMap(pixel, palette):
# Calculate the brightness of pixel
R, G, B = pixel
brightness = sum([R, G, B])/3
# Map gradient of colors to brightness
# ???...
return mappedColor
img = Image.open('image_input.png')
pixels = img.load()
for x in range(img.size[0]):
for y in range(img.size[1]):
pixel = img.getpixel((x, y))
pixels[x, y] = colorMap(pixel, myPalette)
img.save('image_output.png')
加载、计算亮度、保存都很简单。我只是不知道如何将调色板的渐变应用于像素。
您可以使用 ImageMagick 或 PIL/Numpy/OpenCV 轻松完成此操作。
首先是获取颜色图 - 图像右侧下方的垂直条。我没有也不知道 Clip Studio,所以也许它可以让你导出色彩图,或者创建一个灰度渐变并将色彩图应用到它,然后将结果保存为 PNG。就我而言,我将图像加载到 Photoshop 中,剪切出渐变并旋转它,以制作一张完全 256 像素宽 x 1 像素高的图像。放大后是这样的:
颜色图.png
我还从图像的左侧裁剪了你的漩涡状物体 - 请以后单独发布图像。
漩涡.png
现在应用它。首先,只需在终端中使用ImageMagick。我加载了您的漩涡图像并将其分成其组成的 RGB 通道,然后对通道进行平均并应用颜色图,也称为 CLUT 或 “颜色查找表”:
magick swirl.png -channel RGB -separate -evaluate-sequence mean colourmap.png -clut result.png
接下来,与 PIL/Numpy 相同:
#!/usr/bin/env python3
import numpy as np
from PIL import Image
# Load image, make into Numpy array and average RGB channels
im = Image.open('swirl.png').convert('RGB')
na = np.array(im)
grey = np.mean(na, axis=2).astype(np.uint8)
Image.fromarray(grey).save('DEBUG-grey.png') # DEBUG only
# Load colourmap
cmap = Image.open('colourmap.png').convert('RGB')
# cmap must be resized to have a width of 256
# since grey's scaled from 0-255, so np.take will select from indices 0-255 only
cmap = cmap.resize((256, 1))
# Make output image same height and width as grey image, but 3-channel RGB
result = np.zeros((*grey.shape,3), dtype=np.uint8)
# Take entries from RGB colourmap according to greyscale values in image
np.take(cmap.getdata(), grey, axis=0, out=result)
# Save result
Image.fromarray(result).save('result.png')
您还可以生成分段线性颜色图,如下所示:
magick -size 160x1 gradient:navy-"rgb(220,110,110)" \
-size 60x1 gradient:"rgb(220,110,110)"-yellow \
-size 35x1 gradient:yellow-white \
+append colourmap.png
这使得三个段各具有线性渐变:
然后将它们附加在一起。
如果将颜色图的所有段设置为相同的长度,您将得到不同的解释:
magick -size 85x1 \
gradient:navy-"rgb(220,110,110)" \
gradient:"rgb(220,110,110)"-yellow \
gradient:yellow-white +append -resize 256x1\! colourmap.png
这导致了这个:
这里有两种方法,一种使用Matplotlib,一种仅使用OpenCV
方法#1:
OpenCV
+ matplotlib.pyplot.get_cmap
我们首先将图像加载为灰度。默认情况下,OpenCV 将图像读取为 3 通道、8 位 BGR。我们可以使用
cv2.imread()
和 cv2.IMREAD_GRAYSCALE
参数直接将图像加载为灰度图像,或者使用 cv2.cvtColor()
和 cv2.COLOR_BGR2GRAY
参数将 BGR 图像转换为灰度图像。加载图像后,我们将此灰度图像放入 Matplotlib 中以获得热图图像。 Matplotlib 返回 RGB 格式,因此我们必须转换回 Numpy 格式并切换到 BGR 色彩空间以便与 OpenCV 一起使用。这是使用 inferno
颜色图的示例。请参阅在 Matplotlib 中选择颜色图,了解可用的内置颜色图,具体取决于您所需的用例。
输入图像
->
热图图像
代码
import matplotlib.pyplot as plt
import numpy as np
import cv2
image = cv2.imread('1.png', 0)
colormap = plt.get_cmap('inferno')
heatmap = (colormap(image) * 2**16).astype(np.uint16)[:,:,:3]
heatmap = cv2.cvtColor(heatmap, cv2.COLOR_RGB2BGR)
cv2.imshow('image', image)
cv2.imshow('heatmap', heatmap)
cv2.waitKey()
cv2.applyColorMap()
我们可以使用OpenCV内置的热图功能。这是使用
cv2.COLORMAP_HOT
热图 的结果
代码
import cv2
image = cv2.imread('1.png', 0)
heatmap = cv2.applyColorMap(image, cv2.COLORMAP_HOT)
cv2.imshow('heatmap', heatmap)
cv2.waitKey()
注意: 虽然 OpenCV 的内置实现简短而快速,但我建议使用方法#1,因为有更大的颜色图选择。 Matplotlib 拥有数百种不同的颜色图,并允许您创建自己的自定义颜色图,而 OpenCV 只有 12 种可供选择。这是内置的 OpenCV 颜色图选择:
我知道你说过你不想要 matplotlib,但我认为你不需要数学线来让它工作。我用自己的 PNG 进行了测试,希望它也适用于您的。这是一个很大程度上借鉴了本文档的示例。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# Read PNG and take average:
img = plt.imread('image_input.png')
Z = img.mean(-1)
# Kestrel
color_list = [np.array([207,117,80])/255,
np.array([219,179,127])/255,
np.array([248,249,251])/255,
np.array([185,191,205])/255,
np.array([88,104,127])/255]
cmap_name = 'Kestrel'
N_bin=100
# Create the colormap
cmap = LinearSegmentedColormap.from_list(cmap_name, color_list, N=N_bin)
# Fewer bins will result in "coarser" colomap interpolation
fig, ax = plt.subplots()
im = ax.imshow(Z, cmap=cmap)
fig.colorbar(im, ax=ax)
plt.show()