从图像ROI进行高效的直方图计算

时间:2012-04-10 17:38:07

标签: performance matlab histogram

我正在寻找一些现有的功能/工具来计算图像中多个ROI(感兴趣区域)的标准Bag of Visual Words直方图。让我解释一下:

(1)假设你有一个图像,其中每个“像素”都带有一个整数:1 ... K 每个这样的“像素”具有以下信息

  1. x,y坐标
  2. 从1到K的值
  3. (2)假设大量固定大小的区域是来自所有图像的样本:

    1. (x1,y1) - 顶部,左侧坐标
    2. (x2,y2) - 底部,右坐标
    3. (3)对于每个区域:计算K bin直方图,该直方图计算属于该区域的“像素”值的出现次数

      我在MATLAB中实现了以下函数,但由于代码中存在多个for循环,因此非常慢

      function [H words] = sph_roi( wind, tree, desc, feat, bins )
      % FUNCTION computes an SPH histogram for a collection of windows. Spatial
      % information is captured by splitting the window in bins horizontally.
      %
      %   [H words] = sph_roi( obj_wind, tree, desc, feat, [ bins ] );
      %
      % INPUT :
      %   wind        - sampled ROI windows
      %                   [left_x, top_y, right_x, bottom_y] - see sample_roi()
      %   tree        - vocabulary tree
      %   desc        - descriptors matrix
      %   feat        - features matrix
      %   bins        - number of horizontal cells (1=BOVW, 2... SPH)
      %                   by default set to the multiples of window height.
      %
      % OUTPUT :
      %   H           - SPH histograms
      %   words       - word IDs found for every descriptor
      %
      
      verbose = 0;
      
      % input argument number check
      if nargin < 4
      error( 'At least 4 input arguments required.' );
      end
      
      % default number of horizontal cells
      if nargin < 5
      bins = -1;  % will be set in multiples of each window height corresp.
      end
      
      % number of windows
      num_wind = size( wind, 1 );
      
      % number of visual words
      num_words = tree.K;
      
      % pre-compute all visual words
      words = vl_hikmeanspush( tree, desc );
      
      % initialize SPH histograms matrix
      H = zeros( num_words * bins, num_wind );
      
      % compute BOVW for each ROI
      for i = 1 : num_wind
      
      if verbose == 1
          fprintf( 'sph_roi(): processing %d / %d\n', i, num_wind );
      end
      
      % pick a window
      wind_i = wind( i, : );
      
      % get the dimensions of the window
      [w h] = wind_size( wind_i );
      
      % if was not set - the number of horizontal bins
      if bins == -1
          bins = round( w / h );
      end
      
      % return a list of subcell windows
      scw = create_sph_wind( wind_i, bins );
      
      for j = 1 : bins
      
          % pick a cell
          wind_tmp = scw( j, : );
      
          % get the descriptor ids falling in that cell
          ids = roi_feat_ids( wind_tmp, feat );
      
          % compute the BOVW histogram for the current cell
          h = vl_hikmeanshist( tree, words(ids) );
      
          % assemble the SPH histogram in the output matrix directly
          H( 1+(j-1)*num_words : j*num_words, i ) = h( 2:end );
      
      end
      
      end
      
      function ids = roi_feat_ids( w, f )
      % FUNCTION returns those feature ids that fall in the window.
      %
      %   ids = roi_feat_ids( w, f );
      %
      % INPUT :
      %   w   - window
      %   f   - all feature points
      %
      % OUTPUT :
      %   ids - feature ids
      %
      
      % input argument number check
      if nargin ~= 2
      error( 'Two input arguments required.' );
      end
      
      left_x = 1;
      top_y = 2;
      right_x = 3;
      bottom_y = 4;
      
      % extract and round the interest point coordinates
      x = round( f(1,:) );
      y = round( f(2,:) );
      
      % bound successively the interest points
      s1 = ( x > w(left_x) ); % larger than left_x
      s2 = ( x < w(right_x) ); % smaller than right_x
      s3 = ( y > w(top_y) ); % larger than top_y
      s4 = ( y < w(bottom_y) ); % smaller than bottom_y
      
      % intersection of these 4 sets are the ROI enclosed interest points
      ids = s1 & s2 & s3 & s4;
      
      % convert ids to real
      ids = find( ids );
      

      我看过OpenCV提出的例程,甚至是英特尔的MKL,但没有找到合适的例子。使用Matlab的分析器,我发现在roi_feat_ids()中花费了相当多的时间,并且函数sph_roi()中每个区域的外部循环也很慢。在尝试实现MEX文件之前,我想看看是否可以回收一些现有代码。

1 个答案:

答案 0 :(得分:1)

我会采取一些措施来加快速度。

  1. 应删除最后一行(ids = find( ids );。逻辑掩码比使用find快得多,并且几乎在每种情况下都可以使用find语句。我怀疑这会大大加快你的功能,不损失功能/可读性。
  2. 如果你结合了一些s1,s2,s3和s4语句,它可能会更快。
  3. 除非需要,否则尽量不要在for循环中创建大型数据集。具体来说,我会删除两行来执行以下操作:ids = roi_feat_ids( scw( j, : ), feat );
  4. 后两者可能会节省一些时间,但首先应该节省大量时间。祝你好运!