工业相机测试之软触发取图时间

工业相机软触发取图时间测试

测试一下工业相机的软触发到拿到图像的时间
相机:万年不变的0.3MP
使用方法:QueryPerformanceCounter(ref long x);
测试选用海康相机自带回调Demo,曝光时间设置到最小(20us)

using System;
using System.Collections.Generic;
using MvCamCtrl.NET;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;


namespace Grab_Callback
{

    class Grab_Callback
    {
        public static long timeStart = 0, timeEnd = 0;//系统计数器
        public static long freq;//计数频率
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        public extern static short QueryPerformanceCounter(ref long x);


        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        public extern static short QueryPerformanceFrequency(ref long x);


        public static MyCamera.cbOutputExdelegate ImageCallback;
        public static MyCamera device = new MyCamera();
        static void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            QueryPerformanceCounter(ref timeEnd);//计时
            Console.WriteLine("Get one frame: Width[" + Convert.ToString(pFrameInfo.nWidth) + "] , Height[" + Convert.ToString(pFrameInfo.nHeight)
                                + "] , FrameNum[" + Convert.ToString(pFrameInfo.nFrameNum) + "]");
        }

        static void Main(string[] args)
        {
            int nRet = MyCamera.MV_OK;
            do
            {
                // ch:枚举设备 | en:Enum device
                MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
                nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Enum device failed:{0:x8}", nRet);
                    break;
                }
                Console.WriteLine("Enum device count : " + Convert.ToString(stDevList.nDeviceNum));
                if (0 == stDevList.nDeviceNum)
                {
                    break;
                }

                MyCamera.MV_CC_DEVICE_INFO stDevInfo;                            // 通用设备信息

                // ch:打印设备信息 en:Print device info
                for (Int32 i = 0; i < stDevList.nDeviceNum; i++)
                {
                    stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));

                    if (MyCamera.MV_GIGE_DEVICE == stDevInfo.nTLayerType)
                    {
                        MyCamera.MV_GIGE_DEVICE_INFO stGigEDeviceInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                        uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
                        uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
                        uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
                        uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
                        Console.WriteLine("\n" + i.ToString() + ": [GigE] User Define Name : " + stGigEDeviceInfo.chUserDefinedName);
                        Console.WriteLine("device IP :" + nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4);
                    }
                    else if (MyCamera.MV_USB_DEVICE == stDevInfo.nTLayerType)
                    {
                        MyCamera.MV_USB3_DEVICE_INFO stUsb3DeviceInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
                        Console.WriteLine("\n" + i.ToString() + ": [U3V] User Define Name : " + stUsb3DeviceInfo.chUserDefinedName);
                        Console.WriteLine("\n Serial Number : " + stUsb3DeviceInfo.chSerialNumber);
                        Console.WriteLine("\n Device Number : " + stUsb3DeviceInfo.nDeviceNumber);
                    }
                }

                Int32 nDevIndex = 0;
                Console.Write("\nPlease input index (0 -- {0:d}) : ", stDevList.nDeviceNum - 1);
                try
                {
                    nDevIndex = Convert.ToInt32(Console.ReadLine());
                }
                catch
                {
                    Console.Write("Invalid Input!\n");
                    break;
                }

                if (nDevIndex > stDevList.nDeviceNum - 1 || nDevIndex < 0)
                {
                    Console.Write("Input Error!\n");
                    break;
                }
                stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MyCamera.MV_CC_DEVICE_INFO));

                // ch:创建设备 | en:Create device
                nRet = device.MV_CC_CreateDevice_NET(ref stDevInfo);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Create device failed:{0:x8}", nRet);
                    break;
                }

                // ch:打开设备 | en:Open device
                nRet = device.MV_CC_OpenDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Open device failed:{0:x8}", nRet);
                    break;
                }

                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    int nPacketSize = device.MV_CC_GetOptimalPacketSize_NET();
                    if (nPacketSize > 0)
                    {
                        nRet = device.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
                        if (nRet != MyCamera.MV_OK)
                        {
                            Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
                    }
                }

                // ch:设置触发模式为off || en:set trigger mode as off
                nRet = device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Set TriggerMode failed!");
                    break;
                }
                // ch:设置触发模式为off || en:set trigger mode as off
                nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", 7);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Set TriggerSource failed!");
                    break;
                }

                
                // ch:注册回调函数 | en:Register image callback
                ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
                nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Register image callback failed!");
                    break;
                }

                QueryPerformanceFrequency(ref freq);//获取计数频率

                // ch:开启抓图 || en: start grab image
                nRet = device.MV_CC_StartGrabbing_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Start grabbing failed:{0:x8}", nRet);
                    break;
                }

                QueryPerformanceCounter(ref timeStart);

                nRet = device.MV_CC_SetCommandValue_NET("TriggerSoftware");
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Soft trigger failed:{0:x8}", nRet);
                    break;
                }

                Thread.Sleep(1000);

                Console.WriteLine("cost: " + Convert.ToString((timeEnd - timeStart) / Convert.ToDouble(freq) * 1000) + "ms");

                // ch:停止抓图 | en:Stop grabbing
                nRet = device.MV_CC_StopGrabbing_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Stop grabbing failed{0:x8}", nRet);
                    break;
                }

                

                // ch:关闭设备 | en:Close device
                nRet = device.MV_CC_CloseDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Close device failed{0:x8}", nRet);
                    break;
                }

                // ch:销毁设备 | en:Destroy device
                nRet = device.MV_CC_DestroyDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Destroy device failed:{0:x8}", nRet);
                    break;
                }
        } while (false);

        if (MyCamera.MV_OK != nRet)
        {
            // ch:销毁设备 | en:Destroy device
            nRet = device.MV_CC_DestroyDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                Console.WriteLine("Destroy device failed:{0:x8}", nRet);
            }
        }

        Console.WriteLine("Press enter to exit");
        Console.ReadKey();
        }
    }
}

测试结果:
在这里插入图片描述
这个计时函数的精度还是蛮高的,但是软触发出图15ms的耗时以这款相机将近200的帧率来说,还是有些偏长的。
后来了解到,软触发在命令的发送过程中耗时比较长,而且也会受到网络波动影响,看来如果对速度要求高的话,还是得用硬触发。

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: QT是一种跨平台的应用程序开发框架,它提供了许多功能和工具来简化软件开发。对于网口工业相机丢帧检测,QT可以作为一个使用方便且功能强大的工具来实现。 在使用QT来实现网口工业相机丢帧检测时,我们可以利用QT中提供的网络模块来连接相机,并从相机中获取图像帧。通过设置一个定时器,我们可以定时获取相机图像帧,并与上一帧进行对比,以检查是否有帧丢失。 首先,我们需要使用QT的网络模块来建立与相机的连接。QT提供了TCP和UDP的网络通信功能,我们可以选择适合相机的通信方式来与相机进行通信。 然后,我们可以使用QT的定时器功能来定时获取相机图像帧。可以设置一个适当的时间间隔,例如每秒获取一帧图像。在定时器的槽函数中,我们可以调用相机的API来获取当前的图像帧。 获取到图像帧后,我们需要将其与上一帧进行对比,以检查是否有帧丢失。可以通过比较帧的序号或时间戳来判断图像帧是否有丢失。如果发现帧丢失,我们可以在界面上显示相应的提示信息,以便后续处理。 在使用QT进行网口工业相机丢帧检测时,我们需要熟悉QT的各种功能和API,并理解网口工业相机的相关接口和协议。通过合理地利用QT的功能和工具,我们可以方便地进行相机丢帧检测,并及时处理丢失的图像帧。 ### 回答2: QT对于网口工业相机丢帧检测可以通过以下步骤实现: 首先,需要使用QT进行图像采集和显示。可以使用QT自带的图像采集模块或者调用第三方库来读取网口工业相机图像。QT提供了强大的图像显示功能,可以显示相机采集图像。 其次,需要在QT中编写处理图像的算法。针对丢帧检测,可以通过比较连续帧之间的时间戳或帧号来判断是否有丢帧情况发生。可以在每次采集到新的图像时记录下当前的时间戳或帧号,并与前一帧的时间戳或帧号进行比较。如果时间差值或帧号差值超过一定的阈值,则可以判断为发生了丢帧。 接着,可以使用QT的界面设计功能将丢帧检测结果可视化。可以在界面上显示当前的帧号或时间戳,以及检测到的丢帧数量。可以通过改变界面上的颜色或文字来提醒用户是否发生了丢帧情况。 最后,可以通过QT的多线程编程功能将图像采集和处理分离,以提高系统的并发性能。可以将图像采集和处理的任务分别放在不同的线程中进行,这样可以更好地实现丢帧检测的实时性和准确性。 总之,使用QT可以方便地实现网口工业相机丢帧检测功能,并通过界面设计功能将检测结果可视化,提高用户的交互体验。 ### 回答3: Qt是一个跨平台应用程序开发框架,可以用于开发各种类型的应用程序,包括工业相机的丢帧检测系统。 在使用Qt进行网口工业相机丢帧检测时,我们可以利用Qt提供的网络模块来实现与工业相机进行数据通信。通过从相机接收图像数据并进行处理,可以检测到是否有帧丢失的情况发生。 Qt提供了高效且易用的图像处理库,如OpenCV和Qt Multimedia模块,可以帮助我们实现对图像数据的处理和分析。可以通过设置适当的算法来检测图像中是否丢失了某些帧。 此外,Qt还提供了强大的图形界面开发能力,我们可以使用Qt的图形界面设计器设计出直观友好的用户界面,展示相机采集到的图像、显示检测结果等。 在开发过程中,我们可以利用Qt的信号与槽机制来实现相机采集图像数据的实时显示和丢帧检测的响应处理。通过设置合适的信号触发条件,当检测到丢帧时,我们可以及时发出警告或采取其他适当的处理措施。 综上所述,Qt对于网口工业相机丢帧检测提供了全面的支持和强大的开发能力。借助于Qt的跨平台特性和丰富的功能库,我们可以很方便地开发出高效可靠的丢帧检测系统。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值