图像快速特征提取
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 是包含标签的数组。我是你的头像
我在 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 是包含标签的数组。我是你的头像