<p>我试着计算每个像素的CIE76 Delta-E函数,以得到最接近的颜色。Python不是我最好的语言,所以如果它能像您期望的那样工作,那么您可能需要再问一个问题来优化代码。在</p>
<p>我基本上把输入图像和调色板转换成Lab颜色空间,然后计算每个像素到每个调色板条目的CIE76 Delta-E值的平方,并取最近的一个。在</p>
<pre><code>#!/usr/bin/env python3
import numpy as np
from PIL import Image
from skimage import color
def CIE76DeltaE2(Lab1,Lab2):
"""Returns the square of the CIE76 Delta-E colour distance between 2 lab colours"""
return (Lab2[0]-Lab1[0])*(Lab2[0]-Lab1[0]) + (Lab2[1]-Lab1[1])*(Lab2[1]-Lab1[1]) + (Lab2[2]-Lab1[2])*(Lab2[2]-Lab1[2])
def NearestPaletteIndex(Lab,palLab):
"""Return index of entry in palette that is nearest the given colour"""
NearestIndex = 0
NearestDist = CIE76DeltaE2(Lab,palLab[0,0])
for e in range(1,palLab.shape[0]):
dist = CIE76DeltaE2(Lab,palLab[e,0])
if dist < NearestDist:
NearestDist = dist
NearestIndex = e
return NearestIndex
palette = [
0,0,0,
0,0,255,
15,29,15,
26,141,52,
41,41,41,
65,105,225,
85,11,18,
128,0,128,
135,206,236,
144,238,144,
159,30,81,
165,42,42,
166,141,95,
169,169,169,
173,216,230,
211,211,211,
230,208,122,
245,245,220,
247,214,193,
255,0,0,
255,165,0,
255,192,203,
255,255,0,
255,255,255
] + [0,] * 232 * 3
# Load the source image as numpy array and convert to Lab colorspace
imnp = np.array(Image.open('lion.png').convert('RGB'))
imLab = color.rgb2lab(imnp)
h,w = imLab.shape[:2]
# Load palette as numpy array, truncate unused palette entries, and convert to Lab colourspace
palnp = np.array(palette,dtype=np.uint8).reshape(256,1,3)[:24,:]
palLab = color.rgb2lab(palnp)
# Make numpy array for output image
resnp = np.empty((h,w), dtype=np.uint8)
# Iterate over pixels, replacing each with the nearest palette entry
for y in range(0, h):
for x in range(0, w):
resnp[y, x] = NearestPaletteIndex(imLab[y,x], palLab)
# Create output image from indices, whack a palette in and save
resim = Image.fromarray(resnp, mode='P')
resim.putpalette(palette)
resim.save('result.png')
</code></pre>
<p>我明白了:</p>
<p><a href="https://i.stack.imgur.com/5w163.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5w163.png" alt="enter image description here"/></a></p>
<hr/>
<p>使用<code>scipy.spatial.distance</code>的<code>cdist()</code>函数似乎更快、更简洁:</p>
^{pr2}$