日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

八叉树 java_java简单实现八叉树图像处理代码示例

發(fā)布時(shí)間:2025/3/19 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 八叉树 java_java简单实现八叉树图像处理代码示例 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一晃工作有段時(shí)間了,第一次寫博客,有點(diǎn)不知道怎么寫,大家將就著看吧,說(shuō)的有什么不正確的也請(qǐng)大家指正。

最近工作中用到了一個(gè)圖像壓縮的功能。找了一些工具,沒有太好的選擇。最后選了一個(gè)叫jdeli的,奈何效率又成了問題。我迫于無(wú)奈就只能研究了下它的源碼,卻發(fā)現(xiàn)自己對(duì)它的一個(gè)減色量化算法起了興趣,可是尷尬的自己完全不明白它寫的什么,就起了一個(gè)自己實(shí)現(xiàn)一個(gè)量化顏色算法的念頭。

自己找了一些資料,找到三個(gè)比較常用的顏色處理算法:

流行色算法:

具體的算法就是,先對(duì)一個(gè)圖像的所有顏色出現(xiàn)的次數(shù)進(jìn)行統(tǒng)計(jì),選舉出出現(xiàn)次數(shù)最多的256個(gè)顏色作為圖片的調(diào)色板的顏色,然后再次遍歷圖片的所有像素,對(duì)每個(gè)像素找出調(diào)色板中的最接近的顏色(這里我用的是方差的方式),寫回到圖片中。這個(gè)算法的實(shí)現(xiàn)比較簡(jiǎn)單,但是失真比較嚴(yán)重,圖像中一些出現(xiàn)頻率較低,但對(duì)人眼的視覺效挺明顯的信息將丟失。比如,圖像中存在的高亮度斑點(diǎn),由于出現(xiàn)的次數(shù)少,很可能不能被算法選中,將被丟失。

中位切分算法:

這個(gè)算法我沒有研究,想要了解的同學(xué),可以看下,里面有三種算法的介紹。

八叉樹

這個(gè)算法就是我最后選用的算法,它的主要思想就是把圖像的rgb顏色值轉(zhuǎn)成二進(jìn)制分布到八叉樹中,例如:(173,234,144)

轉(zhuǎn)成二進(jìn)制就是(10101101,11101010,10010000),將r,g,b的第一位取出來(lái)組成(111),作為root節(jié)點(diǎn)的子節(jié)點(diǎn),其中111作為root子節(jié)點(diǎn)數(shù)組的索引,以此類推,一直到最后一位,然后在葉子節(jié)點(diǎn)上存放這個(gè)顏色的分量值以及其出現(xiàn)的次數(shù)。具體看圖。

其中我比較疑惑的有一個(gè)處理就是葉子節(jié)點(diǎn)的合并策略,這兒我用的最笨的一個(gè)方法,就是找到層次最深的節(jié)點(diǎn),然后合并,有點(diǎn)簡(jiǎn)單粗暴,有別的比較好的方法,也請(qǐng)大家給我留言。圖片太大上傳不了了,直接上代碼了,代碼沒有重構(gòu),大家湊合看吧。

package com.gys.pngquant.octree;

import java.util.arraylist;

import java.util.hashmap;

import java.util.list;

import java.util.map;

/**

*

*

* @classname 類名:node

* @description 功能說(shuō)明:

*

* 八叉樹實(shí)現(xiàn)

*

*

* 2015-12-16 guoys 創(chuàng)建該類功能。

*

**********************************************************

*

*/

public class node{

private int depth = 0;

// 為0時(shí)為root節(jié)點(diǎn)

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的關(guān)系

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;

}

// 返回節(jié)點(diǎn)原有的子節(jié)點(diǎn)數(shù)量

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;

}

// 獲取葉子節(jié)點(diǎn)的數(shù)量

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);

}

}

}

}

可憐我大學(xué)唯二掛的數(shù)據(jù)結(jié)構(gòu)。代碼實(shí)現(xiàn)的只是八叉樹,對(duì)一個(gè)1920*1080圖片量化,耗時(shí)大概是450ms,如果層次-2的話大概是100ms左右。

好吧,這篇就這樣吧,本來(lái)寫之前,感覺自己想說(shuō)的挺多的,結(jié)果寫的時(shí)候就不知道怎么說(shuō)了,大家見諒。

總結(jié)

以上就是本文關(guān)于java簡(jiǎn)單實(shí)現(xiàn)八叉樹圖像處理代碼示例的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

希望與廣大網(wǎng)友互動(dòng)??

點(diǎn)此進(jìn)行留言吧!

總結(jié)

以上是生活随笔為你收集整理的八叉树 java_java简单实现八叉树图像处理代码示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。