树莓派环境下Python OpenCV如何点击窗口“X”按钮关闭窗口?
解决树莓派OpenCV摄像头流窗口点击关闭按钮退出问题
核心原理
OpenCV默认不会监听窗口右上角关闭按钮的点击事件,需要主动获取窗口的可见性属性判断用户是否点击了关闭按钮。树莓派环境下需要提前创建命名窗口,才能正确读取窗口属性。
所需修改的代码点
- 初始化摄像头后,提前创建命名窗口,和后续
imshow的窗口名称保持一致 - 每次循环渲染后,同时监听键盘按下事件和窗口可见性属性,任意一个满足条件就退出循环
- 如果你使用的是OpenCV 3.x版本(树莓派官方源默认安装的版本通常为3.x),如果
cv2.WND_PROP_VISIBLE报错,可以替换为cv2.CV_WND_PROP_VISIBLE
修改后的完整代码
import cv2 import numpy as np import matplotlib.pyplot as plt net = cv2.dnn.readNetFromDarknet("custom-yolov4-tiny-detector.cfg","custom-yolov4-tiny-detector_best.weights") classes = ['apple','orange','yogurt'] cap = cv2.VideoCapture(0) # 提前创建命名窗口 cv2.namedWindow('Cuisine Vision') while 1: _, img = cap.read() img = cv2.resize(img,(790,450)) hight,width,_ = img.shape blob = cv2.dnn.blobFromImage(img, 1/255,(416,416),(0,0,0),swapRB = True,crop= False) net.setInput(blob) output_layers_name = net.getUnconnectedOutLayersNames() layerOutputs = net.forward(output_layers_name) boxes =[] confidences = [] class_ids = [] for output in layerOutputs: for detection in output: score = detection[5:] class_id = np.argmax(score) confidence = score[class_id] if confidence > 0.7: center_x = int(detection[0] * width) center_y = int(detection[1] * hight) w = int(detection[2] * width) h = int(detection[3]* hight) x = int(center_x - w/2) y = int(center_y - h/2) boxes.append([x,y,w,h]) confidences.append((float(confidence))) class_ids.append(class_id) indexes = cv2.dnn.NMSBoxes(boxes,confidences,.5,.4) boxes =[] confidences = [] class_ids = [] for output in layerOutputs: for detection in output: score = detection[5:] class_id = np.argmax(score) confidence = score[class_id] if confidence > 0.5: center_x = int(detection[0] * width) center_y = int(detection[1] * hight) w = int(detection[2] * width) h = int(detection[3]* hight) x = int(center_x - w/2) y = int(center_y - h/2) boxes.append([x,y,w,h]) confidences.append((float(confidence))) class_ids.append(class_id) indexes = cv2.dnn.NMSBoxes(boxes,confidences,.8,.4) font = cv2.FONT_HERSHEY_PLAIN colors = np.random.uniform(0,255,size =(len(boxes),3)) if len(indexes)>0: for i in indexes.flatten(): x,y,w,h = boxes[i] label = str(classes[class_ids[i]]) color = colors[i] cv2.rectangle(img,(x,y),(x+w,y+h),color,2) cv2.putText(img,label + " " + "", (x,y+200),font,2,color,2) cv2.imshow('Cuisine Vision',img) # 同时监听q键按下和窗口关闭事件 key = cv2.waitKey(1) if key == ord('q') or cv2.getWindowProperty('Cuisine Vision', cv2.WND_PROP_VISIBLE) < 1: break cap.release() cv2.destroyAllWindows()
注意事项
- 必须保证
namedWindow的窗口名称和imshow的窗口名称完全一致,否则无法正确读取窗口属性 - 如果出现属性未定义的报错,将
cv2.WND_PROP_VISIBLE替换为cv2.CV_WND_PROP_VISIBLE即可适配低版本OpenCV
内容的提问来源于stack exchange,提问作者Div
相关产品推荐
相关产品推荐

