如何更改 Matlab 代码以便 imshow() 函数显示正确的颜色?
How to change Matlab code so the imshow() function shows the correct colors?
我写了一个简单的 Matlab 代码,它加载图像并在 x 轴和 y 轴上进行平移。如果图像应在 x 轴上平移 10 个像素,我将前 10 列填充为 0,将所有列向右移动 10 个单位,并将图片右侧剪切 10 个像素。当我输入正 x 值时,加载的图片不再显示正确的颜色(它显示负值),尽管当我将它们打印到屏幕时 RGB 值是正确的!
我已经在 Internet 上看到,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,中间没有任何值。
所以我玩了一会儿代码,发现如果我不手动将 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);
你的代码适合我。
您遇到的一个问题是您没有预分配 picture_out
。它在您第一次为其赋值时创建,并在您每次为其赋值时扩展。您分配给它的第一个值决定了它的类型。如果你赋值0
(一个double
),它就会变成一个double
数组。如果您从 picture_in
中分配一个值(uint8
),它将成为一个 uint8
数组。根据您将图像移动到哪个方向,将发生一种或另一种情况。
一张uint8
图像中的值是0-255。这些是您的输入值。 double
图像可以存储几乎任何数量级的值,但 MATLAB 始终假定此类图像的值在 0-1 范围内。因为您将 0-255 范围内的值放入 double
数组中,所以当您调用 imagesc
时,MATLAB 会假设任何大于 1 的值都应为 1,因此会向您显示一个 all -白色图像。
因此,当您向左移动图像时,您会得到一个 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
此外,在 MATLAB 中,从 k=0
而 k<Q
循环更自然,而不是从 k=1
而 k<=Q
循环,如 [=28] =] 上面的循环。
但是,在很多情况下,您实际上根本不需要循环。您的代码可以更有效地重写为
picture_out = zeros(size(picture_in),'uint8');
picture_out(:,1+tx:end,:) = picture_in(:,1:end-tx,:);
(对于 tx>0
的情况;您可以更改索引以另一种方式移动。)
或者,使用 circshift
:
picture_out = circshift(picture_in,tx,2);
这里,tx
也可以是负数。
我写了一个简单的 Matlab 代码,它加载图像并在 x 轴和 y 轴上进行平移。如果图像应在 x 轴上平移 10 个像素,我将前 10 列填充为 0,将所有列向右移动 10 个单位,并将图片右侧剪切 10 个像素。当我输入正 x 值时,加载的图片不再显示正确的颜色(它显示负值),尽管当我将它们打印到屏幕时 RGB 值是正确的!
我已经在 Internet 上看到,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,中间没有任何值。
所以我玩了一会儿代码,发现如果我不手动将 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);
你的代码适合我。
您遇到的一个问题是您没有预分配 picture_out
。它在您第一次为其赋值时创建,并在您每次为其赋值时扩展。您分配给它的第一个值决定了它的类型。如果你赋值0
(一个double
),它就会变成一个double
数组。如果您从 picture_in
中分配一个值(uint8
),它将成为一个 uint8
数组。根据您将图像移动到哪个方向,将发生一种或另一种情况。
一张uint8
图像中的值是0-255。这些是您的输入值。 double
图像可以存储几乎任何数量级的值,但 MATLAB 始终假定此类图像的值在 0-1 范围内。因为您将 0-255 范围内的值放入 double
数组中,所以当您调用 imagesc
时,MATLAB 会假设任何大于 1 的值都应为 1,因此会向您显示一个 all -白色图像。
因此,当您向左移动图像时,您会得到一个 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
此外,在 MATLAB 中,从 k=0
而 k<Q
循环更自然,而不是从 k=1
而 k<=Q
循环,如 [=28] =] 上面的循环。
但是,在很多情况下,您实际上根本不需要循环。您的代码可以更有效地重写为
picture_out = zeros(size(picture_in),'uint8');
picture_out(:,1+tx:end,:) = picture_in(:,1:end-tx,:);
(对于 tx>0
的情况;您可以更改索引以另一种方式移动。)
或者,使用 circshift
:
picture_out = circshift(picture_in,tx,2);
这里,tx
也可以是负数。