2010-11-24 5 views
3

pgm 일반 ascii 형식 (P2) 용 파이썬 이미징 라이브러리에 필터를 쓰려면 어떻게해야합니까? 문제는 기본 PIL 필터가 픽셀 당 일정한 바이트 수를 가정한다는 것입니다.일반 pgm 형식의 PIL 이미지 필터를 작성하는 방법은 무엇입니까?

내 목표는 Image.open()으로 feep.pgm을 여는 것입니다. http://netpbm.sourceforge.net/doc/pgm.html 이하를 참조하십시오.

대체 솔루션은 PIL 및 모든 주요 그래픽 프로그램에서 지원하는 다른 잘 문서화 된 ASCII 회색 음영 형식을 찾는 것입니다. 어떤 제안?

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를 사용하는 솔루션이 필요합니다(). 파이썬 프로그램의 대부분은 그래픽 조작 (구글 : 파이썬 이미지 열기)을 위해 PIL을 사용합니다. 따라서 PIL에 필터를 등록 할 수 있어야합니다. 그런 다음 PIL을 사용하는 모든 소프트웨어를 사용할 수 있습니다. 나는 이제 대부분 scipy, pylab 등의 의존적 인 프로그램을 생각합니다.

편집 좋아, 이제 알았어. 아래 래퍼는 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 

misha의 답변에는 약간의 업그레이드가 있습니다. 결코 끝나지 않는 루프를 막기 위해 Image.open을 저장해야합니다. > "FOO"와 lena.pgm은 는 IS - pgm2pil가 pgm2pil 호출 없음을 반환하는 pgm2pil 없음 래퍼 전화를 ... 반환하면 다음

테스트 기능 (feep_false.pgm 조작 된 PGM의 예 : "P2"입니다 이미지 파일) :

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() 
+0

감사합니다. 하지만, 왜 numpy.flipud (데이터)를 반환합니까? 데이터 만 반환해야합니다. – user1245262

+0

오래 전이 작업을했을 때 ... 이미지가 직교 좌표계 (y 축 반전)에 있지 않다는 것입니다. IMHO 이미지는 플립이없는 데카르트 시스템에 있어야합니다 (또는 플립과 함께, 나는 어떤 방법으로 기억이 나지 않습니다). 위의 그림에서 imread와 imshow를 사용할 때 이미지가 올바르게 표시됩니다. – Juha

+0

아 ... 그건 의미가 있습니다. 나는 그 생각을 했어야했다. 다시 한번 감사드립니다. – user1245262

답변

5

방법 나는 현재이 처리는 numpy 통해 :

  1. 읽기 이미지 차원 numpy 배열로. 당신은 numpy를 사용하지 필요을,하지만 난 PIL.Image.open를 사용하여 쉽게
  2. 당신이 주장하는 경우 PIL.Image.fromarray

사용 PIL.Image 객체로 2D NumPy와 배열을 변환 일반 파이썬 2 차원 배열보다 사용하는 것으로 나타났습니다 , 먼저 헤더를보고 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 

당신은 약간 즉, 사용자의 목적에 맞게 수정해야합니다 : P2 (ASCII, 그레이 스케일) 대신 P1 (ASCII, 이중 레벨)와

  • 거래.
  • numpy를 사용하지 않는 경우 다른 컨테이너를 사용하십시오. 일반적인 Python 2D 배열은 정상적으로 작동합니다.이 pgm2numpy 매우 유사 될 것 때문에

    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를 작성하지 않은 :

편집 여기

내가 래퍼를 처리 할 방법이다. 유일한 차이점은 numpy 배열과 대조적으로 결과를 PIL.Image에 저장한다는 것입니다. 나는 또한 wrapper 코드를 테스트하지 않았다. (미안하지만 약간의 시간이 조금있다.) 그러나 나는 그것이 작동하기를 기대하기 때문에 상당히 일반적인 접근법이다.

기타 PGM을 처리 할 수 ​​있도록 이미지로드에 PIL을 사용하는 응용 프로그램이 필요합니다. 위의 방법을 사용하면 가능하지만 위의 래퍼 코드가 의 첫 번째 호출 인 앞에 이 추가되었는지 확인해야합니다. PIL 소스 코드에 래퍼 소스 코드를 추가하여 액세스가 가능한지 확인할 수 있습니다.

+0

질문은 다음과 같습니다. 어떻게 래퍼를 작성합니까? 그리고 파이썬에게 PIL.image.open에 대한 래퍼가 있다는 것을 어떻게 알 수 있습니까? – Juha

+0

@Juha 내 업데이트 된 답변을 참조하십시오. – misha

관련 문제