Ler arquivos de imagem

Importante

A Databricks recomenda que você use a fonte de dados de arquivo binário para carregar dados de imagens no DataFrame do Spark como bytes brutos. Consulte Solução de referência para aplicativos de imagem para informar-se sobre o fluxo de trabalho recomendado para manipular dados de imagem.

A fonte de dados de imagem fornece uma API padrão para carregar arquivos de imagem em DataFrames do Spark como um struct decodificado, fornecendo acesso direto aos metadados de imagem, como altura, largura, contagem de canais e dados de pixel brutos. Ele é usado principalmente em pipelines de pré-processamento de machine learning em que campos de imagem estruturados são necessários junto com dados de pixel. Azure Databricks dá suporte à fonte de dados de imagem para leituras em lote, incluindo a descoberta de partição para diretórios de imagem organizados. Para ler arquivos de imagem, especifique a fonte de dados format como image.

Pré-requisitos

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 fonte de dados da imagem. Para obter uma lista completa de opções com suporte, consulte a referência de opções de API do Spark.

Usage

Os exemplos a seguir demonstram o carregamento de arquivos de imagem usando a API do DataFrame do Spark, selecionando campos de metadados de imagem, exibindo miniaturas de imagem e salvando dados de imagem decodificados em uma tabela Delta.

Ler arquivos de imagem

Use a API de DataFrame do Apache Spark para carregar arquivos de imagem em um DataFrame. Você pode importar uma estrutura de diretório aninhada fornecendo um caminho de diretório e usar a descoberta de partição especificando 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ções de canal sem processar os dados de pixel completos, selecione campos específicos na image coluna struct.

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 miniaturas de imagem diretamente na image coluna ao trabalhar com a fonte de dados da imagem. Consulte Imagens para obter opções de exibição com suporte.

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'
)

Salvar dados de imagem em uma tabela Delta

Para melhorar o desempenho de leitura ao carregar dados de imagem de volta, salve o DataFrame em uma tabela Delta.

Observação

A fonte de dados de imagem armazena dados de pixel decodificados, o que aumenta o uso de disco em comparação com bytes brutos. Para persistência com uso eficiente de armazenamento, use a fonte de dados de arquivo 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 que contém uma única coluna de 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 a seguir descrevem o arquivo de imagem e seus dados de pixel decodificados.

  • origin: o caminho do arquivo 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 cores. Os valores típicos são 1 para imagens em escala de cinza, 3 para imagens coloridas (por exemplo, RGB) e 4 para imagens coloridas com canal alfa.
  • mode: sinalizador de inteiro que indica como interpretar o campo de dados. Especifica o tipo de dados e a ordem de canal em que os dados são armazenados. É esperado (mas não imposto) que o valor do campo seja mapeado para um dos tipos 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 de armazenamento das cores. Por exemplo, se você tiver uma imagem típica de três canais com componentes vermelhos, azuis e verdes, haverá seis ordenações possíveis. A maioria das bibliotecas usa RGB ou BGR. Três (quatro) tipos OpenCV de canal devem estar na 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 matriz tridimensional com a forma da 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 de imagem decodifica arquivos de imagem durante a criação do DataFrame, ela aumenta o tamanho dos dados e tem as seguintes limitações:

  • Uso de disco ao persistir: os dados de imagem decodificados são significativamente maiores do que os bytes brutos. Se você persistir o DataFrame em uma tabela Delta, armazene bytes brutos em vez de dados decodificados para economizar espaço em disco.
  • Desempenho do embaralhamento: o embaralhamento de 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 decodificação o máximo possível no seu pipeline.
  • Biblioteca de decodificação fixa: a fonte de dados de imagem usa a biblioteca de E/S de Imagem javax para decodificar imagens, o que impede que você use bibliotecas de decodificação alternativas para melhorar o desempenho ou a lógica de decodificação personalizada.

Para evitar essas limitações, use a fonte de dados de arquivo binário para carregar dados de imagem e decodificar somente conforme necessário.

Recursos adicionais

  • Ler arquivos binários: se sua carga de trabalho exigir bytes brutos de imagem em vez de uma estrutura decodificada, a fonte de dados de arquivos binários evita a sobrecarga de decodificação e as limitações da fonte de dados de imagem.