2026-03-30 17:09:29 +09:00

184 lines
6.2 KiB
C#

using Aurora.Api;
using VisionCommon;
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
namespace VisionSequence.Camera {
/// <summary>
/// 공정에서 사용되는 이미지의 정보
/// </summary>
public class ImageInfo : IDisposable {
/// <summary>공정 이미지</summary>
public object Image { get; set; } = null;
/// <summary>점유(사용) 상태 플래그</summary>
public bool Occupied { get; set; } = false;
/// <summary>
/// 생성자
/// </summary>
/// <param name="image">공정 이미지</param>
/// <param name="occupied">점유(사용) 상태 플래그</param>
public ImageInfo(object image, bool occupied) {
Image = image;
Occupied = occupied;
}
/// <summary>
/// 명시적 해제 (이미지 메모리 해제, Occupied = false)
/// </summary>
public void Dispose() {
IpAdapter.Instance.IpEnvironment.FreeImage(Image);
Image = null;
Occupied = false;
}
}
/// <summary>
/// 공정 이미지 매니저로 그랩 횟수를 최소화하기 위해 사용한다.
/// 패턴에서 동일한 조명 값을 사용하는 경우 카메라 그랩을 1회만 수행한다.
/// </summary>
public class ProcGrabImageManager : IDisposable {
private readonly object _Lock = new object();
private List<ImageInfo> _ImageInfos = new List<ImageInfo>();
private Dictionary<LightInfo, object> _GrabImages = new Dictionary<LightInfo, object>();
private Logger _Logger;
private FovInfo _FovInfo;
private CameraAgentBase _CameraAgent;
private IDisposable _EventDisposable;
/// <summary>
/// 생성자
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <param name="cameraAgent">카메라 에이전트</param>
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();
}
}
}
}
/// <summary>
/// 공정 이미지 초기화
/// </summary>
public void Clear() {
lock (_Lock) {
_GrabImages.Clear();
ClearOccupied();
}
}
private void ClearOccupied() {
lock (_Lock) {
foreach (var imageInfo in _ImageInfos) {
imageInfo.Occupied = false;
}
}
}
/// <summary>
/// 조명 값(LightInfo)의 공정 이미지 그랩 완료 여부
/// </summary>
/// <param name="lightInfo">조명 값</param>
/// <returns>완료 여부</returns>
public bool IsGrabDone(LightInfo lightInfo) {
lock (_Lock) {
return _GrabImages.ContainsKey(lightInfo);
}
}
/// <summary>
/// 조명 값(LightInfo)으로 그랩된 공정 이미지를 등록
/// </summary>
/// <param name="lightInfo">조명 값</param>
/// <param name="image">공정 이미지</param>
public void SetGrabImage(LightInfo lightInfo, object image) {
lock (_Lock) {
if (_GrabImages.ContainsKey(lightInfo)) {
_GrabImages[lightInfo] = image;
}
else {
_GrabImages.Add(lightInfo, image);
}
}
}
/// <summary>
/// 공정이미지를 얻어 온다.
/// </summary>
/// <param name="lightInfo">조명 값</param>
/// <returns>공정 이미지</returns>
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);
}
/// <summary>
/// 명시적 해제
/// </summary>
public void Dispose() {
lock (_Lock) {
DisposeImageInfos();
_EventDisposable.Dispose();
}
}
private void DisposeImageInfos() {
lock (_Lock) {
foreach (var imageInfo in _ImageInfos) {
imageInfo.Dispose();
}
_ImageInfos.Clear();
}
}
}
}