You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EDSDK Python:如何将相机图像加载至系统内存而非磁盘?

直接将EDSDK拍摄的图像存入Python数据结构的可行方案

可以实现直接将图像存入Python数据结构,核心问题在于内存流的生命周期管理和跨线程数据安全传递,以下是修复后的实现方案:

关键问题分析

  • 你当前的代码中,内存流out在回调内创建但未完成数据提取,回调结束后EDSDK会回收相关资源,外部访问会导致崩溃
  • time.sleep(4)是不可靠的等待方式,无法确保回调执行完成
  • 未正确释放EDSDK资源(如相机列表、会话等),可能导致相机无响应

修复后的完整代码

首先导入必要模块:

import edsdk
from edsdk import ObjectEvent, PropID, SaveTo, CameraCommand
import pythoncom
import os
from queue import Queue
import numpy as np
from PIL import Image

定义线程安全队列用于传递图像数据,以及回调函数:

# 线程安全队列,用于从回调传递图像数据到主程序
image_queue = Queue()

def callback_object(event: ObjectEvent, object_handle: edsdk.EdObject) -> int:
    if event == ObjectEvent.DirItemCreated:
        dir_item_info = edsdk.GetDirectoryItemInfo(object_handle)
        
        # 创建内存流并下载图像
        out_stream = edsdk.CreateMemoryStream(dir_item_info["size"])
        edsdk.Download(object_handle, dir_item_info["size"], out_stream)
        edsdk.DownloadComplete(object_handle)
        
        # 从内存流读取原始数据
        raw_data = edsdk.ReadStream(out_stream, 0, dir_item_info["size"])
        
        # 获取图像信息,转换为Python可处理的格式
        image_info = edsdk.GetImageInfo(object_handle)
        # JPEG格式直接转PIL Image
        if image_info["imageType"] == edsdk.ImageType.JPEG:
            img = Image.frombytes("RGB", (image_info["width"], image_info["height"]), raw_data)
            image_queue.put(img)
        # RAW格式需额外处理(需安装rawpy库)
        # elif image_info["imageType"] == edsdk.ImageType.RAW:
        #     import rawpy
        #     with rawpy.imread(raw_data) as raw:
        #         img_np = raw.postprocess()
        #         image_queue.put(img_np)
        
        # 必须释放EDSDK资源
        edsdk.Release(out_stream)
        edsdk.Release(object_handle)
    return 0

主程序逻辑:

def main():
    edsdk.InitializeSDK()
    try:
        cam_list = edsdk.GetCameraList()
        cam_count = edsdk.GetChildCount(cam_list)
        if cam_count == 0:
            print("未检测到相机")
            return
        
        cam = edsdk.GetChildAtIndex(cam_list, 0)
        edsdk.OpenSession(cam)
        
        # 设置保存到主机
        edsdk.SetPropertyData(cam, PropID.SaveTo, 0, SaveTo.Host)
        # 设置对象事件回调
        edsdk.SetObjectEventHandler(cam, ObjectEvent.DirItemCreated, callback_object)
        
        # 发送拍照命令
        edsdk.SendCommand(cam, CameraCommand.TakePicture, 0)
        
        # 等待回调完成并获取图像,超时10秒
        print("等待图像数据...")
        try:
            img = image_queue.get(timeout=10)
            print("成功获取图像,尺寸:", img.size)
            # 此处可直接使用img进行后续处理(如分析、显示)
            # img.show()
        except:
            print("获取图像超时")
        
        # 清理资源
        edsdk.CloseSession(cam)
        edsdk.Release(cam)
        edsdk.Release(cam_list)
    finally:
        edsdk.TerminateSDK()

if __name__ == "__main__":
    if os.name == "nt":
        pythoncom.CoInitialize()
    main()
    if os.name == "nt":
        pythoncom.CoUninitialize()

核心注意事项

  • 资源释放:所有通过EDSDK创建/获取的对象(内存流、目录项、相机、相机列表)必须调用edsdk.Release()释放,否则会导致内存泄漏或相机锁死
  • 回调内完成数据提取:必须在回调函数内部完成内存流的数据读取,回调结束后EDSDK会回收相关资源,外部访问会崩溃
  • 线程安全传递:使用queue.Queue实现回调(EDSDK线程)和主程序线程之间的安全数据传递
  • 避免硬等待:不要用time.sleep(),改用队列的get(timeout)或事件通知来等待回调完成
  • 图像格式处理:根据相机设置的图像格式(JPEG/RAW)选择对应的转换方式,RAW格式需要额外依赖库(如rawpy)

内容的提问来源于stack exchange,提问作者maycookie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:57:24