目标检测学习记录——特征提取之HOG

来源:互联网 发布:什么是图灵机 知乎 编辑:程序博客网 时间:2024/06/05 05:35

===================================================================================================================

          作为一名计算机视觉研究和代码编程上的小菜鸟。上学期就看了Histogram of Oriented Gradient for Human Detection 整篇论文不长,看了似乎也懂,但是回过头来感觉懂得其实很浅显。在此开博,记录学习的知识,也算是记录自己研究生的历程。没有新的见解,更多的是个人对此理解的整理。

==========================================================================================================================================================

     简述:方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子(用于表示特征)。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal2005CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。

     大概过程:

       HOG特征提取方法就是将一个image(你要检测的目标或者扫描窗口):

       1)灰度化(将图像看做一个x,y,z(灰度)的三维图像);

       2)采用Gamma校正法对输入图像进行颜色空间的标准化(归一化);目的是调节图像的对比度,降低图像局部的阴影和光照变化所造成的影响,同时可以抑制噪音的干扰;

       3)计算图像每个像素的梯度(包括大小和方向);主要是为了捕获轮廓信息,同时进一步弱化光照的干扰。

       4)将图像划分成小cells(例如6*6像素/cell);

        5)统计每个cell的梯度直方图(不同梯度的个数),即可形成每个celldescriptor

       6)将每几个cell组成一个block(例如3*3cell/block),一个block内所有cell的特征descriptor串联起来便得到该blockHOG特征descriptor

        7)将图像image内的所有blockHOG特征descriptor串联起来就可以得到该image(你要检测的目标)的HOG特征descriptor了。这个就是最终的可供分类使用的特征向量了。





      理解:将图像灰度化后,将图像分成小的连通区域称为细胞单元(cell),采集得到像素点的梯度或边缘的方向直方图(Histogram of Oriented Gradient)。文章中检测窗口取128*64,区块(block)取16*16,每个Block划分成2*2的cell,细胞单元(cell)取8*8,移动窗口步长为8个像素。所以一个检测窗口分为[(128-16)/8+1]*[(64-16)/8+1]=15*7=105个block块。每个块分为4个cell,每个cell分成9个bin,所以HOG特征描述子有105*4*9=3780维。


                               block分成cell



                                                    cell按方向分成9个bin

还未了解的点:

         三线插值?


Matlab源码:见TimeHandle的blog

转自:http://www.zhizhihu.com/html/y2010/1690.html

Histograms of Oriented Gradients (HOG)特征 MATLAB 计算

[plain] view plaincopy
  1. function F = hogcalculator(img, cellpw, cellph, nblockw, nblockh,...  
  2. nthet, overlap, isglobalinterpolate, issigned, normmethod)  
  3. % HOGCALCULATOR calculate R-HOG feature vector of an input image using the  
  4. % procedure presented in Dalal and Triggs's paper in CVPR 2005.  
  5. %  
  6. % Author: timeHandle  
  7. % Time: March 24, 2010  
  8. % May 12,2010 update.  
  9. %  
  10. % this copy of code is written for my personal interest, which is an   
  11. % original and inornate realization of [Dalal CVPR2005]'s algorithm  
  12. % without any optimization. I just want to check whether I understand  
  13. % the algorithm really or not, and also do some practices for knowing  
  14. % matlab programming more well because I could be called as 'novice'.   
  15. % OpenCV 2.0 has realized Dalal's HOG algorithm which runs faster  
  16. % than mine without any doubt, ╮(╯▽╰)╭ . Ronan pointed a error in   
  17. % the code,thanks for his correction. Note that at the end of this  
  18. % code, there are some demonstration code,please remove in your work.  
  19.   
  20. %   
  21. % F = hogcalculator(img, cellpw, cellph, nblockw, nblockh,  
  22. % nthet, overlap, isglobalinterpolate, issigned, normmethod)  
  23. %  
  24. % IMG:  
  25. % IMG is the input image.  
  26. %  
  27. % CELLPW, CELLPH:  
  28. % CELLPW and CELLPH are cell's pixel width and height respectively.  
  29. %  
  30. % NBLOCKW, NBLCOKH:  
  31. % NBLOCKW and NBLCOKH are block size counted by cells number in x and  
  32. % y directions respectively.  
  33. %  
  34. % NTHET, ISSIGNED:  
  35. % NTHET is the number of the bins of the histogram of oriented  
  36. % gradient. The histogram of oriented gradient ranges from 0 to pi in  
  37. % 'unsigned' condition while to 2*pi in 'signed' condition, which can  
  38. % be specified through setting the value of the variable ISSIGNED by  
  39. % the string 'unsigned' or 'signed'.  
  40. %  
  41. % OVERLAP:  
  42. % OVERLAP is the overlap proportion of two neighboring block.  
  43. %  
  44. % ISGLOBALINTERPOLATE:  
  45. % ISGLOBALINTERPOLATE specifies whether the trilinear interpolation  
  46. % is done in a single global 3d histogram of the whole detecting  
  47. % window by the string 'globalinterpolate' or in each local 3d  
  48. % histogram corresponding to respective blocks by the string  
  49. % 'localinterpolate' which is in strict accordance with the procedure  
  50. % proposed in Dalal's paper. Interpolating in the whole detecting  
  51. % window requires the block's sliding step to be an integral multiple  
  52. % of cell's width and height because the histogram is fixing before  
  53. % interpolate. In fact here the so called 'global interpolation' is  
  54. % a notation given by myself. at first the spatial interpolation is   
  55. % done without any relevant to block's slide position, but when I was  
  56. % doing calculation while OVERLAP is 0.75, something occurred and  
  57. % confused me o__O"… . This let me find that the operation I firstly  
  58. % did is different from which mentioned in Dalal's paper. But this  
  59. % does not mean it is incorrect ^◎^, so I reserve this. As for name,  
  60. % besides 'global interpolate', any others would be all ok, like 'Lady GaGa'   
  61. % or what else, :-).  
  62. %  
  63. % NORMMETHOD:  
  64. % NORMMETHOD is the block histogram normalized method which can be  
  65. % set as one of the following strings:  
  66. % 'none', which means non-normalization;  
  67. % 'l1', which means L1-norm normalization;  
  68. % 'l2', which means L2-norm normalization;  
  69. % 'l1sqrt', which means L1-sqrt-norm normalization;  
  70. % 'l2hys', which means L2-hys-norm normalization.  
  71. % F:  
  72. % F is a row vector storing the final histogram of all of the blocks   
  73. % one by one in a top-left to bottom-right image scan manner, the  
  74. % cells histogram are stored in the same manner in each block's  
  75. % section of F.  
  76. %  
  77. % Note that CELLPW*NBLOCKW and CELLPH*NBLOCKH should be equal to IMG's  
  78. % width and height respectively.  
  79. %  
  80. % Here is a demonstration, which all of parameters are set as the  
  81. % best value mentioned in Dalal's paper when the window detected is 128*64  
  82. % size(128 rows, 64 columns):  
  83. % F = hogcalculator(window, 8, 8, 2, 2, 9, 0.5,  
  84. % 'localinterpolate', 'unsigned', 'l2hys');  
  85. % Also the function can be called like:  
  86. % F = hogcalculator(window);  
  87. % the other parameters are all set by using the above-mentioned "dalal's  
  88. % best value" as default.  
  89. %  
  90. if nargin < 2  
  91. % set default parameters value.  
  92. cellpw = 8;  
  93. cellph = 8;  
  94. nblockw = 2;  
  95. nblockh = 2;  
  96. nthet = 9;  
  97. overlap = 0.5;  
  98. isglobalinterpolate = 'localinterpolate';  
  99. issigned = 'unsigned';  
  100. normmethod = 'l2hys';  
  101. else  
  102. if nargin < 10  
  103. error('Input parameters are not enough.');  
  104. end  
  105. end  
  106. % check parameters's validity.  
  107. [M, N, K] = size(img);  
  108. if mod(M,cellph*nblockh) ~= 0  
  109. error('IMG''s height should be an integral multiple of CELLPH*NBLOCKH.');  
  110. end  
  111. if mod(N,cellpw*nblockw) ~= 0  
  112. error('IMG''s width should be an integral multiple of CELLPW*NBLOCKW.');  
  113. end  
  114. if mod((1-overlap)*cellpw*nblockw, cellpw) ~= 0 ||...  
  115. mod((1-overlap)*cellph*nblockh, cellph) ~= 0  
  116. str1 = 'Incorrect OVERLAP or ISGLOBALINTERPOLATE parameter';  
  117. str2 = ', slide step should be an intergral multiple of cell size';  
  118. error([str1, str2]);  
  119. end  
  120. % set the standard deviation of gaussian spatial weight window.  
  121. delta = cellpw*nblockw * 0.5;  
  122. % calculate gradient scale matrix.  
  123. hx = [-1,0,1];  
  124. hy = -hx';  
  125. gradscalx = imfilter(double(img),hx);  
  126. gradscaly = imfilter(double(img),hy);  
  127. %   
  128. if K > 1  
  129. % gradscalx = max(max(gradscalx(:,:,1),gradscalx(:,:,2)), gradscalx(:,:,3));  
  130. % gradscaly = max(max(gradscaly(:,:,1),gradscaly(:,:,2)), gradscaly(:,:,3));  
  131. maxgrad = sqrt(double(gradscalx.*gradscalx + gradscaly.*gradscaly));  
  132. [gradscal, gidx] = max(maxgrad,[],3);  
  133. gxtemp = zeros(M,N);  
  134. gytemp = gxtemp;  
  135. for kn = 1:K  
  136. [rowidx, colidx] = ind2sub(size(gidx),find(gidx==kn));  
  137. gxtemp(rowidx, colidx) = gradscalx(rowidx,colidx,kn);  
  138. gytemp(rowidx, colidx) =gradscaly(rowidx,colidx,kn);  
  139. end  
  140. gradscalx = gxtemp;  
  141. gradscaly = gytemp;  
  142. else  
  143. gradscal = sqrt(double(gradscalx.*gradscalx + gradscaly.*gradscaly));  
  144. end  
  145.   
  146. % calculate gradient orientation matrix.  
  147. % plus small number for avoiding dividing zero.  
  148. gradscalxplus = gradscalx+ones(size(gradscalx))*0.0001;  
  149. gradorient = zeros(M,N);  
  150. % unsigned situation: orientation region is 0 to pi.  
  151. if strcmp(issigned, 'unsigned') == 1  
  152. gradorient =...  
  153. atan(gradscaly./gradscalxplus) + pi/2;  
  154. or = 1;  
  155. else  
  156. % signed situation: orientation region is 0 to 2*pi.  
  157. if strcmp(issigned, 'signed') == 1  
  158. idx = find(gradscalx >= 0 & gradscaly >= 0);  
  159. gradorient(idx) = atan(gradscaly(idx)./gradscalxplus(idx));  
  160. idx = find(gradscalx < 0);  
  161. gradorient(idx) = atan(gradscaly(idx)./gradscalxplus(idx)) + pi;  
  162. idx = find(gradscalx >= 0 & gradscaly < 0);  
  163. gradorient(idx) = atan(gradscaly(idx)./gradscalxplus(idx)) + 2*pi;  
  164. or = 2;  
  165. else  
  166. error('Incorrect ISSIGNED parameter.');  
  167. end  
  168. end  
  169. % calculate block slide step.  
  170. xbstride = cellpw*nblockw*(1-overlap);  
  171. ybstride = cellph*nblockh*(1-overlap);  
  172. xbstridend = N - cellpw*nblockw + 1;  
  173. ybstridend = M - cellph*nblockh + 1;  
  174. % calculate the total blocks number in the window detected, which is  
  175. % ntotalbh*ntotalbw.  
  176. ntotalbh = ((M-cellph*nblockh)/ybstride)+1;  
  177. ntotalbw = ((N-cellpw*nblockw)/xbstride)+1;  
  178. % generate the matrix hist3dbig for storing the 3-dimensions histogram. the  
  179. % matrix covers the whole image in the 'globalinterpolate' condition or  
  180. % covers the local block in the 'localinterpolate' condition. The matrix is  
  181. % bigger than the area where it covers by adding additional elements  
  182. % (corresponding to the cells) to the surround for calculation convenience.  
  183. if strcmp(isglobalinterpolate, 'globalinterpolate') == 1  
  184. ncellx = N / cellpw;  
  185. ncelly = M / cellph;  
  186. hist3dbig = zeros(ncelly+2, ncellx+2, nthet+2);  
  187. F = zeros(1, (M/cellph-1)*(N/cellpw-1)*nblockw*nblockh*nthet);  
  188. glbalinter = 1;  
  189. else  
  190. if strcmp(isglobalinterpolate, 'localinterpolate') == 1  
  191. hist3dbig = zeros(nblockh+2, nblockw+2, nthet+2);  
  192. F = zeros(1, ntotalbh*ntotalbw*nblockw*nblockh*nthet);  
  193. glbalinter = 0;  
  194. else  
  195. error('Incorrect ISGLOBALINTERPOLATE parameter.')  
  196. end  
  197. end  
  198. % generate the matrix for storing histogram of one block;  
  199. sF = zeros(1, nblockw*nblockh*nthet);  
  200. % generate gaussian spatial weight.  
  201. [gaussx, gaussy] = meshgrid(0:(cellpw*nblockw-1), 0:(cellph*nblockh-1));  
  202. weight = exp(-((gaussx-(cellpw*nblockw-1)/2)...  
  203. .*(gaussx-(cellpw*nblockw-1)/2)+(gaussy-(cellph*nblockh-1)/2)...  
  204. .*(gaussy-(cellph*nblockh-1)/2))/(delta*delta));  
  205. % vote for histogram. there are two situations according to the interpolate  
  206. % condition('global' interpolate or local interpolate). The hist3d which is  
  207. % generated from the 'bigger' matrix hist3dbig is the final histogram.  
  208. if glbalinter == 1  
  209. xbstep = nblockw*cellpw;  
  210. ybstep = nblockh*cellph;  
  211. else  
  212. xbstep = xbstride;  
  213. ybstep = ybstride;  
  214. end  
  215. % block slide loop  
  216. for btly = 1:ybstep:ybstridend  
  217. for btlx = 1:xbstep:xbstridend  
  218. for bi = 1:(cellph*nblockh)  
  219. for bj = 1:(cellpw*nblockw)  
  220.   
  221. i = btly + bi - 1;  
  222. j = btlx + bj - 1;  
  223. gaussweight = weight(bi,bj);  
  224.   
  225. gs = gradscal(i,j);  
  226. go = gradorient(i,j);  
  227.   
  228. if glbalinter == 1  
  229. jorbj = j;  
  230. iorbi = i;  
  231. else  
  232. jorbj = bj;  
  233. iorbi = bi;  
  234. end  
  235.   
  236. % calculate bin index of hist3dbig  
  237. binx1 = floor((jorbj-1+cellpw/2)/cellpw) + 1;  
  238. biny1 = floor((iorbi-1+cellph/2)/cellph) + 1;  
  239. binz1 = floor((go+(or*pi/nthet)/2)/(or*pi/nthet)) + 1;  
  240.   
  241. if gs < 1E-5  
  242. continue;  
  243. end  
  244.   
  245. binx2 = binx1 + 1;  
  246. biny2 = biny1 + 1;  
  247. binz2 = binz1 + 1;  
  248.   
  249. x1 = (binx1-1.5)*cellpw + 0.5;  
  250. y1 = (biny1-1.5)*cellph + 0.5;  
  251. z1 = (binz1-1.5)*(or*pi/nthet);  
  252.   
  253. % trilinear interpolation.  
  254. hist3dbig(biny1,binx1,binz1) =...  
  255. hist3dbig(biny1,binx1,binz1) + gs*gaussweight...  
  256. * (1-(jorbj-x1)/cellpw)*(1-(iorbi-y1)/cellph)...  
  257. *(1-(go-z1)/(or*pi/nthet));  
  258. hist3dbig(biny1,binx1,binz2) =...  
  259. hist3dbig(biny1,binx1,binz2) + gs*gaussweight...  
  260. * (1-(jorbj-x1)/cellpw)*(1-(iorbi-y1)/cellph)...  
  261. *((go-z1)/(or*pi/nthet));  
  262. hist3dbig(biny2,binx1,binz1) =...  
  263. hist3dbig(biny2,binx1,binz1) + gs*gaussweight...  
  264. * (1-(jorbj-x1)/cellpw)*((iorbi-y1)/cellph)...  
  265. *(1-(go-z1)/(or*pi/nthet));  
  266. hist3dbig(biny2,binx1,binz2) =...  
  267. hist3dbig(biny2,binx1,binz2) + gs*gaussweight...  
  268. * (1-(jorbj-x1)/cellpw)*((iorbi-y1)/cellph)...  
  269. *((go-z1)/(or*pi/nthet));  
  270. hist3dbig(biny1,binx2,binz1) =...  
  271. hist3dbig(biny1,binx2,binz1) + gs*gaussweight...  
  272. * ((jorbj-x1)/cellpw)*(1-(iorbi-y1)/cellph)...  
  273. *(1-(go-z1)/(or*pi/nthet));  
  274. hist3dbig(biny1,binx2,binz2) =...  
  275. hist3dbig(biny1,binx2,binz2) + gs*gaussweight...  
  276. * ((jorbj-x1)/cellpw)*(1-(iorbi-y1)/cellph)...  
  277. *((go-z1)/(or*pi/nthet));  
  278. hist3dbig(biny2,binx2,binz1) =...  
  279. hist3dbig(biny2,binx2,binz1) + gs*gaussweight...  
  280. * ((jorbj-x1)/cellpw)*((iorbi-y1)/cellph)...  
  281. *(1-(go-z1)/(or*pi/nthet));  
  282. hist3dbig(biny2,binx2,binz2) =...  
  283. hist3dbig(biny2,binx2,binz2) + gs*gaussweight...  
  284. * ((jorbj-x1)/cellpw)*((iorbi-y1)/cellph)...  
  285. *((go-z1)/(or*pi/nthet));  
  286. end  
  287. end  
  288.   
  289. % In the local interpolate condition. F is generated in this block   
  290. % slide loop. hist3dbig should be cleared in each loop.  
  291. if glbalinter == 0  
  292. if or == 2  
  293. hist3dbig(:,:,2) = hist3dbig(:,:,2)...  
  294. + hist3dbig(:,:,nthet+2);  
  295. hist3dbig(:,:,(nthet+1)) =...  
  296. hist3dbig(:,:,(nthet+1)) + hist3dbig(:,:,1);  
  297. end  
  298. hist3d = hist3dbig(2:(nblockh+1), 2:(nblockw+1), 2:(nthet+1));  
  299. for ibin = 1:nblockh  
  300. for jbin = 1:nblockw  
  301. idsF = nthet*((ibin-1)*nblockw+jbin-1)+1;  
  302. idsF = idsF:(idsF+nthet-1);  
  303. sF(idsF) = hist3d(ibin,jbin,:);  
  304. end  
  305. end  
  306. iblock = ((btly-1)/ybstride)*ntotalbw +...  
  307. ((btlx-1)/xbstride) + 1;  
  308. idF = (iblock-1)*nblockw*nblockh*nthet+1;  
  309. idF = idF:(idF+nblockw*nblockh*nthet-1);  
  310. F(idF) = sF;  
  311. hist3dbig(:,:,:) = 0;  
  312. end  
  313. end  
  314. end  
  315. % In the global interpolate condition. F is generated here outside the  
  316. % block slide loop   
  317. if glbalinter == 1  
  318. ncellx = N / cellpw;  
  319. ncelly = M / cellph;  
  320. if or == 2  
  321. hist3dbig(:,:,2) = hist3dbig(:,:,2) + hist3dbig(:,:,nthet+2);  
  322. hist3dbig(:,:,(nthet+1)) = hist3dbig(:,:,(nthet+1)) + hist3dbig(:,:,1);  
  323. end  
  324. hist3d = hist3dbig(2:(ncelly+1), 2:(ncellx+1), 2:(nthet+1));  
  325.   
  326. iblock = 1;  
  327. for btly = 1:ybstride:ybstridend  
  328. for btlx = 1:xbstride:xbstridend  
  329. binidx = floor((btlx-1)/cellpw)+1;  
  330. binidy = floor((btly-1)/cellph)+1;  
  331. idF = (iblock-1)*nblockw*nblockh*nthet+1;  
  332. idF = idF:(idF+nblockw*nblockh*nthet-1);  
  333. for ibin = 1:nblockh  
  334. for jbin = 1:nblockw  
  335. idsF = nthet*((ibin-1)*nblockw+jbin-1)+1;  
  336. idsF = idsF:(idsF+nthet-1);  
  337. sF(idsF) = hist3d(binidy+ibin-1, binidx+jbin-1, :);  
  338. end  
  339. end  
  340. F(idF) = sF;  
  341. iblock = iblock + 1;  
  342. end  
  343. end  
  344. end  
  345. % adjust the negative value caused by accuracy of floating-point  
  346. % operations.these value's scale is very small, usually at E-03 magnitude  
  347. % while others will be E+02 or E+03 before normalization.  
  348. F(F<0) = 0;  
  349. % block normalization.  
  350. e = 0.001;  
  351. l2hysthreshold = 0.2;  
  352. fslidestep = nblockw*nblockh*nthet;  
  353. switch normmethod  
  354. case 'none'  
  355. case 'l1'  
  356. for fi = 1:fslidestep:size(F,2)  
  357. div = sum(F(fi:(fi+fslidestep-1)));  
  358. F(fi:(fi+fslidestep-1)) = F(fi:(fi+fslidestep-1))/(div+e);  
  359. end  
  360. case 'l1sqrt'  
  361. for fi = 1:fslidestep:size(F,2)  
  362. div = sum(F(fi:(fi+fslidestep-1)));  
  363. F(fi:(fi+fslidestep-1)) = sqrt(F(fi:(fi+fslidestep-1))/(div+e));  
  364. end  
  365. case 'l2'  
  366. for fi = 1:fslidestep:size(F,2)  
  367. sF = F(fi:(fi+fslidestep-1)).*F(fi:(fi+fslidestep-1));  
  368. div = sqrt(sum(sF)+e*e);  
  369. F(fi:(fi+fslidestep-1)) = F(fi:(fi+fslidestep-1))/div;  
  370. end  
  371. case 'l2hys'  
  372. for fi = 1:fslidestep:size(F,2)  
  373. sF = F(fi:(fi+fslidestep-1)).*F(fi:(fi+fslidestep-1));  
  374. div = sqrt(sum(sF)+e*e);  
  375. sF = F(fi:(fi+fslidestep-1))/div;  
  376. sF(sF>l2hysthreshold) = l2hysthreshold;  
  377. div = sqrt(sum(sF.*sF)+e*e);  
  378. F(fi:(fi+fslidestep-1)) = sF/div;  
  379. end  
  380. otherwise  
  381. error('Incorrect NORMMETHOD parameter.');  
  382. end  

===============================================================================================================

他山之石:

     目标检测的图像特征提取之(一)HOG特征

     Histograms of Oriented Gradients (HOG)理解和源码


0 0
原创粉丝点击