Browse Source

feat: 1.新增多边形区域标注取温;2.新增标记显示区域最高温和最低温;3.相机红外算法支持对DLT664的解析

master
yinhuaiwei 3 weeks ago
parent
commit
d60436a1ff
4 changed files with 325 additions and 230 deletions
  1. +8
    -0
      src/main/java/com/inspect/simulator/domain/Infrared/Coordinate.java
  2. +96
    -68
      src/main/java/com/inspect/simulator/service/ImageAnnotationService.java
  3. +45
    -14
      src/main/java/com/inspect/simulator/service/TemperatureDataService.java
  4. +176
    -148
      src/main/java/com/inspect/simulator/service/impl/HikVisionServiceImpl.java

+ 8
- 0
src/main/java/com/inspect/simulator/domain/Infrared/Coordinate.java View File

@ -29,6 +29,8 @@ public class Coordinate {
private String maxValueX;
private String maxValueY;
private int[] points;
public Coordinate(int firstX, int firstY, int secondX, int secondY, int width, int height) {
this.firstX = firstX;
this.firstY = firstY;
@ -37,4 +39,10 @@ public class Coordinate {
this.width = width;
this.height = height;
}
public Coordinate(int[] points, int width, int height) {
this.points = points;
this.width = width;
this.height = height;
}
}

+ 96
- 68
src/main/java/com/inspect/simulator/service/ImageAnnotationService.java View File

@ -8,6 +8,7 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.awt.*;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.ArrayList;
@ -25,6 +26,10 @@ public class ImageAnnotationService {
*/
private static final int CROSSHAIR_R = 6, CROSSHAIR_ARM = 6;
private Font chineseFont;
// 最高温度标注颜色
private static final Color MAX_TEMP_COLOR = new Color(255, 23, 68);
// 最低温度标注颜色
private static final Color MIN_TEMP_COLOR = new Color(41, 121, 255);
private static int clamp(int v, int lo, int hi) {
return Math.max(lo, Math.min(hi, v));
@ -46,6 +51,20 @@ public class ImageAnnotationService {
return false;
}
private static double[][] shapeVertices(Shape shape) {
PathIterator it = shape.getPathIterator(null);
List<double[]> pts = new ArrayList<>();
double[] c = new double[6];
while (!it.isDone()) {
int type = it.currentSegment(c);
if (type == PathIterator.SEG_MOVETO || type == PathIterator.SEG_LINETO) {
pts.add(new double[]{c[0], c[1]});
}
it.next();
}
return pts.toArray(new double[0][]);
}
/**
* @param originalImage 原图
* @param infraredInfo 热成像信息
@ -59,102 +78,98 @@ public class ImageAnnotationService {
infraredInfo.setMaxTemp(tempData.getMaxTemp());
infraredInfo.setMinTemp(tempData.getMinTemp());
// 插值比例红外测温分辨率和可见光图片分辨率可能存在不一致情况
float scaleX = (float) originalImage.getWidth() / tempData.getCols();
float scaleY = (float) originalImage.getHeight() / tempData.getRows();
int originalWidth = originalImage.getWidth();
int originalHeight = originalImage.getHeight();
int outW = originalImage.getWidth();
int outH = originalImage.getHeight();
// 图片宽高 温度矩阵宽高 比例
float scaleX = (float) originalWidth / tempData.getCols();
float scaleY = (float) originalHeight / tempData.getRows();
BufferedImage canvas = new BufferedImage(outW, outH, BufferedImage.TYPE_INT_RGB);
BufferedImage canvas = new BufferedImage(originalWidth, originalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = canvas.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
BufferedImage canvasImage;
if (genThermal) {
canvasImage = ThermalGenerator.generate(tempData, outW, outH);
canvasImage = ThermalGenerator.generate(tempData, originalWidth, originalHeight);
} else {
canvasImage = originalImage;
}
g.drawImage(canvasImage, 0, 0, null);
// 加载字体
ensureFont();
int fontSize = Math.max(16, originalImage.getWidth() / 70);
int fontSize = Math.min(16, Math.max(12, originalImage.getWidth() / 40));
g.setFont(chineseFont.deriveFont(Font.PLAIN, fontSize));
FontMetrics fm = g.getFontMetrics();
List<TextLabel> labels = new ArrayList<>();
/**
* 标注全图最高温和最低温
*/
// 1.转换全图最高温和最低温的点坐标
int maxX = Math.round(tempData.getMaxCol() * scaleX) + 1;
int maxY = Math.round(tempData.getMaxRow() * scaleY) + 1;
int minX = Math.round(tempData.getMinCol() * scaleX) + 1;
int minY = Math.round(tempData.getMinRow() * scaleY) + 1;
// 2.根据坐标绘制十字图形
drawCrosshair(g, maxX, maxY, new Color(255, 23, 68));
drawCrosshair(g, minX, minY, new Color(41, 121, 255));
if (true) {
// 1.转换全图最高温和最低温的点坐标
int maxX = Math.round(tempData.getMaxCol() * scaleX);
int maxY = Math.round(tempData.getMaxRow() * scaleY);
int minX = Math.round(tempData.getMinCol() * scaleX);
int minY = Math.round(tempData.getMinRow() * scaleY);
// 2.根据坐标绘制十字图形
drawCrosshair(g, maxX, maxY, MAX_TEMP_COLOR);
drawCrosshair(g, minX, minY, MIN_TEMP_COLOR);
// 3.根据坐标绘制文本并对十字进行避障展示
int r = CROSSHAIR_R;
int arm = CROSSHAIR_ARM;
Rectangle maxCrosshairRect = new Rectangle(maxX - r - arm, maxY - r - arm, (r + arm) * 2, (r + arm) * 2);
Rectangle minCrosshairRect = new Rectangle(minX - r - arm, minY - r - arm, (r + arm) * 2, (r + arm) * 2);
String maxText = String.format("最高温度: %.1f", tempData.getMaxTemp());
String minText = String.format("最低温度: %.1f", tempData.getMinTemp());
labels.add(createLabel(maxText, maxX, maxY, fm, true, maxCrosshairRect));
labels.add(createLabel(minText, minX, minY, fm, true, minCrosshairRect));
log.info("最高温度: {}, 表格坐标: ({},{}), 图片坐标: ({},{})", tempData.getMaxTemp(), tempData.getMaxCol(), tempData.getMaxRow(), maxX, maxY);
log.info("最低温度: {}, 表格坐标: ({},{}), 图片坐标: ({},{})", tempData.getMinTemp(), tempData.getMinCol(), tempData.getMinRow(), minX, minY);
}
// 3.根据坐标绘制文本并对十字进行避障展示
int r = CROSSHAIR_R;
int arm = CROSSHAIR_ARM;
Rectangle maxCrosshairRect = new Rectangle(maxX - r - arm, maxY - r - arm, (r + arm) * 2, (r + arm) * 2);
Rectangle minCrosshairRect = new Rectangle(minX - r - arm, minY - r - arm, (r + arm) * 2, (r + arm) * 2);
String maxText = String.format("最高温度: %.1f", tempData.getMaxTemp());
String minText = String.format("最低温度: %.1f", tempData.getMinTemp());
labels.add(createLabel(maxText, maxX, maxY, fm, true, maxCrosshairRect));
labels.add(createLabel(minText, minX, minY, fm, true, minCrosshairRect));
log.info("最高温度: {}, 表格坐标: ({},{}), 图片坐标: ({},{})", tempData.getMaxTemp(), tempData.getMaxCol(), tempData.getMaxRow(), maxX, maxY);
log.info("最低温度: {}, 表格坐标: ({},{}), 图片坐标: ({},{})", tempData.getMinTemp(), tempData.getMinCol(), tempData.getMinRow(), minX, minY);
/**
* 画框并标注内部最高温最低温平均温
* TODO: 后续可拓展为多组画框需前端支持
*/
if (coordinates.size() > 0) {
// 暂时只标注第一组坐标
Coordinate coordinate = coordinates.get(0);
int[] points = coordinate.getPoints();
int coordinateWidth = coordinate.getWidth();
int coordinateHeight = coordinate.getHeight();
// 图片宽高 画框时图片宽高 比例
float rateX = (float) originalWidth / coordinateWidth;
float rateY = (float) originalHeight / coordinateHeight;
Polygon region = new Polygon();
for (int i = 0; i + 1 < points.length; i += 2) {
region.addPoint(Math.round(points[i] * rateX), Math.round(points[i + 1] * rateY));
}
double[][] vertices = shapeVertices(region);
double[] xs = new double[vertices.length];
double[] ys = new double[vertices.length];
int fx = coordinate.getFirstX();
int fy = coordinate.getFirstY();
int sx = coordinate.getSecondX();
int sy = coordinate.getSecondY();
int w = coordinate.getWidth();
int h = coordinate.getHeight();
float rateX = (float) outW / w;
float rateY = (float) outH / h;
int x1 = Math.round(fx * rateX);
int y1 = Math.round(fy * rateY);
int x2 = Math.round(sx * rateX);
int y2 = Math.round(sy * rateY);
int rx1 = Math.min(x1, x2), ry1 = Math.min(y1, y2);
int rx2 = Math.max(x1, x2), ry2 = Math.max(y1, y2);
int csvCol1 = Math.round(rx1 / scaleX), csvCol2 = Math.round((rx2 + scaleX - 1) / scaleX);
int csvRow1 = Math.round(ry1 / scaleY), csvRow2 = Math.round((ry2 + scaleY - 1) / scaleY);
// 统计框内温度
TemperatureDataService.RegionStats stats = tempData.calcRegion(csvRow1, csvRow2, csvCol1, csvCol2);
for (int i = 0; i < vertices.length; i++) {
xs[i] = vertices[i][0] / scaleX;
ys[i] = vertices[i][1] / scaleY;
}
g.setColor(Color.white);
g.setStroke(new BasicStroke(3));
g.drawRect(rx1, ry1, rx2 - rx1, ry2 - ry1);
g.draw(region);
String boxText = String.format("最高温度: %.1f 最低温度: %.1f 平均温度: %.1f", stats.getMax(), stats.getMin(), stats.getAvg());
// 用于文本避障
Rectangle occupied = new Rectangle(rx1, ry1, rx2 - rx1, ry2 - ry1);
TemperatureDataService.RegionStats stats = tempData.calcRegion(xs, ys);
labels.add(createLabel(boxText, rx1, ry1 - 5, fm, true, occupied));
java.awt.Rectangle bounds = region.getBounds();
String boxText = String.format("最高温度: %.1f 最低温度: %.1f 平均温度: %.1f", stats.getMax(), stats.getMin(), stats.getAvg());
labels.add(createLabel(boxText, bounds.x, bounds.y - 5, fm, true, bounds));
if (stats.getMaxRow() >= 0) {
int rMaxX = Math.round(stats.getMaxCol() * scaleX);
int rMaxY = Math.round(stats.getMaxRow() * scaleY);
int rMinX = Math.round(stats.getMinCol() * scaleX);
int rMinY = Math.round(stats.getMinRow() * scaleY);
drawDot(g, rMaxX, rMaxY, MAX_TEMP_COLOR);
drawDot(g, rMinX, rMinY, MIN_TEMP_COLOR);
}
infraredInfo.setFrameMax(stats.getMax());
infraredInfo.setFrameMin(stats.getMin());
@ -221,7 +236,7 @@ public class ImageAnnotationService {
int r = CROSSHAIR_R;
int arm = CROSSHAIR_ARM;
g.setColor(color);
g.setStroke(new BasicStroke(3));
g.setStroke(new BasicStroke(2));
g.drawLine(x - r - arm, y, x - r, y);
g.drawLine(x + r, y, x + r + arm, y);
g.drawLine(x, y - r - arm, x, y - r);
@ -229,6 +244,19 @@ public class ImageAnnotationService {
g.drawOval(x - r, y - r, r * 2, r * 2);
}
/**
* 实心点 + 白色描边圆环,用于标注最高/最低温度位置
*/
private void drawDot(Graphics2D g, int x, int y, Color color) {
int dotR = 3;
int ringR = 5;
g.setColor(Color.WHITE);
g.setStroke(new BasicStroke(2));
g.drawOval(x - ringR, y - ringR, ringR * 2, ringR * 2);
g.setColor(color);
g.fillOval(x - dotR, y - dotR, dotR * 2, dotR * 2);
}
/**
* 加载字体文件
*/


+ 45
- 14
src/main/java/com/inspect/simulator/service/TemperatureDataService.java View File

@ -43,32 +43,55 @@ public class TemperatureDataService {
}
}
public RegionStats calcRegion(int rowStart, int rowEnd, int colStart, int colEnd) {
public RegionStats calcRegion(double[] xs, double[] ys) {
if (xs == null || ys == null || xs.length != ys.length || xs.length < 3) {
return new RegionStats(0, 0, 0, -1, -1,-1,-1);
}
// Bounding box of the polygon, clamped to the CSV grid
double minX = Double.MAX_VALUE, maxX = -Double.MAX_VALUE;
double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE;
for (int i = 0; i < xs.length; i++) {
minX = Math.min(minX, xs[i]); maxX = Math.max(maxX, xs[i]);
minY = Math.min(minY, ys[i]); maxY = Math.max(maxY, ys[i]);
}
int r0 = Math.max(0, (int) Math.floor(minY));
int r1 = Math.min(rows, (int) Math.ceil(maxY));
int c0 = Math.max(0, (int) Math.floor(minX));
int c1 = Math.min(cols, (int) Math.ceil(maxX));
float min = Float.MAX_VALUE, max = Float.MIN_VALUE;
double sum = 0;
int count = 0;
int r0 = Math.max(0, rowStart), r1 = Math.min(rows, rowEnd);
int c0 = Math.max(0, colStart), c1 = Math.min(cols, colEnd);
int minR = -1, minC = -1, maxR = -1, maxC = -1;
for (int r = r0; r < r1; r++) {
for (int c = c0; c < c1; c++) {
if (!containsPoint(xs, ys, c + 0.5, r + 0.5)) continue;
float v = temperatures[r][c];
if (!Float.isNaN(v)) {
if (v < min) {
min = v;
}
if (v > max) {
max = v;
}
if (v < min) { min = v; minR = r; minC = c; }
if (v > max) { max = v; maxR = r; maxC = c; }
sum += v;
count++;
}
}
}
if (count == 0) {
return new RegionStats(0, 0, 0);
if (count == 0) return new RegionStats(0, 0, 0, -1, -1,-1,-1);
return new RegionStats(min, max, sum / count, minR, minC, maxR, maxC);
}
private static boolean containsPoint(double[] xs, double[] ys, double px, double py) {
boolean inside = false;
for (int i = 0, j = xs.length - 1; i < xs.length; j = i++) {
double yi = ys[i], yj = ys[j];
if ((yi > py) != (yj > py)) {
double xi = xs[i], xj = xs[j];
if (px < (xj - xi) * (py - yi) / (yj - yi) + xi) {
inside = !inside;
}
}
}
return new RegionStats(min, max, sum / count);
return inside;
}
@Getter
@ -76,11 +99,19 @@ public class TemperatureDataService {
private final float min;
private final float max;
private final double avg;
private final int minRow;
private final int minCol;
private final int maxRow;
private final int maxCol;
public RegionStats(float min, float max, double avg) {
public RegionStats(float min, float max, double avg, int minRow, int minCol, int maxRow, int maxCol) {
this.min = min;
this.max = max;
this.avg = avg;
this.minRow = minRow;
this.minCol = minCol;
this.maxRow = maxRow;
this.maxCol = maxCol;
}
}


+ 176
- 148
src/main/java/com/inspect/simulator/service/impl/HikVisionServiceImpl.java View File

@ -1,7 +1,6 @@
package com.inspect.simulator.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
@ -26,21 +25,6 @@ import com.inspect.simulator.tempCount.TempCount;
import com.inspect.simulator.utils.StringUtils;
import com.inspect.simulator.utils.redis.RedisService;
import com.inspect.simulator.utils.sftp.SftpClient;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import okhttp3.*;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.csv.CSVFormat;
@ -56,6 +40,24 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 海康威视测试服务类
*/
@ -99,6 +101,116 @@ public class HikVisionServiceImpl implements HikVisionService {
@Resource
private ImageAnnotationService annotationService;
//校验
public static byte[] locateAndReadInfraredData(byte[] fileData) {
// 文件末尾标识
final byte[] FOOTER_SIGN = {
(byte) 0x37, (byte) 0x66, (byte) 0x07, (byte) 0x1a,
(byte) 0x12, (byte) 0x3a, (byte) 0x4c, (byte) 0x9f,
(byte) 0xa9, (byte) 0x5d, (byte) 0x21, (byte) 0xd2,
(byte) 0xda, (byte) 0x7d, (byte) 0x26, (byte) 0xbc
};
try {
// 1. 检查数据大小
if (fileData.length < FOOTER_SIGN.length + 4) {
System.err.println("错误:数据太小");
return null;
}
// 2. 读取并验证文件尾标识
byte[] footer = new byte[FOOTER_SIGN.length];
// 从数组末尾读取FOOTER_SIGN
System.arraycopy(fileData, fileData.length - FOOTER_SIGN.length, footer, 0, FOOTER_SIGN.length);
if (!Arrays.equals(footer, FOOTER_SIGN)) {
System.err.println("错误:文件标识不匹配");
return null;
}
// 3. 读取偏移量小端序
byte[] offsetBytes = new byte[4];
// 读取FOOTER_SIGN前的4个字节作为偏移量
System.arraycopy(fileData, fileData.length - FOOTER_SIGN.length - 4, offsetBytes, 0, 4);
int dataOffset = ByteBuffer.wrap(offsetBytes)
.order(ByteOrder.LITTLE_ENDIAN)
.getInt();
// 4. 验证偏移量有效性
if (dataOffset < 0 || dataOffset >= fileData.length - FOOTER_SIGN.length - 4) {
System.err.println("错误:无效的偏移量");
return null;
}
// 5. 定位到偏移量处读取数据直到文件尾标识前
int dataLength = fileData.length - FOOTER_SIGN.length - 4 - dataOffset;
if (dataLength <= 0) {
System.err.println("错误:数据长度为0");
return null;
}
byte[] infraredData = new byte[dataLength];
System.arraycopy(fileData, dataOffset, infraredData, 0, dataLength);
return infraredData;
} catch (Exception e) {
System.err.println("处理错误: " + e.getMessage());
return null;
}
}
//二维数组转 CSV
private static String convertMatrixToCsv(float[][] matrix) {
StringBuilder csvBuilder = new StringBuilder();
for (float[] row : matrix) {
for (int i = 0; i < row.length; i++) {
csvBuilder.append(row[i]);
if (i < row.length - 1) {
csvBuilder.append(",");
}
}
csvBuilder.append("\n");
}
return csvBuilder.toString();
}
public static String truncateFileNameToCsv(String originalPath) {
// 获取文件名部分最后一个 '/' 之后的内容
int lastSlashIndex = originalPath.lastIndexOf('/');
if (lastSlashIndex == -1) {
// 如果没有路径分隔符直接处理整个字符串
return processFileNameToCsv(originalPath);
}
// 分离路径和文件名
String path = originalPath.substring(0, lastSlashIndex + 1);
String fileName = originalPath.substring(lastSlashIndex + 1);
// 处理文件名部分并强制改为.csv
String processedFileName = processFileNameToCsv(fileName);
return path + processedFileName;
}
private static String processFileNameToCsv(String fileName) {
// 去掉文件扩展名如果有
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex != -1) {
fileName = fileName.substring(0, lastDotIndex);
}
// 去掉最后一个 '_' 及其后面的部分
int lastUnderscoreIndex = fileName.lastIndexOf('_');
if (lastUnderscoreIndex != -1) {
fileName = fileName.substring(0, lastUnderscoreIndex);
}
// 强制添加.csv后缀
return fileName + ".csv";
}
@Override
public AjaxResult capturePicture(InfraPictureInfo infraPictureInfo) {
log.info("capturePicture, coordinate:{}", infraPictureInfo);
@ -281,78 +393,6 @@ public class HikVisionServiceImpl implements HikVisionService {
return infraredInfo;
}
//校验
public static byte[] locateAndReadInfraredData(byte[] fileData) {
// 文件末尾标识
final byte[] FOOTER_SIGN = {
(byte) 0x37, (byte) 0x66, (byte) 0x07, (byte) 0x1a,
(byte) 0x12, (byte) 0x3a, (byte) 0x4c, (byte) 0x9f,
(byte) 0xa9, (byte) 0x5d, (byte) 0x21, (byte) 0xd2,
(byte) 0xda, (byte) 0x7d, (byte) 0x26, (byte) 0xbc
};
try {
// 1. 检查数据大小
if (fileData.length < FOOTER_SIGN.length + 4) {
System.err.println("错误:数据太小");
return null;
}
// 2. 读取并验证文件尾标识
byte[] footer = new byte[FOOTER_SIGN.length];
// 从数组末尾读取FOOTER_SIGN
System.arraycopy(fileData, fileData.length - FOOTER_SIGN.length, footer, 0, FOOTER_SIGN.length);
if (!Arrays.equals(footer, FOOTER_SIGN)) {
System.err.println("错误:文件标识不匹配");
return null;
}
// 3. 读取偏移量小端序
byte[] offsetBytes = new byte[4];
// 读取FOOTER_SIGN前的4个字节作为偏移量
System.arraycopy(fileData, fileData.length - FOOTER_SIGN.length - 4, offsetBytes, 0, 4);
int dataOffset = ByteBuffer.wrap(offsetBytes)
.order(ByteOrder.LITTLE_ENDIAN)
.getInt();
// 4. 验证偏移量有效性
if (dataOffset < 0 || dataOffset >= fileData.length - FOOTER_SIGN.length - 4) {
System.err.println("错误:无效的偏移量");
return null;
}
// 5. 定位到偏移量处读取数据直到文件尾标识前
int dataLength = fileData.length - FOOTER_SIGN.length - 4 - dataOffset;
if (dataLength <= 0) {
System.err.println("错误:数据长度为0");
return null;
}
byte[] infraredData = new byte[dataLength];
System.arraycopy(fileData, dataOffset, infraredData, 0, dataLength);
return infraredData;
} catch (Exception e) {
System.err.println("处理错误: " + e.getMessage());
return null;
}
}
//二维数组转 CSV
private static String convertMatrixToCsv(float[][] matrix) {
StringBuilder csvBuilder = new StringBuilder();
for (float[] row : matrix) {
for (int i = 0; i < row.length; i++) {
csvBuilder.append(row[i]);
if (i < row.length - 1) {
csvBuilder.append(",");
}
}
csvBuilder.append("\n");
}
return csvBuilder.toString();
}
//调用华软接口获取csv文件
public float[][] UploadFtpImage(String url, String type, String image) {
log.info("imageName" + image);
@ -691,7 +731,8 @@ public class HikVisionServiceImpl implements HikVisionService {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignored) {}
} catch (IOException ignored) {
}
}
// 关闭FTP连接
@ -835,12 +876,26 @@ public class HikVisionServiceImpl implements HikVisionService {
if (picData != null) {
int[] parts = Arrays.stream(picData.split(",")).mapToInt(Integer::parseInt).toArray();
// 6个值分为左上角(x,y) 右下角(x,y) 图片高宽(h,w)
if (parts.length == 6) {
coordinates.add(new Coordinate(parts[0], parts[1], parts[2], parts[3], parts[5], parts[4]));
} else if (parts.length == 10) {
// 10个值分为左上角(x,y) 右上角(x,y) 右下角(x,y) 左下角(x,y) 图片宽高(w,h)
coordinates.add(new Coordinate(parts[0], parts[1], parts[4], parts[5], parts[8], parts[9]));
if (parts.length > 2) {
int last1 = parts[parts.length - 1];
int last2 = parts[parts.length - 2];
int width = Math.max(last1, last2);
int height = Math.min(last1, last2);
int[] points;
// 移动设备的矩形框只有6个值分为左上角(x,y) 右下角(x,y) 图片高宽(h,w)
if (parts.length == 6 && last1 > last2) {
points = new int[]{
parts[0], parts[1],
parts[2], parts[1],
parts[2], parts[3],
parts[0], parts[3]
};
} else {
points = new int[parts.length - 2];
System.arraycopy(parts, 0, points, 0, parts.length - 2);
}
coordinates.add(new Coordinate(points, width, height));
} else {
log.error("{} 点位画框数据异常,请检查!", basedataPatrolPoint.getPatrolPointId());
}
@ -860,32 +915,42 @@ public class HikVisionServiceImpl implements HikVisionService {
infraredInfo = readDataHw(imageBytes);
//绘制框选标识
imageAnnotation(infraPictureInfo, infraredInfo);
} catch (IOException e) {
log.error("error" + e);
}
} else if (AlgConstants.INFRA_CAMERA_REVERSE.equals(imageType)) {
//相机反算红外
// 相机反算红外优先DL/T664其次反算
InputStream inputStreamPath = downloadFtp(imagePath);
if (StringUtils.isNull(inputStreamPath)) {
log.error("inputStreamPath图片为空");
}
//调取实时测温温度
//传值相机 ip
TemperatureData temperatureData = TemperatureMeasurement(basedataPatrolPoint);
if (temperatureData != null) {
String minTemperature = temperatureData.getMinTemperature();
String maxTemperature = temperatureData.getMaxTemperature();
log.info("[INFRARED] 最高温度值:{}", maxTemperature);
log.info("[INFRARED] 最低温度值:{}", minTemperature);
float[][] matrix = tempCount.countTemp(inputStreamPath, Double.valueOf(maxTemperature), Double.valueOf(minTemperature));//最高值最低值
infraredInfo.setTemperatureMatrix(matrix);
try {
byte[] imageBytes = IOUtils.toByteArray(inputStreamPath);
inputStream.close();
// 1.判断是否为DL/T664
byte[] infraredData = locateAndReadInfraredData(imageBytes);
if (infraredData == null) {
InputStream reusableStream = new ByteArrayInputStream(imageBytes);
//调取实时测温温度
//传值相机 ip
TemperatureData temperatureData = TemperatureMeasurement(basedataPatrolPoint);
if (temperatureData != null) {
String minTemperature = temperatureData.getMinTemperature();
String maxTemperature = temperatureData.getMaxTemperature();
log.info("[INFRARED] 最高温度值:{}", maxTemperature);
log.info("[INFRARED] 最低温度值:{}", minTemperature);
float[][] matrix = tempCount.countTemp(reusableStream, Double.valueOf(maxTemperature), Double.valueOf(minTemperature));//最高值最低值
infraredInfo.setTemperatureMatrix(matrix);
}
} else {
infraredInfo = readDataHw(imageBytes);
}
imageAnnotation(infraPictureInfo, infraredInfo);
} catch (Exception e) {
log.error("error" + e);
}
imageAnnotation(infraPictureInfo, infraredInfo);
} else if (AlgConstants.INFRA_1800.equals(imageType)) {
//ivs1800红外图
imageAnnotation(infraPictureInfo, infraredInfo);
@ -1034,43 +1099,6 @@ public class HikVisionServiceImpl implements HikVisionService {
return inputStream;
}
public static String truncateFileNameToCsv(String originalPath) {
// 获取文件名部分最后一个 '/' 之后的内容
int lastSlashIndex = originalPath.lastIndexOf('/');
if (lastSlashIndex == -1) {
// 如果没有路径分隔符直接处理整个字符串
return processFileNameToCsv(originalPath);
}
// 分离路径和文件名
String path = originalPath.substring(0, lastSlashIndex + 1);
String fileName = originalPath.substring(lastSlashIndex + 1);
// 处理文件名部分并强制改为.csv
String processedFileName = processFileNameToCsv(fileName);
return path + processedFileName;
}
private static String processFileNameToCsv(String fileName) {
// 去掉文件扩展名如果有
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex != -1) {
fileName = fileName.substring(0, lastDotIndex);
}
// 去掉最后一个 '_' 及其后面的部分
int lastUnderscoreIndex = fileName.lastIndexOf('_');
if (lastUnderscoreIndex != -1) {
fileName = fileName.substring(0, lastUnderscoreIndex);
}
// 强制添加.csv后缀
return fileName + ".csv";
}
//解析获取csv文件温度--返回流文件
private InputStream getFtpFileAsStream(String csvUrl) throws IOException {


Loading…
Cancel
Save