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

article/2025/10/28 23:30:31

一晃工作有段时间了,第一次写博客,有点不知道怎么写,大家将就着看吧,说的有什么不正确的也请大家指正。

最近工作中用到了一个图像压缩的功能。找了一些工具,没有太好的选择。最后选了一个叫jdeli的,奈何效率又成了问题。我迫于无奈就只能研究了下它的源码,却发现自己对它的一个减色量化算法起了兴趣,可是尴尬的自己完全不明白它写的什么,就起了一个自己实现一个量化颜色算法的念头。

自己找了一些资料,找到三个比较常用的颜色处理算法:

流行色算法:

具体的算法就是,先对一个图像的所有颜色出现的次数进行统计,选举出出现次数最多的256个颜色作为图片的调色板的颜色,然后再次遍历图片的所有像素,对每个像素找出调色板中的最接近的颜色(这里我用的是方差的方式),写回到图片中。这个算法的实现比较简单,但是失真比较严重,图像中一些出现频率较低,但对人眼的视觉效挺明显的信息将丢失。比如,图像中存在的高亮度斑点,由于出现的次数少,很可能不能被算法选中,将被丢失。

中位切分算法:

这个算法我没有研究,想要了解的同学,可以看下,里面有三种算法的介绍。

八叉树

这个算法就是我最后选用的算法,它的主要思想就是把图像的rgb颜色值转成二进制分布到八叉树中,例如:(173,234,144)

转成二进制就是(10101101,11101010,10010000),将r,g,b的第一位取出来组成(111),作为root节点的子节点,其中111作为root子节点数组的索引,以此类推,一直到最后一位,然后在叶子节点上存放这个颜色的分量值以及其出现的次数。具体看图。

57cd0cfddaf05d61f9d3ff73e487985e.png

其中我比较疑惑的有一个处理就是叶子节点的合并策略,这儿我用的最笨的一个方法,就是找到层次最深的节点,然后合并,有点简单粗暴,有别的比较好的方法,也请大家给我留言。图片太大上传不了了,直接上代码了,代码没有重构,大家凑合看吧。

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简单实现八叉树图像处理代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

希望与广大网友互动??

点此进行留言吧!


http://chatgpt.dhexx.cn/article/tEMmynUl.shtml

相关文章

八叉树

http://hi.baidu.com/onlywater/blog/item/905c5e162ed18f4021a4e9c1.html 一、八叉树基本原理&#xff1a; 用八叉树来表示三维形体&#xff0c;并研究这种表示下的各种操作以及应用&#xff0c;是进入80年代后开展起来的。这种方法&#xff0c;既可以看成是四叉树方法在三维…

Octree(八叉树)

1. 算法原理 八叉树&#xff08;Octree&#xff09;是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素&#xff0c;每个节点有八个子节点&#xff0c;将八个子节点所表示的体积元素加在一起就等于父节点的体积。八叉树是四叉树在三维空间上的扩…

【PCL自学:ocTree】八叉树(octree)的原理及应用案例(点云压缩,搜索,空间变化)

PCL中八叉树&#xff08;octree&#xff09;的原理及应用案例 一、什么是八叉树ocTree&#xff1f;1.八叉树原理 二、八叉树应用案例1.点云压缩2.用八叉树进行空间划分和搜索操作3.无序点云数据的空间变化检测 一、什么是八叉树ocTree&#xff1f; 1.八叉树原理 上世纪80年代&…

十进制小数化为二进制小数的方法是什么_十进制转成二进制的两种方式

第一种&#xff1a;用2整除的方式。 用2整除十进制整数&#xff0c;得到一个商和余数&#xff1b;再用2去除商&#xff0c;又会得到一个商和余数&#xff0c;如此重复&#xff0c;直到商为小于1时为止&#xff0c;然后把先得到余数作为二进制数的低位有效位&#xff0c;后得到的…

Python 利用内置函数把二进制小数转换为十进制

如果需要把一个二进制整数转换为十进制整数&#xff0c;只需要简单的一行&#xff1a; int(1101,2) 但如果有一个二进制小数的话&#xff0c;就需要自己实现一个函数了。 不过&#xff0c;许多人是这样写的&#xff1a;(图片取自这里) 可是&#xff0c;由于python本身并不适…

[学习笔记] 二进制小数表示方法

文章目录 科学计数法二进制推广计算机中的小数EXCESS表示系统特殊情况举例&#xff08;float&#xff09;普通情况最大正实数普通情况最小负实数普通情况最小正实数特殊情况最大正实数 科学计数法 科学计数法想必大家都很熟悉了&#xff0c;往往通过如下形式表示一个实数&…

十进制小数化为二进制小数的方法是什么_二进制的转换

二进制是在计算机中常用的一种进制数&#xff0c;其数据用0和1两个数码来表示数据。我们人类常用的是十进制&#xff0c;那么二进制和十进制之间是有一个转换方法的。 二进制转换十进制 一个二进制数转换为十进制数&#xff0c;是比较简单的&#xff0c;其方法就是用每一个位置…

二进制小数的意义

回忆小学学的十进制小数的意义&#xff1a; 15.23这个小数&#xff0c;1是十位&#xff0c;5是个位&#xff0c;2是十分位&#xff0c;3是百分位。这个小数的意义为&#xff1a;&#xff0c;因为最低位为百分位&#xff0c;所以分母是100。 小数末尾加上0或去掉0&#xff0c;小…

浮点数(小数)在计算机中如何用二进制存储?

浮点数在计算机中如何用二进制存储&#xff1f; 前言 前面我有篇博文详解了二进制数&#xff0c;以及如何同二进制数表示整数。但是&#xff0c;计算机处理的不仅仅是整数&#xff0c;还有小数&#xff0c;同样小数在计算机也是用二进制进行存储的&#xff0c;但是&#xff0…

二进制小数的表示

二级制小数分为两大类&#xff1a;1、定点数&#xff1b;2、浮点数。 定点数 定点数&#xff1a; &#xff08;1&#xff09;小数点位置固定不变的数。 &#xff08;2&#xff09;定点数有定点整数和定点小数。 &#xff08;定点整数&#xff1a;小数部分为0&#xff1b;定点…

腾讯TDSQL全时态数据库系统论文入选VLDB

当地时间2019年8月26至30日&#xff0c;VLDB 2019会议在美国加利福尼亚召开&#xff0c;腾讯分布式数据库TDSQL与中国人民大学最新联合研究成果被VLDB 2019接收并将通过长文形式发表。VLDB是国际数据管理与数据库领域顶尖的学术会议之一&#xff0c;这是继去年腾讯TDSQL相似度计…

顶会VLDB‘22论文解读:CAE-ENSEMBLE算法

摘要&#xff1a;针对时间序列离群点检测问题&#xff0c;提出了基于CNN-AutoEncoder和集成学习的CAE-ENSEMBLE深度神经网络算法&#xff0c;并通过大量的实验证明CAE-ENSEMBLE算法能有效提高时间序列离群点检测的准确度与效率。 本文分享自华为云社区《VLDB22 CAE-ENSEMBLE论文…

【轨迹压缩】Trajectory Simplification: On Minimizing the Direction-based Error [2015] [VLDB]

一、一个动机 保护方向信息的方向保持轨迹简化&#xff08;DPTS&#xff09;已被证明表现良好&#xff0c;而现有关于 DPTS 的研究 要求用户指定一个容错&#xff0c;在某些情况下用户可能不知道如何正确设置&#xff08;例如&#xff0c;容错只能在未来某个时间知道&#xff…

VLDB 2021 EAB最佳论文:深度解析机器学习的基数估计为何无法实现?

©作者 | 曲昌博单位 | 西蒙菲莎大学近日&#xff0c;IEEE 数据工程新星奖王健楠团队论文《Are We Ready for Learned Cardinality Estimation?》夺得数据库顶会 VLDB 2021 年度的 EA&B 最佳论文奖。 数据库是企业管理和查询数据的复杂软件系统。 近年来随着机器学习以…

Transformers如何处理表格数据?【VLDB2022教程】Transformer表格数据表示:模型和应用...

来源&#xff1a;专知 本文为教程介绍&#xff0c;建议阅读5分钟最近的研究工作通过开发表格数据的神经表示扩展了语言模型。 在过去的几年中&#xff0c;自然语言处理界见证了基于transformer的语言模型(LM)在自由文本的神经表示方面的进展。鉴于关系表中可用知识的重要性&…

openGauss亮相VLDB2020,展示内存优化研究成果

VLDB&#xff08;Very Large Data Base&#xff09;作为数据库领域的三大顶级国际会议之一&#xff0c;是面向数据库研究人员&#xff0c;内核开发人员&#xff0c;开发商以及用户的年度国际会议论坛&#xff0c;代表数据库系统领域最杰出的研究和工程进展。在2020年&#xff0…

VLDB 2023 | 北大河图发布分布式训练神器Galvatron,一键实现大模型高效自动并行...

©作者 | 北京大学河图团队 单位 | 北京大学数据与智能实验室 北大河图团队提出了一套面向大模型的自动并行分布式训练系统 Galvatron&#xff0c;相比于现有工作在多样性、复杂性、实用性方面均具有显著优势&#xff0c;论文成果已经被 VLDB 2023 接收。 最近一段时间&…

利用 Map-Reduce 从文件中找到出现频率最高的 10 个 URL(2021 VLDB Summer School Lab0)

这篇博文主要是对 2021 VLDB Summer School Lab0 的一个总结 这个lab与MIT 6.824 的 lab1 相似&#xff0c;个人感觉比MIT 6.824 的 lab1 要稍微简单些&#xff0c;更容易上手。通过这个lab&#xff0c;可以学习到一些 Golang 的基础知识并对分布式系统有一个基础的了解&#…

Flink OLAP 助力 ByteHTAP 亮相数据库顶会 VLDB

复杂查询 QPS 破百&#xff0c;字节跳动 Flink OLAP 助力 ByteHTAP 亮相数据库顶会 VLDB。 2022 年 9 月 5 日至 9 月 9 日&#xff0c;VLDB 2022 在澳大利亚悉尼举行。字节跳动基础架构研究成果《ByteHTAP: ByteDance’s HTAP System with High Data Freshness and Strong Dat…

湖南大学计算机专业硕士研究导师,湖南大学研究生导师李睿科研论文被世界顶级数据库学术会议VLDB刊发...

李睿老师的论文被国际数据库顶级会议Very Large Data Bases接受并发表。 刊发的论文。 日前&#xff0c;以湖南大学信息科学与工程学院计算机科学系研究生导师李睿为第一作者&#xff0c;湖南大学为第一作者单位的科研论文“Fast Range Query Processing with Strong Privacy P…