八叉树 java_java简单实现八叉树图像处理代码示例
一晃工作有段時間了,第一次寫博客,有點不知道怎么寫,大家將就著看吧,說的有什么不正確的也請大家指正。
最近工作中用到了一個圖像壓縮的功能。找了一些工具,沒有太好的選擇。最后選了一個叫jdeli的,奈何效率又成了問題。我迫于無奈就只能研究了下它的源碼,卻發現自己對它的一個減色量化算法起了興趣,可是尷尬的自己完全不明白它寫的什么,就起了一個自己實現一個量化顏色算法的念頭。
自己找了一些資料,找到三個比較常用的顏色處理算法:
流行色算法:
具體的算法就是,先對一個圖像的所有顏色出現的次數進行統計,選舉出出現次數最多的256個顏色作為圖片的調色板的顏色,然后再次遍歷圖片的所有像素,對每個像素找出調色板中的最接近的顏色(這里我用的是方差的方式),寫回到圖片中。這個算法的實現比較簡單,但是失真比較嚴重,圖像中一些出現頻率較低,但對人眼的視覺效挺明顯的信息將丟失。比如,圖像中存在的高亮度斑點,由于出現的次數少,很可能不能被算法選中,將被丟失。
中位切分算法:
這個算法我沒有研究,想要了解的同學,可以看下,里面有三種算法的介紹。
八叉樹
這個算法就是我最后選用的算法,它的主要思想就是把圖像的rgb顏色值轉成二進制分布到八叉樹中,例如:(173,234,144)
轉成二進制就是(10101101,11101010,10010000),將r,g,b的第一位取出來組成(111),作為root節點的子節點,其中111作為root子節點數組的索引,以此類推,一直到最后一位,然后在葉子節點上存放這個顏色的分量值以及其出現的次數。具體看圖。
其中我比較疑惑的有一個處理就是葉子節點的合并策略,這兒我用的最笨的一個方法,就是找到層次最深的節點,然后合并,有點簡單粗暴,有別的比較好的方法,也請大家給我留言。圖片太大上傳不了了,直接上代碼了,代碼沒有重構,大家湊合看吧。
package com.gys.pngquant.octree;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
/**
*
*
* @classname 類名:node
* @description 功能說明:
*
* 八叉樹實現
*
*
* 2015-12-16 guoys 創建該類功能。
*
**********************************************************
*
*/
public class node{
private int depth = 0;
// 為0時為root節點
private node parent;
private node[] children = new node[8];
private boolean isleaf = false;
private int rnum = 0;
private int gnum = 0;
private int bnum = 0;
private int piexls = 0;
private map> levelmapping;
// 存放層次和node的關系
public int getrgbvalue(){
int r = this.rnum / this.piexls;
int g = this.gnum / this.piexls;
int b = this.bnum / this.piexls;
return (r << 16 | g << 8 | b);
}
public map> getlevelmapping() {
return levelmapping;
}
public void aftersetparam(){
if(this.getparent() == null && this.depth == 0){
levelmapping = new hashmap>();
for (int i = 1; i <= 8; i++) {
levelmapping.put(i, new arraylist());
}
}
}
public int getrnum() {
return rnum;
}
public void setrnum(int rnum) {
if(!isleaf){
throw new unsupportedoperationexception();
}
this.rnum = rnum;
}
public int getgnum() {
return gnum;
}
public void setgnum(int gnum) {
if(!isleaf){
throw new unsupportedoperationexception();
}
this.gnum = gnum;
}
public int getbnum() {
return bnum;
}
public void setbnum(int bnum) {
if(!isleaf){
throw new unsupportedoperationexception();
}
this.bnum = bnum;
}
public int getpiexls() {
return piexls;
}
public void setpiexls(int piexls) {
if(!isleaf){
throw new unsupportedoperationexception();
}
this.piexls = piexls;
}
public int getdepth() {
return depth;
}
// 返回節點原有的子節點數量
public int mergerleafnode(){
if(this.isleaf){
return 1;
}
this.setleaf(true);
int rnum = 0;
int gnum = 0;
int bnum = 0;
int pixel = 0;
int i = 0;
for (node child : this.children) {
if(child == null){
continue;
}
rnum += child.getrnum();
gnum += child.getgnum();
bnum += child.getbnum();
pixel += child.getpiexls();
i += 1;
}
this.setrnum(rnum);
this.setgnum(gnum);
this.setbnum(bnum);
this.setpiexls(pixel);
this.children = null;
return i;
}
// 獲取最深層次的node
public node getdepestnode(){
for (int i = 7; i > 0; i--) {
list levellist = this.levelmapping.get(i);
if(!levellist.isempty()){
return levellist.remove(levellist.size() - 1);
}
}
return null;
}
// 獲取葉子節點的數量
public int getleafnum(){
if(isleaf){
return 1;
}
int i = 0;
for (node child : this.children) {
if(child != null){
i += child.getleafnum();
}
}
return i;
}
public void setdepth(int depth) {
this.depth = depth;
}
public node getparent() {
return parent;
}
public void setparent(node parent) {
this.parent = parent;
}
public node[] getchildren() {
return children;
}
public node getchild(int index){
return children[index];
}
public void setchild(int index, node node){
children[index] = node;
}
public boolean isleaf() {
return isleaf;
}
public void setpixel(int r, int g, int b){
this.rnum += r;
this.gnum += g;
this.bnum += b;
this.piexls += 1;
}
public void setleaf(boolean isleaf) {
this.isleaf = isleaf;
}
public void add8bite2root(int _taget, int _speed){
if(depth != 0 || this.parent != null){
throw new unsupportedoperationexception();
}
int speed = 7 + 1 - _speed;
int r = _taget >> 16 & 0xff;
int g = _taget >> 8 & 0xff;
int b = _taget & 0xff;
node pronode = this;
for (int i=7;i>=speed;i--){
int item = ((r >> i & 1) << 2) + ((g >> i & 1) << 1) + (b >> i & 1);
node child = pronode.getchild(item);
if(child == null){
child = new node();
child.setdepth(8-i);
child.setparent(pronode);
child.aftersetparam();
this.levelmapping.get(child.getdepth()).add(child);
pronode.setchild(item, child);
}
if(i == speed){
child.setleaf(true);
}
if(child.isleaf()){
child.setpixel(r, g, b);
break;
}
pronode = child;
}
}
public static node build(int[][] matrix, int speed){
node root = new node();
root.aftersetparam();
for (int[] row : matrix) {
for (int cell : row) {
root.add8bite2root(cell, speed);
}
}
return root;
}
public static byte[] mergecolors(node root, int maxcolors){
byte[] bytearray = new byte[maxcolors * 3];
list result = new arraylist();
int leafnum = root.getleafnum();
try{
while(leafnum > maxcolors){
int mergerleafnode = root.getdepestnode().mergerleafnode();
leafnum -= (mergerleafnode - 1);
}
}
catch(exception e){
e.printstacktrace();
}
fillarray(root, result, 0);
int i = 0;
for (byte byte1 : result) {
bytearray[i++] = byte1;
}
return bytearray;
}
private static void fillarray(node node, list result, int offset){
if(node == null){
return;
}
if(node.isleaf()){
result.add((byte) (node.getrnum() / node.getpiexls()));
result.add((byte) (node.getgnum() / node.getpiexls()));
result.add((byte) (node.getbnum() / node.getpiexls()));
} else{
for (node child : node.getchildren()) {
fillarray(child, result, offset);
}
}
}
}
可憐我大學唯二掛的數據結構。代碼實現的只是八叉樹,對一個1920*1080圖片量化,耗時大概是450ms,如果層次-2的話大概是100ms左右。
好吧,這篇就這樣吧,本來寫之前,感覺自己想說的挺多的,結果寫的時候就不知道怎么說了,大家見諒。
總結
以上就是本文關于java簡單實現八叉樹圖像處理代碼示例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
希望與廣大網友互動??
點此進行留言吧!
總結
以上是生活随笔為你收集整理的八叉树 java_java简单实现八叉树图像处理代码示例的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: java图片转换成base64_Java
- 下一篇: MySQL与会计报表_会计报表的18项必
