Ich arbeite jetzt schon eine Weile. Ich schreibe zum ersten Mal einen Blog. Ich weiß nicht, wie ich es schreiben soll. Lass es uns einfach lesen. Bitte korrigieren Sie mich, wenn Sie falsche Wörter haben.
In letzter Zeit wurde bei der Arbeit eine Bildkomprimierungsfunktion verwendet. Ich fand einige Werkzeuge, aber es gab keine gute Wahl. Schließlich entschied ich mich für eine Person namens Jdeli, aber die Effizienz wurde wieder zu einem Problem. Ich hatte keine andere Wahl, als seinen Quellcode zu untersuchen, stellte jedoch fest, dass ich mich für einen seiner subtraktiven Quantisierungsalgorithmen interessierte. Es war mir jedoch peinlich, dass ich nicht verstand, was es schrieb, also hatte ich die Idee, einen quantitativen Farbalgorithmus alleine umzusetzen.
Ich fand selbst einige Informationen und fand drei häufig verwendete Farbverarbeitungsalgorithmen:
Beliebter Farbalgorithmus:
Der spezifische Algorithmus besteht darin, zunächst die Anzahl der in einem Bild angezeigten Farben zu zählen, die 256 Farben mit den meisten Vorkommen als Farbe der Palette des Bildes auszuwählen und dann alle Pixel des Bildes durchzusetzen, die engste Farbe in der Palette für jedes Pixel (ich benutze die Varianzmethode hier) und schreibe es hier wieder auf das Bild. Die Implementierung dieses Algorithmus ist relativ einfach, aber die Verzerrung ist relativ schwerwiegend. Einige Bilder erscheinen bei niedriger Frequenz, aber der visuelle Effekt auf das menschliche Auge ist ziemlich offensichtlich. Informationen werden verloren gehen. Beispielsweise werden die Spots im Bild mit hoher Britishuge aufgrund der geringen Anzahl von Vorkommen möglicherweise nicht vom Algorithmus ausgewählt und gehen verloren.
Mittlerer Schnittalgorithmus:
Ich habe diesen Algorithmus nicht studiert. Diejenigen, die wissen möchten, können diesen Artikel lesen, der Einführungen von drei Algorithmen enthält.
Oktavbaum
Dieser Algorithmus ist der letzte Algorithmus, den ich ausgewählt habe. Seine Hauptidee ist es, den RGB -Farbwert des Bildes in eine binäre Verteilung in Octree umzuwandeln, zum Beispiel: (173, 234, 144)
Um in binäre IS (10101101, 11101010, 10010000) zu konvertieren, nehmen Sie die ersten Bits von R, G, B aus (111) und dienen Sie als untergeordnete Knoten des Wurzelknotens, wobei 111 der Index des Wurzelknotenknotens und so auf das Laub auf dem Laub auf dem Laub und der Anzahl der Färben und der Anzahl der Laub- und der Anzahl der Laub- und Nodien speichern. Weitere Informationen finden Sie im Bild.
Eines der Dinge, über die ich verwirrter bin, ist die Zusammenführungsstrategie von Blattknoten. Die dümmste Methode, die ich hier verwende, besteht darin, den tiefsten Knoten zu finden und dann zusammenzuarbeiten. Es ist ein bisschen einfach und grob. Es gibt andere bessere Methoden. Bitte hinterlassen Sie mir eine Nachricht. Das Bild ist zu groß und kann nicht hochgeladen werden, daher lade ich einfach den Code hoch. Der Code wurde nicht nachgearbeitet, sodass jeder ihn lesen kann.
Paket com.gys.pngquant.octree; import Java.util.ArrayList; Import Java.util.hashMap; Import Java.util.List; * ********************************************************* * </p> */public class Node{private int depth = 0;// When it is 0, it is a root node 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; b);} public map <Integer, Liste <Node >> getlevelMapping () {return LevelMapping;} public void AfterSetParam () {if (this.getParent () == null && this.depth == 0) {Levelmaping = new Hashmap <ig intiere, list <nodes> (); {LevelMapping.put (i, new ArrayList <node> ());}}} public int getrnum () {return rnum;} public void setRnum (int rnum) {if (! isLef) {throw New UnupportedoperationException ();} this.rnum = rnum; setGnum (int gnum) {if (! getPiexls () {return piexls;} public void setpiexls (int piexls) {if (! mergerleafNode () {if (this.islaf) {return 1;} this.setLeaf (true); int rnum = 0; int gnum = 0; int bnum = 0; int pixel = 0; int i = 0; für (knotenkind: this.children) {if (unter (unter (unter (unter (nel)) {continum; child.getGnum (); bnum += child.getBnum (); pixel += child.getPiexls (); i += 1;} this.setrnum (rnum); this.setgnum (gnum); this.setbnum (Bnum); this.setpiexls (pixel); this.thchildren = null; Node getDepestNode () {für (int i = 7; i> 0; i--) {list <node> levellist = this.levelMapping.get (i); if (! Levellist.isempty ()) {return Levellist.REMOVE (Levellist.Size ()-1);}}}}} // getleafnum () {if (isLeaf) {return 1;} int i = 0; für (Knotenkind: this.Children) {if (child! = null) {i += child.getleafnum ();}} return i; 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; 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); Knoten child = pronode.getchild (item); if (child == null) {child = new node (); child.setDepth (8-i); child.setParent (pronode); child.aftersetaram (); child);} if (i == speed) {child.setleaf (true);} if (chirt.islaf ()) {child.setpixel (r, g, b); break;} pronode = child;}} öffentlicher statischer Node -Build (int [] [] matrix, int speed) {node wurzelwurzel = new node (); für (int [] row: matrix) {für (int cell: row) {root.add8bite2root (Zelle, Geschwindigkeit);}} return root;} öffentliches statisches Byte [] mergeColors (Knotenwurzel, int maxcolors) {byte [] bytearray = new ayte [maxcolors * 3]; root.getleafnum (); try {while (leafnum> maxcolors) {int mergerleafNode = root.getDepestNode (). mergerleafnode (); leafnum - = (mergerleafnode - 1);}} catch (Exception E) {E.printaNTrace ();} fillarray (root, result Ergebnis) {bytearray [i ++] = byte1;} return bytearray;} private statische void fillarray (Knotenknoten, Liste <Byte> Ergebnis, int offset) {if (node == null) {return;} if (node.islaf () {) {ergebnis. node.getPiexls()));result.add((byte) (node.getgNum() / node.getPiexls()));result.add((byte) (node.getbNum() / node.getPiexls()));result.add((byte) (node.getbNum() / node.getPiexls()));} sonst {für (Knoten unterscheidArm meine einzige Datenstruktur im College. Der Code implementiert nur einen Octree. Es dauert ungefähr 450 ms, um ein 1920*1080 -Bild zu quantisieren, und wenn Level -2 ungefähr 100 ms sind.
Okay, das war's. Bevor ich es schrieb, hatte ich das Gefühl, dass ich viel sagen wollte, aber ich wusste nicht, was ich sagen sollte, als ich es schrieb. Bitte verzeihen Sie mir.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels über die einfache Implementierung von Octree -Bildverarbeitungscode -Beispielen durch Java. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!