vs
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
| **批量 D2C** | 对 Orbbec Viewer 导出的深度图批量软件对齐,无需连接相机 |
|
| **批量 D2C** | 对 Orbbec Viewer 导出的深度图批量软件对齐,无需连接相机 |
|
||||||
| **双算法支持** | 正向投影 + Splat 填充 / 逆向投影(SDK 同等),可实时切换预览 |
|
| **双算法支持** | 正向投影 + Splat 填充 / 逆向投影(SDK 同等),可实时切换预览 |
|
||||||
| **自动参数获取** | 从相机实时提取内外参,自动保存为 JSON |
|
| **自动参数获取** | 从相机实时提取内外参,自动保存为 JSON |
|
||||||
| **热插拔监听** | 自动监听设备插入/拔出并刷新设备列表,无需手动反复点击刷新 |
|
| **热插拔监听** | 设备拔出即时 Toast 提示;设备插入后自动加载设备列表 |
|
||||||
| **分辨率自适应** | 支持字体缩放(0.8× ~ 2.0×),适配不同 DPI 屏幕 |
|
| **分辨率自适应** | 支持字体缩放(0.8× ~ 2.0×),适配不同 DPI 屏幕 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -76,7 +76,7 @@ python main.py
|
|||||||
|
|
||||||
### 标签页一:数据采集
|
### 标签页一:数据采集
|
||||||
|
|
||||||
1. **刷新设备**:点击获取相机支持的 RGB / Depth 分辨率列表
|
1. **加载设备**:点击获取相机支持的 RGB / Depth 分辨率列表
|
||||||
2. **流配置**:选择 RGB 分辨率、Depth 分辨率、Preset(可选)
|
2. **流配置**:选择 RGB 分辨率、Depth 分辨率、Preset(可选)
|
||||||
3. **保存目录 & 采集内容**:
|
3. **保存目录 & 采集内容**:
|
||||||
- 设置根目录和子目录名称,点击「创建 / 载入」
|
- 设置根目录和子目录名称,点击「创建 / 载入」
|
||||||
@@ -89,7 +89,7 @@ python main.py
|
|||||||
|
|
||||||
### 标签页二:Orbbec Viewer 深度图 D2C
|
### 标签页二:Orbbec Viewer 深度图 D2C
|
||||||
|
|
||||||
1. **刷新设备**并选择 RGB / Depth 分辨率,点击「从设备获取参数」
|
1. **加载设备**并选择 RGB / Depth 分辨率,点击「从设备获取参数」
|
||||||
- 或手动选择已有的 `camera_params.json`
|
- 或手动选择已有的 `camera_params.json`
|
||||||
2. **选择深度图目录**:包含 PNG 深度图的文件夹
|
2. **选择深度图目录**:包含 PNG 深度图的文件夹
|
||||||
3. **选择转换方式**:
|
3. **选择转换方式**:
|
||||||
|
|||||||
@@ -1222,7 +1222,7 @@ class _Toast(QLabel):
|
|||||||
# ─────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
hotplug_changed = pyqtSignal()
|
hotplug_changed = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -1248,8 +1248,9 @@ class MainWindow(QMainWindow):
|
|||||||
self._build_ui()
|
self._build_ui()
|
||||||
# toast 覆盖在 central widget 上
|
# toast 覆盖在 central widget 上
|
||||||
self._toast = _Toast(self.centralWidget())
|
self._toast = _Toast(self.centralWidget())
|
||||||
self.hotplug_changed.connect(self._schedule_hotplug_refresh)
|
self.hotplug_changed.connect(self._handle_hotplug_event)
|
||||||
self._setup_hotplug_monitor()
|
self._setup_hotplug_monitor()
|
||||||
|
QTimer.singleShot(0, self._refresh_devices)
|
||||||
|
|
||||||
# ─────────────────────────────────
|
# ─────────────────────────────────
|
||||||
# UI Construction
|
# UI Construction
|
||||||
@@ -1351,15 +1352,15 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
COMBO_CSS = "QComboBox { combobox-popup: 0; }"
|
COMBO_CSS = "QComboBox { combobox-popup: 0; }"
|
||||||
|
|
||||||
# ── 第 1 步:刷新设备 ──
|
# ── 第 1 步:加载设备 ──
|
||||||
grp1 = self._step_group(1, "刷新设备")
|
grp1 = self._step_group(1, "加载设备")
|
||||||
g1 = QHBoxLayout(grp1)
|
g1 = QHBoxLayout(grp1)
|
||||||
g1.setContentsMargins(8, 4, 8, 6)
|
g1.setContentsMargins(8, 4, 8, 6)
|
||||||
self.refresh_btn = QPushButton("刷新设备")
|
self.refresh_btn = QPushButton("加载设备")
|
||||||
self.refresh_btn.setFixedHeight(_sz(28))
|
self.refresh_btn.setFixedHeight(_sz(28))
|
||||||
self.refresh_btn.clicked.connect(self._refresh_devices)
|
self.refresh_btn.clicked.connect(self._refresh_devices)
|
||||||
g1.addWidget(self.refresh_btn)
|
g1.addWidget(self.refresh_btn)
|
||||||
self.device_status = QLabel("未连接设备,请点击「刷新设备」")
|
self.device_status = QLabel("未连接设备,请点击「加载设备」")
|
||||||
self.device_status.setStyleSheet(f"color:#aaa; font-size:{_fs(12)}px;")
|
self.device_status.setStyleSheet(f"color:#aaa; font-size:{_fs(12)}px;")
|
||||||
g1.addWidget(self.device_status)
|
g1.addWidget(self.device_status)
|
||||||
g1.addStretch()
|
g1.addStretch()
|
||||||
@@ -1587,15 +1588,15 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
COMBO_CSS = "QComboBox { combobox-popup: 0; }"
|
COMBO_CSS = "QComboBox { combobox-popup: 0; }"
|
||||||
|
|
||||||
# ── 第 1 步:刷新设备 ──
|
# ── 第 1 步:加载设备 ──
|
||||||
grp1 = self._step_group(1, "刷新设备")
|
grp1 = self._step_group(1, "加载设备")
|
||||||
g1 = QHBoxLayout(grp1)
|
g1 = QHBoxLayout(grp1)
|
||||||
g1.setContentsMargins(8, 4, 8, 6)
|
g1.setContentsMargins(8, 4, 8, 6)
|
||||||
self.d2c_refresh_btn = QPushButton("刷新设备")
|
self.d2c_refresh_btn = QPushButton("加载设备")
|
||||||
self.d2c_refresh_btn.setFixedHeight(_sz(28))
|
self.d2c_refresh_btn.setFixedHeight(_sz(28))
|
||||||
self.d2c_refresh_btn.clicked.connect(self._refresh_devices)
|
self.d2c_refresh_btn.clicked.connect(self._refresh_devices)
|
||||||
g1.addWidget(self.d2c_refresh_btn)
|
g1.addWidget(self.d2c_refresh_btn)
|
||||||
self.d2c_device_status = QLabel("未连接设备,请点击「刷新设备」")
|
self.d2c_device_status = QLabel("未连接设备,请点击「加载设备」")
|
||||||
self.d2c_device_status.setStyleSheet(f"color:#aaa; font-size:{_fs(12)}px;")
|
self.d2c_device_status.setStyleSheet(f"color:#aaa; font-size:{_fs(12)}px;")
|
||||||
g1.addWidget(self.d2c_device_status)
|
g1.addWidget(self.d2c_device_status)
|
||||||
g1.addStretch()
|
g1.addStretch()
|
||||||
@@ -1729,14 +1730,45 @@ class MainWindow(QMainWindow):
|
|||||||
self._ob_context = None
|
self._ob_context = None
|
||||||
self._append_d2c_log(f"[热插拔] 启用失败:{exc}")
|
self._append_d2c_log(f"[热插拔] 启用失败:{exc}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _device_list_serials(device_list) -> list[str]:
|
||||||
|
sns: list[str] = []
|
||||||
|
try:
|
||||||
|
count = len(device_list)
|
||||||
|
except Exception:
|
||||||
|
return sns
|
||||||
|
for i in range(count):
|
||||||
|
try:
|
||||||
|
sn = device_list.get_device_serial_number_by_index(i)
|
||||||
|
sns.append(sn if sn else "unknown")
|
||||||
|
except Exception:
|
||||||
|
sns.append("unknown")
|
||||||
|
return sns
|
||||||
|
|
||||||
def _on_device_changed_callback(self, removed_list, added_list):
|
def _on_device_changed_callback(self, removed_list, added_list):
|
||||||
self.hotplug_changed.emit()
|
removed_sns = self._device_list_serials(removed_list)
|
||||||
|
added_sns = self._device_list_serials(added_list)
|
||||||
|
self.hotplug_changed.emit(removed_sns, added_sns)
|
||||||
|
|
||||||
|
def _handle_hotplug_event(self, removed_sns: list[str], added_sns: list[str]):
|
||||||
|
if removed_sns:
|
||||||
|
msg = "、".join(removed_sns)
|
||||||
|
self._toast.show_msg(f"设备 SN {msg} 已拔出", 1600)
|
||||||
|
self._append_d2c_log(f"[热插拔] 设备拔出:SN {msg}")
|
||||||
|
for lbl in (self.device_status, self.d2c_device_status):
|
||||||
|
lbl.setText(f"设备 SN {msg} 已拔出")
|
||||||
|
lbl.setStyleSheet(f"color:#cc8844; font-size:{_fs(12)}px;")
|
||||||
|
if added_sns:
|
||||||
|
msg = "、".join(added_sns)
|
||||||
|
self._toast.show_msg(f"设备 SN {msg} 已插入,正在自动加载", 1800)
|
||||||
|
self._append_d2c_log(f"[热插拔] 设备插入:SN {msg},自动加载设备列表")
|
||||||
|
self._schedule_hotplug_refresh()
|
||||||
|
|
||||||
def _schedule_hotplug_refresh(self):
|
def _schedule_hotplug_refresh(self):
|
||||||
if self._hotplug_pending:
|
if self._hotplug_pending:
|
||||||
return
|
return
|
||||||
self._hotplug_pending = True
|
self._hotplug_pending = True
|
||||||
QTimer.singleShot(350, self._run_hotplug_refresh)
|
QTimer.singleShot(500, self._run_hotplug_refresh)
|
||||||
|
|
||||||
def _run_hotplug_refresh(self):
|
def _run_hotplug_refresh(self):
|
||||||
if getattr(self, "_refreshing", False):
|
if getattr(self, "_refreshing", False):
|
||||||
@@ -1852,7 +1884,7 @@ class MainWindow(QMainWindow):
|
|||||||
if checked:
|
if checked:
|
||||||
if not self._color_profiles_data or not self._depth_profiles_data:
|
if not self._color_profiles_data or not self._depth_profiles_data:
|
||||||
self._set_stream_btn(False)
|
self._set_stream_btn(False)
|
||||||
QMessageBox.warning(self, "提示", "请先点击「刷新设备」以获取可用配置。")
|
QMessageBox.warning(self, "提示", "请先点击「加载设备」以获取可用配置。")
|
||||||
return
|
return
|
||||||
ci = self.color_combo.currentIndex()
|
ci = self.color_combo.currentIndex()
|
||||||
di = self.depth_combo.currentIndex()
|
di = self.depth_combo.currentIndex()
|
||||||
@@ -1942,7 +1974,7 @@ class MainWindow(QMainWindow):
|
|||||||
for lbl in (self.color_lbl, self.depth_lbl):
|
for lbl in (self.color_lbl, self.depth_lbl):
|
||||||
lbl.setText("设备已断开,请刷新后重新开启")
|
lbl.setText("设备已断开,请刷新后重新开启")
|
||||||
lbl.setPixmap(QPixmap())
|
lbl.setPixmap(QPixmap())
|
||||||
self.device_status.setText("设备已断开连接,请重新插入后点击「刷新设备」")
|
self.device_status.setText("设备已断开连接,请重新插入后点击「加载设备」")
|
||||||
self.device_status.setStyleSheet(f"color:#cc8844; font-size:{_fs(12)}px;")
|
self.device_status.setStyleSheet(f"color:#cc8844; font-size:{_fs(12)}px;")
|
||||||
|
|
||||||
# ─────────────────────────────────
|
# ─────────────────────────────────
|
||||||
@@ -2017,14 +2049,14 @@ class MainWindow(QMainWindow):
|
|||||||
ci = self.d2c_color_combo.currentIndex()
|
ci = self.d2c_color_combo.currentIndex()
|
||||||
di = self.d2c_depth_combo.currentIndex()
|
di = self.d2c_depth_combo.currentIndex()
|
||||||
if ci < 0 or di < 0:
|
if ci < 0 or di < 0:
|
||||||
self.params_selected_lbl.setText("请先刷新设备并选择分辨率")
|
self.params_selected_lbl.setText("请先加载设备并选择分辨率")
|
||||||
self.params_selected_lbl.setStyleSheet(f"color:#cc6666; font-size:{_fs(12)}px;")
|
self.params_selected_lbl.setStyleSheet(f"color:#cc6666; font-size:{_fs(12)}px;")
|
||||||
return
|
return
|
||||||
|
|
||||||
cc = self.d2c_color_combo.itemData(ci)
|
cc = self.d2c_color_combo.itemData(ci)
|
||||||
dc = self.d2c_depth_combo.itemData(di)
|
dc = self.d2c_depth_combo.itemData(di)
|
||||||
if not cc or not dc:
|
if not cc or not dc:
|
||||||
self.params_selected_lbl.setText("无配置数据,请先刷新设备")
|
self.params_selected_lbl.setText("无配置数据,请先加载设备")
|
||||||
self.params_selected_lbl.setStyleSheet(f"color:#cc6666; font-size:{_fs(12)}px;")
|
self.params_selected_lbl.setStyleSheet(f"color:#cc6666; font-size:{_fs(12)}px;")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user