画像ファイルの読み取り
Databricks では、 バイナリ ファイル データソースを使用して、イメージ データを生のバイトとして Spark データフレーム にロードすることをお勧めします。 画像データの処理に推奨されるワークフローについては、 画像アプリケーションのリファレンス ソリューション を参照してください。
イメージデータソースは、イメージファイルをデコードされた構造体としてSpark DataFramesにロードするための標準APIを提供し、高さ、幅、チャンネル数、生ピクセルデータなどのイメージメタデータに直接アクセスできます。ピクセルデータと並行して構造化された画像フィールドが必要とされる機械学習の前処理パイプラインで、主に使用されます。Databricksは、整理された画像ディレクトリのパーティション検出を含め、バッチ読み込み向けの画像データソースをサポートしています。画像ファイルを読み取るには、データソース format を image として指定します。
前提条件
Databricks はイメージデータソースを使用するのに追加の設定は必要ありません。
オプション
画像データソースを構成するには、DataFrameReaderの.option()と.options()のメソッドを使用します。サポートされているオプションの完全なリストについては、Spark API オプション参照をご覧ください。
使い方
次の例では、Spark DataFrame API を使用した画像ファイルの読み込み、画像メタデータフィールドの選択、画像サムネイルの表示、およびデコードされた画像データの Delta テーブルへの保存について説明します。
画像ファイルの読み取り
Apache Spark DataFrame API を使用して、画像ファイルを DataFrame に読み込みます。ディレクトリパスを指定することで、入れ子になったディレクトリ構造をインポートできます。また、パーティションディレクトリのパス(例:/path/to/dir/date=2018-01-02/category=automobile)を指定してパーティション検出機能を使用できます。
- Python
- Scala
- SQL
# 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)
// 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()
-- Read all images from a directory
SELECT * FROM read_files(
'/Volumes/<catalog>/<schema>/<volume>/images/',
format => 'image'
)
画像メタデータを選択します
完全なピクセルデータを処理することなく、画像の寸法やチャンネル情報を扱うには、image 構造体列から特定のフィールドを選択します。
- Python
- Scala
- SQL
df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
metadata = df.select("image.origin", "image.height", "image.width", "image.nChannels")
display(metadata)
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()
SELECT image.origin, image.height, image.width, image.nChannels FROM read_files(
'/Volumes/<catalog>/<schema>/<volume>/images/',
format => 'image'
)
画像データの表示
画像データソースを使用する場合、Databricks display 関数はimage列に画像を直接表示します。サポートされている表示オプションについては、「画像」を参照してください。
- Python
- Scala
- SQL
df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
display(df)
val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.show()
SELECT * FROM read_files(
'/Volumes/<catalog>/<schema>/<volume>/images/',
format => 'image'
)
画像データをDeltaテーブルに保存します
画像データを再度読み込む際の読み取りパフォーマンスを向上させるには、DataFrameをDeltaテーブルに保存してください。
イメージデータソースは、デコードされたピクセルデータを保存し、生のバイトと比較してディスク使用量が増加します。ストレージ効率の高い永続化には、代わりにバイナリファイルデータソースを使用してください。
- Python
- Scala
df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.write.format("delta").saveAsTable("<catalog>.<schema>.<table>")
val df = spark.read.format("image").load("/Volumes/<catalog>/<schema>/<volume>/images/")
df.write.format("delta").saveAsTable("<catalog>.<schema>.<table>")
出力スキーマ
イメージ ファイルは、次のフィールドを持つ image という 1 つの構造体型列を含む データフレーム として読み込まれます。
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 タイプのいずれかにマップされることが想定されます (ただし、強制されません)。 OpenCV タイプは、1、2、3、または 4 チャンネルと、ピクセル値に対していくつかのデータ型に対して定義されます。 チャンネルの順序は、色が保存される順序を指定します。 たとえば、赤、青、緑のコンポーネントを含む一般的な 3 つのチャンネル画像がある場合、6 つの順序が可能です。 ほとんどのライブラリは RGB または BGR を使用します。 OpenCVの3種類はBGR(A)順になる予定です。
OpenCVにおけるタイプから数値へのマップ (データ型 × チャンネル数)
Type | 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: バイナリ形式で保存された画像データ。 イメージ データは、次元形状 (height、width、nChannels) と mode フィールドで指定されたタイプ t の配列値を持つ 3 次元配列として表されます。 配列は、行優先の順序で格納されます。
制限事項:
イメージ データソースは、DataFrame の作成時に画像ファイルをデコードするため、データサイズが増加し、以下の制限があります。
- 永続化時のディスク使用量 :デコードされた画像データは、生のバイトよりもかなり大きくなります。DataFrame を Delta テーブルに永続化する場合、デコードされたデータの代わりに生のバイトを保存し、ディスク領域を節約してください。
- シャッフルパフォーマンス :デコードされた画像データのシャッフルには、より多くのディスク領域とネットワーク帯域幅が必要となるため、シャッフル操作が遅くなります。パイプラインでは、デコード処理を可能な限り遅らせてください。
- 固定デコードライブラリ :image データソースは、画像をデコードするために javax Image IO ライブラリを使用しています。これにより、パフォーマンスの向上やカスタムデコードロジックのための代替デコードライブラリを使用することができません。
これらの制限を回避するには、バイナリファイルデータソースを使用してイメージデータをロードし、必要な場合にのみデコードしてください。
その他のリソース
- バイナリファイルの読み取り: ワークロードでデコードされた構造体ではなく生の画像バイトが必要な場合、バイナリファイルデータソースは画像データソースのデコードのオーバーヘッドと制限を回避します。