关于DPM(Deformable Part Model)算法中模型可视化的解释

    DPM源码(voc-release)中的模型可视化做的还算相当炫酷的,可以让我们直观的看到训练好的模型,甚至我们不用去做模型的评价,直接根据肉眼的观察,就能大致了解一个目标训练的好不好,比如我训练一个人体模型,那他的可视化图当然就是越接近人体越好。

        下面是对DPM源码中有关模型可视化部分代码的分析,通过分析这些代码,有助于更好的理解DPM模型。

        注意:我的源码版本是voc-release3.1,第4版往后的模型变得更复杂,这里不讨论。

        有关模型可视化的代码主要在visualizemodel.m,foldHOG.m和HOGpicture.m中。


(1)简化分类器参数向量(或者叫滤波器权重向量)

        DPM中使用降维后的31维HOG特征向量,所以,与之对应的,训练好的模型的参数向量也是31维的,为了方便可视化,需要将31维的参数向量简化为9维,foldHOG函数就负责参数向量的简化。

        31维的HOG特征向量是有分段含义的,如下:

        设C是聚合有9个对比度不敏感方向的像素级特征映射而获得的基于cell的特征映射,D是聚合有18个对比度敏感方向的像素级特征而获得的基于cell的特征映射。用4种不同的归一化方法对C(i,j)和D(i,j)进行归一化和截断(限幅),可以获得一个4*(9+18)=108维的特征向量F(i,j)。实际中我们使用此108维向量的一个解析投影,此投影由下面几个统计量定义:27个在不同归一化因子上的累加和(即列的和),F中的每个方向通道对应一个;以及4个在不同方向(9维对比度不敏感方向)上的累加和(即行的和),每个归一化因子对应一个。cell尺寸k=8,截断(限幅)阈值α=0.2。最终的特征映射是31维向量G(i,j),其中27维对应不同的方向通道(9个对比度不敏感方向和18个对比度敏感方向),剩下4维表示(i,j)周围4个cell组成的block的梯度能量

        所以,foldHOG中的简化过程就是将31维参数向量的后4维丢弃,将前27维进行负值抑制折叠累加,缩减为9维的参数向量。

        foldHOG函数源码注释如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. function f = foldHOG(w)  
  2. % 简化滤波器向量w,用以可视化显示模型  
  3. % 将 width*height*31 的滤波器参数向量w浓缩为 width*height*9 的向量(width和height是滤波器的宽度和高度)  
  4. % 返回值f是一个width*height*9的矩阵  
  5. %  
  6. f = foldHOG(w)  
  7. % Condense HOG features into one orientation histogram.  
  8. % Used for displaying a feature.  
  9.   
  10.   
  11. % max(w(:,:,1:9),0)返回w(:,:,1:9)中元素和0两者中的较大值(去除负权重),返回结果组成一个width*height*9维的矩阵  
  12. % 所以下面的处理相当于把滤波器参数向量w沿第三维维折叠了两次,形成一个了一个width*height*9的简化版的参数向量  
  13. % w的第三维的长度为31,只使用了前27个值,舍弃了后面4个值,这和DPM中使用的31维HOG特征向量所代表的意义有关。  
  14. % DPM中的特征向量为31维,其中前27维对应不同的方向通道(9个对比度不敏感方向和18个对比度敏感方向),  
  15. % 剩下4维表示(i,j)周围4个cell组成的block的梯度能量。  
  16. f = max(w(:,:,1:9),0) + max(w(:,:,10:18),0) + max(w(:,:,19:27),0);  

(2)生成滤波器权重向量的可视化图

        这一工作在HOGpicture函数中完成,此函数负责为简化后的w*h*9维的权重向量生成可视化图。

        首先要生成一个间隔为20度的方向坐标基,然后将滤波器向量中的点(i,j,k)向坐标基中的方向k上投影,而用该点的值衡量(i,j)在k方向的幅度。

        HOGpicture函数源码注释如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. function im = HOGpicture(w, bs)  
  2. % 画出HOG正权重w的条纹图像   
  3. % 参数:  
  4. % w:简化后的width*height*9的HOG正权重向量(width和height是滤波器的宽度和高度)  
  5. % bs:生成的图像im相比于滤波器尺寸的扩大倍数  
  6. % 返回值:  
  7. % im:滤波器权重向量的可视化图,是大小为(width*bs)*(height*bs)的图像  
  8. %  
  9. % HOGpicture(w, bs)  
  10. % Make picture of positive HOG weights.  
  11.   
  12. % 为间隔20度的9个方向生成条纹线  
  13. % 其实bim相当于有9个方向的方向空间的一个坐标基,将滤波器向量中某点的值w(i,j,:)向bim的各个方向投影可以反映每个点的方向分布  
  14. % construct a "glyph" for each orientaion  
  15. bim1 = zeros(bs, bs); % 生成一个bs*bs的全零矩阵bim1  
  16. bim1(:,round(bs/2):round(bs/2)+1) = 1; % 将bim1的中间两个竖条的值置为1  
  17. bim = zeros([size(bim1) 9]); % 生成一个bs*bs*9的全零矩阵bim,可以将bim看做9层bim1叠加在一起  
  18. bim(:,:,1) = bim1; % 将bim的第1层bim(:,:,1)赋值为bim1  
  19. % 接下来通过20度递进的顺时针旋转依次生成bim的第2到9层,并将旋转后的矩阵裁剪为和bim1相同大小  
  20. % 例如,i=2时,顺时针旋转bim1,并裁剪为和bim1相同的大小,赋值给bim的第2层  
  21. for i = 2:9,  
  22.   bim(:,:,i) = imrotate(bim1, -(i-1)*20, 'crop'); % 依次顺时针旋转20度,将结果赋值给bim的第2到9层  
  23. end  
  24.   
  25.   
  26. % 通过添加带有方向权重的条纹来绘制正权重的可视化图  
  27. % make pictures of positive weights bs adding up weighted glyphs  
  28. s = size(w); % height * width * 9  
  29. w(w < 0) = 0; % 保证w中全部是正权重  
  30. im = zeros(bs*s(1), bs*s(2)); % 生成一个(width*bs)*(height*bs)的图像,即将滤波器w的尺寸扩大bs倍  
  31.   
  32. % 遍历滤波器权重向量w,将每个坐标的值投影到9个方向上,然后扩大bs倍画到图像im上  
  33. for i = 1:s(1), % 第i行(w原尺寸)  
  34.   iis = (i-1)*bs+1:i*bs; % 对应在图像im上的横坐标  
  35.   for j = 1:s(2), % 第j列(w原尺寸)  
  36.     jjs = (j-1)*bs+1:j*bs; % 对应在图像im上的纵坐标  
  37.     for k = 1:9, % 遍历9个方向  
  38.         % bim(:,:,k) * w(i,j,k):如果滤波器向量在方向k上有正值的话,将这个值w(i,j,k)投影到大小为bs*bs的方向坐标基bim的方向k上,  
  39.         % 然后将9个方向上的投影累加,累加值反映了滤波器中(i,j)位置在各个方向上的幅度大小,最后将累加值放到扩大bs倍的显示图像im的对应位置上  
  40.         im(iis,jjs) = im(iis,jjs) + bim(:,:,k) * w(i,j,k);   
  41.     end  
  42.     %imagesc(im); % 自己添加的语句,分析代码用,显示画图过程  
  43.   end  
  44.   %imagesc(im); % 自己添加的语句,调试用,显示画图过程  
  45. end  

下面图1-6是HOGpicture中一个根滤波器可视化图的绘制过程:


                     图1,根滤波器权重向量点(1,1)的可视化                                                    图2,加上点(1,2)的可视化


                                图3,完成第1行的可视化                                                                图4,完成前2行的可视化


                  图5,完成前10行的可视化,可以看出人形了                                          图6,完成整个根滤波器的可视化      



(3)在visualizemodel函数中进行一些后处理,分割绘图区域,依次调用HOGpicture画出根滤波器和各个部件滤波器的可视化图,以及各个部件的变形花费图

        在visualizemodel中调用HOGpicture画出根滤波器的可视化图,返回值为图6,然后将像素值扩充到[0,255]并转换为8位无符号整型,得到图7


                         图7,根滤波器可视化图_Uint8


        然后分割绘图区域,将根滤波器的可视化图画到指定区域,如图8;再转换为灰度图,如图9


                                图8,根滤波器_subplot                                                                            图9,根滤波器_subplot_gray


        再之后依次绘制各个部件的可视化图,如图10是人体头部的可视化图,覆盖到根滤波器的对应位置。


       图10,头部部件可视化



         图11,左图是根滤波器,右图是各个部件的可视化图覆盖到根的对应位置后的可视化图

        从图11中可以看出,部件滤波器明显要比根滤波器细致,能提供更多细节。


        最后就是生成各个部件的变形花费图了,这要用到各个部件的变形信息,在模型的defs[]数组中。defs数组中,每个部件对应一个锚点坐标和一个变形花费参数(4维向量)。计算部件内每个位置距离部件中心的距离,用变形特征向量v = [Δx^2, Δx, Δy^2, Δy]' 和 部件的变形花费 相乘,得到的结果可以反映此位置的变形花费。值越大,说明变形费用越高,表明不是部件的理想位置;值越小,说明变形费用越低,表明是该部件的理想位置。反映到变形花费图上,越亮(白)的地方花费越大,越暗(黑)的地方花费越小。

        如下图12是头部的变形花费图:


                      图12,头部的变形花费图


        最后,就获得了完整的模型可视化图


图13,左图:根滤波器的可视化图;中图:各个部件的可视化图覆盖到根的对应位置后的可视化图;右图:各个部件的变形花费图


        visualizemodel函数源码注释如下

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. function visualizemodel(model, components)  
  2. % 绘制模型的可视化图像  
  3. % 参数:  
  4. % model:要可视化的模型  
  5. % components:指定可视化某个组件模型  
  6. %  
  7. % visualizemodel(model)  
  8. % Visualize a model.  
  9.   
  10. clf; % 删除当前绘图  
  11. if nargin < 2 % 未指定可视化哪个组件模型,则可视化所有组件模型  
  12.   components = 1:model.numcomponents;  
  13. end  
  14.   
  15. % 依次可视化每个组件模型  
  16. k = 1;  
  17. for i = components  
  18.   visualizecomponent(model, i, length(components), k);  
  19.   k = k+1;  
  20. end  
  21.   
  22.   
  23. % 可视化一个组件模型  
  24. % 参数  
  25. % model:要可视化的模型  
  26. % c:当前要可视化的第c个组件  
  27. % nc:此模型中总的组件个数  
  28. % k:指定绘制区域  
  29. function visualizecomponent(model, c, nc, k)  
  30.   
  31. pad = 2; % 填充宽度  
  32. bs = 20; % 生成的图像相比于滤波器尺寸的扩大倍数  
  33.   
  34. % 将 width*height*31 的滤波器参数向量浓缩为 width*height*9 的向量,所以返回值w是一个 width*height*9 的向量(width和height是滤波器的宽度和高度)  
  35. w = foldHOG(model.rootfilters{model.components{c}.rootindex}.w); % 简化组件c的根滤波器向量,用以可视化显示模型  
  36.   
  37. scale = max(w(:)); % w(:)返回由width*height*9的矩阵w的所有元素组成的一维向量,所以scale是w中所有元素的最大值,scale是一个标量  
  38.   
  39. im = HOGpicture(w, bs); % 画出滤波器权重向量w的可视化图,返回值im是大小为(width*bs)*(height*bs)的图像,像素值为double型  
  40. %imagesc(im); % 自己添加的语句,分析代码用,显示HOGpicture的绘图结果  
  41.   
  42. im = imresize(im, 2); % 将im的尺寸扩大一倍  
  43. %imagesc(im); % 自己添加的语句,分析代码用,显示图像  
  44.   
  45. im = padarray(im, [pad pad], 0); % 填充图像边界,在图像im的上下左右各填充pad行(列)零值,填充后im的大小为(width*bs+pad*2)*(height*bs+pad*2)  
  46. im = uint8(im * (255/scale)); % 将im的值扩充到[0-255]并转换为8位无符号整型  
  47. %imagesc(im); % 自己添加的语句,分析代码用,显示图像  
  48.   
  49. % 分割绘图区域并画出根滤波器的可视化图  
  50. numparts = length(model.components{c}.parts); % numparts:组件c的部件个数  
  51. % 根据组件个数和是否含有部件来分割绘图区域  
  52. % 对于含nc个组件的模型,将绘图区域分为nc行  
  53. if numparts > 0 % 对于有部件的模型,再将每行分为3列  
  54.   subplot(nc,3,1+3*(k-1)); % 选中分割后的第1+3(k-1)个绘图区域,即每行的第一列  
  55. else % 对于没有部件的模型,每行只有一列  
  56.   subplot(nc,1,k); % 选中每行第一列的绘图区域  
  57. end  
  58. imagesc(im); % 缩放数据并显示为图片,画到上一步选中的绘图区域中  
  59. colormap gray; % 设为灰度图  
  60. axis equal; % 使横纵坐标的刻度相同  
  61. axis off; % 不显示坐标轴  
  62.   
  63.   
  64. % 画出组件c的带部件的可视化图im和变形花费图def_im  
  65. % draw parts and deformation model  
  66. if numparts > 0 % 只对含有部件的模型进行下面的操作  
  67.     
  68.   def_im = zeros(size(im)); % 初始化变形花费图def_im,和根滤波器的可视化图大小相同  
  69.   def_scale = 500;  
  70.     
  71.   % 遍历组件c的各个部件  
  72.   for i = 1:numparts  
  73.       
  74.     % 生成部件i的可视化图  
  75.     w = model.partfilters{model.components{c}.parts{i}.partindex}.w; % 组件c的第i个部件的滤波器向量,尺寸为:width*height*31  
  76.     p = HOGpicture(foldHOG(w), bs); % 简化滤波器向量w为width*height*9,并生成可视化图,返回值p是大小为(width*bs)*(height*bs)的图像,像素值为double型  
  77.     %clf;imagesc(p); % 自己添加的语句,分析代码用,显示图像  
  78.       
  79.     p = padarray(p, [pad pad], 0); % 填充图像边界,在图像p的上下左右各增加pad行(列)零值,填充后p的大小为(width*bs+pad*2)*(height*bs+pad*2)  
  80.     p = uint8(p * (255/scale)); % 将p的值扩充到[0-255]并转换为8位无符号整型  
  81.     %imagesc(p); % 自己添加的语句,分析代码用,显示图像  
  82.       
  83.     % 将部件i的可视化图p的上下左右宽度为pad*2区域的边界的值设为128,也就是加边框  
  84.     p(:,1:2*pad) = 128;  
  85.     p(:,end-2*pad+1:end) = 128;  
  86.     p(1:2*pad,:) = 128;  
  87.     p(end-2*pad+1:end,:) = 128;  
  88.     %imagesc(p); % 自己添加的语句,分析代码用,显示图像  
  89.       
  90.     % paste into root 将部件i的可视化图p覆盖到根滤波器可视化图图像im的对应位置上  
  91.     def = model.defs{model.components{c}.parts{i}.defindex}; % 组件c的第i个部件的锚点信息  
  92.     x1 = (def.anchor(1)-1)*bs+1; % 部件i的锚点(左上角点)对应在根滤波器的可视化图im中的坐标  
  93.     y1 = (def.anchor(2)-1)*bs+1;   
  94.     x2 = x1 + size(p, 2)-1; % 部件i的右下角点在根滤波器的可视化图im中的坐标  
  95.     y2 = y1 + size(p, 1)-1;  
  96.     im(y1:y2, x1:x2) = p; % 覆盖到根滤波器的指定位置  
  97.     %imagesc(p); % 自己添加的语句,分析代码用,显示图像  
  98.       
  99.     % deformation model 生成部件i的变形花费图并复制到整体的变形花费图def_im中  
  100.     probex = size(p,2)/2; % p的宽度的一半  
  101.     probey = size(p,1)/2; % p的高度的一半  
  102.     % 生成p的每个位置(忽略边框)的变形花费值  
  103.     for y = 2*pad+1:size(p,1)-2*pad % 第y行  
  104.       for x = 2*pad+1:size(p,2)-2*pad % 第x列  
  105.         px = ((probex-x)/bs); % 点(y,x)距部件i中心的水平距离,Δx  
  106.         py = ((probey-y)/bs); % 点(y,x)距部件i中心的垂直距离,Δy  
  107.         v = [px^2; px; py^2; py]; % 偏移量及其平方组合成一个变形特征向量v = [Δx^2, Δx, Δy^2, Δy]'  
  108.         % 变形特征向量 乘以 变形花费参数 并进行缩放,得到点(y,x)的变形花费值,保存在p中  
  109.         % 根据计算公式可知,距离部件i中心越远的地方,变形花费越大,反应到变形花费图中就是越亮的地方变形花费越大  
  110.         p(y, x) = def.w * v * def_scale;   
  111.       end  
  112.     end  
  113.     def_im(y1:y2, x1:x2) = p; % 将p中保存的部件i各个位置的变形花费值复制到整体的变形花费图def_im的对应位置  
  114.   end  
  115.     
  116.   % 在对应绘图区域画出组件c的带部件的可视化图im  
  117.   % plot parts  
  118.   subplot(nc,3,2+3*(k-1)); % 选中每行的第2列  
  119.   imagesc(im); % 绘制图片  
  120.   colormap gray; % 设为灰度图  
  121.   axis equal; % 使横纵坐标的刻度相同  
  122.   axis off; % 不显示坐标轴  
  123.     
  124.   % 在对应绘图区域画出组件c的各个部件的变形花费图  
  125.   % plot deformation model  
  126.   subplot(nc,3,3+3*(k-1)); % 选中每行的第3列  
  127.   imagesc(def_im); % 绘制图片  
  128.   colormap gray; % 设为灰度图  
  129.   axis equal; % 使横纵坐标的刻度相同  
  130.   axis off; % 不显示坐标轴  
  131. end  
  132.   
  133. % set(gcf, 'Color', 'white')  


相关链接:

Deformable Part Model 相关网页http://www.cs.berkeley.edu/~rbg/latent/index.html

Pedro Felzenszwalb的个人主页http://cs.brown.edu/~pff/

PASCAL VOC 目标检测挑战http://pascallin.ecs.soton.ac.uk/challenges/VOC/


A Discriminatively Trained, Multiscale, Deformable Part Model [CVPR 2008] 中文翻译

Object Detection with Discriminatively Trained Part Based Models [PAMI 2010]中文翻译

有关可变形部件模型(Deformable Part Model)的一些说明


在Windows下运行Felzenszwalb的Deformable Part Models(voc-release4.01)目标检测matlab源码

在Windows下运行Felzenszwalb的star-cascade DPM(Deformable Part Models)目标检测Matlab源码

在windows下运行Felzenszwalb的Deformable Part Model(DPM)源码voc-release3.1来训练自己的模型

用DPM(Deformable Part Model,voc-release3.1)算法在INRIA数据集上训练自己的人体检测模型

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值