获取yolo4的模型文件
yolov4.cfg yolov4.weights coco.names 复制代码
示例
public static void testYOLO(Mat image) throws IOException { String config = "E:/opencv4.4.0/age-and-gender-classification/yolo/yolov4.cfg"; String weights = "E:/opencv4.4.0/age-and-gender-classification/yolo/yolov4.weights"; String classesFile = "E:/opencv4.4.0/age-and-gender-classification/yolo/coco.names"; List<String> classes = new ArrayList<String>(); // 存放类别的列表 InputStream in = new FileInputStream(classesFile); int iAvail = in.available(); // 适用于本地一次读取多个字节时,返回得到的字节数。 byte[] bytes = new byte[iAvail]; in.read(bytes); String allContent = new String(bytes); // 文件中的所有内容 String[] tempContent = allContent.trim().split("\n"); // allContent去除首尾空格,再按换行符分割。 // 遍历tempContent,添加到保存类别名的列表classes里。 for (int i = 0; i < tempContent.length; i++) { classes.add(tempContent[i]); } System.out.println(classes.size()); Net net = Dnn.readNetFromDarknet(config, weights); net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV); // Don't understand command line argument "-cl-no-subgroup-ifp" // net.setPreferableTarget(Dnn.DNN_TARGET_OPENCL); // 改为cpu net.setPreferableTarget(Dnn.DNN_TARGET_CPU); Mat im = image.clone(); if (im.empty()) { System.out.println("图片加载失败"); } Size sz = new Size(416, 416); List<Mat> outs = new ArrayList<>(); Mat blob = Dnn.blobFromImage(image, 0.00392, sz, new Scalar(0), true, false); net.setInput(blob); net.forward(outs, getOutputNames(net)); float confThreshold = 0.8f; List<Rect2d> boxes = new ArrayList<Rect2d>(); // 矩形框列表 List<Integer> classIds = new ArrayList<Integer>(); // 类的序号列表 List<Float> confidences = new ArrayList<Float>(); // 置信度列表 for (int i = 0; i < outs.size(); ++i) { Mat level = outs.get(i); for (int j = 0; j < level.rows(); ++j) { Mat row = level.row(j); // [x,y,h,w,c,class1,class2] 所以是标号5 Mat scores = row.colRange(5, level.cols()); Core.MinMaxLocResult mm = Core.minMaxLoc(scores); float confidence = (float) mm.maxVal; Point classIdPoint = mm.maxLoc; int size = (int) (level.cols() * level.channels()); float[] data = new float[size]; level.get(j, 0, data); if (confidence > confThreshold) { float x = data[0]; // centerX 矩形中心点的X坐标 float y = data[1]; // centerY 矩形中心点的Y坐标 float width = data[2]; // 矩形框的宽 float height = data[3]; // 矩形框的高 float xLeftBottom = (x - width / 2) * im.cols(); // 矩形左下角点的X坐标 float yLeftBottom = (y - height / 2) * im.rows(); // 矩形左下角点的Y坐标 float xRightTop = (x + width / 2) * im.cols(); // 矩形右上角点的X坐标 float yRightTop = (y + height / 2) * im.rows(); // 矩形右上角点的Y坐标 // boxes列表填值 Rect对象,参数是两个点 boxes.add(new Rect2d(new Point(xLeftBottom, yLeftBottom), new Point(xRightTop, yRightTop))); confidences.add(confidence); classIds.add((int) classIdPoint.x); // Imgproc.rectangle(image, new Point(xLeftBottom, yLeftBottom), // new Point(xRightTop, yRightTop), new Scalar(255, 0, 0)); // Imgproc.putText(image, classes.get((int)classIdPoint.x)+" "+confidence, new Point(xLeftBottom, yLeftBottom),Imgproc.FONT_HERSHEY_PLAIN,0.8, new Scalar(255, 0, 0)); } } } System.out.println(classIds); System.out.println(confidences); System.out.println(boxes.size()); System.out.println(boxes); float nmsThresh = 0.5f; MatOfFloat confidences2 = new MatOfFloat(Converters.vector_float_to_Mat(confidences)); // Rect2d[] boxesArray = boxes.toArray(new Rect2d[0]); // MatOfRect boxes2 = new MatOfRect(boxesArray); MatOfRect2d m = new MatOfRect2d(); m.fromList(boxes); MatOfInt indices = new MatOfInt(); /** * NMS(Non Maximum Suppression),又名非极大值抑制 删除高度冗余的Rect2d */ Dnn.NMSBoxes(m, confidences2, confThreshold, nmsThresh, indices); // We draw the bounding boxes for objects // here// int[] ind = indices.toArray(); for (int i = 0; i < ind.length; ++i) { int index = ind[i]; Rect2d box = boxes.get(index); int idGuy = classIds.get(index); float conf = confidences.get(index); Imgproc.rectangle(image, box.tl(), box.br(), new Scalar(255, 0, 0)); Imgproc.putText(image, classes.get(idGuy) + " " + conf, box.tl(), Imgproc.FONT_HERSHEY_PLAIN, 0.8, new Scalar(255, 0, 0)); } HighGui.imshow("yolo", image); } 复制代码
效果
网络异常,图片无法展示
|
遇到问题
报错-cl-no-subgroup-ifp 修改为cpu net.setPreferableTarget(Dnn.DNN_TARGET_CPU); 复制代码
匹配模型过多 NMS(Non Maximum Suppression),又名非极大值抑制 删除高度冗余的Rect2d 复制代码
再NMS需要的是Rect2d 直接从Rect,修改为Rect2d即可