带枕头的像素化图像 [英] Pixelate Image With Pillow

查看:165
本文介绍了带枕头的像素化图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开展一个项目,我想把彩色网格的图片作为输入(在这个例子中用乐高积木制作)并返回一个小得多的修改图片。

I am working on a project where I want to take a picture of a colored grid as an input (made with Lego bricks in this example) and return a much smaller modified picture.

以下是输入示例:

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

以下是预期结果的更大版本:

到目前为止我的代码是这样的:
它只能起作用使用黑白图像。

Here is my code so far: It only works with black and white images.

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")

我的代码返回的输出:

我的程序工作正常黑白图像,但我需要帮助改变它以使用几种颜色(红色,奥兰ge,黄色,浅绿色,深绿色,浅蓝色,深蓝色,紫色,黑色和白色。)

My program works fine for black and white images, but I need help changing it to work with several colors (red, orange, yellow, light green, dark green, light blue, dark blue, purple, black and white).

提前致谢!

推荐答案

你做错了。

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

First of all, you should use PNG, not JPG for your output. JPG introduces so many artifacts, that small images like your output get completely degenerated.

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

Then, you should reduce your palette. It's much easier to work with input containing no noise.

首先,无聊的初始化:

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

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

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

Then we declare the palette - this should contain colors of all possible LEGO bricks. I sampled the values below from your image, but you can use black and white like you do in your code, or any colors you want as long as they're similar to colors in the source image:

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需要平面数组而不是元组数组:

The code below will declare palette for PIL, since PIL needs flat array rather than array of tuples:

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

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

Now we can declare an image that will hold the palette. We'll use it to reduce the colors from the original image later.

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

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

Here we open the image and quantize it. We scale it to size eight times bigger than needed, since we're going to sample the average output later.

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

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

After this, our image looks like this:

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

We need to convert it back to RGB so that we can sample pixels now:

img = img.convert('RGB')

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

Now we're going to construct our final image. To do this, we'll sample how many pixels of each palette color each square in the bigger image contains. Then we'll choose the color that occurs most often.

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)

结果:

上调1600%:

这篇关于带枕头的像素化图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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