【问题标题】:How to change Matlab code so the imshow() function shows the correct colors?如何更改 Matlab 代码以便 imshow() 函数显示正确的颜色?
【发布时间】:2019-09-10 05:25:32
【问题描述】:

我编写了一个简单的 Matlab 代码,它加载图像并在 x 轴和 y 轴上进行平移。如果图像应该在 x 轴上平移 10 个像素,我用 0 填充前 10 列,将所有列向右移动 10 个单位,并将图片的右侧切割 10 个像素。当我输入正 x 值时,加载的图片不再显示正确的颜色(它显示负值),尽管当我将 RGB 值打印到屏幕上时它们是正确的!

我已经在互联网上读到,imshow() 做了某种缩放,但这并没有真正帮助我。

代码如下:

clear;
clc;

picture_in = imread('landscape.jpg');    %load picture
[P,Q,RGB]=size(picture_in);              %obtain size of dimension

%Translation
tx=2;
ty=0;

k=0;
j=0;
h=0;
while k<Q
    j=0;
    while j<P
        h=0;
        while h<RGB
            if (round(k+1-tx)>0)&&(round(k+1-tx)<=Q)&&(round(j+1+ty)>0)&&(round(j+1+ty)<=P) 
                picture_out(j+1,k+1,h+1)=picture_in(round(j+1+ty),round(k+1-tx),h+1);
            else
                picture_out(j+1,k+1,h+1)=0;
            end

            h=h+1;
        end
        j=j+1;
    end
    k=k+1;
end
picture_out;
imagesc(picture_out);

我真的很感谢这里的一些帮助。正如我已经提到的: - 如果翻译是否定的,那么颜色是正确的 - 当我查看移动了 2 个像素的小图像(例如 10x10)的张量时,我可以看到前两个列是 0,后面的列包含它们应该包含的值。 所以我猜是imshow()的问题

编辑(附加注释):输出图片的 RGB 值只有 0 或 255 值,但两者之间没有。

【问题讨论】:

    标签: matlab image-processing imshow


    【解决方案1】:

    您的代码适合我。

    您遇到的一个问题是您没有预先分配picture_out。它在您第一次为其分配值时创建,并在您每次为其分配另一个值时扩展。您分配给它的第一个值决定了它的类型。如果你分配0(一个double),它将变成一个double数组。如果您从picture_inuint8)中分配一个值,它将成为uint8 数组。根据您移动图像的方向,会发生其中一个或另一个。

    uint8 图像中的值是 0-255。这些是您的输入值。 double 图像可以存储几乎任何大小的值,但 MATLAB 始终假定此类图像的值在 0-1 范围内。因为您将 0-255 范围内的值放入 double 数组中,所以当您调用 imagesc 时,MATLAB 会假定任何大于 1 的值都应为 1,因此将向您显示全白图像。

    因此,当您将图像向左移动时,您会得到一个uint8 输出图像,并且它会正确显示。当您将图像向右移动时,您会得到一个double 输出图像,它会显示为全白。

    解决方案是在循环之前正确分配一个数组:

    picture_out = zeros(size(picture_in),'uint8');
    

    这将额外加速您的代码。


    不请自来的建议:

    你应该学会使用for 循环,它们比while 循环容易得多。而不是:

    k=0;
    while k<Q
        % do something
        k=k+1;
    end
    

    你得到

    for k = 1:Q
        % do something
    end
    

    另外,不是从k=0 while k&lt;Q 循环,在 MATLAB 中从k=1 while k&lt;=Q 循环更自然,就像上面的for 循环一样。


    但是,在许多情况下,您实际上根本不需要循环。您的代码可以更有效地重写为

    picture_out = zeros(size(picture_in),'uint8');
    picture_out(:,1+tx:end,:) = picture_in(:,1:end-tx,:);
    

    (对于tx&gt;0的情况;您可以将索引更改为另一种方式。)


    或者,使用circshift:

    picture_out = circshift(picture_in,tx,2);
    

    这里,tx 也可以是负数。

    【讨论】:

    • 嘿@Cris,虽然我已经发现了问题所在,但我非常感谢你的深入回答,它清除了一切。也感谢您的其他建议。
    【解决方案2】:

    所以我玩了一会儿代码,发现如果我不手动将 0 放在 else 子句中,而是像这样从图片张量中取出它:

    else
                    picture_out(j+1,k+1,h+1)=picture_in(1,1,1);
    
    

    然后一切正常。深入挖掘我发现我可以手动输入值,但我需要将它们作为 uint8() 变量放入。

    如果我像这样更改else 子句,最后代码可以工作:

    else
                    picture_out(j+1,k+1,h+1)=uint8(0);
    

    【讨论】:

      猜你喜欢
      • 2012-07-19
      • 2019-12-17
      • 1970-01-01
      • 2021-04-21
      • 2018-06-24
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      相关资源
      最近更新 更多