복붙노트

[PYTHON] PIL에서 Image.point () 메서드를 사용하여 픽셀 데이터 조작

PYTHON

PIL에서 Image.point () 메서드를 사용하여 픽셀 데이터 조작

파이썬 이미징 라이브러리를 사용하여 색상 관계를 정의하는 조회 테이블을 사용하여 흑백 이미지를 채색합니다. 룩업 테이블은 간단히 256 요소의 RGB 튜플 목록입니다.

>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>> 

내 첫 번째 버전에서는 getpixel () 및 putpixel () 메서드를 사용했습니다.

    for x in range(w):
        for y in range(h):
            pix = img.getpixel((x,y))
            img.putpixel((x,y), colors[pix[0]])

이것은 끔찍하게 느렸다. 프로파일 보고서는 putpixel 및 getpixel 메소드를 범인으로 지적했습니다. 약간의 조사 (즉, 문서 읽기)와 나는 "이 방법은 상대적으로 느리다는 것을 알았습니다." 다시 : putpixel. (실제 런타임 : puts 픽셀의 53s 및 1024x1024 이미지의 50s getpixel)

문서의 제안을 토대로 im.load ()를 사용하고 직접 픽셀 액세스를 사용했습니다.

    pixels = img.load()
    for x in range(w):
        for y in range(h):
            pix = pixels[x, y]
            pixels[x, y] = colors[pix[0]]                

처리 속도는 빨라졌지만 여전히 느립니다. 1024x1024 이미지를 처리하려면 약 3.5 초.

PIL 문서에 대한보다 철저한 연구는 Image.point ()가이 목적을 위해 의도 된 것임을 나타냅니다.

나는 인터페이스를 해킹하는 데 약간의 시간을 할애했지만 제대로 이해할 수는 없다. 내 무지를 용서하지만, PIL의 문서는 깔끔하지 않으며 많은 이미지 처리 경험이 없습니다. 몇 번 봤 거든 몇 가지 예를 들어, 아무것도 나를 위해 "클릭"사용했다. 따라서, 마지막으로, 내 질문 :

해결법

  1. ==============================

    1.예, 실제로 Image.point ()는이 작업에 적합합니다.

    예, 실제로 Image.point ()는이 작업에 적합합니다.

    [(12, 140, 10), (10, 100, 200), ...] 대신에 목록을 병합해야합니다.

    [12, 140, 10, 10, 100, 200, ...]
    

    다음은 방금 시도한 간단한 예입니다.

    im = im.point(range(256, 0, -1) * 3)
    

    그런데 색상을 더 많이 제어해야하는 경우 Image.point를 사용할 수 없다고 생각하면 Image.getdata 및 Image.putdata를 사용하여 load 및 putpixel보다 더 빨리 색상을 변경할 수 있습니다. 그래도 Image.point보다 느립니다.

    Image.getdata는 모든 픽셀의 목록을 제공하고 수정하고 Image.putdata를 사용하여 다시 씁니다. 그렇게 간단합니다. 그러나 먼저 Image.point를 사용하여 해보십시오.

    편집하다

    첫 번째 설명에서 실수를했습니다. 지금 올바르게 설명하겠습니다.

    실제로 색상 표는 다음과 같습니다.

    [0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]
    

    각 밴드는 다른 밴드와 나란히 있습니다. 색상 (0, 0, 0)을 (10, 100, 10)으로 변경하려면 다음과 같이해야합니다.

    [10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]
    

    색상 목록을 올바른 형식으로 변환하려면 다음을 시도하십시오.

    table = sum(zip(*colors), ())
    

    제 첫 번째 예제가 당신을위한 형식을 보여줘야한다고 생각합니다.

  2. ==============================

    2.필자는 PIL 튜토리얼에서 직접 들었던 것처럼 밴드 대 기본을 지적하는 것이 더 일반적이라고 생각합니다.

    필자는 PIL 튜토리얼에서 직접 들었던 것처럼 밴드 대 기본을 지적하는 것이 더 일반적이라고 생각합니다.

    # split the image into individual bands
    source = im.split()
    
    R, G, B = 0, 1, 2
    
    # select regions where red is less than 100
    mask = source[R].point(lambda i: i < 100 and 255)
    
    # process the green band
    out = source[G].point(lambda i: i * 0.7)
    
    # paste the processed band back, but only where red was < 100
    source[G].paste(out, None, mask)
    
    # build a new multiband image
    im = Image.merge(im.mode, source)
    
  3. from https://stackoverflow.com/questions/2181292/using-the-image-point-method-in-pil-to-manipulate-pixel-data by cc-by-sa and MIT license