標籤:
在目標檢測過程中,常用的方法就是設定一個模板,以滑動視窗的形式遍曆整幅源映像(待檢測的映像);每次滑動都會產生一個和模板等大小的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 = rgb2gray(imread(‘src.jpg‘));2 template = rgb2gray(imread(‘template.jpg‘));3 [x,y,ncc_Img] = pyramidMatch(src, template, 4);
左圖為源映像,中間圖為模板映像,右邊圖為
基於金字塔的模板匹配演算法