Java+OpenCV学习计算机视觉-灰度直方图及其均衡化
灰度直方图
灰度直方图简单来说就是一个柱状图,横坐标是灰度0~255,纵坐标是频率或者是频数。
具体可以看这篇博客:: https://blog.csdn.net/qq_36554582/article/details/82928489.
所以从代码层面来实现的话只需要一个int类型的数组:int []hist=new int[256];
,然后我们遍历所有的像素点,每个像素点相当于数组的下标,然后频数加1即可。
代码实现如下:
/**
* 获取图像的灰度值的数组
*
* @param image 输入的图像
* @return 灰度值的数组
*/
public static int[] getHist(BufferedImage image) {
int[] hist = new int[256];
Mat mat = CvUtils.BufImg2Mat(image, BufferedImage.TYPE_BYTE_GRAY, CvType.CV_8UC1);
for (int i = 0; i < mat.width(); i++)
for (int j = 0; j < mat.height(); j++) {
double[] value = mat.get(i, j);
hist[(int) value[0]]++;
}
return hist;
}
其中涉及到了BufferedImage到Mat,工具函数实现如下:
/**
* BufferedImage转换成Mat
*
* @param original 要转换的BufferedImage
* @param imgType bufferedImage的类型 如 BufferedImage.TYPE_3BYTE_BGR
* @param matType 转换成mat的type 如 CvType.CV_8UC3
*/
public static Mat BufImg2Mat(BufferedImage original, int imgType, int matType) {
if (original == null) {
throw new IllegalArgumentException("original == null");
}
// Don't convert if it already has correct type
if (original.getType() != imgType) {
// Create a buffered image
BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);
// Draw the image onto the new buffer
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
} finally {
g.dispose();
}
}
DataBufferByte dbi = (DataBufferByte) original.getRaster().getDataBuffer();
byte[] pixels = dbi.getData();
Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
mat.put(0, 0, pixels);
return mat;
}
到这里我们能够得到一张图像的灰度值的频数的数组,我们想把它绘制成一张图像如何实现呢?
我们可以采用柱状图的形式来画,对每一个像素点,我们可以使用Java的drawLine()方法来绘制一条直线,然后从下往上画,线的长度取决于这个像素点的频率高低。
所以在此之前,我们要对我们之前获取到的频数数组进行归一化的操作,方面后续画图会更加好看一些。
归一化主要便是将所有的频数转化为频率分布在0~1之间,所以我们使用每个像素点的频数值除以最高的频数值即可,(如果更加精细的话还可以考虑最小值,我这相当于只考虑了最大值)。
代码实现如下(也可以放置到CVUtils这个工具类里面):
/**
* 归一化
*
* @param histValue 灰度值数组
* @return 归一化之后的频率
*/
public static double[] normalize(int[] histValue) {
double[] lengths = new double[histValue.length];
double max = 0.0;
f