下面介紹兩種簡單的處理圖像色彩平衡問題的算法,色彩平衡就是說將一張圖片中RGB三個通道的值處理的相對均衡,也就是將圖像中物體原本的顏色恢復出來,而不是在光照或者陽光下變色。
算法1:White Balance
matlab實現如下:
function res = WhiteBalance(img) RGB=imread(img); R=RGB(:,:,1); G=RGB(:,:,2); B=RGB(:,:,3); I=0.299*R+0.587*G+0.114*B; kr=mean(I(:))/mean(R(:)); kg=mean(I(:))/mean(G(:)); kb=mean(I(:))/mean(B(:)); % res(:,:,1)=kr*R; % res(:,:,2)=kg*G; % res(:,:,3)=kb*B; res=cat(3,kr*R,kg*G,kb*B); end
算法2:Maximum Value Balance
TR,TG,TB的含義:首先統計三個通道中高於SRGB的強度的個數,找到最大個數為Nmax,最后在每個通道中找到第Nmax個最大的強度值(也就是從大到小排序第Nmax個值)分別為TR,TG,TB。
matlab實現如下:
function res = MaxValueBalance(img) RGB=imread(img); R=RGB(:,:,1); % figure, imhist(R); G=RGB(:,:,2); % figure, imhist(G); B=RGB(:,:,3); % figure, imhist(B); Srgb=min([max(R(:)) max(G(:)) max(B(:))]); Nmax=max([sum(sum(R>=Srgb)) sum(sum(G>=Srgb)) sum(sum(B>=Srgb))]); Tr_temp=sort(R(:),'descend'); Tr=Tr_temp(Nmax); Tg_temp=sort(G(:),'descend'); Tg=Tg_temp(Nmax); Tb_temp=sort(B(:),'descend'); Tb=Tb_temp(Nmax); kr=Srgb/Tr; kg=Srgb/Tg; kb=Srgb/Tb; % res(:,:,1)=kr*R; % res(:,:,2)=kg*G; % res(:,:,3)=kb*B; res=cat(3,kr*R,kg*G,kb*B); end
最后主函數測試一些示例圖片,主函數如下:
clear;close all;clc; addpath('E:\Digital_img_processing\Lecture_3_dicussion_color_balance'); fig1='BW1.png'; fig2='BW2.png'; fig3='BW3.jpg'; wb_algorithm3=WhiteBalance(fig3); % wb_algorithm2=WhiteBalance(fig2); % wb_algorithm1=WhiteBalance(fig1); % figure, imshow(wb_algorithm3); title('White Balance algorithm 3'); % figure, imshow(wb_algorithm2); % title('White Balance algorithm 2'); % figure, imshow(wb_algorithm1); % title('White Balance algorithm 1'); % mvb_algorithm3=MaxValueBalance(fig3); % mvb_algorithm2=MaxValueBalance(fig2); % mvb_algorithm1=MaxValueBalance(fig1); % figure, imshow(mvb_algorithm3); % title('Max Value Balance algorithm 3'); % figure, imshow(mvb_algorithm2); % title('Max Value Balance algorithm 2'); % figure, imshow(mvb_algorithm1); % title('Max Value Balance algorithm 1');
測試結果如下:
算法1(輸入->輸出):
值得注意的是,后面兩個測試圖片有白色的邊框,這在平衡后的圖像中也可以看出,如果去掉這些白色的邊框效果會更好,如下:
算法2(輸入->輸出):
需要注意的問題:(這些問題是一些使用matlab或者是處理數字圖像的基本問題,查了一些其他資料,予以總結)
①變量清除的問題:如果重復執行某一腳本命令文件,需要在最前面加上在前面clc; close all; clear all; 為了清除工作空間中之前的變量,否則會影響后續的變量值。(clc: 清空命令窗口內容,不影響變量;close all: 關閉所有figure窗口;clear all: 清除工作空間所有變量,函數,MEX文件)
本實驗沒有加...作為一個好習慣以后都應該加上。
②數據類型的問題:
matlab中讀取圖片后保存的數據是uint8類型(8位無符號整數,即1個字節),而matlab默認數據類型雙精度浮點double(64位,8個字節)。雖然matlab中讀入圖像的數據類型是uint8,但圖像矩陣運算時的數據類型是double類型(這是因為精度及計算溢出問題)。
將圖像轉為double格式:
(1) im2double()函數:參數為uint8型時,轉化結果矩陣元素取值位於(0,1)。
(2) double()函數:參數為uint8型時,轉化結果矩陣元素取值位於(0,255)。
圖像顯示:
matlab處理完圖像矩陣后,用imshow()顯示圖像或用inwrite()寫入圖片。如果參數數據類型是double型,認為double型數據位於(0,1),對於數組中大於1的元素,會將其歸為1,顯示為白色。而imshow顯示uint8型時是0~255范圍。所以對double類型的圖像顯示的時候,要么歸一化到0~1之間,要么將double類型的0~255數據轉為uint8類型。解決方法如下:
imshow(I/255); % 將圖像矩陣轉化到0-1之間 imshow(I,[]); % 自動調整數據的范圍以便於顯示 inshow(uint8(I)); % 轉成uint8
另外如果矩陣數據圖像是double類型(0~1之間)可直接im2uint8,這樣不僅完成數據類型轉換,而且將0~1之間映射為了0~255之間的數據。但是如果圖像矩陣數據是double類型的0~255,直接im2uint8轉換的話,matlab會將大於1的數據都轉換為255,0~1之間的數據才會映射到0~255之間整型的數據。
mat2gray()和im2double()區別
這兩個如果都是對uint8數據操作,區別就在於前者是歸一化操作,歸一化后也在0~1之間,自然結果也是double類型,后者是將數據從0~255映射到0~1。計算公式如下(I 代表強度,也就是像素值):
mat2gray:
im2double:
總結:(均考慮uint8)
int->double:(讀入圖像並進行運算)
im2double: 映射 (0,1)
double: (0,255)
mat2gray: 歸一化 (0,1)
double->int:(輸出圖像)
① double類型在(0,255)之間
imshow(I/255): (0,1)
imshow(I,[]): (0,255)
imshow(uint8(I)) : (0,255)
② double類型在(0,1)之間
im2uint8(): (0,255)
uint8(round(I*255))
總之,就像是一個解碼-編碼的過程,im_和im_ 配合食用,其他類似。
ref:
matlab中clc,close,close all,clear,clear all作用區別: https://blog.csdn.net/majinlei121/article/details/46605783
Matlab圖像數據類型unit8,double關系: https://blog.csdn.net/cymy001/article/details/78038324
matlab圖像類型轉換以及uint8、double、im2double、im2uint8和mat2gray等說明: https://blog.csdn.net/FX677588/article/details/53301740?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task