🔥 新作首發 🎮 天堂私服 YOLOv8 物件偵測實戰 — 從資料蒐集、模型訓練到即時偵測 立即閱讀 →
熱門系列
Like Share Discussion Bookmark Smile

J.J. Huang   2026-04-13   Python OpenCV 08.專案實作篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV 專案:即時濾鏡相機

📚 前言

在上一篇 OpenCV QR Code 與 BarCode 辨識 中,我們完成了條碼辨識的實作,正式踏入 專案實作篇

這一篇是第一個整合專案:即時濾鏡相機
目標是把前面學過的色彩轉換、模糊、形態學、繪圖等功能整合在一起,做出一個可用鍵盤切換濾鏡的即時相機程式。沒有攝影機也沒關係,程式同時支援以影片檔作為輸入來源,效果完全相同。

🎯 專案目標

  • 攝影機或影片檔即時預覽
  • 按鍵切換 10 種以上的濾鏡效果
  • 畫面顯示目前濾鏡名稱
  • s 截圖儲存
  • q 離開

🗃️ 專案結構

1
2
3
4
5
6
filter_camera/
├── assets/ ← 測試影片(無攝影機時使用)
│ └── sample.mp4
├── output/ ← 截圖輸出
├── main.py ← 主程式
└── filters.py ← 濾鏡函式集合

🎨 範例影片

  • 來源:Pexels - Code,屬於無版權影片,可自由下載與使用。
  • 下載後將檔名改為 sample.mp4,放到專案的 assets/ 目錄下。

💻 filters.py — 濾鏡函式集合

  • 定義灰階、模糊、邊緣、復古、負片、銳化、浮雕、卡通、馬賽克、暖冷色調等 12 種濾鏡函式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# filters.py
import cv2
import numpy as np

def original(frame):
return frame

def grayscale(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
return cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

def blur(frame):
return cv2.GaussianBlur(frame, (21, 21), 0)

def edge(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
return cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)

def sepia(frame):
kernel = np.array([[0.272, 0.534, 0.131],
[0.349, 0.686, 0.168],
[0.393, 0.769, 0.189]])
result = cv2.transform(frame.astype(np.float32), kernel)
return np.clip(result, 0, 255).astype(np.uint8)

def invert(frame):
return cv2.bitwise_not(frame)

def sharpen(frame):
kernel = np.array([[ 0, -1, 0],
[-1, 5, -1],
[ 0, -1, 0]])
return cv2.filter2D(frame, -1, kernel)

def emboss(frame):
kernel = np.array([[-2, -1, 0],
[-1, 1, 1],
[ 0, 1, 2]])
result = cv2.filter2D(frame, -1, kernel) + 128
return np.clip(result, 0, 255).astype(np.uint8)

def cartoon(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray_blur = cv2.medianBlur(gray, 5)
edges = cv2.adaptiveThreshold(gray_blur, 255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, 9, 9)
color = cv2.bilateralFilter(frame, 9, 300, 300)
return cv2.bitwise_and(color, color, mask=edges)

def mosaic(frame, block=20):
h, w = frame.shape[:2]
small = cv2.resize(frame, (w // block, h // block),
interpolation=cv2.INTER_LINEAR)
return cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)

def warm(frame):
# 提高紅/黃色調
lut = np.arange(256, dtype=np.uint8)
lut_r = np.clip(lut * 1.2, 0, 255).astype(np.uint8)
lut_b = np.clip(lut * 0.8, 0, 255).astype(np.uint8)
b, g, r = cv2.split(frame)
return cv2.merge([cv2.LUT(b, lut_b), g, cv2.LUT(r, lut_r)])

def cool(frame):
# 提高藍色調
lut = np.arange(256, dtype=np.uint8)
lut_r = np.clip(lut * 0.8, 0, 255).astype(np.uint8)
lut_b = np.clip(lut * 1.2, 0, 255).astype(np.uint8)
b, g, r = cv2.split(frame)
return cv2.merge([cv2.LUT(b, lut_b), g, cv2.LUT(r, lut_r)])

# 濾鏡清單:(名稱, 函式)
FILTERS = [
("原始畫面", original),
("灰階", grayscale),
("模糊", blur),
("邊緣", edge),
("復古", sepia),
("負片", invert),
("銳化", sharpen),
("浮雕", emboss),
("卡通", cartoon),
("馬賽克", mosaic),
("暖色調", warm),
("冷色調", cool),
]

💻 main.py — 主程式

cv2.VideoCapture() 同時支援攝影機 index(整數)與影片檔路徑(字串),因此只需在開頭以 sys.argv 判斷來源,其餘邏輯完全不變。影片播完後以 CAP_PROP_POS_FRAMES seek 回第 0 幀即可無縫循環,濾鏡效果的呈現與真實攝影機沒有差異。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# main.py
import cv2
import os
import sys
from datetime import datetime
from filters import FILTERS

# python main.py → 攝影機 (index 0)
# python main.py assets/sample.mp4 → 影片檔
source = sys.argv[1] if len(sys.argv) > 1 else 0
is_video = isinstance(source, str)
cap = cv2.VideoCapture(source)
if not cap.isOpened():
print("無法開啟來源,請確認攝影機或影片路徑是否正確")
exit()
filter_index = 0
save_dir = "output"
os.makedirs(save_dir, exist_ok=True)

print("操作說明:")
print(" ← / → 方向鍵 切換濾鏡")
print(" s 截圖儲存")
print(" q 離開")

while True:
ret, frame = cap.read()
if not ret:
if is_video: # 影片播完後從頭循環
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
continue
break

name, func = FILTERS[filter_index]

try:
output = func(frame)
except Exception as e:
print(f"濾鏡 [{name}] 發生錯誤:{e}")
output = frame

cv2.imshow("Filter Camera", output)

key = cv2.waitKey(1) & 0xFF

if key == ord("q"):
break
elif key == ord("s"):
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = os.path.join(save_dir, f"{ts}.jpg")
cv2.imwrite(filename, output)
print(f"截圖已儲存:{filename}")
elif key == 81 or key == ord("a"): # ← 或 a
filter_index = (filter_index - 1) % len(FILTERS)
elif key == 83 or key == ord("d"): # → 或 d
filter_index = (filter_index + 1) % len(FILTERS)

cap.release()
cv2.destroyAllWindows()


圖:開啟影片檔,以方向鍵或是(a / d)切換濾鏡並在畫面顯示名稱,按 s 截圖儲存,按 q 離開

💻 執行方式

1
2
3
4
5
6
7
cd filter_camera

# 使用攝影機
python main.py

# 使用影片檔(不需攝影機)
python main.py assets/sample.mp4

⚠️ 注意事項

  • 影片檔模式自動循環:影片播完會自動從頭播放,適合無攝影機環境展示所有濾鏡效果;若要單次播放,移除 if is_video 的 seek 邏輯即可。
  • 方向鍵的 keycode 因平台而異:Windows 上 8183;若方向鍵無效,可改用 a / d 切換。
  • 卡通濾鏡速度較慢bilateralFilter 計算量大,幀率可能下降,可縮小 d(直徑)參數或降低解析度改善。
  • 截圖目錄:預設儲存在執行目錄下的 output/,初次執行會自動建立。

🎯 結語

即時濾鏡相機整合了色彩轉換、濾波、形態學、LUT 色調調整等多種技術,是一個能快速驗證學習成果的入門專案。

下一篇將進入 OpenCV 專案:即時人臉辨識系統,把人臉偵測進一步升級為能辨識具體身份的系統。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
OpenCV 官方文件 — Image Filtering
OpenCV 官方文件 — Color Conversions