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


  在目標檢測過程中,常用的方法就是設置一個模板,以滑動窗口的形式遍歷整幅源圖像(待檢測的圖像);每次滑動都會產生一個和模板等大小的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 end
101 % =========================================================================
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:nLevels
110     pyImg{i} = downSample(pyImg{i-1});
111 end  
112 end
113 % =========================================================================
114 
115 % =========================================================================
116 % 對圖像進行降采樣(2*2)並平滑處理
117 function d_img = downSample(img)
118 % 如果原圖像的行列是基數則補齊
119 if mod(size(img,1), 2) ~= 0
120     img = [img(1,:); img];
121 end
122 if mod(size(img,2), 2) ~= 0
123     img = [img(:,1), img];
124 end
125 [r,c] = size(img);
126 d_img = zeros(r/2, c/2);
127 for i=1:2:r
128     for j=1:2:c
129         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     end
133 end
134 end

  測試代碼如下:

1 src = rgb2gray(imread('src.jpg'));
2 template = rgb2gray(imread('template.jpg'));
3 [x,y,ncc_Img] = pyramidMatch(src, template, 4);

 

左圖為源圖像,中間圖為模板圖像,右邊圖為效果圖

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM