safer
This commit is contained in:
@@ -15,8 +15,8 @@ from webrtc_server import WebRTCServer
|
||||
from HeartRateMonitor import HeartRateMonitor
|
||||
from hook_mocker import HookMocker
|
||||
|
||||
API_URL = "http://10.128.48.48:5000/api/states"
|
||||
CAMERA_ID = 5
|
||||
API_URL = "http://10.128.48.204:5000/api/states"
|
||||
CAMERA_ID = 3
|
||||
|
||||
BASIC_FACE_DB = {
|
||||
"Zhihang": {"name": "Zhihang Deng", "age": 20, "image-path": "zhihang.png"},
|
||||
@@ -42,6 +42,21 @@ ana_data_queue = queue.Queue(maxsize=10)
|
||||
stop_event = threading.Event()
|
||||
|
||||
|
||||
def put_latest(q, item):
|
||||
try:
|
||||
if q.full():
|
||||
q.get_nowait()
|
||||
q.put_nowait(item)
|
||||
except queue.Full:
|
||||
try:
|
||||
q.get_nowait()
|
||||
q.put_nowait(item)
|
||||
except (queue.Empty, queue.Full):
|
||||
pass
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
|
||||
def capture_thread():
|
||||
"""
|
||||
采集线程:优化了分发逻辑,对视频流进行降频处理
|
||||
@@ -97,148 +112,116 @@ def analysis_thread():
|
||||
2. 队列满时丢弃旧数据,保证数据实时性。
|
||||
"""
|
||||
monitor = MonitorSystem(BASIC_FACE_DB)
|
||||
print("[Analysis] 分析系统启动...")
|
||||
freq = 0
|
||||
gap = 60
|
||||
status = 0 # 0:open 1:close
|
||||
last_time = time.time()
|
||||
last_freq = 0
|
||||
heart_monitor = HeartRateMonitor()
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
frame = frame_queue.get(timeout=1)
|
||||
except queue.Empty:
|
||||
continue
|
||||
|
||||
# 核心分析
|
||||
result = monitor.process_frame(frame)
|
||||
result["eye_close_freq"] = 0
|
||||
result["heart_rate"] = 0
|
||||
|
||||
if video_queue.full():
|
||||
video_queue.get_nowait()
|
||||
video_queue.put(result["frame"])
|
||||
if ana_video_queue.full():
|
||||
ana_video_queue.get_nowait()
|
||||
ana_video_queue.put(result["frame"])
|
||||
# print(f"[Analysis] {time.strftime('%Y-%m-%d %H:%M:%S')} - Frame processed")
|
||||
|
||||
payload = {
|
||||
"seat_id": CAMERA_ID,
|
||||
"timestamp": time.time(),
|
||||
"heart_rate": 0,
|
||||
"emo_v": 0,
|
||||
"emo_a": 0,
|
||||
"pose_0": 0, #pitch
|
||||
"pose_1": 0, #yaw
|
||||
"pose_2": 0, #roll
|
||||
"ear": 0,
|
||||
"mar": 0,
|
||||
"label": "",
|
||||
"eye_close_freq": 0,
|
||||
"iris_ratio_x": 0,
|
||||
"iris_ratio_y": 0,
|
||||
}
|
||||
|
||||
front_data = {
|
||||
"seat_id": CAMERA_ID,
|
||||
"timestamp": time.time(),
|
||||
"label": "",
|
||||
"eye_close_freq": 0.0,
|
||||
"iris_ratio_x": 0,
|
||||
"iris_ratio_y": 0,
|
||||
"pose_0": 0, #pitch
|
||||
"pose_1": 0, #yaw
|
||||
"pose_2": 0, #roll
|
||||
"heart_rate": 0,
|
||||
}
|
||||
|
||||
if result["has_face"]: # and result["identity"]:
|
||||
payload.update(
|
||||
{
|
||||
"ear": result["ear"],
|
||||
"mar": result["mar"],
|
||||
"iris_ratio_x": result["iris_ratio"][0],
|
||||
"iris_ratio_y": result["iris_ratio"][1],
|
||||
"pose_0": result["pose"][0],
|
||||
"pose_1": result["pose"][1],
|
||||
"pose_2": result["pose"][2],
|
||||
"label": result["emotion_label"],
|
||||
"emo_v": result["emotion_va"][0],
|
||||
"emo_a": result["emotion_va"][1],
|
||||
}
|
||||
)
|
||||
front_data.update(
|
||||
{
|
||||
"label": result["emotion_label"],
|
||||
"iris_ratio_x": result["iris_ratio"][0],
|
||||
"iris_ratio_y": result["iris_ratio"][1],
|
||||
"pose_0": result["pose"][0],
|
||||
"pose_1": result["pose"][1],
|
||||
"pose_2": result["pose"][2],
|
||||
}
|
||||
)
|
||||
# elif result["has_face"]:
|
||||
# payload.update(
|
||||
# {
|
||||
# "name": "Unknown",
|
||||
# "ear": result["ear"],
|
||||
# "mar": result["mar"],
|
||||
# "iris_ratio": result["iris_ratio"],
|
||||
# "pose": result["pose"],
|
||||
# "emo_label": result["emotion_label"],
|
||||
# "emo_va": result["emotion_va"],
|
||||
# }
|
||||
# )
|
||||
|
||||
if result["has_face"] and result["ear"] < 0.2:
|
||||
if status == 0:
|
||||
freq += 1
|
||||
status = 1
|
||||
elif result["has_face"] and result["ear"] >= 0.2:
|
||||
if status == 1:
|
||||
freq += 1
|
||||
status = 0
|
||||
|
||||
if time.time() - last_time >= gap:
|
||||
last_freq = freq / 2
|
||||
freq = 0
|
||||
last_time = time.time()
|
||||
result["eye_close_freq"] = last_freq
|
||||
payload["eye_close_freq"] = last_freq
|
||||
front_data["eye_close_freq"] = last_freq
|
||||
bpm = heart_monitor.process_frame(frame, result["landmark"])
|
||||
if bpm != None:
|
||||
result["heart_rate"] = bpm
|
||||
payload["heart_rate"] = bpm
|
||||
front_data["heart_rate"] = bpm
|
||||
if data_queue.full():
|
||||
try:
|
||||
print("[Analysis] 分析系统启动...")
|
||||
freq = 0
|
||||
gap = 60
|
||||
status = 0 # 0:open 1:close
|
||||
last_time = time.time()
|
||||
last_freq = 0
|
||||
heart_monitor = HeartRateMonitor()
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
_ = data_queue.get_nowait()
|
||||
frame = frame_queue.get(timeout=1)
|
||||
except queue.Empty:
|
||||
pass
|
||||
if front_data_queue.full():
|
||||
try:
|
||||
_ = front_data_queue.get_nowait()
|
||||
except queue.Empty:
|
||||
pass
|
||||
if ana_data_queue.full():
|
||||
try:
|
||||
_ = ana_data_queue.get_nowait()
|
||||
except queue.Empty:
|
||||
pass
|
||||
continue
|
||||
|
||||
data_queue.put(payload)
|
||||
# 核心分析
|
||||
result = monitor.process_frame(frame)
|
||||
result["eye_close_freq"] = 0
|
||||
result["heart_rate"] = 0
|
||||
|
||||
ana_data_queue.put(payload)
|
||||
put_latest(video_queue, result["frame"])
|
||||
put_latest(ana_video_queue, result["frame"])
|
||||
# print(f"[Analysis] {time.strftime('%Y-%m-%d %H:%M:%S')} - Frame processed")
|
||||
|
||||
front_data_queue.put(front_data)
|
||||
payload = {
|
||||
"seat_id": CAMERA_ID,
|
||||
"timestamp": time.time(),
|
||||
"heart_rate": 0,
|
||||
"emo_v": 0,
|
||||
"emo_a": 0,
|
||||
"pose_0": 0, #pitch
|
||||
"pose_1": 0, #yaw
|
||||
"pose_2": 0, #roll
|
||||
"ear": 0,
|
||||
"mar": 0,
|
||||
"label": "",
|
||||
"eye_close_freq": 0,
|
||||
"iris_ratio_x": 0,
|
||||
"iris_ratio_y": 0,
|
||||
}
|
||||
|
||||
show_queue.put((result["frame"], result))
|
||||
# draw_debug_info(frame, result)
|
||||
# cv2.imshow("Monitor Client", frame)
|
||||
front_data = {
|
||||
"seat_id": CAMERA_ID,
|
||||
"timestamp": time.time(),
|
||||
"label": "",
|
||||
"eye_close_freq": 0.0,
|
||||
"iris_ratio_x": 0,
|
||||
"iris_ratio_y": 0,
|
||||
"pose_0": 0, #pitch
|
||||
"pose_1": 0, #yaw
|
||||
"pose_2": 0, #roll
|
||||
"heart_rate": 0,
|
||||
}
|
||||
|
||||
print("[Analysis] 分析线程结束")
|
||||
if result["has_face"]: # and result["identity"]:
|
||||
payload.update(
|
||||
{
|
||||
"ear": result["ear"],
|
||||
"mar": result["mar"],
|
||||
"iris_ratio_x": result["iris_ratio"][0],
|
||||
"iris_ratio_y": result["iris_ratio"][1],
|
||||
"pose_0": result["pose"][0],
|
||||
"pose_1": result["pose"][1],
|
||||
"pose_2": result["pose"][2],
|
||||
"label": result["emotion_label"],
|
||||
"emo_v": result["emotion_va"][0],
|
||||
"emo_a": result["emotion_va"][1],
|
||||
}
|
||||
)
|
||||
front_data.update(
|
||||
{
|
||||
"label": result["emotion_label"],
|
||||
"iris_ratio_x": result["iris_ratio"][0],
|
||||
"iris_ratio_y": result["iris_ratio"][1],
|
||||
"pose_0": result["pose"][0],
|
||||
"pose_1": result["pose"][1],
|
||||
"pose_2": result["pose"][2],
|
||||
}
|
||||
)
|
||||
|
||||
if result["has_face"] and result["ear"] < 0.2:
|
||||
if status == 0:
|
||||
freq += 1
|
||||
status = 1
|
||||
elif result["has_face"] and result["ear"] >= 0.2:
|
||||
if status == 1:
|
||||
freq += 1
|
||||
status = 0
|
||||
|
||||
if time.time() - last_time >= gap:
|
||||
last_freq = freq / 2
|
||||
freq = 0
|
||||
last_time = time.time()
|
||||
result["eye_close_freq"] = last_freq
|
||||
payload["eye_close_freq"] = last_freq
|
||||
front_data["eye_close_freq"] = last_freq
|
||||
bpm = heart_monitor.process_frame(frame, result["landmark"])
|
||||
if bpm != None:
|
||||
result["heart_rate"] = bpm
|
||||
payload["heart_rate"] = bpm
|
||||
front_data["heart_rate"] = bpm
|
||||
|
||||
put_latest(data_queue, payload)
|
||||
put_latest(ana_data_queue, payload)
|
||||
put_latest(front_data_queue, front_data)
|
||||
put_latest(show_queue, (result["frame"], result))
|
||||
# draw_debug_info(frame, result)
|
||||
# cv2.imshow("Monitor Client", frame)
|
||||
finally:
|
||||
monitor.close()
|
||||
print("[Analysis] 分析线程结束")
|
||||
|
||||
|
||||
def video_stream_thread(server):
|
||||
@@ -288,6 +271,13 @@ def video_stream_thread(server):
|
||||
# print("✅ [Video] H.264 软编码启动成功!视频将保存为 MP4。")
|
||||
# -----------------------------------------------------------
|
||||
out1 = cv2.VideoWriter('output1.mp4', fourcc, 30.0, (1280, 720))
|
||||
if not out1.isOpened():
|
||||
print("[Video] avc1 编码器不可用,回退到 mp4v")
|
||||
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
||||
out1 = cv2.VideoWriter('output1.mp4', fourcc, 30.0, (1280, 720))
|
||||
if not out1.isOpened():
|
||||
print("[Video] 视频写入初始化失败,跳过本地录像")
|
||||
out1 = None
|
||||
# out2 = cv2.VideoWriter('output2.mp4', fourcc, 30.0, (1280, 720))
|
||||
|
||||
while not stop_event.is_set():
|
||||
@@ -296,7 +286,8 @@ def video_stream_thread(server):
|
||||
server.provide_frame(frame)
|
||||
data = front_data_queue.get(timeout=1)
|
||||
server.send_data(json.dumps(data))
|
||||
out1.write(frame)
|
||||
if out1 is not None:
|
||||
out1.write(frame)
|
||||
# out2.write(frame)
|
||||
except queue.Empty:
|
||||
continue
|
||||
@@ -347,7 +338,8 @@ def video_stream_thread(server):
|
||||
# except Exception as e:
|
||||
# print(f"[Video] 重连中... {e}")
|
||||
# time.sleep(3)
|
||||
out1.release()
|
||||
if out1 is not None:
|
||||
out1.release()
|
||||
# out2.release()
|
||||
print("[Video] 线程结束")
|
||||
|
||||
@@ -541,7 +533,7 @@ def alert_thread(server):
|
||||
if alert_status:
|
||||
print(f"警报: {alert_st}")
|
||||
alert = server.alert(int(time.time()), alert_st, info_level)
|
||||
alert = HookMocker(alert, "http://10.128.48.48:5000/api/osshook")
|
||||
alert = HookMocker(alert, "http://10.128.48.204:5000/api/osshook")
|
||||
alert.start(width=1280, height=720, fps=30)
|
||||
for f in buffered_frame:
|
||||
alert.provide_frame(f)
|
||||
@@ -644,7 +636,7 @@ def draw_debug_info(frame, result):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
server = WebRTCServer(60, 5, "ws://10.128.48.48:5000")
|
||||
server = WebRTCServer(60, CAMERA_ID, "ws://10.128.48.204:5000")
|
||||
server.start()
|
||||
t1 = threading.Thread(target=capture_thread, daemon=True)
|
||||
t2 = threading.Thread(target=analysis_thread, daemon=True)
|
||||
@@ -659,23 +651,26 @@ if __name__ == "__main__":
|
||||
t5.start()
|
||||
|
||||
try:
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
frame, result = show_queue.get(timeout=1)
|
||||
except queue.Empty:
|
||||
continue
|
||||
# frame = apply_soft_roi(frame)
|
||||
display_frame = frame.copy()
|
||||
draw_debug_info(display_frame, result)
|
||||
cv2.imshow("Monitor Client", display_frame)
|
||||
if cv2.waitKey(1) & 0xFF == ord("q"):
|
||||
stop_event.set()
|
||||
# time.sleep(1)
|
||||
|
||||
cv2.destroyAllWindows()
|
||||
except KeyboardInterrupt:
|
||||
print("停止程序...")
|
||||
try:
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
frame, result = show_queue.get(timeout=1)
|
||||
except queue.Empty:
|
||||
continue
|
||||
# frame = apply_soft_roi(frame)
|
||||
display_frame = frame.copy()
|
||||
draw_debug_info(display_frame, result)
|
||||
cv2.imshow("Monitor Client", display_frame)
|
||||
if cv2.waitKey(1) & 0xFF == ord("q"):
|
||||
stop_event.set()
|
||||
# time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("停止程序...")
|
||||
stop_event.set()
|
||||
finally:
|
||||
stop_event.set()
|
||||
cv2.destroyAllWindows()
|
||||
server.stop()
|
||||
|
||||
t1.join()
|
||||
t2.join()
|
||||
|
||||
Reference in New Issue
Block a user