最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java簡單實(shí)現(xiàn)八叉樹圖像處理代碼示例

 更新時(shí)間:2017年12月21日 15:02:06   作者:gys13200  
這篇文章主要介紹了java簡單實(shí)現(xiàn)八叉樹圖像處理代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。

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

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

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

流行色算法:

具體的算法就是,先對一個(gè)圖像的所有顏色出現(xiàn)的次數(shù)進(jìn)行統(tǒng)計(jì),選舉出出現(xiàn)次數(shù)最多的256個(gè)顏色作為圖片的調(diào)色板的顏色,然后再次遍歷圖片的所有像素,對每個(gè)像素找出調(diào)色板中的最接近的顏色(這里我用的是方差的方式),寫回到圖片中。這個(gè)算法的實(shí)現(xiàn)比較簡單,但是失真比較嚴(yán)重,圖像中一些出現(xiàn)頻率較低,但對人眼的視覺效挺明顯的信息將丟失。比如,圖像中存在的高亮度斑點(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的第一位取出來組成(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)簡單粗暴,有別的比較好的方法,也請大家給我留言。圖片太大上傳不了了,直接上代碼了,代碼沒有重構(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 功能說明: 
 * <p>
 *   八叉樹實(shí)現(xiàn)
 * </p>
 * 
 *  2015-12-16  guoys 創(chuàng)建該類功能。
 *
 **********************************************************
 * </p>
 */
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<Integer, List<Node>> 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<Integer, List<Node>> getLevelMapping() {
		return levelMapping;
	}
	public void afterSetParam(){
		if(this.getParent() == null && this.depth == 0){
			levelMapping = new HashMap<Integer, List<Node>>();
			for (int i = 1; i <= 8; i++) {
				levelMapping.put(i, new ArrayList<Node>());
			}
		}
	}
	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<Node> 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<byte> result = new ArrayList<byte>();
		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<byte> 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)的只是八叉樹,對一個(gè)1920*1080圖片量化,耗時(shí)大概是450ms,如果層次-2的話大概是100ms左右。

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

總結(jié)

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

相關(guān)文章

  • Java如何識別圖片或掃描PDF中的文字詳解

    Java如何識別圖片或掃描PDF中的文字詳解

    這篇文章主要介紹了Java如何識別圖片或掃描PDF中文字的相關(guān)資料,介紹了Java中使用Spire.OCRforJava庫來識別圖片和掃描PDF文件中的文字,需要的朋友可以參考下
    2025-01-01
  • 詳解SpringBoot如何讓指定的Bean先加載

    詳解SpringBoot如何讓指定的Bean先加載

    這篇文章主要給大家介紹了在 SpringBoot 中如何讓自己的某個(gè)指定的 Bean 在其他 Bean 前完成被 Spring 加載,文中通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • 微信公眾平臺(測試接口)準(zhǔn)備工作

    微信公眾平臺(測試接口)準(zhǔn)備工作

    想要微信開發(fā),首先要有個(gè)服務(wù)器,但是自己沒有。這時(shí)候可以用花生殼,將內(nèi)網(wǎng)映射到公網(wǎng)上,這樣就可以在公網(wǎng)訪問自己的網(wǎng)站了。
    2016-05-05
  • SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式

    SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式

    這篇文章主要介紹了SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 如何在mapper文件中使用in("str1","str2")

    如何在mapper文件中使用in("str1","str2")

    這篇文章主要介紹了如何在mapper文件中使用in("str1","str2"),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 詳解springMVC容器加載源碼分析

    詳解springMVC容器加載源碼分析

    這篇文章主要介紹了詳解springMVC容器加載源碼分析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java實(shí)現(xiàn)藍(lán)橋杯數(shù)獨(dú)游戲的示例代碼

    Java實(shí)現(xiàn)藍(lán)橋杯數(shù)獨(dú)游戲的示例代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)藍(lán)橋杯數(shù)獨(dú)游戲的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 解決import包時(shí)報(bào) Java 程序包不存在的問題

    解決import包時(shí)報(bào) Java 程序包不存在的問題

    你是否也有過在import包時(shí)idea報(bào)錯(cuò)說這個(gè)包不存在,可是這個(gè)包我們看得到確實(shí)存在的情況,不要慌,今天這篇文章帶你徹底告別這個(gè)問題
    2021-10-10
  • ZooKeeper開發(fā)實(shí)際應(yīng)用案例實(shí)戰(zhàn)

    ZooKeeper開發(fā)實(shí)際應(yīng)用案例實(shí)戰(zhàn)

    這篇文章主要為大家介紹了ZooKeeper開發(fā)的實(shí)際應(yīng)用案例實(shí)戰(zhàn),文中附含詳細(xì)開發(fā)應(yīng)用源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-01-01
  • Mybatis的Mapper代理對象生成及調(diào)用過程示例詳解

    Mybatis的Mapper代理對象生成及調(diào)用過程示例詳解

    這篇文章主要為大家介紹了Mybatis的Mapper代理對象生成及調(diào)用過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09

最新評論

手游| 永登县| 平潭县| 镇赉县| 江油市| 五台县| 黔江区| 道真| 文登市| 沁水县| 北碚区| 鹿泉市| 瓦房店市| 大悟县| 红河县| 正定县| 太和县| 鄂托克旗| 依兰县| 峨山| 望都县| 玉环县| 石城县| 荆州市| 临泉县| 包头市| 体育| 新津县| 修水县| 长岛县| 桦甸市| 洪泽县| 建阳市| 阳高县| 兴隆县| 观塘区| 青龙| 阜城县| 莫力| 临潭县| 祁阳县|