图像快速特征提取

image fast feature extraction

我在 matlab 中有一个定义为真实比例 (0,1) 的图像和一个定义为整数比例的蒙版。

例子

mask = [ 1 1 1 3 4 ;
         1 1 1 2 4 ;
         1 1 2 2 2  ]

img = [ 0.1 0.1 0.2 0.2 0.3 ;
        0.1 0.1 0.2 0.3 0.3 ;
        0.1 0.1 0.3 0.3 0.3 ]

对于掩码中的每个区域(即 1、2、3、4),我想计算相应图像强度的某个特征(比如平均值)。

我用过的算法是

for i = labels
  region = img(mask==i);
  feature(i) = mean(region);
end

现在,对于大小为 300x400x500 且标签集的基数 > 40000(顺便说一句,这正是我的情况)的图像,此算法非常慢。

关于如何加速我的代码有什么建议吗?

bsxfun and fast matrix-multiplication 基于方法获取平均值 -

num_labels = max(mask(:)); %// number of labels used
labels = 1:num_labels;     %// array of all labels

%// Get a 2D mask for all labels, with each column representing a label.
%// This is a setup for use with matix-multiplication later on
mask_labels = bsxfun(@eq,mask(:),labels);

%// Perform fast matrix multiplication as a way to perform summation for
%// all labels and then do elementwise division to get the mean values
feature_out = (img(:)'*mask_labels)./sum(mask_labels,1);

我认为我们需要了解更多:

  • 如何计算遮罩?
  • 您想在这些区域上计算哪些特征? (仅表示?)
  • 慢是什么意思?

如果可以矢量化为掩码的每个元素赋值的公式,那么对您的体积的访问也可以。

不过,在一般情况下,我会说使用 Mex 文件很容易做到这一点。 如果你想那样做,我建议使用 my tiny library 来简化向 Mex 的过渡,但你需要使用 C++11(-std=c++0x 标志)进行编译。

如果您想留在 Matlab 中,并且只想计算这些区域的平均值,那么 accumarray 就是您要查找的函数。

为了优雅地获得平均值(尽管它可能不是绝对最快的方法),您可以使用 accumarray:

meanFeatures = accumarray(mask(:),image(:),[],@mean);

如果你想要,例如均值和标准,你用

meanAndStd = cell2mat(accumarray(mask(:),image(:),[],@(x){mean(x), std(x)}));

据我所知,这不是 Matlab 擅长的问题。我会尝试天真的 - 非 Matlab 方法:

 label_sum = zeros(1,num_labels);
 label_size = zeros(1,num_labels);
 for z=1:500,
    for x=1:400,
       for y=1:300,
          label = labels(y, x, z);
          label_sum(label) += img(y, x, z);
          label_size(label) += 1;
        end
     end
  end
  label_sum(label_size > 0) ./ label_size(label_size > 0)

它并不理想,但可能需要不到 10 分钟...

您可以使用 arrayfun 并避免使用 for 循环。使用要迭代的 labels 值向量,它是:

features=arrayfun(@(x) mean(img(mask==x)), labels);

语法 @(x) 将迭代 labels 的每个元素,以这种方式替换 for 循环。您也可以使用任何函数代替 mean,它可以是内置函数,也可以是您创建的函数。你应该检查它的速度,但我认为这是最快的方法。

图像处理工具箱中的 regionprops 函数应该可以为您完成。例如,使用此语法:

stats = regionprops(L,I, 'MeanIntensity');

获取每个区域的平均值。 L 是包含标签的数组。我是你的头像