显示图像数据的直方图 [英] Displaying a histogram of image data

查看:22
本文介绍了显示图像数据的直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有时需要以直方图的形式显示

import java.awt.BorderLayout;导入 java.awt.Color;导入 java.awt.EventQueue;导入 java.awt.Paint;导入 java.awt.event.ActionEvent;导入 java.awt.image.BufferedImage;导入 java.awt.image.Raster;导入 java.io.IOException;导入 java.net.URL;导入 javax.imageio.ImageIO;导入 javax.swing.AbstractAction;导入 javax.swing.ImageIcon;导入 javax.swing.JCheckBox;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 org.jfree.chart.ChartFactory;导入 org.jfree.chart.ChartPanel;导入 org.jfree.chart.JFreeChart;导入 org.jfree.chart.plot.DefaultDrawingSupplier;导入 org.jfree.chart.plot.PlotOrientation;导入 org.jfree.chart.plot.XYPlot;导入 org.jfree.chart.renderer.xy.StandardXYBarPainter;导入 org.jfree.chart.renderer.xy.XYBarRenderer;导入 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*/公共类直方图{私有静态最终 int BINS = 256;私有最终 BufferedImage 图像 = getImage();私有 HistogramDataset 数据集;私人 XYBarRenderer 渲染器;私有 BufferedImage getImage() {尝试 {返回 ImageIO.read(新 URL("https://i.imgur.com/kxXhIH1.jpg"));} catch (IOException e) {e.printStackTrace(System.err);}返回空;}私人图表面板 createChartPanel() {//数据集数据集 = 新的 HistogramDataset();光栅 raster = image.getRaster();最终 int w = image.getWidth();最终 int h = image.getHeight();双[] r = 新双[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);//图表JFreeChart 图表 = ChartFactory.createHistogram("Histogram", "Value",计数",数据集,PlotOrientation.VERTICAL,真,真,假);XYPlot plot = (XYPlot) chart.getPlot();渲染器 = (XYBarRenderer) plot.getRenderer();renderer.setBarPainter(new StandardXYBarPainter());//半透明的红、绿 &蓝色油漆[] 油漆阵列 = {新颜色(0x80ff0000,真),新颜色(0x8000ff00,真),新颜色(0x800000ff,真)};plot.setDrawingSupplier(new DefaultDrawingSupplier(油漆阵列,DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE));ChartPanel 面板 = new ChartPanel(chart);panel.setMouseWheelEnabled(true);返回面板;}私人 JPanel createControlPanel() {JPanel 面板 = new JPanel();panel.add(new JCheckBox(new VisibleAction(0)));panel.add(new JCheckBox(new VisibleAction(1)));panel.add(new JCheckBox(new VisibleAction(2)));返回面板;}私有类 VisibleAction 扩展了 AbstractAction {私人最终 int i;公共 VisibleAction(int i) {this.i = i;this.putValue(NAME, (String) dataset.getSeriesKey(i));this.putValue(SELECTED_KEY, true);renderer.setSeriesVisible(i, true);}@覆盖public void actionPerformed(ActionEvent e) {renderer.setSeriesVisible(i, !renderer.getSeriesVisible(i));}}私人无效显示(){JFrame f = new JFrame(直方图");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);}公共静态无效主(字符串 [] args){EventQueue.invokeLater(() -> {新直方图().显示();});}}

I sometimes need to display a representation of image data in the form of a histogram. I'm especially interested in ways to access the image data. I'm familiar with JFreeChart, which includes histogram support, but I'd consider other approaches.

解决方案

The example below uses several techniques to create an RGB histogram of an arbitrary image:

  • The Raster method getSamples() extracts the values of each color band from the BufferedImage.

  • The HistogramDataset method addSeries() adds each band's counts to the dataset.

  • A StandardXYBarPainter replaces the ChartFactory default, as shown here.

  • A custom DefaultDrawingSupplier supplies the color required for each series; it contains translucent colors.

  • A variation of VisibleAction, discussed here, is used to control the visibility of each band; a complementary approach using ChartMouseListener is shown here.

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(
                "https://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();
        });
    }
}

这篇关于显示图像数据的直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆