using Aurora.Api; using VisionCommon; using System; using System.Collections.Generic; using System.Reactive.Linq; namespace VisionSequence.Camera { /// /// 공정에서 사용되는 이미지의 정보 /// public class ImageInfo : IDisposable { /// 공정 이미지 public object Image { get; set; } = null; /// 점유(사용) 상태 플래그 public bool Occupied { get; set; } = false; /// /// 생성자 /// /// 공정 이미지 /// 점유(사용) 상태 플래그 public ImageInfo(object image, bool occupied) { Image = image; Occupied = occupied; } /// /// 명시적 해제 (이미지 메모리 해제, Occupied = false) /// public void Dispose() { IpAdapter.Instance.IpEnvironment.FreeImage(Image); Image = null; Occupied = false; } } /// /// 공정 이미지 매니저로 그랩 횟수를 최소화하기 위해 사용한다. /// 패턴에서 동일한 조명 값을 사용하는 경우 카메라 그랩을 1회만 수행한다. /// public class ProcGrabImageManager : IDisposable { private readonly object _Lock = new object(); private List _ImageInfos = new List(); private Dictionary _GrabImages = new Dictionary(); private Logger _Logger; private FovInfo _FovInfo; private CameraAgentBase _CameraAgent; private IDisposable _EventDisposable; /// /// 생성자 /// /// FOV 키 정보 /// 카메라 에이전트 public ProcGrabImageManager(FovInfo fovInfo, CameraAgentBase cameraAgent) { _Logger = new Logger(GetType().Name); _FovInfo = fovInfo; _CameraAgent = cameraAgent; SetObservable(); } private void SetObservable() { var camRecipe = VisionRecipeManager.GetCamRecipe(_FovInfo); if (_EventDisposable == null) { _EventDisposable = VisionEnv.AuroraEnv.EventObservable.AsObservable(VisionEventId.CAMERA_UPDATE_GRAB_IMAGE_BUFFER). Where(x => x.From == camRecipe.CamId.ToString()). Subscribe(_ => UpdateGrabImageBuffer()); } } private void UpdateGrabImageBuffer() { lock (_Lock) { if (0 < _ImageInfos.Count) { var camImageSize = _CameraAgent.GetImageSize(); var imageSize = IpAdapter.Instance.IpEnvironment.GetImageSize(_ImageInfos[0].Image); if (!IpAdapter.Instance.IpEnvironment.ImageSizeEquals(camImageSize, imageSize)) { DisposeImageInfos(); Clear(); } } } } /// /// 공정 이미지 초기화 /// public void Clear() { lock (_Lock) { _GrabImages.Clear(); ClearOccupied(); } } private void ClearOccupied() { lock (_Lock) { foreach (var imageInfo in _ImageInfos) { imageInfo.Occupied = false; } } } /// /// 조명 값(LightInfo)의 공정 이미지 그랩 완료 여부 /// /// 조명 값 /// 완료 여부 public bool IsGrabDone(LightInfo lightInfo) { lock (_Lock) { return _GrabImages.ContainsKey(lightInfo); } } /// /// 조명 값(LightInfo)으로 그랩된 공정 이미지를 등록 /// /// 조명 값 /// 공정 이미지 public void SetGrabImage(LightInfo lightInfo, object image) { lock (_Lock) { if (_GrabImages.ContainsKey(lightInfo)) { _GrabImages[lightInfo] = image; } else { _GrabImages.Add(lightInfo, image); } } } /// /// 공정이미지를 얻어 온다. /// /// 조명 값 /// 공정 이미지 public object GetGrabImage(LightInfo lightInfo) { lock (_Lock) { if (_GrabImages.ContainsKey(lightInfo)) { return _GrabImages[lightInfo]; } else { _GrabImages[lightInfo] = GetImage(); return _GrabImages[lightInfo]; } } } private object GetImage() { lock (_Lock) { foreach (var imageInfo in _ImageInfos) { if (!imageInfo.Occupied) { imageInfo.Occupied = true; return imageInfo.Image; } } var newImageInfo = CreateImageInfo(); _ImageInfos.Add(newImageInfo); return newImageInfo.Image; } } private ImageInfo CreateImageInfo() { return new ImageInfo(_CameraAgent.CloneImageBuffer(), occupied: true); } /// /// 명시적 해제 /// public void Dispose() { lock (_Lock) { DisposeImageInfos(); _EventDisposable.Dispose(); } } private void DisposeImageInfos() { lock (_Lock) { foreach (var imageInfo in _ImageInfos) { imageInfo.Dispose(); } _ImageInfos.Clear(); } } } }