绘制灰度直方图(OpenCV + Java)

本文介绍一下如何使用Java语言绘制灰度图的直方图。由于Java环境下OpenCV不提供Mat图像的显示方法,如imshow(),因此需要使用SWing组件自己编写显示方法。同时,OpenCV的Jar包也并没有提供相关的抽象数据类型和方法,比如CvHistogram等。

灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级,纵坐标表示图像中该灰度级出现的个数(频率)。下面的方法是绘制一张灰度图的直方图:

    /**
     * Plot histogram of a single channel grayscale image
     *
     * @param img a single channel grayscale image
     */
    public static void plotGrayHistogram(Mat img) {
        java.util.List<Mat> images = new ArrayList<>();
        images.add(img); 
        MatOfInt channels = new MatOfInt(0); // 图像通道数,0表示只有一个通道 
        MatOfInt histSize = new MatOfInt(256); // CV_8U类型的图片范围是0~255,共有256个灰度级
        Mat histogramOfGray = new Mat(); // 输出直方图结果,共有256行,行数的相当于对应灰度值,每一行的值相当于该灰度值所占比例
        MatOfFloat histRange = new MatOfFloat(0, 255);
        Imgproc.calcHist(images, channels, new Mat(), histogramOfGray, histSize, histRange, false);  // 计算直方图 
        // 按行归一化
        Core.normalize(histogramOfGray, histogramOfGray, 0, histogramOfGray.rows(), Core.NORM_MINMAX, -1, new Mat());

        // 创建画布
        int histImgRows = 300;
        int histImgCols = 300;
        int colStep = (int) Math.floor(histImgCols / histSize.get(0, 0)[0]);
        Mat histImg = new Mat(histImgRows, histImgCols, CvType.CV_8UC3, new Scalar(255,255,255));  // 重新建一张图片,绘制直方图
        for (int i = 0; i < histSize.get(0, 0)[0]; i++) {  // 画出每一个灰度级分量的比例,注意OpenCV将Mat最左上角的点作为坐标原点
            Imgproc.line(histImg,
                    new org.opencv.core.Point(colStep * i, histImgRows - 20),
                    new org.opencv.core.Point(colStep * i, histImgRows - Math.round(histogramOfGray.get(i, 0)[0]) - 20),
                    new Scalar(0, 0,0), 2,8,0);  
            if (i%50 == 0) {
                 Imgproc.putText(histImg, Integer.toString(i), new org.opencv.core.Point(colStep * i, histImgRows - 5), 1, 1, new Scalar(0, 0, 0));  // 附上x轴刻度
            }
        }
        MatView.imshow(histImg, "Gray Histogram");

    }

下面的方法是在Java环境下显示一张Mat图像:

     /**
     * Display Mat image
     *
     * @param image
     * @param windowName
     */
    public static void imshow(Mat image, String windowName){
       try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }

        JFrame jFrame = new JFrame(windowName);
        JLabel imageView = new JLabel();
        final JScrollPane imageScrollPane = new JScrollPane(imageView);
        imageScrollPane.setPreferredSize(new Dimension(500, 500));  // set window size
        jFrame.add(imageScrollPane, BorderLayout.CENTER);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        Image loadedImage = Mat2BufferedImage(image);
        imageView.setIcon(new ImageIcon(loadedImage));
        jFrame.pack();
        jFrame.setLocationRelativeTo(null);
        jFrame.setVisible(true);
    }

下图分别是测试原图图与其对应的灰度图和直方图:
这里写图片描述

这里写图片描述这里写图片描述

猜你喜欢

转载自blog.csdn.net/MengchiCMC/article/details/73499475