搭建了自己的博客平台,本文地址:http://masikkk.com/blog/DPM-model-visualization/

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函数源代码凝视例如以下:

  1. function f = foldHOG(w)
  2. % 简化滤波器向量w。用以可视化显示模型
  3. % width*height*31 的滤波器參数向量w浓缩为 width*height*9 的向量(widthheight是滤波器的宽度和高度)
  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. % max(w(:,:,1:9),0)返回w(:,:,1:9)中元素和0两者中的较大值(去除负权重)。返回结果组成一个width*height*9维的矩阵
  11. % 所以以下的处理相当于把滤波器參数向量w沿第三维维折叠了两次,形成一个了一个width*height*9的简化版的參数向量
  12. % w的第三维的长度为31,仅仅使用了前27个值,舍弃了后面4个值。这和DPM中使用的31HOG特征向量所代表的意义有关。
  13. % DPM中的特征向量为31维,当中前27维相应不同的方向通道(9个对照度不敏感方向和18个对照度敏感方向),
  14. % 剩下4维表示(i,j)周围4cell组成的block的梯度能量。
  15.  
  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函数源代码凝视例如以下:

  1. function im = HOGpicture(w, bs)
  2. % 画出HOG正权重w的条纹图像
  3. % 參数:
  4. % w:简化后的width*height*9HOG正权重向量(widthheight是滤波器的宽度和高度)
  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看做9bim1叠加在一起
  18. bim(:,:,1) = bim1; % bim的第1bim(:,:,1)赋值为bim1
  19. % 接下来通过20度递进的顺时针旋转依次生成bim的第29层,并将旋转后的矩阵裁剪为和bim1同样大小
  20. % 比如,i=2时,顺时针旋转bim1,并裁剪为和bim1同样的大小,赋值给bim的第2
  21. for i = 2:9,
  22. bim(:,:,i) = imrotate(bim1, -(i-1)*20, 'crop'); % 依次顺时针旋转20度,将结果赋值给bim的第29
  23. end
  24.  
  25. % 通过加入带有方向权重的条纹来绘制正权重的可视化图
  26. % make pictures of positive weights bs adding up weighted glyphs
  27. s = size(w); % height * width * 9
  28. w(w < 0) = 0; % 保证w中所有是正权重
  29. im = zeros(bs*s(1), bs*s(2)); % 生成一个(width*bs)*(height*bs)的图像,即将滤波器w的尺寸扩大bs
  30.  
  31. % 遍历滤波器权重向量w,将每一个坐标的值投影到9个方向上,然后扩大bs倍画到图像im
  32. for i = 1:s(1), % i行(w原尺寸)
  33. iis = (i-1)*bs+1:i*bs; % 相应在图像im上的横坐标
  34. for j = 1:s(2), % j列(w原尺寸)
  35. jjs = (j-1)*bs+1:j*bs; % 相应在图像im上的纵坐标
  36. for k = 1:9, % 遍历9个方向
  37. % bim(:,:,k) * w(i,j,k):假设滤波器向量在方向k上有正值的话,将这个值w(i,j,k)投影到大小为bs*bs的方向坐标基bim的方向k上,
  38. % 然后将9个方向上的投影累加,累加值反映了滤波器中(i,j)位置在各个方向上的幅度大小,最后将累加值放到扩大bs倍的显示图像im的相应位置上
  39. im(iis,jjs) = im(iis,jjs) + bim(:,:,k) * w(i,j,k);
  40. end
  41. %imagesc(im); % 自己加入的语句。分析代码用,显示绘图过程
  42. end
  43. %imagesc(im); % 自己加入的语句。调试用。显示绘图过程
  44. end

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaWJ1YWE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="400" height="420" alt="">

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaWJ1YWE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="400" height="420" alt="">

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

图5。完毕前10行的可视化。能够看出人形了                                          图6,完毕整个根滤波器的可视化

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

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaWJ1YWE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="400" height="420" alt="">

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

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

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

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

图10,头部部件可视化

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

从图11中能够看出,部件滤波器明显要比根滤波器仔细,能提供很多其它细节。

最后就是生成各个部件的变形花费图了,这要用到各个部件的变形信息,在模型的defs[]数组中。defs数组中。每一个部件相应一个锚点坐标和一个变形花费參数(4维向量)。

计算部件内每一个位置距离部件中心的距离,用变形特征向量v = [Δx^2, Δx, Δy^2, Δy]' 和 部件的变形花费 相乘,得到的结果能够反映此位置的变形花费。值越大。说明变形费用越高,表明不是部件的理想位置;值越小,说明变形费用越低。表明是该部件的理想位置。

反映到变形花费图上,越亮(白)的地方花费越大。越暗(黑)的地方花费越小。

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaWJ1YWE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

图12,头部的变形花费图

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

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

visualizemodel函数源代码凝视例如以下:

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

关于DPM(Deformable Part Model)算法中模型可视化的解释的更多相关文章

  1. 关于DPM(Deformable Part Model)算法中模型结构的解释

    关于可变部件模型的描写叙述在作者[2010 PAMI]Object Detection with Discriminatively Trained Part Based Models的论文中已经有说明 ...

  2. DPM(Deformable Parts Model)--原理(一)(转载)

    DPM(Deformable Parts Model) Reference: Object detection with discriminatively trained partbased mode ...

  3. DPM(Deformable Parts Model)

    DPM(Deformable Parts Model) Reference: Object detection with discriminatively trained partbased mode ...

  4. DPM(Deformable Parts Model)--原理(一)

    http://blog.csdn.net/ttransposition/article/details/12966521 DPM(Deformable Parts Model) Reference: ...

  5. (2) 用DPM(Deformable Part Model,voc-release4.01)算法在INRIA数据集上训练自己的人体检測模型

    步骤一,首先要使voc-release4.01目标检測部分的代码在windows系统下跑起来: 參考在window下执行DPM(deformable part models) -(检測demo部分) ...

  6. 使用DPM(Deformable Part Model,voc-release3.1)算法INRIA通过训练你的身体检测模型数据集

    我的环境 DPM源代码版本号:voc-release3.1 VOC开发包版本号:VOC2007_devkit_08-Jun Matlab版本号:MatlabR2012b c++编译器:VS2010 系 ...

  7. kmp算法中的nextval实例解释

    求nextval数组值有两种方法,一种是不依赖next数组值直接用观察法求得,一种方法是根据next数组值进行推理,两种方法均可使用,视更喜欢哪种方法而定. 本文主要分析nextval数组值的第二种方 ...

  8. DPM(Deformable Part Model)原理详解(汇总)

    写在前面: DPM(Deformable Part Model),正如其名称所述,可变形的组件模型,是一种基于组件的检测算法,其所见即其意.该模型由大神Felzenszwalb在2008年提出,并发表 ...

  9. Journal of Proteomics Research | 利用混合蛋白质组模型对MBR算法中错误转移鉴定率的评估

    题目:Evaluating False Transfer Rates from the Match-between-Runs Algorithm with a Two-Proteome Model 期 ...

随机推荐

  1. NYIST 677 碟战

    碟战时间限制:2000 ms | 内存限制:65535 KB难度:4 描述知己知彼,百战不殆!在战争中如果被敌人掌握了自己的机密,失败是必然的.K国在一场战争中屡屡失败,就想到自己的某些城市可能会有敌 ...

  2. spring-boot-maven-plugin 插件的作用(转)

    OM 文件中添加了“org.springframework.boot:spring-boot-maven-plugin”插件.在添加了该插件之后,当运行“mvn package”进行打包时,会打包成一 ...

  3. [AngularJS]Chapter 1 AnjularJS简介

    创建一个完美的Web应用程序是很令人激动的,但是构建这样应用的复杂度也是不可思议的.我们Angular团队的目标就是去减轻构建这样AJAX应用的复杂度.在谷歌我们经历过各种复杂的应用创建工作比如:GM ...

  4. Ruby中写换行

    Ruby中写换行 print("Hello,\nRuby\n!\n") print("Hello, Ruby ! ") 这两个竟然是一样的:就是说,可以直接回车 ...

  5. html屏蔽鼠标右键

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 指向类成员函数的函数指针及#define typedef 实现类成员函数的类型转换

    #include <iostream> using namespace std; class Test { public : void print() { cout << &q ...

  7. ie浏览器检测不到cookie的问题

    之前做项目由于客户的要求设置缓存必须由后台来设置必须使用cookie(session是没问题的),后期设置时出现了登录页面与首页来还跳转的局面.原因就是首页没检测到登录后的缓存,而后台验证到确实已经是 ...

  8. MEF基本概念

    基本概念: Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库,在.NET 4.0发布 Container:容器,使用Compositi ...

  9. P3809 【模版】后缀排序

    题目背景 这是一道模版题. 题目描述 读入一个长度为 nn 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编 ...

  10. ARM的六大类指令集---LDR、LDRB、LDRH、LDM、STR、STRB、STRH、STM

    http://blog.csdn.net/u013477200/article/details/50723555