2017-02-21 8 views
0

나는 Vips 이미지 라이브러리를 사용하여 거대한 조직 이미지를 만들고 있습니다. 이미지와 함께 좌표가있는 배열이 있습니다. 좌표로 생성 된 다각형 내의 이미지 부분을 가려내는 바이너리 마스크를 만들고 싶습니다. 먼저 vips draw 함수를 사용하여이 작업을 시도했지만 매우 비효율적이며 영원히 필요합니다 (실제 코드에서 이미지는 약 100000 x 100000 픽셀이고 폴리곤 배열은 매우 큽니다).PIL 이미지를 VIPS 이미지로 변환

필자는 PIL을 사용하여 바이너리 마스크를 만들려고했는데이 방법이 효과적입니다. 내 문제는 PIL 이미지를 vips 이미지로 변환하는 것입니다. multiply-command를 사용할 수 있으려면 둘 다 vips 이미지 여야합니다. 또한 디스크에 쓰는 것보다 빠르다고 믿기 때문에 메모리에서 쓰고 읽고 싶습니다.

im_PIL.save(memory_area,'TIFF') 명령에서 이미지 형식을 지정해야하지만 새 이미지를 작성하기 때문에 여기에 무엇을 넣을 지 잘 모르겠습니다.

Vips.Image.new_from_memory(..) 명령이 리턴 : TypeError: constructor returned NULL

from gi.overrides import Vips 
from PIL import Image, ImageDraw 
import io 

# Load the image into a Vips-image 
im_vips = Vips.Image.new_from_file('images/image.tif') 

# Coordinates for my mask 
polygon_array = [(368, 116), (247, 174), (329, 222), (475, 129), (368, 116)] 

# Making a new PIL image of only 1's 
im_PIL = Image.new('L', (im_vips.width, im_vips.height), 1) 

# Draw polygon to the PIL image filling the polygon area with 0's 
ImageDraw.Draw(im_PIL).polygon(polygon_array, outline=1, fill=0) 

# Write the PIL image to memory ?? 
memory_area = io.BytesIO() 
im_PIL.save(memory_area,'TIFF') 
memory_area.seek(0) 

# Read the PIL image from memory into a Vips-image 
im_mask_from_memory = Vips.Image.new_from_memory(memory_area.getvalue(), im_vips.width, im_vips.height, im_vips.bands, im_vips.format) 

# Close the memory buffer ? 
memory_area.close() 

# Apply the mask with the image 
im_finished = im_vips.multiply(im_mask_from_memory) 

# Save image 
im_finished.tiffsave('mask.tif') 

답변

1

당신은 TIFF 형식으로 PIL에서 저장하지만, 다음의 VIP를 픽셀 값의 간단한 C 배열을 기대하고있다 new_from_memory 생성자를 사용하고 있습니다.

가장 쉬운 방법은 new_from_buffer을 사용하는 것입니다.이 방법은 이미지를 어떤 형식으로로드하여 문자열에서 형식을 스니핑합니다. 프로그램의 중간 부분을 다음과 같이 변경하십시오.

# Write the PIL image to memory in TIFF format 
memory_area = io.BytesIO() 
im_PIL.save(memory_area,'TIFF') 
image_str = memory_area.getvalue() 

# Read the PIL image from memory into a Vips-image 
im_mask_from_memory = Vips.Image.new_from_buffer(image_str, "") 

그러면 작동합니다.

두 개의 8 비트 uchar 이미지에 대한 multiply 작업은 16 비트 uchar 이미지를 만듭니다. 숫자 범위는 0 - 255가 될 것이므로 매우 어둡게 보일 것입니다. 다시 uchar로 캐스팅하거나 저장하기 전에 .cast("uchar")을 곱하기 선에 추가하십시오.) 또는 PIL 마스크에 대해 1 대신 255를 사용하십시오.

간단한 바이트 배열로 이미지를 PIL에서 VIPS로 이동할 수도 있습니다. 약간 더 빠를 수도 있습니다.

당신이 맞습니다. draw의 작업은 파이썬의 매우 큰 이미지에서는 잘 작동하지 않습니다. 한 세트의 포인트로부터 임의의 크기의 마스크 이미지를 만들기 위해 (단지 굴곡 규칙으로 &&<의 롯트를 합치는 것), 그러나 PIL을 사용하는 것은 확실히 간단합니다.

폴리 마스크를 SVG 이미지로 생각할 수도 있습니다. libvips는 매우 큰 SVG 이미지를 효율적으로로드 할 수 있습니다 (필요에 따라 섹션을 렌더링합니다). 따라서 래스터 이미지에 필요한 크기까지 확대하면됩니다.

+0

답변 해 주신 'new_from_buffer'로 변경해 주셔서 감사합니다. 또한 multiply 함수에 캐스팅을 추가하는 것과 관련된 추가 정보를 보내 주셔서 감사합니다. 먼저이 솔루션을 시도해보고 필요한 경우 다른 제안을 고려하십시오. – Rune