JAVA 后端生成热力图图片返回
基于定位的热力图展示,后端实现
- 首先将实际坐标转换成像素坐标
- 操作图片像素 不断的增加像素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; }