如何为pgm平面ascii格式(P2)的python成像库编写过滤器。这里的问题是,基本的PIL过滤器假设每个像素的字节数是恒定的。
我的目标是使用feep.pgm ()打开Image.open()。请参阅http://netpbm.sourceforge.net/doc/pgm.html或更低版本。
另一种解决方案是,我找到其他有良好记录的ascii灰度格式,它是由PIL和所有主要的图形程序支持的。有什么建议吗?
feep.pgm:
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0编辑:谢谢你的回答,它有效.但是我需要一个使用Image.open()的解决方案。大多数python程序都使用PIL进行图形操作(google: python )。因此,我需要能够注册一个过滤器到PIL。然后,我可以使用任何使用PIL的软件。我现在认为主要是枕木,吡咯烷酮等依赖的程序。
编辑 Ok,我想我现在明白了。下面是包装器pgm2pil.py:
import Image
import numpy
def pgm2pil(filename):
try:
inFile = open(filename)
header = None
size = None
maxGray = None
data = []
for line in inFile:
stripped = line.strip()
if stripped[0] == '#':
continue
elif header == None:
if stripped != 'P2': return None
header = stripped
elif size == None:
size = map(int, stripped.split())
elif maxGray == None:
maxGray = int(stripped)
else:
for item in stripped.split():
data.append(int(item.strip()))
data = numpy.reshape(data, (size[1],size[0]))/float(maxGray)*255
return numpy.flipud(data)
except:
pass
return None
def imageOpenWrapper(fname):
pgm = pgm2pil(fname)
if pgm is not None:
return Image.fromarray(pgm)
return origImageOpen(fname)
origImageOpen = Image.open
Image.open = imageOpenWrapper米莎的答案略有提升。为了防止永不结束的循环,必须保存Image.open。如果pgm2pil返回None包装器调用pgm2pil,后者返回None,后者调用pgm2pil.
下面是测试函数(feep_false.pgm是一个畸形的pgm。"P2“-> "FOO”和lena.pgm只是图像文件):
import pgm2pil
import pylab
try:
pylab.imread('feep_false.pgm')
except IOError:
pass
else:
raise ValueError("feep_false should fail")
pylab.subplot(2,1,1)
a = pylab.imread('feep.pgm')
pylab.imshow(a)
pylab.subplot(2,1,2)
b = pylab.imread('lena.png')
pylab.imshow(b)
pylab.show()发布于 2010-11-25 00:58:57
我目前处理这个问题的方式是通过numpy
numpy数组中。您不需要使用numpy,但是我发现它比常规的Python2D数组更容易使用PIL.Image将二维numpy数组转换为PIL.Image.fromarray对象如果坚持使用PIL.Image.open,可以编写一个包装器,首先尝试加载PGM文件(通过查看头部)。如果是PGM,使用上述步骤加载映像,否则只需将责任交给PIL.Image.open。
下面是一些代码,用于将PBM图像导入numpy数组。
import re
import numpy
def pbm2numpy(filename):
"""
Read a PBM into a numpy array. Only supports ASCII PBM for now.
"""
fin = None
debug = True
try:
fin = open(filename, 'r')
while True:
header = fin.readline().strip()
if header.startswith('#'):
continue
elif header == 'P1':
break
elif header == 'P4':
assert False, 'Raw PBM reading not implemented yet'
else:
#
# Unexpected header.
#
if debug:
print 'Bad mode:', header
return None
rows, cols = 0, 0
while True:
header = fin.readline().strip()
if header.startswith('#'):
continue
match = re.match('^(\d+) (\d+)$', header)
if match == None:
if debug:
print 'Bad size:', repr(header)
return None
cols, rows = match.groups()
break
rows = int(rows)
cols = int(cols)
assert (rows, cols) != (0, 0)
if debug:
print 'Rows: %d, cols: %d' % (rows, cols)
#
# Initialise a 2D numpy array
#
result = numpy.zeros((rows, cols), numpy.int8)
pxs = []
#
# Read to EOF.
#
while True:
line = fin.readline().strip()
if line == '':
break
for c in line:
if c == ' ':
continue
pxs.append(int(c))
if len(pxs) != rows*cols:
if debug:
print 'Insufficient image data:', len(pxs)
return None
for r in range(rows):
for c in range(cols):
#
# Index into the numpy array and set the pixel value.
#
result[r, c] = pxs[r*cols + c]
return result
finally:
if fin != None:
fin.close()
fin = None
return None您必须稍微修改它以满足您的目的,即:
编辑
下面是我处理包装器的方法:
def pgm2pil(fname):
#
# This method returns a PIL.Image. Use pbm2numpy function above as a
# guide. If it can't load the image, it returns None.
#
pass
def wrapper(fname):
pgm = pgm2pil(fname)
if pgm is not None:
return pgm
return PIL.Image.open(fname)
#
# This is the line that "adds" the wrapper
#
PIL.Image.open = wrapper我没有编写pgm2pil,因为它将非常类似于pgm2numpy。唯一的区别是它将结果存储在PIL.Image中,而不是numpy数组中。我也没有测试包装代码(抱歉,现在时间有点短),但这是一个相当常见的方法,所以我希望它能工作。
现在,听起来您希望使用PIL进行图像加载的其他应用程序能够处理PGM。使用上面的方法是可能的,但是您需要确保上面的包装代码在第一次调用PIL.Image.open之前被添加到PIL.Image.open。您可以通过将包装器源代码添加到PIL源代码(如果您有访问权限)来确保这一点。
https://stackoverflow.com/questions/4270700
复制相似问题