采集卡bug修复

This commit is contained in:
Ray
2025-10-29 17:55:54 +08:00
parent 754501b933
commit 94fa69043b

View File

@@ -322,11 +322,11 @@ class PreviewWindow:
pil_image = Image.fromarray(resized_frame) pil_image = Image.fromarray(resized_frame)
photo = ImageTk.PhotoImage(image=pil_image) photo = ImageTk.PhotoImage(image=pil_image)
# 多重引用保护防止被GC回收 # 保存引用(按索引保存,方便查找)
self.photo_objects[idx] = photo # 按索引保存 self.photo_objects[idx] = photo
self.photo_objects_list.append(photo) # 在列表中保存防止GC
images_to_draw.append((photo, center_x, center_y)) # 添加到绘制列表在列表中保存引用防止GC
images_to_draw.append((photo, center_x, center_y, idx))
texts_to_draw.append((center_x, y + 15, name, 'white')) texts_to_draw.append((center_x, y + 15, name, 'white'))
frame_idx += 1 frame_idx += 1
@@ -353,31 +353,57 @@ class PreviewWindow:
print(f" 当前保存的照片对象数量: {len(self.photo_objects_list)}") print(f" 当前保存的照片对象数量: {len(self.photo_objects_list)}")
if images_to_draw: if images_to_draw:
# 创建一个临时列表保存所有photo引用防止在绘制时被GC # 先收集所有photo对象到列表中确保引用不丢失
photos_to_keep = [] photos_current_frame = []
for i, (photo, x, y) in enumerate(images_to_draw):
for i, item in enumerate(images_to_draw):
if len(item) == 4:
photo, x, y, idx = item
else:
# 兼容旧格式(如果还有的话)
photo, x, y = item[:3]
idx = None
try: try:
# 确保坐标在画布范围内 # 确保坐标在画布范围内
if 0 <= x <= canvas_width and 0 <= y <= canvas_height: if 0 <= x <= canvas_width and 0 <= y <= canvas_height:
# 在绘制前保存引用 # 先保存引用到列表防止GC
photos_to_keep.append(photo) photos_current_frame.append(photo)
# 然后绘制
canvas.create_image(x, y, image=photo, anchor='center') canvas.create_image(x, y, image=photo, anchor='center')
if self.debug_count <= 3 and i == 0: if self.debug_count <= 3 and i == 0:
print(f" 绘制图像 #{i} 到位置 ({x}, {y}), photo id: {id(photo)}") print(f" 绘制图像 #{i} (idx={idx}) 到位置 ({x}, {y})")
else: else:
if self.debug_count <= 3: if self.debug_count <= 3:
print(f" ⚠️ 图像 #{i} 位置 ({x}, {y}) 超出画布范围") print(f" ⚠️ 图像 #{i} 位置 ({x}, {y}) 超出画布范围")
except Exception as e: except Exception as e:
print(f" 绘制图像 #{i} 错误: {e}") error_msg = str(e).lower()
print(f" ❌ 绘制图像 #{i} 时出错: {type(e).__name__}: {e}")
if "pyimage" in error_msg:
# PhotoImage 对象被 GC 了,尝试恢复
if self.debug_count <= 5:
print(f" ⚠️ PhotoImage 对象丢失,尝试从字典恢复 (idx={idx})")
if idx is not None and idx in self.photo_objects:
try:
photo = self.photo_objects[idx]
photos_current_frame.append(photo)
canvas.create_image(x, y, image=photo, anchor='center')
if self.debug_count <= 5:
print(f" ✅ 已从字典恢复并重新绘制")
except Exception as e2:
if self.debug_count <= 5:
print(f" ❌ 恢复失败: {e2}")
else:
# 其他类型的错误,打印完整堆栈
import traceback import traceback
traceback.print_exc() traceback.print_exc()
# 确保照片对象不被回收(保存引用到实例变量 # 保存当前帧的所有photo引用替换旧的列表只保留当前帧
# 只保留最近的一批照片对象,避免内存泄漏 # 这样确保正在显示的photo对象不会被GC
self.photo_objects_list = photos_to_keep[:] # 复制列表 self.photo_objects_list = photos_current_frame[:] # 复制列表
# 限制列表大小只保留最近的20个对象
if len(self.photo_objects_list) > 20:
self.photo_objects_list = self.photo_objects_list[-20:]
else: else:
# 如果没有图像,至少显示一些提示 # 如果没有图像,至少显示一些提示
if self.debug_count <= 3: if self.debug_count <= 3: