【问题标题】:Calculate the pixel distance to three defined pixel in matlab在matlab中计算到三个定义像素的像素距离
【发布时间】:2015-03-14 16:15:22
【问题描述】:

我想根据像素的 RGB 颜色对一张 tiff 图像的像素进行分类。输入是一张图像和三种预定义颜色,分别用于水(r0,g0,b0)、森林(r1,g1,b1)和建筑物(r2,g2,c2)。分类是基于图像像素与这三种颜色之间的距离。如果像素离水最近,则该像素为水并将其更改为水 RGB。距离计算为(一个样本)sqrt((x-r0)^2+(y-g0)^2+(z0-b0)^2)

示例实现是:

a=imread(..);
[row col dim] = size(a);   % dim =3 
for i=1:row
   for j=1:col
       dis1=sqrtCal(a(i,j,:)-water) 
       dis2=sqrtCal(a(i,j,:)-forest) 
       dis3=sqrtCal(a(i,j,:)-build)
       a(i,j,:) = water;
       if  dis2< dis1
           dis1 = dis2
           a(i,j,:) = forest
       end
       dis3=sqrt(a(i,j,:)-build)
       if dis3<dis1
          a(i,j,:) = build
       end
   end
end

这个实现应该可以工作。问题是这两个for循环不是一个好的选择。

那么在 Matlab 中有什么好的替代品吗?这 D = pdist(X,distance) 似乎不适用于我的情况。

【问题讨论】:

  • 所以结果将是一个包含 1、2、3 个值的 MxN 数组,其中 M、N 是图像大小?而且,参考颜色的数量是否固定(在您的情况下为 3)?
  • 是的,它已修复。图像为M*N*3,其中'3'为(R,G,B)
  • 同时我已经为任意数量的参考颜色写了一个答案
  • 您可以使用im2double,而不是手动从uint8 转换为double

标签: matlab distance


【解决方案1】:

我认为这可以满足您的需求。参考颜色的数量是任意的(在您的示例中为3)。每个参考颜色定义为矩阵ref_colors 的一行。让MxN 表示原始图像中的像素数。因此原始图像是一个MxNx3 数组。

result_index 是一个 MxN 数组,其中每个原始像素都包含最接近参考颜色的索引。

result 是一个MxNx3 数组,其中每个像素都分配了最接近参考颜色的 RBG 值。

im = rand(10,12,3);          %// example image
ref_colors = [ .1 .1 .8; ... %// water
               .3 .9 .2; ... %// forest
               .6 .6 .6 ];   %// build: example reference colors
dist = sum(bsxfun(@minus, im, permute(ref_colors, [3 4 2 1])).^2, 3);
    %// 4D array containing the distance from each pixel to each reference color.
    %// Dimensions are: 1st: pixel row, 2nd: pixel col, 3rd: not used,
    %// 4th: index of reference color
[~, result_index] = min(dist, [], 4); %// compute arg min along 4th dimension
result = reshape(ref_colors(result_index,:), size(im,1), size(im,2), 3);

【讨论】:

  • 你可以用min(..[],4)避免squeeze
  • 看来result 是沿第三维度的最小距离。但是如何更新原始矩阵im。比如im(2,3,:)归类为水,怎么给im(2,3,:)赋值水RGB,这里是(.1, .1, .8)?
  • @shijiexu result 已经包含更新的颜色值,正如您在答案中指定的那样。检查我的例子
  • @Divakar 好主意!谢谢!
  • 谢谢大家。这段代码对我来说似乎没问题,我现在说清楚了。一个小问题是生成的图像不像我预期的那样(我更新了我的帖子)。这可能是因为脚本是在图像写入库已过期的机器上执行的。
【解决方案2】:

这是另一个基于 bsxfun 的解决方案,但仍保留在 3D 中,并且可能更高效 -

%// Concatenate water, forest, build as a 2D array for easy processing
wfb = cat(2,water(:),forest(:),build(:))

%// Calculate square root of squared distances & indices corresponding to min vals
[~,idx] = min(sum(bsxfun(@minus,reshape(a,[],3),permute(wfb,[3 1 2])).^2,2),[],3)

%// Get the output with the minimum from the set of water, forest & build
a_out = reshape(wfb(:,idx).',size(a))

【讨论】:

  • 好主意:少一维。要实现这一点,您需要将原始图像的前两个维度合并为一个,但它可能更有效
  • @LuisMendo 是的,我发现 reshape 有时更便宜!
【解决方案3】:

如果你安装了统计工具箱,你可以使用这个基于knnsearch的版本,它可以很好地适应大量颜色。

result_index = knnsearch(ref_colors, reshape(im,[],3));
result = reshape(ref_colors(result_index,:), size(im));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2014-11-16
    • 2020-07-29
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多