1、对图片做灰度处理
2、用圆心投影法(或用surf积分图方法)做对比图形匹配
3、抓取实时图中圆图时,考虑应用视网膜方式,说简单点就是越靠近图中心,扫描粒度越细,离图中心越远,扫描粒度越粗,减低计算量。
4、系统中的基准图片是带有坐标属性的图片
只对两张图片的边框图比较,减小单片机运算量,如果匹配算法耗费时间长,无实际应用意义。
因实时采集的图片,因摄影角度、天气等影响与系统中基准图只要有几度的角度差异,传统识别算法就不能识别,也就是必须解决图像的旋转不变性。
用以下方式实现。
1、方式一、扫描原图生成小圆图,利用同心圆投影算法中任意一点i(x,y)的灰度和这点到圆心(0,0))的距离r的之比是旋转不变量,构建两个圆图矩阵比较匹配。
可以看出,即使实时采集的图像,因摄影角度、天气等问题和基准图有方向差,这种方式仍能匹配到正确的图形。(如下图圆图1和圆图2有90度的差异,测试时仍能成功匹配)
圆心投影识别匹配的算法部分 类C代码(该算法简单可靠,但测试时识别时间为1秒左右,测试时基准图分辨率为100*100,实时图分辨率为300*300),做为巡航导弹的图形识别无任何问题。
假设巡航导弹为1倍音速,距离目标10km时开始抓图,此时飞行剩余时间为27秒左右,所以整个识别算法控制必须控制在1秒以下。
//基准图分辨率为150*150或200*200
//实时图分辨率为400*400 或500*500
jztmap1 = Bitmap.FromFile("c:/txsb/jpg1/1.jpg") as Bitmap; //弹载系统中原有基准边框图
jztmap2 = Bitmap.FromFile("c:/txsb/jpg1/2.jpg") as Bitmap;
jztmap3 = Bitmap.FromFile("c:/txsb/jpg1/3.jpg") as Bitmap;
jztmap4 = Bitmap.FromFile("c:/txsb/jpg0/test6.jpg") as Bitmap;
pictureBox6.Image = jztmap1;
jztclmap = TXYTYPP(jztmap1, 200, 200); //调用构建基准图同心圆投影
// jztmap4 = TXYTYPP(jztmap4, 200, 200);
pictureBox6.Image = jztclmap;
sj1 = DateTime.Now .Second ;
for (int i = 0; i < 240; i=i+35) //h 后期改为用视网膜算法,中心部分扫描粒度高,边缘部分扫描粒度低
{
for (int j = 0; j < 240; j=j+35) //w
{
sstclmap = SSTTXY(nbitmap, Width, Height, i, j); //调用构建实时图同心圆投影
// sstclmap = jztmap4; //测试用
//pictureBox7.Image = sstclmap;
F1=JZTF1(jztclmap);
ppd1 = TXYPP(jztclmap, sstclmap,F1); //调用同心圆投影匹配函数 Bitmap3=基准,Bitmap4=实时
sj2 = DateTime.Now.Second;
sj = sj2 - sj1;
label5.Text = (ppd1 * 100).ToString() + "%";
label10.Text = sj.ToString();
if (ppd1 > Convert.ToDecimal (0.85)) //匹配度大于85%,退出扫描实时图
{
mbx = j+75;
mby = i+75;
sj2 = DateTime.Now.Second;
sj = sj2 - sj1;
//pictureBox7.Image = sstclmap;
return;
}
}
}
//ppd1 = TXYPP(jztclmap, sstclmap); //测试用
//pictureBox7.Image = sstclmap;
//label5.Text = (ppd1*100).ToString()+"%";
// label8.Text = "x:"+ mbx.ToString() + "y:"+mby.ToString();
}
public Bitmap TXYTYPP(Bitmap oldBitmap, int Width, int Height) //定义构建基准图同心圆投影
{
Bitmap newBitmap = new Bitmap(Width, Height);
//构建基准图的同心圆矩阵
Color color1;
int r = 150 / 2;
PointF c = new PointF(150 / 2.0F, 150 / 2.0F);
for (int i = 0; i < oh -75; i++) //h
{
for (int j = 0; j < ow -75; j++) //w
{
if (Convert.ToInt32(Math.Pow(r, 2)) > ((Convert.ToInt32(Math.Pow(j * 1.0 - c.X, 2)) + Convert.ToInt32(Math.Pow(i * 1.0 - c.Y, 2)))))
{
color1 = oldBitmap.GetPixel(j, i);
newBitmap.SetPixel(j, i, Color.FromArgb(color1.R, color1.G, color1.B));
}
}
}
return newBitmap;
}
//构建实时边框图中的同心圆矩阵函数
public Bitmap SSTTXY(Bitmap oldBitmap, int Width, int Height,int x,int y) //定义实时图抓取同心圆函数
{
//x,y为每次生成同心圆的起始点
Bitmap newBitmap2 = new Bitmap(150, 150); //构建实时图的同心圆矩阵
Color color1;
int r = 150 / 2;
PointF c = new PointF(150 / 2.0F, 150 / 2.0F);
for (int i = x; i < x +150; i++) //h
{
for (int j = y; j <y +150; j++) //w
{
if (Convert.ToInt32(Math.Pow(r, 2)) > ((Convert.ToInt32(Math.Pow((j-y) * 1.0 - c.X, 2)) + Convert.ToInt32(Math.Pow((i-x) * 1.0 - c.Y, 2)))))
{
color1 = oldBitmap.GetPixel(j, i);
newBitmap2.SetPixel(j-y, i-x, Color.FromArgb(color1.R, color1.G, color1.B));
}
}
}
return newBitmap2;
}
//进行实时边框图中的同心圆矩阵的比较匹配
public int JZTF1(Bitmap Bitmap3) //基准图的F计算函数,加快运行速度
{
int F; //定义基准图圆灰度平均值
int r;
int f1=0;
for (int i = 1; i < 150; i++) //h
{
for (int j = 1; j < 150; j++) //w
{
r = ssbj(i, j);
f1 = f1 + Bitmap3.GetPixel(i, j).R/r; //基准图圆灰度值求sum,i为圆半径r
}
}
F= f1 / (150 * 150);
return F;
}
public decimal TXYPP(Bitmap Bitmap3,Bitmap Bitmap4,int F) //定义同心圆投影匹配函数 去均值归一化积算法(把基准图的F计算定义在函数外,加快运行速度)
{
Bitmap newBitmap2 = new Bitmap(150, 150);
//int F; //定义基准图圆灰度平均值
int G; //定义实时图圆灰度平均值
// int f1=0;
int g1=0;
decimal num=0;
int den1=0;
int den2=0;
int r = 0; //实时半径
// int den = 0; //总分母
decimal ppd=0; //匹配度
// for (int i = 1; i < 150; i++) //h
// {
// for (int j = 1; j < 150; j++) //w
// {
// r = ssbj(i, j);
// f1 = f1 + Bitmap3.GetPixel(i, j).R/r; //基准图圆灰度值求sum,i为圆半径r
// }
// }
for (int i = 1; i < 150; i++) //h
{
for (int j = 1; j < 150; j++) //w
{
r = ssbj(i, j);
g1 = g1 + Bitmap4.GetPixel(i, j).R/r; //实时图圆灰度值求sum
}
}
// F = f1 /( 150 * 150);
G = g1 /(150 * 150);
// 计算匹配度相关性
for (int i = 1; i < 150; i++) //h
{
for (int j = 1; j < 150; j++) //w
{
r = ssbj(i, j);
num = num + (Bitmap3.GetPixel(i, j).R/r - F) * (Bitmap4.GetPixel(i, j).R/r - G);
}
}
for (int i = 1; i < 150; i++) //h
{
for (int j = 1; j < 150; j++) //w
{
r = ssbj(i, j);
den1 = den1 + (Bitmap3.GetPixel(i, j).R/r - F)* (Bitmap3.GetPixel(i, j).R/r - F);
}
}
den1 = Convert .ToInt16 (Math.Sqrt (den1));
for (int i = 1; i < 150; i++) //h
{
for (int j = 1; j < 150; j++) //w
{
r = ssbj(i, j);
den2 = den2 + (Bitmap4.GetPixel(i, j).R/r - G) * (Bitmap4.GetPixel(i, j).R/r - G);
}
}
den2 = Convert.ToInt16(Math.Sqrt(den2));
if (den1 * den2 > 0)
{
ppd = Math.Round (num / (den1 * den2),3);
}
return ppd;
}
public int ssbj(int i,int j)
{
double r;
if (i > 75)
{
if (j > 75)
{
r = Math.Sqrt((i - 75) * (i - 75) + (j - 75) * (j - 75)); //求实时半径
}
else
{
r = Math.Sqrt((i - 75) * (i - 75) + j * j); //求实时半径
}
}
else
{
if (j > 75)
{
r = Math.Sqrt(i * i + (j - 75) * (j - 75)); //求实时半径
}
else
{
r = Math.Sqrt(i * i + j * j); //求实时半径
}
}
return Convert.ToInt16 (r);
}