文、意如
自動開啟視訊攝像頭、

當使用者按下Y鍵就會擷取影像存檔

程式碼:
py11.py
import cv2 # 匯入 OpenCV 函式庫,用於影像處理
# 建立一個命名的視窗,視窗名稱為 "myimg"
cv2.namedWindow("myimg")
# 開啟預設攝影機(0 為第一個攝影機裝置)
cap = cv2.VideoCapture(0)
# 檢查攝影機是否成功開啟
while cap.isOpened():
# 讀取一幀影像(ret 為是否成功讀取,img 為影像資料)
ret, img = cap.read()
if ret: # 若成功讀取影像
# 在視窗中顯示影像
cv2.imshow("myimg", img)
# 等待 100 毫秒,並接收鍵盤輸入(回傳按鍵的 ASCII 值)
w = cv2.waitKey(100)
# 若按下 "Y" 或 "y" 鍵(大小寫都接受)
if w == ord("Y") or w == ord("y"):
# 儲存目前畫面為圖片,指定儲存路徑
cv2.imwrite("media/myimg.jpg", img)
print("已儲存圖片:media/myimg.jpg") # 顯示成功訊息
break # 跳出迴圈,結束程式
# 釋放攝影機資源(避免占用)
cap.release()
# 關閉所有由 OpenCV 建立的視窗
cv2.destroyAllWindows()
加上拍照按鈕

py12.py
import cv2 # 匯入 OpenCV,用於影像擷取與處理
import tkinter as tk # 匯入 tkinter,建立 GUI 視窗與按鈕
from tkinter import messagebox # 匯入訊息框模組,用於顯示提示訊息
from PIL import Image, ImageTk # 匯入 PIL 模組,用於影像格式轉換與顯示
# 圖片儲存的路徑
SAVE_PATH = "media/myimg.jpg"
# 建立主視窗(視窗物件)
root = tk.Tk()
root.title("拍照相機") # 設定視窗標題
# 建立一個 Label 元件,用來顯示攝影機畫面
label = tk.Label(root)
label.pack() # 將 Label 放入視窗中
# 開啟預設攝影機(參數 0 代表第一台攝影機)
cap = cv2.VideoCapture(0)
def update_frame():
"""
持續更新攝影機畫面,顯示在 GUI 上的 Label 元件中
"""
ret, frame = cap.read() # 讀取攝影機一張影像(ret:成功與否, frame:影像本身)
if ret:
# 將 OpenCV 的 BGR 顏色格式轉換為 RGB(因為 tkinter 不支援 BGR)
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 將 numpy 陣列轉為 PIL 的影像物件
img_pil = Image.fromarray(frame_rgb)
# 將 PIL 影像轉為 tkinter 可顯示的格式
imgtk = ImageTk.PhotoImage(image=img_pil)
# 保留影像參考,否則會顯示空白
label.imgtk = imgtk
# 將影像顯示在 Label 元件上
label.configure(image=imgtk)
# 每 30 毫秒再次執行 update_frame,達到不斷更新畫面效果
root.after(30, update_frame)
def take_photo():
"""
按下按鈕時拍照並儲存圖片
"""
ret, frame = cap.read() # 再次擷取一張畫面
if ret:
# 儲存圖片到指定路徑
cv2.imwrite(SAVE_PATH, frame)
# 顯示訊息視窗:圖片已儲存
messagebox.showinfo("提示", f"圖片已儲存:{SAVE_PATH}")
else:
# 若拍照失敗,顯示錯誤訊息
messagebox.showerror("錯誤", "無法擷取圖片")
# 建立一個按鈕,點擊後執行 take_photo 函式(拍照)
btn = tk.Button(root, text="📸 拍照", font=("Arial", 14), command=take_photo)
btn.pack(pady=10) # 加入視窗並設定間距
# 啟動第一次影像更新(之後會自動每30毫秒呼叫一次)
update_frame()
def on_close():
"""
當視窗關閉時執行,釋放攝影機並關閉視窗
"""
cap.release() # 釋放攝影機資源
root.destroy() # 關閉 tkinter 視窗
# 當使用者關閉視窗時,呼叫 on_close 函式
root.protocol("WM_DELETE_WINDOW", on_close)
# 開始進入 tkinter 的主事件迴圈(等待互動)
root.mainloop()
另存照片
py13.py
✅ 按下拍照鍵時再跳出輸入視窗 (輸入另存新檔的檔名)
✅ 自動在圖片右下角疊加當下時間戳記
✅ 儲存檔案名稱附加時間戳記


# 匯入所需模組
import cv2 # OpenCV:用來存取攝影機與處理影像
import tkinter as tk # 建立 GUI 視窗
from tkinter import messagebox, simpledialog # tkinter 的訊息視窗與輸入對話框
from PIL import Image, ImageTk # 用來將 OpenCV 影像轉為 tkinter 可用格式
import datetime # 處理日期與時間
import os # 處理檔案與資料夾操作
# 建立主視窗
root = tk.Tk()
root.title("拍照相機") # 設定視窗標題
# 建立影像顯示區域,之後會用來顯示即時影像
label = tk.Label(root)
label.pack()
# 啟動攝影機,參數 0 代表預設攝影機(通常是筆電內建的)
cap = cv2.VideoCapture(0)
def update_frame():
"""從攝影機取得影像並更新到畫面上(每 30 毫秒執行一次)"""
ret, frame = cap.read() # 從攝影機讀取一張影像
if ret:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # OpenCV 預設是 BGR,要轉成 RGB 才能給 tkinter 顯示
img_pil = Image.fromarray(frame_rgb) # 將 NumPy 陣列轉成 PIL 影像物件
imgtk = ImageTk.PhotoImage(image=img_pil) # 將 PIL 影像轉成 tkinter 影像格式
label.imgtk = imgtk # 儲存影像避免被垃圾回收
label.configure(image=imgtk) # 將影像顯示在 Label 上
root.after(30, update_frame) # 每 30 毫秒呼叫一次自己(達成即時畫面)
def take_photo():
"""按下拍照按鈕時呼叫此函式,會拍照、加上時間戳記、讓使用者輸入檔名並儲存"""
ret, frame = cap.read() # 讀取一張影像
if not ret:
messagebox.showerror("錯誤", "拍照失敗") # 如果讀取失敗,跳出錯誤訊息
return
now = datetime.datetime.now() # 取得目前的日期與時間
timestamp_str = now.strftime("%Y-%m-%d %H:%M:%S") # 產生格式化的時間字串(顯示用)
filename_time = now.strftime("%Y%m%d_%H%M%S") # 產生檔名用的時間字串(不含特殊符號)
# 加入時間戳記到影像的右下角
font = cv2.FONT_HERSHEY_SIMPLEX # 使用 OpenCV 內建字型
font_scale = 0.6 # 字型大小
thickness = 2 # 線條粗細
color = (0, 255, 255) # 文字顏色為黃色(BGR)
# 計算文字寬高
(text_width, text_height), baseline = cv2.getTextSize(timestamp_str, font, font_scale, thickness)
x = frame.shape[1] - text_width - 10 # 計算文字的 X 座標(右邊預留 10 px)
y = frame.shape[0] - 10 # Y 座標設在底部往上 10 px
# 在影像上加上時間戳記
cv2.putText(frame, timestamp_str, (x, y), font, font_scale, color, thickness, cv2.LINE_AA)
# 彈出視窗讓使用者輸入自訂檔名
user_filename = simpledialog.askstring("輸入檔名", "請輸入檔名(不含副檔名):")
if not user_filename:
messagebox.showwarning("警告", "未輸入檔名,取消儲存") # 使用者未輸入則取消拍照
return
save_folder = "media" # 要儲存圖片的資料夾名稱
os.makedirs(save_folder, exist_ok=True) # 若資料夾不存在就自動建立
# 組合完整檔案名稱,例如:myphoto_20250519_153045.jpg
full_filename = f"{user_filename}_{filename_time}.jpg"
save_path = os.path.join(save_folder, full_filename) # 組合完整路徑
# 儲存圖片到指定路徑
cv2.imwrite(save_path, frame)
# 顯示儲存成功的提示訊息
messagebox.showinfo("成功", f"圖片已儲存:\n{save_path}")
# 建立拍照按鈕,按下時會呼叫 take_photo 函式
btn = tk.Button(root, text="拍照", font=("Arial", 14), command=take_photo)
btn.pack(pady=10) # 加入一些垂直間距
# 啟動即時畫面更新(呼叫上面的 update_frame 函式)
update_frame()
def on_close():
"""當使用者關閉視窗時,釋放攝影機資源並結束程式"""
cap.release() # 釋放攝影機資源
root.destroy() # 關閉 tkinter 主視窗
# 設定關閉視窗時要執行的清理動作
root.protocol("WM_DELETE_WINDOW", on_close)
# 啟動 tkinter 主迴圈(GUI 開始執行)
root.mainloop()
Yiru@Studio - 關於我 - 意如