Python PIL.Image.convert不会用最接近的调色板替换颜色. [英] Python PIL.Image.convert not replacing color with the closest palette.

查看:491
本文介绍了Python PIL.Image.convert不会用最接近的调色板替换颜色.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自以下问题的后续问题:使用PIL将图像转换为特定的调色板而无需抖动

This is a sort-of follow-up question from :Convert image to specific palette using PIL without dithering

我也想创建一个脚本,该脚本可以将图像转换为没有抖动的特定颜色.

I, too, want to create a script that can convert an image to a specific set of colors without dithering.

我已经实现了解决方法自定义量化"功能,作为对问题的答案.除了一个大问题外,大多数脚本都能正常工作.

I have implemented the work-around "custom quantization" function given as the answer for the questions. Most of the scripts works well except for 1 big problem.

浅绿色RGB(130,190,40)替换为浅棕色RGB(166、141、95). (请参见鬃毛左上方的浅绿色.)

Light green color RGB(130,190,40) is replaced by a light brown color RGB(166, 141, 95). (see the light green on the top left of the mane.)

from PIL import Image

def customConvert(silf, palette, dither=False):
    ''' Convert an RGB or L mode image to use a given P image's palette.
        PIL.Image.quantize() forces dither = 1. 
        This custom quantize function will force it to 0.
        https://stackoverflow.com/questions/29433243/convert-image-to-specific-palette-using-pil-without-dithering
    '''

    silf.load()

    # use palette from reference image made below
    palette.load()
    im = silf.im.convert("P", 0, palette.im)
    # the 0 above means turn OFF dithering making solid colors
    return silf._new(im)

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


# a palette image to use for quant
paletteImage = Image.new('P', (1, 1), 0)
paletteImage.putpalette(palette)


# open the source image
imageOrginal = Image.open('lion.png').convert('RGB')

# convert it using our palette image
imageCustomConvert = customConvert(imageOrginal, paletteImage, dither=False).convert('RGB')

CIE76 Delta-E:

CIE76 Delta-E:

当前:RGB(130,190,40)-> RGB(166,141,95)= 57.5522

Currently: RGB(130,190,40) --> RGB(166, 141, 95) = 57.5522

预期:RGB(130,190,40)-> RGB(144,238,144) = 31.5623

Expected: RGB(130,190,40) --> RGB(144,238,144) = 31.5623

有人可以解释我是否错误地编写了代码,或提出了如何使它正常工作的建议.

Can someone explain if I wrote the code incorrectly or suggestions how to get it to work.

推荐答案

ImageMagick 可以更快地完成此任务.它已安装在大多数Linux发行版上,并且可用于macOS和Windows.

ImageMagick can do this much faster, if speed is the issue. It is installed on most Linux distros and is available for macOS and Windows.

基本上,您将创建一个名为"map.png"的24x1图像,其中调色板中每种颜色都有一个像素,然后告诉 ImageMagick 将狮子图像重新映射到Lab色彩空间中的该色彩映射表没有抖动.因此,终端/命令提示符"中的命令为:

Basically you would create a 24x1 image, called "map.png", with one pixel of each colour in your palette, and tell ImageMagick to remap your lion image to that colormap in the Lab colourspace without dithering. So, the command in Terminal/Command Prompt would be:

magick lion.png +dither -quantize Lab -remap map.png result.png

运行时间不到0.3秒.如果您想从Python做到这一点,则可以像这样进行炮击:

That runs in under 0.3 seconds. If you wanted to do that from Python, you could shell out like this:

#!/usr/bin/env python3

import subprocess
import numpy as np
from PIL import Image

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


# Write "map.png" that is a 24x1 pixel image with one pixel for each colour
entries = 24
resnp   = np.arange(entries,dtype=np.uint8).reshape(24,1)
resim = Image.fromarray(resnp, mode='P')
resim.putpalette(palette)
resim.save('map.png')

# Use Imagemagick to remap to palette saved above in 'map.png'
# magick lion.png +dither -quantize Lab -remap map.png result.png
subprocess.run(['magick', 'lion.png', '+dither', '-quantize', 'Lab', '-remap', 'map.png', 'result.png'])

这篇关于Python PIL.Image.convert不会用最接近的调色板替换颜色.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆