不变矩匹配法 TM算法 具有平移、旋转、尺寸不变性

p+q>=2

归一化公式:

算法过程:计算 分别计算模板和原图的7个不变矩 ,根据归一化公式得出相似度。
代码如下:
(取b通道作为检测的通道)
//源文件.cpp
<pre name="code" class="cpp">void Ctry::OnTryTyr1()
{
//TODO: 在此添加命令处理程序代码
IplImage* TemplateSrc = cvLoadImage("D:\\13.jpg"); //模板图像
IplImage* Src = cvLoadImage("D:\\24.jpg"); //原图
int i, j; //循环变量
double dbr; //原图,模板的相似度
double temp; // 临时变量
double Su00, Su02, Su20, Su11, Su30, Su12, Su21, Su03;
double Tu00, Tu02, Tu20, Tu11, Tu30, Tu12, Tu21, Tu03;
double dbR; //原图,模板的相似度
double Sa[8], Ta[8]; //原图,模板7个不变矩,二阶,三阶重心矩
double dSigmaST = 0; //中间结果
double dSigmaT = 0;
double dSigmaS = 0;
//计算重心x,y坐标
CalBarycenter(Src, &nBarycenterX, &nBarycenterY);
CalBarycenter(TemplateSrc, &nTBarycenterX, &nTBarycenterY);
//计算二阶,三阶矩(规格化)
Su00 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 0, 0);
Su02 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 0, 2) / pow(Su00,2);
Su20 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 2, 0) / pow(Su00, 2);
Su11 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 1, 1) / pow(Su00, 2);
Su30 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 3, 0) / pow(Su00, 2.5);
Su12 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 1, 2) / pow(Su00, 2.5);
Su21 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 2, 1) / pow(Su00, 2.5);
Su03 = BarycenterMoment(Src, &nBarycenterX, &nBarycenterY, 0, 3) / pow(Su00, 2.5);
Tu00 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 0, 0);
Tu02 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 0, 2) / pow(Tu00, 2);
Tu20 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 2, 0) / pow(Tu00, 2);
Tu11 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 1, 1) / pow(Tu00, 2);
Tu30 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 3, 0) / pow(Tu00, 2.5);
Tu12 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 1, 2) / pow(Tu00, 2.5);
Tu21 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 2, 1) / pow(Tu00, 2.5);
Tu03 = BarycenterMoment(TemplateSrc, &nTBarycenterX, &nTBarycenterY, 0, 3) / pow(Tu00, 2.5);
Sa[1] = Su02 + Su20;
Sa[2] = (Su20 - Su02)*(Su20 - Su02) + 4 * Su11*Su11;
Sa[3] = pow((Su30 - 3 * Su12), 2) + pow((3 * Su21 - Su03), 2);
Sa[4] = pow((Su30 + Su12), 2) + pow((Su21 + Su03), 2);
Sa[5] = (Su30 - 3 * Su12)*(Su30 + Su12)*(pow((Su30 + Su12), 2) - 3 * pow((Su21 + Su03), 2)) + (3 * Su21 - Su03)*(Su21 + Su03)*(3 * pow((Su30 + Su12), 2) - pow((Su21 + Su03), 2));
Sa[6] = (Su20 - Su02)*(pow((Su30 + Su12), 2) - pow((Su21 + Su03), 2)) + 4 * Su11*(Su30 + Su12)*(Su21 + Su03);
Sa[7] = (3 * Su21 - Su03)*(Su30 + Su12)*(pow((Su30 + Su12), 2) - 3 * pow((Su21 + Su03), 2)) + (Su30 - 3 * Su12)*(Su21 + Su03)*(3 * pow((Su30 + Su12), 2) - pow((Su21 + Su03), 2));
Ta[1] = Tu02 + Tu20;
Ta[2] = (Tu20 - Tu02)*(Tu20 - Tu02) + 4 * Tu11*Tu11;
Ta[3] = pow((Tu30 - 3 * Tu12), 2) + pow((3 * Tu21 - Tu03), 2);
Ta[4] = pow((Tu30 + Tu12), 2) + pow((Tu21 + Tu03), 2);
Ta[5] = (Tu30 - 3 * Tu12)*(Tu30 + Tu12)*(pow((Tu30 + Tu12), 2) - 3 * pow((Tu21 + Tu03), 2)) + (3 * Tu21 - Tu03)*(Tu21 + Tu03)*(3 * pow((Tu30 + Tu12), 2) - pow((Tu21 + Tu03), 2));
Ta[6] = (Tu20 - Tu02)*(pow((Tu30 + Tu12), 2) - pow((Tu21 + Tu03), 2)) + 4 * Tu11*(Tu30 + Tu12)*(Tu21 + Tu03);
Ta[7] = (3 * Tu21 - Tu03)*(Tu30 + Tu12)*(pow((Tu30 + Tu12), 2) - 3 * pow((Tu21 + Tu03), 2)) + (Tu30 - 3 * Tu12)*(Tu21 + Tu03)*(3 * pow((Tu30 + Tu12), 2) - pow((Tu21 + Tu03), 2));
for (int i = 1; i < 8; i++)
{
temp = Sa[i] * Ta[i];
dSigmaST += temp;
dSigmaT += pow(Ta[i], 2);
dSigmaS += pow(Sa[i], 2);
}
dbr = dSigmaST / (sqrt(dSigmaS)*sqrt(dSigmaT));
//显示匹配的相似度
CString str;
str.Format(_T("%lf"), dbr);
AfxMessageBox(str);
}
void Ctry::CalBarycenter(IplImage* src, int *nBarycenterX0, int *nBarycenterY0)
{
CvScalar pixel0;
double m00=0, m10=0, m01=0; //0次矩m00, x方向一次矩m01, y方向一次矩m10
double temp; //临时变量
//求0次矩m00, x方向一次矩m01, y方向一次矩m10
for (int j = 0; j < src->height; j++)
{
for (int i = 0; i <src->width; i++)
{
pixel0 = cvGet2D(src, j, i);
m00 += pixel0.val[0];
m10 += i*pixel0.val[0];
m01 += j*pixel0.val[0];
}
}
//重心x,y坐标
*nBarycenterX0 = (int)(m10 / m00 + 0.5);
*nBarycenterY0 = (int)(m01 / m00 + 0.5);
}
double Ctry::BarycenterMoment(IplImage* src, int *nBarycenterX0, int *nBarycenterY0, int ip, int jp)
{
double temp; //临时变量
double dbImageMoment = 0; //图像的矩
CvScalar pixel1;
//力矩的计算
for (int j = 0; j < src->height; j++)
{
for (int i = 0; i < src->width; i++)
{
pixel1 = cvGet2D(src, j, i);
temp = pow((double)(i - *nBarycenterX0), ip)*pow((double)(j - *nBarycenterY0), jp);
temp = temp*pixel1.val[0];
dbImageMoment = dbImageMoment + temp;
}
}
return dbImageMoment;
}
//头文件.h
public:
void CalBarycenter(IplImage* src, int *nBarycenterX0, int *nBarycenterY0);
double BarycenterMoment(IplImage* src, int *nBarycenterX0, int *nBarycenterY0, int ip, int jp);
public:
//原图模板重心x,y坐标值
int nBarycenterX, nBarycenterY;
int nTBarycenterX, nTBarycenterY;
匹配结果: