using HalconDotNet; using LB_SmartVisionCommon; using LB_VisionControls; using LB_VisionProcesses.Alogrithms.Halcon; using OpenCvSharp; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Extensions = OpenCvSharp.Extensions; namespace LB_VisionProcesses.Alogrithms { public class OneImageConvertTool : TAlgorithm { public enum ImageType { Bitmap, HObject, Mat } public enum PixelType { None, Gray, ChannelR, ChannelG, ChannelB, ChannelH, ChannelS, ChannelV } public OneImageConvertTool() { strProcessClass = "LB_VisionProcesses.Alogrithms.OneImageConvertTool"; strProcessName = "单图像处理工具"; Params.Inputs.Add("输入格式", "Bitmap"); Params.Inputs.Add("输出格式", "HObject"); Params.Inputs.Add("是否后处理", false); Params.Inputs.Add("后处理格式", "Gray"); Params.Inputs.Add("斜率", 1.0); Params.Inputs.Add("截距", 0.0); } /// /// 算子逻辑 /// public override void TAlgorithmMain() { #region 初始化变量 HObject ho_Regions, ho_ConnectedRegions, ho_SelectedRegions; HOperatorSet.GenEmptyObj(out ho_Regions); HOperatorSet.GenEmptyObj(out ho_ConnectedRegions); #endregion try { if (InputImage == null) { Msg = "输入图片为空"; Result = false; AsyncLogHelper.Error(Msg); return; } #region 算子逻辑 Record = new ObjectRecord(); bool bConvert = Convert.ToBoolean(Params.Inputs["是否后处理"]); if (!Enum.TryParse(ProcessParams.ConvertToString(Params.Inputs["输入格式"]), out ImageType eInputImageType)) { Msg = "输入格式不存在"; Result = false; AsyncLogHelper.Error(Msg); return; } if (!Enum.TryParse(ProcessParams.ConvertToString(Params.Inputs["输出格式"]), out ImageType eOutputImageType)) { Msg = "输出格式不存在"; Result = false; AsyncLogHelper.Error(Msg); return; } if (!Enum.TryParse(ProcessParams.ConvertToString(Params.Inputs["后处理格式"]), out PixelType ePixelType)) { Msg = "后处理格式不存在"; Result = false; AsyncLogHelper.Error(Msg); return; } lock (InputImage) { switch (eInputImageType) { case ImageType.Bitmap: { if (InputImage is Bitmap bmp) { switch (eOutputImageType) { case ImageType.Bitmap: { OutputImage = bmp.Clone(); break; } case ImageType.HObject: { TAlgorithm.Bitmap2HObject(bmp, out HObject bHObject); OutputImage = bHObject; break; } case ImageType.Mat: { OutputImage = Extensions.BitmapConverter.ToMat(bmp); break; } default: { Msg = "不支持的输出格式"; Result = false; return; } } } else { Msg = $"输入图片格式为{InputImage.GetType()},不是Bitmap格式"; Result = false; return; } break; } case ImageType.HObject: { if (InputImage is HObject hObject) { switch (eOutputImageType) { case ImageType.Bitmap: { TAlgorithm.HObject2Bitmap(hObject, out Bitmap hBitmap); OutputImage = hBitmap; break; } case ImageType.HObject: { OutputImage = hObject.CopyObj(1, -1); break; } case ImageType.Mat: { TAlgorithm.HObject2Mat(hObject, out Mat hMat); OutputImage = hMat; break; } default: { Msg = "不支持的输出格式"; Result = false; return; } } } else { Msg = $"输入图片格式为{InputImage.GetType()},不是HObject格式"; Result = false; return; } break; } case ImageType.Mat: { if (InputImage is Mat mat) { switch (eOutputImageType) { case ImageType.Bitmap: { OutputImage = Extensions.BitmapConverter.ToBitmap(mat); break; } case ImageType.HObject: { TAlgorithm.Mat2HObject(mat, out HObject mHObject); OutputImage = mHObject; break; } case ImageType.Mat: { OutputImage = mat.Clone(); break; } default: { Msg = "不支持的输出格式"; Result = false; return; } } } else { Msg = $"输入图片格式为{InputImage.GetType()},不是Mat格式"; Result = false; return; } break; } default: { Msg = "不支持的输入格式"; Result = false; AsyncLogHelper.Error(Msg); return; } } } #endregion #region 裁剪区域 object DomainImage = null; if (!ReduceDomainImage(OutputImage, ref DomainImage)) { Msg = "裁剪区域失败"; Result = false; AsyncLogHelper.Error(Msg); return; } #endregion #region 结果后处理 if (bConvert && ePixelType != PixelType.None) { double k = Convert.ToDouble(Params.Inputs["斜率"]); double b = Convert.ToDouble(Params.Inputs["截距"]); switch (eOutputImageType) { case ImageType.HObject: { switch (ePixelType) { case PixelType.Gray: if (DomainImage is HObject hObjectGray) { // 转换为灰度图像 HOperatorSet.Rgb1ToGray(hObjectGray, out HObject grayImage); HOperatorSet.ScaleImage(grayImage, out grayImage, k, b); DomainImage = grayImage; } break; case PixelType.ChannelR: if (DomainImage is HObject hObjectR) { HOperatorSet.CountChannels(hObjectR, out HTuple hv_ChannelR); if (hv_ChannelR.I == 3) { // 提取红色通道 HOperatorSet.Decompose3(hObjectR, out HObject channelR, out _, out _); HOperatorSet.ScaleImage(channelR, out channelR, k, b); DomainImage = channelR; } } break; case PixelType.ChannelG: if (DomainImage is HObject hObjectG) { HOperatorSet.CountChannels(hObjectG, out HTuple hv_ChannelG); if (hv_ChannelG.I == 3) { // 提取绿色通道 HOperatorSet.Decompose3(hObjectG, out _, out HObject channelG, out _); HOperatorSet.ScaleImage(channelG, out channelG, k, b); DomainImage = channelG; } } break; case PixelType.ChannelB: if (DomainImage is HObject hObjectB) { HOperatorSet.CountChannels(hObjectB, out HTuple hv_ChannelB); if (hv_ChannelB.I == 3) { // 提取蓝色通道 HOperatorSet.Decompose3(hObjectB, out _, out _, out HObject channelB); HOperatorSet.ScaleImage(channelB, out channelB, k, b); DomainImage = channelB; } } break; case PixelType.ChannelH: if (DomainImage is HObject hObjectH) { HOperatorSet.CountChannels(hObjectH, out HTuple hv_ChannelH); if (hv_ChannelH.I == 3) { // 转换为HSV颜色空间并提取H通道 HOperatorSet.Decompose3(hObjectH, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out HObject channelH, out _, out _, "hsv"); HOperatorSet.ScaleImage(channelH, out channelH, k, b); DomainImage = channelH; } } break; case PixelType.ChannelS: if (DomainImage is HObject hObjectS) { HOperatorSet.CountChannels(hObjectS, out HTuple hv_ChannelS); if (hv_ChannelS.I == 3) { // 转换为HSV颜色空间并提取S通道 HOperatorSet.Decompose3(hObjectS, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out _, out HObject channelS, out _, "hsv"); HOperatorSet.ScaleImage(channelS, out channelS, k, b); DomainImage = channelS; } } break; case PixelType.ChannelV: if (DomainImage is HObject hObjectV && hObjectV.CountObj() > 0) { HOperatorSet.CountChannels(hObjectV, out HTuple hv_ChannelV); if (hv_ChannelV.I == 3) { // 转换为HSV颜色空间并提取V通道 HOperatorSet.Decompose3(hObjectV, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out _, out _, out HObject channelV, "hsv"); HOperatorSet.ScaleImage(channelV, out channelV, k, b); DomainImage = channelV; } } break; default: Msg = "不支持的后处理格式"; Result = false; return; } break; } case ImageType.Mat: { Mat mat = new Mat(); switch (ePixelType) { case PixelType.Gray: // 转换为灰度图像 { if (DomainImage is Mat matGray) { Cv2.CvtColor(matGray, mat, ColorConversionCodes.BGR2GRAY); } break; } case PixelType.ChannelR: { if (DomainImage is Mat matR) { // 提取红色通道 if (matR.Channels() == 3) { mat = matR.Split()[2]; } if (k != 1) { Cv2.Multiply(mat, k, mat); } } break; } case PixelType.ChannelG: { if (DomainImage is Mat matG) { // 提取绿色通道 if (matG.Channels() == 3) { mat = matG.Split()[1]; } if (k != 1) { Cv2.Multiply(mat, k, mat); } } break; } case PixelType.ChannelB: { if (DomainImage is Mat matB) { // 提取蓝色通道 if (matB.Channels() == 3) { mat = matB.Split()[0]; } if (k != 1) { Cv2.Multiply(mat, k, mat); } } break; } case PixelType.ChannelH: { if (DomainImage is Mat matHH) { // 提取H通道 if (matHH.Channels() == 3) { Mat matH = new Mat(); Cv2.CvtColor(matHH, matH, ColorConversionCodes.BGR2HSV); mat = matH.Split()[0]; if (k != 1) { Cv2.Multiply(mat, k, mat); } } } break; } case PixelType.ChannelS: { if (DomainImage is Mat matSS) { // 提取S通道 if (matSS.Channels() == 3) { Mat matS = new Mat(); Cv2.CvtColor(matSS, matS, ColorConversionCodes.BGR2HSV); mat = matS.Split()[1]; if (k != 1) { Cv2.Multiply(mat, k, mat); } } } break; } case PixelType.ChannelV: { if (DomainImage is Mat matVV) { // 提取V通道 if (matVV.Channels() == 3) { Mat matV = new Mat(); Cv2.CvtColor(matVV, matV, ColorConversionCodes.BGR2HSV); mat = matV.Split()[2]; if (k != 1) { Cv2.Multiply(mat, k, mat); } } } break; } default: { Msg = "不支持的后处理格式"; Result = false; AsyncLogHelper.Error(Msg); return; } } DomainImage = mat; break; } case ImageType.Bitmap: switch (ePixelType) { case PixelType.Gray: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectGray); // 转换为灰度图像 HOperatorSet.Rgb1ToGray(hObjectGray, out HObject grayImage); DomainImage = grayImage; TAlgorithm.HObject2Bitmap(grayImage, out Bitmap grayBitmap); DomainImage = grayBitmap; break; } case PixelType.ChannelR: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectR); HOperatorSet.CountChannels(hObjectR, out HTuple hv_ChannelR); if (hv_ChannelR.I == 3) { // 提取红色通道 HOperatorSet.Decompose3(hObjectR, out HObject channelR, out _, out _); TAlgorithm.HObject2Bitmap(channelR, out Bitmap rBitmap); DomainImage = rBitmap; } break; } case PixelType.ChannelG: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectG); HOperatorSet.CountChannels(hObjectG, out HTuple hv_ChannelG); if (hv_ChannelG.I == 3) { // 提取绿色通道 HOperatorSet.Decompose3(hObjectG, out _, out HObject channelG, out _); TAlgorithm.HObject2Bitmap(channelG, out Bitmap gBitmap); DomainImage = gBitmap; } break; } case PixelType.ChannelB: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectB); HOperatorSet.CountChannels(hObjectB, out HTuple hv_ChannelB); if (hv_ChannelB.I == 3) { // 提取蓝色通道 HOperatorSet.Decompose3(hObjectB, out _, out _, out HObject channelB); TAlgorithm.HObject2Bitmap(channelB, out Bitmap bBitmap); DomainImage = bBitmap; } break; } case PixelType.ChannelH: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectH); HOperatorSet.CountChannels(hObjectH, out HTuple hv_ChannelH); if (hv_ChannelH.I == 3) { // 转换为HSV颜色空间并提取H通道 HOperatorSet.Decompose3(hObjectH, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out HObject channelH, out _, out _, "hsv"); TAlgorithm.HObject2Bitmap(channelH, out Bitmap hBitmap); DomainImage = hBitmap; } break; } case PixelType.ChannelS: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectS); HOperatorSet.CountChannels(hObjectS, out HTuple hv_ChannelS); if (hv_ChannelS.I == 3) { // 转换为HSV颜色空间并提取S通道 HOperatorSet.Decompose3(hObjectS, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out _, out HObject channelS, out _, "hsv"); TAlgorithm.HObject2Bitmap(channelS, out Bitmap sBitmap); DomainImage = sBitmap; } break; } case PixelType.ChannelV: { TAlgorithm.Bitmap2HObject((Bitmap)DomainImage, out HObject hObjectV); HOperatorSet.CountChannels(hObjectV, out HTuple hv_ChannelV); if (hv_ChannelV.I == 3) { // 转换为HSV颜色空间并提取V通道 HOperatorSet.Decompose3(hObjectV, out HObject hr, out HObject hg, out HObject hb); HOperatorSet.TransFromRgb(hr, hg, hb, out _, out _, out HObject channelV, "hsv"); TAlgorithm.HObject2Bitmap(channelV, out Bitmap vBitmap); DomainImage = vBitmap; } break; } default: { Msg = "不支持的后处理格式"; Result = false; AsyncLogHelper.Error(Msg); return; } } break; default: Msg = "不支持的输出格式"; Result = false; return; } } //else if (!bConvert) //{ // DomainImage = OutputImage; //} #endregion #region 生成OutputImage给后续处理 try { OutputImage = DomainImage; } catch (Exception ex) { Msg = "生成OutputImage失败,原因是:" + ex.ToString(); Result = false; AsyncLogHelper.Error(Msg); return; } #endregion if (Msg == "运行超时") { Result = false; return; } Msg = "运行成功"; Result = true; return; } catch (Exception ex) { Msg = "运行失败,原因是:" + ex.ToString().TrimEnd(); OutputImage = null; Result = false; AsyncLogHelper.Error(Msg); return; } finally { if (!Result) { Params.Outputs.Add("ConvertImage", null); } bCompleted = true; #region 内存释放 ho_Regions.Dispose(); ho_ConnectedRegions.Dispose(); #endregion } } } }