You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
13 KiB
C#
412 lines
13 KiB
C#
using GxIAPINET;
|
|
using HalconDotNet;
|
|
using Rs.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Rs.Cameras
|
|
{
|
|
|
|
public class DaHengCameras
|
|
{
|
|
private static DaHengCameras instance;
|
|
public static DaHengCameras Instance
|
|
{
|
|
get
|
|
{
|
|
if (instance == null)
|
|
instance = new DaHengCameras();
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
|
|
private DaHengCameras()
|
|
{
|
|
}
|
|
|
|
List<DaHengCameraInfo> cameraInfos = new List<DaHengCameraInfo>();
|
|
|
|
public List<DaHengCameraInfo> Init()
|
|
{
|
|
IGXFactory.GetInstance().Init();
|
|
List<IGXDeviceInfo> infos = new List<IGXDeviceInfo>();
|
|
IGXFactory.GetInstance().UpdateAllDeviceList(1000, infos);
|
|
if(infos!=null && infos.Count>0)
|
|
{
|
|
foreach (IGXDeviceInfo devInfo in infos)
|
|
{
|
|
try
|
|
{
|
|
string userID = string.Empty;
|
|
userID = devInfo.GetUserID();
|
|
if(!string.IsNullOrEmpty(userID))
|
|
{
|
|
IGXDevice dev = IGXFactory.GetInstance().OpenDeviceByUserID(userID, GX_ACCESS_MODE.GX_ACCESS_EXCLUSIVE);
|
|
IGXFeatureControl featureControl = dev.GetRemoteFeatureControl();
|
|
IGXStream stream = dev.OpenStream(0);
|
|
IGXFeatureControl streamFeatureControl = stream.GetFeatureControl();
|
|
|
|
GX_DEVICE_CLASS_LIST objDeviceClass = dev.GetDeviceInfo().GetDeviceClass();
|
|
if (GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV == objDeviceClass)
|
|
{
|
|
// 判断设备是否支持流通道数据包功能
|
|
if (true == featureControl.IsImplemented("GevSCPSPacketSize"))
|
|
{
|
|
// 获取当前网络环境的最优包长值
|
|
uint nPacketSize = stream.GetOptimalPacketSize();
|
|
// 将最优包长值设置为当前设备的流通道包长值
|
|
featureControl.GetIntFeature("GevSCPSPacketSize").SetValue(nPacketSize);
|
|
}
|
|
}
|
|
featureControl.GetEnumFeature("AcquisitionMode").SetValue("Continuous");
|
|
//m_objIGXStreamFeatureControl = stream.GetFeatureControl();
|
|
DaHengCameraInfo camInfo = new DaHengCameraInfo(userID, dev, featureControl, stream, streamFeatureControl);
|
|
cameraInfos.Add(camInfo);
|
|
camInfo.SetTrigger(ETriggerSource.Line0);
|
|
camInfo.SetExposure(50);
|
|
camInfo.SetGain(10);
|
|
camInfo.StartGrabbing();
|
|
MessageQueue.Instance.Insert($"Camera {userID} opened success");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageQueue.Instance.Warn(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogHelper.Debug($"cann't find camera");
|
|
}
|
|
return cameraInfos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据相机名称获取相机
|
|
/// </summary>
|
|
/// <param name="cameraName"></param>
|
|
/// <returns></returns>
|
|
public DaHengCameraInfo GetCameraInfo(string cameraName)
|
|
{
|
|
return cameraInfos.Where(c => c.CameraName == cameraName).FirstOrDefault();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取所有的相机
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public List<DaHengCameraInfo> GetAllCameras()
|
|
{
|
|
return cameraInfos;
|
|
}
|
|
|
|
public void Deinit()
|
|
{
|
|
foreach (DaHengCameraInfo ci in cameraInfos)
|
|
{
|
|
ci.Deinit();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 相机信息
|
|
/// </summary>
|
|
public class DaHengCameraInfo
|
|
{
|
|
public IGXDevice Camera { get; set; }
|
|
/// <summary>
|
|
/// 属性控制
|
|
/// </summary>
|
|
IGXFeatureControl featureControl;
|
|
IGXStream stream;
|
|
IGXFeatureControl streamFeatureControl;
|
|
public string CameraName { get; set; }
|
|
|
|
public int Index { get; set; }
|
|
|
|
private List<TakePicResult> Images;
|
|
|
|
public event Action<TakePicResult> OnImageLoaded;
|
|
|
|
|
|
|
|
public DaHengCameraInfo(string userID,IGXDevice _dev, IGXFeatureControl _featureControl, IGXStream _stream, IGXFeatureControl _streamFeatureControl)
|
|
{
|
|
CameraName = userID;
|
|
this.Camera = _dev;
|
|
this.featureControl = _featureControl;
|
|
this.stream = _stream;
|
|
streamFeatureControl = _streamFeatureControl;
|
|
Images = new List<TakePicResult>();
|
|
}
|
|
|
|
public void Deinit()
|
|
{
|
|
if (Camera != null)
|
|
{
|
|
featureControl.GetCommandFeature("AcquisitionStop").Execute();
|
|
stream.StopGrab();
|
|
//注销采集回调函数
|
|
// m_objIGXStream.UnregisterCaptureCallback();
|
|
stream.Close();
|
|
stream = null;
|
|
featureControl = null;
|
|
Camera.Close();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 清除内存中的图片
|
|
/// </summary>
|
|
public void ClearImage()
|
|
{
|
|
lock (this)
|
|
{
|
|
if (Images != null)
|
|
{
|
|
Images.Clear();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取图
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public void Grab()
|
|
{
|
|
if (Camera != null)
|
|
{
|
|
featureControl.GetCommandFeature("TriggerSoftware").Execute();
|
|
}
|
|
}
|
|
|
|
public void StartGrabbing()
|
|
{
|
|
if (Camera != null && streamFeatureControl!=null && stream!=null)
|
|
{
|
|
streamFeatureControl.GetEnumFeature("StreamBufferHandlingMode").SetValue("OldestFirst");
|
|
stream.RegisterCaptureCallback(this, CaptureCallbackPro);
|
|
stream.StartGrab();
|
|
featureControl.GetCommandFeature("AcquisitionStart").Execute();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 回调函数,用于获取图像信息和显示图像
|
|
/// </summary>
|
|
/// <param name="obj">用户自定义传入参数</param>
|
|
/// <param name="objIFrameData">图像信息对象</param>
|
|
private void CaptureCallbackPro(object objUserParam, IFrameData objIFrameData)
|
|
{
|
|
try
|
|
{
|
|
TakePicResult result = new TakePicResult();
|
|
LogHelper.Debug($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}-> 收到相机数据");
|
|
result.TakeTime = DateTime.Now;
|
|
//string msg = $"{trayNum},{rowNum},{slotNum},{dt.ToString("yyyy-MM-dd HH:mm:ss fff")},{GetTimeStamp(dt,true)}\r\n";
|
|
//File.AppendAllText("d://temp/test.csv", msg);
|
|
HObject image;
|
|
HOperatorSet.GenEmptyObj(out image);
|
|
image.Dispose();
|
|
HOperatorSet.GenImage1(out image, "byte", objIFrameData.GetWidth(), objIFrameData.GetHeight(), objIFrameData.GetBuffer());
|
|
result.SourceImage = image;
|
|
//HOperatorSet.WriteImage(image, "bmp", 0, $"d://temp//{trayNum}_{rowNum}_{slotNum}");
|
|
//HOperatorSet.WriteImage(image, "tiff",0, "d://d");
|
|
AddImage(result);
|
|
//GxSingleCam objGxSingleCam = objUserParam as GxSingleCam;
|
|
//objGxSingleCam.ImageShowAndSave(objIFrameData);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
public void AddImage(TakePicResult result)
|
|
{
|
|
lock (this)
|
|
{
|
|
Images.Add(result);
|
|
OnImageLoaded?.Invoke(result);
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置曝光时间
|
|
/// </summary>
|
|
/// <param name="timer"></param>
|
|
/// <returns></returns>
|
|
public void SetExposure(double timer)
|
|
{
|
|
if (Camera != null && featureControl != null)
|
|
{
|
|
featureControl.GetFloatFeature("ExposureTime").SetValue(timer);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置相机增益
|
|
/// </summary>
|
|
/// <param name="camName"></param>
|
|
/// <param name="gain"></param>
|
|
/// <returns></returns>
|
|
public void SetGain(double gain)
|
|
{
|
|
if (Camera != null && featureControl != null)
|
|
{
|
|
featureControl.GetFloatFeature("Gain").SetValue(gain);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置相机的触发模式
|
|
/// </summary>
|
|
/// <param name="camName"></param>
|
|
/// <param name="triggerSource"></param>
|
|
/// <returns></returns>
|
|
public void SetTrigger(ETriggerSource triggerSource = ETriggerSource.Line0)
|
|
{
|
|
if (Camera != null)
|
|
{
|
|
if (triggerSource == ETriggerSource.Line0)
|
|
{
|
|
featureControl.GetEnumFeature("TriggerMode").SetValue("On");
|
|
featureControl.GetEnumFeature("TriggerSource").SetValue(ETriggerSource.Line0.ToString());
|
|
featureControl.GetEnumFeature("TriggerActivation").SetValue("RisingEdge");
|
|
}
|
|
else
|
|
{
|
|
featureControl.GetEnumFeature("TriggerMode").SetValue("On");
|
|
featureControl.GetEnumFeature("TriggerSource").SetValue(ETriggerSource.Software.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置相机XY方向是否反转
|
|
/// </summary>
|
|
/// <param name="camName"></param>
|
|
/// <param name="dir"></param>
|
|
/// <param name="reverse"></param>
|
|
/// <returns></returns>
|
|
public int SetReverse(EDir dir = EDir.X, bool reverse = false)
|
|
{
|
|
if (Camera != null)
|
|
{
|
|
if (dir == EDir.X)
|
|
{
|
|
featureControl.GetBoolFeature("ReverseX").SetValue(reverse);
|
|
}
|
|
else
|
|
{
|
|
featureControl.GetBoolFeature("ReverseY").SetValue(reverse);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取最后一张图片
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public TakePicResult GetLastImage()
|
|
{
|
|
lock (this)
|
|
{
|
|
if (Images != null && Images.Count > 0)
|
|
{
|
|
return Images[Images.Count - 1];
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取所有的图片
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public List<TakePicResult> GetAllImages()
|
|
{
|
|
lock (this)
|
|
{
|
|
return Images;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取图片数量
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public int GetImageCount()
|
|
{
|
|
lock (this)
|
|
{
|
|
if (Images != null && Images.Count > 0)
|
|
{
|
|
return Images.Count;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static long GetTimeStamp(DateTime dt,bool ismilliseconds = false)
|
|
{
|
|
//时间戳 毫秒值
|
|
//var time = new DateTimeOffset(DateTime.UtcNow);
|
|
var time = new DateTimeOffset(dt);
|
|
var timestamp = 0L;
|
|
if (ismilliseconds)
|
|
{
|
|
timestamp = time.ToUnixTimeMilliseconds();
|
|
}
|
|
else
|
|
timestamp = time.ToUnixTimeSeconds();
|
|
|
|
return timestamp;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取图结果类
|
|
/// </summary>
|
|
public class TakePicResult
|
|
{
|
|
/// <summary>
|
|
/// 原图
|
|
/// </summary>
|
|
public HObject SourceImage { get; set; }
|
|
/// <summary>
|
|
/// 相机返回图片时间
|
|
/// </summary>
|
|
public DateTime TakeTime { get; set; }
|
|
/// <summary>
|
|
/// 二维码
|
|
/// </summary>
|
|
public string SN { get; set; }
|
|
public TakePicResult()
|
|
{
|
|
|
|
}
|
|
|
|
public TakePicResult(HObject sourceImage, DateTime takeTime)
|
|
{
|
|
SourceImage = sourceImage;
|
|
TakeTime = takeTime;
|
|
}
|
|
}
|
|
}
|