讀取影像檔案

重要

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 函式庫來解碼影像,這會防止你使用其他解碼函式庫來提升效能或自訂解碼邏輯。

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

其他資源

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