| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Drawing; |
| | | using System.Drawing.Imaging; |
| | | using System.Runtime.InteropServices; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using LB_SmartVisionCameraSDK.PHM6000; |
| | | using LB_VisionProcesses.Cameras; |
| | | using LB_SmartVisionCommon; |
| | | using LB_SmartVisionCameraDevice.PHM6000; |
| | | |
| | | namespace LB_VisionProcesses.Cameras.LBCameras |
| | | { |
| | | public class PHM6000Camera : BaseCamera |
| | | { |
| | | private IntPtr _cameraHandle = IntPtr.Zero; |
| | | private PHM6000SensorConfig _sensorConfig; |
| | | private AcquisitionCallbackZA _acquisitionCallback; |
| | | private AcquisitionCompletedCallback _acquisitionCompletedCallback; |
| | | private bool _isConnected = false; |
| | | |
| | | // å¾åç¼å² |
| | | private List<byte[]> _lineDataBuffer = new List<byte[]>(); |
| | | private readonly object _bufferLock = new object(); |
| | | private int _currentLineCount = 0; |
| | | |
| | | public PHM6000Camera() |
| | | { |
| | | Brand = CameraBrand.LBCamera; |
| | | _sensorConfig = new PHM6000SensorConfig(); |
| | | } |
| | | |
| | | #region ICamera Implementation |
| | | |
| | | public override bool InitDevice(string sn, object handle = null) |
| | | { |
| | | try |
| | | { |
| | | SN = sn; |
| | | _cameraHandle = PHM6000Profiler.CreateCameraEntry(); |
| | | if (_cameraHandle == IntPtr.Zero) return false; |
| | | |
| | | // ä¼å
ä»é
ç½®å è½½ IPï¼å¦æ sn æ¯ IP æ ¼å¼åè¦ç |
| | | string ip = "192.168.0.10"; |
| | | if (System.Net.IPAddress.TryParse(sn, out _)) ip = sn; |
| | | |
| | | int port = 32001; |
| | | var addr = Encoding.ASCII.GetBytes(ip); |
| | | int result = PHM6000Profiler.ConnectToCamera(_cameraHandle, addr, port); |
| | | |
| | | if (result == 0) |
| | | { |
| | | _isConnected = true; |
| | | // å è½½ç¸æºå½ååæ°å° _sensorConfig |
| | | SyncConfigFromCamera(); |
| | | |
| | | // åå§ååè° |
| | | _acquisitionCallback = new AcquisitionCallbackZA(OnLineReceived); |
| | | _acquisitionCompletedCallback = new AcquisitionCompletedCallback(OnAcquisitionCompleted); |
| | | |
| | | PHM6000Profiler.SetAcquisitionCallbackZA(_cameraHandle, _acquisitionCallback, IntPtr.Zero); |
| | | PHM6000Profiler.RegisterAcquisitionCompletedCallback(_cameraHandle, _acquisitionCompletedCallback, IntPtr.Zero); |
| | | |
| | | return true; |
| | | } |
| | | } |
| | | catch (Exception ex) { AsyncLogHelper.Error($"PHM6000: InitDeviceå¼å¸¸ - {ex.Message}"); } |
| | | return false; |
| | | } |
| | | |
| | | public override bool CloseDevice() |
| | | { |
| | | if (_isConnected && _cameraHandle != IntPtr.Zero) |
| | | { |
| | | StopGrabbing(); |
| | | PHM6000Profiler.DestroyCameraEntry(_cameraHandle); |
| | | _cameraHandle = IntPtr.Zero; |
| | | _isConnected = false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public override List<string> GetListEnum() |
| | | { |
| | | List<string> cameraList = new List<string>(); |
| | | IntPtr tempHandle = PHM6000Profiler.CreateCameraEntry(); |
| | | int count = PHM6000Profiler.DiscoverCameras(tempHandle); |
| | | // ç®åï¼å®é
åºå¾ªç¯è·åè®¾å¤ IP |
| | | PHM6000Profiler.DestroyCameraEntry(tempHandle); |
| | | return cameraList; |
| | | } |
| | | |
| | | public override bool StartGrabbing() |
| | | { |
| | | if (!_isConnected) return false; |
| | | lock (_bufferLock) |
| | | { |
| | | _lineDataBuffer.Clear(); |
| | | _currentLineCount = 0; |
| | | } |
| | | |
| | | // 设置é鿍¡å¼ï¼1=æ«ææ¨¡å¼ï¼1=è¿ç»æ¨¡å¼ |
| | | PHM6000Profiler.SetAcquisitionMode(_cameraHandle, 1, 1); |
| | | int result = PHM6000Profiler.StartAcquisition(_cameraHandle, 0, 0, 0.0); |
| | | if (result == 0) |
| | | { |
| | | isGrabbing = true; |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | public override bool StopGrabbing() |
| | | { |
| | | if (!_isConnected) return true; |
| | | PHM6000Profiler.StopAcquisition(_cameraHandle); |
| | | isGrabbing = false; |
| | | return true; |
| | | } |
| | | |
| | | public override bool SoftTrigger() |
| | | { |
| | | // 线æ«ç¸æºé常ä¸éè¦ä¼ ç»è½¯è§¦åï¼ä½å¨æäºæ¨¡å¼ä¸å¯æ¨¡æ |
| | | return true; |
| | | } |
| | | |
| | | #region åæ°è®¾ç½®æ å° |
| | | |
| | | public override bool SetExpouseTime(double value) => SetParam(EnumNameId.ExposureTime, (float)value); |
| | | public override bool GetExpouseTime(out double value) { float v; bool r = GetParam(EnumNameId.ExposureTime, out v); value = v; return r; } |
| | | public override bool SetGain(double gain) => SetParam(EnumNameId.AnalogGain, (float)gain); |
| | | public override bool GetGain(out double gain) { float v; bool r = GetParam(EnumNameId.AnalogGain, out v); gain = v; return r; } |
| | | |
| | | // å
¶ä»æ¥å£å ä½å®ç° |
| | | public override bool SetTriggerMode(TriggerMode mode, TriggerSource triggerEnum = TriggerSource.Line0) => true; |
| | | public override bool GetTriggerMode(out TriggerMode mode, out TriggerSource source) { mode = TriggerMode.Off; source = TriggerSource.Software; return true; } |
| | | public override bool SetTriggerPolarity(TriggerPolarity polarity) => true; |
| | | public override bool GetTriggerPolarity(out TriggerPolarity polarity) { polarity = TriggerPolarity.RisingEdge; return true; } |
| | | public override bool SetTriggerFliter(double flitertime) => true; |
| | | public override bool GetTriggerFliter(out double flitertime) { flitertime = 0; return true; } |
| | | public override bool SetTriggerDelay(double delay) => true; |
| | | public override bool GetTriggerDelay(out double delay) { delay = 0; return true; } |
| | | public override bool SetLineMode(IOLines line, LineMode mode) => true; |
| | | public override bool SetLineStatus(IOLines line, LineStatus linestatus) => true; |
| | | public override bool GetLineStatus(IOLines line, out LineStatus lineStatus) { lineStatus = LineStatus.Low; return true; } |
| | | public override bool AutoBalanceWhite() => true; |
| | | |
| | | public PHM6000SensorConfig GetSensorConfig() |
| | | { |
| | | SyncConfigFromCamera(); |
| | | return _sensorConfig; |
| | | } |
| | | |
| | | public void UpdateSensorConfig(PHM6000SensorConfig config) |
| | | { |
| | | _sensorConfig = config; |
| | | // ç®å示ä¾ï¼è®¾ç½®æå
åå¢ç |
| | | SetExpouseTime(config.ExposureTime); |
| | | SetGain((double)config.AnalogGain); |
| | | // æ´å¤åæ°åæ¥é»è¾åºå¨æ¤å¤å®ç° |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #endregion |
| | | |
| | | #region Private Callback & Helpers |
| | | |
| | | private void OnLineReceived(IntPtr pInstance, IntPtr buffer, int points) |
| | | { |
| | | // 宿¶åè°å¤çï¼ç´¯ç§¯è¡æ°æ® |
| | | if (!isGrabbing) return; |
| | | |
| | | int lineSize = points * Marshal.SizeOf(typeof(LBPointZA)); |
| | | byte[] lineData = new byte[lineSize]; |
| | | Marshal.Copy(buffer, lineData, 0, lineSize); |
| | | |
| | | lock (_bufferLock) |
| | | { |
| | | _lineDataBuffer.Add(lineData); |
| | | _currentLineCount++; |
| | | } |
| | | } |
| | | |
| | | private void OnAcquisitionCompleted(IntPtr pInstance, int nOption) |
| | | { |
| | | // nOption: 0=䏿¹æ°æ®ç»æ, 1=å
¨é¨å®æ, 2=ç¹äºå°±ç»ª |
| | | // æ ¹æ®éæ±åæ´ï¼æä»¬åªå¤ç亮度å¾ãOption 1 æ 0 表示 2D æ°æ®å°±ç»ªã |
| | | if (nOption == 1 || nOption == 0) |
| | | { |
| | | GenerateIntensityMap(); |
| | | } |
| | | } |
| | | |
| | | private void GenerateIntensityMap() |
| | | { |
| | | if (_cameraHandle == IntPtr.Zero) return; |
| | | |
| | | int width = 0; |
| | | int height = 0; |
| | | |
| | | // ç´æ¥ä» SDK è·ååå¹¶åçå¼ºåº¦æ°æ®æé (unsigned char*) |
| | | IntPtr pIntensity = PHM6000Profiler.GetIntensityData(_cameraHandle, ref width, ref height); |
| | | |
| | | if (pIntensity == IntPtr.Zero || width <= 0 || height <= 0) return; |
| | | |
| | | try |
| | | { |
| | | Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); |
| | | |
| | | // 设置ç°åº¦è°è²æ¿ |
| | | ColorPalette palette = bmp.Palette; |
| | | for (int i = 0; i < 256; i++) palette.Entries[i] = Color.FromArgb(i, i, i); |
| | | bmp.Palette = palette; |
| | | |
| | | BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); |
| | | |
| | | // 髿§è½å
åæ·è´ |
| | | int size = width * height; |
| | | byte[] managedData = new byte[size]; |
| | | Marshal.Copy(pIntensity, managedData, 0, size); |
| | | Marshal.Copy(managedData, 0, bmpData.Scan0, size); |
| | | |
| | | bmp.UnlockBits(bmpData); |
| | | |
| | | // 触åäºä»¶éç¥ UI æ´æ°äº®åº¦å¾ |
| | | ImageGrabbed?.Invoke(this, new CameraEventArgs(SN, bmp)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AsyncLogHelper.Error($"PHM6000: çæäº®åº¦å¾å¼å¸¸ - {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private void SyncConfigFromCamera() |
| | | { |
| | | // ä»ç¸æºè¯»åææåæ°å¹¶å¡«å
å° _sensorConfig |
| | | foreach (EnumNameId id in Enum.GetValues(typeof(EnumNameId))) |
| | | { |
| | | int iVal = 0; double dVal = 0; int eVal = 0; |
| | | if (PHM6000Profiler.GetProfilerParameter(_cameraHandle, (int)id, ref iVal, ref dVal, ref eVal) == 0) |
| | | { |
| | | // å®é
项ç®ä¸åºä½¿ç¨åå°å°å¼åå _sensorConfig |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool SetParam(EnumNameId id, float value) |
| | | { |
| | | if (!_isConnected) return false; |
| | | return PHM6000Profiler.SetProfilerParameter(_cameraHandle, (int)id, 0, value, 0) == 0; |
| | | } |
| | | |
| | | private bool GetParam(EnumNameId id, out float value) |
| | | { |
| | | value = 0; |
| | | if (!_isConnected) return false; |
| | | int iVal = 0; double dVal = 0; int eVal = 0; |
| | | if (PHM6000Profiler.GetProfilerParameter(_cameraHandle, (int)id, ref iVal, ref dVal, ref eVal) == 0) |
| | | { |
| | | value = (float)dVal; |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | #endregion |
| | | } |
| | | |
| | | } |