色彩增強不同於彩色圖像增強,圖像增強的一般處理方式為直方圖均衡化等,目的是為了增強圖像局部以及整體對比度。而色彩增強的目的是為了使的原有的不飽和的色彩信息變得飽和、豐富起來。對應於Photoshop里面的“色相/飽和度”調節選項里面對飽和度的操作。色彩增強的過程,並不改變原有彩色圖像的顏色以及亮度信息。
在我的色彩增強算法模塊里面,始終只針對色彩飽和度(Saturation)信息做研究,調整。這樣的話,那就不得不介紹HSV顏色空間了,H代表Hue(色彩),S代表Saturation(飽和度),V代表Value,也可用B表示(Brightness,明度),HSV空間也可稱作HSB空間。
HSV空間在wikipedia上的介紹,https://en.wikipedia.org/wiki/HSL_and_HSV
下面根據自己的理解介紹一下HSV空間,以及其各通道在Matlab和OpenCV中的不同。
HSV的圓柱模型
HSV的圓錐模型
從上圖可以看出,在HSV空間中,Hue通道的取值從0-360°變化時,顏色從紅->黃->綠->青->藍逐步變化。Saturation從0->1變化時,色彩逐漸加深變成純色(pure)。Value值從0->1變化時,圖像整體亮度增加,V值為0時,圖像為全黑,V值為1時,圖像為全白。
Matlab RGB色彩空間向HSV轉換,采用函數rgb2hsv,轉換后的hsv各通道的元素取值范圍為[0,1];OpenCV中彩色圖像向HSV空間中轉換,cvtColor(src,srcHsv,CV_BGR2HSV),轉換后H的取值范圍為[0,180],S,V的取值范圍為[0,255].
下面介紹自己的算法處理思路,后面會給出完整的Matlab代碼:
步驟一、給出一張原圖src,用PS進行飽和度(Saturation)+40處理后另存為src_40;
步驟二、將以上兩張圖像分別轉換到hsv空間,提取出飽和度信息,分別為S,S_40;
步驟三、統計飽和度增加40后,原色彩飽和度與飽和度增量之間的對應關系,即S -- (S_40-S);
步驟四、對關系S -- (S_40-S)進行二次多項式曲線擬合,得到二次曲線f(x) = p1*x^2 + p2*x + p3;
為什么是二次?1.對應關系呈現出拋物線形狀;2.更高次曲線並沒有明顯改善擬合性能,且計算消耗會變高。
步驟五、任意給定輸出圖像input,根據其色彩飽和度信息,即可進行色彩增強40處理,新的飽和度信息可以表示為S'(x) = S(x) + f(x),得到增強后的色彩信息后返回RGB圖像輸出;
步驟六、分別對原圖+20,+40,+60后進行飽和度信息統計,並得到相應擬合參數,設置為色彩增強的低、中、高三擋,在實際處理過程中,根據輸入圖像input自身色彩飽和度信息(均值)自適應選取相應參數進行色彩增強;
步驟七、按需對某一單獨顏色通道進行色彩增強處理,例如綠色范圍為105°-135°,在對該范圍進行增強的同時,還需對75°-105°,135°-165°進行一半強度的增強,這樣才會保證色彩的連續性,不會出現色斑;
步驟八、按需對色彩(Hue)進行轉換;
代碼部分:第一部分用作估計擬合參數,在Curve fitting tool里面對X,Y進行擬合,得到曲線參數。
- % Color Enhancement
- clc,clear,close all
- src1 = imread('src.bmp');
- src2 = imread('src_40.bmp');
- src1_hsv = rgb2hsv(src1);
- src2_hsv = rgb2hsv(src2);
- h1 = src1_hsv(:,:,1);
- s1 = src1_hsv(:,:,2);
- v1 = src1_hsv(:,:,3);
- h2 = src2_hsv(:,:,1);
- s2 = src2_hsv(:,:,2);
- v2 = src2_hsv(:,:,3);
- %
- meanS1 = mean(s1(:));
- varS1 = std2(s1);
- %
- meanS2 = mean(s2(:));
- varS2 = std2(s2);
- %
- deltaS = s2 - s1;
- deltaV = v2 - v1;
- %% test1 : 觀測“原飽和度-飽和度調整增量”的關系 saturation and delta saturation
- figure;
- oriS = zeros(101,2);
- s3 = s1;
- j = 1;
- for i = 0: 0.01 : 1
- oriS(j,1) = i + 0.01;
- oriS(j,2) = mean(deltaS(find(s1 > i & s1< i + 0.01)));
- j = j + 1;
- end
- X = oriS(:,1);
- Y = oriS(:,2);
- XX = oriS(:,1) * 255;
- YY = oriS(:,2) * 255;
- plot(XX,YY)
% Color Enhancement clc,clear,close all src1 = imread('src.bmp'); src2 = imread('src_40.bmp'); src1_hsv = rgb2hsv(src1); src2_hsv = rgb2hsv(src2); h1 = src1_hsv(:,:,1); s1 = src1_hsv(:,:,2); v1 = src1_hsv(:,:,3); h2 = src2_hsv(:,:,1); s2 = src2_hsv(:,:,2); v2 = src2_hsv(:,:,3); % meanS1 = mean(s1(:)); varS1 = std2(s1); % meanS2 = mean(s2(:)); varS2 = std2(s2); % deltaS = s2 - s1; deltaV = v2 - v1; %% test1 : 觀測“原飽和度-飽和度調整增量”的關系 saturation and delta saturation figure; oriS = zeros(101,2); s3 = s1; j = 1; for i = 0: 0.01 : 1 oriS(j,1) = i + 0.01; oriS(j,2) = mean(deltaS(find(s1 > i & s1< i + 0.01))); j = j + 1; end X = oriS(:,1); Y = oriS(:,2); XX = oriS(:,1) * 255; YY = oriS(:,2) * 255; plot(XX,YY)
第二部分,對輸入圖像進行高、中、低三級自適應增強處理
- %% Color Enhancement Module -- Authored by HuangDao,08/17/2015
- % functions: input a image of type BMP or PNG, the program will decide to
- % do the Color Enhancement choice for you.There are four types of Enhanced
- % intensity - 20,40,60,80.The larger number stands for stronger
- % enhancement.
- % And we can also choose the simple color channel(eg.R,G,B) to do the
- % enhancement.There are also four different types of enhanced intensity.
- %
- % parameters table
- % ------------------------------------------------------------------------
- % | Enhanced | MATLAB params | OpenCV params |
- % | intensity |p1 p2 p3 | p1 p2 p3 |
- % | 20 |-0.1661 0.2639 -0.003626 |-0.0006512 0.2639 -0.9246|
- % | 40 |-0.4025 0.6238 -0.0005937 |0.001578 0.6238 -0.1514|
- % | 60 |1.332 1.473 -0.01155 |-0.005222 1.473 -2.946 |
- % | 80 |-4.813 3.459 -0.004568 |-0.01887 3.459 -1.165 |
- % ------------------------------------------------------------------------
- clc; clear ;close all
- % 載入文件夾
- pathName = '.\';
- fileType = '*.bmp';
- files = dir([pathName fileType]);
- len = length(files);
- for pic = 5%1:1:len
- srcName = files(pic).name;
- srcImg = imread(srcName);
- srcHSV = rgb2hsv(srcImg);
- srcH = srcHSV(:,:,1);
- srcS = srcHSV(:,:,2);
- srcV = srcHSV(:,:,3);
- meanS = mean(srcS(:));
- varS = std2(srcS);
- %圖像整體進行色彩增強處理
- if (meanS >= 0.5)
- p1 = 0;p2 = 0;p3 = 0;
- else if (meanS >= 0.35 && meanS < 0.5)
- p1 = -0.1661;p2 = 0.2639;p3 = -0.003626;
- else if (meanS >=0.2 && meanS <0.35)
- p1 = -0.4025;p2 = 0.6238;p3 = -0.0005937;
- else
- p1 = 1.332;p2 = 1.473;p3 = -0.01155;
- end
- end
- end
- dstS = srcS + p1*srcS.*srcS + p2*srcS + p3 ;
- dstHSV = srcHSV;
- dstHSV(:,:,2) = dstS;
- dstImg = hsv2rgb(dstHSV);
- figure;imshow(srcImg);
- figure;imshow(dstImg);
- %指定R,G,B通道進行色彩增強處理,紅色范圍([225-255]),綠色范圍(75-[105-135]-165),藍色范圍([-15-15])
- p11 = -0.4025;p21 = 0.6238;p31 = -0.0005937;%周邊雜色調整系數,40
- p12 = 1.332; p22 = 1.473; p32 = -0.01155; %純色區域調整系數,60
- compHue = srcH;
- GcompS = dstS;
- RcompS = dstS;
- BcompS = dstS;
- channel = 'B';
- switch channel
- case 'G'
- I1 = find(compHue > 0.2083 & compHue <0.2917);
- GcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31;
- I2 = find(compHue >= 0.2917 & compHue <= 0.3750);
- GcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32;
- I3 = find(compHue > 0.3750 & compHue <0.4583);
- GcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31;
- compHSV = dstHSV;
- compHSV(:,:,2) = GcompS;
- dstImgG = hsv2rgb(compHSV);
- figure;imshow(dstImgG);
- case 'R'
- I1 = find(compHue > 0.875 & compHue <0.9583);
- RcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31;
- I2 = find(compHue >= 0.9583 | compHue <= 0.0417);
- RcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32;
- I3 = find(compHue > 0.0417 & compHue <0.125);
- RcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31;
- compHSV = dstHSV;
- compHSV(:,:,2) = RcompS;
- dstImgR = hsv2rgb(compHSV);
- figure;imshow(dstImgR);
- case 'B'
- I1 = find(compHue > 0.5417 & compHue <0.625);
- BcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31;
- I2 = find(compHue >= 0.625 & compHue <= 0.7083);
- BcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32;
- I3 = find(compHue > 0.7083 & compHue <0.7917);
- BcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31;
- compHSV = dstHSV;
- compHSV(:,:,2) = BcompS;
- dstImgB = hsv2rgb(compHSV);
- figure;imshow(dstImgB);
- end
- %進行R,G,B通道之間的互換
- convH = zeros(size(srcH,1),size(srcH,2)); %convert
- deltaHue = 240;
- switch deltaHue
- case 120
- disp('R -> G')
- convH = srcH + 1/3;
- convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1;
- case 240
- disp('R -> B')
- convH = srcH + 2/3;
- convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1;
- end
- convHSV = dstHSV;
- convHSV(:,:,1) = convH;
- convImg = hsv2rgb(convHSV);
- figure;imshow(convImg)
- pause();
- end
%% Color Enhancement Module -- Authored by HuangDao,08/17/2015 % functions: input a image of type BMP or PNG, the program will decide to % do the Color Enhancement choice for you.There are four types of Enhanced % intensity - 20,40,60,80.The larger number stands for stronger % enhancement. % And we can also choose the simple color channel(eg.R,G,B) to do the % enhancement.There are also four different types of enhanced intensity. % % parameters table % ------------------------------------------------------------------------ % | Enhanced | MATLAB params | OpenCV params | % | intensity |p1 p2 p3 | p1 p2 p3 | % | 20 |-0.1661 0.2639 -0.003626 |-0.0006512 0.2639 -0.9246| % | 40 |-0.4025 0.6238 -0.0005937 |0.001578 0.6238 -0.1514| % | 60 |1.332 1.473 -0.01155 |-0.005222 1.473 -2.946 | % | 80 |-4.813 3.459 -0.004568 |-0.01887 3.459 -1.165 | % ------------------------------------------------------------------------ clc; clear ;close all % 載入文件夾 pathName = '.\'; fileType = '*.bmp'; files = dir([pathName fileType]); len = length(files); for pic = 5%1:1:len srcName = files(pic).name; srcImg = imread(srcName); srcHSV = rgb2hsv(srcImg); srcH = srcHSV(:,:,1); srcS = srcHSV(:,:,2); srcV = srcHSV(:,:,3); meanS = mean(srcS(:)); varS = std2(srcS); %圖像整體進行色彩增強處理 if (meanS >= 0.5) p1 = 0;p2 = 0;p3 = 0; else if (meanS >= 0.35 && meanS < 0.5) p1 = -0.1661;p2 = 0.2639;p3 = -0.003626; else if (meanS >=0.2 && meanS <0.35) p1 = -0.4025;p2 = 0.6238;p3 = -0.0005937; else p1 = 1.332;p2 = 1.473;p3 = -0.01155; end end end dstS = srcS + p1*srcS.*srcS + p2*srcS + p3 ; dstHSV = srcHSV; dstHSV(:,:,2) = dstS; dstImg = hsv2rgb(dstHSV); figure;imshow(srcImg); figure;imshow(dstImg); %指定R,G,B通道進行色彩增強處理,紅色范圍([225-255]),綠色范圍(75-[105-135]-165),藍色范圍([-15-15]) p11 = -0.4025;p21 = 0.6238;p31 = -0.0005937;%周邊雜色調整系數,40 p12 = 1.332; p22 = 1.473; p32 = -0.01155; %純色區域調整系數,60 compHue = srcH; GcompS = dstS; RcompS = dstS; BcompS = dstS; channel = 'B'; switch channel case 'G' I1 = find(compHue > 0.2083 & compHue <0.2917); GcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31; I2 = find(compHue >= 0.2917 & compHue <= 0.3750); GcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32; I3 = find(compHue > 0.3750 & compHue <0.4583); GcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31; compHSV = dstHSV; compHSV(:,:,2) = GcompS; dstImgG = hsv2rgb(compHSV); figure;imshow(dstImgG); case 'R' I1 = find(compHue > 0.875 & compHue <0.9583); RcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31; I2 = find(compHue >= 0.9583 | compHue <= 0.0417); RcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32; I3 = find(compHue > 0.0417 & compHue <0.125); RcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31; compHSV = dstHSV; compHSV(:,:,2) = RcompS; dstImgR = hsv2rgb(compHSV); figure;imshow(dstImgR); case 'B' I1 = find(compHue > 0.5417 & compHue <0.625); BcompS(I1) = dstS(I1) + dstS(I1).*dstS(I1)*p11 + dstS(I1)*p21 + p31; I2 = find(compHue >= 0.625 & compHue <= 0.7083); BcompS(I2) = dstS(I2) + dstS(I2).*dstS(I2)*p12 + dstS(I2)*p22 + p32; I3 = find(compHue > 0.7083 & compHue <0.7917); BcompS(I3) = dstS(I3) + dstS(I3).*dstS(I3)*p11 + dstS(I3)*p21 + p31; compHSV = dstHSV; compHSV(:,:,2) = BcompS; dstImgB = hsv2rgb(compHSV); figure;imshow(dstImgB); end %進行R,G,B通道之間的互換 convH = zeros(size(srcH,1),size(srcH,2)); %convert deltaHue = 240; switch deltaHue case 120 disp('R -> G') convH = srcH + 1/3; convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1; case 240 disp('R -> B') convH = srcH + 2/3; convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1; end convHSV = dstHSV; convHSV(:,:,1) = convH; convImg = hsv2rgb(convHSV); figure;imshow(convImg) pause(); end
添加OpenCV代碼段:
- Mat srcHSV,sat,satAdj,dstMerge,dst; //sat - saturation飽和度分量
- Mat imageAwb = imread("m_ImageAwb.bmp");
- vector<Mat> channels,channels1;
- double p1,p2,p3;
- cvtColor(imageAwb,srcHSV,CV_BGR2HSV);
- split(srcHSV,channels);
- split(srcHSV,channels1);
- sat = channels.at(1);
- Scalar m = mean(sat);
- if (m(0) <= 51.5)
- {p1 = -0.002714 , p2 = 0.9498, p3 = -0.5073; AfxMessageBox("High Color Enhancement!"); }//高
- else if (m(0) > 38.5 && m(0) <= 89.5)
- {p1 = -0.001578 , p2 = 0.6238, p3 = -0.1514;AfxMessageBox("Middle Color Enhancement!"); }//中
- else if (m(0) > 89.5 && m(0) <=127.5)
- {p1 = -0.0006512, p2 = 0.2639, p3 = -0.9246;AfxMessageBox("Low Color Enhancement!");}//低
- else
- {p1 = 0,p2 = 0,p3 =0;AfxMessageBox("No Color Enhancement!");}
- satAdj = sat;
- for (int i = 0 ; i < sat.rows;i ++)
- {
- for (int j = 0;j < sat.cols;j ++)
- {
- uchar val = sat.at<uchar>(i,j);
- satAdj.at<uchar>(i,j) = (val + p1 * val * val + p2 * val + p3) ;
- }
- }
- channels1.at(1) = satAdj;
- merge(channels1,dstMerge);
- cvtColor(dstMerge,dst,CV_HSV2BGR);
- imwrite("m_ImageCE.bmp",dst);
Mat srcHSV,sat,satAdj,dstMerge,dst; //sat - saturation飽和度分量 Mat imageAwb = imread("m_ImageAwb.bmp"); vector<Mat> channels,channels1; double p1,p2,p3; cvtColor(imageAwb,srcHSV,CV_BGR2HSV); split(srcHSV,channels); split(srcHSV,channels1); sat = channels.at(1); Scalar m = mean(sat); if (m(0) <= 51.5) {p1 = -0.002714 , p2 = 0.9498, p3 = -0.5073; AfxMessageBox("High Color Enhancement!"); }//高 else if (m(0) > 38.5 && m(0) <= 89.5) {p1 = -0.001578 , p2 = 0.6238, p3 = -0.1514;AfxMessageBox("Middle Color Enhancement!"); }//中 else if (m(0) > 89.5 && m(0) <=127.5) {p1 = -0.0006512, p2 = 0.2639, p3 = -0.9246;AfxMessageBox("Low Color Enhancement!");}//低 else {p1 = 0,p2 = 0,p3 =0;AfxMessageBox("No Color Enhancement!");} satAdj = sat; for (int i = 0 ; i < sat.rows;i ++) { for (int j = 0;j < sat.cols;j ++) { uchar val = sat.at<uchar>(i,j); satAdj.at<uchar>(i,j) = (val + p1 * val * val + p2 * val + p3) ; } } channels1.at(1) = satAdj; merge(channels1,dstMerge); cvtColor(dstMerge,dst,CV_HSV2BGR); imwrite("m_ImageCE.bmp",dst);
最后給出算法效果圖:
Group1.原圖->增強后
Group2.原圖->R通道增強->顏色通道改變R2B
Group3.原圖->增強后->顏色通道改變R2B
完!下篇講Local Tone Mapping。