Extração de metadados de imagens com Python
Tags: programming, python, braziliandevs, tutorial
Published: 2024-04-14 14:17:46

Neste post, falamos sobre os metadados de imagens. Mostramos como usar ferramentas na linguagem Python para extrair esse tipo de informação.

Atualmente, na "Era dos Dados/IA", é comum ouvir que <a href="https://medium.com/geekculture/if-data-is-petrol-a4358b3f2038">_"Dados são o novo petróleo"_</a>. Não é difícil entender esse jargão, mas fica a dúvida: "Se os dados são análogos ao petróleo, nos dias de hoje, os <a href="https://en.wikipedia.org/wiki/Metadata">metadados</a> seriam comparáveis ao que"?

---

## Um pouco sobre imagens e metadados

Antes de rodar o código Python que fará a extração dos metadados, vejamos rapidamente alguns pontos sobre as imagens digitais.

### Como é formado um arquivo de imagem?
De forma resumida, uma <a href="https://en.wikipedia.org/wiki/Digital_imaging">imagem digital</a> é um <a href="https://en.wikipedia.org/wiki/File_format">arquivo</a>, no formato `PNG`, `JPEG`, `GIF`, etc., que segue as especificações que o definem. Assim como muitos arquivos digitais, no computador as imagens podem ser representadas por matrizes, onde cada entrada da matriz está associada a um <a href="https://en.wikipedia.org/wiki/Pixel">pixel</a>. Essa relação não é biunívoca, pois depende da configuração do computador usado para trabalhar com a imagem. Se uma imagem digital tem resolução 800 X 600 (largura X altura), então corresponde a um total de 480.000 pixels na tela do computador. Geralmente, quando se aplica alguma transformação numa imagem, estamos realizando operações com matrizes/submatrizes de pixels.

### O que significa o prefixo *meta*?
Segundo o <a href="https://dicionario.priberam.org/meta">dicionário online Priberam</a>, o prefixo `meta` é uma palavra que _"exprime a noção de reflexão sobre si (ex.: metalinguagem)"_. Dessa maneira, o termo ***metadados*** significa "dados sobre algum dado". Neste post, focamos nas imagens e seus metadados. Muitas vezes o sistema operacional do computador acessa esses dados para alguma finalidade.

### Os metadados de uma imagem são obrigatórios?
Assim como cada imagem pode ter um formato diferente, as informações que essas imagens carregam sobre si também podem mudar. Para ilustrar, nas respectivas extensões, os formatos GIF (lançado em 1987), JPEG (introduzida em 1982) e WebP (de 2010) possuem especificações diferentes para sua formação. A palavra hexadecimal</a> usada para identificar cada um destes é diferente. Mais detalhes podem ser encontrados neste <a href="https://en.wikipedia.org/wiki/List_of_file_signatures">link</a>.

Além disso, as imagens podem ser geradas em contextos particulares e por dispositivos com característica diferentes, como imagens de satélite, imagens médicas, imagens geofísicas, etc. Isso adiciona maior complexidade para uma padronização única dos metadados de imagens. Os metadados de imagens costumam variar ou mesmo serem excluídos. O WhatsApp serve de exemplo de um aplicativo que costuma <a href="https://www.editprivacy.com/whatsapp-photo-metadata/">remover alguns metadados</a> de imagens enviadas através dele.

---

## Como extrair os metadados usando Python?
Agora veremos como extrair os metadados de uma imagem na prática. Para isso usaremos a biblioteca open source chamada <u>[`Hachoir`](https://hachoir.readthedocs.io/en/latest/index.html)</u>.

![Mata-Atlântica](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkrvuhbkeqf3pzelky9r.jpg)

<small><small>Fonte: <a href="www.ecolibrary.org/page/DP43">www.ecolibrary.org/page/DP43</a> | Licença: <a href="https://creativecommons.org/licenses/by-nc/3.0/us/">https://creativecommons.org/licenses/by-nc/3.0/us/</a></small></small>

### Hachoir

A ferramenta Hachoir é uma biblioteca Python que permite extrairmos metadados de arquivos como imagens, vídeos, áudio, entre outros. Sua <a href="https://hachoir.readthedocs.io/en/latest/metadata.html#metadata">documentação</a> traz exemplos interessantes.

**Instalação:** Para instalá-lo `Hachoir`, basta digitar o seguinte comando num terminal com Python 3 instalado:
```shell
pip install hachoir
```

**Código usado:** Para realizar a extração dos metadados usaremos o script abaixo:

```Python
# extrai_metadados.py
import hachoir.metadata
import hachoir.parser
from hachoir.core import config as HachoirConfig
HachoirConfig.quiet = True

img_path = 'mata_atlantica.jpg'
# www.ecolibrary.org/page/DP43
# license: https://creativecommons.org/licenses/by-nc/3.0/us/

filename = img_path
parser = hachoir.parser.createParser(filename)

hachoir_metadata = hachoir.metadata.extractMetadata(parser)
metadata = hachoir_metadata.exportDictionary()['Metadata']
print(metadata)
```
Note que a variável `img_path` é onde definimos o caminho até o arquivo de imagem que escolhemos. No caso, foi escolhido uma foto em `JPG`, mas poderíamos ter escolhido um outro formato.

Podemos rodar o script `extrai_metadados.py` mencionado acima com:
```shell
python extrai_metadados.py
```

**Saída esperada:** Após rodar esse script, obtemos como resposta um dicionário Python (semelhante a um `json`):

```json
{"Author": "Dan L. Perlman",
"Image width": "1024 pixels",
"Image height": "768 pixels",
"Image orientation": "Horizontal (normal)",
"Bits/pixel": "24",
"Pixel format": "YCbCr",
"Image DPI width": "93 DPI",
"Image DPI height": "93 DPI",
"Creation date": "2008-03-20 16:53:27",
"Camera focal": "19",
"Camera exposure": "1/4",
"Camera brightness": "5.16",
"Camera model": "FinePixS2Pro",
"Camera manufacturer": "FUJIFILM",
"Compression": "JPEG (Baseline)",
"Copyright": "© Dan L. Perlman 2008
http://creativecommons.org/licenses/by-nc/3.0/us/",
"Thumbnail size": "8471 bytes",
"ISO speed rating": "100",
"EXIF version": "0220",
"Date-time original": "2004-10-23 09:47:24",
"Date-time digitized": "2004-10-23 09:47:24",
"Compressed bits per pixel": "3.2",
"Shutter speed": "2",
"Aperture": "8.5",
"Exposure bias": "0",
"Focal length": "18",
"Flashpix version": "0100",
"Focal plane width": "1.86e+03",
"Focal plane height": "1.86e+03",
"Focal length in 35mm film": "27",
"Producer": "Adobe Photoshop CS3 Windows",
"Comment": "JPEG quality: 91% (approximate)",
"Format version": "JFIF 1.02",
"MIME type": "image/jpeg",
"Endianness": "Big endian"}
```

Acima temos os metadados extraídos da <a href="www.ecolibrary.org/page/DP43">imagem</a> que escolhemos para este teste. Parte desses itens são extraídos do EXIF, <a href="https://en.wikipedia.org/wiki/Exif">uma padronização</a> que especifica formatos para imagens geradas por dispositivos como câmeras, smartphones, scanner, etc. Com o EXIF é possível obter dados de data e hora, informações do dispositivo usado na geração da imagem, geolocalização, métricas sobre os pixels e os direitos autorais da imagem.

### Observações sobre os metadados extraídos
Para a imagem `JPG` que usamos (`mata_atlantica.jpg`), a resposta do script `extrai_metadados.py` fornece informações básicas como:
```json
"Image width": "1024 pixels",
"Image height": "768 pixels",
"Image orientation": "Horizontal (normal)",
"Bits/pixel": "24",
"Pixel format": "YCbCr",
"MIME type": "image/jpeg",
"Endianness": "Big endian"
...
```
Também há informações sobre o dispositivo usado para gerar essa imagem:
```json
"Camera focal": "19",
"Camera exposure": "1/4",
"Camera brightness": "5.16",
"Camera model": "FinePixS2Pro",
"Camera manufacturer": "FUJIFILM",
"Shutter speed": "2",
"Aperture": "8.5",
"Exposure bias": "0",
"Focal length": "18",
"Flashpix version": "0100",
"Focal plane width": "1.86e+03",
"Focal plane height": "1.86e+03",
"Focal length in 35mm film": "27"
...
```
**Curiosidade:** Pelos metadados, a máquina usada para tirar a foto foi uma [FUJIFILM FinePix S2 Pro](https://www.dpreview.com/reviews/fujis2pro).

Os metadados extraídos ainda trazem a data de criação, autoria e licença de uso da imagem:
```json
"Author": "Dan L. Perlman",
"Creation date": "2008-03-20 16:53:27",
"Date-time original": "2004-10-23 09:47:24",
"Date-time digitized": "2004-10-23 09:47:24",
"Copyright": "© Dan L. Perlman 2008
http://creativecommons.org/licenses/by-nc/3.0/us/"
...
```

**Nota:** Embora para `mata_atlantica.jpg` foi possível a extração de inúmeros metadados, pode ser que isso mude conforme a imagem escolhida. Dependendo da caso, os dados extraídos podem ser diferentes dos apresentados neste exemplo.

Lembremos ainda que os metadados são <u>editáveis</u>. Ou seja, uma imagem pode ter informações detalhadas, ou não, sobre sua criação. Já o objeto real, usado para gerar a imagem digital, não muda (excluindo situações particulares).

***Agradecemos a leitura! Vc conhece algum caso de uso que ache interessante e envolva metadados? Compartilhe, será bem-vindo!***

<center>📖 . 🤖 .. ☕ ... 🐌 .... 🦥 ..... 👾 ..... 👻💡</center>

<small><small><small>* **A imagem de capa deste post foi gerada com um text-to-image usando a frase _"Data about data about data about data about data ad infinitum in pt-br"_.**</small></small></small>