本文介绍一下如何使用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 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);
}