2015-02-14 12 views

risposta

9

L'esempio seguente utilizza diverse tecniche per creare un istogramma RGB dell'immagine arbitraria:

  • Procedimento RastergetSamples() estrae i valori di ciascuna banda di colore dalla BufferedImage.

  • Il metodo HistogramDataset aggiunge i conteggi di ogni banda allo dataset.

  • A StandardXYBarPainter sostituisce la ChartFactory predefinito, come mostrato here.

  • Un'abitudine DefaultDrawingSupplier fornisce il colore richiesto per ciascuna serie; contiene colori traslucidi.

  • Una variazione di VisibleAction, discussa here, viene utilizzata per controllare la visibilità di ciascuna banda; un approccio complementare utilizzando ChartMouseListener viene mostrato here.

color histogram

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Paint; 
import java.awt.event.ActionEvent; 
import java.awt.image.BufferedImage; 
import java.awt.image.Raster; 
import java.io.IOException; 
import java.net.URL; 
import javax.imageio.ImageIO; 
import javax.swing.AbstractAction; 
import javax.swing.ImageIcon; 
import javax.swing.JCheckBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.plot.DefaultDrawingSupplier; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.StandardXYBarPainter; 
import org.jfree.chart.renderer.xy.XYBarRenderer; 
import org.jfree.data.statistics.HistogramDataset; 

/** 
* @see https://stackoverflow.com/q/40537278/230513 
* @see https://stackoverflow.com/q/11870416/230513 
* @see https://stackoverflow.com/a/28519356/230513 
*/ 
public class Histogram { 

    private static final int BINS = 256; 
    private final BufferedImage image = getImage(); 
    private HistogramDataset dataset; 
    private XYBarRenderer renderer; 

    private BufferedImage getImage() { 
     try { 
      return ImageIO.read(new URL(
       "http://i.imgur.com/kxXhIH1.jpg")); 
     } catch (IOException e) { 
      e.printStackTrace(System.err); 
     } 
     return null; 
    } 

    private ChartPanel createChartPanel() { 
     // dataset 
     dataset = new HistogramDataset(); 
     Raster raster = image.getRaster(); 
     final int w = image.getWidth(); 
     final int h = image.getHeight(); 
     double[] r = new double[w * h]; 
     r = raster.getSamples(0, 0, w, h, 0, r); 
     dataset.addSeries("Red", r, BINS); 
     r = raster.getSamples(0, 0, w, h, 1, r); 
     dataset.addSeries("Green", r, BINS); 
     r = raster.getSamples(0, 0, w, h, 2, r); 
     dataset.addSeries("Blue", r, BINS); 
     // chart 
     JFreeChart chart = ChartFactory.createHistogram("Histogram", "Value", 
      "Count", dataset, PlotOrientation.VERTICAL, true, true, false); 
     XYPlot plot = (XYPlot) chart.getPlot(); 
     renderer = (XYBarRenderer) plot.getRenderer(); 
     renderer.setBarPainter(new StandardXYBarPainter()); 
     // translucent red, green & blue 
     Paint[] paintArray = { 
      new Color(0x80ff0000, true), 
      new Color(0x8000ff00, true), 
      new Color(0x800000ff, true) 
     }; 
     plot.setDrawingSupplier(new DefaultDrawingSupplier(
      paintArray, 
      DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE, 
      DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE, 
      DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, 
      DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE, 
      DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE)); 
     ChartPanel panel = new ChartPanel(chart); 
     panel.setMouseWheelEnabled(true); 
     return panel; 
    } 

    private JPanel createControlPanel() { 
     JPanel panel = new JPanel(); 
     panel.add(new JCheckBox(new VisibleAction(0))); 
     panel.add(new JCheckBox(new VisibleAction(1))); 
     panel.add(new JCheckBox(new VisibleAction(2))); 
     return panel; 
    } 

    private class VisibleAction extends AbstractAction { 

     private final int i; 

     public VisibleAction(int i) { 
      this.i = i; 
      this.putValue(NAME, (String) dataset.getSeriesKey(i)); 
      this.putValue(SELECTED_KEY, true); 
      renderer.setSeriesVisible(i, true); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      renderer.setSeriesVisible(i, !renderer.getSeriesVisible(i)); 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("Histogram"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(createChartPanel()); 
     f.add(createControlPanel(), BorderLayout.SOUTH); 
     f.add(new JLabel(new ImageIcon(image)), BorderLayout.WEST); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      new Histogram().display(); 
     }); 
    } 
} 
+1

Per divertimento, ecco una [istogramma] (http://i.imgur.com/1aQdxsM.png) del (famigerato) [nero blu vestito in oro bianco] (http://www.wired.com/2015/02/science-one-agrees-color-dress/). – trashgod

+0

Vedere anche questo relativo [esempio] (http://stackoverflow.com/q/40537278/230513). – trashgod

3

Utilizzando la libreria Chart2D, l'esempio qui sotto illustra alcuni approcci alternativi.

  • Un ColorConvertOp viene utilizzato per convertire l'immagine campione in scala di grigi, come mostrato here e here.

  • I cicli nidificati eseguono un'iterazione sui pixel di BufferedImage, richiamando il metodo getRGB() per estrarre il valore di ciascun pixel; i conteggi corrispondenti sono utilizzati per costruire il dataset.

Chart2DHistogram

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GradientPaint; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.image.BufferedImage; 
import java.awt.image.ColorConvertOp; 
import javax.swing.BorderFactory; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import net.sourceforge.chart2d.Chart2DProperties; 
import net.sourceforge.chart2d.Dataset; 
import net.sourceforge.chart2d.GraphChart2DProperties; 
import net.sourceforge.chart2d.GraphProperties; 
import net.sourceforge.chart2d.LBChart2D; 
import net.sourceforge.chart2d.LegendProperties; 
import net.sourceforge.chart2d.MultiColorsProperties; 
import net.sourceforge.chart2d.Object2DProperties; 

/** @see https://stackoverflow.com/q/9964872/230513 */ 
public class Histogram extends JPanel { 

    private BufferedImage image = getImage("OptionPane.warningIcon"); 
    private BufferedImage gray = getGray(image); 

    public Histogram() { 
     JPanel panel = new JPanel(new GridLayout(0, 1)); 
     panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); 
     panel.add(new JLabel(new ImageIcon(image))); 
     panel.add(new JLabel(new ImageIcon(gray))); 
     this.setLayout(new BorderLayout()); 
     this.add(panel, BorderLayout.WEST); 
     this.add(createChart(gray, 20), BorderLayout.CENTER); 
    } 

    private BufferedImage getImage(String name) { 
     Icon icon = UIManager.getIcon(name); 
     int w = icon.getIconWidth(); 
     int h = icon.getIconHeight(); 
     this.setPreferredSize(new Dimension(w, h)); 
     BufferedImage i = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2d = (Graphics2D) i.getGraphics(); 
     g2d.setPaint(new GradientPaint(
      0, 0, Color.blue, w, h, Color.green, true)); 
     g2d.fillRect(0, 0, w, h); 
     icon.paintIcon(null, g2d, 0, 0); 
     g2d.dispose(); 
     return i; 
    } 

    private BufferedImage getGray(BufferedImage image) { 
     BufferedImage g = new BufferedImage(
      image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY); 
     ColorConvertOp op = new ColorConvertOp(
      image.getColorModel().getColorSpace(), 
      g.getColorModel().getColorSpace(), null); 
     op.filter(image, g); 
     return g; 
    } 

    private LBChart2D createChart(BufferedImage gray, int buckets) { 
     // Chart2D configuration 
     Object2DProperties object2DProps = new Object2DProperties(); 
     object2DProps.setObjectTitleText("Gray Histogram"); 
     Chart2DProperties chart2DProps = new Chart2DProperties(); 
     chart2DProps.setChartDataLabelsPrecision(-1); 
     LegendProperties legendProps = new LegendProperties(); 
     String[] legendLabels = {"Gray"}; 
     legendProps.setLegendLabelsTexts(legendLabels); 
     GraphChart2DProperties graphChart2DProps = new GraphChart2DProperties(); 
     graphChart2DProps.setLabelsAxisTitleText("Gray"); 
     graphChart2DProps.setNumbersAxisTitleText("Count"); 

     // Dataset 
     String[] labelsAxisLabels = new String[buckets]; 
     for (int i = 0; i < labelsAxisLabels.length; i++) { 
      labelsAxisLabels[i] = String.valueOf(i * 256/buckets); 
     } 
     graphChart2DProps.setLabelsAxisLabelsTexts(labelsAxisLabels); 
     int[] counts = new int[buckets]; 
     for (int r = 0; r < gray.getHeight(); r++) { 
      for (int c = 0; c < gray.getWidth(); c++) { 
       int v = (gray.getRGB(c, r) & 0xff) * buckets/256; 
       counts[v]++; 
      } 
     } 
     Dataset dataset = new Dataset(1, counts.length, 1); 
     for (int i = 0; i < counts.length; i++) { 
      dataset.set(0, i, 0, counts[i]); 
     } 

     GraphProperties graphProps = new GraphProperties(); 
     MultiColorsProperties multiColorsProps = new MultiColorsProperties(); 
     LBChart2D chart2D = new LBChart2D(); 
     chart2D.setObject2DProperties(object2DProps); 
     chart2D.setChart2DProperties(chart2DProps); 
     chart2D.setLegendProperties(legendProps); 
     chart2D.setGraphChart2DProperties(graphChart2DProps); 
     chart2D.addGraphProperties(graphProps); 
     chart2D.addDataset(dataset); 
     chart2D.addMultiColorsProperties(multiColorsProps); 

     //Optional validation: Prints debug messages if invalid only. 
     if (!chart2D.validate(false)) { 
      chart2D.validate(true); 
     } 
     return chart2D; 
    } 

    private void display() { 
     JFrame f = new JFrame("Histogram"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.pack(); 
     f.setSize(640, 480); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Histogram().display(); 
      } 
     }); 
    } 
} 
Problemi correlati