Tkinter窗口无法显示OpenCV摄像头画面,热插拔摄像头未被检测
Hey there, let's break down why your code isn't picking up the camera after plugging it in post-launch, and fix it step by step.
What's Going Wrong
Your current code initializes cv2.VideoCapture(0) right at the start. If there's no camera connected then, this capture object becomes permanently invalid. Even when you plug in the camera later, cap.read() just keeps trying to pull frames from that dead object—so it never detects the new camera connection.
The Fix
We need to retry initializing the VideoCapture object every time we fail to read a frame, instead of sticking with the first (invalid) instance. Here's how to implement that:
Modified Full Code
from tkinter import * import cv2 from PIL import Image, ImageTk print("[INFO] Imports done") width, height = 800, 600 RootGeometry = f"{width}x{height}" print("[INFO] Geometries made") # Don't initialize cap upfront—we'll create it on demand cap = None root = Tk() print("[INFO] Window made") root.title("Main Window") root.configure(background="white") root.geometry(RootGeometry) root.bind('<Escape>', lambda e: root.quit()) lmain = Label(root) lmain.pack() print("[INFO] Configuration done.") def ShowFrame(frame): cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) img = Image.fromarray(cv2image) imgtk = ImageTk.PhotoImage(image=img) lmain.imgtk = imgtk lmain.configure(image=imgtk) lmain.after(10, CheckSource) def CheckSource(): global cap print("[INFO] CheckSource Triggered.") # If cap isn't initialized or isn't open, try to connect to camera if cap is None or not cap.isOpened(): print("[INFO] Attempting to connect to camera...") cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) ok, frame = cap.read() if ok: print("[INFO] Camera detected! Showing feed.") ShowFrame(frame) else: print("[WARNING] No camera found. Retrying in 1 second...") # Release the dead capture object and reset it for next attempt if cap is not None: cap.release() cap = None lmain.after(1000, CheckSource) # Slow down retries to reduce log spam CheckSource() root.mainloop() # Cleanup when exiting if cap is not None: cap.release()
Key Changes Explained
- Lazy Camera Initialization: We no longer create the
capobject at launch—we only create it when we need to check for a camera. - Status Check Before Reading: Every time
CheckSourceruns, it verifies ifcapis actually open and usable. If not, it creates a new capture instance. - Reset On Failure: When reading fails, we release the invalid
capand set it toNone, so the next loop will try connecting again. I also bumped the retry delay to 1 second to stop log output from flooding your console. - Remove Redundant cv2 Event Handling: Tkinter's
mainloopalready handles window events, socv2.waitKeywas unnecessary and could cause lag.
With these changes, your program will automatically detect the camera when you plug it in after launching, and start displaying the feed right away.
内容的提问来源于stack exchange,提问作者GottaAimHigherPal

