1,机器视觉形状匹配,首先要用roi抠图学习,roi就是感兴趣区域,这和人工智能的注意力机制一脉相承。
2,其次,就是学习canny线条,然后匹配,在人工智能上也有一个术语,和这个相似YOLO,you only look once ,意思是只需要看一眼就可以检测所有的目标。
先看图:
我们并没有使用鼠标去画一个roi框,但我们确实使用了一个矩形,框住了黄色字"资源库",并且处理了,学习后,canny线条(形状)结果图如下:
,好我们看,"在(440,340)学习**"按钮**做了什么?
//20241210
//第一,不gaos
//第二,截图
int xstart = Convert.ToInt32(textBox5x.Text);//440
int ystart = Convert.ToInt32(textBox5y.Text);///340
int temproiX = xstart;
int temproiY = ystart;
byte[] globgaospydoutimgN = 非极大抑制黑中白202210261519(rgbbufercopyR, 640, 480,.15f);
byte[] roiImage = new byte[120 * 60];
for (int i = 0; i < 60; i++)
for (int j = 0; j < 120; j++)//zhege roi 的宽和高就指定120,60,不再改变
{
int tihuan = (i + temproiY) * 640 + j + temproiX;
int tempij=i * 120 + j;
//roiImage[i * 120 + j] = globgaospydoutimgN[((i + temproiY) * 640 + j + temproiX)];
roiImage[tempij] = globgaospydoutimgN[tihuan];
}
看到没有,我们在(440,340)起点的矩形宽=120,高=60,图像抠出来并做了canny处理。
上面这个函数 **非极大抑制黑中白202210261519(...)**我就不介绍了,博客中搜得到。下一步:
List<List<Point>> llpgaos12896roi = new List<List<Point>>();
llpgaos12896roi.Clear();
int ww = 120; int hh = 60;
for (int i = 0; i < hh; i++)//****染色算法必须202209091600染色算法也隐含了白底黑斑
{//所以这里必须反色处理,负责没有结果//202209091606
roiImage[i * ww + 0] = 0;
roiImage[i * ww + ww - 1] = 0;
}
for (int j = 0; j < ww; j++)
{
roiImage[0 * ww + j] = 0;
roiImage[(hh - 1) * ww + j] = 0;
}
//染色算法黑中白(ref llpgaos12896roi, ref roiImage, ww, hh);//在边界崩溃了20220831
染色算法黑中白(ref llpgaos12896roi, ref roiImage, ww, hh,5);//点数大于等于5的线条,然后找出梯度门槛值
if (llpgaos12896roi.Count == 0) return;
showbuffer2pict(roiImage, 120, 60, pictureBox6);
第三,合并轮廓点
hebingllp1.Clear();
for (int i = 0; i < llpgaos12896roi.Count; i++)
{
for (int j = 0; j < llpgaos12896roi[i].Count; j++)
{
hebingllp1.Add(llpgaos12896roi[i][j]);//找出x,y中最大,最小,差值加一来确认宽和高202210261709
}
}
找出>=5的轮廓线条,并且把轮廓线条线条上的点合并。
下面代码,找出轮廓中重要的特征,做了记录,准备存储下来,以备使用时加载。
//
匹配www = 120; 匹配hhh = 60;
第四,中心点和最长线梯度赋值最大点
int maxlineC = 0; int 计数 = 0;//位置
int jiluii = 0;
foreach (List<Point> templspt in llpgaos12896roi)
{
//轮廓中线条大于等于十个点的全部合并20230228
// list<Point> templspt = *iter;
int tempint = templspt.Count;
//int tempint = templspt.size();
// if (tempint < 5) { 计数++; continue; }
if (tempint > maxlineC)
{
maxlineC = tempint; jiluii = 计数; //jiluii =position,最大线条in roi的点数=maxlineC
}
计数++;
}
///
List<Point> templong = llpgaos12896roi[jiluii];
// int
maxtiduC = 0;
// int
jiluiitidupos =-1;
for (int i = 0; i < templong.Count; i++)
{
int fangbian = templong[i].Y * 120 + templong[i].X + temproiY * 640 + temproiX;
int gradx=rgbbufercopyR[fangbian+1]-rgbbufercopyR[fangbian];
int grady = rgbbufercopyR[fangbian+640] - rgbbufercopyR[fangbian];
int tidufuzhi = Math.Abs(gradx) + Math.Abs(gradx);
if (tidufuzhi > maxtiduC)
{
maxtiduC = tidufuzhi;
jiluiitidupos = i;
}
}
最长线梯度最大x = 0;
最长线梯度最大y = 0;
if (jiluiitidupos == -1) { MessageBox.Show("序号为负值"); return; }
最长线梯度最大x = templong[jiluiitidupos].X;
最长线梯度最大y = templong[jiluiitidupos].Y;
矩形中心
zhongxingray = 0;
zhongxingray = roiImage[30 * 120 + 60];
因为是0度匹配,这个学习就算完成了。保存轮廓和重要特征的代码如下,即图中"保存学习模板"按钮的代码:
string curFileName = "c:\\测试matchshape杨振宁.mch";
FileInfo fin = new FileInfo(curFileName);
FileStream fs1 = fin.Create();
//hebingllp1
if (hebingllp1.Count != 0)
{
int temp = hebingllp1.Count;
byte[] arrXY = new byte[temp * 2];
for (int i = 0; i < temp; i++)
{
arrXY[i] = (byte)hebingllp1[i].X;
arrXY[i + temp] = (byte)hebingllp1[i].Y;
}
fs1.Write(arrXY, 0, temp * 2);
fs1.Close();
}
else { return; }
XmlDocument xmlDoc = new XmlDocument();//實例化XML文件
XmlElement root = xmlDoc.CreateElement("Matchshape");
xmlDoc.AppendChild(root);
string str = string.Empty;
XmlElement xe1 = xmlDoc.CreateElement("Matchshaperoi");
root.AppendChild(xe1);
XmlElement xe = xmlDoc.CreateElement("最长线梯度最大X");
str = 最长线梯度最大x.ToString();
xe.InnerText = str;
xe1.AppendChild(xe);
xe = xmlDoc.CreateElement("最长线梯度最大Y");
str = 最长线梯度最大y.ToString();
xe.InnerText = str;
xe1.AppendChild(xe);
xe = xmlDoc.CreateElement("中心灰度");//byte,加载出现过负数,要注意
str = zhongxingray.ToString();
xe.InnerText = str;
xe1.AppendChild(xe);
//xe = xmlDoc.CreateElement("最长线梯度最大灰度");//知道不等于零即可!=0,不用保存此参数
//str = 最长线梯度最大灰度.ToString();
//xe.InnerText = str;
//xe1.AppendChild(xe);
//轮廓保存,参数保存以上3个,剩下五个都指定了,w=120,h=60,centrex=60,centrey=30,轮廓点数知道,mch长度除以2
xmlDoc.Save("c:\\matchshaperoi杨振宁" + ".xml");