Portál o technologiích a vývoji

Grafika – histogram

Autor: Redakce ZdrojovyKod.cz Datum: 15.2.2011 Počet shlédnutí: 65 879x

Histogram je speciální typ grafu, který vyjadřuje hodnotu jasu v obrázku, černou zpravidla vyjadřujeme vlevo a bílou vpravo. Hodnoty sloupců vyjadřují počet pixelů dané hodnoty jasu v grafu. Zjednodušeně řečeno se jedná o graf rozložení „jasů“ v obrázku.

1. Načteme si obrázek a uložíme jej s datovým typem BufferedImage.
2. Deklarujeme a naalokujeme si pole pro jednotlivé barevné kanaly RGB:

private int[] histogram = new int[256];     // hodnoty 0 až 255
private int[] redHistogram = new int[256];
private int[] greenHistogram = new int[256];
private int[] blueHistogram = new int[256];

3. V metodě vytvorHistogram() si tato pole vynulujeme:

       for (int i = 0; i < histogram.length; i++) {
            histogram[i] = 0;
            redHistogram[i] = 0;
            greenHistogram[i] = 0;
            blueHistogram[i] = 0;
        }

4. Nyní vypočítáme hodnoty jasů jednotlivých kanálu a naplníme jimy pole:

     if (obrazek != null) {
            for (int x = 0; x < obrazek.getWidth(); x++) {
                for (int y = 0; y < obrazek.getHeight(); y++) {
                    red = ((obrazek.getRGB(x, y)) & 0xFF0000) >> 16;
                    redHistogram[red]++;
                    green = ((obrazek.getRGB(x, y)) & 0xFF00) >> 8;
                    greenHistogram[green]++;
                    blue = ((obrazek.getRGB(x, y)) & 0xFF);
                    blueHistogram[blue]++;
                    jas = (int) Math.round((red * 0.299) + (green * 0.587) + (blue * 0.114));
                    histogram[jas]++;
                }
            }
        }

Jak vidíte, vždy vypočítáme hodnotu jasu kanálu, tu najdeme v polu (resp. pouzijeme hodnotu jako index pole) a na tomto indexu inkrementujeme hodnotu o 1. Krome barevných kanálů taky počítáme jas pro histogram v odstinech šedi, využíváme k tomu převod za pomoci vynasobeni kanálů konstantou.

5. Nyní již nezbývá než histogram vykreslit, nejdříve však nesmíme zapomenout zavolat metodu vytvorHistogram()

   vytvorHistogram();
   if (obrazek == null) {
        } else {

Deklarujeme si proměnné:

 
            int maximum = histogram[0];
            float pomer;
            int prepocitanaCetnost;
            int predchoziPrepocitanaCetnost;

Najdeme maximum z pole histogramu, je důležité k vypočítání poměru vypočítaných hodnot vzhledek ke kreslícímu plátnu.

 
            for (int i = 0; i < histogram.length; i++) {
                if (maximum < histogram[i]) {
                    maximum = histogram[i];
                }
            }

Zjistíme si onen zmiňovaný poměr

 
            pomer = (float) getHeight() / maximum;

Přepočítaná četnost nám slouží k vypočítání hodnoty konkrétního sloupce vzhledem k velikosti zobrazovacího plátna.
Dále již jen vykreslujeme za pomocí cyklů jednotlivé barevné kanály.

 
            for (int i = 0; i < histogram.length; i++) {
                g.setColor(Color.BLACK);
                prepocitanaCetnost = Math.round(histogram[i] * pomer);  
                g.drawLine(i + 1, getHeight() - 1, i + 1, getHeight() - 1 - prepocitanaCetnost);

                if (i > 0) {

                    g.setColor(Color.RED);
                    prepocitanaCetnost = Math.round(redHistogram[i] * pomer);
                    predchoziPrepocitanaCetnost = Math.round(redHistogram[i - 1] * pomer);
                    g.drawLine(i, getHeight() - 1 - predchoziPrepocitanaCetnost, i + 1, getHeight() - 1 - prepocitanaCetnost);
 
                    g.setColor(Color.GREEN);
                    prepocitanaCetnost = Math.round(greenHistogram[i] * pomer);
                    predchoziPrepocitanaCetnost = Math.round(greenHistogram[i - 1] * pomer);
                    g.drawLine(i, getHeight() - 1 - predchoziPrepocitanaCetnost, i + 1, getHeight() - 1 - prepocitanaCetnost);
 
                    g.setColor(Color.BLUE);
                    prepocitanaCetnost = Math.round(blueHistogram[i] * pomer);
                    predchoziPrepocitanaCetnost = Math.round(blueHistogram[i - 1] * pomer);
                    g.drawLine(i, getHeight() - 1 - predchoziPrepocitanaCetnost, i + 1, getHeight() - 1 - prepocitanaCetnost);

                }
            }
        }
    }

Výsledek může vypadat například takto:

Žádné komentáře

Poslat komentář

Vaše e-mailová adresa nebude zveřejněna.