Commit 9f93245a by yhb

1

parent 2da70438
...@@ -33,7 +33,7 @@ channel4: ...@@ -33,7 +33,7 @@ channel4:
channel1: channel1:
general: general:
task_id: '1' task_id: '1'
task_name: 海信现场测试 task_name: 历史回放功能展示
area_count: 0 area_count: 0
safe_low: 2.0mm safe_low: 2.0mm
safe_high: 10.0mm safe_high: 10.0mm
...@@ -41,7 +41,7 @@ channel1: ...@@ -41,7 +41,7 @@ channel1:
video_format: AVI video_format: AVI
push_address: '' push_address: ''
video_path: '' video_path: ''
save_liquid_data_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\1_海信现场测试 save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_历史回放功能展示
areas: areas:
area_1: 通道1_区域1 area_1: 通道1_区域1
area_heights: area_heights:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -364,12 +364,32 @@ class CurvePanelHandler: ...@@ -364,12 +364,32 @@ class CurvePanelHandler:
print(f" - 实际添加数据点数: {added_count}") print(f" - 实际添加数据点数: {added_count}")
print(f" - 更新后数据点数: {after_add_count}") print(f" - 更新后数据点数: {after_add_count}")
# 🔥 同步布局模式:根据时间轴范围过滤数据
is_sync_layout = hasattr(self, '_video_layout_mode') and self._video_layout_mode == 1
if is_sync_layout and self.curve_panel:
start_time, end_time = self.curve_panel.getTimeAxisRange()
if start_time is not None and end_time is not None:
print(f" - 同步布局模式,过滤时间范围: {start_time:.3f} 到 {end_time:.3f}")
# 过滤数据点,只保留在时间范围内的点
filtered_time = []
filtered_value = []
for t, v in zip(channel['time'], channel['value']):
if start_time <= t <= end_time:
filtered_time.append(t)
filtered_value.append(v)
before_filter = len(channel['time'])
channel['time'] = filtered_time
channel['value'] = filtered_value
after_filter = len(channel['time'])
print(f" - 时间过滤: {before_filter} -> {after_filter} 个数据点")
# 🔥 限制数据点数量 # 🔥 限制数据点数量
# - 'realtime' 模式:限制为3000个点(滚动窗口) # - 'realtime' 同步布局模式:限制为3000个点(滚动窗口)
# - 'history' 模式:显示完整数据(不采样) # - 'history' 历史回放模式:显示完整数据(不采样)
if self.curve_load_mode == 'realtime': if self.curve_load_mode == 'realtime':
# 实时模式:保留最新3000个点 # 同步布局模式:保留最新3000个点
if len(channel['time']) > self.max_points: if len(channel['time']) > self.max_points:
before_limit = len(channel['time']) before_limit = len(channel['time'])
channel['time'] = channel['time'][-self.max_points:] channel['time'] = channel['time'][-self.max_points:]
...@@ -679,6 +699,17 @@ class CurvePanelHandler: ...@@ -679,6 +699,17 @@ class CurvePanelHandler:
except Exception as e: except Exception as e:
pass pass
def getTimeAxisRange(self):
"""
获取曲线面板时间轴显示范围
Returns:
tuple: (starttime, endtime) - 时间轴起始时刻和结束时刻(Unix时间戳)
"""
if self.curve_panel:
return self.curve_panel.getTimeAxisRange()
return (None, None)
# ========== 数据管理方法 ========== # ========== 数据管理方法 ==========
def clearAllData(self): def clearAllData(self):
......
...@@ -333,7 +333,7 @@ class ViewHandler: ...@@ -333,7 +333,7 @@ class ViewHandler:
# 🔥 停止所有曲线线程(切换回默认布局时) # 🔥 停止所有曲线线程(切换回默认布局时)
self._stopAllCurveThreads() self._stopAllCurveThreads()
# 🔥 切换曲线绘制模式为实时模式 # 🔥 切换曲线绘制模式为同步布局模式
if hasattr(self, 'curvePanelHandler'): if hasattr(self, 'curvePanelHandler'):
self.curvePanelHandler.setCurveLoadMode('realtime') self.curvePanelHandler.setCurveLoadMode('realtime')
......
使用HKCapture类进行捕获画面帧
使用HKCapture类进行捕获画面帧
以avi的形式,五分钟保存一次视频到本地
rtsp相机为海康威视类型
rtsp地址和保存路径在代码中设置,要求最多能同时录制四个rtsp相机
相机1地址rtsp://admin:cei345678@192.168.2.126:8000/stream1,相机1存放路径"D:\record\通道1"
相机2地址rtsp://admin:cei345678@192.168.2.27:8000/stream1,相机2存放路径"D:\record\通道2"
相机3地址rtsp://admin:cei345678@192.168.2.121:8000/stream1相机3存放路径"D:\record\通道3"
\ No newline at end of file
时间轴变量starttime,endtime
时间轴变量starttime,endtime
采样逻辑,根据数据点个数设置不同采样率
@curvepanel_handler.py#L371-378 修改self._video_layout_mode = 1同步布局,绘制曲线的数据范围
实验最长时间三天,strattime到endtime,缩放限制
曲线面板所有都历史模式下,
\ No newline at end of file
import cv2
import threading
import time
import os
from datetime import datetime, timedelta
import logging
# 导入HKcapture类
try:
from handlers.videopage.HK_SDK.HKcapture import HKcapture
except ImportError:
# 如果相对导入失败,尝试绝对导入
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'handlers', 'videopage'))
from HK_SDK.HKcapture import HKcapture
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
class VideoRecorder:
def __init__(self, rtsp_url, save_path, camera_id):
self.rtsp_url = rtsp_url
self.save_path = save_path
self.camera_id = camera_id
self.cap = None
self.writer = None
self.is_recording = False
self.thread = None
self.file_start_time = None
def start_recording(self):
if not os.path.exists(self.save_path):
os.makedirs(self.save_path)
self.is_recording = True
self.thread = threading.Thread(target=self._record_loop)
self.thread.start()
logging.info(f"相机{self.camera_id}开始录制: {self.rtsp_url}")
def stop_recording(self):
self.is_recording = False
if self.thread:
self.thread.join()
if self.cap:
self.cap.stop_capture()
self.cap.release()
if self.writer:
self.writer.release()
logging.info(f"相机{self.camera_id}停止录制")
def _record_loop(self):
# 使用HKcapture类初始化
self.cap = HKcapture(source=self.rtsp_url, fps=25)
# 打开连接
if not self.cap.open():
logging.error(f"无法打开相机{self.camera_id}: {self.rtsp_url}")
return
# 开始捕获
if not self.cap.start_capture():
logging.error(f"无法开始捕获相机{self.camera_id}: {self.rtsp_url}")
return
# 获取视频属性
width, height = self.cap.get_frame_size()
fps = self.cap.get_fps()
if width == 0 or height == 0:
# 如果无法获取尺寸,尝试读取一帧来获取
time.sleep(2) # 等待数据开始流入
ret, frame = self.cap.read()
if ret and frame is not None:
height, width = frame.shape[:2]
else:
width, height = 1920, 1080 # 默认尺寸
fourcc = cv2.VideoWriter_fourcc(*'MJPG') # AVI格式
self.file_start_time = datetime.now()
self._create_new_writer(fourcc, fps, width, height)
while self.is_recording:
ret, frame = self.cap.read()
if ret and frame is not None:
self.writer.write(frame)
else:
time.sleep(0.1) # 等待新帧
# 检查是否需要切换新文件(5分钟)
if datetime.now() - self.file_start_time >= timedelta(minutes=5):
self.writer.release()
self.file_start_time = datetime.now()
self._create_new_writer(fourcc, fps, width, height)
if self.writer:
self.writer.release()
self.cap.stop_capture()
self.cap.release()
def _create_new_writer(self, fourcc, fps, width, height):
timestamp = self.file_start_time.strftime('%Y%m%d_%H%M%S')
filename = f"{self.save_path}/camera_{self.camera_id}_{timestamp}.avi"
self.writer = cv2.VideoWriter(filename, fourcc, fps, (width, height))
logging.info(f"创建新视频文件: {filename}")
def main():
# 相机配置(最多支持4个)
cameras = [
{
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.126:8000/stream1',
'save_path': r'D:\record\通道1',
'id': 1
},
{
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.27:8000/stream1',
'save_path': r'D:\record\通道2',
'id': 2
},
{
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.121:8000/stream1',
'save_path': r'D:\record\通道3',
'id': 3
},
# 第四个相机可在此添加
# {
# 'rtsp_url': 'rtsp://...',
# 'save_path': r'D:\record\通道4',
# 'id': 4
# }
]
# 创建录制器
recorders = []
for cam in cameras:
recorder = VideoRecorder(cam['rtsp_url'], cam['save_path'], cam['id'])
recorders.append(recorder)
# 启动录制
for recorder in recorders:
recorder.start_recording()
try:
# 持续运行,可添加停止逻辑
while True:
time.sleep(1)
except KeyboardInterrupt:
logging.info("收到停止信号,正在停止录制...")
for recorder in recorders:
recorder.stop_recording()
if __name__ == '__main__':
main()
\ No newline at end of file
...@@ -104,6 +104,10 @@ class CurvePanel(QtWidgets.QWidget): ...@@ -104,6 +104,10 @@ class CurvePanel(QtWidgets.QWidget):
self.current_channel = None # 当前显示的通道ID self.current_channel = None # 当前显示的通道ID
self.curve_items = {} # {channel_id: PlotDataItem} - 只存储曲线UI对象 self.curve_items = {} # {channel_id: PlotDataItem} - 只存储曲线UI对象
# 时间轴显示范围变量
self.starttime = None # 时间轴起始时刻(Unix时间戳)
self.endtime = None # 时间轴结束时刻(Unix时间戳)
# 颜色配置 # 颜色配置
self.channel_colors = [ self.channel_colors = [
'#1f77b4', # 蓝色 '#1f77b4', # 蓝色
...@@ -718,6 +722,15 @@ class CurvePanel(QtWidgets.QWidget): ...@@ -718,6 +722,15 @@ class CurvePanel(QtWidgets.QWidget):
""" """
return (self.spn_upper_limit.value(), self.spn_lower_limit.value()) return (self.spn_upper_limit.value(), self.spn_lower_limit.value())
def getTimeAxisRange(self):
"""
获取当前时间轴显示范围
Returns:
tuple: (starttime, endtime) - 时间轴起始时刻和结束时刻(Unix时间戳)
"""
return (self.starttime, self.endtime)
# ========== 私有方法 ========== # ========== 私有方法 ==========
...@@ -812,6 +825,10 @@ class CurvePanel(QtWidgets.QWidget): ...@@ -812,6 +825,10 @@ class CurvePanel(QtWidgets.QWidget):
y_min, y_max = y_range y_min, y_max = y_range
x_min, x_max = x_range x_min, x_max = x_range
# 更新时间轴显示范围变量
self.starttime = x_min # 时间轴起始时刻(Unix时间戳)
self.endtime = x_max # 时间轴结束时刻(Unix时间戳)
# 确保Y轴范围在0-23之间 # 确保Y轴范围在0-23之间
if y_min < 0 or y_max > 23: if y_min < 0 or y_max > 23:
# 调整到合法范围 # 调整到合法范围
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment