/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using Aurora.Api; using Aurora.Api.DataType; using VisionCommon; using Hermes; using Cognex.VisionPro; using System; using System.Collections.Generic; using System.IO; using System.Windows; using System.Drawing; using Aurora; using System.Windows.Media.Imaging; using System.Drawing.Imaging; using Cognex.VisionPro.ImageFile; using System.Runtime.InteropServices; using Cognex.VisionPro.Display; using System.Linq; using Cognex.VisionPro.ImageProcessing; using VisionCommonUI; using VisionCommonUI.Resources; namespace CogCommon { /// /// Cognex 환경 변수 및 메소드 관리 /// public class CogEnvironment : IDisposable { private static readonly Logger _Logger = new Logger("CogEnvironment"); private static object LockObj = new object(); //private MIL_INT _LicenseModules = 0; private static CogEnvironment _instance = null; /// /// 싱글톤 객체 /// public static CogEnvironment Instance { get { lock (LockObj) { if (_instance == null) { _instance = new CogEnvironment(); } return _instance; } } } private CogEnvironment() { IpAdapter.Instance.IpEnvironment = new IpEnvironment(); CheckLangToken(); CheckCogVersion(); } private void CheckLangToken() { string lastLanguage = (VisionEnv.AuroraEnv.SettingEntry[AuroraSettings.Equipment] as EquipmentInfo)?.Language ?? null; if (lastLanguage != null && lastLanguage.Length > 0) { System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo(lastLanguage); StrTokens.Culture = System.Globalization.CultureInfo.CurrentCulture; } } private void CheckCogVersion() { if (!VersionChecker.CheckCogVersionAndType()) { MessageBoxUtil.ShowMessageBoxWarning( string.Format(StrTokens.MSG_W_CogVersion, VersionChecker.GetCogVersion(), VersionChecker.GetCogType())); } } /// /// Cognex 라이센스 체크. /// 대략 70ms이상이 소요되므로, 프로그램 시작시 최초 1번만 수행할 것을 권장 /// /// 라이센스 여부 public bool HasValidLicense() { return CogLicense.IsLicenseEnabled(CogLicenseConstants.Generic, false); } /// /// 리소스 회수 /// public void Dispose() { } /// /// 원본 이미지 할당 /// /// 원본 이미지 버퍼 /// 카메라 컨피그 /// 성공 유무 public int AllocOriginalImage(CamConfig camConfig, ref ICogImage image) { switch (camConfig.ImageSize.Channel) { case 1: // 원본이미지는 항상 정사이즈 (W > H) image = new CogImage8Grey(camConfig.ImageSize.Width, camConfig.ImageSize.Height); return E1.OK; case 3: default: // 원본이미지는 항상 정사이즈 (W > H) image = new CogImage8Grey(camConfig.ImageSize.Width, camConfig.ImageSize.Height); return E1.OK; } } /// /// GrayScale 이미지 할당 /// /// 카메라 컨피그 /// 결과 이미지 /// 성공 유무 public int AllocGrayImage(CamConfig camConfig, bool isCropped, ref ICogImage image) { if (IsHeightLongerThanWidth(camConfig)) { return AllocGrayImage_HLongerThanW(camConfig, isCropped, ref image); } else { return AllocGrayImage_WLongerThanH(camConfig, isCropped, ref image); } } /// /// Color 이미지 할당 /// /// 카메라 컨피그 /// 결과 이미지 /// 성공 유무 public int AllocColorImage(CamConfig camConfig, bool isCropped, ref ICogImage image) { if (IsHeightLongerThanWidth(camConfig)) { return AllocColorImage_HLongerThanW(camConfig, isCropped, ref image); } else { return AllocColorImage_WLongerThanH(camConfig, isCropped, ref image); } } private int AllocGrayImage_HLongerThanW(CamConfig camConfig, bool isCropped, ref ICogImage image) { // Gray (H > W) image = new CogImage8Grey( isCropped ? (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY) : camConfig.ImageSize.Height, isCropped ? (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX) : camConfig.ImageSize.Width); return E1.OK; } private int AllocGrayImage_WLongerThanH(CamConfig camConfig, bool isCropped, ref ICogImage image) { // Gray (W > H) image = new CogImage8Grey( isCropped ? (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX) : camConfig.ImageSize.Width, isCropped ? (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY) : camConfig.ImageSize.Height); return E1.OK; } private int AllocColorImage_HLongerThanW(CamConfig camConfig, bool isCropped, ref ICogImage image) { // Color (H > W) image = new CogImage24PlanarColor( isCropped ? (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY) : camConfig.ImageSize.Height, isCropped ? (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX) : camConfig.ImageSize.Width); return E1.OK; } private int AllocColorImage_WLongerThanH(CamConfig camConfig, bool isCropped, ref ICogImage image) { // Color (W > H) image = new CogImage24PlanarColor( isCropped ? (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX) : camConfig.ImageSize.Width, isCropped ? (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY) : camConfig.ImageSize.Height); return E1.OK; } /// /// 이미지 세로 사이즈가 가로 사이즈보다 큰지 확인 /// /// 카메라 컨피그 /// 이미지 세로 사이즈가 가로 사이즈보다 크면 True public bool IsHeightLongerThanWidth(CamConfig camConfig) { switch (camConfig.FlipAndRotation.ImageRotation) { case eImageRotation.CW_DEG_90: case eImageRotation.CW_DEG_270: return true; } return false; } /// /// 이미지 반전 유무 확인 /// /// 카메라 컨피그 /// 이미지 반전 유무 public bool IsFlipEnabled(CamConfig camConfig) { if (camConfig.FlipAndRotation.ImageFlip.Equals(eImageFlip.None)) return false; else return true; } /// /// 이미지 회전 유무 확인 /// /// 카메라 컨피그 /// 이미지 회전 유무 public bool IsRotationEnabled(CamConfig camConfig) { if (camConfig.FlipAndRotation.ImageRotation.Equals(eImageRotation.None) && camConfig.FlipAndRotation.ImageRotationOffset == 0) return false; else return true; } /// /// 이미지 저장 /// /// 파일 경로 /// 이미지 /// ROI /// 성공 유무 public static int SaveImage(string filePath, ICogImage image, Rect roi) { try { ICogImage childImage = CropImage(image, roi); SaveImage(filePath, childImage); } catch (Exception e) { _Logger.FuncE(e.Message); return E1.GENERIC; } return E1.OK; } /// /// 이미지 저장 /// /// 파일 경로 /// 이미지 /// 이미지 형식 /// 성공 유무 public static int SaveImage(string filePath, ICogImage image, eImageFormat imageFormat = eImageFormat.PNG) { try { var dirPath = Path.GetDirectoryName(filePath); if (!Directory.Exists(dirPath)) { new DirectoryInfo(dirPath).Create(); } ICogImageFileProvider cogImageFile = GetCogImageFileFormat(imageFormat); cogImageFile.Open(filePath, CogImageFileModeConstants.Write); cogImageFile.Append(image); cogImageFile.Close(); #region 기존 //using (var ms = new MemoryStream()) //using (var fs = new FileStream(filePath, FileMode.Create)) { // var bitmapSource = ConvertToBitmapSource(image); // var encoder = new PngBitmapEncoder(); // encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); // encoder.Save(ms); // var data = ms.ToArray(); // fs.Write(data, 0, data.Length); //} #endregion } catch (Exception e) { _Logger.FuncE(e.Message); return E1.GENERIC; } return E1.OK; } private static ICogImageFileProvider GetCogImageFileFormat(eImageFormat imageFormat) { switch (imageFormat) { case eImageFormat.PNG: return new CogImageFilePNG(); case eImageFormat.BMP: return new CogImageFileBMP(); case eImageFormat.JPG: return new CogImageFileJPEG(); } return new CogImageFilePNG(); } /// /// 이미지 저장 /// /// 파일 경로 /// 이미지 /// 이미지 형식 /// 성공 유무 public static int SaveImage(string filePath, Bitmap image, eImageFormat imageFormat = eImageFormat.PNG) { ImageFormat imageFileFormat = GetBitmapImageFileFormat(imageFormat); image.Save(filePath, imageFileFormat); return E1.OK; } private static ImageFormat GetBitmapImageFileFormat(eImageFormat imageFormat) { switch (imageFormat) { case eImageFormat.PNG: return ImageFormat.Png; case eImageFormat.BMP: return ImageFormat.Bmp; case eImageFormat.JPG: return ImageFormat.Jpeg; } return ImageFormat.Png; } private static BitmapSource ConvertToBitmapSource(ICogImage cogImage) { try { using (var pixelMemory = ((CogImage8Grey)cogImage).Get8GreyPixelMemory( CogImageDataModeConstants.Read, 0, 0, cogImage.Width, cogImage.Height)) { // Declare an array to hold the bytes of the bitmap. int bytes = Math.Abs(pixelMemory.Stride) * pixelMemory.Height; byte[] pixelValues = new byte[bytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(pixelMemory.Scan0, pixelValues, 0, bytes); return BitmapSource.Create( cogImage.Width, cogImage.Height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null, pixelValues, pixelMemory.Stride); } } catch (Exception e) { _Logger.FuncE(e.Message); } return null; } //public static void SaveImage(string path, Bitmap bitmap) { // try { // using (var ms = new MemoryStream()) // using (var fs = new FileStream(path, FileMode.Create)) { // var bitmapImage = ConvertToBitmapImage(bitmap); // if (bitmapImage != null) { // var encoder = new JpegBitmapEncoder() { QualityLevel = 100 }; // encoder.Frames.Add(BitmapFrame.Create(bitmapImage)); // encoder.Save(ms); // var data = ms.ToArray(); // fs.Write(data, 0, data.Length); // } // } // } // catch (Exception e) { // _Logger.FuncE(e.Message); // } //} /// /// Bitmap을 BitmapImage로 변환 /// /// 비트맵 /// 비트맵 이미지 public static BitmapImage ConvertToBitmapImage(Bitmap bitmap) { try { BitmapImage image; using (var memory = new MemoryStream()) { bitmap.Save(memory, ImageFormat.Bmp); memory.Position = 0; var bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = memory; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); image = bitmapImage; } return image; } catch (Exception e) { _Logger.FuncE(e.Message); } return null; } /// /// 이미지 불러오기 /// /// 파일 경로 /// 이미지 public static ICogImage LoadImage(string filePath) { ICogImage loadImage = null; try { if (!File.Exists(filePath)) { return null; } using (CogImageFile ImageFile = new CogImageFile()) { ImageFile.Open(filePath, CogImageFileModeConstants.Read); loadImage = ImageFile[0] as ICogImage; ImageFile.Close(); } } catch (Exception e) { _Logger.FuncE(e.Message); } return loadImage; } /// /// 이미지 사이즈와 픽셀 데이터만 복사 /// /// 소스 이미지 /// 복사 이미지 /// 성공 유무 public static int CopyImage(ICogImage srcImage, ref ICogImage dstImage) { try { if (srcImage == null) { _Logger.FuncE("srcImage is null"); return E1.GENERIC; } if (dstImage == null) { _Logger.FuncE("dstImage is null"); return E1.GENERIC; } using (var copyRegionTool = new CogCopyRegionTool()) { copyRegionTool.InputImage = srcImage; copyRegionTool.DestinationImage = dstImage; copyRegionTool.Region = null; // 설정 필수 : 이미지 전체 영역 copyRegionTool.Run(); } } catch (Exception e) { _Logger.FuncE(e.Message); return E1.GENERIC; } return E1.OK; } /// /// 새로운 이미지 복제. 반복 남용시 메모리 누수가 발생할 수 있음. /// /// 소스 이미지 /// 복제 이미지 public static ICogImage CloneImage(ICogImage image) { return image.CopyBase(CogImageCopyModeConstants.CopyPixels); // new CogImage8Grey((CogImage8Grey)image)와 동일 } /// /// 이미지 자르기 /// /// 이미지 /// 자를 영역 /// 자른 이미지 public static ICogImage CropImage(ICogImage image, Rect rect) { var imageSize = GetImageSize(image); if (imageSize.Width > rect.Width && imageSize.Height > rect.Height) { var convertTool = new CogImageConvertTool(); convertTool.InputImage = image; convertTool.Region = ConvertToCogRectangle(rect); convertTool.Run(); //convertTool.OutputImage.PixelFromRootTransform = new CogTransform2DLinear(); // 상대 좌표계로 리셋 return convertTool.OutputImage; } else { return image; } } /// /// 이미지 자르기 /// /// 이미지 /// 자를 영역 /// 자른 이미지 public static ICogImage CropImage(ICogImage image, ROI roi) { var imageSize = GetImageSize(image); if (imageSize.Width > roi.Width && imageSize.Height > roi.Height) { var convertTool = new CogImageConvertTool(); convertTool.InputImage = image; convertTool.Region = ConvertToCogRectangleAffine(roi); convertTool.Run(); //convertTool.OutputImage.PixelFromRootTransform = new CogTransform2DLinear(); // 상대 좌표계로 리셋 return convertTool.OutputImage; } else { return image; } } /// /// 이미지 자원 회수 /// /// 이미지 /// 성공 유무 public static int FreeImage(ICogImage image) { if (image != null) { (image as CogImage8Grey).Dispose(); } return E1.OK; } /// /// 사각영역 중심 가져오기 /// /// 사각영역 /// 사각영역 중심 public static ImagePoint GetRectCenter(Rect roi) { return new ImagePoint(roi.Left + roi.Width / 2, roi.Top + roi.Height / 2); } /// /// 이미지 중심 가져오기 /// /// 이미지 /// 이미지 중심 public static ImagePoint GetImageCenter(ICogImage image) { var imageSize = GetImageSize(image); return new ImagePoint( imageSize.Width * 0.5, imageSize.Height * 0.5); } /// /// 이미지 크기 가져오기 /// /// 이미지 /// 이미지 크기 public static ImageSize GetImageSize(ICogImage image) { int width = -1; int height = -1; int band = -1; int bitDepth = -1; try { width = image.Width; height = image.Height; band = 1; bitDepth = 8; } catch (Exception e) { } return new ImageSize() { Width = width, Height = height, Channel = band, BitDepth = bitDepth }; } /// /// 이미지 사이즈 가져오기 /// /// 카메라 컨피그 /// 성공 유무 public ImageSize GetImageSize(CamConfig camConfig) { var imageSize = new ImageSize(); if (IsHeightLongerThanWidth(camConfig)) { imageSize.Width = camConfig.ImageSize.Height; imageSize.Height = camConfig.ImageSize.Width; } else { imageSize.Width = camConfig.ImageSize.Width; imageSize.Height = camConfig.ImageSize.Height; } imageSize.Channel = camConfig.ImageSize.Channel; imageSize.BitDepth = camConfig.ImageSize.BitDepth; return imageSize; } /// /// 이미지 크기가 동일한지 체크 /// /// 이미지1 /// 이미지2 /// 이미지 크기 동일 여부 public static bool ImageSizeEquals(ICogImage image1, ICogImage image2) { var imageSize1 = GetImageSize(image1); var imageSize2 = GetImageSize(image2); return ImageSizeEquals(imageSize1, imageSize2); } /// /// 이미지 크기가 동일한지 체크 /// /// 이미지 크기1 /// 이미지 크기2 /// 이미지 크기 동일 여부 public static bool ImageSizeEquals(ImageSize imageSize1, ImageSize imageSize2) { if (imageSize1.Width != imageSize2.Width || imageSize1.Height != imageSize2.Height || imageSize1.BitDepth != imageSize2.BitDepth || imageSize1.Channel != imageSize2.Channel) { return false; } return true; } /// /// 이미지 크기가 null인지 체크 /// /// 이미지 크기 /// 이지지 크기 null 여부 public static bool IsImageSizeNull(ImageSize imageSize) { if (imageSize.Width == -1 && imageSize.Height == -1) { return true; } else { return false; } } /// /// 컬러 이미지인지 체크 /// /// 이미지 /// 컬러 이미지 여부 public static bool IsColorImage(ICogImage image) { var imageSize = GetImageSize(image); return (imageSize.Channel != 1); } /// /// CogImage를 ByteArry로 변환 /// /// CogImage /// ByteArry public static byte[] ConvertCogToByteArry(ICogImage image) { ImageSize imageSize = GetImageSize(image); byte[] byteArry = new byte[imageSize.Width * imageSize.Height * imageSize.Channel]; //MIL.MbufGet2d(imageId, 0, 0, imageSize.Width, imageSize.Height, byteArry); return byteArry; } /// /// ByteArry를 CogImage로 변환 /// /// ByteArry /// 이미지 너비 /// 이미지 높이 /// CogImage public static void ConvertByteArryToCog(byte[] byteArry, int width, int height, ref ICogImage image) { var imageSize = GetImageSize(image); if (imageSize.Channel == 3) { //MIL.MbufPutColor2d(image, MIL.M_PACKED + MIL.M_BGR24, MIL.M_ALL_BANDS, 0, 0, width, height, byteArry); } else { //MIL.MbufPut2d(image, 0, 0, width, height, byteArry); } } /// /// 컬러 이미지를 흑백 이미지로 변환 /// /// 컬러 이미지 /// 흑백 이미지 public static ICogImage ConvertToGray(ICogImage colorImage) { ICogImage grayImageId = null; ConvertToGray(colorImage, grayImageId); return grayImageId; } /// /// 컬러 이미지를 흑백 이미지로 변환 /// /// 컬러 이미지 /// 흑백 이미지 /// 성공 유무 public static int ConvertToGray(ICogImage colorImage, ICogImage grayImage) { //MIL.MimConvert(colorImageId, grayImageId, MIL.M_RGB_TO_L); return E1.OK; } /// /// 흑백 이미지를 컬러 이미지로 변환 /// /// 흑백 이미지 /// 컬러 이미지 public static ICogImage ConvertGrayToRGB(ICogImage image) { var imageSize = GetImageSize(image); if (IsColorImage(imageSize)) { return CloneImage(image); } else { ICogImage rgbImageId = null; //MIL.MbufAllocColor( // Instance.GetSystem(boardSlotPos), // 3, // imageSize.Width, // imageSize.Height, // 8 + MIL.M_UNSIGNED, // MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP, // ref rgbImageId); //MIL.MbufCopyColor(image, rgbImageId, MIL.M_RED); //MIL.MbufCopyColor(image, rgbImageId, MIL.M_GREEN); //MIL.MbufCopyColor(image, rgbImageId, MIL.M_BLUE); return rgbImageId; } } /// /// 컬러 이미지인지 체크 /// /// 이미지 크기 /// 컬러 이미지 여부 public static bool IsColorImage(ImageSize imageSize) { return imageSize.Channel != 1; } /// /// 이미지 클리어 (Pixel Zero) /// /// 이미지 /// RunParams.FillRegionValue public static void ClearImage(ICogImage image, int value = 0) { if (image == null) { return; } CogCopyRegionTool copyRegionTool = new CogCopyRegionTool(); copyRegionTool.InputImage = image; copyRegionTool.DestinationImage = image; copyRegionTool.Region = null; copyRegionTool.RunParams.FillRegion = true; copyRegionTool.RunParams.FillRegionValue = value; copyRegionTool.RunParams.FillBoundingBox = false; copyRegionTool.Run(); } /// /// 이미지 클리어 (Pixel Zero) /// /// 이미지 /// RunParams.FillRegionValue public static void ClearImage(object image, int value = 0) { if (image == null) { return; } CogCopyRegionTool copyRegionTool = new CogCopyRegionTool(); copyRegionTool.InputImage = (ICogImage)image; copyRegionTool.DestinationImage = (ICogImage)image; copyRegionTool.Region = null; copyRegionTool.RunParams.FillRegion = true; copyRegionTool.RunParams.FillRegionValue = value; copyRegionTool.RunParams.FillBoundingBox = false; copyRegionTool.Run(); } /// /// 자른 영역에서 픽셀 Sharpness 값 얻어오기 /// /// 이미지 /// 자른 영역 /// 픽셀 Sharpness public static int GetSharpnessWithCropRoi(ICogImage image, Rect cropRoi) { ICogImage cropImage = CropImage(image, cropRoi); return GetSharpness(cropImage); } /// /// 자른 영역에서 픽셀 Sharpness 값 얻어오기 /// /// 이미지 /// 자른 영역 /// 픽셀 Sharpness public static int GetSharpnessWithCropRoi(ICogImage image, ROI cropRoi) { ICogImage cropImage = CropImage(image, cropRoi); return GetSharpness(cropImage); } /// /// 픽셀 Sharpness 값 얻어오기 /// /// 이미지 /// 픽셀 Sharpness public static int GetSharpness(ICogImage image) { var sharpnessTool = new CogImageSharpnessTool(); int sharpness = 0; sharpnessTool.InputImage = (CogImage8Grey)image; sharpnessTool.RunParams.Mode = CogImageSharpnessModeConstants.BandPass; sharpnessTool.Run(); if (sharpnessTool.RunStatus.Result == CogToolResultConstants.Accept) { sharpness = (int)sharpnessTool.Score; // BandPass Score } sharpnessTool.Dispose(); return sharpness; } /// /// 자른 영역에서 픽셀 밝기 정보 가져오기 /// /// 이미지 /// 자른 영역 /// 픽셀 밝기 정보 public static BrightnessResult GetBrightnessWithCropRoi(ICogImage image, Rect cropRoi) { ICogImage cropImage = CropImage(image, cropRoi); return GetBrightness(cropImage, GetRectCenter(cropRoi)); } /// /// 자른 영역에서 픽셀 밝기 정보 가져오기 /// /// 이미지 /// 자른 영역 /// 픽셀 밝기 정보 public static BrightnessResult GetBrightnessWithCropRoi(ICogImage image, ROI cropRoi) { ICogImage cropImage = CropImage(image, cropRoi); return GetBrightness(cropImage, cropRoi.Center); } /// /// 픽셀 밝기 정보 가져오기 /// /// 이미지 /// ROI 중심 /// 픽셀 밝기 정보 public static BrightnessResult GetBrightness(ICogImage image, ImagePoint imagePoint) { var histogramTool = new CogHistogramTool(); int min = 0; int max = 0; int avg = 0; histogramTool.InputImage = (CogImage8Grey)image; histogramTool.Run(); if (histogramTool.RunStatus.Result == CogToolResultConstants.Accept) { min = histogramTool.Result.Minimum; max = histogramTool.Result.Maximum; avg = (int)histogramTool.Result.Mean; } histogramTool.Dispose(); return new BrightnessResult( imagePoint, (int)min, (int)max, (int)avg); } /// /// Overlay 이미지 가져오기 /// /// 카메라 디스플레이 /// Overlay 이미지 public static System.Drawing.Bitmap GetOverlayImage(ICogCameraDisplay cogCameraDisplay) { var cogDisplay = cogCameraDisplay.GetDisplay(); var drawingImage = cogDisplay.CreateContentBitmap(CogDisplayContentBitmapConstants.Image); return new System.Drawing.Bitmap(drawingImage); } /// /// Overlay 이미지 저장 /// /// 파일 경로 /// FOV 정보 리스트 /// 디스플레이 타입 /// 이미지 /// 성공 유무 public static int SaveScreenShot(string filePath, List fovInfos, eDisplayType displayType, object image) { var overlayImages = new Dictionary(); Bitmap screenShotImage = null; try { foreach (var fovInfo in fovInfos) { var cogCameraDisplay = CameraDisplayManager.GetDisplay(fovInfo, displayType) as ICogCameraDisplay; var overlayImage = GetOverlayImage(cogCameraDisplay); overlayImages[fovInfo] = overlayImage; } if (0 < overlayImages.Count) { var screenShotImageSize = ScreenShotUtil.GetScreenShotImageSize(overlayImages, displayType); if (screenShotImageSize == null) { return E1.GENERIC; } screenShotImage = new Bitmap(screenShotImageSize.Width, screenShotImageSize.Height); var (ltFovInfo, ltFovUiPos) = ScreenShotUtil.GetLeftTopFovInfo(overlayImages.Keys.ToList(), displayType); var (ltFovUiPosRow, ltFovUiPosCol) = FovRecipe.GetFovUiPosRowCol(ltFovUiPos); foreach (var fovInfo in fovInfos) { var fovRecipe = VisionRecipeManager.GetFovRecipe(fovInfo); eFovUiPos fovUiPos = new eFovUiPos(); foreach (var mainUiRecipe in fovRecipe.MainUiRecipes) { if (mainUiRecipe.MainDisplayType == displayType) { fovUiPos = mainUiRecipe.FovUiPos; } } var (curFovUiPosRow, curFovUiPosCol) = FovRecipe.GetFovUiPosRowCol(fovUiPos); ScreenShotUtil.MergeImages( overlayImages[fovInfo], screenShotImage, (curFovUiPosCol - ltFovUiPosCol) * overlayImages[fovInfo].Width, (curFovUiPosRow - ltFovUiPosRow) * overlayImages[fovInfo].Height); } SaveImage(filePath, screenShotImage); } } catch (Exception e) { _Logger.E(e.Message); } finally { screenShotImage?.Dispose(); foreach (var overlayImage in overlayImages.Values) { overlayImage?.Dispose(); } } return E1.OK; } /// /// 사각 영역(Rect)을 CogRectangle로 변환 /// /// 사각 영역 /// CogRectangle public static CogRectangle ConvertToCogRectangle(Rect rect) { try { var cogRectangle = new CogRectangle(); cogRectangle.SetXYWidthHeight( rect.X, rect.Y, rect.Width, rect.Height); return cogRectangle; } catch (Exception e) { _Logger.FuncE(e.Message); } return null; } /// /// 사각 영역(ROI)을 CogRectangle로 변환 /// /// 사각 영역 /// CogRectangle public static CogRectangle ConvertToCogRectangle(ROI roi) { try { var cogRectangle = new CogRectangle(); cogRectangle.SetCenterWidthHeight( roi.CenterX, roi.CenterY, roi.Width, roi.Height); return cogRectangle; } catch (Exception e) { _Logger.FuncE(e.Message); } return null; } /// /// 사각 영역(ROI)을 CogRectangleAffine으로 변환 /// /// 사각 영역 /// CogRectangleAffine public static CogRectangleAffine ConvertToCogRectangleAffine(ROI roi) { try { var cogRectangleAffine = new CogRectangleAffine(); cogRectangleAffine.SetCenterLengthsRotationSkew( roi.CenterX, roi.CenterY, roi.Width, roi.Height, roi.Angle.Radian, 0); return cogRectangleAffine; } catch (Exception e) { _Logger.FuncE(e.Message); } return new CogRectangleAffine(); } /// /// CogRectangle을 사각 영역(ROI)으로 변환 /// /// CogRectangle /// 사각 영역(ROI) public static ROI ConvertToRoi(CogRectangle cogRectangle) { try { var roi = new ROI( (int)cogRectangle.X, (int)cogRectangle.Y, (int)cogRectangle.Width, (int)cogRectangle.Height); return roi; } catch (Exception e) { _Logger.FuncE(e.Message); } return new ROI(); } /// /// CogRectangleAffine을 사각 영역(ROI)으로 변환 /// /// CogRectangleAffine /// 사각 영역(ROI) public static ROI ConvertToRoi(CogRectangleAffine cogRectangleAffine) { try { var angle = new Angle() { Radian = cogRectangleAffine.Rotation, Degree = CogMisc.RadToDeg(cogRectangleAffine.Rotation) }; var roi = new ROI( cogRectangleAffine.CenterX, cogRectangleAffine.CenterY, (int)cogRectangleAffine.SideXLength, (int)cogRectangleAffine.SideYLength, angle); return roi; } catch (Exception e) { _Logger.FuncE(e.Message); } return new ROI(); } /// /// CogRectangleAffine 영역 X,Y 픽셀 이동 /// /// CogRectangleAffine /// 픽셀 이동량X /// 픽셀 이동량Y /// CogRectangleAffine public static CogRectangleAffine Translate(CogRectangleAffine region, double translationX, double translationY) { try { var translatedRegion = new CogRectangleAffine(); translatedRegion.SetOriginCornerXCornerY( region.CornerOriginX + translationX, region.CornerOriginY + translationY, region.CornerXX + translationX, region.CornerXY + translationY, region.CornerYX + translationX, region.CornerYY + translationY); return translatedRegion; } catch (Exception e) { _Logger.FuncE(e.Message); } return null; } /// /// 소수점 단위인 Cog 스코어를 백분율(%) 단위로 변환 /// /// Cog 스코어 /// 스코어(%) public static double ConvertToVisionScore(double cogScore) { return cogScore * 100; } /// /// 백분율(%) 단위인 스코어를 소수점 단위인 Cog 스코어로 변환 /// /// 스코어(%) /// Cog 스코어 public static double ConvertToCogScore(double visionScore) { return visionScore / 100; } /// /// 소수점 단위인 scale을 백분율(%) 단위로 변환 /// /// 스케일 /// Certainty(%) public static double ConvertToCertainty(double scale) { return scale * 100; } /// /// 백분율(%) 단위인 certainty를 소수점 단위로 변환 /// /// Certainty(%) /// 스케일 public static double ConvertToScale(double certainty) { return certainty / 100; } } }