這裡介紹如何使用 Python 與 OpenCV 讀取圖檔,以及將處理好的圖形寫入檔案。

OpenCV 讀取圖片

首先引入 NumPy 與 OpenCV 的 Python 模組:

import numpy as np
import cv2

OpenCV 本身就有提供讀取圖片檔的函數可用,讀取一般的圖片檔,只要呼叫 cv2.imread 即可將圖片讀取進來:

# 讀取圖檔
img = cv2.imread('image.jpg')

cv2.imread 讀進來的資料,會儲存成一個 NumPy 的陣列,我們可以用 type 檢查一下:

# 查看資料型態
type(img)
<class 'numpy.ndarray'>

此 NumPy 陣列的前兩個維度分別是圖片的高度與寬度,第三個維度則是圖片的 channel(RGB 彩色圖片的 channel 是 3,灰階圖片則為 1)。

以這個子來說,我們的原始圖片是一張 1920×1080 的彩色圖片,我們可以檢查一下這個 NumPy 陣列的大小:

img.shape
(1080, 1920, 3)

圖檔格式

OpenCV 的 cv2.imread 在讀取圖片時,可以在第二個參數指定圖片的格式,可用的選項有三種:

cv2.IMREAD_COLOR
此為預設值,這種格式會讀取 RGB 三個 channels 的彩色圖片,而忽略透明度的 channel。
cv2.IMREAD_GRAYSCALE
以灰階的格式來讀取圖片。
cv2.IMREAD_UNCHANGED
讀取圖片中所有的 channels,包含透明度的 channel。

這是讀取灰階圖片的範例:

# 以灰階的方式讀取圖檔
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

顯示圖片

將圖片讀取進來之後,可以使用 OpenCV 所提供的 cv2.imshow 來顯示圖片:

# 顯示圖片
cv2.imshow('My Image', img)

# 按下任意鍵則關閉所有視窗
cv2.waitKey(0)
cv2.destroyAllWindows()

這裡 cv2.waitKey 函數是用來等待與讀取使用者按下的按鍵,而其參數是等待時間(單位為毫秒),若設定為 0 就表示持續等待至使用者按下按鍵為止,這樣當我們按下任意按鍵之後,就會呼叫 cv2.destroyAllWindows 關閉所有 OpenCV 的視窗。

如果在程式中有許多的 OpenCV 視窗,而我們只要關閉特定的視窗時,可以改用 cv2.destroyWindow 加上視窗名稱,關閉指定的視窗:

# 關閉 'My Image' 視窗
cv2.destroyWindow('My Image')

在預設的狀況下,以 cv2.imshow 所開啟的視窗會依據圖片來自動調整大小,但若是圖片太大、佔滿整個螢幕時,我們會希望可以自由縮放視窗的大小,這時候就可以使用 cv2.namedWindow 將視窗設定為 cv2.WINDOW_NORMAL

# 讓視窗可以自由縮放大小
cv2.namedWindow('My Image', cv2.WINDOW_NORMAL)

cv2.imshow('My Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

使用 OpenCV 開啟的圖形視窗會類似這樣:

OpenCV 顯示圖片視窗

灰階的圖片也可以顯示,用法都相同:

OpenCV 顯示圖片視窗

寫入圖片檔案

若要將 NumPy 陣列中儲存的圖片寫入檔案,可以使用 OpenCV 的 cv2.imwrite

# 寫入圖檔
cv2.imwrite('output.jpg', img)

cv2.imwrite 可透過圖片的副檔名來指定輸出的圖檔格式:

# 寫入不同圖檔格式
cv2.imwrite('output.png', img)
cv2.imwrite('output.tiff', img)

輸出圖片檔案時,也可以調整圖片的品質或壓縮率:

# 設定 JPEG 圖片品質為 90(可用值為 0 ~ 100)
cv2.imwrite('output.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])

# 設定 PNG 壓縮層級為 5(可用值為 0 ~ 9)
cv2.imwrite('output.png', img, [cv2.IMWRITE_PNG_COMPRESSION, 5])

Matplotlib

Matplotlib 是 Python 之中很常被使用的繪圖工具,以下介紹如何以 Matplotlib 顯示 OpenCV 讀入或產生的圖片。

彩色圖片

Matplotlib 顯示圖片的方式也很簡單,只要呼叫 imshow 就可以了,但是由於 OpenCV 讀取進來的圖片會以 BGR 的方式儲存三個顏色的 channel,如果直接把 OpenCV 讀入的圖片放進 Matplotlib 來顯示,就會出現類似這樣的顏色錯誤問題:

Matplotlib 圖片顏色錯誤

遇到這樣的問題,只要將 OpenCV 讀入的 BGR 格式轉為 Matplotlib 用的 RGB 格式,再交給 Matplotlib 顯示就會得到正確的結果了。以下是使用 Matplotlib 顯示彩色圖片的範例:

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 使用 OpenCV 讀取圖檔
img_bgr = cv2.imread('image.jpg')

# 將 BGR 圖片轉為 RGB 圖片
img_rgb = img_bgr[:,:,::-1]

# 使用 Matplotlib 顯示圖片
plt.imshow(img_rgb)
plt.show()

顯示出來的視窗繪像這樣:

Matplotlib 顯示彩色圖片

灰階圖片

而如果是以 OpenCV 讀取灰階的圖片時,由於 channel 只有一個,所以就不會有上述的色彩問題,直接把 OpenCV 讀入的 NumPy 陣列放進 Matplotlib 的 imshow 中即可顯示,但是 Matplotlib 在顯示一個 channel 的圖片時,會用預設的 colormap 上色,所以畫出來繪像這樣:

Matplotlib 顯示灰階圖片

如果想要以黑白的方式呈現灰階圖片,可以自己設定 colormap:

# 使用 OpenCV 讀取灰階圖檔
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 使用 Matplotlib 顯示圖片
plt.imshow(img_gray, cmap = 'gray')
plt.show()

結果會像這樣:

Matplotlib 顯示灰階圖片

參考資料:OpenCVMatplotlib