带枕头的像素化图像

时间:2015-05-29 03:32:49

标签: python image image-resizing pillow

我正在开展一个项目,我希望将彩色网格的图片作为输入(在此示例中使用乐高积木制作)并返回一个小得多的修改后的图片。

以下是输入示例:

Input

下面是一个非常小的8x8图像,结果如下:

Output

这是预期结果的更大版本:

Big Output

到目前为止,这是我的代码: 它只适用于黑白图像。

from PIL import Image
import re

black = [(110,110,110),(0,0,0)] #The highest value and the lowest RGB value for the color black

img = Image.open("input.jpg") #The input image
size = (8,8) #The dimensions of the output image

out = img.resize(size,resample=Image.LANCZOS) #Resize the image

for y in range(size[0]): #loop through every pixel
    for x in range(size[1]):

        if out.getpixel((x,y)) <= black[0] and out.getpixel((x,y)) >= black[1]: #check to see if the pixel is within the accepted black values

            out.putpixel((x,y), (0,0,0)) #Give the current pixel true color
        else:
            #otherwise make the pixel black
            out.putpixel((x,y), (255,255,255)) #Give the current pixel true color

"""Save the pixelated image"""
out.save("output.jpg")

我的代码返回的输出:

Actual Output

我的程序适用于黑白图像,但我需要帮助更改它以使用多种颜色(红色,橙色,黄色,浅绿色,深绿色,浅蓝色,深蓝色,紫色,黑色和白色)。

提前致谢!

3 个答案:

答案 0 :(得分:9)

你做错了一些事。

首先,您应该使用PNG而不是JPG作为输出。 JPG引入了很多工件,像输出这样的小图像完全退化了。

然后,你应该减少调色板。使用不含噪音的输入更容易处理。

首先,无聊的初始化:

from PIL import Image
import operator
from collections import defaultdict
import re

input_path = 'input.jpg'
output_path = 'output.png'
size = (4,4)

然后我们宣布调色板 - 这应该包含所有可能的乐高积木的颜色。我从您的图像中采样了下面的值,但您可以像使用代码一样使用黑白,也可以使用您想要的任何颜色,只要它们与源图像中的颜色相似:

palette = [
    (45,  50,  50),  #black
    (240, 68,  64),  #red
    (211, 223, 223), #white
    (160, 161, 67),  #green
    (233, 129, 76),  #orange
]
while len(palette) < 256:
    palette.append((0, 0, 0))

下面的代码将为PIL声明调色板,因为PIL需要平面数组而不是元组数组:

flat_palette = reduce(lambda a, b: a+b, palette)
assert len(flat_palette) == 768

现在我们可以声明一个包含调色板的图像。我们稍后会用它来减少原始图像的颜色。

palette_img = Image.new('P', (1, 1), 0)
palette_img.putpalette(flat_palette)

这里我们打开图像并量化它。我们将其缩放到比所需大8倍的尺寸,因为我们将在稍后对平均输出进行采样。

multiplier = 8
img = Image.open(input_path)
img = img.resize((size[0] * multiplier, size[1] * multiplier), Image.BICUBIC)
img = img.quantize(palette=palette_img) #reduce the palette

在此之后,我们的图像如下所示:

quantized image

我们需要将其转换回RGB,以便我们现在可以对像素进行采样:

img = img.convert('RGB')

现在我们要构建我们的最终形象。为此,我们将对较大图像中每个方块包含的每种调色板颜色的像素进行采样。然后我们将选择最常出现的颜色。

out = Image.new('RGB', size)
for x in range(size[0]):
    for y in range(size[1]):
        #sample at get average color in the corresponding square
        histogram = defaultdict(int)
        for x2 in range(x * multiplier, (x + 1) * multiplier):
            for y2 in range(y * multiplier, (y + 1) * multiplier):
                histogram[img.getpixel((x2,y2))] += 1
        color = max(histogram.iteritems(), key=operator.itemgetter(1))[0]
        out.putpixel((x, y), color)

最后,我们保存输出:

out.save(output_path)

结果:

small image

升级1600%:

big image

答案 1 :(得分:4)

为了好玩,我用ImageMagick解决了这个问题 - 它也可以从Python中调用...

首先,我创建一个小的自定义调色板来匹配你的颜色 - 你的白色不是很白,你的绿色与ImageMagick的绿色想法不同所以我使用了十六进制代替颜色名称。

convert xc:black xc:red xc:"rgb(200,200,200)" xc:"rgb(168,228,23)"  xc:orange +append palette.png

如果我调整该调色板,它看起来像这样:

enter image description here

然后我将图像调整为4x4并将结果映射到自定义调色板并将其缩放,以便您可以这样看到它:

convert lego.jpg -resize 4x4! +dither -remap palette.png -scale 1600 result.png

这是结果

enter image description here

白色关闭以匹配原件中的&#34;白色&#34;

答案 2 :(得分:0)

Pixelator可以解决问题。它是基于rr-答案的软件包。它还为AI和ML应用带来了一些额外的好处。

在bash中

pip install pixelator

在python

from pixelator import pixelator
palette = [
    (45,  50,  50),  #black
    (240, 68,  64),  #red
    (211, 223, 223), #white
    (160, 161, 67),  #green
    (233, 129, 76),  #orange
]

sensitivity_multiplier = 10

size = (4,4)

output=pixelator(
    in_path='./images/input.jpg',
    palette=palette,
    size=size,
    sensitivity_multiplier=sensitivity_multiplier
    )

output.resize_out_img().save_out_img(path='./images/output.jpg', overwrite=True)