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);
|
}
|
|
/// <summary>
|
/// 算子逻辑
|
/// </summary>
|
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
|
}
|
}
|
}
|
}
|