HOWTO · NumPy
在 Python 中將 NumPy 陣列儲存為影像
本教程演示了如何將 numpy 陣列另存為 python 中的影像
本頁內容
NumPy 陣列可以透過 Pillow、imageio、Matplotlib 或 OpenCV 寫入影像檔。適合的方法取決於專案已使用的函式庫,以及陣列如何儲存像素資料。二維陣列通常表示灰階像素;三維陣列通常以「高度 × 寬度 × 通道」的方式表示色彩通道。RGB 資料的最後一個維度有三個通道,RGBA 則多了一個 alpha 通道。
對常見的 8 位元影像而言,值介於 0 到 255 的 numpy.uint8 是實用的起點。浮點數陣列可能會因函式庫不同而有不同的解讀或縮放方式,因此存檔前請確認寫入函式預期的數值範圍。以下可執行範例使用小型陣列和暫存 PNG 路徑。如果尚未安裝 NumPy 或範例使用的函式庫,請先安裝;例如 Pillow 範例可執行 python -m pip install numpy pillow。
準備要輸出為影像的 NumPy 陣列
請選擇符合影像資料的陣列形狀:灰階影像使用 (height, width),RGB 使用 (height, width, 3);若寫入函式預期通道位於最後一個維度,RGBA 則使用 (height, width, 4)。形狀描述資料排列方式,但不會指出通道代表的意義。將彩色像素傳給函式庫前,請確認來源資料使用 RGB 還是 BGR 順序。
資料型別和數值範圍都必須受影像格式與所選寫入函式支援。一般 8 位元輸出廣泛接受值介於 0 到 255 的 numpy.uint8。如果來源值是浮點數或採用其他範圍,請有意識地轉換或縮放;不同寫入函式可能會以不同方式截斷、縮放或拒絕這些值。
使用 Image.fromarray() 函式將 NumPy 陣列另存為影像
Pillow 的 Image.fromarray() 會從陣列建立影像,而 Image.save() 會將影像寫入檔案。二維 uint8 陣列代表灰階資料。若要輸出彩色影像,請提供適當的三通道 RGB 陣列。以下範例會將小型灰階陣列存成 gray.png:
from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np
from PIL import Image
pixels = np.array([[0, 64, 128], [192, 224, 255]], dtype=np.uint8)
with TemporaryDirectory() as directory:
output_path = Path(directory) / "gray.png"
image = Image.fromarray(pixels)
image.save(output_path)
print("Saved gray.png")
Saved gray.png
暫存目錄讓這個範例可以獨立執行。彩色範例可使用形狀為 (height, width, 3) 且通道順序為 RGB 的陣列;只要三通道陣列的格式合適,Pillow 就能推斷為 RGB。
使用 imageio.imwrite() 函式將 NumPy 陣列另存為影像
imageio.imwrite() 會將陣列寫入第一個引數指定的路徑。檔名副檔名通常會決定使用哪個寫入器,因此請選擇已安裝的 imageio 外掛支援的副檔名。這個獨立範例會建立自己的灰階陣列,並在整個寫入過程中將輸出路徑留在暫存目錄內。提供的執行結果未涵蓋此 imageio 範例;若要在自己的環境執行,請安裝 NumPy 和 imageio,例如執行 python -m pip install numpy imageio。
from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np
pixels = np.array([[0, 64, 128], [192, 224, 255]], dtype=np.uint8)
try:
import imageio.v2 as imageio
except ImportError:
print("imageio is unavailable; install imageio to write the image.")
else:
with TemporaryDirectory() as directory:
output_path = Path(directory) / "gray.png"
imageio.imwrite(output_path, pixels)
print("Saved gray.png")
此任務可使用 imageio 這類影像寫入函式庫。本文不將歷史上的 scipy.io.imsave() 範例當作目前的操作指南,也不依賴任何關於 SciPy API 歷史或棄用狀態的說法。
使用 matplotlib.pyplot.imsave() 函式將 NumPy 陣列另存為影像
Matplotlib 可透過 matplotlib.pyplot.imsave() 直接寫入陣列。對二維陣列傳入 cmap="gray",即可指定輸出為灰階。若未指定色彩映射表,Matplotlib 可能會將純量值映射成顏色。三通道輸入會視為 RGB。以下範例使用明確指定的灰階色彩映射表來儲存灰階值:
from pathlib import Path
from tempfile import TemporaryDirectory
import matplotlib.pyplot as plt
import numpy as np
pixels = np.array([[0, 64, 128], [192, 224, 255]], dtype=np.uint8)
with TemporaryDirectory() as directory:
output_path = Path(directory) / "gray.png"
plt.imsave(output_path, pixels, cmap="gray")
print("Saved gray.png")
Saved gray.png
若純量資料的數值範圍具有實際意義,請審慎選擇正規化方式和色彩映射表。如此可將視覺化用的色彩映射與原始像素通道區分開來。
使用 cv2.imwrite() 函式將 NumPy 陣列另存為影像
OpenCV 的 cv2.imwrite() 會根據檔名副檔名選擇編碼器,並以布林值表示寫入是否成功。請檢查這個回傳值,尤其是在輸出目錄或編碼器可能無法使用時。依照慣例,OpenCV 的彩色陣列使用 BGR 通道順序。若希望存檔後的顏色與來源相符,請先轉換 RGB 資料。二維灰階陣列不需要轉換通道順序。範例會建立有效的輸出路徑,並在回傳值為 false 或未安裝 OpenCV 時顯示可採取行動的訊息。提供的執行結果未涵蓋此 OpenCV 範例;若要在自己的環境執行,請安裝 NumPy 和 opencv-python,例如執行 python -m pip install numpy opencv-python。
from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np
pixels = np.array([[0, 64, 128], [192, 224, 255]], dtype=np.uint8)
try:
import cv2
except ImportError:
print("OpenCV is unavailable; install opencv-python to write the image.")
else:
with TemporaryDirectory() as directory:
output_path = Path(directory) / "gray.png"
written = cv2.imwrite(str(output_path), pixels)
if written:
print("Saved gray.png")
else:
print(f"Could not write {output_path}; check the directory and image encoder.")
RGB 彩色輸入可先使用 cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR) 轉換,再呼叫 cv2.imwrite()。請確保轉換方式與陣列排列都符合來源資料。
選擇輸出格式並確認影像
檔名副檔名通常會決定或暗示輸出格式,但各函式庫及已安裝外掛所支援的格式與選項不盡相同。PNG 不會造成有損壓縮;JPEG 則會有損壓縮,且不保留透明度。請確認所選寫入器支援指定的副檔名。
如果 API 提供回傳值,例如 OpenCV,請檢查該值。若需要確認輸出結果,可重新開啟已儲存的檔案,檢查其尺寸、模式或通道數,以及像素值。顏色不如預期可能是 RGB/BGR 通道順序造成的;灰階影像出現顏色,則可能是 Matplotlib 套用了色彩映射表。若輸出不正確,請比對陣列的形狀、資料型別、數值範圍和通道順序是否符合寫入器的預期。