Matlab 圖像處理中出現純黑或純白是怎么回事?


在圖像處理中,經常會出現這圖像顯示為純黑或者純白的情況,這其實是數據類型轉換時出錯導致的。

所涉及到的函數主要包括以下幾個

  • imread
  • imshow
  • double、im2double
  • uint8、im2uint8

imread

圖像文件經過 imread 函數讀取后,獲取到的圖像數據類型為 uint8 。

clear;close all;clc

%% 導入圖像
% https://www.ece.rice.edu/~wakin/images/lena512.bmp
img = imread('lena512.bmp');

%% 查看變量
whos img

%% 輸出結果
%{

  Name        Size              Bytes  Class    Attributes

  img       512x512            262144  uint8  

%}
 

double

double 是 matlab 默認的數據類型,即雙精度浮點數據,允許小數點的和負數存在。

在 matlab 中使用 double() 函數實現數據轉型為 double 類型。

clear;close all;clc

%% 默認數據類型為 double
x1 = 123.5;
%{
  Name      Size            Bytes  Class     Attributes

  x1        1x1                 8  double  
%}

%% 默認數據轉 double
x2 = double(x1);
whos x2
%{
  Name      Size            Bytes  Class     Attributes

  x2        1x1                 8  double              
%}

%% uint8 轉double
x3 = uint8(245);
whos x3
%{
  Name      Size            Bytes  Class    Attributes

  x3        1x1                 1  uint8    
%}

x4 = double(x3);
whos x4
%{
  Name      Size            Bytes  Class     Attributes

  x4        1x1                 8  double   
%}

結論

由於 double 屬於浮點數據,精度高,取值范圍廣,因此輸入數據轉換為 double 類型后,數值一般不會發生改變,只是變成了浮點型數據,即數據允許小數點和負數存在了。

uint8

uint8 是一種無符號整型數據。取值范圍為 0 到 255 之間的整數。

double --> uint8

clear;close all;clc

x = -100:1:350;
y = uint8(x);

plot(x,y);
xlabel('x');ylabel('y')

值得注意的是,這里的取整采用的是四舍五入的方式,即就近取整原則。

clear;close all;clc

x = -1:0.1:2;
y = uint8(x);

plot(x,y);
xlabel('x');ylabel('y')

結論

對於 double 類型的輸入數據,uint8 將其 0 - 255 部分的數據取整,溢出的部分就近處理為 0 或 255。

im2uint8

uint8 --> im2uint8

clear;close all;clc

x = uint8(0:255);
y = im2uint8(x);

plot(x,y);
xlabel('x');ylabel('y')
axis square
axis tight

double --> im2uint8

clear;close all;clc

x = double(-100:255);
y = im2uint8(x);

plot(x,y);
xlabel('x');ylabel('y')
axis square
axis tight

clear;close all;clc

x = double(0:0.1:1);
y = im2uint8(x);

plot(x,y);
xlabel('x');ylabel('y')
axis square
axis tight

結論

  1. 對於 uint8 類型數據,im2uint8 不對其做變換。
  2. 對於 double 類型數據,im2uint8 將其 0 - 1 部分重新映射到 0 - 255 之間,然后對於溢出的部分,就近處理為 0 或 255。

im2double

double --> im2double

clear;close all;clc

x = double(-255:255);
y = im2double(x);

plot(x,y);
xlabel('x');ylabel('y')
axis square
axis tight

uint8 --> im2double

clear;close all;clc

x = uint8(0:255);
y = im2double(x);

plot(x,y);
xlabel('x');ylabel('y')
axis square
axis tight

結論

  1. 對於 double 類型數據,im2double 不對其做變換。
  2. 對於 uint8 類型數據,im2double 將其 0 - 255 部分重新映射到 0 - 1 之間,這里 uint8 數據本身有溢出限制,因此不存在小於 0 或 大於 1 的部分。

imshow

uint8 --> imshow

clear;close all;clc
x =uint8(0:255);
y = repmat(x,length(x),1);
imshow(y)

double --> imshow

clear;close all;clc
x =double(-255:255);
y = repmat(x,length(x),1);
imshow(y)

clear;close all;clc
x =double(0:0.01:1);
y = repmat(x,length(x),1);
imshow(y)

結論

  1. 對於 uint8 數據,imshow 直接按照 0 - 255 將數值映射到灰度級上,0 對應純黑,255 對應純白,中間為漸變灰。
  2. 對於 double 數據,imhsow 僅保留其 0 - 1 之間的數值,並映射到灰度級上,0 對應純黑,1 對應純白,中間為漸變灰;對於溢出的部分,就近處理到 0 或 1 ,顯示為純黑或純白。

圖像數據轉換關系分析

根據以上結論,可以總結出在圖像處理中數據類型的轉換類型關系圖。

當讀取了一張圖像后,數據就來到了圖中的 uint8(0,255) 這個節點,表示數據類型為 uint8,取值范圍為 0 到 255 ,然后,它可以使用前面提到的函數在 double 和uint8 之間任意地相互轉換,但若想正常顯示,則需要轉換到 uint8 ,取值范圍覆蓋 0 到 255 之間,或轉換到 double 取值范圍覆蓋 0 到 1。若無法對應以上規則,則有可能出現純黑或者純白的情況。

參考資料

  1. https://www.cs.utah.edu/~germain/PPS/Topics/Matlab/uint8.html
  2. https://ww2.mathworks.cn/help/matlab/matlab_prog/integers.html
  3. https://ww2.mathworks.cn/help/matlab/ref/double.html
  4. https://ww2.mathworks.cn/help/matlab/matlab_prog/floating-point-numbers.html
  5. https://ww2.mathworks.cn/help/matlab/ref/imread.html
  6. https://www.ece.rice.edu/~wakin/images/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM