获取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")
// 遍历tempContent,添加到保存类别名的列表classes里。
for (int i = 0
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
Mat level = outs.get(i)
for (int j = 0
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]
float y = data[1]
float width = data[2]
float height = data[3]
float xLeftBottom = (x - width / 2) * im.cols()
float yLeftBottom = (y - height / 2) * im.rows()
float xRightTop = (x + width / 2) * im.cols()
float yRightTop = (y + height / 2) * im.rows()
// 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)
// here//
int[] ind = indices.toArray()
for (int i = 0
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即可