Commit 917fbb65 by yhb

1

parent 38c68ebe
...@@ -386,20 +386,45 @@ class DataCollectionChannelHandler: ...@@ -386,20 +386,45 @@ class DataCollectionChannelHandler:
def _parseRTSP(self, rtsp_url): def _parseRTSP(self, rtsp_url):
"""解析RTSP URL(复用实时监测管理的方法)""" """解析RTSP URL(复用实时监测管理的方法)"""
try: try:
import re
# RTSP URL格式: rtsp://username:password@ip:port/path # RTSP URL格式: rtsp://username:password@ip:port/path
pattern = r'rtsp://([^:]+):([^@]+)@([^:/]+)' # 支持密码中包含@符号的情况
match = re.match(pattern, rtsp_url) if not rtsp_url.startswith('rtsp://'):
return None, None, None
if match: url_part = rtsp_url[7:] # 去掉 "rtsp://"
username = match.group(1)
password = match.group(2) # 找到最后一个 @ 符号(IP地址前的那个)
ip = match.group(3) last_at_index = url_part.rfind('@')
return username, password, ip if last_at_index == -1:
else:
return None, None, None return None, None, None
credentials_part = url_part[:last_at_index]
host_part = url_part[last_at_index + 1:]
# 分离用户名和密码(第一个:分隔)
first_colon = credentials_part.find(':')
if first_colon == -1:
return None, None, None
username = credentials_part[:first_colon]
password = credentials_part[first_colon + 1:]
# URL解码密码
from urllib.parse import unquote
password = unquote(password)
# 提取IP(到:或/为止)
ip_end = len(host_part)
colon_idx = host_part.find(':')
slash_idx = host_part.find('/')
if colon_idx != -1:
ip_end = min(ip_end, colon_idx)
if slash_idx != -1:
ip_end = min(ip_end, slash_idx)
ip = host_part[:ip_end]
return username, password, ip
except Exception as e: except Exception as e:
return None, None, None return None, None, None
......
...@@ -79,11 +79,14 @@ class AmplifyWindowHandler: ...@@ -79,11 +79,14 @@ class AmplifyWindowHandler:
self.min_zoom = 1.0 self.min_zoom = 1.0
self.max_zoom = 30.0 # 支持更大倍数变焦 self.max_zoom = 30.0 # 支持更大倍数变焦
self.zoom_step = 0.1 self.zoom_step = 0.1
self.zoom_center_x = 960 # 变焦中心X坐标 self.zoom_center_x = 0 # 变焦中心X坐标(将根据图片尺寸自适应设置)
self.zoom_center_y = 540 # 变焦中心Y坐标 self.zoom_center_y = 0 # 变焦中心Y坐标(将根据图片尺寸自适应设置)
self._zoom_center_initialized = False # 标记放大中心是否已初始化
# 当前帧缓存 # 当前帧缓存
self._current_frame = None self._current_frame = None
self._frame_width = 0 # 帧宽度
self._frame_height = 0 # 帧高度
# 连接信号 # 连接信号
self._connectSignals() self._connectSignals()
...@@ -270,6 +273,10 @@ class AmplifyWindowHandler: ...@@ -270,6 +273,10 @@ class AmplifyWindowHandler:
# 缓存当前帧 # 缓存当前帧
self._current_frame = frame.copy() self._current_frame = frame.copy()
# 获取帧尺寸并自适应设置放大中心
height, width = frame.shape[:2]
self._updateZoomCenter(width, height)
# 物理变焦模式下,变焦由硬件完成,直接返回帧 # 物理变焦模式下,变焦由硬件完成,直接返回帧
return frame return frame
...@@ -277,6 +284,49 @@ class AmplifyWindowHandler: ...@@ -277,6 +284,49 @@ class AmplifyWindowHandler:
print(f"[物理变焦] 帧处理失败: {e}") print(f"[物理变焦] 帧处理失败: {e}")
return frame return frame
def _updateZoomCenter(self, width, height):
"""
根据图片尺寸自适应更新放大中心
Args:
width: 图片宽度
height: 图片高度
"""
# 检查尺寸是否变化
if width != self._frame_width or height != self._frame_height:
self._frame_width = width
self._frame_height = height
# 设置放大中心为图片中心
self.zoom_center_x = width // 2
self.zoom_center_y = height // 2
self._zoom_center_initialized = True
def setZoomCenter(self, x, y):
"""
手动设置放大中心点
Args:
x: 中心点X坐标
y: 中心点Y坐标
"""
# 确保坐标在有效范围内
if self._frame_width > 0 and self._frame_height > 0:
self.zoom_center_x = max(0, min(x, self._frame_width))
self.zoom_center_y = max(0, min(y, self._frame_height))
else:
self.zoom_center_x = x
self.zoom_center_y = y
self._zoom_center_initialized = True
def getZoomCenter(self):
"""
获取当前放大中心点
Returns:
tuple: (x, y) 放大中心坐标
"""
return (self.zoom_center_x, self.zoom_center_y)
def onMouseClicked(self, click_x, click_y): def onMouseClicked(self, click_x, click_y):
"""处理鼠标点击事件 - 物理变焦中心点设置""" """处理鼠标点击事件 - 物理变焦中心点设置"""
try: try:
......
...@@ -774,7 +774,8 @@ class ChannelPanelHandler: ...@@ -774,7 +774,8 @@ class ChannelPanelHandler:
return return
# 解析RTSP URL获取连接信息 # 解析RTSP URL获取连接信息
username, password, ip = self._parseRTSP(rtsp_url) username, password, ip, port = self._parseRTSP(rtsp_url)
# 创建捕获对象 # 创建捕获对象
if username and password and ip: if username and password and ip:
...@@ -783,7 +784,7 @@ class ChannelPanelHandler: ...@@ -783,7 +784,7 @@ class ChannelPanelHandler:
source=ip, source=ip,
username=username, username=username,
password=password, password=password,
port=8000, port=port,
channel=1, channel=1,
fps=fps # 传入配置的帧率 fps=fps # 传入配置的帧率
) )
...@@ -861,26 +862,78 @@ class ChannelPanelHandler: ...@@ -861,26 +862,78 @@ class ChannelPanelHandler:
# 检查是否为纯IP # 检查是否为纯IP
ip_pattern = r'^(\d{1,3}\.){3}\d{1,3}$' ip_pattern = r'^(\d{1,3}\.){3}\d{1,3}$'
if re.match(ip_pattern, rtsp_url): if re.match(ip_pattern, rtsp_url):
return None, None, rtsp_url return None, None, rtsp_url, 8000
# 检查是否为USB设备(如 "0") # 检查是否为USB设备(如 "0")
if rtsp_url.isdigit(): if rtsp_url.isdigit():
return None, None, None return None, None, None, 8000
# 解析完整RTSP URL(支持密码中包含@符号)
if rtsp_url.startswith('rtsp://'):
url_part = rtsp_url[7:] # 去掉 "rtsp://"
# 找到最后一个 @ 符号(IP地址前的那个)
last_at_index = url_part.rfind('@')
if last_at_index != -1:
# 有认证信息
credentials_part = url_part[:last_at_index]
host_part = url_part[last_at_index + 1:]
# 分离用户名和密码(第一个:分隔)
first_colon = credentials_part.find(':')
if first_colon != -1:
username = credentials_part[:first_colon]
password = credentials_part[first_colon + 1:]
# URL解码密码
from urllib.parse import unquote
password = unquote(password)
else:
username = credentials_part
password = None
else:
# 没有认证信息
username = None
password = None
host_part = url_part
# 提取IP和端口
colon_idx = host_part.find(':')
slash_idx = host_part.find('/')
if colon_idx != -1:
ip = host_part[:colon_idx]
# 提取端口
if slash_idx != -1:
port_str = host_part[colon_idx + 1:slash_idx]
else:
port_str = host_part[colon_idx + 1:]
try:
port = int(port_str)
except ValueError:
port = 8000
else:
if slash_idx != -1:
ip = host_part[:slash_idx]
else:
ip = host_part
port = 8000
# 解析完整RTSP URL
pattern = r'rtsp://(?:([^:]+):([^@]+)@)?([^:/]+)'
match = re.match(pattern, rtsp_url)
if match: return username, password, ip, port
username = match.group(1)
password = match.group(2)
ip = match.group(3)
return username, password, ip
return None, None, None return None, None, None, 8000
except Exception as e: except Exception as e:
return None, None, None return None, None, None, 8000
def _updateChannelConnectedUI(self, channel_id): def _updateChannelConnectedUI(self, channel_id):
"""更新通道连接UI状态(在主线程中执行)""" """更新通道连接UI状态(在主线程中执行)"""
......
...@@ -132,17 +132,17 @@ def main(): ...@@ -132,17 +132,17 @@ def main():
# 相机配置(最多支持4个) # 相机配置(最多支持4个)
cameras = [ cameras = [
{ {
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.126:8000/stream1', 'rtsp_url': 'rtsp://admin:123456aA@@192.168.8.225:8000/stream1',
'save_path': r'D:\record\通道1', 'save_path': r'D:\record\通道1',
'id': 1 'id': 1
}, },
{ {
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.27:8000/stream1', 'rtsp_url': 'rtsp://admin:123456aA@@192.168.8.215:8000/stream1',
'save_path': r'D:\record\通道2', 'save_path': r'D:\record\通道2',
'id': 2 'id': 2
}, },
{ {
'rtsp_url': 'rtsp://admin:cei345678@192.168.2.121:8000/stream1', 'rtsp_url': 'rtsp://admin:123456aA@@192.168.8.228:8000/stream1',
'save_path': r'D:\record\通道3', 'save_path': r'D:\record\通道3',
'id': 3 'id': 3
}, },
......
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