DPM(Defomable Parts Model) 源码分析-检测(二)

来源:互联网 发布:文字转word软件 编辑:程序博客网 时间:2024/05/28 11:30

原文转载自:http://blog.csdn.net/ttransposition/article/details/12954195

DPM(Defomable Parts Model)原理

首先声明此版本为V3.1。因为和论文最相符。V4增加了模型数由2个增加为6个,V5提取了语义特征。源码太长纯代码应该在2K+,只选取了核心部分代码

demo.m

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. function demo()  
  2.   
  3. test('000034.jpg''car');  
  4. test('000061.jpg''person');  
  5. test('000084.jpg''bicycle');  
  6.   
  7. function test(name, cls)  
  8. % load and display image  
  9. im=imread(name);  
  10. clf;  
  11. image(im);  
  12. axis equal;   
  13. axis on;  
  14. disp('input image');  
  15. disp('press any key to continue'); pause;  
  16.   
  17. % load and display model  
  18. load(['VOC2007/' cls '_final']); %加载模型  
  19. visualizemodel(model);  
  20. disp([cls ' model']);  
  21. disp('press any key to continue'); pause;  
  22.   
  23. % detect objects  
  24. boxes = detect(im, model, 0); %model为mat中的结构体  
  25. top = nms(boxes, 0.5);  %Non-maximum suppression.  
  26. showboxes(im, top);  
  27. %print(gcf, '-djpeg90''-r0', [cls '.jpg']);  
  28. disp('detections');  
  29. disp('press any key to continue'); pause;  
  30.   
  31. % get bounding boxes  
  32. bbox = getboxes(model, boxes);  %根据检测到的root,parts,预测bounding  
  33. top = nms(bbox, 0.5);  
  34. bbox = clipboxes(im, top); %预测出来的bounding,可能会超过图像原始尺寸,所以要减掉  
  35. showboxes(im, bbox);  
  36. disp('bounding boxes');  
  37. disp('press any key to continue'); pause;  


detect.m

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. function [boxes] = detect(input, model, thresh, bbox, ...  
  2.                           overlap, label, fid, id, maxsize)  
  3. % 论文 fig.4                         
  4.   
  5. % boxes = detect(input, model, thresh, bbox, overlap, label, fid, id, maxsize)  
  6. % Detect objects in input using a model and a score threshold.  
  7. % Higher threshold leads to fewer detections.  
  8. % boxes = [rx1 ry1 rx2 ry2 | px1 py1 px2 py2 ...| componetindex | score ]  
  9. % The function returns a matrix with one row per detected object.  The  
  10. % last column of each row gives the score of the detection.  The  
  11. % column before last specifies the component used for the detection.  
  12. % The first 4 columns specify the bounding box for the root filter and  
  13. % subsequent columns specify the bounding boxes of each part.  
  14. %  
  15. % If bbox is not empty, we pick best detection with significant overlap.   
  16. % If label and fid are included, we write feature vectors to a data file.  
  17.   
  18. %phase 2: im, model, 0, bbox, overlap, 1, fid, 2*i-1  
  19. % trian boxex : detect(im, model, 0, bbox, overlap)  
  20. if nargin > 3 && ~isempty(bbox)  
  21.   latent = true;  
  22. else  
  23.   latent = false;  
  24. end  
  25.   
  26. if nargin > 6 && fid ~= 0  
  27.   write = true;  
  28. else  
  29.   write = false;  
  30. end  
  31.   
  32. if nargin < 9  
  33.   maxsize = inf;  
  34. end  
  35.   
  36. % we assume color images  
  37. input = color(input);   %如果是灰度图,扩充为三通道 R=G=B=Gray  
  38.   
  39. % prepare model for convolutions  
  40. rootfilters = [];  
  41. for i = 1:length(model.rootfilters) %   
  42.   rootfilters{i} = model.rootfilters{i}.w;% r*w*31维向量,9(方向范围 0~180) +18(方向范围 0-360)+4(cell熵和)  
  43. end  
  44. partfilters = [];  
  45. for i = 1:length(model.partfilters)  
  46.   partfilters{i} = model.partfilters{i}.w;  
  47. end  
  48.   
  49. % cache some data 获取所有 root,part的所有信息  
  50. for c = 1:model.numcomponents   % releas3.1 一种对象,只有2个模型,releas5 有3*2个模型  
  51.   ridx{c} = model.components{c}.rootindex; % m1=1,m2=2  
  52.   oidx{c} = model.components{c}.offsetindex; %o1=1,o2=2  
  53.   root{c} = model.rootfilters{ridx{c}}.w;  
  54.   rsize{c} = [size(root{c},1) size(root{c},2)]; %root size,单位为 sbin*sbin的block块,相当于原始HOG中的一个cell  
  55.   numparts{c} = length(model.components{c}.parts); %目前为固定值6个,但是有些part是 fake  
  56.   for j = 1:numparts{c}  
  57.     pidx{c,j} = model.components{c}.parts{j}.partindex; %part是在该对象的所有component的part下连续编号  
  58.     didx{c,j} = model.components{c}.parts{j}.defindex;  % 在 rootfiter中的 anchor location  
  59.     part{c,j} = model.partfilters{pidx{c,j}}.w; % 6*6*31  
  60.     psize{c,j} = [size(part{c,j},1) size(part{c,j},2)]; %   
  61.     % reverse map from partfilter index to (component, part#)  
  62.     rpidx{pidx{c,j}} = [c j];  
  63.   end  
  64. end  
  65.   
  66. % we pad the feature maps to detect partially visible objects  
  67. padx = ceil(model.maxsize(2)/2+1); % 7/2+1 = 5  
  68. pady = ceil(model.maxsize(1)/2+1); % 11/2+1 = 7  
  69.   
  70. % the feature pyramid  
  71. interval = model.interval;  %10  
  72. %--------------------------------特征金字塔---------------------------------------------------------  
  73. % feat的尺寸为 img.rows/sbin,img.cols/sbin  
  74. % scales:缩放了多少  
  75. [feat, scales] = featpyramid(input, model.sbin, interval); % 8,10  
  76.   
  77. % detect at each scale  
  78. best = -inf;  
  79. ex = [];  
  80. boxes = [];  
  81. %---------------------逐层检测目标-----------------------------------------------------------%  
  82. for level = interval+1:length(feat) %注意是从第二层开始  
  83.   scale = model.sbin/scales(level);  % 1/缩小了多少    
  84.   if size(feat{level}, 1)+2*pady < model.maxsize(1) || ... %扩展后还是未能达到 能同时计算两个component的得分  
  85.      size(feat{level}, 2)+2*padx < model.maxsize(2) || ...  
  86.      (write && ftell(fid) >= maxsize) %已经没有空间保存样本了  
  87.     continue;  
  88.   end  
  89.     
  90.   if latent %训练时使用,检测时跳过  
  91.     skip = true;  
  92.     for c = 1:model.numcomponents  
  93.       root_area = (rsize{c}(1)*scale) * (rsize{c}(2)*scale);% rootfilter  
  94.       box_area = (bbox(3)-bbox(1)+1) * (bbox(4)-bbox(2)+1); % bbox该class 所有 rootfilter 的交集即minsize  
  95.       if (root_area/box_area) >= overlap && (box_area/root_area) >= overlap %这句话真纠结,a>=0.7b,b>=0.7a -> a>=0.7b>=0.49a  
  96.         skip = false;  
  97.       end  
  98.     end  
  99.     if skip  
  100.       continue;  
  101.     end  
  102.   end  
  103.       
  104.   % -----------convolve feature maps with filters -----------  
  105.   %rootmatch,partmatch ,得分图root的尺度总是part的一半,  
  106.   %rootmatch尺寸是partmatch的一半  
  107.   featr = padarray(feat{level}, [pady padx 0], 0);  % 上下各补充 pady 行0,左右各补充padx行 0  
  108.   %C = fconv(A, cell of B, start, end);  
  109.   rootmatch = fconv(featr, rootfilters, 1, length(rootfilters));  
  110.   if length(partfilters) > 0  
  111.     featp = padarray(feat{level-interval}, [2*pady 2*padx 0], 0);  
  112.     partmatch = fconv(featp, partfilters, 1, length(partfilters));  
  113.   end  
  114.   %-------------------逐component检测-----------------------------------  
  115.   % 参见论文 Fig 4  
  116.   % 最终得到  综合得分图   score  
  117.   for c = 1:model.numcomponents  
  118.     % root score + offset  
  119.     score = rootmatch{ridx{c}} + model.offsets{oidx{c}}.w;    
  120.     % add in parts  
  121.     for j = 1:numparts{c}  
  122.       def = model.defs{didx{c,j}}.w;  
  123.       anchor = model.defs{didx{c,j}}.anchor;  
  124.       % the anchor position is shifted to account for misalignment  
  125.       % between features at different resolutions  
  126.       ax{c,j} = anchor(1) + 1; %  
  127.       ay{c,j} = anchor(2) + 1;  
  128.       match = partmatch{pidx{c,j}};  
  129.       [M, Ix{c,j}, Iy{c,j}] = dt(-match, def(1), def(2), def(3), def(4)); % dx,dy,dx^2,dy^2的偏移惩罚系数  
  130.       % M part的综合匹配得分图,与part尺寸一致。Ix{c,j}, Iy{c,j} 即part实际的最佳位置(相对于root)  
  131.       % 参见论文公式 9  
  132.       score = score - M(ay{c,j}:2:ay{c,j}+2*(size(score,1)-1), ...  
  133.                         ax{c,j}:2:ax{c,j}+2*(size(score,2)-1));  
  134.     end  
  135.       
  136.     %-------阈值淘汰------------------------  
  137.     if ~latent  
  138.       % get all good matches  
  139.       % ---thresh  在 分类时为0,在 找 hard exmaple 时是 -1.05--  
  140.       I = find(score > thresh);  %返回的是从上到下从左到右的索引  
  141.       [Y, X] = ind2sub(size(score), I);  %还原为 行,列坐标        
  142.       tmp = zeros(length(I), 4*(1+numparts{c})+2);  %一个目标的root,part,score信息,见程序开头说明  
  143.       for i = 1:length(I)  
  144.         x = X(i);  
  145.         y = Y(i);  
  146.         [x1, y1, x2, y2] = rootbox(x, y, scale, padx, pady, rsize{c});  
  147.         b = [x1 y1 x2 y2];  
  148.         if write  
  149.           rblocklabel = model.rootfilters{ridx{c}}.blocklabel;  
  150.           oblocklabel = model.offsets{oidx{c}}.blocklabel;        
  151.           f = featr(y:y+rsize{c}(1)-1, x:x+rsize{c}(2)-1, :);  
  152.           xc = round(x + rsize{c}(2)/2 - padx); %   
  153.           yc = round(y + rsize{c}(1)/2 - pady);  
  154.           ex = [];  
  155.           ex.header = [label; id; level; xc; yc; ...  
  156.                        model.components{c}.numblocks; ...  
  157.                        model.components{c}.dim];  
  158.           ex.offset.bl = oblocklabel;  
  159.           ex.offset.w = 1;  
  160.           ex.root.bl = rblocklabel;  
  161.           width1 = ceil(rsize{c}(2)/2);  
  162.           width2 = floor(rsize{c}(2)/2);  
  163.           f(:,1:width2,:) = f(:,1:width2,:) + flipfeat(f(:,width1+1:end,:));  
  164.           ex.root.w = f(:,1:width1,:);  
  165.           ex.part = [];  
  166.         end  
  167.         for j = 1:numparts{c}  
  168.           [probex, probey, px, py, px1, py1, px2, py2] = ...  
  169.               partbox(x, y, ax{c,j}, ay{c,j}, scale, padx, pady, ...  
  170.                       psize{c,j}, Ix{c,j}, Iy{c,j});  
  171.           b = [b px1 py1 px2 py2];  
  172.           if write  
  173.             if model.partfilters{pidx{c,j}}.fake  
  174.               continue;  
  175.             end  
  176.             pblocklabel = model.partfilters{pidx{c,j}}.blocklabel;  
  177.             dblocklabel = model.defs{didx{c,j}}.blocklabel;  
  178.             f = featp(py:py+psize{c,j}(1)-1,px:px+psize{c,j}(2)-1,:);  
  179.             def = -[(probex-px)^2; probex-px; (probey-py)^2; probey-py];  
  180.             partner = model.partfilters{pidx{c,j}}.partner;  
  181.             if partner > 0  
  182.               k = rpidx{partner}(2);  
  183.               [kprobex, kprobey, kpx, kpy, kpx1, kpy1, kpx2, kpy2] = ...  
  184.                   partbox(x, y, ax{c,k}, ay{c,k}, scale, padx, pady, ...  
  185.                           psize{c,k}, Ix{c,k}, Iy{c,k});  
  186.               kf = featp(kpy:kpy+psize{c,k}(1)-1,kpx:kpx+psize{c,k}(2)-1,:);  
  187.               % flip linear term in horizontal deformation model  
  188.               kdef = -[(kprobex-kpx)^2; kpx-kprobex; ...  
  189.                        (kprobey-kpy)^2; kprobey-kpy];  
  190.               f = f + flipfeat(kf);  
  191.               def = def + kdef;  
  192.             else  
  193.               width1 = ceil(psize{c,j}(2)/2);  
  194.               width2 = floor(psize{c,j}(2)/2);  
  195.               f(:,1:width2,:) = f(:,1:width2,:) + flipfeat(f(:,width1+1:end,:));  
  196.               f = f(:,1:width1,:);  
  197.             end  
  198.             ex.part(j).bl = pblocklabel;  
  199.             ex.part(j).w = f;  
  200.             ex.def(j).bl = dblocklabel;  
  201.             ex.def(j).w = def;  
  202.           end  
  203.         end  
  204.         if write  
  205.           exwrite(fid, ex); % 写入负样本  
  206.         end  
  207.         tmp(i,:) = [b c score(I(i))];  
  208.       end  
  209.       boxes = [boxes; tmp];  
  210.     end  
  211.   
  212.     if latent  
  213.       % get best match  
  214.       for x = 1:size(score,2)  
  215.         for y = 1:size(score,1)  
  216.           if score(y, x) > best    
  217.             % 以该(y,x)为left-top点的rootfilter的范围在原图像中的位置  
  218.             [x1, y1, x2, y2] = rootbox(x, y, scale, padx, pady, rsize{c});  
  219.             % intesection with bbox  
  220.             xx1 = max(x1, bbox(1));  
  221.             yy1 = max(y1, bbox(2));  
  222.             xx2 = min(x2, bbox(3));  
  223.             yy2 = min(y2, bbox(4));  
  224.             w = (xx2-xx1+1);  
  225.             h = (yy2-yy1+1);  
  226.             if w > 0 && h > 0  
  227.               % check overlap with bbox  
  228.               inter = w*h;  
  229.               a = (x2-x1+1) * (y2-y1+1); % rootfilter 的面积  
  230.               b = (bbox(3)-bbox(1)+1) * (bbox(4)-bbox(2)+1); % bbox的面积  
  231.               % 计算很很独特,如果只是 inter / b 那么 如果a很大,只是一部分与 bounding box重合,那就不可靠了,人再怎么标注错误,也不会这么大  
  232.               % 所以,a越大,要求的重合率越高才好,所以分母+a,是个不错的选择,但是这样减小的太多了,所以减去 inter  
  233.               o = inter / (a+b-inter);  
  234.               if (o >= overlap)  
  235.                 %  
  236.                 best = score(y, x);  
  237.                 boxes = [x1 y1 x2 y2];  
  238.                 % 这一部分一直被覆盖,最后保留的是 best样本  
  239.                 if write                    
  240.                   f = featr(y:y+rsize{c}(1)-1, x:x+rsize{c}(2)-1, :);  
  241.                   rblocklabel = model.rootfilters{ridx{c}}.blocklabel;  
  242.                   oblocklabel = model.offsets{oidx{c}}.blocklabel;        
  243.                   xc = round(x + rsize{c}(2)/2 - padx);  
  244.                   yc = round(y + rsize{c}(1)/2 - pady);            
  245.                   ex = [];  
  246.                   % label; id; level; xc; yc,正样本的重要信息!  
  247.                   % xc,yc,居然是相对于剪切后的图片  
  248.                   ex.header = [label; id; level; xc; yc; ...  
  249.                                model.components{c}.numblocks; ...  
  250.                                model.components{c}.dim];  
  251.                   ex.offset.bl = oblocklabel;  
  252.                   ex.offset.w = 1;  
  253.                   ex.root.bl = rblocklabel;  
  254.                   width1 = ceil(rsize{c}(2)/2);  
  255.                   width2 = floor(rsize{c}(2)/2);  
  256.                   f(:,1:width2,:) = f(:,1:width2,:) + flipfeat(f(:,width1+1:end,:));  
  257.                   ex.root.w = f(:,1:width1,:); %样本特征  
  258.                   ex.part = [];  
  259.                 end  
  260.                 for j = 1:numparts{c}  
  261.                   %probex,probey综合得分最高的位置,相对于featp  
  262.                   %px1,py1,px2,py2 转化成相对于featr  
  263.                   [probex, probey, px, py, px1, py1, px2, py2] = ...  
  264.                       partbox(x, y, ax{c,j}, ay{c,j}, scale, ...  
  265.                               padx, pady, psize{c,j}, Ix{c,j}, Iy{c,j});  
  266.                   boxes = [boxes px1 py1 px2 py2];  
  267.                   if write  
  268.                     if model.partfilters{pidx{c,j}}.fake  
  269.                       continue;  
  270.                     end  
  271.                     p = featp(py:py+psize{c,j}(1)-1, ...  
  272.                               px:px+psize{c,j}(2)-1, :);  
  273.                     def = -[(probex-px)^2; probex-px; (probey-py)^2; probey-py];  
  274.                     pblocklabel = model.partfilters{pidx{c,j}}.blocklabel;  
  275.                     dblocklabel = model.defs{didx{c,j}}.blocklabel;  
  276.                     partner = model.partfilters{pidx{c,j}}.partner;  
  277.                     if partner > 0  
  278.                       k = rpidx{partner}(2);  
  279.                       [kprobex, kprobey, kpx, kpy, kpx1, kpy1, kpx2, kpy2] = ...  
  280.                           partbox(x, y, ax{c,k}, ay{c,k}, scale, padx, pady, ...  
  281.                                   psize{c,k}, Ix{c,k}, Iy{c,k});  
  282.                       kp = featp(kpy:kpy+psize{c,k}(1)-1, ...  
  283.                                  kpx:kpx+psize{c,k}(2)-1, :);  
  284.                       % flip linear term in horizontal deformation model  
  285.                       kdef = -[(kprobex-kpx)^2; kpx-kprobex; ...  
  286.                                (kprobey-kpy)^2; kprobey-kpy];  
  287.                       p = p + flipfeat(kp);  
  288.                       def = def + kdef;  
  289.                     else  
  290.                       width1 = ceil(psize{c,j}(2)/2);  
  291.                       width2 = floor(psize{c,j}(2)/2);  
  292.                       p(:,1:width2,:) = p(:,1:width2,:) + ...  
  293.                           flipfeat(p(:,width1+1:end,:));  
  294.                       p = p(:,1:width1,:);  
  295.                     end  
  296.                     ex.part(j).bl = pblocklabel;  
  297.                     ex.part(j).w = p;  
  298.                     ex.def(j).bl = dblocklabel;  
  299.                     ex.def(j).w = def;  
  300.                   end  
  301.                 end  
  302.                 boxes = [boxes c best];  
  303.               end  
  304.             end  
  305.           end  
  306.         end  
  307.       end  
  308.     end  
  309.   end  
  310. end  
  311.   
  312. if latent && write && ~isempty(ex)  
  313.   exwrite(fid, ex); %datfile  
  314. end  
  315.   
  316. % The functions below compute a bounding box for a root or part   
  317. template placed in the feature hierarchy.  
  318. %  
  319. % coordinates need to be transformed to take into account:  
  320. % 1. padding from convolution  
  321. % 2. scaling due to sbin & image subsampling  
  322. % 3. offset from feature computation      
  323. %  
  324.   
  325. function [x1, y1, x2, y2] = rootbox(x, y, scale, padx, pady, rsize)  
  326. x1 = (x-padx)*scale+1;  %图像是先缩放(构造金字塔时)再打补丁  
  327. y1 = (y-pady)*scale+1;  
  328. x2 = x1 + rsize(2)*scale - 1; % 宽度也要缩放  
  329. y2 = y1 + rsize(1)*scale - 1;  
  330.   
  331. function [probex, probey, px, py, px1, py1, px2, py2] = ...  
  332.     partbox(x, y, ax, ay, scale, padx, pady, psize, Ix, Iy)  
  333. probex = (x-1)*2+ax; %最优位置  
  334. probey = (y-1)*2+ay;  
  335. px = double(Ix(probey, probex)); %综合得分最高的位置  
  336. py = double(Iy(probey, probex));  
  337. px1 = ((px-2)/2+1-padx)*scale+1; % pading是root的两倍  
  338. py1 = ((py-2)/2+1-pady)*scale+1;  
  339. px2 = px1 + psize(2)*scale/2 - 1;  
  340. py2 = py1 + psize(1)*scale/2 - 1;  
  341.   
  342. % write an example to the data file  
  343. function exwrite(fid, ex)  
  344. fwrite(fid, ex.header, 'int32');  
  345. buf = [ex.offset.bl; ex.offset.w(:); ...  
  346.        ex.root.bl; ex.root.w(:)];  
  347. fwrite(fid, buf, 'single');  
  348. for j = 1:length(ex.part)  
  349.   if ~isempty(ex.part(j).w)  
  350.     buf = [ex.part(j).bl; ex.part(j).w(:); ...  
  351.            ex.def(j).bl; ex.def(j).w(:)];  
  352.     fwrite(fid, buf, 'single');  
  353.   end  
  354. end  


features.cc

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <math.h>  
  2. #include "mex.h"  
  3.   
  4. // small value, used to avoid division by zero  
  5. #define eps 0.0001  
  6.   
  7. #define bzero(a, b) memset(a, 0, b)   
  8. int round(float a) { float tmp = a - (int)a; if( tmp >= 0.5 ) return (int)a + 1; else return (int)a; }  
  9. // unit vectors used to compute gradient orientation  
  10. // cos(20*i)  
  11. double uu[9] = {1.0000,   
  12.         0.9397,   
  13.         0.7660,   
  14.         0.500,   
  15.         0.1736,   
  16.         -0.1736,   
  17.         -0.5000,   
  18.         -0.7660,   
  19.         -0.9397};  
  20. //sin(20*i)  
  21. double vv[9] = {0.0000,   
  22.         0.3420,   
  23.         0.6428,   
  24.         0.8660,   
  25.         0.9848,   
  26.         0.9848,   
  27.         0.8660,   
  28.         0.6428,   
  29.         0.3420};  
  30.   
  31. static inline double min(double x, double y) { return (x <= y ? x : y); }  
  32. static inline double max(double x, double y) { return (x <= y ? y : x); }  
  33.   
  34. static inline int min(int x, int y) { return (x <= y ? x : y); }  
  35. static inline int max(int x, int y) { return (x <= y ? y : x); }  
  36.   
  37. // main function:  
  38. // takes a double color image and a bin size   
  39. // returns HOG features  
  40. mxArray *process(const mxArray *mximage, const mxArray *mxsbin) {  
  41.   double *im = (double *)mxGetPr(mximage);  
  42.   const int *dims = mxGetDimensions(mximage);  
  43.   if (mxGetNumberOfDimensions(mximage) != 3 ||  
  44.       dims[2] != 3 ||  
  45.       mxGetClassID(mximage) != mxDOUBLE_CLASS)  
  46.     mexErrMsgTxt("Invalid input");  
  47.   
  48.   int sbin = (int)mxGetScalar(mxsbin);  
  49.   
  50.   // memory for caching orientation histograms & their norms  
  51.   int blocks[2];  
  52.   blocks[0] = (int)round((double)dims[0]/(double)sbin);//行  
  53.   blocks[1] = (int)round((double)dims[1]/(double)sbin);//列  
  54.   double *hist = (double *)mxCalloc(blocks[0]*blocks[1]*18, sizeof(double));//只需要计算18bin,9bin的推  
  55.   double *norm = (double *)mxCalloc(blocks[0]*blocks[1], sizeof(double));  
  56.   
  57.   // memory for HOG features  
  58.   int out[3];//size  
  59.   out[0] = max(blocks[0]-2, 0);//减去2干嘛??  
  60.   out[1] = max(blocks[1]-2, 0);  
  61.   out[2] = 27+4;  
  62.   mxArray *mxfeat = mxCreateNumericArray(3, out, mxDOUBLE_CLASS, mxREAL);//特征,size=out   
  63.   double *feat = (double *)mxGetPr(mxfeat);  
  64.     
  65.   int visible[2];  
  66.   visible[0] = blocks[0]*sbin;  
  67.   visible[1] = blocks[1]*sbin;  
  68.   //先列再行  
  69.   for (int x = 1; x < visible[1]-1; x++) {  
  70.     for (int y = 1; y < visible[0]-1; y++) {  
  71.       // first color channel  
  72.       double *s = im + min(x, dims[1]-2)*dims[0] + min(y, dims[0]-2);//在im中的位置  
  73.       double dy = *(s+1) - *(s-1);  
  74.       double dx = *(s+dims[0]) - *(s-dims[0]); //坐标系是一样的,c和matlab的存储顺序不一样  
  75.       double v = dx*dx + dy*dy;  
  76.   
  77.       // second color channel  
  78.       s += dims[0]*dims[1];  
  79.       double dy2 = *(s+1) - *(s-1);  
  80.       double dx2 = *(s+dims[0]) - *(s-dims[0]);  
  81.       double v2 = dx2*dx2 + dy2*dy2;  
  82.   
  83.       // third color channel  
  84.       s += dims[0]*dims[1];  
  85.       double dy3 = *(s+1) - *(s-1);  
  86.       double dx3 = *(s+dims[0]) - *(s-dims[0]);  
  87.       double v3 = dx3*dx3 + dy3*dy3;  
  88.   
  89.       // pick channel with strongest gradient,计算v  
  90.       if (v2 > v) {  
  91.         v = v2;  
  92.         dx = dx2;  
  93.         dy = dy2;  
  94.           }   
  95.           if (v3 > v) {  
  96.         v = v3;  
  97.         dx = dx3;  
  98.         dy = dy3;  
  99.       }  
  100.   
  101.       // snap to one of 18 orientations,就算角度best_o  
  102.       double best_dot = 0;  
  103.       int best_o = 0;  
  104.       for (int o = 0; o < 9; o++) {  
  105.         // (sinθ)^2+(cosθ)^2 =1  
  106.         // max cosθ*dx+ sinθ*dy 对其求导,可得极大值 θ = arctan dy/dx  
  107.         double dot = uu[o]*dx + vv[o]*dy;  
  108.         if (dot > best_dot) {  
  109.           best_dot = dot;  
  110.           best_o = o;  
  111.         } else if (-dot > best_dot) {  
  112.           best_dot = -dot;  
  113.           best_o = o+9;  
  114.         }  
  115.       }  
  116.         
  117.       // add to 4 histograms around pixel using linear interpolation  
  118.       double xp = ((double)x+0.5)/(double)sbin - 0.5;  
  119.       double yp = ((double)y+0.5)/(double)sbin - 0.5;  
  120.       int ixp = (int)floor(xp);  
  121.       int iyp = (int)floor(yp);  
  122.       double vx0 = xp-ixp;  
  123.       double vy0 = yp-iyp;  
  124.       double vx1 = 1.0-vx0;  
  125.       double vy1 = 1.0-vy0;  
  126.       v = sqrt(v);  
  127.     //左上角     
  128.       if (ixp >= 0 && iyp >= 0) {  
  129.         *(hist + ixp*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) +=   
  130.           vx1*vy1*v;  
  131.       }  
  132.       //右上角        
  133.       if (ixp+1 < blocks[1] && iyp >= 0) {  
  134.         *(hist + (ixp+1)*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) +=   
  135.           vx0*vy1*v;  
  136.       }  
  137.       //左下角  
  138.       if (ixp >= 0 && iyp+1 < blocks[0]) {  
  139.         *(hist + ixp*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) +=   
  140.           vx1*vy0*v;  
  141.       }  
  142.       //右下角  
  143.       if (ixp+1 < blocks[1] && iyp+1 < blocks[0]) {  
  144.         *(hist + (ixp+1)*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) +=   
  145.           vx0*vy0*v;  
  146.       }  
  147.     }  
  148.   }  
  149.   
  150.   // compute energy in each block by summing over orientations  
  151.   //计算每一个cell的 sum( ( v(oi)+v(oi+9) )^2 ),oi=0..8  
  152.   for (int o = 0; o < 9; o++) {  
  153.     double *src1 = hist + o*blocks[0]*blocks[1];  
  154.     double *src2 = hist + (o+9)*blocks[0]*blocks[1];  
  155.     double *dst = norm;  
  156.     double *end = norm + blocks[1]*blocks[0];  
  157.     while (dst < end) {  
  158.       *(dst++) += (*src1 + *src2) * (*src1 + *src2);  
  159.       src1++;  
  160.       src2++;  
  161.     }  
  162.   }  
  163.   
  164.   // compute features  
  165.   for (int x = 0; x < out[1]; x++) {  
  166.     for (int y = 0; y < out[0]; y++) {  
  167.       double *dst = feat + x*out[0] + y;        
  168.       double *src, *p, n1, n2, n3, n4;  
  169.   
  170.       p = norm + (x+1)*blocks[0] + y+1;//右下角的constrain insensitive sum  
  171.       n1 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps);  
  172.       p = norm + (x+1)*blocks[0] + y;//右边  
  173.       n2 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps);  
  174.       p = norm + x*blocks[0] + y+1;//下边  
  175.       n3 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps);  
  176.       p = norm + x*blocks[0] + y;//自己        
  177.       n4 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps);  
  178.   
  179.       double t1 = 0;  
  180.       double t2 = 0;  
  181.       double t3 = 0;  
  182.       double t4 = 0;  
  183.   
  184.       // contrast-sensitive features  
  185.       src = hist + (x+1)*blocks[0] + (y+1);  
  186.       for (int o = 0; o < 18; o++) {  
  187.         double h1 = min(*src * n1, 0.2);//截短  
  188.         double h2 = min(*src * n2, 0.2);  
  189.         double h3 = min(*src * n3, 0.2);  
  190.         double h4 = min(*src * n4, 0.2);  
  191.         *dst = 0.5 * (h1 + h2 + h3 + h4);//求和  
  192.         t1 += h1;  
  193.         t2 += h2;  
  194.         t3 += h3;  
  195.         t4 += h4;  
  196.         dst += out[0]*out[1];//下一个bin  
  197.         src += blocks[0]*blocks[1];  
  198.       }  
  199.   
  200.       // contrast-insensitive features  
  201.       src = hist + (x+1)*blocks[0] + (y+1);  
  202.       for (int o = 0; o < 9; o++) {  
  203.         double sum = *src + *(src + 9*blocks[0]*blocks[1]);  
  204.         double h1 = min(sum * n1, 0.2);  
  205.         double h2 = min(sum * n2, 0.2);  
  206.         double h3 = min(sum * n3, 0.2);  
  207.         double h4 = min(sum * n4, 0.2);  
  208.         *dst = 0.5 * (h1 + h2 + h3 + h4);  
  209.         dst += out[0]*out[1];  
  210.         src += blocks[0]*blocks[1];  
  211.       }  
  212.   
  213.       // texture features  
  214.       *dst = 0.2357 * t1;  
  215.       dst += out[0]*out[1];  
  216.       *dst = 0.2357 * t2;  
  217.       dst += out[0]*out[1];  
  218.       *dst = 0.2357 * t3;  
  219.       dst += out[0]*out[1];  
  220.       *dst = 0.2357 * t4;  
  221.     }  
  222.   }  
  223.   
  224.   mxFree(hist);  
  225.   mxFree(norm);  
  226.   return mxfeat;  
  227. }  
  228.   
  229. // matlab entry point  
  230. // F = features(image, bin)  
  231. // image should be color with double values  
  232. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {   
  233.   if (nrhs != 2)  
  234.     mexErrMsgTxt("Wrong number of inputs");   
  235.   if (nlhs != 1)  
  236.     mexErrMsgTxt("Wrong number of outputs");  
  237.   plhs[0] = process(prhs[0], prhs[1]);  
  238. }  

 

dt.cc

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <math.h>  
  2. #include <sys/types.h>  
  3. #include "mex.h"  
  4.   
  5. #define int32_t int  
  6. /* 
  7.  * Generalized distance transforms. 
  8.  * We use a simple nlog(n) divide and conquer algorithm instead of the 
  9.  * theoretically faster linear method, for no particular reason except 
  10.  * that this is a bit simpler and I wanted to test it out. 
  11.  * 
  12.  * The code is a bit convoluted because dt1d can operate either along 
  13.  * a row or column of an array.   
  14.  */  
  15.   
  16. static inline int square(int x) { return x*x; }  
  17.   
  18. // dt helper function  
  19. void dt_helper(double *src, double *dst, int *ptr, int step,   
  20.            int s1, int s2, int d1, int d2, double a, double b) {  
  21.  if (d2 >= d1) {  
  22.    int d = (d1+d2) >> 1;  
  23.    int s = s1;  
  24.    for (int p = s1+1; p <= s2; p++)  
  25.      if (src[s*step] + a*square(d-s) + b*(d-s) >   
  26.      src[p*step] + a*square(d-p) + b*(d-p))  
  27.     s = p;  
  28.    dst[d*step] = src[s*step] + a*square(d-s) + b*(d-s);  
  29.    ptr[d*step] = s;  
  30.    dt_helper(src, dst, ptr, step, s1, s, d1, d-1, a, b);  
  31.    dt_helper(src, dst, ptr, step, s, s2, d+1, d2, a, b);  
  32.  }  
  33. }  
  34.   
  35. // dt of 1d array  
  36. void dt1d(double *src, double *dst, int *ptr, int step, int n,   
  37.       double a, double b) {  
  38.   dt_helper(src, dst, ptr, step, 0, n-1, 0, n-1, a, b);  
  39. }  
  40.   
  41. // matlab entry point  
  42. // [M, Ix, Iy] = dt(vals, ax, bx, ay, by)  
  43. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {   
  44.   if (nrhs != 5)  
  45.     mexErrMsgTxt("Wrong number of inputs");   
  46.   if (nlhs != 3)  
  47.     mexErrMsgTxt("Wrong number of outputs");  
  48.   if (mxGetClassID(prhs[0]) != mxDOUBLE_CLASS)  
  49.     mexErrMsgTxt("Invalid input");  
  50.   
  51.   const int *dims = mxGetDimensions(prhs[0]);  
  52.   double *vals = (double *)mxGetPr(prhs[0]);  
  53.   double ax = mxGetScalar(prhs[1]);  
  54.   double bx = mxGetScalar(prhs[2]);  
  55.   double ay = mxGetScalar(prhs[3]);  
  56.   double by = mxGetScalar(prhs[4]);  
  57.     
  58.   mxArray *mxM = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL);  
  59.   mxArray *mxIx = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);  
  60.   mxArray *mxIy = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);  
  61.   double *M = (double *)mxGetPr(mxM);  
  62.   int32_t *Ix = (int32_t *)mxGetPr(mxIx);  
  63.   int32_t *Iy = (int32_t *)mxGetPr(mxIy);  
  64.   
  65.   double *tmpM = (double *)mxCalloc(dims[0]*dims[1], sizeof(double)); // part map  
  66.   int32_t *tmpIx = (int32_t *)mxCalloc(dims[0]*dims[1], sizeof(int32_t));  
  67.   int32_t *tmpIy = (int32_t *)mxCalloc(dims[0]*dims[1], sizeof(int32_t));  
  68.   
  69.   for (int x = 0; x < dims[1]; x++)  
  70.     dt1d(vals+x*dims[0], tmpM+x*dims[0], tmpIy+x*dims[0], 1, dims[0], ay, by);  
  71.   
  72.   for (int y = 0; y < dims[0]; y++)  
  73.     dt1d(tmpM+y, M+y, tmpIx+y, dims[0], dims[1], ax, bx);  
  74.   
  75.   // get argmins and adjust for matlab indexing from 1  
  76.   for (int x = 0; x < dims[1]; x++) {  
  77.     for (int y = 0; y < dims[0]; y++) {  
  78.       int p = x*dims[0]+y;  
  79.       Ix[p] = tmpIx[p]+1;  
  80.       Iy[p] = tmpIy[tmpIx[p]*dims[0]+y]+1;  
  81.     }  
  82.   }  
  83.   
  84.   mxFree(tmpM);  
  85.   mxFree(tmpIx);  
  86.   mxFree(tmpIy);  
  87.   plhs[0] = mxM;  
  88.   plhs[1] = mxIx;  
  89.   plhs[2] = mxIy;  
  90. }  

0 0