图像匹配之序贯相似性检测法匹配
发布时间
阅读量:
阅读量
图像匹配计算量大的原因在于搜索窗口在待匹配的图像上进行滑动,每滑动一次就要做一次匹配相关运算,在不匹配点做的运算就是'无用'的,从而导致计算量上升。序贯相似性检测法在计算匹配度的同时,不断累积模板和像元的灰度差,当累积值大于某一指定阈值时,则说明该点为非匹配点,进行下一个位置的计算,这样大大减少了计算复杂度。
这里定义了一个绝对误差:

计算每一个子图像中像素点与模板中的像素点的绝对误差累积值,当该值大于设定阈值时,便可放弃计算该子图,进入下一子图的计算,并存下超出阈值时的累加次数。
opencv的编写的代码如下:
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include "highgui.h"
#include <math.h>
IplImage *src_gray1, *src_gray2, *src_gray3;
IplImage *T_gray1, *T_gray2, *T_gray3;
IplImage* S_img,*Match_image;
void AllocateImage(IplImage* I,IplImage* T) //给图像分配大小
{
CvSize sz = cvGetSize(I);
CvSize sz_T = cvGetSize(T);
src_gray1 = cvCreateImage( sz, IPL_DEPTH_8U, 1); //原图的三个通道
src_gray2 = cvCreateImage( sz, IPL_DEPTH_8U, 1);
src_gray3 = cvCreateImage( sz, IPL_DEPTH_8U, 1);
T_gray1 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1); //模板的三个通道
T_gray2 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1);
T_gray3 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1);
S_img = cvCreateImage( sz_T, IPL_DEPTH_8U, 1); //模板覆盖下的子图
Match_image = cvCreateImage( sz, IPL_DEPTH_8U, 1); //匹配位置图,图中的白点即为匹配得到的位置
cvSetZero(Match_image);
}
long abs_value (long value)
{
if( value < 0 )
value = -value;
return value;
}
int main(int argc, char* argv[])
{
IplImage* img = cvLoadImage("Images/序贯相似性.bmp"); //加载图像 原图
IplImage* T_img = cvLoadImage("Images/序贯相似性模板.bmp"); //模板图
int i,j,m,n,Max_width,Max_height;
unsigned int src_width = img->width;
unsigned int src_height = img->height;
unsigned int T_width = T_img->width;
unsigned int T_height = T_img->height;
unsigned long S_mean=0, T_mean=0, dbr=0, lR= 0, dbr_threshold = 5000, dbr_min = 5000;
AllocateImage( img, T_img);
cvNamedWindow("my picture",CV_WINDOW_AUTOSIZE);
cvNamedWindow("my model",CV_WINDOW_AUTOSIZE);
cvNamedWindow("result",CV_WINDOW_AUTOSIZE);
cvSplit( img, src_gray1, src_gray2, src_gray3, 0);
cvSplit( T_img, T_gray1, T_gray2, T_gray3, 0);
for( m=0; m<T_height; m++) //计算模板T的均值
{
unsigned char* T_ptr = (unsigned char*)T_gray1->imageData + m*T_gray1->widthStep;
for( n=0; n<T_width; n++)
{
unsigned char T_value = T_ptr[n];
T_mean = T_mean + T_value*T_value;
}
}
T_mean = T_mean/(T_width*T_height);
for( i= 0; i<(src_height-T_height); i++) //模板图在搜索图上平移
{
for( j= 0; j<(src_width-T_width); j++)
{
S_mean = 0;
lR = 0;
dbr = 0;
cvSetImageROI(src_gray1,
cvRect( j, i, T_img->width, T_img->height )
);
cvCopy( src_gray1, S_img, 0 );
cvResetImageROI(src_gray1);
for( m=0; m<T_height; m++) //计算子图S的均值
{
unsigned char* S_ptr = (unsigned char*)S_img->imageData + m*S_img->widthStep;
for( n=0; n<T_width; n++)
{
unsigned char S_value = S_ptr[n];
S_mean = S_mean + S_value*S_value;
}
}
S_mean = S_mean/(T_width*T_height);
for( m=0; m<T_height; m++) //计算误差dbr,lR
{
unsigned char* S_ptr = (unsigned char*)S_img->imageData + m*S_img->widthStep;
unsigned char* T_ptr = (unsigned char*)T_gray1->imageData + m*T_gray1->widthStep;
for( n=0; n<T_width; n++)
{
unsigned char S_value = S_ptr[n];
unsigned char T_value = T_ptr[n];
dbr += abs_value( (long)S_value - S_mean - T_value + T_mean );
if ( dbr>= dbr_threshold )
{
lR = (m+1)*(n+1);
break; //跳出一次循环
}
}
if ( dbr>= dbr_threshold )
{
break; //再跳出一次循环
}
}
if ( dbr < dbr_min ) //找出误差最小的点,就是匹配点
{
dbr_min = dbr;
Max_height = i;
Max_width = j;
}
}
}
cvSet2D( Match_image, Max_height, Max_width, cvScalar( 255, 0, 0, 0) );
cvRectangle(img, cvPoint(Max_width, Max_height), cvPoint(Max_width+T_width, Max_height+T_height), cvScalar(0, 0, 255, 0), 1,8,0);
cvShowImage("my picture",img); //原图,图中红色矩形区域即为匹配的位置
cvShowImage("my model",T_img); //模板图
cvShowImage("result",Match_image); //匹配的位置
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&T_img);
cvReleaseImage(&src_gray1);
cvReleaseImage(&src_gray2);
cvReleaseImage(&src_gray3);
cvReleaseImage(&T_gray1);
cvReleaseImage(&T_gray2);
cvReleaseImage(&T_gray3);
cvReleaseImage(&Match_image);
cvReleaseImage(&S_img);
cvDestroyWindow("my picture");
cvDestroyWindow("my model");
cvDestroyWindow("result");
return 0;
}

全部评论 (0)
还没有任何评论哟~
