|
|
|
|
@ -664,7 +664,7 @@ public class ONNXServiceNew {
|
|
|
|
|
detection.setH(h);
|
|
|
|
|
detection.setConfidence(conf);
|
|
|
|
|
detection.setIndex(label);
|
|
|
|
|
detection.setName(config.getNames()[label]);
|
|
|
|
|
// detection.setName(config.getNames()[label]);
|
|
|
|
|
|
|
|
|
|
detections.add(detection);
|
|
|
|
|
}
|
|
|
|
|
@ -686,6 +686,437 @@ public class ONNXServiceNew {
|
|
|
|
|
return arg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* YOLO26 专用检测方法
|
|
|
|
|
* 处理 YOLO26 的两种输出格式:
|
|
|
|
|
* 1. [1, 300, 6]: NMS 后的输出,格式为 [x1, y1, x2, y2, conf, class_id]
|
|
|
|
|
* 2. [1, 84, 8400]: YOLOv8 原始输出,84 = 4(xywh) + 1(conf) + 79(classes)
|
|
|
|
|
*
|
|
|
|
|
* @param imagePath 输入图片路径
|
|
|
|
|
* @param type 模型类型
|
|
|
|
|
* @return 检测结果列表
|
|
|
|
|
* @throws OrtException
|
|
|
|
|
*/
|
|
|
|
|
public List<BoundingBox> detect26(String imagePath, String type) throws OrtException {
|
|
|
|
|
|
|
|
|
|
OrtSession session = getSession(type);
|
|
|
|
|
AppConfig.YoloModelConfig config = getConfig(type);
|
|
|
|
|
// 处理图像
|
|
|
|
|
float[] imageData = new float[0];
|
|
|
|
|
try {
|
|
|
|
|
imageData = processImageFromURL(imagePath, config.getImageSize());
|
|
|
|
|
} catch (IOException ex) {
|
|
|
|
|
log.error("处理图像时出错: {}", ex.getMessage(), ex);
|
|
|
|
|
return new ArrayList<>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建输入张量
|
|
|
|
|
long[] shape = new long[]{1, 3, config.getImageSize(), config.getImageSize()};
|
|
|
|
|
OnnxTensor inputTensor = null;
|
|
|
|
|
OrtSession.Result result = null;
|
|
|
|
|
try {
|
|
|
|
|
inputTensor = OnnxTensor.createTensor(environment, FloatBuffer.wrap(imageData), shape);
|
|
|
|
|
|
|
|
|
|
HashMap<String, OnnxTensor> stringOnnxTensorHashMap = new HashMap<>();
|
|
|
|
|
stringOnnxTensorHashMap.put(session.getInputInfo().keySet().iterator().next(), inputTensor);
|
|
|
|
|
|
|
|
|
|
// 执行推理
|
|
|
|
|
result = session.run(stringOnnxTensorHashMap);
|
|
|
|
|
|
|
|
|
|
log.info("YOLO26 输出数量: {}", result.size());
|
|
|
|
|
|
|
|
|
|
// 获取第一个输出(检测输出)
|
|
|
|
|
float[][][] detOutput = (float[][][]) result.get(0).getValue();
|
|
|
|
|
|
|
|
|
|
// 调试:打印输出维度
|
|
|
|
|
int batch = detOutput.length;
|
|
|
|
|
int dim1 = detOutput[0].length;
|
|
|
|
|
int dim2 = detOutput[0][0].length;
|
|
|
|
|
log.info("YOLO26 输出维度: [{}, {}, {}]", batch, dim1, dim2);
|
|
|
|
|
|
|
|
|
|
// 判断输出格式
|
|
|
|
|
// [1, 300, 6]: NMS 后的输出,格式为 [x1, y1, x2, y2, conf, class_id]
|
|
|
|
|
// [1, 84, 8400]: YOLOv8 原始输出格式
|
|
|
|
|
|
|
|
|
|
boolean isNMSOutput = (dim2 == 6); // 第三个维度是 6,说明是 NMS 后的输出
|
|
|
|
|
|
|
|
|
|
List<BoundingBox> detections = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
if (isNMSOutput) {
|
|
|
|
|
// [1, 300, 6] -> NMS 后的输出
|
|
|
|
|
// 格式: [x1, y1, x2, y2, conf, class_id]
|
|
|
|
|
log.info("检测到 NMS 后的输出格式 [1, {}, 6],直接解析", dim1);
|
|
|
|
|
|
|
|
|
|
// 获取原始图像尺寸,用于坐标转换
|
|
|
|
|
int originalWidth = 0;
|
|
|
|
|
int originalHeight = 0;
|
|
|
|
|
try {
|
|
|
|
|
File file = new File(imagePath);
|
|
|
|
|
BufferedImage originalImage = ImageIO.read(file);
|
|
|
|
|
if (originalImage != null) {
|
|
|
|
|
originalWidth = originalImage.getWidth();
|
|
|
|
|
originalHeight = originalImage.getHeight();
|
|
|
|
|
log.info("原始图像尺寸: {} x {}", originalWidth, originalHeight);
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
log.warn("无法读取原始图像尺寸: {}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int imageSize = config.getImageSize();
|
|
|
|
|
log.info("模型输入尺寸: {} x {}", imageSize, imageSize);
|
|
|
|
|
|
|
|
|
|
double scale = (originalWidth > 0 && originalHeight > 0)
|
|
|
|
|
? Math.min((double) imageSize / originalWidth, (double) imageSize / originalHeight)
|
|
|
|
|
: 1.0;
|
|
|
|
|
int scaledWidth = (int) (originalWidth * scale);
|
|
|
|
|
int scaledHeight = (int) (originalHeight * scale);
|
|
|
|
|
int offsetX = (imageSize - scaledWidth) / 2;
|
|
|
|
|
int offsetY = (imageSize - scaledHeight) / 2;
|
|
|
|
|
|
|
|
|
|
log.info("缩放参数: scale={}, scaledWidth={}, scaledHeight={}, offsetX={}, offsetY={}",
|
|
|
|
|
scale, scaledWidth, scaledHeight, offsetX, offsetY);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dim1; i++) {
|
|
|
|
|
float x1 = detOutput[0][i][0];
|
|
|
|
|
float y1 = detOutput[0][i][1];
|
|
|
|
|
float x2 = detOutput[0][i][2];
|
|
|
|
|
float y2 = detOutput[0][i][3];
|
|
|
|
|
float conf = detOutput[0][i][4];
|
|
|
|
|
int classId = (int) detOutput[0][i][5];
|
|
|
|
|
|
|
|
|
|
// 如果置信度为 0 或低于阈值,跳过(NMS 后的输出,空的框 conf 为 0)
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将检测框坐标从缩放后图像转换回原始图像
|
|
|
|
|
// 先减去偏移,再除以缩放比例
|
|
|
|
|
x1 = (float) ((x1 - offsetX) / scale);
|
|
|
|
|
y1 = (float) ((y1 - offsetY) / scale);
|
|
|
|
|
x2 = (float) ((x2 - offsetX) / scale);
|
|
|
|
|
y2 = (float) ((y2 - offsetY) / scale);
|
|
|
|
|
|
|
|
|
|
// xyxy -> xywh(YOLO 的 xywh 是左上角坐标 + 宽高)
|
|
|
|
|
float x = x1;
|
|
|
|
|
float y = y1;
|
|
|
|
|
float w = x2 - x1;
|
|
|
|
|
float h = y2 - y1;
|
|
|
|
|
|
|
|
|
|
BoundingBox box = new BoundingBox();
|
|
|
|
|
box.setX(x);
|
|
|
|
|
box.setY(y);
|
|
|
|
|
box.setW(w);
|
|
|
|
|
box.setH(h);
|
|
|
|
|
box.setConfidence(conf);
|
|
|
|
|
box.setIndex(classId);
|
|
|
|
|
if (classId < config.getNames().length) {
|
|
|
|
|
box.setName(config.getNames()[classId]);
|
|
|
|
|
}
|
|
|
|
|
detections.add(box);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// YOLOv8 原始输出格式 [1, 84, 8400]
|
|
|
|
|
// 需要 transpose(1, 0) 变成 [8400, 84]
|
|
|
|
|
boolean isYOLOv8Format = (dim1 > dim2);
|
|
|
|
|
|
|
|
|
|
// 获取原始图像尺寸,用于坐标转换
|
|
|
|
|
int originalWidth = 0;
|
|
|
|
|
int originalHeight = 0;
|
|
|
|
|
try {
|
|
|
|
|
File file = new File(imagePath);
|
|
|
|
|
BufferedImage originalImage = ImageIO.read(file);
|
|
|
|
|
if (originalImage != null) {
|
|
|
|
|
originalWidth = originalImage.getWidth();
|
|
|
|
|
originalHeight = originalImage.getHeight();
|
|
|
|
|
log.info("原始图像尺寸: {} x {}", originalWidth, originalHeight);
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
log.warn("无法读取原始图像尺寸: {}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int imageSize = config.getImageSize();
|
|
|
|
|
double scale = (originalWidth > 0 && originalHeight > 0)
|
|
|
|
|
? Math.min((double) imageSize / originalWidth, (double) imageSize / originalHeight)
|
|
|
|
|
: 1.0;
|
|
|
|
|
int scaledWidth = (int) (originalWidth * scale);
|
|
|
|
|
int scaledHeight = (int) (originalHeight * scale);
|
|
|
|
|
int offsetX = (imageSize - scaledWidth) / 2;
|
|
|
|
|
int offsetY = (imageSize - scaledHeight) / 2;
|
|
|
|
|
|
|
|
|
|
int numPredictions, numFeatures;
|
|
|
|
|
|
|
|
|
|
if (isYOLOv8Format) {
|
|
|
|
|
// [1, 84, 8400] -> 需要转置
|
|
|
|
|
numPredictions = dim2; // 8400
|
|
|
|
|
numFeatures = dim1; // 84
|
|
|
|
|
log.info("检测到 YOLOv8 格式 [1, {}, {}],转置后 [8400, {}]", dim1, dim2, numFeatures);
|
|
|
|
|
} else {
|
|
|
|
|
// [1, 8400, 84]
|
|
|
|
|
numPredictions = dim1; // 8400
|
|
|
|
|
numFeatures = dim2; // 84
|
|
|
|
|
log.info("检测到标准格式 [1, {}, {}]", dim1, dim2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("预测框数量: {}, 特征数: {}", numPredictions, numFeatures);
|
|
|
|
|
|
|
|
|
|
// 解析每个预测框
|
|
|
|
|
for (int i = 0; i < numPredictions; i++) {
|
|
|
|
|
float x, y, w, h, conf;
|
|
|
|
|
|
|
|
|
|
if (isYOLOv8Format) {
|
|
|
|
|
// detOutput[0] 是 [84, 8400]
|
|
|
|
|
// 格式: [x, y, w, h, conf, class_scores...]
|
|
|
|
|
|
|
|
|
|
x = detOutput[0][0][i];
|
|
|
|
|
y = detOutput[0][1][i];
|
|
|
|
|
w = detOutput[0][2][i];
|
|
|
|
|
h = detOutput[0][3][i];
|
|
|
|
|
conf = detOutput[0][4][i];
|
|
|
|
|
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将检测框坐标从缩放后图像转换回原始图像
|
|
|
|
|
// YOLOv8 的 xywh 是中心点坐标,需要转换为左上角坐标
|
|
|
|
|
// 然后减去偏移,再除以缩放比例
|
|
|
|
|
x = (float) ((x - w / 2 - offsetX) / scale);
|
|
|
|
|
y = (float) ((y - h / 2 - offsetY) / scale);
|
|
|
|
|
w = (float) (w / scale);
|
|
|
|
|
h = (float) (h / scale);
|
|
|
|
|
|
|
|
|
|
float[] clsScores = new float[numFeatures - 5];
|
|
|
|
|
for (int j = 0; j < clsScores.length; j++) {
|
|
|
|
|
clsScores[j] = detOutput[0][5 + j][i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int classId = argmax(clsScores, 0.0f);
|
|
|
|
|
|
|
|
|
|
if (classId != -1) {
|
|
|
|
|
BoundingBox box = new BoundingBox();
|
|
|
|
|
box.setX(x);
|
|
|
|
|
box.setY(y);
|
|
|
|
|
box.setW(w);
|
|
|
|
|
box.setH(h);
|
|
|
|
|
box.setConfidence(conf);
|
|
|
|
|
box.setIndex(classId);
|
|
|
|
|
if (classId < config.getNames().length) {
|
|
|
|
|
box.setName(config.getNames()[classId]);
|
|
|
|
|
}
|
|
|
|
|
detections.add(box);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// detOutput[0] 是 [8400, 84]
|
|
|
|
|
x = detOutput[0][i][0];
|
|
|
|
|
y = detOutput[0][i][1];
|
|
|
|
|
w = detOutput[0][i][2];
|
|
|
|
|
h = detOutput[0][i][3];
|
|
|
|
|
conf = detOutput[0][i][4];
|
|
|
|
|
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将检测框坐标从缩放后图像转换回原始图像
|
|
|
|
|
// YOLOv8 的 xywh 是中心点坐标,需要转换为左上角坐标
|
|
|
|
|
// 然后减去偏移,再除以缩放比例
|
|
|
|
|
x = (float) ((x - w / 2 - offsetX) / scale);
|
|
|
|
|
y = (float) ((y - h / 2 - offsetY) / scale);
|
|
|
|
|
w = (float) (w / scale);
|
|
|
|
|
h = (float) (h / scale);
|
|
|
|
|
|
|
|
|
|
float[] clsScores = new float[numFeatures - 5];
|
|
|
|
|
for (int j = 0; j < clsScores.length; j++) {
|
|
|
|
|
clsScores[j] = detOutput[0][i][5 + j];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int classId = argmax(clsScores, 0.0f);
|
|
|
|
|
|
|
|
|
|
if (classId != -1) {
|
|
|
|
|
BoundingBox box = new BoundingBox();
|
|
|
|
|
box.setX(x);
|
|
|
|
|
box.setY(y);
|
|
|
|
|
box.setW(w);
|
|
|
|
|
box.setH(h);
|
|
|
|
|
box.setConfidence(conf);
|
|
|
|
|
box.setIndex(classId);
|
|
|
|
|
if (classId < config.getNames().length) {
|
|
|
|
|
box.setName(config.getNames()[classId]);
|
|
|
|
|
}
|
|
|
|
|
detections.add(box);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NMS 过滤
|
|
|
|
|
List<BoundingBox> filteredDetections = nonMaxSuppression(detections, 0.5f);
|
|
|
|
|
|
|
|
|
|
log.info("YOLO26 检测结果: {} 个", filteredDetections.size());
|
|
|
|
|
return filteredDetections;
|
|
|
|
|
} finally {
|
|
|
|
|
if (inputTensor != null) {
|
|
|
|
|
inputTensor.close();
|
|
|
|
|
}
|
|
|
|
|
if (result != null) {
|
|
|
|
|
result.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* YOLO26 专用分类方法
|
|
|
|
|
* 处理 YOLO26 的两种输出格式:
|
|
|
|
|
* 1. [1, 300, 6]: NMS 后的输出,格式为 [x1, y1, x2, y2, conf, class_id]
|
|
|
|
|
* 2. [1, 84, 8400]: YOLOv8 原始输出,84 = 4(xywh) + 1(conf) + 79(classes)
|
|
|
|
|
*
|
|
|
|
|
* @param imagePath 输入图片路径
|
|
|
|
|
* @param type 模型类型
|
|
|
|
|
* @return 分类结果
|
|
|
|
|
* @throws OrtException
|
|
|
|
|
*/
|
|
|
|
|
public ClassifyEntity classify26(String imagePath, String type) throws OrtException {
|
|
|
|
|
|
|
|
|
|
OrtSession session = getSession(type);
|
|
|
|
|
AppConfig.YoloModelConfig config = getConfig(type);
|
|
|
|
|
// 处理图像
|
|
|
|
|
float[] imageData = new float[0];
|
|
|
|
|
try {
|
|
|
|
|
imageData = processImageFromURL(imagePath, config.getImageSize());
|
|
|
|
|
} catch (IOException ex) {
|
|
|
|
|
log.error("处理图像时出错: {}", ex.getMessage(), ex);
|
|
|
|
|
ClassifyEntity errorResult = new ClassifyEntity();
|
|
|
|
|
errorResult.setName("Unknown");
|
|
|
|
|
return errorResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建输入张量
|
|
|
|
|
long[] shape = new long[]{1, 3, config.getImageSize(), config.getImageSize()};
|
|
|
|
|
OnnxTensor inputTensor = null;
|
|
|
|
|
OrtSession.Result result = null;
|
|
|
|
|
try {
|
|
|
|
|
inputTensor = OnnxTensor.createTensor(environment, FloatBuffer.wrap(imageData), shape);
|
|
|
|
|
|
|
|
|
|
HashMap<String, OnnxTensor> stringOnnxTensorHashMap = new HashMap<>();
|
|
|
|
|
stringOnnxTensorHashMap.put(session.getInputInfo().keySet().iterator().next(), inputTensor);
|
|
|
|
|
|
|
|
|
|
// 执行推理
|
|
|
|
|
result = session.run(stringOnnxTensorHashMap);
|
|
|
|
|
|
|
|
|
|
log.info("YOLO26 输出数量: {}", result.size());
|
|
|
|
|
|
|
|
|
|
// YOLO26 第一个输出是检测输出
|
|
|
|
|
float[][][] detOutput = (float[][][]) result.get(0).getValue();
|
|
|
|
|
|
|
|
|
|
// 判断输出格式
|
|
|
|
|
int dim1 = detOutput[0].length;
|
|
|
|
|
int dim2 = detOutput[0][0].length;
|
|
|
|
|
boolean isNMSOutput = (dim2 == 6); // NMS 后的输出
|
|
|
|
|
|
|
|
|
|
float bestConfidence = -Float.MAX_VALUE;
|
|
|
|
|
int bestClassId = -1;
|
|
|
|
|
|
|
|
|
|
if (isNMSOutput) {
|
|
|
|
|
// [1, 300, 6] -> NMS 后的输出,格式为 [x1, y1, x2, y2, conf, class_id]
|
|
|
|
|
log.info("YOLO26 分类检测到 NMS 后的输出格式 [1, {}, 6]", dim1);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < dim1; i++) {
|
|
|
|
|
float conf = detOutput[0][i][4];
|
|
|
|
|
int classId = (int) detOutput[0][i][5];
|
|
|
|
|
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (conf > bestConfidence) {
|
|
|
|
|
bestConfidence = conf;
|
|
|
|
|
bestClassId = classId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// YOLOv8 原始输出格式
|
|
|
|
|
boolean isYOLOv8Format = (dim1 > dim2);
|
|
|
|
|
int numPredictions = isYOLOv8Format ? dim2 : dim1;
|
|
|
|
|
int numFeatures = isYOLOv8Format ? dim1 : dim2;
|
|
|
|
|
|
|
|
|
|
log.info("YOLO26 分类预测框数量: {}, 特征数: {}, YOLOv8格式: {}",
|
|
|
|
|
numPredictions, numFeatures, isYOLOv8Format);
|
|
|
|
|
|
|
|
|
|
// 找到置信度最高的类别
|
|
|
|
|
for (int i = 0; i < numPredictions; i++) {
|
|
|
|
|
float conf;
|
|
|
|
|
int classId;
|
|
|
|
|
float[] clsScores;
|
|
|
|
|
|
|
|
|
|
if (isYOLOv8Format) {
|
|
|
|
|
// detOutput[0] 是 [84, 8400]
|
|
|
|
|
conf = detOutput[0][4][i];
|
|
|
|
|
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取类别分数
|
|
|
|
|
clsScores = new float[numFeatures - 5];
|
|
|
|
|
for (int j = 0; j < clsScores.length; j++) {
|
|
|
|
|
clsScores[j] = detOutput[0][5 + j][i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
classId = argmax(clsScores, 0.0f);
|
|
|
|
|
float classScore = clsScores[classId];
|
|
|
|
|
|
|
|
|
|
if (classScore > bestConfidence) {
|
|
|
|
|
bestConfidence = classScore;
|
|
|
|
|
bestClassId = classId;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// detOutput[0] 是 [8400, 84]
|
|
|
|
|
conf = detOutput[0][i][4];
|
|
|
|
|
|
|
|
|
|
if (conf < config.getConfThreshold()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clsScores = new float[numFeatures - 5];
|
|
|
|
|
for (int j = 0; j < clsScores.length; j++) {
|
|
|
|
|
clsScores[j] = detOutput[0][i][5 + j];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
classId = argmax(clsScores, 0.0f);
|
|
|
|
|
float classScore = clsScores[classId];
|
|
|
|
|
|
|
|
|
|
if (classScore > bestConfidence) {
|
|
|
|
|
bestConfidence = classScore;
|
|
|
|
|
bestClassId = classId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClassifyEntity classifyEntity = new ClassifyEntity();
|
|
|
|
|
classifyEntity.setIndex(bestClassId);
|
|
|
|
|
|
|
|
|
|
if (bestClassId != -1 && bestClassId < config.getNames().length) {
|
|
|
|
|
String className = config.getNames()[bestClassId];
|
|
|
|
|
classifyEntity.setName(className);
|
|
|
|
|
classifyEntity.setConfidence(bestConfidence);
|
|
|
|
|
log.info("YOLO26 识别模版:{},置信度:{}", className, bestConfidence);
|
|
|
|
|
} else {
|
|
|
|
|
log.info("YOLO26 未识别到模版");
|
|
|
|
|
classifyEntity.setName("Unknown");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return classifyEntity;
|
|
|
|
|
} finally {
|
|
|
|
|
if (inputTensor != null) {
|
|
|
|
|
inputTensor.close();
|
|
|
|
|
}
|
|
|
|
|
if (result != null) {
|
|
|
|
|
result.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 销毁时清理资源
|
|
|
|
|
*/
|
|
|
|
|
|