Paul 的回答更优雅,但基本上我认为您可以通过定义一个函数来解决它,该函数为您提供任意两种 RGB 颜色之间的 “距离”,如下所示:
def distance(col1, col2):
(r1,g1,b1) = col1
(r2,g2,b2) = col2
return (r1 - r2)**2 + (g1 - g2) ** 2 + (b1 - b2) **2
现在,您需要做的(在伪代码中)是:
load your pre-existing reference colours into a list
load your new image
for each pixel in new image
# Calculate distance from this pixel to first one in reference list
mindist=distance(this pixel, first pixel in reference colours)
nearest=first pixel in reference colours
# Now see if any other colour in reference list is closer
for index=1 to number of colours in reference list
d=distance(this pixel, reference list[index])
if d < mindist:
mindist=d
nearest=reference list[index]
end
replace pixel with nearest one from reference list as determined above
end
我还在学习 Python,所以我对上述内容的翻译可能不是最佳的,但它确实有效!
#!/usr/local/bin/python3
from PIL import Image
import numpy as np
# Calculate distance in RGB space between two RGB pixels
def distance(col1, col2):
r1,g1,b1 = col1
r2,g2,b2 = col2
return (r1 - r2)**2 + (g1 - g2) ** 2 + (b1 - b2) **2
# All colours in the image will be forced to nearest one in this list
refColours=(
[[255, 0, 0], # red
[ 0, 255, 0], # green
[ 0, 0, 255], # blue
[255, 255, 0], # yellow
[ 0, 255, 255], # cyan
[255, 0, 255], # magenta
[ 0, 0, 0], # black
[255, 255, 255]]) # white
# Load your new image and note its width and height
im = Image.open('colorwheel.png')
imrgb = im.convert("RGB")
(w,h)=im.size[0],im.size[1]
# Make a buffer for our output pixels
px=np.zeros(w*h,dtype=np.uint8)
idx=0
for pixel in list(imrgb.getdata()):
# Calculate distance from this pixel to first one in reference list
mindist = distance([pixel[0],pixel[1],pixel[2]],refColours[0])
nearest = 0
# Now see if any other colour in reference list is closer
for index in range(1,len(refColours)):
d=distance([pixel[0],pixel[1],pixel[2]],refColours[index])
if d < mindist:
mindist=d
nearest=index
# Set output pixel to nearest
px[idx]=nearest
idx += 1
# Reshape our output pixels to match input image
px=px.reshape(w,h)
# Make output image from our pixels
outimg=Image.fromarray(px).convert('P')
# Put our palette of favourite colours into the output image
palette=[item for sublist in refColours for item in sublist]
outimg.putpalette(palette)
outimg.save("result.png")
所以,我从 colorwheel.png 开始:
最后是这样的:
当然,像我在 cmets 中建议的那样,更简单的解决方案是使用 ImageMagick 之类的工具将新图像中的颜色重新映射到“参考”图像中的颜色,您可以这样做像这样在命令行上:
convert colorwheel.png +dither -remap colormap.png result.png
如my other answer here所示。因此,在 Python 中,您可以使用 system() 调用或使用 subprocess 模块:
cmd="https://stackoverflow.com/a/38328879/2836621"
system(cmd)