HOWTO · Python
在 Python 中使用 OpenCV 模組反轉影象
瞭解如何使用 Python 中的 OpenCV 模組反轉影象
本頁內容
在 Python 中,將 OpenCV 傳回的陣列交給 cv2.bitwise_not(),即可反轉影像。對無符號 8 位元影像通道而言,每個值 v 都會變成 255 - v。以下各節會說明通道的處理方式,以範例像素資料展示計算過程,並示範如何處理彩色或灰階影像檔及儲存結果。
準備環境並載入影像
請在執行腳本的環境中安裝 Python 和 OpenCV。套件名稱是 opencv-python,但 Python 程式使用 cv2 匯入。若尚未安裝,請執行 pip install opencv-python。NumPy 範例也需要 NumPy;標準的 OpenCV Python 套件會將 NumPy 安裝為相依套件。
將 input_path 設為可讀取的影像檔路徑。OpenCV 預設會依 BGR 通道順序載入彩色影像。指定 image = cv2.imread(input_path) 即可載入影像;處理前請確認 image is not None,因為檔案不存在或無法讀取時,imread 會傳回 None。以下範例使用 8 位元通道值,這是常見影像檔通常採用的表示方式。
影像反轉的原理
反轉會將每個通道值轉換為其補數。對於介於 0 到 255 的無符號 8 位元值,黑色會變成白色,白色會變成黑色,而像 40 這樣的值則會變成 215。這項操作會分別套用至每個通道,因此彩色像素的藍、綠、紅值都會各自反轉。OpenCV 預設的彩色陣列通道順序是 BGR,而非 RGB;反轉會保留通道順序,因此不會交換顏色。
使用 OpenCV 反轉影像
OpenCV 的 cv2.bitwise_not() 會對陣列中的每個元素套用位元 NOT。對無符號 8 位元影像資料而言,結果等同於用 255 減去各個值。這個簡短的標準函式庫範例不需要影像檔或影像處理套件,能直接呈現像素的計算方式。可用它理解數值;處理 OpenCV 影像陣列時,請先確認影像載入成功,再呼叫 cv2.bitwise_not(image)。
執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
pixel = [10, 40, 200]
inverted_pixel = [255 - value for value in pixel]
print("original:", pixel)
print("inverted:", inverted_pixel)
original: [10, 40, 200]
inverted: [245, 215, 55]
若要處理影像檔,請將 input_path 和 output_path 設為影像來源與輸出目的地,再執行此範例。請先安裝 OpenCV。下方路徑是明確的佔位值,請替換成電腦上的檔案路徑;若影像載入或寫入失敗,程式會回報問題,且不會繼續處理不存在的影像。
try:
import cv2
except ImportError:
print("Install opencv-python to run this example.")
else:
input_path = "input.png"
output_path = "inverted.png"
image = cv2.imread(input_path)
if image is None:
print(f"Could not read {input_path}")
else:
inverted = cv2.bitwise_not(image)
written = cv2.imwrite(output_path, inverted)
if not written:
print(f"Could not write {output_path}")
show_preview = False
if show_preview:
cv2.imshow("Original", image)
cv2.imshow("Inverted", inverted)
cv2.waitKey(0)
cv2.destroyAllWindows()
載入的彩色陣列及其反轉結果分別儲存在 image 和 inverted 中。OpenCV 預設以 BGR 順序傳回彩色通道,而此操作會逐一反轉通道,不會重新排列。上方的像素計算範例展示了相同的無符號 8 位元結果。
反轉灰階影像
灰階影像的每個像素只有一個亮度值,而不是三個色彩通道。使用 cv2.IMREAD_GRAYSCALE 直接載入灰階影像,確認 gray_image is not None,再套用相同的位元操作。結果仍是二維單通道陣列,可以使用 cv2.imwrite() 儲存。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
try:
import cv2
except ImportError:
print("Install opencv-python to run this example.")
else:
input_path = "input.png"
gray_output_path = "inverted-gray.png"
gray_image = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE)
if gray_image is None:
print(f"Could not read {input_path} as grayscale")
else:
inverted_gray = cv2.bitwise_not(gray_image)
written = cv2.imwrite(gray_output_path, inverted_gray)
if not written:
print(f"Could not write {gray_output_path}")
使用 NumPy 反轉影像
如果影像資料已經是 NumPy 陣列,可以改用 NumPy 提供的 numpy.invert。此函式會對每個元素執行位元 NOT;對無符號 8 位元值而言,結果與 OpenCV 的通道補數相同。此範例會讀取 8 位元彩色影像、使用 NumPy 反轉,並確認結果已儲存。此處的 255 - v 解釋僅適用於無符號 8 位元資料;不要將它套用到有號或較寬的整數陣列,因為 NumPy 在這些情況下仍執行的是位元補數運算。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
try:
import cv2
import numpy as np
except ImportError:
print("Install opencv-python and numpy to run this example.")
else:
input_path = "input.png"
numpy_output_path = "inverted-numpy.png"
image = cv2.imread(input_path)
if image is None:
print(f"Could not read {input_path}")
else:
inverted_numpy = np.invert(image)
written = cv2.imwrite(numpy_output_path, inverted_numpy)
if not written:
print(f"Could not write {numpy_output_path}")
一般的 8 位元影像檔使用 cv2.bitwise_not(image) 和 numpy.invert(image) 時,會得到相同的逐通道結果。如果工作流程其他部分已使用 OpenCV,建議使用 OpenCV 的操作;若需要 NumPy 的陣列運算,則使用 NumPy 函式。
儲存並顯示反轉後的影像
請寫入對應於已反轉影像的陣列:彩色結果使用 cv2.imwrite(output_path, inverted),灰階結果則使用 cv2.imwrite(gray_output_path, inverted_gray)。請檢查傳回的布林值;False 表示 OpenCV 無法寫入檔案,例如目的地路徑無法使用或格式不受支援。範例會透過 written 檢查結果,並在寫入失敗時回報。
OpenCV 範例包含一段可選的預覽程式碼。將該處的 show_preview 設為 True,即可開啟兩個視窗。圖形介面顯示需要圖形環境,因此在無頭工作階段中可能無法使用。使用 cv2.imwrite() 儲存不需要開啟視窗。OpenCV 與 NumPy 的影像檔範例適用於已安裝相應套件且有可讀取 input.png 的環境;本文提供的執行證據僅涵蓋上方簡短的像素計算範例。