我们开始讲匹配:匹配就是在新出现的图像中寻找我们曾经学习过的特征.
上一节,我们已经把特征记录下来,放在hebingllp中,他是一个point序列list
同时,我们对他进行了限制,找到了最小矩形,能容纳所有特征,这个一定比roi抠图框小,所以你在学习算法中也会看到hebingllp变成了hebingllp1,而且对应了一个矩形框,也就是做了修正的point序列hebingllp1以及对应的矩形框(匹配www* 匹配hhh),这是在匹配中会用到。
下面有几个巧妙的地方要陈述一下:
首先匹配也会iir高斯,并且得到256*192新图像,但是不必再做那么多学习的工作,我们用好学习结果point序列hebingllp1和对应的矩形框(匹配www* 匹配hhh)就好。
其次,学习是不需要耗费时间的,而真正的耗时在匹配中,因为匹配是实时的,自动的,而学习是在自动停下来,手动操作的,所以尽可能把匹配中的工作放入学习中。
下面我们看代码:
DateTime dt = DateTime.Now;
//
buttonAgaos_Click(sender, e);//canny没有优化,用赵春江法,尽量用弧度,效率还可以提高
//1,原图
if (globgaospydoutimgN == null) return;
// 2,找什么
// 匹配www = 0; 匹配hhh = 0;
if (匹配www == 0 && 匹配hhh == 0) return;
//if (hebingllp.Count == 0) return;
if (hebingllp1.Count == 0) return;
// int 匹配qidianX = 0; int 匹配qidianY = 0;
if (匹配qidianX == -1000 || 匹配qidianY == -1000) return;
pipeiRespt.Clear(); pipeiRes1.Clear();
if (hebingllp1.Count == 0) return;
/0度匹配
看上面红色标出,就是要利用的结果。buttonAgaos_Click函数如下,处理新采集图像到非极大值抑制:对比学习,看看是不是少了很多东西,因为我们已经学习过了:
private void buttonAgaos_Click(object sender, EventArgs e)
{
if (glob_buffer8 == null) return;
int hh = 768;
int ww = 1024;
float[] 原图copy = new float[1024 * 768];
// MeGaugingLibNew.ImageSourceForm secondhello = meGaugingLib1.getImage();
for (int j = 0; j < hh; j++)
for (int i = 0; i < ww; i++)
{
//原图copy[j * ww + i] = secondhello.IS_orgImg[j * ww + i];
原图copy[j * ww + i] = glob_buffer8[j * ww + i];
}
//float[] glob_buffer1024768smooth1dot25 = new float[1024 * 768];
// DateTime hellostart = DateTime.Now;
// gausssmooth(原图copy, ref glob_buffer1024768smooth1dot25, hh, ww, hello);
for (int y = 0; y < hh; y++)
{
float[] temp = new float[ww];
float[] temp1 = new float[ww];
for (int x = 0; x < ww; x++)//在这个地方c的指针是有优势的,c#要迂回一下。202210200907
{
temp[x] = 原图copy[y * ww + x];
}
//gausssmooth(原图copy[y * ww], glob_buffer1024768smooth1dot25[y * ww], ww, 1, hello);
加速gausssmooth(temp, ref temp1, ww, 1, 高斯因子);
for (int x = 0; x < ww; x++)
{
原图copy[y * ww + x] = temp1[x];
}
}
// 原图copy在这里已改变,存储了行一维高斯处理结果
for (int x = 0; x < ww; x++)
{
float[] temp = new float[hh];
float[] temp1 = new float[hh];
for (int y = 0; y < hh; y++)
{
temp[y] = 原图copy[y * ww + x];
}
/* gausssmooth(glob_buffer1024768smooth1dot25[x], glob_buffer1024768smooth1dot25[x], hh, ww, hello);//可以参考fft*/
//gausssmooth(temp, ref temp1, hh, ww, hello);//可以参考fft
加速gausssmooth(temp, ref temp1, hh, 1, 高斯因子);//可以参考fft,我已经处理为1了,忘了
for (int y = 0; y < hh; y++)
{
原图copy[y * ww + x] = temp1[y];
}
}
for (int i = 0; i < ww * hh; i++)
{
output加速gaos[i] = (byte)原图copy[i];
}
ww = 1024; hh = 768;
if (!checkBox4sigma667.Checked)
{
byte[]
temp_buffer12896 = new byte[128 * 96];
int k = 0;
for (int j = 0; j < hh; j += 8)
{
for (int i = 0; i < ww; i += 8)
{
int nn = j * ww + i;
byte b = output加速gaos[nn];
temp_buffer12896[k] = b;
k++;
}
}
// DateTime dt = DateTime.Now;
globgaospydoutimgN = 非极大抑制黑中白202210261519(temp_buffer12896, 128, 96);
// showbuffer2pict(globgaospydoutimgN, 128, 96,pictureBox1);
// TimeSpan ts = DateTime.Now - dt;
// textBox1.Text = ""; textBox1.Text = ts.ToString();
// DateTime dt1 = DateTime.Now;
zhaochunjiangfa(temp_buffer12896, 128, 96);//202211071641尝试赵春江canny法
// showbuffer2pict(zhaochunjiangfa(temp_buffer12896, 128, 96), 128, 96, pictureBox2);
// TimeSpan ts1 = DateTime.Now - dt1;
// textBox2.Text = ""; textBox2.Text = ts1.ToString();
}
else
{
byte[] temp_buffer256192 = new byte[256 * 192];
int k = 0;
for (int j = 0; j < hh; j += 4)
{
for (int i = 0; i < ww; i += 4)
{
int nn = j * ww + i;
byte b = output加速gaos[nn];
temp_buffer256192[k] = b;
k++;
}
}
globgaospydoutimgN精细 = 非极大抑制黑中白202210261519(temp_buffer256192, 256, 192);
}
//TimeSpan end = DateTime.Now - dt;
//textBox快速gaos.Text = "";
//textBox快速gaos.Text = end.ToString();
// showbuffer2pict(output加速gaos, ww, hh, pictureBox加速gaos);
buttonAgaos.Enabled = false;
}
我们学习的是0度轮廓和矩形,所以我们匹配时,也用这个结果:
/0度匹配
int jilux = 0; int jiluy = 0;
//long minhe = 15 * 255;//要求变得很严格202211051030
//long minhe = 30* 255;
//long minhe = 100000;
long minhe = 255 * hebingllp1.Count;
for (int i = 0; i < 128 - 匹配www; i++)
for (int j = 0; j < 96 - 匹配hhh; j++)
{
//1,拷贝出每一个www*hhhh
byte[] pipeiarr = new byte[匹配www * 匹配hhh];
for (int m = 0; m < 匹配www; m++)
for (int n = 0; n < 匹配hhh; n++)
{
int temp = n * 匹配www + m;
pipeiarr[temp] = globgaospydoutimgN[(n + j) * 128 + i + m];
}
//2,轮廓上场
long zonghe = 0;
for (int kk = 0; kk < hebingllp1.Count; kk++)//轮廓点至少大于10
{
int temp = hebingllp1[kk].Y * 匹配www + hebingllp1[kk].X;//这个128对吗?宽度应该是多少呢?是匹配www吗?怎么证明?
//看的出来是这个,还是谨慎点,慎吾,慎吾,真悟,真悟202210261929
zonghe += 255 - pipeiarr[temp];//好像最后的值被改为240了,查一下,不急,没事,这个255已经指定了。
//其实可以更改为zonghe += pipeiarr[temp];效率更高;有点像积分图
//其实还可以设定一个门槛值针对zonghe,提高效率
//if (zonghe > minhe)
//{
// break;//
//}
}
if (minhe >= zonghe && zonghe != 0)
{
minhe = zonghe;
jilux = i;
jiluy = j;
}//宽进严出
if (zonghe == 0 && minhe != 255 * hebingllp1.Count)//新加条件,更改处,注意观察
{
pipeiRespt.Add(new Point(i, j));
pipeiRes1.Add(zonghe);
//i = 256;
//j = 192;
}
}
// if (pipeiRes1.Count == 0) return;
pipeiRespt.Add(new Point(jilux, jiluy));
pipeiRes1.Add(minhe);
//i = 256;
//j = 192;
textBoxpipeizhi.Text = "";
for (int i = 0; i < pipeiRes1.Count; i++)
{
textBoxpipeizhi.Text += (pipeiRes1[i] / 255).ToString() + "点失误;score:" + (1 - (pipeiRes1[i] / 255) / (1.0f * hebingllp1.Count)).ToString() + "\r\n";
}
//用来画初始位置的点 = new Point(临时性www, 临时性hhh);
用来画初始位置的点 = new Point(匹配www, 匹配hhh);//先画零度,后头稳定了,画最好结果
textBox42.Text = ""; textBox42.Text = (pipeiRespt[0].X * 8).ToString();
textBox43.Text = ""; textBox43.Text = (pipeiRespt[0].Y * 8).ToString();
//
///零度失误的话
这个算法,是我匹配中的精髓,你慢慢消化和理解。
这一节到此,待续。。。
下一节讲1度的匹配,我们这里只完成了0度匹配,新来的图像有可能旋转了1度呢?