修改为openvivn
This commit is contained in:
@@ -5,21 +5,14 @@ import org.bytedeco.javacpp.indexer.FloatRawIndexer;
|
|||||||
import org.bytedeco.opencv.opencv_core.*;
|
import org.bytedeco.opencv.opencv_core.*;
|
||||||
import org.bytedeco.opencv.opencv_dnn.Net;
|
import org.bytedeco.opencv.opencv_dnn.Net;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.*;
|
||||||
import java.nio.file.Path;
|
import java.util.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.bytedeco.opencv.global.opencv_core.*;
|
import static org.bytedeco.opencv.global.opencv_dnn.*; // DNN API(readNetFromModelOptimizer / blobFromImage 等)
|
||||||
import static org.bytedeco.opencv.global.opencv_dnn.*;
|
import static org.bytedeco.opencv.global.opencv_core.*; // Mat/Size/Scalar/transpose 等
|
||||||
import static org.bytedeco.opencv.global.opencv_imgproc.*;
|
import static org.bytedeco.opencv.global.opencv_imgproc.*; // cvtColor 等
|
||||||
|
|
||||||
/**
|
public final class OpenVinoYoloDetector implements YoloDetector {
|
||||||
* 纯 OpenCV CPU 后端的 YOLO IR 检测器(.xml/.bin)
|
|
||||||
* 与原 OpenVinoYoloDetector 代码保持一致,只是固定:DNN_BACKEND_OPENCV + DNN_TARGET_CPU。
|
|
||||||
*/
|
|
||||||
public final class OpenCvYoloDetector implements YoloDetector {
|
|
||||||
private final String modelName;
|
private final String modelName;
|
||||||
private final Net net;
|
private final Net net;
|
||||||
private final Size input;
|
private final Size input;
|
||||||
@@ -27,15 +20,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
private final String[] classes;
|
private final String[] classes;
|
||||||
private final int colorBGR;
|
private final int colorBGR;
|
||||||
|
|
||||||
/**
|
public OpenVinoYoloDetector(String name, Path dir, int inW, int inH, String backend, int colorBGR) throws Exception {
|
||||||
* @param name 模型别名
|
|
||||||
* @param dir 模型目录(含 model.xml / model.bin / classes.txt)
|
|
||||||
* @param inW 推理输入宽
|
|
||||||
* @param inH 推理输入高
|
|
||||||
* @param backend 兼容参数,忽略(统一使用 OpenCV CPU)
|
|
||||||
* @param colorBGR 画框颜色(BGR packed int)
|
|
||||||
*/
|
|
||||||
public OpenCvYoloDetector(String name, Path dir, int inW, int inH, String backend, int colorBGR) throws Exception {
|
|
||||||
this.modelName = name;
|
this.modelName = name;
|
||||||
this.input = new Size(inW, inH);
|
this.input = new Size(inW, inH);
|
||||||
this.colorBGR = colorBGR;
|
this.colorBGR = colorBGR;
|
||||||
@@ -45,18 +30,26 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
|
|
||||||
Path clsPath = dir.resolve("classes.txt");
|
Path clsPath = dir.resolve("classes.txt");
|
||||||
if (Files.exists(clsPath)) {
|
if (Files.exists(clsPath)) {
|
||||||
this.classes = Files.readAllLines(clsPath).stream()
|
this.classes = Files.readAllLines(clsPath).stream().map(String::trim)
|
||||||
.map(String::trim).filter(s -> !s.isEmpty())
|
.filter(s -> !s.isEmpty()).toArray(String[]::new);
|
||||||
.toArray(String[]::new);
|
|
||||||
} else {
|
} else {
|
||||||
this.classes = new String[0];
|
this.classes = new String[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.net = readNetFromModelOptimizer(xml, bin);
|
this.net = readNetFromModelOptimizer(xml, bin);
|
||||||
|
|
||||||
// ✅ 固定使用 OpenCV CPU 后端(不再尝试 OpenVINO)
|
boolean set = false;
|
||||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
if ("openvino".equalsIgnoreCase(backend)) {
|
||||||
net.setPreferableTarget(DNN_TARGET_CPU);
|
try {
|
||||||
|
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
|
||||||
|
net.setPreferableTarget(DNN_TARGET_CPU);
|
||||||
|
set = true;
|
||||||
|
} catch (Throwable ignore) { /* 回退 */ }
|
||||||
|
}
|
||||||
|
if (!set) {
|
||||||
|
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||||
|
net.setPreferableTarget(DNN_TARGET_CPU);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String name() { return modelName; }
|
@Override public String name() { return modelName; }
|
||||||
@@ -65,7 +58,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
public List<Detection> detect(Mat bgr) {
|
public List<Detection> detect(Mat bgr) {
|
||||||
if (bgr == null || bgr.empty()) return Collections.emptyList();
|
if (bgr == null || bgr.empty()) return Collections.emptyList();
|
||||||
|
|
||||||
// 保证 BGR 3通道
|
// 统一成 BGR 3 通道,避免 blobFromImage 断言失败
|
||||||
if (bgr.channels() != 3) {
|
if (bgr.channels() != 3) {
|
||||||
Mat tmp = new Mat();
|
Mat tmp = new Mat();
|
||||||
if (bgr.channels() == 1) cvtColor(bgr, tmp, COLOR_GRAY2BGR);
|
if (bgr.channels() == 1) cvtColor(bgr, tmp, COLOR_GRAY2BGR);
|
||||||
@@ -76,19 +69,23 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
|
|
||||||
try (Mat blob = blobFromImage(bgr, 1.0/255.0, input, new Scalar(0.0), true, false, CV_32F)) {
|
try (Mat blob = blobFromImage(bgr, 1.0/255.0, input, new Scalar(0.0), true, false, CV_32F)) {
|
||||||
net.setInput(blob);
|
net.setInput(blob);
|
||||||
|
// ===== 多输出兼容(Bytedeco 正确写法)=====
|
||||||
// 兼容单/多输出
|
|
||||||
org.bytedeco.opencv.opencv_core.StringVector outNames = net.getUnconnectedOutLayersNames();
|
org.bytedeco.opencv.opencv_core.StringVector outNames = net.getUnconnectedOutLayersNames();
|
||||||
List<Mat> outs = new ArrayList<>();
|
List<Mat> outs = new ArrayList<>();
|
||||||
|
|
||||||
if (outNames == null || outNames.size() == 0) {
|
if (outNames == null || outNames.size() == 0) {
|
||||||
Mat out = net.forward();
|
// 只有一个默认输出
|
||||||
|
Mat out = net.forward(); // ← 直接返回 Mat
|
||||||
outs.add(out);
|
outs.add(out);
|
||||||
} else {
|
} else {
|
||||||
|
// 多输出:用 MatVector 承接
|
||||||
org.bytedeco.opencv.opencv_core.MatVector outBlobs =
|
org.bytedeco.opencv.opencv_core.MatVector outBlobs =
|
||||||
new org.bytedeco.opencv.opencv_core.MatVector(outNames.size());
|
new org.bytedeco.opencv.opencv_core.MatVector(outNames.size());
|
||||||
net.forward(outBlobs, outNames);
|
net.forward(outBlobs, outNames); // ← 正确的重载
|
||||||
for (long i = 0; i < outBlobs.size(); i++) outs.add(outBlobs.get(i));
|
|
||||||
|
for (long i = 0; i < outBlobs.size(); i++) {
|
||||||
|
outs.add(outBlobs.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int fw = bgr.cols(), fh = bgr.rows();
|
int fw = bgr.cols(), fh = bgr.rows();
|
||||||
@@ -101,6 +98,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
}
|
}
|
||||||
if (boxes.isEmpty()) return Collections.emptyList();
|
if (boxes.isEmpty()) return Collections.emptyList();
|
||||||
|
|
||||||
|
// 纯 Java NMS,避免 MatOf* / Vector API 兼容问题
|
||||||
List<Integer> keep = nmsIndices(boxes, scores, nmsTh);
|
List<Integer> keep = nmsIndices(boxes, scores, nmsTh);
|
||||||
|
|
||||||
List<Detection> result = new ArrayList<>(keep.size());
|
List<Detection> result = new ArrayList<>(keep.size());
|
||||||
@@ -113,6 +111,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
// 单帧失败不影响整体
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +123,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
Mat m;
|
Mat m;
|
||||||
|
|
||||||
if (dims == 2) {
|
if (dims == 2) {
|
||||||
|
// NxC 或 CxN
|
||||||
if (out.cols() >= 6) {
|
if (out.cols() >= 6) {
|
||||||
m = out;
|
m = out;
|
||||||
} else {
|
} else {
|
||||||
@@ -132,6 +132,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
m = tmp;
|
m = tmp;
|
||||||
}
|
}
|
||||||
} else if (dims == 3) {
|
} else if (dims == 3) {
|
||||||
|
// [1,N,C] 或 [1,C,N]
|
||||||
if (out.size(2) >= 6) {
|
if (out.size(2) >= 6) {
|
||||||
m = out.reshape(1, out.size(1)); // -> N×C
|
m = out.reshape(1, out.size(1)); // -> N×C
|
||||||
} else {
|
} else {
|
||||||
@@ -141,6 +142,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
m = tmp;
|
m = tmp;
|
||||||
}
|
}
|
||||||
} else if (dims == 4) {
|
} else if (dims == 4) {
|
||||||
|
// [1,1,N,C] 或 [1,1,C,N]
|
||||||
int a = out.size(2), b = out.size(3);
|
int a = out.size(2), b = out.size(3);
|
||||||
if (b >= 6) {
|
if (b >= 6) {
|
||||||
m = out.reshape(1, a).clone(); // -> N×C
|
m = out.reshape(1, a).clone(); // -> N×C
|
||||||
@@ -151,7 +153,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
m = tmp.clone();
|
m = tmp.clone();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return; // 不支持的形状
|
||||||
}
|
}
|
||||||
|
|
||||||
int N = m.rows(), C = m.cols();
|
int N = m.rows(), C = m.cols();
|
||||||
@@ -170,7 +172,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
float conf = obj * bestScore;
|
float conf = obj * bestScore;
|
||||||
if (conf < confTh) continue;
|
if (conf < confTh) continue;
|
||||||
|
|
||||||
// 假定 (cx,cy,w,h) 为归一化中心点格式;如是 x1,y1,x2,y2,请按需改这里
|
// 默认假设归一化中心点格式 (cx,cy,w,h);若你的 IR 是 x1,y1,x2,y2,请把这里换算改掉
|
||||||
int bx = Math.max(0, Math.round(cx * fw - (w * fw) / 2f));
|
int bx = Math.max(0, Math.round(cx * fw - (w * fw) / 2f));
|
||||||
int by = Math.max(0, Math.round(cy * fh - (h * fh) / 2f));
|
int by = Math.max(0, Math.round(cy * fh - (h * fh) / 2f));
|
||||||
int bw = Math.min(fw - bx, Math.round(w * fw));
|
int bw = Math.min(fw - bx, Math.round(w * fw));
|
||||||
@@ -187,6 +189,7 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
private List<Integer> nmsIndices(List<Rect2d> boxes, List<Float> scores, float nmsThreshold) {
|
private List<Integer> nmsIndices(List<Rect2d> boxes, List<Float> scores, float nmsThreshold) {
|
||||||
List<Integer> order = new ArrayList<>(boxes.size());
|
List<Integer> order = new ArrayList<>(boxes.size());
|
||||||
for (int i = 0; i < boxes.size(); i++) order.add(i);
|
for (int i = 0; i < boxes.size(); i++) order.add(i);
|
||||||
|
// 按分数降序
|
||||||
order.sort((i, j) -> Float.compare(scores.get(j), scores.get(i)));
|
order.sort((i, j) -> Float.compare(scores.get(j), scores.get(i)));
|
||||||
|
|
||||||
List<Integer> keep = new ArrayList<>();
|
List<Integer> keep = new ArrayList<>();
|
||||||
@@ -224,4 +227,4 @@ public final class OpenCvYoloDetector implements YoloDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public void close(){ net.close(); }
|
@Override public void close(){ net.close(); }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user