基于定位的热力图展示,后端实现

  • 首先将实际坐标转换成像素坐标
  • 操作图片像素 不断的增加像素RGB值
  • 扩大像素点范围,根据聚集程度设置色阶,最后高斯模糊形成热力图
  • 这里是根据实际场景自动生成对应等比例大小的透明贴图,当然也可以直接在指定的图片上画热力图

1.坐标转换以前有发过一个工具类任意坐标系转换可以去看看

这里取的4个点分别为图片左下角,图片右上角 对应的实际位置坐标左下角和右上角

使用工具类获取到偏移量,旋转值等基本参数

  double rotation = Math.toRadians(Math.abs(coordinateUtil.getAngle(imgPoint1, imgPoint2) - coordinateUtil.getAngle(mapPoint1, mapPoint2)));
        double scale = coordinateUtil.getScale(mapPoint1, imgPoint1, mapPoint2, imgPoint2);
        double tx = coordinateUtil.getXTranslation(mapPoint1, imgPoint1, rotation, scale);
        double ty = coordinateUtil.getYTranslation(mapPoint1, imgPoint1, rotation, scale);

将实际点转换成像素点

Point boePoint = coordinateUtil.transformBoePoint(new Point(o.getX(), o.getZ(), 0.0), rotation, scale, tx, ty);
//去吹掉超出图片范围的点
 //若转换的坐标超出了图片范围舍弃
            Double x = boePoint.getX();
            Double y = boePoint.getY();
            if (!(x < 0 || y < 0 || x > imageWidth || y > imageHeight)){
                heatMapData.setX(x)
                        .setY(y);
                heatMapDataList.add(heatMapData);
            }

渲染图片 这里说明下,因为像素点的坐标系原点是左上角的点,与我们最开始设置的对应坐标系不同,所有转换出来的像素点的y值需要用图片高度减去他剩下的就是实际的像素点,因为像素点很小,在设置时count我是默认将该点周围8个点作为一个大的像素点,这样在设置颜色时就会很明显,这个参数根据需求设置

 /**
     * 渲染图片
     * @param image 图片流
     * @param x 操作的像素点x
     * @param y 操作的像素点y
     * @param count 渲染的像素点
     */
    public static void renderPictures(BufferedImage image, Double x, Double y, int count){
        //获取画笔对象
        int xValue = x.intValue();
        int yValue = y.intValue();
        int pixel = image.getRGB(xValue, yValue);
        //从pixel中获取rgba的值
        int b = (0xff & pixel);
        int g = (0xff & (pixel >> 8));
        int r = (0xff & (pixel >> 16));
        //α通道值
        int alpha = (0xff & (pixel >> 24));
        //颜色解析
        if (r == 0){
            if (g < 255){
                g = 255;
            }
        }
        int rgb = b + (g << 8) + (r << 16) + (255 << 24);
        int vy = image.getHeight() - yValue;
//        image.setRGB(xValue, vy, rgb);
//        image.setRGB(xValue, vy, rgb);
//        image.setRGB(xValue, vy, rgb);
//        image.setRGB(xValue, vy, rgb);
        for (int i = xValue - count; i< xValue + count; i++) {
            for (int j = vy - count; j< vy + count; j++) {
                if (i >= 0 && i < image.getWidth()) {
                    if (j >=0 && j < image.getHeight() ) {
                        image.setRGB(i, j, rgb);
                    }
                }
            }
        }
    }

最后高斯模糊刚才处理后的图片,根据α通道设置色阶,实现多个目标聚集时颜色加深(这里色阶可根据实际情况调整)

/**
     * 高斯模糊 设置色阶
     * @param blur
     * @param outPat
     */
    public static void gaussFuzzy(BufferedImage blur, String outPat) {
        try {
            blur = HeatMapUtil.blur(blur, 25);
            int width = blur.getWidth();
            int height = blur.getHeight();
            //获取像素点
            for (int i = 0; i< width; i++) {
                for (int j = 0; j < height; j++) {
                    int pixel = blur.getRGB(i, j);
                    //从pixel中获取rgba的值
                    int a = (pixel >> 24) & 0xff;
                    int g = (pixel >> 8) & 0xff;
                    if (g == 255) {
                        //颜色分级
                        if (a > 0 && a <= 25){
                            blur.setRGB(i, j, new Color(0, 0, 255, 15).getRGB());
                        }
                        if (a > 25 && a <= 50){
                            blur.setRGB(i, j, new Color(0, 255, 0, 160).getRGB());
                        }
                        if (a > 50 && a <= 100){
                            blur.setRGB(i, j, new Color(255, 255, 0, 185).getRGB());
                        }
                        if (a > 100 && a <= 125){
                            blur.setRGB(i, j, new Color(255, 213, 0, 200).getRGB());
                        }
                        if (a > 125 && a <= 150){
                            blur.setRGB(i, j, new Color(255, 171, 0, 215).getRGB());
                        }
                        if (a > 125 && a <= 150){
                            blur.setRGB(i, j, new Color(255, 129, 0, 225).getRGB());
                        }
                        if (a > 150 && a <= 175){
                            blur.setRGB(i, j, new Color(255, 87, 0, 235).getRGB());
                        }
                        if (a > 175 && a <= 200){
                            blur.setRGB(i, j, new Color(255, 42, 0, 245).getRGB());
                        }
                        if (a > 200){
                            blur.setRGB(i, j, new Color(255, 0, 0, 255).getRGB());
                        }
                    }
                }
            }
            blur = HeatMapUtil.blur(blur, 10);
            //输出
            ImageIO.write(blur,"png",new File(outPat));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   /**
     * 高斯模糊
     * @param source 数据源
     * @param radius 模糊半径
     * @return
     */
    public static BufferedImage blur(BufferedImage source, int radius) {
        BufferedImage img = new BufferedImage(source.getWidth() + radius
                * 2, source.getHeight() + radius * 2,
                BufferedImage.TRANSLUCENT);
        Graphics2D g2 = (Graphics2D) img.getGraphics();
        g2.setColor(new Color(0,0,0,0));
        g2.fillRect(0, 0, source.getWidth() + radius * 2,
                source.getHeight() + radius * 2);
        g2.drawImage(source, radius, radius, null);
        g2.dispose();
        int square = radius * radius;
        float sum = 0;
        float[] matrix = new float[square];
        for (int i = 0; i < square; i++) {
            int dx = i % radius - radius / 2;
            int dy = i / radius - radius / 2;
            matrix[i] = (float) (radius - Math.sqrt(dx * dx + dy * dy));
            sum += matrix[i];
        }
        for (int i = 0; i < square; i++) {
            matrix[i] /= sum;
        }
        BufferedImageOp op = new ConvolveOp(new Kernel(radius, radius,
                matrix), ConvolveOp.EDGE_ZERO_FILL, null);
        BufferedImage res = op.filter(img, null);
        BufferedImage out = new BufferedImage(source.getWidth(),
                source.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g3 = (Graphics2D) out.getGraphics();
        g3.drawImage(res, -radius, -radius, null);
        g3.dispose();
        return out;
    }