最近买了一个摄像头,考虑结合AI让它发挥点实际作用.这里的功能是: 人走熄屏,人来亮屏
python有很长时间没用了,代码基本也是靠AI给的.
打包: pyinstaller –onefile –add-data “yolov5s.onnx;.” –name=“AutoMonitor” .\888.py
import sys
import cv2
import time
import ctypes
import os
import urllib.request
import argparse
def resource_path(relative_path):
""" 获取打包后资源文件的绝对路径 """
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def download_model(url, save_path):
print("📥 正在下载 YOLOv5s ONNX 模型(约 14MB)...")
try:
urllib.request.urlretrieve(url, save_path)
print("✅ 下载完成")
except Exception as e:
print(f"❌ 下载失败: {e}")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="AutoMonitor: 基于 YOLOv5 的人体检测自动开关显示器")
parser.add_argument("--interval", type=int, default=5,
help="检测间隔(秒),默认: 5")
parser.add_argument("--max-miss", type=int, default=3,
help="连续无人多少次后关屏,默认: 3")
parser.add_argument("--model", type=str, default="yolov5s.onnx",
help="ONNX 模型文件路径,默认: yolov5s.onnx")
parser.add_argument("--no-display-control", action="store_true",
help="禁用显示器开关(仅打印日志,用于调试)")
parser.add_argument("--confidence", type=float, default=0.5,
help="置信度阈值,默认: 0.5")
parser.add_argument("--nms", type=float, default=0.4,
help="NMS 阈值,默认: 0.4")
args = parser.parse_args()
# === 处理模型路径 ===
MODEL_FILE = resource_path(args.model)
if not os.path.exists(MODEL_FILE):
if args.model == "yolov5s.onnx":
# 自动下载官方模型
url = "https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s.onnx"
download_model(url, MODEL_FILE)
else:
print(f"❌ 模型文件不存在: {MODEL_FILE}")
sys.exit(1)
print("👀 AutoMonitor 人走熄屏, 人来亮屏")
# === 加载模型 ===
print("🧠 加载 YOLOv5s 模型...")
net = cv2.dnn.readNet(MODEL_FILE)
print("✅ 模型加载成功")
# === 配置 ===
CHECK_INTERVAL = args.interval
MAX_NO_PERSON_COUNT = args.max_miss
CONFIDENCE_THRESHOLD = args.confidence
NMS_THRESHOLD = args.nms
DISABLE_DISPLAY = args.no_display_control
no_person_count = 0
monitor_on = True
def wake_up_monitor():
if not DISABLE_DISPLAY:
ctypes.windll.user32.mouse_event(0x0001, 0, 0, 0, 0)
print("💡 唤醒显示器")
def turn_off_monitor():
if not DISABLE_DISPLAY:
ctypes.windll.user32.SendMessageW(0xFFFF, 0x0112, 0xF170, 2)
print("🌑 关闭显示器")
def is_person_detected(frame):
height, width = frame.shape[:2]
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (640, 640), swapRB=True, crop=False)
net.setInput(blob)
outputs = net.forward(net.getUnconnectedOutLayersNames())
boxes = []
confidences = []
for output in outputs:
if output.ndim == 3:
output = output[0]
for detection in output:
if len(detection) < 85:
continue
x, y, w, h = detection[:4]
obj_conf = detection[4]
class_scores = detection[5:85]
if len(class_scores) != 80:
continue
class_id = int(class_scores.argmax())
if class_id != 0: # 只检测 person
continue
confidence = obj_conf * class_scores[class_id]
if confidence > CONFIDENCE_THRESHOLD:
x1 = int((x - w / 2) * width)
y1 = int((y - h / 2) * height)
x2 = int((x + w / 2) * width)
y2 = int((y + h / 2) * height)
boxes.append([x1, y1, x2 - x1, y2 - y1])
confidences.append(float(confidence))
indices = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)
return len(indices) > 0
# === 主循环 ===
print(f" - 检测间隔: {CHECK_INTERVAL}s")
print(f" - 连续无人 {MAX_NO_PERSON_COUNT} 次后关屏")
print(f" - 置信度阈值: {CONFIDENCE_THRESHOLD}")
print(f" - 显示器控制: {'禁用' if DISABLE_DISPLAY else '启用'}\n")
try:
while True:
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()
if not ret:
print("⚠️ 摄像头失败,跳过...")
time.sleep(CHECK_INTERVAL)
continue
start = time.time()
has_person = is_person_detected(frame)
elapsed = time.time() - start
ts = time.strftime("%H:%M:%S")
print(f"[{ts}] 耗时: {elapsed:.2f}s | 有人: {has_person}")
if has_person:
if not monitor_on:
wake_up_monitor()
monitor_on = True
no_person_count = 0
else:
no_person_count += 1
print(f" → 连续无人: {no_person_count}/{MAX_NO_PERSON_COUNT}")
if no_person_count >= MAX_NO_PERSON_COUNT and monitor_on:
turn_off_monitor()
monitor_on = False
time.sleep(CHECK_INTERVAL)
except KeyboardInterrupt:
print("\n🛑 程序退出")
if __name__ == "__main__":
main()
打赏