【问题标题】:How to compute the mean value of all sub-imges in image I如何计算图像 I 中所有子图像的平均值
【发布时间】:2015-04-05 18:03:27
【问题描述】:

我有一个任务是计算从输入图像 I 中提取的子图像的平均值。让我们解释一下我的任务。我有一个图像 I(即 9x9)和一个窗口(即大小 3x3)。窗口将从图像的左上角到右下角运行。因此,它将输入图像提取为许多子图像。我想计算这些子图像的平均值。您能否向我建议一些 matlab 代码来计算它。

这是我的解决方案。但它不起作用。

  • 首先,我定义了一个高斯窗口
  • 其次,高斯函数将使用卷积函数从左上角运行到右下角。 (注意,必须使用高斯核)
  • 计算每个子窗口的平均值

    %% Given Image I,Defined a Gaussian Kernel
    sigma=3;
    K=fspecial('gaussian',round(2*sigma)*2+1,sigma);     
    KI=conv2(I,K,'same');
    %% mean value
    mean(KI)
    

    这里的问题是所有子图像的平均值都会有大小相似的图像I。因为图像中的每个像素都会形成一个子图像。但我的代码只返回一个值。什么问题?

【问题讨论】:

  • mean(KI) 对于 2D 矩阵 / 信号将为您提供一个单行向量,其中每个元素是位于 KI 中该索引处的 的平均值.鉴于您的描述,这肯定不是您想要计算的。无论哪种方式,我都提供了答案。
  • 是的,我误用了函数均值(KI)

标签: matlab image-processing


【解决方案1】:

如果您希望在使用高斯核过滤图像后计算每个子图像的平均值,只需将图像与mean or average filter 进行卷积即可。这将收集原始图像中的子图像,并且对于每个输出位置,您将计算平均值。

按照您最初假设掩码大小为 3 x 3,只需将 conv2 与具有所有 1/9 系数的 3 x 3 掩码结合使用即可。换句话说:

%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);     
KI=conv2(I,K,'same');

%// New code
mask = (1/9)*ones(3,3);
out = conv2(KI, mask, 'same');

out 中的每个位置都会为您提供高斯过滤结果中每个 3 x 3 子图像的平均值。

您还可以通过使用 fspecial 和标志 average 并指定掩码的大小/宽度来创建平均掩码。鉴于您已经在代码中使用它,您已经知道它的存在。因此,您也可以这样做:

mask = fspecial('average', 3);

上面的代码假设掩码的宽度和高度相同,因此它将创建一个包含所有 1/9 系数的 3 x 3 掩码。

一边

conv2 专为一般二维信号而设计。如果您要过滤图像,我建议您改用imfilter。您应该可以访问它,因为fspecial 是图像处理工具箱的一部分,imfilter 也是如此。众所周知,imfilterconv2 效率更高,并且如果可用,还可以使用Intel Integrated Performance Primitives (Intel IPP)(基本上,如果您在具有支持 IPP 的 Intel 处理器的计算机上运行 MATLAB)。因此,您确实应该以这种方式执行过滤:

%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);     
KI=imfilter(I,K,'replicate'); %// CHANGE

%// New code
mask = fspecial('average', 3);
out = imfilter(KI, mask, 'replicate'); %// CHANGE

replicate 标志用于处理边界条件。当您的遮罩超出原始图像的边界时,replicate 会简单地复制图像每一侧的边框,以便在执行过滤时遮罩可以舒适地适合图像。

编辑

鉴于您的评论,您想要提取在KI 中看到的子图像。您可以使用非常强大的im2col 函数,它是图像处理工具箱的一部分。你这样称呼它:

B = im2col(A,[m n]);

A 将是您的输入图像,B 将是一个大小为mn x L 的矩阵,其中L 将是您的图像中可能存在的子图像的总数,m ,n分别是每个子图像的高度和宽度。 im2col 的工作原理是,对于图像中存在的每个子图像,它会扭曲它们,使其适合B 中的单个 列。因此,B 中的每一列都会生成一个单独的子图像,该子图像会被扭曲成一列。然后,您可以使用 B 中的每一列进行 GMM 建模。

但是,im2col 仅返回不会超出范围的有效子图像。如果您想处理边缘和角落的情况,您需要先填充图像。使用padarray 来促进此填充。因此,要满足您的要求,我们只需:

Apad = padarray(KI, [1 1], 'replicate');
B = im2col(Apad, [3 3]);

第一行代码将填充图像,使图像周围有一个 1 像素的边框。这将允许您在边界位置提取 3 x 3 子图像。我使用replicate 标志,以便您可以简单地复制边框像素。接下来,我们使用im2col,以便您获得 3 x 3 的子图像,然后将其存储在B 中。因此,B 将成为一个 9 x L 矩阵,其中每一列都会为您提供一个 3 x 3 的子图像。

请注意,im2col 会以 column-major 格式扭曲这些列。这意味着对于您拥有的每个子图像,它会获取子图像中的每一列并将它们堆叠在一起,从而为您提供9 x 1 列。您将拥有L 总子图像,这些子图像水平连接以产生9 x L 矩阵。此外,请记住,子图像的读取顺序从上到下,然后从左到右,因为这是 MATLAB 以列优先顺序运行的本质。

【讨论】:

  • 感谢rayryeng,代码很清晰。但是,我有一个简短的问题。如果我想从 I 中提取这些子图像。怎么做。因为平均是我的一项简单任务。另一个任务是为每个子图像使用高斯混合模型找到 pdf。对于高斯混合器模型已完成。现在我想为每个子图像应用该功能。提前致谢
  • 完美。 L 是否等于 mxn,因为每个像素都会创建一个以该像素为中心的 sub_image?为了显示子图像,我必须重塑它。例如,这是我要查看的代码 ....for i=1:L sub_image= B(:,i); sub_image=reshape(sub_image,[3 3]); imshow(sub_image);结束
  • @user8430 - 填充图像后,可以。此外,您的代码可以正确显示每个子图像。确保将pause 作为for 循环中的最后一条语句,以便您可以慢慢查看每个补丁。这样,您可以按下一个键,以便它转到下一个子图像。如果您不确定L,只需执行:L = size(B,2); 自动让 MATLAB 为您计算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-01
  • 1970-01-01
  • 2022-11-30
  • 2012-04-27
  • 2014-03-01
相关资源
最近更新 更多