From 36f5fd3c5717d1499a0de5b4ea8dbcd7ccd4382b Mon Sep 17 00:00:00 2001 From: lhiven Date: Fri, 13 Sep 2024 14:35:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E7=9A=84=E7=9B=B8?= =?UTF-8?q?=E6=9C=BA=E5=BA=93=E4=BB=A5=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E7=9B=B8=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Rs.Cameras/HikCamera.cs | 467 ++++++++++++++++++++++++++ Rs.Cameras/Properties/AssemblyInfo.cs | 36 ++ Rs.Cameras/Rs.Cameras.csproj | 60 ++++ Rs.MotionPlat.sln | 6 + 4 files changed, 569 insertions(+) create mode 100644 Rs.Cameras/HikCamera.cs create mode 100644 Rs.Cameras/Properties/AssemblyInfo.cs create mode 100644 Rs.Cameras/Rs.Cameras.csproj diff --git a/Rs.Cameras/HikCamera.cs b/Rs.Cameras/HikCamera.cs new file mode 100644 index 0000000..800ee79 --- /dev/null +++ b/Rs.Cameras/HikCamera.cs @@ -0,0 +1,467 @@ +using HalconDotNet; +using MvCamCtrl.NET; +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 enum EDir + { + X, + Y + } + + public enum ETriggerSource + { + /// + /// 硬触发 + /// + Line0, + /// + /// 软触发 + /// + Software + } + public class HikCameras + { + private static HikCameras instance; + public static HikCameras Instance + { + get + { + if (instance == null) + instance = new HikCameras(); + return instance; + } + } + + + private HikCameras() + { + cbImage = new MyCamera.cbOutputExdelegate(ImageCallBack); + } + + MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList; + int apiResult = 0; + MyCamera.cbOutputExdelegate cbImage; + IntPtr m_BufForDriver = IntPtr.Zero; + List cameraInfos = new List(); + + private void ImageCallBack(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser) + { + HObject image; + HOperatorSet.GenEmptyObj(out image); + image.Dispose(); + int nIndex = (int)pUser; + HOperatorSet.GenImage1(out image, "byte", pFrameInfo.nWidth, pFrameInfo.nHeight, pData); + CameraInfo ci = GetCameraInfo(nIndex); + if (ci != null) + { + ci.AddImage(image); + } + } + + public List Init() + { + int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList); + if (nRet != 0) + { + LogHelper.Debug($"MV_CC_EnumDevices_NET ret = {nRet}"); + //未找到任何相机 + return null; + } + else if (m_pDeviceList.nDeviceNum>0) + { + for (int i = 0; i < m_pDeviceList.nDeviceNum; i++) + { + string cameraInfo = string.Empty; + ///获取相机信息 + MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO)); + if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) + { + MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); + if(!string.IsNullOrEmpty(gigeInfo.chUserDefinedName)) + { + cameraInfo = gigeInfo.chUserDefinedName; + }// gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")"; + else + { + cameraInfo = gigeInfo.chSerialNumber; + } + } + else if (device.nTLayerType == MyCamera.MV_USB_DEVICE) + { + MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO)); + if (!string.IsNullOrEmpty(usbInfo.chUserDefinedName)) + { + cameraInfo = usbInfo.chUserDefinedName; + } + else + { + cameraInfo = usbInfo.chSerialNumber; + } + } + + MyCamera camera = new MyCamera(); + apiResult = camera.MV_CC_CreateDevice_NET(ref device); + if (apiResult != 0) + { + LogHelper.Debug($"MV_CC_CreateDevice_NET ret = {apiResult}"); + //MV_CC_CreateDevice_NET fail; + //return ECameraErrorCode.CreateDeviceFail; + continue; + } + apiResult = camera.MV_CC_OpenDevice_NET(); + if (apiResult != 0) + { + LogHelper.Debug($"MV_CC_OpenDevice_NET ret = {apiResult}"); + //return ECameraErrorCode.OpenDeviceFail; + continue; + } + if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) + { + int nPacketSize = camera.MV_CC_GetOptimalPacketSize_NET(); + if (nPacketSize > 0) + { + nRet = camera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize); + if (nRet != MyCamera.MV_OK) + { + LogHelper.Debug($"MV_CC_SetIntValue_NET GevSCPSPacketSize ret = {apiResult}"); + //return ECameraErrorCode.GevSCPSPacketSizeFail; + continue; + } + } + else + { + //return ECameraErrorCode.GevSCPSPacketSizeFail; + continue; + } + } + apiResult = camera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); + if (nRet != MyCamera.MV_OK) + { + LogHelper.Debug($"MV_CC_SetIntValue_NET TriggerMode ret = {apiResult}"); + //return ECameraErrorCode.SetTriggerModeFail; + continue; + } + apiResult = camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); + if (nRet != MyCamera.MV_OK) + { + LogHelper.Debug($"MV_CC_SetIntValue_NET TriggerSource ret = {apiResult}"); + //return ECameraErrorCode.SetTriggerSourceFail; + continue; + } + apiResult = camera.MV_CC_RegisterImageCallBackEx_NET(cbImage, (IntPtr)i); + if (apiResult != 0) + { + LogHelper.Debug($"MV_CC_RegisterImageCallBackEx_NET ret = {apiResult}"); + continue; + //return ECameraErrorCode.RegisterImageCallBackExFail; + } + CameraInfo ci = new CameraInfo(); + ci.Camera = camera; + ci.CameraName = cameraInfo; + ci.Index = i; + cameraInfos.Add(ci); + LogHelper.Debug($"Find camera {cameraInfo}"); + } + + } + else + { + //未找到任何相机 + return null; + } + return cameraInfos; + } + + /// + /// 根据相机名称获取相机 + /// + /// + /// + public CameraInfo GetCameraInfo(string cameraName) + { + return cameraInfos.Where(c=>c.CameraName==cameraName).FirstOrDefault(); + } + + /// + /// 根据索引获取相机 + /// + /// + /// + private CameraInfo GetCameraInfo(int index) + { + return cameraInfos.Where(c => c.Index == index).FirstOrDefault(); + } + + /// + /// 获取所有的相机 + /// + /// + public List GetAllCameras() + { + return cameraInfos; + } + + public void Deinit() + { + foreach (CameraInfo ci in cameraInfos) + { + ci.Deinit(); + } + } + } + + /// + /// 相机信息 + /// + public class CameraInfo + { + public MyCamera Camera { get; set; } + public string CameraName { get; set; } + + public int Index { get; set; } + + private List Images; + + int apiResult = -1; + + public CameraInfo() + { + Images = new List(); + } + + public void Deinit() + { + if(Camera != null) + { + Camera.MV_CC_CloseDevice_NET(); + Camera.MV_CC_DestroyDevice_NET(); + } + } + /// + /// 清除内存中的图片 + /// + public void ClearImage() + { + lock(this) + { + if (Images != null) + { + Images.Clear(); + } + } + + } + + /// + /// 取图 + /// + /// + public int Grab() + { + if (Camera != null) + return Camera.MV_CC_SetCommandValue_NET("TriggerSoftware"); + return -1; + } + + public int StartGrabbing() + { + if (Camera != null) + return Camera.MV_CC_StartGrabbing_NET(); + return -1; + } + + public void AddImage(HObject image) + { + lock (this) + { + Images.Add(image); + } + + } + + /// + /// 设置曝光时间 + /// + /// + /// + public int SetExposure(float timer) + { + if (Camera != null) + { + apiResult = Camera.MV_CC_SetEnumValue_NET("ExposureAuto", 0); + if (apiResult != 0) + { + + return apiResult; + } + apiResult = Camera.MV_CC_SetFloatValue_NET("ExposureTime", timer); + if (apiResult != 0) + { + return apiResult; + } + } + else + { + return -1; + } + return 0; + } + + /// + /// 设置相机增益 + /// + /// + /// + /// + public int SetGain(float gain) + { + if (Camera != null) + { + apiResult = Camera.MV_CC_SetEnumValue_NET("GainAuto", 0); + if (apiResult != 0) + { + return apiResult; + } + apiResult = Camera.MV_CC_SetFloatValue_NET("Gain", gain); + if (apiResult != 0) + { + return apiResult; + } + } + else + { + return -1; + } + return 0; + } + + /// + /// 设置相机的触发模式 + /// + /// + /// + /// + public int SetTrigger(ETriggerSource triggerSource = ETriggerSource.Line0) + { + if(Camera!=null) + { + if (triggerSource == ETriggerSource.Line0) + { + apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); + if (apiResult != 0) + { + apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerActivation", 0);//设置上升沿触发 + if (apiResult != 0) + { + return apiResult; + } + } + else + { + return apiResult; + } + } + else + { + apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); + if (apiResult != 0) + { + return apiResult; + } + } + } + else + { + return -1; + } + return 0; + } + + /// + /// 设置相机XY方向是否反转 + /// + /// + /// + /// + /// + public int SetReverse(string camName, EDir dir = EDir.X, bool reverse = false) + { + if(Camera!=null) + { + if (dir == EDir.X) + { + apiResult = Camera.MV_CC_SetBoolValue_NET("ReverseX", reverse); + if (apiResult != 0) + return apiResult; + } + else + { + apiResult = Camera.MV_CC_SetBoolValue_NET("ReverseY", reverse); + if (apiResult != 0) + return apiResult; + } + } + else + { + return -1; + } + return 0; + } + + /// + /// 获取最后一张图片 + /// + /// + public HObject GetLastImage() + { + lock (this) + { + if (Images != null && Images.Count > 0) + { + return Images[Images.Count - 1]; + } + return null; + } + } + + /// + /// 获取所有的图片 + /// + /// + public List GetAllImages() + { + lock (this) + { + return Images; + } + } + + /// + /// 获取图片数量 + /// + /// + public int GetImageCount() + { + lock (this) + { + if (Images != null && Images.Count > 0) + { + return Images.Count; + } + return 0; + } + } + } +} diff --git a/Rs.Cameras/Properties/AssemblyInfo.cs b/Rs.Cameras/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fc333b8 --- /dev/null +++ b/Rs.Cameras/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Rs.Cameras")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Rs.Cameras")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("971d93ff-fd34-4088-9591-c25147290d22")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Rs.Cameras/Rs.Cameras.csproj b/Rs.Cameras/Rs.Cameras.csproj new file mode 100644 index 0000000..d302df5 --- /dev/null +++ b/Rs.Cameras/Rs.Cameras.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {971D93FF-FD34-4088-9591-C25147290D22} + Library + Properties + Rs.Cameras + Rs.Cameras + v4.8 + 512 + true + + + true + full + false + ..\Rs.MotionPlat\bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\Rs.MotionPlat\bin\Debug\halcondotnet.dll + + + ..\Rs.MotionPlat\bin\Debug\MvCameraControl.Net.dll + + + + + + + + + + + + + + + + + {f6dbc74d-4a0b-4d50-9c79-2a5a1518849d} + Rs.Framework + + + + \ No newline at end of file diff --git a/Rs.MotionPlat.sln b/Rs.MotionPlat.sln index e1def4d..45cb0c6 100644 --- a/Rs.MotionPlat.sln +++ b/Rs.MotionPlat.sln @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rs.DataAccess", "Rs.DataAcc EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HWindow_Tool", "HWindow_Tool\HWindow_Tool.csproj", "{0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rs.Cameras", "Rs.Cameras\Rs.Cameras.csproj", "{971D93FF-FD34-4088-9591-C25147290D22}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -51,6 +53,10 @@ Global {0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU {0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Release|Any CPU.Build.0 = Release|Any CPU + {971D93FF-FD34-4088-9591-C25147290D22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {971D93FF-FD34-4088-9591-C25147290D22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {971D93FF-FD34-4088-9591-C25147290D22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {971D93FF-FD34-4088-9591-C25147290D22}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE