将每个像素从图像转换为字母 PIL

Convert each pixel from a image to a letter PIL

我有一个由黑白像素 (16x16 img) 组成的文件“map.jpg”,我想在文本文件中将白色像素转换为 0,将黑色像素转换为 a 1. 我有这个:

from PIL import Image
import os

mapImg = Image.open('map.png')

with open('map.txt', 'a+') as map:
    for y in range(16):
        for x in range(16):
            pix = mapImg.getpixel((x, y))
            if x == 15:
                map.write('\n')
            else:
                if pix == (255, 255, 255):
                    map.write('0')
                else:
                    map.write('1')

但是我不知道为什么我的txt文件中的结果是这样的:

000000000
0011000000
0111110000
0100000110
0010011100
0101010
0111100
000010101000
001110000
00011000000
0000100000
0011000
0000010000
00000000
000000000
000000000

这不是“map.jpg”文件的样子。

编辑:多亏了 Random Davis,问题解决了!只是需要更改图像格式,因为 jpeg 将 img 压缩了很多,谢谢!

如果您的图像是 jpg,那么它是有损压缩的,这意味着所有像素不一定都是全黑或全白的。您需要一个真正只有这两种颜色的无损源,否则像素将被错误分类。

除了jpg文件使用有损压缩这一事实之外,如其他答案所述,无损压缩图像文件(例如png)还可以包含所有不同的RGB颜色组合(例如不同的灰色调)。如果您只对黑色和白色之间的区别感兴趣,您可以例如计算平均 RGB 值¹ 并使用阈值(如果平均值≥128,则写 0,否则写 1)。这也适用于有损压缩的 jpg 文件,因为压缩算法通常不会改变像素太多,以至于亮像素会突然变暗。

您最后的 if 语句可以这样写:

pix_avg_rgb = sum(pix) / 3
if pix_avg_rgb >= 128:
    map.write('0')
else:
    map.write('1')

¹ 由于 RGB 颜色 space 与感知亮度的非线性,平均 RGB 值与像素的感知亮度不完全匹配,但这超出了此问题的范围。