C#Halcon差异分类模型
缺陷检测抛开blob分析,尺寸判定与深度学习之外还有一种常用的方式,个人称之为差异分类模型,简称差分模型
个人对其应用过程为:
准备阶段:图像预处理,创建模型,查找模型定位,创建差分模型
应用阶段:查找模型定位,差分模型分类
Demo效果(由于限制5M动图,图像压缩的有些失真,下面进行详细介绍时会以单图呈现)
一,图像预处理
1,加载图像
2,绘制目标区域大致ROI
鉴于图像情况个人建议可以采用
create_drawing_object_rectangle2 || draw_rectangle2 || draw_rectangle2_mod
进行封装
3,锁定抠出目标区域
二值化提取区域然后进行区域膨胀(这一步主要是扣取模板图像,个人采用 threshold 算子提取,shape_trans生成多边形,dilation_circle进行区域膨胀)
二,创建create_shape_model用以定位
num_levels # 金字塔的层数
angle_start # 模板旋转的起始角度
angle_extent # 模板旋转角度范围
angle_step # 旋转角度的步长
optimization # 模板优化和模板创建方法
metric # 匹配方法设置
contrast # 设置对比度
min_contrast # 设置最小对比度
三,验证find_shape_model定位效果
四,创建差分模型
1,选择图像文件夹路径
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
2,创建差分模型(CreateVariationModel参数最好是开放,小编Demo案例直接写死)
private void btn_create_variation_model_Click(object sender, EventArgs e)
{
try
{
hv_VarModelID.Dispose();
HOperatorSet.CreateVariationModel(imageWidth, imageHeight, "byte", "standard",
out hv_VarModelID);
laTicps2.ForeColor = Color.Green;
laTicps2.Text = "创建差异模型成功";
}
catch
{
laTicps2.ForeColor = Color.Red;
laTicps2.Text = "创建差异模型失败";
}
}
3,训练差分模型(养成良好的内存管理习惯很重要)
private void btn_train_variation_model_Click(object sender, EventArgs e)
{
try
{
DirectoryInfo TheFolder = new DirectoryInfo(fileName);//文件路径
for (int i = 0; i < TheFolder.GetFiles().Length; i++)//遍历文件夹
{
if (TheFolder.GetFiles()[i].Length > 0 && (TheFolder.GetFiles()[i].Extension == ".png" || TheFolder.GetFiles()[i].Extension == ".bmp"))//或者jpg,png 文件大小要大于0且是图片文件
{
Application.DoEvents();
HOperatorSet.ReadImage(out HIMage, fileName + "\\" + tifNames[i]);
FitImage(HIMage, hWC);
HTuple angle_start2, angle_extent2, MinScore, matchNum, MaxOverlap, SubPixel, numLeave, greediness;
angle_start2 = (new HTuple(Convert.ToDouble(tbx_angle_start2.Text))).TupleRad();
angle_extent2 = (new HTuple(Convert.ToDouble(tbx_angle_extent2.Text))).TupleRad();
MinScore = Convert.ToDouble(tbx_MinScore.Text);
matchNum = Convert.ToDouble(tbx_matchNum.Text);
MaxOverlap = Convert.ToDouble(tbx_MaxOverlap.Text);
SubPixel = cbx_SubPixel.Text;
numLeave = Convert.ToDouble(tbx_numLeave.Text);
greediness = Convert.ToDouble(tbx_greediness.Text);
HTuple hv_Column = new HTuple(), hv_Angle = new HTuple();
HTuple hv_Score = new HTuple(), hv_Row = new HTuple();
hv_Row.Dispose(); hv_Column.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();
HOperatorSet.FindShapeModel(HIMage, hv_ModelID, angle_start2, angle_extent2, MinScore, matchNum, MaxOverlap, SubPixel, numLeave, greediness, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
HTuple hv_HomMat2D = new HTuple();
HObject ho_TraingImage = null, ho_ImageAffineTrans = null;
HOperatorSet.GenEmptyObj(out ho_ImageAffineTrans);
HOperatorSet.GenEmptyObj(out ho_TraingImage);
//创建一个矩阵将当前图像变换到模板位置
hv_HomMat2D.Dispose();
HOperatorSet.VectorAngleToRigid(hv_Row, hv_Column, hv_Angle, hv_SRow, hv_SColumn,
0, out hv_HomMat2D);
//把当前图像变换到参照位置
ho_ImageAffineTrans.Dispose();
HOperatorSet.AffineTransImage(HIMage, out ho_ImageAffineTrans, hv_HomMat2D,
"constant", "false");
//把训练模型图像锁定出来
ho_TraingImage.Dispose();
HOperatorSet.ReduceDomain(ho_ImageAffineTrans, ho_RegionDilation, out ho_TraingImage
);
//训练模板
HOperatorSet.TrainVariationModel(ho_TraingImage, hv_VarModelID);
//操作提示
laTicps.Text = "当前正在训练" + (i + 1) + "/" + (TheFolder.GetFiles().Length) + "张图像";
Thread.Sleep(1000);
}
}
laTicps2.ForeColor = Color.Green;
laTicps2.Text = "训练模型成功";
}
catch
{
laTicps2.ForeColor = Color.Red;
laTicps2.Text = "训练模型失败";
}
}
4,确定最终差分模型
PrepareVariationModel
5,查看差分模型效果区域图像
五,应用验证
private void btn_getResult_Click(object sender, EventArgs e)
{
HTuple angle_start2, angle_extent2, MinScore, matchNum, MaxOverlap, SubPixel, numLeave, greediness;
angle_start2 = (new HTuple(Convert.ToDouble(tbx_angle_start2.Text))).TupleRad();
angle_extent2 = (new HTuple(Convert.ToDouble(tbx_angle_extent2.Text))).TupleRad();
MinScore = Convert.ToDouble(tbx_MinScore.Text);
matchNum = Convert.ToDouble(tbx_matchNum.Text);
MaxOverlap = Convert.ToDouble(tbx_MaxOverlap.Text);
SubPixel = cbx_SubPixel.Text;
numLeave = Convert.ToDouble(tbx_numLeave.Text);
greediness = Convert.ToDouble(tbx_greediness.Text);
HTuple hv_Column = new HTuple(), hv_Angle = new HTuple();
HTuple hv_Score = new HTuple(), hv_Row = new HTuple();
hv_Row.Dispose(); hv_Column.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();
HOperatorSet.FindShapeModel(HIMage, hv_ModelID, angle_start2, angle_extent2, MinScore, matchNum, MaxOverlap, SubPixel, numLeave, greediness, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
//创建一个矩阵将当前图像变换到模板位置
HTuple hv_HomMat2D = new HTuple();
HTuple hv_Number = new HTuple();
HObject ho_ImageAffineTrans = null, ho_CheckImage = null;
HObject ho_CheckRegion = null, ho_ConnectedRegions = null, ho_SelectedRegions = null;
HOperatorSet.GenEmptyObj(out ho_ImageAffineTrans);
HOperatorSet.GenEmptyObj(out ho_CheckImage);
HOperatorSet.GenEmptyObj(out ho_CheckRegion);
HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
HOperatorSet.GenEmptyObj(out ho_SelectedRegions);
hv_HomMat2D.Dispose();
HOperatorSet.VectorAngleToRigid(hv_Row, hv_Column, hv_Angle, hv_SRow, hv_SColumn,
0, out hv_HomMat2D);
//把当前图像变换到参照位置
ho_ImageAffineTrans.Dispose();
HOperatorSet.AffineTransImage(HIMage, out ho_ImageAffineTrans, hv_HomMat2D,
"constant", "false");
//把训练模型图像锁定出来
ho_CheckImage.Dispose();
HOperatorSet.ReduceDomain(ho_ImageAffineTrans, ho_RegionDilation, out ho_CheckImage
);
//获取模板图像与差异化图像的差分区域
ho_CheckRegion.Dispose();
HOperatorSet.CompareVariationModel(ho_CheckImage, out ho_CheckRegion, hv_VarModelID);
//联通区域断开
ho_ConnectedRegions.Dispose();
HOperatorSet.Connection(ho_CheckRegion, out ho_ConnectedRegions);
//根据要求筛选区域
ho_SelectedRegions.Dispose();
HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, "area",
"and", 100, 99999);
//判断及输出缺陷区域
hv_Number.Dispose();
HOperatorSet.CountObj(ho_SelectedRegions, out hv_Number);
HOperatorSet.DispObj(ho_ImageAffineTrans, HW);
HObject ho_ModelContours;
HOperatorSet.GenEmptyObj(out ho_ModelContours);
ho_ModelContours.Dispose();
HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelID, 1);
HOperatorSet.VectorAngleToRigid(0, 0, 0, hv_SRow, hv_SColumn,0, out HTuple homMat2D);
HOperatorSet.AffineTransContourXld(ho_ModelContours, out HObject ho_ModelContours1, homMat2D);
HW.SetColor("green");
HW.DispObj(ho_ModelContours1);
if (hv_Number>0)
{
HW.SetDraw("fill");
HW.SetLineWidth(2);
HW.SetColor("red");
//显示ROI
HOperatorSet.DispObj(ho_SelectedRegions, HW);
ticps3.ForeColor = Color.Red;
ticps3.Text = "NG";
}
else
{
ticps3.ForeColor = Color.Green;
ticps3.Text = "OK";
}
}