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

如何使用C#/Python调用Pleora eBUS SDK获取Photon Focus相机像素数据

问题背景

我手上有一台型号为MV1-D2048x1088-3D06-760-G2的Photon Focus 3D相机,在Windows 10系统下用C#搭配5.1.1版本的Pleora eBUS SDK做开发。当前相机配置为LineFinder模式扫描激光线,DataFormat3D参数设为2,返回的缓冲区有效载荷为2×2048=4096字节,载荷数值正常。我需要将这部分数据保存,但目前遇到阻碍,想了解如何将缓冲区内容写入数组或其他数据结构后保存到文件流中。
我当前的代码调用了Pleora eBUS SDK的DataPointer参数,但不清楚该参数的作用。
相机数据格式说明

现有可运行代码
private unsafe static void ThreadProc(object aParameters)
{
    object[] lParameters = (object[])aParameters;
    MainForm lThis = (MainForm)lParameters[0];

    for (;;)
    {
        if (lThis.mIsStopping)
        {
            // 收到线程终止信号,返回
            return;
        }

        PvBuffer lBuffer = null;
        PvResult lOperationResult = new PvResult(PvResultCode.OK);                
        // 从采集管线中获取下一个缓冲区
        PvResult lResult = lThis.mStream.RetrieveBuffer(ref lBuffer, ref lOperationResult, 100);
        if (lResult.IsOK)
        {
            // 缓冲区操作结果正常,进行处理
            if (lOperationResult.IsOK)
            {
                //lThis.displayControl.Display(lBuffer);
                uint bSize = lBuffer.GetPayloadSize();
                PvImage image1 = lBuffer.Image;
                uint height1 = image1.Height;
                uint width1 = image1.Width;
                uint offx1 = image1.OffsetX;
                uint offy1 = image1.OffsetY;                        
                PvPixelType imgpixtype = image1.PixelType;                                               
                byte *data_pnt = image1.DataPointer ;
                byte[] MSB_array = new byte[(int)width1];
                int buff_size = 2 * (int)width1;
                byte[] pix_array = new byte[buff_size];                       
                
                ulong tStamp = lBuffer.Timestamp;
                string msgOut = (bSize.ToString() + " 时间戳 " + tStamp.ToString() + " 宽度 " + width1.ToString());
                Console.WriteLine(msgOut);
                for (int i = 0; i < width1; i++)
                {
                    MSB_array[i] = *data_pnt;
                    data_pnt += 1;
                }
                data_pnt += 1;
                Console.WriteLine(height1.ToString());
                for (int i = 0; i < width1; i++)
                {
                    ushort msb1 = MSB_array[i];
                    ushort last_4 = (ushort)(*data_pnt & 0x0F);
                    int integer1 = (msb1 << 4)+(ushort)(*data_pnt>>4);
                    double dec_part = (float)last_4 / (float)16;
                    double val1 = (float)integer1 + dec_part;
                    Console.WriteLine(val1.ToString());
                    data_pnt += 1;
                }
                Console.WriteLine(height1.ToString());
            }
            else
            {
                uint bSize = lBuffer.GetPayloadSize();
                ulong tStamp = lBuffer.Timestamp;
                string msgOut = (bSize.ToString() + " 结果异常 时间戳 " + tStamp.ToString());
                Console.WriteLine(msgOut);
            }

            // 处理完图像后必须将缓冲区重新加入流对象队列,否则会出现丢帧
            lThis.mStream.QueueBuffer(lBuffer);
        }
    }
}
实现方案

1. DataPointer参数说明

Pleora eBUS SDK中PvImage.DataPointer返回的是指向图像原始数据缓冲区起始位置的非托管内存指针,可直接通过该指针读取相机返回的原生字节数据,无需额外转换。

注意:你原代码中写了image1.Alloc(width1, (uint)2, imgpixtype),这行代码会重新分配内存覆盖原有缓冲区的真实数据,必须删除这行才能拿到正确的相机数据。

2. 缓冲区数据拷贝到托管数组

使用Marshal.Copy可以快速把非托管内存中的数据批量拷贝到C#托管数组,比逐字节读取效率更高:

// 放在获取data_pnt之后执行即可
System.Runtime.InteropServices.Marshal.Copy((IntPtr)data_pnt, pix_array, 0, buff_size);

3. 数据写入文件流

你可以根据业务需求选择保存格式:

保存原始二进制数据(方便后续二次解析)

using (FileStream fs = new FileStream($"scan_data_{tStamp}.bin", FileMode.Create, FileAccess.Write))
{
    fs.Write(pix_array, 0, pix_array.Length);
}

保存解析后的高度值到CSV文件(方便直接查看分析)

// 先把解析得到的所有val1存入列表
List<double> heightList = new List<double>();
// 你的解析逻辑中把val1添加到heightList中
using (StreamWriter sw = new StreamWriter($"height_result_{tStamp}.csv"))
{
    sw.WriteLine("列索引,高度值(单位:mm)");
    for (int i = 0; i < heightList.Count; i++)
    {
        sw.WriteLine($"{i},{heightList[i]:F4}");
    }
}

性能优化建议

如果采集帧率较高,不要在采集线程中直接做文件写入操作,建议把拷贝好的数组存入线程安全队列,单独开一个IO线程做异步写入,避免阻塞采集逻辑导致丢帧。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:27:05