使用PPM文件在Python中将图像转换为ASCII,不允许使用PIL

1 投票
2 回答
3648 浏览
提问于 2025-04-17 01:57

我需要一点帮助或者指导,正在做一个项目。我们的任务是读取一个 .ppm 文件(我们需要测试的文件可以在这里找到:http://beastie.cs.ua.edu/cs250/projects/asciiart/tux.ppm),然后用 ASCII 字符在屏幕上重新打印出来。我们需要把像素转换成灰度。这正是我卡住的地方。我不知道怎么读取每三个元素(因为在 PPM 文件中,每三个元素代表一个像素),把它们转换成灰度后再继续。再说一遍,不允许使用 PIL 库。如果有人能提供帮助或者推荐一些阅读材料,那就太好了!

2 个回答

1

读取ppm文件时,你可以这样做:

# Open the PPM file and process the 3 first lines
f = open("tux.ppm")
color = f.readline().splitlines()
size_x, size_y = f.readline().split()
max = f.readline().splitlines()

其实你不需要了解文件的前三行内容。你只需要知道你正在处理的是一张RGB图像,这意味着每个像素有三个值(范围是0到255)。

要把图像转换为灰度图,你有两个选择:你可以生成另一个PPM文件(每个像素仍然有三个值),或者你可以生成一个PGM文件,它的格式和PPM一样,但第一行是P2而不是P3,并且每个像素只有一个值(这是一种更酷的方式)。

要把一个RGB颜色值(r,g,b)转换成一个灰度强度值,你可以使用这个公式(比简单取平均值要好):

0.21*r + 0.71*g + 0.07*b

生成每个像素只有一个值的灰度图像(如果你想要三个值的格式,只需把这个值重复三次,分别对应r、g、b):

# Getting the image data (if you have read the 3 first lines...)
data = f.read().split()

# Generate a new array of pixels with grayscale values (1 per pixel)
gray_data = [0.21*data[i] + 0.71*data[i+1] + 0.07*data[i+2] for i in range(0,len(data),3)]
3

PPM格式的解析其实并不复杂。

首先是文件的头部:

P3
50 50
255
  • P3表示这个图片是一个ASCII格式的彩色图像。
  • 50 50表示图片的宽度和高度都是50像素。
  • 255是颜色的最大值,也就是最亮的颜色。

接下来是文件的主体部分:

254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 
254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 
254 254 252 254 254 252 254 254 252 253 255 250 239 244 237 251 255 248 
234 236 231 255 255 251 252 251 249 255 254 251 253 248 242 255 255 244 
...

只需要去掉所有的换行符:

body.replace('\n', ' ')

然后以三元组的方式解析(虽然看起来不太优雅):

raw = body.split(' ')

for i in range(0, len(raw), 3):
  red = raw[i]
  green = raw[i + 1]
  blue = raw[i + 2]

撰写回答