微信公众号:OpenCV学堂
关注获取更多计算机视觉与深度学习知识
前言
OpenCV DNN人脸检测
OpenCV4.8 Java SDK实现YOLOv5模型部署
https://gitee.com/opencv_ai/opencv_tutorial_data/tree/master/models
1x1xNx7
[batchId, classId, confidence, left, top, right, bottom]
代码实现与演示
public static void main(String[] args) {
String model_file = "D:/projects/opencv_face_detector_uint8.pb";
String pb_txt_file = "D:/projects/opencv_face_detector.pbtxt";
System.load("D:/opencv-4.8.0/opencv/build/java/x64/opencv_java480.dll");
System.out.println("start to read image...");
Mat inputImage = Imgcodecs.imread("D:/images/mmc.png");
JavaFaceDetection face_detector = new JavaFaceDetection(model_file, pb_txt_file, 0.5f);
face_detector.infer_image(inputImage);
HighGui.imshow("OpenCV Java 深度学习人脸检测演示", inputImage);
HighGui.waitKey(0);
VideoCapture capture = new VideoCapture();
capture.open(0);
while(true) {
Mat frame = new Mat();
boolean ret = capture.read(frame);
Core.flip(frame, frame, 1);
if(ret) {
face_detector.infer_image(frame);
HighGui.imshow("OpenCV Java 深度学习人脸检测演示", frame);
int c = HighGui.waitKey(1);
if (c == 27) {
break;
}
}
}
HighGui.destroyAllWindows();
System.exit(0);
}
import com.sun.jna.Pointer;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.dnn.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;
public class JavaFaceDetection {
public Net getNet() {
return net;
}
public void setNet(Net net) {
this.net = net;
}
private Net net;
private float score_t = 0.5f;
public JavaFaceDetection(String model_path, String pb_txt_file, float conf) {
this.score_t = conf;
this.net = Dnn.readNetFromTensorflow(model_path, pb_txt_file);
}
public void infer_image(Mat frame) {
long stime = System.currentTimeMillis();
// 推理
Mat blob = Dnn.blobFromImage(frame, 1.0, new Size(300, 300), new Scalar(104.0, 177.0, 123.0), false, false);
this.net.setInput(blob);
Mat probs = this.net.forward();
// 1x1xNx7
int rows = probs.size(2);
int cols = probs.size(3);
float[] result = new Pointer(probs.dataAddr()).getFloatArray(0, rows*cols);
probs.get(0, 0, result);
Mat detectOut = new Mat(rows, cols, CvType.CV_32F);
detectOut.put(0, 0, result);
for (int row = 0; row < detectOut.rows(); row++) {
float conf = (float)detectOut.get(row, 2)[0];
if (conf > this.score_t) {
float x1 = (float)(detectOut.get(row, 3)[0] * frame.cols());
float y1 = (float)(detectOut.get(row, 4)[0] * frame.rows());
float x2 = (float)(detectOut.get(row, 5)[0] * frame.cols());
float y2 = (float)(detectOut.get(row, 6)[0] * frame.rows());
Rect2d box = new Rect2d();
box.x = x1;
box.y = y1;
box.width = x2 - x1;
box.height = y2 - y1;
Rect rect = new Rect((int) box.x, (int) box.y, (int) box.width, (int) box.height);
Imgproc.rectangle(frame, rect, new Scalar(0,0, 255), 2, 8);
Imgproc.putText(frame, String.format("%.2f", conf), new Point(rect.x, rect.y-5), Imgproc.FONT_HERSHEY_COMPLEX, 0.5, new Scalar(255, 0, 255), 1, 8);
}
}
long end_time = System.currentTimeMillis();
float fps = 1000.0f / (end_time - stime);
Imgproc.putText(frame, String.format("FPS: %.2f", fps), new Point(30, 30), Imgproc.FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255), 2, 8);
}
}
其中最关键的是如何把推理输出得到四维Tensor张量 1x1xNx7 转换为 一个2D的Mat对象,这个就是各种大语言模型胡编乱造的地方,其实只有用JNA通过JNI接口访问本地C++地址获取推理以后的浮点数数组,然后重新构建一个2D Mat对象即可。解决这个问题其它代码基本是C++版本的Java语言翻译,容易了。
推荐阅读
OpenCV4.8+YOLOv8对象检测C++推理演示
ZXING+OpenCV打造开源条码检测应用
总结 | OpenCV4 Mat操作全接触
三行代码实现 TensorRT8.6 C++ 深度学习模型部署
实战 | YOLOv8+OpenCV 实现DM码定位检测与解析
对象检测边界框损失 – 从IOU到ProbIOU
YOLOv8 OBB实现自定义旋转对象检测
初学者必看 | 学习深度学习的五个误区
YOLOv8自定义数据集训练实现安全帽检测