影象濾鏡研究——基礎概念
最近寫自己的個人專案,是用OpenGL去實現一個拍視訊的應用,可以在寫濾鏡這一塊,遇到了麻煩,對於影象方面的知識不足,導致自己理解不了那些濾鏡的編寫,現在先補充一下基本知識。
影象中基本概念:色調,色相,飽和度,對比度,亮度
對比度:
對比度值不同顏色之間的差別。對比度越大,不同顏色之間的反差越大,即所謂黑白分明,對比度過大,影象就會顯得很刺眼。對比度越小,不同顏色之間的反差就越小。
亮度:
亮度指照射在景物或影象上光線的明暗程度。影象亮度增加時,就會顯得耀眼或刺眼。亮度越小時,影象就會顯得灰暗。
色調:
色調是各種影象色彩模式下原色的明暗程度,級別範圍從0到255,共256級色調。例如灰度影象,當色調級別為255時,就是白色,當級別為0時,就是黑色,中間是各種程度不同的灰色。在RGB模式中,色調代表紅,綠,藍三種原色的明暗程度,對綠色就有淡綠,深綠,深綠等不同的色調。
色調是指色彩外觀基本傾向。在明度,純度,色相這三個要素中,某種因素起主導作用,可以稱為某種色調。
色相:
色相就是顏色,調整色相就是調整景物的顏色,例如,彩虹由紅、橙、黃、綠、青、藍、紫七色組成,那麼它就有七種色相。顧名思義即各類色彩的相貌稱謂,如大紅,普藍等。色相是色彩的首要特徵,是區別不同色彩的最準確的標準,事實上任何黑白灰以外的顏色都有色相的屬性,而色相也就是由原色(三原色),間色(由三原色調配出來的顏色)和複色(複色是用原色與間色相調或用間色與間色相調而成的“三次色”)來構成的。
飽和度:
飽和度是指影象顏色的濃度。飽和度越高,顏色越飽滿,即所謂的青翠欲滴的感覺。飽和度越低,顏色就會顯得越懷舊,慘淡。飽和度越0時,影象就為灰度影象。
在影象處理中,常見的顏色模型包括HSB(色相、飽和度、亮度)、RGB(紅色、綠色、藍色)、CMYK(青色、品紅、黃色、黑色)和CIE La
色相或者色調(Hue)是從物體反射或透過物體傳播的顏色。在0°到360°的標準色輪上,按位置度量色相。通常情況下,色相由顏色名稱標識,如紅色、橙色或綠色。
亮度(Brightness或者intensity)是顏色的相對明暗程度,通常使用從0%(黑色)至100%(白色)的百分比來度量
影象的色調通常是指影象的整體明暗度,例如,如果影象亮部畫素較多的話,則影象整體上看起來較為明快。反之,如果影象中暗部畫素較多的話,則影象整體上看起來較為昏暗。對於彩色影象而言,影象具有多個色調。通過調整不同顏色通道的色調,可對影象進行細微的調整。
在影象處理的各種顏色模型中,HSB模型以人類對顏色的感覺為基礎,描述了顏色的3種基本特性。
下面是我用Android中的ColorMatrix做的:
- 把紅色的飽和度增加了50:
程式碼如下:
ColorMatrix matrix = new ColorMatrix();
Bitmap bitmap =mBitmap.copy(Bitmap.Config.ARGB_8888,true);
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);
matrix.set(new float[]{
1.0f,0.0f,0.0f,0,50,
0.0f,1.0f,0.0f,0,0,
0.0f,0.0f,1.0f,0,0,
0,0,0,1,0
});
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
canvas.drawBitmap(bitmap,0,0,paint);
mImage.setImageBitmap(bitmap);
-
把RGB的飽和度都增加了50:
ColorMatrix matrix = new ColorMatrix();
Bitmap bitmap =mBitmap.copy(Bitmap.Config.ARGB_8888,true);
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);
matrix.set(new float[]{
1.0f,0.0f,0.0f,0,50,
0.0f,1.0f,0.0f,0,50,
0.0f,0.0f,1.0f,0,50,
0,0,0,1,0
});
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
canvas.drawBitmap(bitmap,0,0,paint);
mImage.setImageBitmap(bitmap);
- 懷舊效果:
ColorMatrix matrix = new ColorMatrix();
Bitmap bitmap =mBitmap.copy(Bitmap.Config.ARGB_8888,true);
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);
matrix.set(new float[]{
0.393f,0.769f,0.189f,0,0,
0.349f,0.686f,0.168f,0,0,
0.272f,0.534f,0.131f,0,0,
0,0,0,1,0
});
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
canvas.drawBitmap(bitmap,0,0,paint);
mImage.setImageBitmap(bitmap);
其實就是降低飽和度
- 浮雕效果:
浮雕的演算法就是這一個畫素點rgb減去上一個畫素點的rgb
Bitmap bitmap =mBitmap.copy(Bitmap.Config.ARGB_8888,true);
int[] newP = new int[bitmap.getWidth()*bitmap.getHeight()];
int[] old = new int[bitmap.getWidth()*bitmap.getHeight()];
bitmap.getPixels(old,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());
for(int i = 1;i<old.length;i++){
int oldcolor = old[i-1];
int r0 = Color.red(oldcolor);
int g0 = Color.green(oldcolor);
int b0 = Color.blue(oldcolor);
int a0 = Color.alpha(oldcolor);
int color = old[i];
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
int a = Color.alpha(color);
int r1 = r-r0+128;
if(r1<0){
r1 = 0;
}else if(r1>255){
r1 = 255;
}
int g1 = g-g0+128;
if(g1<0){
g1 = 0;
}else if(g1>255){
g1 = 255;
}
int b1 = b-b0+128;
if(b1<0){
b1 = 0;
}else if(b1>255){
b1 = 255;
}
newP[i] = Color.argb(a,r1,g1,b1);
}
// paint.setColorFilter(new ColorMatrixColorFilter(matrix));
// canvas.drawBitmap(bitmap,0,0,paint);
bitmap.setPixels(newP,0,bitmap.getWidth(),0,0,
bitmap.getWidth(),bitmap.getHeight());
mImage.setImageBitmap(bitmap);
- 黑白
ColorMatrix matrix = new ColorMatrix();
Bitmap bitmap =mBitmap.copy(Bitmap.Config.ARGB_8888,true);
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);
matrix.set(new float[]{
0.213f,0.715f,0.072f,0,0,
0.213f,0.715f,0.072f,0,0,
0.213f,0.715f,0.072f,0,0,
0,0,0,1,0
});
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
canvas.drawBitmap(bitmap,0,0,paint);
mImage.setImageBitmap(bitmap);
黑白的濾鏡,主要是灰度圖片的去色原理:只要把RGB的三色通道的數值設定為一樣,即R=G=B,那麼影象就變成了灰色,同時為了保證影象的亮度,需要使同一個通道中的R+G+B的結果接近1
關於colorMatrix可以參考:https://blog.csdn.net/harvic880925/article/details/51187277
圖層混合模式
PS中,混合圖層是製作濾鏡的必需品。
1.正常(Normal)模式:
在“正常模式下”,“混合色”的顯示與不透明度的設定有關。當“不透明度”為100%,“結果色”的畫素將完全由“混合色”代替;當不透明度小於100%時,混合色的畫素會透過所用的顏色顯示出來,顯示的程度取決於不透明度的設定與“基色”的顏色。如果在處理“點陣圖”顏色模式影象或“索引顏色”顏色模式影象時,正常模式就改稱為閥值模式了,不過功能時一樣的。
混合色*不透明度+(100%-混合色不透明度)*基色
2.溶解模式(Dissolve)
溶解模式下混合色的不透明度及填充都是100%的話,我們就看不到基色圖層。降低混合色圖層的不透明度後,我們就會發送結果色中出現了很多細小的顆粒。這些顆粒會隨著混合色的不透明度變化。不透明度越低,混合色圖層就被溶解的越多。剩下的部分就越少。不透明度越高,混合色圖層被溶解的部分就越少,剩下的部分就越多,結果色也就越接近混合色。
3.變暗模式
變暗混合模式下,會把混合色和基色進行對比,分別選擇R,G,B三組數值中最小的數值,也就是最暗的顏色作為結果色的數值。這樣整個畫面就會變暗,如果是彩色影象,顏色也會發生很大的改變。
4.正片疊底:
按照混合色與基色中的各R,G,B值計算,計算公式:結果色R=混合色R * 基色R / 255,G值與B值相同。由於各通道的最大值是255,因此結果色的數值比混合色即基色的數值都要小,也就是結果色要暗。
5.顏色加深
顏色加深可以快速增加圖片的暗部。計算公式:(基色 + 混合色 - 255)* 255 /混合色,如果(基色 + 混合色 - 255)出現負數,就直接歸0.因此在基色和混合色都較暗時就直接變成黑色了。這樣結果色的暗部就會增加。整體效果看上去對比較為強烈。
6.線性加深:
線性加深的計算公式是:結果色 =基色 +混合色 - 255,如果基色 +混合色的數值小於255,結果色就為0。由這個公式可以看出,畫面暗部會直接變成黑色。因此畫面整體會更暗。白色與基色混合得到基色,黑色與基色混合得到黑色。
7.深色模式:
它是通過計算混合色與基色的所有通道的數值,然後選擇數值較小的作為結果色。因此結果色只跟混合色或基色相同,不會產生出另外的顏色。白色與基色混合色得到基色,黑色與基色混合得到黑色。深色模式中,混合色與基色的數值是固定的,我們顛倒位置後,混合色出來的結果色是沒有變化的。
8.變涼模式:
變亮混合模式跟變暗模式是相對的,通過混合色與基色的相關數值進行比較,選擇較大的數值作為結果色。因此結果色會更亮,同時顏色也會變化。
9.濾色模式:
濾色模式與正片疊底模式相對。她的計算公式是用:255 -混合色的補色* 基色補色 / 255。得到的資料會比混合及基色更大,因此結果色會更亮。從計算公式也可以看出基色或混合色任何一項為255也就是白色,結果色數值就是255為白色。任何一項數值為0,也就是為黑色的話,結果色就跟數值不為0的一致。
10.顏色減淡:
顏色減淡是通過混合色及基色的各通道顏色值進行對比,減少二者的對比度使基色的變亮來反映混合色。
她的計算公式:結果色 = 基色 + (混合色 * 基色) / (255 - 混合色)。混合色為黑色,結果色就等於基色,混合色為白色結果色就為白色。基色為黑色結果色就為黑色。
11. 柔光模式:
柔光模式是較為常用的模式,她是根據混合色的通道數值選擇不同的公式計算混合色。數值大於128的時候,結果色就比基色稍亮;數值小於或等於128,結果色就比基色稍暗。柔光模式是以基色為主導,混合色只相應改變區域性明暗。其中混合色為黑色,結果色不會為黑色,只比結果色稍暗,混合色為中性色,結果色跟基色一樣。
計算公式:
混合色 <=128:結果色 =基色 + (2 混合色 - 255) * (基色 -基色基色 / 255) / 255;
混合色 >128:結果色= 基色 + (2 *混合色 - 255) * (Sqrt(基色/255)*255-基色)/255。
更多的模式參考:https://blog.csdn.net/trent1985/article/details/40891661