Ler ficheiros de imagem

Importante

A Databricks recomenda que utilize a fonte de dados de ficheiro binário para carregar dados de imagem no DataFrame do Spark como bytes em bruto. Consulte Solução de referência para aplicativos de imagem para o fluxo de trabalho recomendado para lidar com dados de imagem.

A fonte de dados de imagem fornece uma API padrão para carregar ficheiros de imagem no Spark DataFrames como uma estrutura decodificada, dando-lhe acesso direto a metadados de imagem como altura, largura, contagem de canais e dados brutos de pixels. É utilizado principalmente em pipelines de pré-processamento de aprendizagem automática, onde são necessários campos de imagem estruturados juntamente com dados de pixels. O Azure Databricks suporta a fonte de dados de imagem para leituras em lote, incluindo a descoberta de partições para diretórios de imagens organizados. Para ler arquivos de imagem, especifique a fonte format de dados como image.

Prerequisites

O Azure Databricks não requer configuração adicional para usar a fonte de dados da imagem.

Opções

Use os métodos .option() e .options() de DataFrameReader para configurar a origem dos dados da imagem. Para uma lista completa de opções suportadas, consulte a referência de opções da API Spark.

Usage

Os exemplos seguintes demonstram como carregar ficheiros de imagem usando a API Spark DataFrame, selecionar campos de metadados de imagem, mostrar miniaturas de imagem e guardar dados de imagem decodificados numa tabela Delta.

Ler ficheiros de imagem

Use a API Apache Spark DataFrame para carregar ficheiros de imagem num DataFrame. Pode importar uma estrutura de diretórios aninhada ao indicar um caminho de diretório e utilizar a deteção de partições ao especificar um caminho com um diretório de partição (por exemplo, /path/to/dir/date=2018-01-02/category=automobile).

Python

# Read all images from a directory
df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
display(df)

# Use partition discovery by specifying a partitioned path
df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/date=2024-01-01/category=dogs/")
display(df)

Scala

// Read all images from a directory
val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.show()

// Use partition discovery by specifying a partitioned path
val partitioned = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/date=2024-01-01/category=dogs/")
partitioned.show()

SQL

-- Read all images from a directory
SELECT * FROM read_files(
  '/Volumes/<catalog>/<schema>/<volume>/images/',
  format => 'image'
)

Selecionar metadados de imagem

Para trabalhar com dimensões de imagem ou informação de canal sem processar todos os dados do pixel, selecione campos específicos da image coluna da estrutura.

Python

df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
metadata = df.select("image.origin", "image.height", "image.width", "image.nChannels")
display(metadata)

Scala

val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
val metadata = df.select("image.origin", "image.height", "image.width", "image.nChannels")
metadata.show()

SQL

SELECT image.origin, image.height, image.width, image.nChannels FROM read_files(
  '/Volumes/<catalog>/<schema>/<volume>/images/',
  format => 'image'
)

Exibir dados de imagem

A função Databricks display renderiza as miniaturas das imagens diretamente na image coluna ao trabalhar com a fonte de dados da imagem. Consulte Imagens para opções de visualização suportadas.

Python

df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
display(df)

Scala

val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.show()

SQL

SELECT * FROM read_files(
  '/Volumes/<catalog>/<schema>/<volume>/images/',
  format => 'image'
)

Guardar os dados da imagem numa tabela Delta

Para melhorar o desempenho de leitura ao carregar dados de imagem de volta, guarde o DataFrame numa tabela Delta.

Note

A fonte de dados de imagem armazena dados de píxeis decodificados, o que aumenta o uso do disco em comparação com bytes brutos. Para uma persistência com utilização eficiente do armazenamento, use em vez disso a fonte de dados de ficheiro binário.

Python

df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.write.format("delta").saveAsTable("<catalog>.<schema>.<table>")

Scala

val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.write.format("delta").saveAsTable("<catalog>.<schema>.<table>")

Esquema de saída

Os arquivos de imagem são carregados como um DataFrame contendo uma única coluna do tipo struct chamada image com os seguintes campos:

root
 |-- image: struct (nullable = true)
 |    |-- origin: string (nullable = true)
 |    |-- height: integer (nullable = false)
 |    |-- width: integer (nullable = false)
 |    |-- nChannels: integer (nullable = false)
 |    |-- mode: integer (nullable = false)
 |    |-- data: binary (nullable = false)

Os campos seguintes descrevem o ficheiro de imagem e os seus dados de píxeis decodificados.

  • origin: O caminho do ficheiro da imagem de origem.
  • height: A altura da imagem em pixels.
  • width: A largura da imagem em pixels.
  • nChannels: O número de canais de cor. Os valores típicos são 1 para imagens em tons de cinza, 3 para imagens coloridas (por exemplo, RGB) e 4 para imagens coloridas com canal alfa.
  • mode: Sinalizador inteiro que indica como interpretar o campo de dados. Ele especifica o tipo de dados e a ordem do canal em que os dados são armazenados. O valor do campo é esperado (mas não imposto) para mapear para um dos tipos de OpenCV exibidos na tabela a seguir. Os tipos OpenCV são definidos para 1, 2, 3 ou 4 canais e vários tipos de dados para os valores de pixel. A ordem do canal especifica a ordem em que as cores são armazenadas. Por exemplo, se você tiver uma imagem típica de três canais com componentes vermelhos, azuis e verdes, há seis pedidos possíveis. A maioria das bibliotecas usa RGB ou BGR. Espera-se que os tipos OpenCV de três (quatro) canais sigam a ordem BGR(A).

Mapa do tipo para números no OpenCV (tipos de dados x número de canais)

Tipo C1 C2 C3 C4
CV_8U 0 8 16 24
CV_8S 1 9 17 25
CV_16U 2 10 18 26
CV_16S 3 11 19 27
CV_32U 4 12 20 28
CV_32S 5 13 21 29
CV_64F 6 14 22 30
  • data: Dados de imagem armazenados em formato binário. Os dados de imagem são representados como uma matriz de 3 dimensões com a forma de dimensão (altura, largura, nChannels) e valores de matriz do tipo t especificados pelo campo de modo. A matriz é armazenada em ordem de linha principal.

Limitações

Como a fonte de dados da imagem decodifica ficheiros de imagem durante a criação do DataFrame, aumenta o tamanho dos dados e apresenta as seguintes limitações:

  • Utilização do disco durante a persistência: Os dados de imagem descodificados são significativamente maiores do que os bytes brutos. Se persistir o DataFrame numa tabela Delta, armazene bytes brutos em vez de dados descodificados para poupar espaço em disco.
  • Desempenho em embaralhamento: Embaralhar dados de imagem decodificados requer mais espaço em disco e largura de banda de rede, resultando em operações de embaralhamento mais lentas. Adie a descodificação o máximo possível na sua cadeia de processamento.
  • Biblioteca de decodificação fixa: A fonte de dados de imagem utiliza a biblioteca javax Image IO para decodificar imagens, o que impede que utilize bibliotecas alternativas de decodificação para melhor desempenho ou lógica de decodificação personalizada.

Para evitar estas limitações, use a fonte de dados de ficheiro binário para carregar dados de imagem e descodificar apenas conforme necessário.

Recursos adicionais

  • Ler ficheiros binários: Se a sua carga de trabalho requer bytes de imagem brutos em vez de uma estrutura decodificada, a fonte de dados do ficheiro binário evita a sobrecarga de decodificação e as limitações da fonte de dados da imagem.