1105 lines
42 KiB
C#
1105 lines
42 KiB
C#
/*
|
|
* 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 {
|
|
/// <summary>
|
|
/// Cognex 환경 변수 및 메소드 관리
|
|
/// </summary>
|
|
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;
|
|
/// <summary>
|
|
/// 싱글톤 객체
|
|
/// </summary>
|
|
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()));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cognex 라이센스 체크.
|
|
/// 대략 70ms이상이 소요되므로, 프로그램 시작시 최초 1번만 수행할 것을 권장
|
|
/// </summary>
|
|
/// <returns>라이센스 여부</returns>
|
|
public bool HasValidLicense() {
|
|
return CogLicense.IsLicenseEnabled(CogLicenseConstants.Generic, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 리소스 회수
|
|
/// </summary>
|
|
public void Dispose() {
|
|
}
|
|
|
|
/// <summary>
|
|
/// 원본 이미지 할당
|
|
/// </summary>
|
|
/// <param name="image">원본 이미지 버퍼</param>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>성공 유무</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// GrayScale 이미지 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">결과 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color 이미지 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">결과 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 세로 사이즈가 가로 사이즈보다 큰지 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 세로 사이즈가 가로 사이즈보다 크면 True</returns>
|
|
public bool IsHeightLongerThanWidth(CamConfig camConfig) {
|
|
switch (camConfig.FlipAndRotation.ImageRotation) {
|
|
case eImageRotation.CW_DEG_90:
|
|
case eImageRotation.CW_DEG_270:
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 반전 유무 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 반전 유무</returns>
|
|
public bool IsFlipEnabled(CamConfig camConfig) {
|
|
if (camConfig.FlipAndRotation.ImageFlip.Equals(eImageFlip.None))
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 회전 유무 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 회전 유무</returns>
|
|
public bool IsRotationEnabled(CamConfig camConfig) {
|
|
if (camConfig.FlipAndRotation.ImageRotation.Equals(eImageRotation.None) &&
|
|
camConfig.FlipAndRotation.ImageRotationOffset == 0)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="roi">ROI</param>
|
|
/// <returns>성공 유무</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="imageFormat">이미지 형식</param>
|
|
/// <returns>성공 유무</returns>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="imageFormat">이미지 형식</param>
|
|
/// <returns>성공 유무</returns>
|
|
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);
|
|
// }
|
|
//}
|
|
|
|
/// <summary>
|
|
/// Bitmap을 BitmapImage로 변환
|
|
/// </summary>
|
|
/// <param name="bitmap">비트맵</param>
|
|
/// <returns>비트맵 이미지</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 불러오기
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <returns>이미지</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 사이즈와 픽셀 데이터만 복사
|
|
/// </summary>
|
|
/// <param name="srcImage">소스 이미지</param>
|
|
/// <param name="dstImage">복사 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 새로운 이미지 복제. 반복 남용시 메모리 누수가 발생할 수 있음.
|
|
/// </summary>
|
|
/// <param name="image">소스 이미지</param>
|
|
/// <returns>복제 이미지</returns>
|
|
public static ICogImage CloneImage(ICogImage image) {
|
|
return image.CopyBase(CogImageCopyModeConstants.CopyPixels); // new CogImage8Grey((CogImage8Grey)image)와 동일
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 자르기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="rect">자를 영역</param>
|
|
/// <returns>자른 이미지</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 자르기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="roi">자를 영역</param>
|
|
/// <returns>자른 이미지</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 자원 회수
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int FreeImage(ICogImage image) {
|
|
if (image != null) {
|
|
(image as CogImage8Grey).Dispose();
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사각영역 중심 가져오기
|
|
/// </summary>
|
|
/// <param name="roi">사각영역</param>
|
|
/// <returns>사각영역 중심</returns>
|
|
public static ImagePoint GetRectCenter(Rect roi) {
|
|
return new ImagePoint(roi.Left + roi.Width / 2, roi.Top + roi.Height / 2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 중심 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>이미지 중심</returns>
|
|
public static ImagePoint GetImageCenter(ICogImage image) {
|
|
var imageSize = GetImageSize(image);
|
|
return new ImagePoint(
|
|
imageSize.Width * 0.5,
|
|
imageSize.Height * 0.5);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 크기 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>이미지 크기</returns>
|
|
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
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 사이즈 가져오기
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>성공 유무</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 크기가 동일한지 체크
|
|
/// </summary>
|
|
/// <param name="image1">이미지1</param>
|
|
/// <param name="image2">이미지2</param>
|
|
/// <returns>이미지 크기 동일 여부</returns>
|
|
public static bool ImageSizeEquals(ICogImage image1, ICogImage image2) {
|
|
var imageSize1 = GetImageSize(image1);
|
|
var imageSize2 = GetImageSize(image2);
|
|
|
|
return ImageSizeEquals(imageSize1, imageSize2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 크기가 동일한지 체크
|
|
/// </summary>
|
|
/// <param name="imageSize1">이미지 크기1</param>
|
|
/// <param name="imageSize2">이미지 크기2</param>
|
|
/// <returns>이미지 크기 동일 여부</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 크기가 null인지 체크
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 크기</param>
|
|
/// <returns>이지지 크기 null 여부</returns>
|
|
public static bool IsImageSizeNull(ImageSize imageSize) {
|
|
if (imageSize.Width == -1 && imageSize.Height == -1) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 컬러 이미지인지 체크
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>컬러 이미지 여부</returns>
|
|
public static bool IsColorImage(ICogImage image) {
|
|
var imageSize = GetImageSize(image);
|
|
|
|
return (imageSize.Channel != 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// CogImage를 ByteArry로 변환
|
|
/// </summary>
|
|
/// <param name="image">CogImage</param>
|
|
/// <returns>ByteArry</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// ByteArry를 CogImage로 변환
|
|
/// </summary>
|
|
/// <param name="byteArry">ByteArry</param>
|
|
/// <param name="width">이미지 너비</param>
|
|
/// <param name="height">이미지 높이</param>
|
|
/// <param name="image">CogImage</param>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 컬러 이미지를 흑백 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="colorImage">컬러 이미지</param>
|
|
/// <returns>흑백 이미지</returns>
|
|
public static ICogImage ConvertToGray(ICogImage colorImage) {
|
|
ICogImage grayImageId = null;
|
|
ConvertToGray(colorImage, grayImageId);
|
|
|
|
return grayImageId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 컬러 이미지를 흑백 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="colorImage">컬러 이미지</param>
|
|
/// <param name="grayImage">흑백 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int ConvertToGray(ICogImage colorImage, ICogImage grayImage) {
|
|
//MIL.MimConvert(colorImageId, grayImageId, MIL.M_RGB_TO_L);
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 흑백 이미지를 컬러 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="image">흑백 이미지</param>
|
|
/// <returns>컬러 이미지</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 컬러 이미지인지 체크
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 크기</param>
|
|
/// <returns>컬러 이미지 여부</returns>
|
|
public static bool IsColorImage(ImageSize imageSize) {
|
|
return imageSize.Channel != 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 클리어 (Pixel Zero)
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="value">RunParams.FillRegionValue</param>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 클리어 (Pixel Zero)
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="value">RunParams.FillRegionValue</param>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 자른 영역에서 픽셀 Sharpness 값 얻어오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">자른 영역</param>
|
|
/// <returns>픽셀 Sharpness</returns>
|
|
public static int GetSharpnessWithCropRoi(ICogImage image, Rect cropRoi) {
|
|
ICogImage cropImage = CropImage(image, cropRoi);
|
|
return GetSharpness(cropImage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 자른 영역에서 픽셀 Sharpness 값 얻어오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">자른 영역</param>
|
|
/// <returns>픽셀 Sharpness</returns>
|
|
public static int GetSharpnessWithCropRoi(ICogImage image, ROI cropRoi) {
|
|
ICogImage cropImage = CropImage(image, cropRoi);
|
|
return GetSharpness(cropImage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 픽셀 Sharpness 값 얻어오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>픽셀 Sharpness</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 자른 영역에서 픽셀 밝기 정보 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">자른 영역</param>
|
|
/// <returns>픽셀 밝기 정보</returns>
|
|
public static BrightnessResult GetBrightnessWithCropRoi(ICogImage image, Rect cropRoi) {
|
|
ICogImage cropImage = CropImage(image, cropRoi);
|
|
return GetBrightness(cropImage, GetRectCenter(cropRoi));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 자른 영역에서 픽셀 밝기 정보 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">자른 영역</param>
|
|
/// <returns>픽셀 밝기 정보</returns>
|
|
public static BrightnessResult GetBrightnessWithCropRoi(ICogImage image, ROI cropRoi) {
|
|
ICogImage cropImage = CropImage(image, cropRoi);
|
|
return GetBrightness(cropImage, cropRoi.Center);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 픽셀 밝기 정보 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="imagePoint">ROI 중심</param>
|
|
/// <returns>픽셀 밝기 정보</returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overlay 이미지 가져오기
|
|
/// </summary>
|
|
/// <param name="cogCameraDisplay">카메라 디스플레이</param>
|
|
/// <returns>Overlay 이미지</returns>
|
|
public static System.Drawing.Bitmap GetOverlayImage(ICogCameraDisplay cogCameraDisplay) {
|
|
var cogDisplay = cogCameraDisplay.GetDisplay();
|
|
var drawingImage = cogDisplay.CreateContentBitmap(CogDisplayContentBitmapConstants.Image);
|
|
|
|
return new System.Drawing.Bitmap(drawingImage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overlay 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <param name="fovInfos">FOV 정보 리스트</param>
|
|
/// <param name="displayType">디스플레이 타입</param>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int SaveScreenShot(string filePath, List<FovInfo> fovInfos, eDisplayType displayType, object image) {
|
|
var overlayImages = new Dictionary<FovInfo, Bitmap>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사각 영역(Rect)을 CogRectangle로 변환
|
|
/// </summary>
|
|
/// <param name="rect">사각 영역</param>
|
|
/// <returns>CogRectangle</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사각 영역(ROI)을 CogRectangle로 변환
|
|
/// </summary>
|
|
/// <param name="roi">사각 영역</param>
|
|
/// <returns>CogRectangle</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사각 영역(ROI)을 CogRectangleAffine으로 변환
|
|
/// </summary>
|
|
/// <param name="roi">사각 영역</param>
|
|
/// <returns>CogRectangleAffine</returns>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// CogRectangle을 사각 영역(ROI)으로 변환
|
|
/// </summary>
|
|
/// <param name="cogRectangle">CogRectangle</param>
|
|
/// <returns>사각 영역(ROI)</returns>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// CogRectangleAffine을 사각 영역(ROI)으로 변환
|
|
/// </summary>
|
|
/// <param name="cogRectangleAffine">CogRectangleAffine</param>
|
|
/// <returns>사각 영역(ROI)</returns>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// CogRectangleAffine 영역 X,Y 픽셀 이동
|
|
/// </summary>
|
|
/// <param name="region">CogRectangleAffine</param>
|
|
/// <param name="translationX">픽셀 이동량X</param>
|
|
/// <param name="translationY">픽셀 이동량Y</param>
|
|
/// <returns>CogRectangleAffine</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 소수점 단위인 Cog 스코어를 백분율(%) 단위로 변환
|
|
/// </summary>
|
|
/// <param name="cogScore">Cog 스코어</param>
|
|
/// <returns>스코어(%)</returns>
|
|
public static double ConvertToVisionScore(double cogScore) {
|
|
return cogScore * 100;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 백분율(%) 단위인 스코어를 소수점 단위인 Cog 스코어로 변환
|
|
/// </summary>
|
|
/// <param name="visionScore">스코어(%)</param>
|
|
/// <returns>Cog 스코어</returns>
|
|
public static double ConvertToCogScore(double visionScore) {
|
|
return visionScore / 100;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 소수점 단위인 scale을 백분율(%) 단위로 변환
|
|
/// </summary>
|
|
/// <param name="scale">스케일</param>
|
|
/// <returns>Certainty(%)</returns>
|
|
public static double ConvertToCertainty(double scale) {
|
|
return scale * 100;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 백분율(%) 단위인 certainty를 소수점 단위로 변환
|
|
/// </summary>
|
|
/// <param name="certainty">Certainty(%)</param>
|
|
/// <returns>스케일</returns>
|
|
public static double ConvertToScale(double certainty) {
|
|
return certainty / 100;
|
|
}
|
|
}
|
|
} |