在影像處理的專案中,我們經常會遇到「複製圖片」與「將圖片傳入函式」的需求。這兩個動作看似簡單,實際上卻藏有許多細節,特別是在 Python 的 numpy array(OpenCV 讀進來的圖片即為 numpy array)操作上,**shallow copy(淺拷貝)與deep copy(深拷貝)**的差異,以及「傳參考」的特性,常常讓初學者誤踩地雷。
本篇教學將帶你一步步了解:
- Python 中圖片物件的複製方式
- 函式傳遞時的行為
- 如何用 Matplotlib 一次比較多張圖片
- 常見錯誤與最佳實踐
1. 背景知識:圖片在 Python 中的型態
在 Python 影像處理領域,最常見的兩大套件是 OpenCV 與 Pillow。- OpenCV 讀取圖片後,會得到一個
numpy.ndarray
物件(多維陣列)。 - Pillow 則是
PIL.Image
物件。
本教學以 OpenCV 為例,因為它的圖片物件本質上就是 numpy array,這讓我們可以直接用 numpy 的方法來複製、切片、操作像素。
2. 程式碼範例
以下是一個典型的圖片複製與函式傳遞實驗:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def modify_inplace(img):
img[0:100, 0:100] = [0, 0, 255] # 直接修改左上角為紅色
def modify_copy(img):
img_new = img.copy()
img_new[0:100, 0:100] = [0, 255, 0] # 複製後改成綠色
return img_new
img1 = cv2.imread(r'image path')
img2 = img1.copy()
modify_inplace(img1) # img1 會被改
img3 = modify_copy(img2) # img2 不變,img3 被改
def cvt(img):
return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
fig, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].imshow(cvt(img1))
axs[0].set_title('img1 (inplace modified)')
axs[1].imshow(cvt(img2))
axs[1].set_title('img2 (original)')
axs[2].imshow(cvt(img3))
axs[2].set_title('img3 (copy modified)')
for ax in axs:
ax.axis('off')
plt.tight_layout()
plt.show()
3. 程式碼說明
(1) 載入圖片
img1 = cv2.imread(r'C:\Users\10410056\Pictures\img.bmp')
img2 = img1.copy()
img1
讀入原始圖片。img2
是img1
的深拷貝(內容完全獨立)。
(2) 定義兩種修改函式
def modify_inplace(img):
img[0:100, 0:100] = [0, 0, 255] # 直接改
def modify_copy(img):
img_new = img.copy()
img_new[0:100, 0:100] = [0, 255, 0]
return img_new
modify_inplace
:直接改動傳入的圖片,會影響原始物件。modify_copy
:先複製一份再改動,原始圖片不受影響。
(3) 呼叫函式
modify_inplace(img1) # img1 被改
img3 = modify_copy(img2) # img2 不變,img3 被改
img1
會被直接修改。img2
經過modify_copy
處理後,產生新的img3
,img2
保持不變。
(4) 用 Matplotlib 顯示多張圖片
fig, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].imshow(cvt(img1))
axs[0].set_title('img1 (inplace modified)')
axs[1].imshow(cvt(img2))
axs[1].set_title('img2 (original)')
axs[2].imshow(cvt(img3))
axs[2].set_title('img3 (copy modified)')
- 一次顯示三張圖,方便比較。
- 注意:OpenCV 讀進來的圖片是 BGR 格式,Matplotlib 需要 RGB,所以用
cv2.cvtColor
轉換。
4. 實驗結果與解析
- img1:左上角被塗成紅色,因為直接在函式內修改。
- img2:完全沒變,因為沒有被直接改動。
- img3:左上角被塗成綠色,這是
img2
的複製品。
這個實驗清楚展現:

- 直接傳入 numpy array 並修改,會影響原始圖片。
- 如需保留原圖,請先用
.copy()
複製一份再處理。
5. 常見陷阱
- 直接賦值(img2 = img1)只是建立新參考,兩者共用同一份資料。
- 只有用
.copy()
或copy.deepcopy()
才能真正複製內容。 - 在函式內直接改 numpy array,外部也會被改到。
結論
- 在 Python 影像處理中,物件的複製方式與參數傳遞機制非常重要。
- 不小心直接改到原圖,會導致不可預期的 bug。
- 善用 copy/deepcopy 與良好函式設計,能讓你的程式更安全、可維護。