Back-End

24 abr, 2012

Primeiros passos com PIL: a biblioteca de imagens do Python

JeGX

Tem 1 artigos publicados com 100 visualizações desde 2011

JeGX
Publicidade

Este é um tutorial sobre Python e GeeXLab. O objetivo é dar uma olhada geral nas bibliotecas Python que podem ser úteis para demos GeeXLab E que funcionam no GeeXLab.

O GeeXLab tem uma maneira muito simples de trabalhar. Superficialmente falando, um demo é feito a partir de um script de inicialização (INIT, executado uma vez) e de um script por frame (FRAME, executado a cada frame). Esses scripts podem ser programados no Lua ou no Python. Em um script, você pode codificar o que quiser com ambas as linguagens. Não existe restrição: o GeeXLab pode ser visto como uma máquina virtual para o Lua ou o Python. É por isso que a maioria dos pacotes Python disponíveis irá funcionar com o GeeXLab.

Para interagir com os dados de cenário do GeeXLab (texturas, GLSL shaders, meshes etc.) existe o Host-API, que é simplesmente a API do GeeXLab para Lua e para Python. A descrição das funções do Host-API para GeeXLab está disponível aqui.

A rápida descrição do scripting do GeeXLab é importante, porque irei focar nas funcionalidades oferecidas por essas bibliotecas, e tentarei limitar o uso das funções GeeXLab ao mínimo. Dessa maneira, você poderá rapidamente reutilizar todos os fragmentos de códigos em seus próprios projetos Python.

Dito isso, vamos falar sobre a primeira biblioteca Python: PIL.

1 – PIL: biblioteca de imagens do Python

PIL ou Biblioteca de Imagens do Python é um pacote que expõe muitas funções para manipular imagens a partir de um script Python. A homepage oficial do PIL está aqui. Quando escrevi este artigo, a versão atual do PIL era PIL 1.1.7 e estava disponível para Python 2.3 até Python 2.7. Irei usar o PIL 1.1.7 for Python 2.6 neste artigo.

No Windows (XP, Vista ou 7), a instalação do PIL é bem simples: apenas inicie o PIL Windows installer e pronto. Claro que você precisa de uma instalação válida do Python 2.6.6 antes.

A documentação do PIL está disponível aqui:

2 – Carregando uma imagem

Aqui está um pequeno script INIT que usa o PIL para carregar uma imagem e exibi-la. Se você precisar, uma versão do PIL pode ser encontrada na variável Image.VERSION.

import HYP_Utils
import sys

from PIL import Image

scriptDir = HYP_Utils.GetDemoDir()

PIL_Version = Image.VERSION

img_filename = "%s/flower.jpg" % scriptDir
im = Image.open(img_filename)
im.show()

No Windows, a função Image.show() salva a imagem em um arquivo temporário e chama o visualizador de imagem padrão. No meu sistema, o Irfanview é chamado para visualizar a imagem:

Demo_Python_PIL_01.xml

3 – Salvando uma imagem

Apenas chame e função Image.save(). Você quer salvar no formato JPEG? Apenas adicione a extensão.jpg no nome do seu arquivo… Mesma coisa para os outros formatos.

Formatos suportados em leitura E escrita: *.bmp, *.gif, *.jpg, *.msp, *.pcx, *.png, *.ppm, *.tiff e .xbm.

Aqui está um simples conversor de JPG para BMP:

import HYP_Utils
from PIL import Image

scriptDir = HYP_Utils.GetDemoDir()

PIL_Version = Image.VERSION

img_filename = "%s/flower.jpg" % scriptDir
im = Image.open(img_filename)
im.save("%s/flower.bmp" % scriptDir)

4 – Lendo os pixels

Existem duas funções que possibilitam a leitura do mapa de pixels (ou pixel data): Image.getpixel() e Image.getdata().

Image.getpixel() retorna o valor de um único pixel. Apenas faça a enupla com as coordenadas X e Y e o getpixel() retornará um 3-tuple RGB para uma imagem RGB ou um único valor para uma imagem de luminância. O Image.getdata() retorna o mapa de pixels completo. Você precisa da função list() do Python para criar a lista do mapa de pixels das tuplenuplas RGB.

Aqui está um fragmento de código que carrega uma imagem com PIL, cria um objeto de textura com o GeeXLab Python API e preenche a textura com os pixels da imagem.

import HYP_Utils
import HYP_Texture
import HYP_Material
import sys

from PIL import Image

scriptDir = HYP_Utils.GetDemoDir()

PIL_Version = Image.VERSION

img_filename = "%s/flower.jpg" % scriptDir
im = Image.open(img_filename)

imageW = im.size[0]
imageH = im.size[1]

TEXTURE_2D = 2
RGB_BYTE = 2
texId = HYP_Texture.Create(TEXTURE_2D, RGB_BYTE, imageW, imageH, 0)

matId = HYP_Material.GetId("plane1_mat")
HYP_Material.AddTexture(matId, texId)

if (im.mode == "RGB"):
for y in range(0, imageH):
for x in range(0, imageW):
offset = y*imageW + x
xy = (x, y)
rgb = im.getpixel(xy)
HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb[0], rgb[1], rgb[2])
elif (imout.mode == "L"):
for y in range(0, imageH):
for x in range(0, imageW):
offset = y*imageW + x
xy = (x, y)
rgb = im.getpixel(xy)
HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb, rgb, rgb)

Com o Image.getdata(), as últimas linhas do script anterior seriam:

pixels = list(im.getdata())
if (im.mode == "RGB"):
for y in range(0, imageH):
for x in range(0, imageW):
offset = y*imageW + x
rgb = pixels[offset]
HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb[0], rgb[1], rgb[2])
elif (imout.mode == "L"):
for y in range(0, imageH):
for x in range(0, imageW):
offset = y*imageW + x
rgb = pixels[offset]
HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb, rgb, rgb)


Demo_Python_PIL_02.xml

5 – Processamento de imagem

Você pode facilmente aplicar filtros comuns de imagem com o PIL: blur, emboss, sharpen etc. Apenas importe o módulo ImageFilter:

from PIL import Image
from PIL import ImageFilter

...

i = Image.open(img_filename)
im = i.filter(ImageFilter.EMBOSS)
#im = i.filter(ImageFilter.FIND_EDGES)

...

Os filtros pré-definidos são: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SMOOTH, SMOOTH_MORE, e SHARPEN.

Demo_Python_PIL_03.xml – EMBOSS

Demo_Python_PIL_03.xml – FIND_EDGES

Existe também um módulo chamado ImageOps que expõe as funções de processamento da imagem, como colorize(), flip(), grayscale(), invert(), mirror(), solarize(), ou posterize().

Demo_Python_PIL_04.xml – solarise()

Demo_Python_PIL_04.xml – posterize()

6 – Adicionando uma marca d’água

ImageDraw e ImageFont garantem ao PIL a capacidade de escrever textos em uma imagem, bem como desenhar linhas ou pontos. Aqui está o fragmento do código que mostra um simples conversor de lotes com PIL: ele lê todos os arquivos jpg de uma pasta, adiciona a marca d’água (uma cruz e a faixa “GEEXLAB”) e salva as imagens com o prefixo gxl_.

import HYP_Utils
import os, glob
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

scriptDir = HYP_Utils.GetDemoDir()

ft = ImageFont.load("timR24.pil")

os.chdir(scriptDir)
file_list = glob.glob("*.jpg")
for f in file_list:
im = Image.open(scriptDir + str(f))
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=(255, 255, 255))
draw.line((0, im.size[1], im.size[0], 0), fill=(255, 255, 255))
wh = ft.getsize("G E E X L A B")
draw.text((im.size[0]/2 - wh[0]/2, im.size[1]/2 + 20), "G E E X L A B",
fill=(255, 255, 0), font=ft)
draw.text((im.size[0]/2 - wh[0]/2, im.size[1]/2 - 60), "G E E X L A B",
fill=(255, 255, 0), font=ft)
del draw
im.save(scriptDir + "gxl_" + str(f))

O arquivo timR24.pil vem com um pacote de fontes PIL. Você pode fazer o download aqui.

Demo_Python_PIL_05.xml

Existe também uma função legal ImageFont.truetype(), mas ela não funcionou no meu sistema porque essa função se apóia na biblioteca _imagingft.pyd (na verdade um DLL) que não pôde ser carregada devido a um problema de tempo de execução do Visual C. Aqui está o erro em um console GeeXLab:

# ERROR: Python – Script [initScene] has a runtime error. Error line: 29 – Error object: – Error data: DLL load failed: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.. Script disabled.

Este link tem alguns detalhes sobre esse problema.

7 – Downloads

Se você quiser brincar com os demos GeeXLab, você pode encontrá-los no pacote de amostras demo disponíveis aqui. Os demos relacionados ao PIL estão na pasta Python_PIL/.

Aqui está um patch para o GeeXLab 0.2.5 + Python 2.6.6 que você deve usar para executar os demos. Apenas unzip o arquivo e copie o DLL para dentro da pasta GeeXLab_Python_Lua/.

PATCH DOWNLOAD: GeeXLabCore.dll

?

Texto original em inglês de JeGX, disponível em http://www.geeks3d.com/20100930/tutorial-first-steps-with-pil-python-imaging-library/