首页 > 代码库 > 基于金字塔的模板匹配算法

基于金字塔的模板匹配算法

  在目标检测过程中,常用的方法就是设置一个模板,以滑动窗口的形式遍历整幅源图像(待检测的图像);每次滑动都会产生一个和模板等大小的ROI图像,基于某种度量方式,计算模板与当前ROI图像的相似性度量值。这样遍历完整幅图像后就会形成一个图像,找出最大值对应的位置(x,y),它就是我们要寻找的目标的位置。

  上面是模板匹配大致的步骤,当源图像很大,遍历完整幅图像很耗时,故提出了基于金字塔的模板匹配方法,下面是该方法涉及到几点:

  (1) 设置金字塔层数nLevels,创建源图像和模板图像对应的nLevels层金字塔图像;

  (2) 创建每层金字塔图像时,涉及到降采样(除以2),降采样后会出现锯齿,需要采用平滑滤波器进行处理;高斯平滑滤波器效果好但耗时,可以直接采用小模板的均值滤波器;

  (3) 计算模板与ROI图像的相似性值时,需要选择相似性度量准则;相似性度量准则有SAD(绝对值总和),SSD(平方差总和)和NCC(归一化相关系数),NCC的计算最耗时但效果最好,能很好的适应光照变化。

  理解了大致的流程和涉及到的操作后,可以直接写代码,金字塔匹配算法如下:

  1 function [r,c,nccImg] = pyramidMatch(img, template, nLevels)  2 % -------------------------------------------------------------------------  3 % 采用金字塔匹配算法进行模板匹配  4 %  5 % 过程:(1)为待匹配的图像和模板图像创建nLevels层金字塔图像  6 %       (2)从金字塔最高层开始进行匹配,最高层的要完全扫描匹配,得到的最佳匹配位置  7 % 后向下层传递(乘以2);根据传递的位置,在5*5的窗口范围内进行扫描匹配,如此这样  8 % 直到最低层。  9 %       (3)匹配时采用的相似性度量为归一化相关系数 10 %       (4)创建金字塔时进行了降采样(除2),然后用2*2的平滑滤波器进行了处理 11 %  12 % img-- 源图像(这里假设为灰度图) 13 % template-- 模板图像(假设为灰度图) 14 % nLevels-- 金字塔层数 15 % @r,c-- 源图像中最匹配的位置 16 % @nccImg-- 进行金字塔匹配时每层对应的归一化相关系数图像 17 % 18 % Author: L.L.He 19 % Time: 26/7/2014 20 %%------------------------------------------------------------------------- 21 imshow(img); 22 hold on; 23 [t_r,t_c] = size(template); 24 nccImg = cell(nLevels, 1); 25 % 这里计算待匹配图像和模板的图像金字塔 26 nStep = 2; %5*5 27 srcPrad = pyramid(img, nLevels); 28 temPrad = pyramid(template, nLevels); 29 [r,c,nccImg{nLevels}] = matchTemplate(srcPrad{nLevels}, temPrad{nLevels}); 30 for i=nLevels-1:-1:1 31     r_start = 2*r - floor((size(temPrad{i},1)-1)/2) - nStep; 32     r_end = r_start+2*nStep+1; 33     c_start = 2*c - floor((size(temPrad{i},2)-1)/2) - nStep; 34     c_end = c_start++2*nStep+1; 35     [r,c,nccImg{i}] = matchTemplate(srcPrad{i}, temPrad{i},... 36                       r_start, r_end, c_start, c_end); 37 end 38 c_r = round(t_r/2); 39 c_c = round(t_c/2); 40 rectangle(Position,[c-c_c+1,r-c_r+1,t_c,t_r], edgecolor, r); 41 end 42 % ------------------------------------------------------------------------- 43  44 % ========================================================================= 45 % 模板匹配算法 46 function [objr, objc, ncc_Img] = matchTemplate(img, template, r_start, ... 47                                 r_end, c_start, c_end) 48 [src_r,src_c] = size(img); 49 [t_r,t_c] = size(template); 50 if nargin == 2 51     r_start = 1; 52     r_end = src_r-t_r+1; 53     c_start = 1; 54     c_end = src_c-t_c+1; 55 end 56 % 这里先计算模板图像的归一化图像 57 norm_Img = normalize(template); 58 ncc_Img = zeros(r_end-r_start+1, c_end-c_start+1); 59 c_r = round(t_r/2); 60 c_c = round(t_c/2); 61 for r = r_start:r_end 62     for c = c_start:c_end 63         currPatch = img(r:r+t_r-1,c:c+t_c-1); 64         currPatch = normalize(currPatch); 65         ncc_Img(r+c_r-1,c+c_c-1) = NCC(norm_Img, currPatch); 66     end 67 end 68 [val_1,pos] = max(ncc_Img); 69 [val_2,objc] = max(val_1); 70 objr= pos(find(val_1==val_2)); 71 end 72 % ========================================================================= 73  74 % ========================================================================= 75 % 计算两幅图像的归一化相关系数(一种相似性度量),其绝对值越大表示越相似 76 function ncc = NCC(img_1, img_2, isNorm) 77 if ~exist(isNorm,var) 78     isNorm = 1; 79 end 80 % 判断参数是否是归一化后的图像 81 if ~isNorm 82     img_1 = normalize(img_1); 83     img_2 = normalize(img_2); 84 end 85 ncc = sum(sum(img_1.*img_2)) ./ size(img_1(:),1); 86 end 87 % ========================================================================= 88  89 % ========================================================================= 90 % 图像归一化 91 function norm_Img = normalize(img) 92 if size(img, 3) ~= 1 93     img = rgb2gray(img); 94 end 95 norm_Img = zeros(size(img)); 96 mu = mean(img(:)); 97 st = max(std(double(img(:))), eps); 98 norm_Img = bsxfun(@minus, img, mu); 99 norm_Img = bsxfun(@rdivide, norm_Img, st);100 end101 % =========================================================================102 103 % =========================================================================104 % 计算图像的金字塔,层数由nLevels参数指定,返回一个结构体,其中包含nLevels张图像105 function pyImg = pyramid(img, nLevels)106 % 创建金字塔中的每一层图像107 pyImg = cell(nLevels, 1);108 pyImg{1} = img;109 for i=2:nLevels110     pyImg{i} = downSample(pyImg{i-1});111 end  112 end113 % =========================================================================114 115 % =========================================================================116 % 对图像进行降采样(2*2)并平滑处理117 function d_img = downSample(img)118 % 如果原图像的行列是基数则补齐119 if mod(size(img,1), 2) ~= 0120     img = [img(1,:); img];121 end122 if mod(size(img,2), 2) ~= 0123     img = [img(:,1), img];124 end125 [r,c] = size(img);126 d_img = zeros(r/2, c/2);127 for i=1:2:r128     for j=1:2:c129         x = (i+1)/2;130         y = (j+1)/2;131         d_img(x,y) = sum(sum(img(i:i+1,j:j+1)))/4;132     end133 end134 end

  测试代码如下:

1 src = http://www.mamicode.com/rgb2gray(imread(src.jpg));2 template = rgb2gray(imread(template.jpg));3 [x,y,ncc_Img] = pyramidMatch(src, template, 4);

 

左图为源图像,中间图为模板图像,右边图为效果图

 

基于金字塔的模板匹配算法