java通过opencv运行yolo4

获取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);

}
复制代码

效果

image.png

遇到问题

报错-cl-no-subgroup-ifp 修改为cpu
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
复制代码
匹配模型过多
NMS(Non Maximum Suppression),又名非极大值抑制 删除高度冗余的Rect2d
复制代码
再NMS需要的是Rect2d
直接从Rect,修改为Rect2d即可
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享