获取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即可
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END