图像匹配计算量大的原因在于搜索窗口在待匹配的图像上进行滑动,每滑动一次就要做一次匹配相关运算,在不匹配点做的运算就是'无用'的,从而导致计算量上升。序贯相似性检测法在计算匹配度的同时,不断累积模板和像元的灰度差,当累积值大于某一指定阈值时,则说明该点为非匹配点,进行下一个位置的计算,这样大大减少了计算复杂度。
代码如下:
double dbMaxR = 0; //最大累加误差次数
double dbMinr=2000; //最小累积误差,dbr<LTK时,最小的r
double dSigmaST, dSigmaS, dSigmaT; // 中间结果
double dbr; //误差
int i, j, m, n ;
int nMaxWidth, nMaxHeight; //序贯匹配位置
long LR = 0; //累加误差次数
long LTK = 2000; //阈值
bool br = false;
CvScalar pixelSrc, pixelTem, pixel0, pixel1;
IplImage* TemplateSrc = cvLoadImage("D:\\13.jpg"); //模板图像
IplImage* src = cvLoadImage("D:\\24.jpg"); //原图
//计算dSigmaT
dSigmaT = 0;
for (n = 0; n < TemplateSrc->height; n++)
{
for (m = 0; m < TemplateSrc->width; m++)
{
pixelTem = cvGet2D(TemplateSrc, n, m);
dSigmaT += (double)pixelTem.val[0]; //修改
}
}
dSigmaT = dSigmaT / ((TemplateSrc->height)*(TemplateSrc->width));
//序贯算法
for (j = 0; j < src->height - TemplateSrc->height+1; j++)
{
for (i = 0; i < src->width - TemplateSrc->width + 1; i++)
{
dSigmaS = 0;
LR = 0;
dbr = 0;
//计算dSigmaS
for (n = 0; n < TemplateSrc->height; n++)
{
for (m = 0; m < TemplateSrc->width; m++)
{
pixelSrc = cvGet2D(src, j+n, i+m);
dSigmaS += (double)pixelSrc.val[0]; //修改;
}
}
dSigmaS = dSigmaS /((TemplateSrc->height)*(TemplateSrc->width));
//计算误差dbr、LR
for (n = 0; n < TemplateSrc->height; n++)
{
for (m = 0; m < TemplateSrc->width; m++)
{
pixelSrc = cvGet2D(src, j + n, i + m);
pixelTem = cvGet2D(TemplateSrc, n, m);
dbr += abs(pixelSrc.val[0] - dSigmaS - pixelTem.val[0] + dSigmaT);
if (dbr>=LTK)
{
LR = (m + 1)*(n + 1);
break; //跳出一次循环
}
}
if (dbr >= LTK) //再跳出一次循环
{
break;
}
}
if (dbr<dbMinr)
{
br = true;
dbMinr = dbr;
nMaxHeight = j;
nMaxWidth = i;
}
if (dbr >= LTK && LR > dbMaxR && br == false)
{
dbMaxR = LR;
nMaxHeight = j;
nMaxWidth = i;
}
}
}
//对目标像素进行赋值
for (j = nMaxHeight; j <TemplateSrc->height + nMaxHeight; j++)
{
for (i = nMaxWidth; i < TemplateSrc->width + nMaxWidth; i++)
{
pixel0 = cvGet2D(src, j , i );
pixel1.val[0] = pixel0.val[0] / 2;
pixel1.val[1] = pixel0.val[1] / 2;
pixel1.val[2] = pixel0.val[2] / 2;
cvSet2D(src,j, i, pixel1);
}
}
cvRectangle(src, cvPoint(nMaxWidth, nMaxHeight), cvPoint(nMaxWidth + TemplateSrc->width, TemplateSrc->height + nMaxHeight), cvScalar(0, 0, 255, 0), 1, 8, 0);
cvNamedWindow("White", CV_WINDOW_AUTOSIZE);
cvShowImage("White", src);
while (1)
{
if (cvWaitKey(100) == 27) break;
}
cvDestroyWindow("White");
cvReleaseImage(&src);
exit(0);