知道術語的英文翻譯很重要,因為百度高質量的博文和文章比谷歌搜索到的要少。
對於灰度圖而言,一個像素點由8個比特組成。代替突出灰度級范圍,我們可以突出特定比特來為整個圖像外觀作出貢獻(理解這一點很重要)一副8比特灰度圖可考慮分層1到8個比特平面。很容易理解的是,4個高階比特平面,特別是最后兩個比特平面,包含了在視覺上很重要的大多數數據。而低階比特平面則在圖像上貢獻了更精細的灰度細節。
比特平面分層最重要的是它的分層算法,算法依據就是上段的黑體字,突出該層的比特,如何突出則是每一層分層算法需要考慮的。開始看這一章節內容的時候,沒有關注到比特平面分層的作用是什么,以為只是簡單的把每一層的比特提取出來建立比特平面圖。所以有了下面的算法:
//下面的color都是爭對灰度而言的
private int bitLevel(int color, int level) { int color_lev1 = color & 1; //00000001 int color_lev2 = color & 0x2; //00000010 int color_lev3 = color & 0x4; //00000100 int color_lev4 = color & 0x8; //00001000 int color_lev5 = color & 0x10;//00010000 int color_lev6 = color & 0x20;//00100000 int color_lev7 = color & 0x40;//01000000 int color_lev8 = color & 0x80;//10000000 int color_lev;// = color & 0x80; color_lev = color & (1 << level)//level取值為0到7 return (255 << 24) + (color_lev << 16) + (color_lev << 8) + color_lev; }
這個算法的作用就是簡單的提取每一層的比特,但我忽略了“突出該層比特”的要義。實際結果也證明是錯誤的,例如第一層,值不是0就是1,這樣的色值顯示出來就是純黑,根本顯現不了第一層比特的貢獻。突出分層的最好做法就是二值化,因為每個像素點每層比特的值只有1(有貢獻)和0(無貢獻),我們要做的就是突出1值。真正的分層算法如下:
第一層:
第一層位置上的值只能是0和1,所以值為0時,可令其轉換值為255
private int bitLevelOne(int color){ int gray = color >> 8 & 0xFF; int color_lev; if(gray == 1)color_lev = 255; else color_lev = 0; return (255 << 24) + (color_lev << 16) + (color_lev << 8) + color_lev; }
(實驗是以《數字圖像處理》書中提供的樣圖作處理的,該圖本身就是8比特的灰度圖,傳給函數的參數值是argb像素點值,該值a=r=g=b,所以取出右邊的8位即得到它的灰度圖,同樣為了“突出”考慮,alpha通道取255)
原圖:(500x1192像素的灰度圖)
第一層平面圖:
其它層級的分層算法如上依次類推,如果該層級的比特值為1,則二值化為255,如果為0,則二值化為0。比如第六層分層算法如下
private int bitLevelSixth(int color) { int gray = color >> 8 & 0xFF; int color_lev6 = gray & 0x20;// 00100000 int color_lev; if (color_lev6 == 0x20) color_lev = 255; else color_lev = 0; return (255 << 24) + (color_lev << 16) + (color_lev << 8) + color_lev; }
注意:上述算法涉及到各種移位等操作,實際結果效率比較低,這里暫不考慮這一點,只說明實際的比特平面分層算法的原理。
第6,7,8層結果如下:
比特平面分層的另一個應用是在圖像壓縮中,從上面的分層圖結果來看,我們只需要使用高階的幾層便能重建原圖,這也就意味着可以使用比原來更少的比特層來構建原圖(比如4層,這樣就減少了50%的存儲量)。
使用6,7,8三個平面重建的算法和結果如下:
private int combine678(int color){ int gray = color >> 8 & 0xFF; int colors = gray & 0xE0;//11100000 return (255 << 24) + (colors << 16) + (colors << 8) + colors; }