Olá, daqui é o Alex da DEV STORIES DOT EU. Pillow: The Imaging Library, episódio 4 de 5. Frameworks de machine learning como o PyTorch ou o TensorFlow não sabem exatamente o que é um JPEG ou um PNG. Eles só entendem matemática, o que significa que só entendem arrays multidimensionais. Se passares um ficheiro de imagem diretamente para um modelo, ele vai falhar. Precisas de uma forma de traduzir esses bytes codificados para um formato puramente matemático. The Array Bridge: Moving Pixels to PyTorch é exatamente como resolves isto.
O Pillow atua como o tradutor universal na stack de IA. Quando abres uma imagem usando o Pillow, obténs um objeto Image. Para alimentares uma data pipeline com esse objeto, passas esse objeto Pillow diretamente para o
Numpy usando a função as array. Nos bastidores, o Pillow expõe uma interface de buffer standard. O Numpy lê este memory buffer e encapsula-o num array multidimensional. Para uma fotografia a cores standard, obténs um array tridimensional que representa a altura, a largura e os canais de cor.
É aqui que a coisa fica interessante. Quando fazes esta conversão, sais completamente do ecossistema do Pillow. O array resultante não contém nenhuma da metadata do Pillow. As definições de DPI, os dados EXIF, os perfis de cor ICC e as paletas de cores são completamente removidos. Ficas apenas com os valores numéricos puros e raw dos pixels. Se a tua imagem original era baseada em paletas, como um ficheiro GIF, tens de a converter para uma imagem RGB dentro do Pillow antes de a passares para o Numpy. Caso contrário, vais obter apenas um array de números de index da paleta sem significado, em vez de cores reais.
Assim que os teus pixels estiverem em formato de array, a tua framework pode correr as suas operações de tensores, aplicar filtros ou executar um modelo de computer vision. Mas, eventualmente, recebes um resultado de volta. Um modelo pode fazer o output de um novo array que representa uma imagem gerada ou uma máscara de segmentação. Para veres ou guardares este resultado, tens de atravessar a ponte na direção oposta. Pegas nesse array de output e passas para a função do Pillow chamada from array. O Pillow lê o shape e o data type do array Numpy para descobrir como interpretar os números. Se vir um array de inteiros unsigned de oito bits com três canais, cria por default uma imagem RGB. Se vir apenas um canal, cria uma imagem em tons de cinzento. Também tens a opção de passar explicitamente o color mode, caso precises de fazer override ao comportamento default. Assim que o Pillow reconstrói o objeto de imagem, só tens de chamar o método save para o gravar diretamente no teu disco rígido.
Mover memória entre diferentes libraries pode ser dispendioso. Se estiveres a processar um dataset massivo de imagens de alta resolução, copiar os dados dos pixels de um lado para o outro cria um bottleneck significativo. Para resolver isto, o Pillow suporta o formato Apache Arrow através de uma função chamada from arrow. O Arrow é um standard para dados in-memory. Quando usas a função from arrow, o Pillow constrói uma imagem diretamente da estrutura de dados do Arrow usando zero-copy shared memory. Isto significa que o Pillow e as tuas outras tools apontam exatamente para a mesma localização de memória física. Os dados nunca são duplicados. É uma forma altamente eficiente de alimentar grandes volumes de pixels em pipelines modernas sem esgotar a memória do teu sistema.
O verdadeiro poder de uma imaging library numa stack de IA não está apenas em abrir o ficheiro, mas em sair do caminho de forma elegante para que a matemática possa acontecer. Obrigado por passares uns minutos comigo. Até à próxima, fica bem.