0

我的一个过程产生 256 个二进制(逻辑)矩阵,一个用于灰度源图像的每一级。

这是代码:

so = imread('bio_sd.bmp');
co = rgb2gray(so);

for l = 1:256
    bw = (co == l); %         Binary image from level l of original image
    be = ordfilt2(bw, 1, ones(3, 3)); %  Convolution filter
    bl(int16(l)) = {bwlabel(be, 8)}; %   Component labelling
end

我获得了一个包含 256 个二进制图像的单元阵列。如果该位置的源图像像素与二进制图像的索引具有相同的级别,则这样的二进制图像包含 1。

IE。二值图像 bl{12} 包含 1,其中源图像具有级别为 12 的像素。

我想通过将 256 个二进制矩阵组合回灰度图像来创建新图像。

但我对 Matlab 很陌生,我想知道是否有人可以帮我编写代码:)

ps:我用的是matlab R2010a学生版。

4

3 回答 3

3

整个答案仅适用于问题的原始形式

假设您可以将所有二进制矩阵组合成一个大的 n×m×256 矩阵binaryimage(x,y,greyvalue)。然后你可以计算你的最终图像

newimage=sum(bsxfun(@times,binaryimage,reshape(0:255,1,1,[])),3)

这里的魔法是由 bsxfun 完成的,它将 3D (nxmx 256) 二进制图像与包含灰度值 0...255 的 1 x 1 x 256 向量相乘。这将生成一个 3D 图像,其中对于固定的 x 和 y,向量 (y,x,:) 包含许多零,并且(对于G二进制图像包含 a的一个灰度值1)它包含值G。所以现在你只需要对这个第三维求和就可以得到一张n x m图像。

更新

为了测试它是否正常工作,让我们先换一种方式:

fullimage=floor(rand(100,200)*256);
figure;imshow(fullimage,[0 255]);

是一个随机灰度图像。您可以像这样计算 256 个二进制矩阵:

binaryimage=false([size(fullimage) 256]);
for i=1:size(fullimage,1)
   for j=1:size(fullimage,2)
      binaryimage(i,j,fullimage(i,j)+1)=true;
   end
end

我们现在可以应用我上面给出的解决方案

newimage=sum(bsxfun(@times,binaryimage,reshape(0:255,1,1,[])),3);

并验证我是否返回了原始图像:

all(newimage(:)==fullimage(:))

这给出了1(真):-)。

更新 2

你现在提到你的二进制图像在一个单元格数组中,我假设binimg{1:256}每个单元格都包含一个 nxm 二进制数组。如果可以的话,更改生成此数据的代码以创建我在上面使用的 3D 二进制数组可能是有意义的 - 如果不同的单元格包含不同类型、形状或大小的数据,则单元格最有用。

如果有充分的理由坚持使用元胞数组,您可以使用将其转换为 3D 数组

binaryimage = reshape(cell2mat(reshape(binimg,1,256)),n,m,256);

和上面使用nm一样。如果你已经有内部重塑是不必要的size(binimg)==[1 256]。所以总结一下,你需要使用你的单元格数组binimg来计算 3D 矩阵二进制图像,然后你可以用它来计算newimage你有兴趣使用我的答案开头的代码。

希望这可以帮助...

于 2011-06-03T11:36:38.260 回答
2

你的代码做什么...

我认为最好先了解您发布的代码实际上在做什么,因为有一些不一致之处。我将遍历循环中的每一行:

  • bw = (co == l);

    这只是创建一个二进制矩阵bw,其中灰度图像co的像素强度等于循环值l。我注意到你从 1 循环到 256,这让我觉得很奇怪。通常,加载到 MATLAB 中的图像将是无符号 8 位整数类型,这意味着灰度值将跨越 0 到 255 的范围。在这种情况下,bw您计算的最后一个二进制矩阵何时l = 256将始终包含全零。此外,您不会对灰度级别为 0 的像素进行任何处理。从后续处理中,我猜您有意忽略 0 的灰度值,在这种情况下,您可能只需要从 1 循环到 255 .

  • be = ordfilt2(bw, 1, ones(3, 3));

    您在这里使用ORDFILT2所做的基本上是执行二元腐蚀操作。任何值为 1bw的 0 作为其 8 个邻居之一的值都将设置为 0,从而导致岛的侵蚀(即尺寸缩小)。小岛将消失,只留下具有相同灰度级别的较大的连续像素簇。

  • bl(int16(l)) = {bwlabel(be, 8)};

    这就是你可能有一些误解的地方。首先, 中的矩阵bl 不是 逻辑矩阵。在您的示例中,函数BWLABEL将找到由 8 个连接的集群组成的集群。找到的第一个簇将在输出图像中将其元素标记为 1,找到的第二个簇将其元素标记为 2,依此类推。因此,矩阵将包含正整数值,其中 0 表示背景。

    其次,你打算将这些标记的集群用于任何事情吗?您可能需要进行进一步的处理,您需要在给定的灰度强度级别识别单独的集群,但关于从 中的元素创建灰度图像bl,特定的标签是不必要的。您只需要识别零值与非零值,因此如果您不使用bl其他任何值,我建议您只需将 的各个值保存be在一个单元格数组中并使用它们重新创建灰度图像。

现在,回答...

一个非常简单的解决方案是使用函数CAT将您的图像单元阵列连接成一个 3-D 矩阵,然后使用函数MAX查找沿第三维出现非零值的索引(对应于灰度值从原始图像)。对于给定的像素,如果在第三维上没有找到非零值(即全为零),那么我们可以假设像素值应该为 0。但是,MAX返回的该像素的索引将默认为 1 ,因此您必须使用最大值作为逻辑索引将像素设置为 0:

[maxValue,grayImage] = max(cat(3,bl{:}),[],3);
grayImage(~maxValue) = 0;

请注意,出于显示保存图像的目的,您可能希望将结果图像的类型更改为grayImage无符号 8 位整数类型,如下所示:

grayImage = uint8(grayImage);
于 2011-06-03T15:41:45.357 回答
1

最简单的解决方案是依次遍历每个逻辑矩阵,将其乘以相应的权重,然后累积成一个输出矩阵,该矩阵将代表您的最终图像。

于 2011-06-03T11:26:48.643 回答