Dalsa彩色Nano相机采集图像,Halcon+OpenCV显示图像

开发工具:vs2022

以下Demo借鉴了以下两位博主的文章编写
http://t.csdnimg.cn/GwLJA
http://t.csdnimg.cn/xZguR

傻瓜式安装SDK

在这里插入图片描述
安装后在软件安装路径中找到DALSA.SaperaLT.SapClassBasic.dll文件,因为后续开发我们需要引用这个文件
在这里插入图片描述

接着引用halcon和OpenCvSharp,Oencv可以直接在VS中的NuGet包中下载引用

大致引用的文件如下:
在这里插入图片描述

初始化相机信息


private SapLocation m_ServerLocation; // 设备的连接地址
private SapAcqDevice m_AcqDevice; // 采集设备
private SapBuffer m_Buffers =new SapBuffer(); // 缓存对textBox3象
private SapAcqDeviceToBuf m_Xfer; // 传输对象
 
public bool GetCameraInfo(out string sCameraName, out int nIndex)//得到连接的相机信息,并将加入到ArrayList里面去
 {
     sCameraName = "";
     nIndex = 0;

     int serverCount = SapManager.GetServerCount();
     int GenieIndex = 0;
     System.Collections.ArrayList listServerNames = new System.Collections.ArrayList();

     bool bFind = false;
     string serverName = "";
     for (int serverIndex = 0; serverIndex < serverCount; serverIndex++)
     {
         if (SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice) != 0)
         {
             serverName = SapManager.GetServerName(serverIndex);
             listServerNames.Add(serverName);
             GenieIndex++;
             bFind = true;
         }
     }

     int count = 1;
     string deviceName = "";
     foreach (string sName in listServerNames)
     {
         deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice, 0);
         count++;
     }

     sCameraName = serverName;
     nIndex = GenieIndex;

     return bFind;
 }

 private bool CreateNewObjects()//初始化设备
 {
     string name;
     int index;
     bool success = GetCameraInfo(out name, out index);
     if (!success)
     {
         MessageBox.Show("Get camera info failed!");
         return false;
     }

     m_ServerLocation = new SapLocation(name, 0);

     // 创建采集设备
     m_AcqDevice = new SapAcqDevice(m_ServerLocation);
     // 创建颜色转换对象
   
     if (!m_AcqDevice.Create())
     {
         DestroyObjects();
         DisposeObjects();
         return false;
     }
     
     // 创建缓存对象
     SapBuffer.MemoryType memoryType = SapBuffer.MemoryType.ScatterGather;
     if (!SapBuffer.IsBufferTypeSupported(m_ServerLocation, memoryType))
     {
         memoryType = SapBuffer.MemoryType.ScatterGatherPhysical;
     }
     m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, memoryType);
     if (!m_Buffers.Create())
     {
         DestroyObjects();
         DisposeObjects();
         return false;
     }

     btn_getValue_Click(null, null);

     // 创建采集到缓冲区的对象
     m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers);
     m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify);
     m_Xfer.XferNotifyContext = this;
     m_Xfer.Pairs[0].EventType = SapXferPair.XferEventType.EndOfFrame;
     m_Xfer.Pairs[0].Cycle = SapXferPair.CycleMode.NextWithTrash;
     if (m_Xfer.Pairs[0].Cycle != SapXferPair.CycleMode.NextWithTrash)
     {
         DestroyObjects();
         DisposeObjects();
         return false;
     }
     if (!m_Xfer.Create())
     {
         DestroyObjects();
         DisposeObjects();
         return false;
     }

     return true;
 }


private void btn_getValue_Click(object sender, EventArgs e)//获取相机属性的值
{
    string deviceModelName;
    string deviceUserId;
    string pixelFormat;
    string triggerMode;

    double acquisitionLineRate; //行频和曝光时间不能设置为int类型
    double exposureTime;
    double gain;
    int width;
    int height;
    int sensorWidth;
    int sensorHeight;
    
    m_AcqDevice.GetFeatureValue("DeviceModelName", out deviceModelName);
    m_AcqDevice.GetFeatureValue("DeviceUserID", out deviceUserId);
    m_AcqDevice.GetFeatureValue("PixelFormat", out pixelFormat); 
    m_AcqDevice.GetFeatureValue("TriggerMode", out triggerMode); 
    m_AcqDevice.GetFeatureValue("ExposureTime", out exposureTime); 
    m_AcqDevice.GetFeatureValue("Gain", out gain); 
    m_AcqDevice.GetFeatureValue("Width", out width); 
    m_AcqDevice.GetFeatureValue("Height", out height);
    m_AcqDevice.GetFeatureValue("SensorWidth", out sensorWidth);
    m_AcqDevice.GetFeatureValue("SensorHeight", out sensorHeight);
    
}

 private void DestroyObjects()//销毁采集对象
 {
     if (m_Xfer != null && m_Xfer.Initialized)
         m_Xfer.Destroy();
     if (m_Buffers != null && m_Buffers.Initialized)
         m_Buffers.Destroy();
     if (m_AcqDevice != null && m_AcqDevice.Initialized)
         m_AcqDevice.Destroy();
 }

 private void DisposeObjects()//销毁缓存对象
 {
     if (m_Xfer != null)
     {
         m_Xfer.Dispose();
         m_Xfer = null;
     }
     if (m_Buffers != null)
     {
         m_Buffers.Dispose();
         m_Buffers = null;
     }
     if (m_AcqDevice != null)
     {
         m_AcqDevice.Dispose();
         m_AcqDevice = null;
     }
 }

获取相机最大最小值与显示采集实时帧率

private double GetMaxValue(string featureName)
{
    SapFeature feature = new SapFeature(m_ServerLocation);
    if (!feature.Create())
        return -1;
    if (!m_AcqDevice.GetFeatureInfo(featureName, feature))
        return -1;
    double maxValue = 0;
    if (!feature.GetValueMax(out maxValue))
        return -1;
    return maxValue;
}

private double GetMinValue(string featureName)
{
    SapFeature feature = new SapFeature(m_ServerLocation);
    if (!feature.Create())
        return -1;
    if (!m_AcqDevice.GetFeatureInfo(featureName, feature))
        return -1;
    int minValue = 0;
    if (!feature.GetValueMin(out minValue))
        return -1;
    return minValue;
}

private void UpdateFrameRate()//实时帧率
{
    if (m_Xfer.UpdateFrameRateStatistics())
    {
        float framerate = 0.0f;
        SapXferFrameRateInfo stats = m_Xfer.FrameRateStatistics;

        if (stats.IsBufferFrameRateAvailable)
            framerate = stats.BufferFrameRate;
        else if (stats.IsLiveFrameRateAvailable && !stats.IsLiveFrameRateStalled)
            framerate = stats.LiveFrameRate;

        m_Buffers.FrameRate = framerate;
    }
}

单次采集

private void btn_Snap_Click(object sender, EventArgs e)
{
    m_Xfer.Snap();
}

连续采集

 private void btn_grab_Click(object sender, EventArgs e)
 {
     m_Xfer.Grab();
 }

停止采集

 private void btn_freeze_Click(object sender, EventArgs e)
{
    m_Xfer.Freeze();
}

获取图像,不清楚得到的数据为什么是Mono8格式,需用转换方法,我在方法中使用了OpenCV将图像转换为BayerBG2RGB格式,然后通过MatToHImage方法将Mat对象转换为Hoject对象后使用Halcon显示图像

HObject ImageTemp1;
Mat imageOne =new Mat();
 void m_Xfer_XferNotify(object sender, SapXferNotifyEventArgs argsNotify)    
 {
     try
     {
         //首先需判断此帧是否是废弃帧,若是则立即返回,等待下一帧(但这句话似乎有时候m_Xfer.Snap(n)时会导致丢帧,可以注释掉试试)
         if (argsNotify.Trash) return;
         IntPtr addr;
         m_Buffers.GetAddress(out addr);
         int count = m_Buffers.Count;
         double rate = m_Buffers.FrameRate;
         HTuple height = m_Buffers.Height;
         int pixd = m_Buffers.PixelDepth;
         Mat frame = new Mat(m_Buffers.Height, m_Buffers.Width, MatType.CV_8UC1, addr);//Opencv将黑白转为RGB
         Cv2.CvtColor(frame, imageOne, ColorConversionCodes.BayerBG2RGB);
          ImageTemp1 = MatToHImage(imageOne);
         //HObject ImageTemp;
         //显示实时帧率
         UpdateFrameRate();
         textBox2.BeginInvoke(new Action(() => { textBox2.Text = m_Buffers.FrameRate.ToString(); }));
         if (ImageTemp1.IsInitialized() && ImageTemp2.IsInitialized() && ImageTemp3.IsInitialized() && ImageTemp4.IsInitialized())
         {
             hWindowControl1.HalconWindow.SetPart(0, 0, (int)height, m_Buffers.Width);
             HOperatorSet.DispObj(ImageTemp1, hWindowControl1.HalconWindow);
         }
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message);
     }
     finally
     {
         ImageTemp1.Dispose();
     }
 }
//转换方法
public HObject MatToHImage(Mat mImage)
{
    try
    {
        HObject hImage;
        int matChannels = 0;   // 通道数
        Type matType = null;
        int width, height;   // 宽,高
        width = height = 0;  // 宽,高初始化

        // 获取通道数
        matChannels = mImage.Channels();
        if (matChannels == 0)
        {
            return null;
        }
        if (matChannels == 1)        // 单通道
        {
            IntPtr ptr;      // 灰度图通道
            Mat[] mats = mImage.Split();

            // 改自:Mat.GetImagePointer1(mImage, out ptr, out matType, out width, out height);    // ptr=2157902018096    cType=byte    width=830    height=822
            ptr = mats[0].Data;          // 取灰度图值
            matType = mImage.GetType();  // byte
            height = mImage.Rows;        // 高
            width = mImage.Cols;         // 宽

            // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, newScalar(0));
            byte[] dataGrayScaleImage = new byte[width * height];      //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);

            unsafe
            {
                fixed (byte* ptrdata = dataGrayScaleImage)
                {

                    #region 按行复制
                    CopyMemory((IntPtr)ptrdata, new IntPtr((long)ptr), width * height);
                    HOperatorSet.GenImage1(out hImage, "byte", width, height, (IntPtr)ptrdata);
                    #endregion
                }
            }
            return hImage;
        }
        else if (matChannels == 3)   // 三通道
        {
            IntPtr ptrRed;    // R通道图
            IntPtr ptrGreen;  // G通道图
            IntPtr ptrBlue;   // B通道图
            Mat[] mats = mImage.Split();

            ptrRed = mats[0].Data;    // 取R通道值
            ptrGreen = mats[1].Data;  // 取G通道值
            ptrBlue = mats[2].Data;   // 取B通道值
            matType = mImage.GetType();  // 类型
            height = mImage.Rows;        // 高
            width = mImage.Cols;         // 宽

            // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0));
            byte[] dataRed = new byte[width * height];      //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
            byte[] dataGreen = new byte[width * height];
            byte[] dataBlue = new byte[width * height];

            unsafe
            {
                fixed (byte* ptrdataRed = dataRed, ptrdataGreen = dataGreen, ptrdataBlue = dataBlue)
                {

                    #region 按行复制
                    CopyMemory((IntPtr)ptrdataRed, new IntPtr((long)ptrRed), width * height);        // 复制R通道
                    CopyMemory((IntPtr)ptrdataGreen, new IntPtr((long)ptrGreen), width * height);    // 复制G通道
                    CopyMemory((IntPtr)ptrdataBlue, new IntPtr((long)ptrBlue), width * height);      // 复制B通道
                    HOperatorSet.GenImage3(out hImage, "byte", width, height, (IntPtr)ptrdataRed, (IntPtr)ptrdataGreen, (IntPtr)ptrdataBlue);   // 合成
                    #endregion
                }
            }
            return hImage;
        }
        else
        {
            return null;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }

}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: dalsa相机采集显示程序是一款用于控制和管理dalsa相机设备的软件应用程序。dalsa相机采集显示程序支持连接dalsa相机设备,并提供实时的采集显示和处理图像的功能。用户可以通过该程序来设置dalsa相机的参数、调节曝光时间、帧率、增益等,以获得更好的图像质量。同时,该程序提供了多种图像处理算法选择,供用户在采集后进行图像处理,例如颜色滤波、图像增强、直方图均衡化等,用于改善图像质量或提取特定信息。此外,dalsa相机采集显示程序还支持视频流录制和截图功能。录制的视频可以保存为AVI文件格式,截取的图像可以保存为BMP、JPEG或PNG等格式的图像文件。总之,dalsa相机采集显示程序提供数据采集、实时图像显示和灵活的图像处理功能,适用于各种工业、科研和医疗等不同领域的应用需求。 ### 回答2: dalsa相机采集显示程序是一个用于控制和操作dalsa相机的软件程序。这个程序允许用户对相机进行设置,如采集模式、曝光时间、增益等,并可以实时显示相机采集到的图像。用户可以在图像中进行测量、分析和处理,这对于科学研究、工业质量控制等领域非常有用。 dalsa相机采集显示程序具有用户友好的界面,使得用户可以方便地进行参数设置和图像处理。该程序还支持多种数据格式,如RAW、BMP、TIF等,可以保存和导出图像数据以进行后续分析或打印。 此外,该程序还具有一些高级功能,如自动对焦、畸变校正、直方图均衡化等。这些功能可以提高相机的性能和图像质量,使用户可以更好地满足各种应用需求。 总之,dalsa相机采集显示程序是一个功能强大、易于使用的软件工具,可以帮助用户有效地控制和操作dalsa相机,并实时获取和处理图像数据。 ### 回答3: Dalsa相机采集显示程序是一种专门用于管理Dalsa相机采集数据和显示图像的应用程序。该程序基于Dalsa相机的软件开发工具包(SDK)开发,可以在Windows和Linux操作系统上运行。 使用Dalsa相机采集显示程序,用户可以方便地控制相机的参数和配置,进行采集、处理和显示图像。该程序可以自动检测已连接的Dalsa相机并列出相机属性,允许用户设置曝光时间、增益、帧率等参数,并可以在实时采集数据时直接显示图像。此外,该程序还支持图像的基本处理功能,如调整亮度、对比度、伽马校正等。 除此之外,Dalsa相机采集显示程序还支持高级功能,例如时间同步采集、多相机同步采集、区域感兴趣(ROI)采集等,使得用户在复杂应用场景下能够更加灵活地应用Dalsa相机。 总之,Dalsa相机采集显示程序是一种功能齐全、易于使用的软件工具,旨在帮助用户更加高效地管理并处理Dalsa相机采集图像数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值