重要
Databricks では、バイナリ ファイル データ ソースを使用して、イメージ データを未加工のバイトとして Spark DataFrame に読み込むことが推奨されています。 イメージ データを処理するために推奨されるワークフローについては、「イメージ アプリケーションのリファレンス ソリューション」を参照してください。
イメージ データ ソースには、デコードされた構造体として Spark DataFrames にイメージ ファイルを読み込むための標準 API が用意されており、高さ、幅、チャネル数、生のピクセル データなどの画像メタデータに直接アクセスできます。 これは主に、ピクセル データと共に構造化された画像フィールドが必要な機械学習の前処理パイプラインで使用されます。 Azure Databricksでは、整理されたイメージ ディレクトリのパーティション検出など、バッチ読み取りのイメージ データ ソースがサポートされます。 イメージ ファイルを読み取る場合は、データ ソース format を image として指定します。
前提条件
Azure Databricksでは、イメージ データ ソースを使用するために追加の構成は必要ありません。
オプション
.option()の.options()およびDataFrameReaderメソッドを使用して、イメージ データ ソースを構成します。 サポートされているオプションの完全な一覧については、 Spark API オプションのリファレンスを参照してください。
Usage
次の例では、Spark DataFrame API を使用したイメージ ファイルの読み込み、画像メタデータ フィールドの選択、画像サムネイルの表示、デコードされた画像データの Delta テーブルへの保存を示します。
イメージ ファイルの読み取り
Apache Spark DataFrame API を使用して、イメージ ファイルを DataFrame に読み込みます。 入れ子になったディレクトリ構造をインポートするには、ディレクトリ パスを指定し、パーティション ディレクトリでパスを指定してパーティション探索を使用します (たとえば、 /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'
)
イメージ メタデータの選択
完全なピクセル データを処理せずに画像ディメンションまたはチャネル情報を操作するには、 image 構造体列から特定のフィールドを選択します。
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'
)
イメージ データの表示
Databricks display 関数は、イメージ データ ソースを操作するときに、 image 列に画像のサムネイルを直接レンダリングします。 サポートされている表示オプションについては、「 イメージ」 を参照してください。
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'
)
画像データを Delta テーブルに保存する
イメージ データを読み込む際の読み取りパフォーマンスを向上させるには、DataFrame を Delta テーブルに保存します。
Note
画像データ ソースにはデコードされたピクセル データが格納され、生バイトと比較してディスク使用量が増加します。 ストレージ効率の高い永続化を実現するために、代わりに バイナリ ファイル のデータ ソースを使用します。
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>")
出力スキーマ
イメージ ファイルは、次のフィールドで image と呼ばれる 1 つの構造体型の列を含む DataFrame として読み込まれます。
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)
次のフィールドでは、画像ファイルとそのデコードされたピクセル データについて説明します。
-
origin: ソース イメージのファイル パス。 -
height: イメージの高さ (ピクセル単位)。 -
width: イメージの幅 (ピクセル単位)。 -
nChannels: カラー チャネルの数。 一般的な値は、グレースケール イメージの場合は 1、色付きイメージ (RGB など) の場合は 3、アルファ チャネルを持つ色付きイメージの場合は 4 です。 -
mode: データ フィールドの解釈方法を示す整数フラグ。 データの種類と、データが格納されているチャネルの順序を指定します。 フィールドの値は、次の表に示す OpenCV 型の 1 つにマップすることが期待されています (ただし、強制ではありません)。 OpenCV 型は、1、2、3、または 4 チャネル用に定義され、ピクセル値にはいくつかのデータ型が定義されます。 チャネルの順序は、色が格納される順序を指定します。 たとえば、赤、青、緑のコンポーネントを含む一般的な 3 つのチャネル イメージがある場合、6 つの順序が可能です。 ほとんどのライブラリでは、RGB または BGR のいずれかを使用します。 3 (4) つのチャネルの OpenCV 型は、BGR(A) の順序であることが期待されます。
OpenCV の数値に対する型のマップ (データ型 x チャネル数)
| タイプ | 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: バイナリ形式で格納されたイメージ データ。 イメージ データは、ディメンションの形状 (高さ、幅、nChannels) と、モード フィールドで指定された t 型の配列値を持つ 3 次元配列として表されます。 この配列は、行優先順で格納されます。
制限事項
イメージ データ ソースは DataFrame の作成時にイメージ ファイルをデコードするため、データ サイズが増加し、次の制限があります。
- 永続化時のディスク使用量: デコードされたイメージ データは、生バイトよりも大幅に大きくなります。 DataFrame を Delta テーブルに永続化する場合は、デコードされたデータの代わりに生バイトを格納してディスク領域を節約します。
- シャッフル パフォーマンス: デコードされたイメージ データをシャッフルするには、必要なディスク領域とネットワーク帯域幅が増え、シャッフル操作が遅くなります。 パイプラインで可能な限りデコードを遅延します。
- デコード ライブラリの修正: イメージ データ ソースでは、javax Image IO ライブラリを使用してイメージをデコードします。これにより、パフォーマンスを向上させるために代替デコード ライブラリを使用したり、カスタム デコード ロジックを使用したりできなくなります。
これらの制限を回避するには、バイナリ ファイル データ ソースを使用してイメージ データを読み込み、必要に応じてのみデコードします。
その他のリソース
- バイナリ ファイルの読み取り: ワークロードでデコードされた構造体ではなく生の画像バイトが必要な場合、バイナリ ファイル データ ソースでは、イメージ データ ソースのデコードのオーバーヘッドと制限が回避されます。