讀取影像檔案

重要

Databricks 建議您使用二進位檔案資料來源,將影像資料載入 Spark DataFrame 做為原始位元組。 如需處理影像資料的建議工作流程,請參閱影像應用程式的參考解決方案。

影像資料來源提供標準 API,將影像檔案以解碼結構形式載入 Spark DataFrames,讓你直接存取影像中繼資料,如高度、寬度、通道數及原始像素資料。 它主要用於機器學習預處理流程中,在除了像素資料之外還需要結構化影像欄位的情況下。 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>")

輸出結構描述

影像檔案會載入為 DataFrame,其中包含名為 image 的單一結構類型數據行,並具有下列欄位:

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 和帶有 Alpha 通道的彩色影像 4。
  • mode:指出如何解譯資料欄位的整數旗標。 它會指定資料儲存其中的資料類型和通道順序。 欄位的值預期會是(但未強制),對應到下表中顯示的其中一個 OpenCV 類型。 OpenCV 類型是針對圖元值的 1、2、3 或 4 通道和數個資料類型所定義。 通道順序會指定儲存色彩的順序。 例如,如果您有具有紅色、藍色和綠色元件的一般三個通道影像,則有六個可能的順序。 大部分的程式庫都會使用 RGB 或 BGR。 三(四)通道 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。 陣列是以列優先順序儲存。

Limitations

由於影像資料來源在建立 DataFrame 時會解碼影像檔案,因此資料大小增加,並有以下限制:

  • 持久化時的磁碟使用情況:解碼影像資料遠大於原始位元組。 如果你將 DataFrame 持久化為 Delta 表格,儲存原始位元組而非解碼資料以節省磁碟空間。
  • 洗牌效能:洗牌解碼影像資料需要更多磁碟空間與網路頻寬,導致洗牌操作較慢。 在您的流程中,盡可能延後解碼。
  • 固定解碼函式庫:影像資料來源使用 javax Image IO 函式庫來解碼影像,這會防止你使用其他解碼函式庫來提升效能或自訂解碼邏輯。

為避免這些限制,請使用二進位檔案資料來源載入影像資料,並僅在必要時解碼。

其他資源

  • 讀取二進位檔案:如果你的工作負載需要原始影像位元組而非解碼結構,二進位檔案資料來源可避免解碼的負擔與影像資料來源的限制。