【问题标题】:image fast feature extraction图像快速特征提取
【发布时间】:2015-03-27 10:38:36
【问题描述】:

我在 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(顺便说一句,这正是我的情况)的图像,此算法非常慢。

关于如何加快我的代码的任何建议?

【问题讨论】:

  • 大小为300x400x500 的图像是什么意思?是 500 张大小为300x400 的图像吗?
  • @knedlsepp 明明是体积图像,Matlab中的3维数组。
  • @Sh3ljohn:我之所以问是因为该示例与给出的数据不符。 OP 可以具有:2D mask、3D img 并希望沿第三维为 img 的所有层使用相同的掩码,或者具有 3D mask 和 3D img。这就是为什么它不那么明显。
  • @knedlsepp 鉴于所提出的问题,OP 中缺乏相关信息令人震惊。但总结一下 cmets,OP 正在一个小的体积图像中进行聚类,并希望在 Matlab 中尽可能快地计算聚类强度的平均值、sdev 和偏度。
  • @Sh3ljohn:哦!在评论你的答案!所以mask 真的是一个 3D 数组。

标签: performance matlab image-processing feature-extraction


【解决方案1】:

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

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

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

【讨论】:

  • 天哪!每天学习:)这看起来是一个非常有用的功能!
【解决方案2】:

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

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

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

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

【讨论】:

  • 我认为选择accumarray 是合乎逻辑的选择(可能会添加unique 以获得带有1:length(unique(mask(:)) 条目的安全掩码),不要介意使用循环遍历图像。
  • 哦! mask 应该是一个 3D 数组。没关系。
【解决方案3】:

bsxfunfast 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);

【讨论】:

    【解决方案4】:

    我认为我们需要进一步了解:

    • 如何计算掩码?
    • 您希望在这些区域上计算哪些特征? (仅指?)
    • 慢是什么意思?

    如果为掩码的每个元素分配值的公式可以向量化,那么对您的卷的访问也可以。

    不过,在一般情况下,我会说使用 Mex 文件可以轻松做到这一点。 如果您想采用这种方式,我建议您使用my tiny library 来简化向Mex 的过渡,但您需要使用C++11(-std=c++0x 标志)进行编译。

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

    【讨论】:

    • 你如何计算掩码?这是一个创建超体素的过程,但实际上我如何创建它并不重要,假设它已经给出。您想在这些区域上计算哪些特征? (仅平均值?)平均值,强度的标准偏差,偏度。你说的慢是什么意思? > 10 分钟。我再说一遍,我有一个大小为 300x400x500 的图像,并且相应的蒙版(当然)具有相同的大小。
    • 我问是因为它很重要。如果没有关于创建掩码的过程的更多详细信息,并且给定您希望计算的一组特征,Mex 文件就是要走的路。也就是说,考虑到您计算的特征的简单性和体积的小尺寸,您的 Matlab 代码可能写得不好;话又说回来,如果没有关于这段代码的更多信息,我不能说它为什么这么慢。
    • @user1384636:您在这里的评论真的应该添加到问题本身!
    【解决方案5】:

    据我所知,这不是 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 分钟...

    【讨论】:

    • 也许可以,但这是一个非常简单的尝试,而且近年来 Matlab 在执行循环方面变得更好。
    • 它并没有回答这个问题,除非 OP 实现写得很糟糕,否则你的代码几乎是我能想到的最慢的解决方案,而且肯定比 OP 中给出的算法慢(再次,如果写得正确)。
    • 在这个实现中,我访问 3D 图像中的每个元素一次。问题中建议的实现每个标签访问 3D 图像中的每个元素一次(== 40,000 次),所以我认为值得尝试。
    • 你使用的算法是高效的;事实上,我能想到的最高效的 Mex/C++ 解决方案与此非常相似。但是 Matlab 不会有效地执行该代码。
    【解决方案6】:

    您可以使用arrayfun 并避免使用for 循环。使用要迭代的值的 labels 向量,如下所示:

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

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

    【讨论】:

    • 希望如此。然而实际上,arrayfun 甚至比原来的 for 方法还要慢...这可能是一个漂亮的单行,但使用 arrayfun 不会提高性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多