Java+OpenCV学习计算机视觉-灰度直方图及其均衡化

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
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值