Java实现darknet+yolov4的目标检测

yolov5+opencv+java:通过DJL在maven项目中使用yolov5的小demo 目录前言环境导出yolov5s模型编写Maven项目编写pom.xml文件引入opencv依赖下载opencv获取opencv的jar包和动态链接库dll文件将lib文件夹添加为Library将yolov5权重文件放到资源文件编写代码运行程序 前言 这篇博客主要是介绍如何通过djl在java中调用yolov5进行推理,顺便也学习了一下在java上的opencv api。 Deep Java Library是由亚马逊(Amazon)提供的一个深度学习工具包,能够让java开发者在java上调用目前主流的深度学 阅读详情

目录

1、darknet 简介

2、yolov4

3、java 如何实现

3.1、OpenCV 原理和内存管理

3.2、实现详解

3.3、完整代码

 4、结语


1、darknet 简介

darknet 是 c 语言实现的开源 AI 深度学习框架,一般用于物体分类识别。他的优点就是轻量级、开源、没有什么依赖、支持 CPU 和 GPU 两种计算模式。官网默认的网络模型能够支持80种常见物体的分类识别。当然也可以使用自己的数据集进行训练自己的网络模型,实现自定义的场景。具体的请看darknet 官网文档。

2、yolov4

YOLO(you only look once)的第4个版本。是非常优秀的卷积神经网络,对象检测和定位的实现算法,优点就是速度快,精度高。github 项目网址,上面对 yolov4 的环境和训练做了详细的说明。

3、java 如何实现

darknet 框架是 c 语言的,是可以通过 JNI 或者 JNA 来实现调用,但是很有幸,java openCV 在 3.x 版本后推出了 DNN(深度学习)模块,已经内置实现了 darknet、torch、ONNX、caffe、tensorflow 等常见的深度学习框架,直接使用即可,非常简单。

当然实现之前,需要下载 3 个 yolov4 的文件(需要科学上网下载,不然贼慢或打不开)

配置文件:https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4.cfg

权重文件:https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights​​​​​​

类别名称:darknet/coco.names at master · AlexeyAB/darknet · GitHub (能够检测的对象)

我的百度网盘:https://pan.baidu.com/s/1tREeprjsq3mYGuCJ_vMnmg 
                         提取码:1pia

3.1、OpenCV 原理和内存管理

java OpenCV 的原理是借助 javaCPP 包(底层依然是 JNI)实现 C 代码的调用;

(非常重要)只要涉及到 java 调用 C/C++ 这种情况,就一定要注意内存管理,因为 C/C++ 是 JVM 堆外内存,GC 是无法自动管理的,所以一定要记得手动释放 C/C++ 内存、一定要记得手动释放 C/C++ 内存、一定要记得手动释放 C/C++ 内存(重要的事情说3遍)。

java OpenCV 已经很人性化的帮我们封装了 release 和 delete 这两个释放 C/C++ 内存的方法了,所以只要使用 OpenCV 包中的类,就一定要记得看看有没有这两个方法,如果有的,在使用完这个对象一定调用下。

3.2、实现详解

  • maven 依赖
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv-platform</artifactId>
    <version>4.5.3-1.5.6</version>
</dependency>

只需要依赖 opencv-platform 即可,不需要依赖 java-opencv,后者依赖了很多平台,下载大量的包。

  • 加载网络

使用前面下载的配置文件、权重文件初始化 darknet,注意,文件最终都是在 C 代码中加载的,所以要绝对路径才能加载到。

// 加载 opencv
Loader.load(opencv_java.class);

// 指定配置文件和模型文件加载网络
String cfgFile = "D:\\xxx\\ai-demo\\src\\main\\resources\\yolov4.cfg";
String weights = "D:\\xxx\\ai-demo\\src\\main\\resources\\yolov4.weights";
// opencv 的 Dnn 模块初始化网络
Net net = Dnn.readNetFromDarknet(cfgFile, weights);
if(net.empty){
    System.out.println("init net fail");
    return;
}

// 设置计算后台:如果电脑有GPU,可以指定为:DNN_BACKEND_CUDA
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
// 指定为 CPU 模式,如果电脑有 GPU,指定CUDA模式
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);

// 读取类别名称
String[] names = new String[80];
try (BufferedReader reader = new BufferedReader(new InputStreamReader(DarknetMain.class.getClassLoader().getResourceAsStream("coco.names")))) {
	for (int i = 0; i < names.length; i++) {
		names[i] = reader.readLine();
	}
}
  • 输入检测图片

现在就输入一张我们需要检测的图片给网络检测;我们输入的图片大小可能是不一样的,但是网络的图片输入都是一个尺寸,这个尺寸最好是与 yolov4.cfg 中配置的 width、height 一致,所以在输入之前需要对图片进行预处理;

// 图片绝对路径
String img_file = "D:\\xxx\\ai-demo\\src\\main\\resources\\dog_bike_car.jpg";
// 使用 opencv 提供的 api 读取图片
Mat im = Imgcodecs.imread(img_file, Imgcodecs.IMREAD_COLOR);
if (im.empty) {
    System.out.println("read img fail");
    return;
}
// 成功读取到了图片,进行预处理
float scale = 1 / 255F;
Mat inputBlob = Dnn.blobFromImage(im, scale, new Size(416, 416), new Scalar(0), true, false);
// 将处理后的图片输入到网络中
net.setInput(inputBlob);

这里简单讲解下 blobFromImage 的各个参数:
第一个参数:要处理的图片;
第二个参数:缩放比例因子,执行完平均减法后对图片的缩放因子,1表示不缩放,值见opencv文档的约定:https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml#L31
第三个参数:处理后的大小,与网络配置 cfg 中的 width、height 一致;
第四个参数:平均减法的均值,通道顺序为RGB,是用来减少光照影响,值见opencv文档的约定:https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml#L30 ​​​​​​(非0图片会变色)
第五个参数:是否转换R和B通道的顺序,因为 openCV 的图片通道顺序为BGR,而平均减法的通道顺序是RGB,所以需要转换顺序。
第六个参数:是否在调整图片大小后裁剪图片,所以是false,不要裁剪。

opencv 的 blobFromImage 的论文参考:Deep learning: How OpenCV's blobFromImage works - PyImageSearch

  • 对象检测(推理)、处理结果集

yolov4 神经网络是存在 3 个yolo输出层,第1层507个单元,第2层2028个单元,第3层8112个单元,最后一个输出层才是输出最精准的结果,所以直接拿这个输出层的结果。

// 从网络中获取所有输出层,index =0对应的是第3层输出层
List<String> outLayersNames = net.getUnconnectedOutLayersNames();
// 推理,并指定需要输出的层
Mat out = net.forward(outLayersNames.get(0));
if (outs.empty()) {
    System.out.println("forward result is null");
    return;
}

通过 forward 推理,我们已经拿到对象检测的结果集了;但是,这些结果集是不能直接使用的,需要丢弃掉置信度比较低的结果、box去重(box信息用来画框,在图片上标注出检测的物体位置)。

首先来过滤置信度比较低的结果,并转换 box 信息,记录每个类别的索引和该类别的置信度等结果信息:

List<Rect2d> rect2dList = new ArrayList<>();  // box 信息集
List<Float> confList = new ArrayList<>();     // 置信度
List<Integer> objIndexList = new ArrayList<>(); // 对象类别索引,与 names 的索引对应

// 每个 row 就是一个单元的预测结果,cols 就是当前单元的预测框信息和每个类型的置信度
for (int i = 0; i < out.rows(); i++) {
	int size = out.cols() * out.channels();
	float[] data = new float[size];
	// 将结果拷贝到 data 中,0 表示从索引0开始拷贝
	out.get(i, 0, data);
	float confidence = -1; // 置信度
	int objectClass = -1;  // 类别索引

	// data中的前4个是box的数据,第5个是分数,后面是每个 classes 的置信度,所以从5开始
	int pro_index = 5;
	for (int j = pro_index; j < out.cols(); j++) {
		if (confidence < data[j]) {
			// 记录本单元中最大的置信度及其类别索引
			confidence = data[j];
			objectClass = j - pro_index;
		}
	}
	if (confidence > 0.5) { // 置信度大于 0.5 的才记录
		for (int j = 0; j < out.cols(); j++) {
			System.out.println(" " + j + ":" + data[j]); // 输出 data 中的所有数据看看
		}
		// 计算中点、长宽、左下角点位
		float centerX = data[0] * im.cols();
		float centerY = data[1] * im.rows();
		float width = data[2] * im.cols();
		float height = data[3] * im.rows();
		float leftBottomX = centerX - width / 2;
		float leftBottomY = centerY - height / 2;

		System.out.println("Class: " + names[objectClass]); // names 是读取的类别名称
		System.out.println("Confidence: " + confidence);
		System.out.println("ROI: " + leftBottomX + "," + leftBottomY + "," + width + "," + height);
		System.out.println("");
		// 记录box信息、置信度、类型索引
		rect2dList.add(new Rect2d(leftBottomX, leftBottomY, width, height));
		confList.add(confidence);
		objIndexList.add(objectClass);
	}
}

置信度比较低的结果已经过滤掉了,经过这一步,已经拿到了 rect2dList、confList、objIndexList 三个结果集,这三个结果集 size 相等,并且 index 相互对应;但是现在还存在重复的结果,展示下效果:

 所以进行去重:

// 去重后保留的索引值,用于获取三个List的结果集
MatOfInt indexs = new MatOfInt();
// 转换 box 的结果集
MatOfRect2d boxes = new MatOfRect2d(rect2dList.toArray(new Rect2d[0]));
// 转换置信度的结果集
float[] confArr = new float[confList.size()];
for (int i = 0; i < confList.size(); i++) {
	confArr[i] = confList.get(i);
}
MatOfFloat con = new MatOfFloat(confArr);
// 使用 dnn 的 NMS 算法去重,并将去重后的索引结果保存在 indexs 中
Dnn.NMSBoxes(boxes, con, 0.5F, 0.5F, indexs);
if (indexs.empty()) {
	System.out.println("indexs is empty");
	return;
}

NMSBoxes 方法的简单讲解:
第一个参数:要去重的 box 数据;
第二个参数:要去重的置信度数据;
第三个参数:置信度阈值,如果低于这个置信度的 box 将被过滤(前面过滤了一次了)
第四个参数:NMS 的过滤阈值;
第五个参数:去重后的索引信息,用于从三个List中获取最后的结果;

NMS 算法就是通过计算重叠率(交并比 IoU),如果当前两个框的IoU大于了NMS阈值,保留置信度最高的一个。所以要注意了,当两个相同类别的对象,本来就重叠了,并且成功检测出来了,这个时候 NMS 的阈值就很重要了,遇到这种情况,多调整下阈值测试下。或者在校验权重文件的时候也是会输出 IoU 值,这里进行配置即可。

  • 输出结果

对图片画框、输出每种类别出现的次数

// 去重后的索引
int[] ints = indexs.toArray();
int[] classesNumberList = new int[names.length]; // 记录每种类别出现的次数
for (int i : ints) {
    // i 与 names 的索引位置相对应
	Rect2d rect2d = rect2dList.get(i);
	Integer obj = objIndexList.get(i);
	classesNumberList[obj] += 1; // 记录次数
	// 将 box 信息画在图片上, Scalar 对象是 BGR 的顺序,与RGB顺序反着的。
	Imgproc.rectangle(im, new Point(rect2d.x, rect2d.y), new Point(rect2d.x + rect2d.width, rect2d.y + rect2d.height),
			new Scalar(0, 255, 0), 1);
}

String jpgFile = Paths.get("D:\\xxx\\ai-demo\\outs", "out_" + System.currentTimeMillis() + ".jpg").toString();
// 保存图片
Imgcodecs.imwrite(jpgFile, im);
// 输出每种类别的数量
for (int i = 0; i < names.length; i++) {
	System.out.println(names[i] + ": " + classesNumberList[i]);
}

去重后的结果:

  •  最后最后,不要忘记释放内存
try {
    //...上面的代码
} finally {
	if (im != null) {
		im.release(); // 输入图片释放
	}
	if (out != null) { // 推理的结果集释放
		out.release();
	}
    // 去重过程中的对象释放
	if (indexs != null) {
		indexs.release();
	}
	if (boxes != null) {
		boxes.release();
	}
	if (con != null) {
		con.release();
	}
}

3.3、完整代码

其实就是上面的代码拼装到一起

package com.chc.ai.darknet;

import org.bytedeco.javacpp.Loader;
import org.bytedeco.opencv.opencv_java;
import org.opencv.core.*;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用官方模型和配置
 * 修改了网络大小为 416
 *
 * @author chc
 * @date 2022/01/25
 * @since 1.0
 */
public class DarknetMain {

    public static void main(String[] args) throws IOException {
        Loader.load(opencv_java.class); // 加载opencv

        // 读取类别名称
        String[] names = new String[80];
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(DarknetMain.class.getClassLoader().getResourceAsStream("coco.names")))) {
            for (int i = 0; i < names.length; i++) {
                names[i] = reader.readLine();
            }
        }

        // 定义对象
        Mat im = null;
        Mat out = null;
        MatOfInt indexs = null;
        MatOfRect2d boxes = null;
        MatOfFloat con = null;
        try {
            // 指定配置文件和模型文件加载网络
            String cfgFile = "D:\\xxx\\ai-demo\\src\\main\\resources\\yolov4.cfg";
            String weights = "D:\\xxx\\ai-demo\\src\\main\\resources\\yolov4.weights";
            Net net = Dnn.readNetFromDarknet(cfgFile, weights);
            if (net.empty()) {
                System.out.println("init net fail");
                return;
            }
            // 设置计算后台:如果电脑有GPU,可以指定为:DNN_BACKEND_CUDA
            net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
            // 指定为 CPU 模式
            net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
            System.out.println("create net success");

            // 读取要被推理的图片
            String img_file = "D:\\xxx\\ai-demo\\src\\main\\resources\\dog_bike_car.jpg";
            im = Imgcodecs.imread(img_file, Imgcodecs.IMREAD_COLOR);
            if (im.empty()) {
                System.out.println("read image fail");
                return;
            }
            

            // 图片预处理:将图片转换为 416 大小的图片,这个数值最好与配置文件的网络大小一致
            // 缩放因子大小,opencv 文档规定的:https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml#L31
            float scale = 1 / 255F;
            Mat inputBlob = Dnn.blobFromImage(im, scale, new Size(416, 416), new Scalar(0), true, false);
            // 输入图片到网络中
            net.setInput(inputBlob);

            // 推理
            List<String> outLayersNames = net.getUnconnectedOutLayersNames();
            out = net.forward(outLayersNames.get(0));
            if (outs.empty()) {
                System.out.println("forward result is null");
                return;
            }
            System.out.println("net forward success");

            // 处理 out 的结果集: 移除小的置信度数据和去重
            List<Rect2d> rect2dList = new ArrayList<>();
            List<Float> confList = new ArrayList<>();
            List<Integer> objIndexList = new ArrayList<>();
			// 每个 row 就是一个单元,cols 就是当前单元的预测信息
			for (int i = 0; i < out.rows(); i++) {
				int size = out.cols() * out.channels();
				float[] data = new float[size];
				// 将结果拷贝到 data 中,0 表示从索引0开始拷贝
				out.get(i, 0, data);
				float confidence = -1; // 置信度
				int objectClass = -1; // 类型索引
				// data中的前4个是box的数据,第5个是分数,后面是每个 classes 的置信度
				int pro_index = 5;
				for (int j = pro_index; j < out.cols(); j++) {
					if (confidence < data[j]) {
						// 记录本单元中最大的置信度及其类型索引
						confidence = data[j];
						objectClass = j - pro_index;
					}
				}
				if (confidence > 0.5) { // 置信度大于 0.5 的才记录
					System.out.println("result unit index: " + i);
					for (int j = 0; j < out.cols(); j++) {
						System.out.println(" " + j + ":" + data[j]);
					}
					// 计算中点、长宽、左下角点位
					float centerX = data[0] * im.cols();
					float centerY = data[1] * im.rows();
					float width = data[2] * im.cols();
					float height = data[3] * im.rows();
					float leftBottomX = centerX - width / 2;
					float leftBottomY = centerY - height / 2;

					System.out.println("Class: " + names[objectClass]);
					System.out.println("Confidence: " + confidence);
					System.out.println("ROI: " + leftBottomX + "," + leftBottomY + "," + width + "," + height);
					System.out.println("");
					// 记录box信息、置信度、类型索引
					rect2dList.add(new Rect2d(leftBottomX, leftBottomY, width, height));
					confList.add(confidence);
					objIndexList.add(objectClass);
				}
			}
            if (rect2dList.isEmpty()) {
                System.out.println("not object");
                return;
            }
            // box 去重
            indexs = new MatOfInt();
            boxes = new MatOfRect2d(rect2dList.toArray(new Rect2d[0]));
            float[] confArr = new float[confList.size()];
            for (int i = 0; i < confList.size(); i++) {
                confArr[i] = confList.get(i);
            }
            con = new MatOfFloat(confArr);
            // NMS 算法去重
            Dnn.NMSBoxes(boxes, con, 0.5F, 0.5F, indexs);
            if (indexs.empty()) {
                System.out.println("indexs is empty");
                return;
            }
            // 去重后的索引
            int[] ints = indexs.toArray();
            int[] classesNumberList = new int[names.length];
            for (int i : ints) {
                // 与 names 的索引位置相对应
                Rect2d rect2d = rect2dList.get(i);
                Integer obj = objIndexList.get(i);
                classesNumberList[obj] += 1;
                // 将 box 信息画在图片上, Scalar 对象是 BGR 的顺序,与RGB顺序反着的。
                Imgproc.rectangle(im, new Point(rect2d.x, rect2d.y), new Point(rect2d.x + rect2d.width, rect2d.y + rect2d.height),
                        new Scalar(0, 255, 0), 1);
            }

            String jpgFile = Paths.get("D:\\xxx\\ai-demo\\outs", "out_" + System.currentTimeMillis() + ".jpg").toString();
            Imgcodecs.imwrite(jpgFile, im);
            for (int i = 0; i < names.length; i++) {
                System.out.println(names[i] + ": " + classesNumberList[i]);
            }
        } finally {
            // 释放资源
            if (im != null) {
                im.release();
            }
            if (out != null) {
                out.release();
            }
            if (indexs != null) {
                indexs.release();
            }
            if (boxes != null) {
                boxes.release();
            }
            if (con != null) {
                con.release();
            }
        }
    }
}

 4、结语

java 语言其实不是非常适合做 AI,至少不是首选语言,唯一的优点就是对 java 工程师友好,没有学习新语言的成本(小公司可是很在意成本的)。我接触到的就是 opencv dnn 模块和 AWS 推出的 DJL。

opencv dnn 模块通过 JNI 桥接到 C/C++ 让java有能力实现 AI 的推理过程,还是非常棒的,填补了 java 在 AI 的空白。

DJL 官网说的是专门为 java 开发的 AI 套件,可以使用 DJL 做训练、推理,但是目前还没有过多的尝试,暂且不评论。

最后还是那句话,不要忘记释放 c 内存,不然内存爆了不好排除原因。

YOLOv4 Darknet模型转成tflite模型然后进行Android设备端部署 YOLOv4 Darknet模型转成Tflite模型然后进行Android设备端部署 文章目录YOLOv4 Darknet模型转成Tflite模型然后进行Android设备端部署前言1. 安卓apk项目的开源1.1 uint8模型的量化1.2 编译并生成apk1.3 int8量化模型运行速度2. YOLOv4 darknet版本转tflite2.1 与样例一样的转换遇到了问题2.3 另一种方法转换2.3.1 修改config2.3.2 修改save_model.py3.3 fp32,fp16,int8转换3 阅读详情

相关推荐

使用Java和OpenCV调用YOLOv3完成实施目标检测

使用Java和OpenCV调用YOLOv3完成实施目标检测,识别到目标就将包含目标的图片保存下来,没有目标就不保存。 第一步:在IDEA中完成对OpenCV包的导入 从官网上下载OpenCV:Releases - OpenCV。选择window版本下载,解压之后 把 opencv\build\目录下的java文件整个复制到项目文件下,名字随意。 File>Project Structure>Libraries ,选择+号,选择java,之后选择jar...

qq_50087672的博客 4067

YOLOv8目标检测实战:Android手机部署

YOLOv8 目标检测基于先前 YOLO 版本的成功,引入了新功能和改进,进一步提升了性能和灵活性。本课程在Windows上手把手演示YOLOv8(YOLOv8n和YOLOv8s)目标检测在Android(安卓)手机进行部署的过程。内容包括:安装软件环境、安装PyTorch,克隆和安装YOLOv8,导出onnx模型,onnx转换成NCNN文件,安装Android Studio,准备Android项目文件(下载项目文件、放置ncnn文件、放置ncnn和opencv的android文件),手机连接电脑并编译软件(安装投屏软件、手机连接电脑配置、编译和调试、导出签名apk),自己数据集训练模型的部署,项目代码解析(安卓的JNI机制、C++代码、Java代码)。

基于ROS的YOLOV3实现目标检测项目过程记录

2020.08.07 问题记录 1.要命的ros_darknet 整体逻辑是用yolo检测出目标,然后通过ros节点将目标类别和位置信息发布出来,因此选择ros_darknet,2个问题: (1)依赖opencv和boost,boost库安装过程中并没有出现"安装成功"的最后提示,但是在工控机上编译仍然能通过 (2)工控机上运行roslaunch时,加载完.weights后进程突然死掉,在百度和github issues上搜了很多方法,仍然没有解决.之后将问题定位到创建yolo线程这一步,但是没有解决办法

cxhmike的博客 4567

使用Java调用Yolo模型的准备工作与输入输出

Yolo是一种基于深度学习的目标检测算法,通过将目标检测任务转化为一个回归问题,直接在图像级别上预测边界框和类别信息。相比于传统的两步检测方法(如R-CNN系列),Yolo算法具有更快的速度和更好的实时性能。Yolo(You Only Look Once)是一种流行的实时目标检测算法,具有高效性和准确性。Yolo算法的主要思想是将目标检测问题转化为一个回归问题,并使用单个卷积神经网络同时预测目标的位置和类别。本文介绍了如何使用Java调用Yolo目标检测模型,并给出了相关示例代码。

m0_61789994的博客 5412

基于Java 实现的 YOLO 对象检测

一个基于 java 的模板,用于仅使用 YOLO 权重进行基于流视频的对象检测

m0_75176907的博客 1397

【嵌入式AI】yolov3-tiny基于darknet2ncnn在安卓实现

yolov3-tiny基于darknet2ncnn在安卓实现 1、构建ncnn以及编译darknet2ncnn 参考:https://github.com/xiangweizeng/darknet2ncnn git clone https://gitee.com/damone/darknet2ncnn.git cd darknet2ncnn git submodule init git ...

AI知识搬运工 1672

如何将darknet yolov4模型文件转化为pb文件_YOLOv4实用训练实践

YOLOv4实用训练实践准备工作· 推荐使用Ubuntu 18.04· CMake >= 3.8: https://cmake.org/download/· CUDA >= 10.0: https://developer.nvidia.com/cuda-toolkit-archive· OpenCV >= 2.4: https://opencv.org/releases.html...

weixin_39665302的博客 1442

用·java实现yolo算法,训练自己的数据 由浅入深代码集.docx

用·java实现yolo算法,训练自己的数据 由浅入深代码集

yolov3-tiny:Android端基于darknet2ncnn之实现二

经过一段时间的反复摸索,终于在Android端基于darknet2ncnn的框架实现了yolov3-tiny,一张图片的检测时间为500ms以内,基本满足需求,接着分享该实现的第二部分内容,同时也欢迎大家关注我的微信公众号“机器视觉交流社”或个人微信号“LuckyZiXiao”进行交流。 前提:在pc端已经编译好darknet2ncnn环境,并且将Android下需要的...

liuwei36120516的博客 2527

yolov3的java调用示例

通过java代码使用yolov3的示例代码,yolov3是先进的图片内物品识别的神经网络。由于目前通过jvm运行神经网络效率较低,项目的示例意义大于实用意义。 此项目参考了yolov2的java项目:https://github.com/szaza/android-yolo-v2,是在这个项目的基础上改造成的yolov3示例。 此项目使用springboot和maven,下载项目和依赖后运行起来访问localhost:8080即可使用。项目内的模型和依赖比较重,下载需要一段时间。

YOLO目标检测+摔倒检测数据集已标注可以直接使用(5700张图像+对应已标注txt和xml文件).rar

1、资源描述: 2、资源内容:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 3、适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 4、更多数据集合和仿真源码下载列表(自行寻找自己需要的):https://blog.youkuaiyun.com/m0_62143653?type=download 5、作者介绍:某大厂资深算法工程师,从事Matlab、Python、C/C++、Java、YOLO算法仿真工作10年;擅长计算机视觉、目标检测模型、智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、智能控制、路径规划、无人机等多种领域的算法仿真实验,欢迎交流学习。

darknet + yolov4 训练自定义数据集 + windows环境搭建

windows系统下的 darkent 和 yolov4 训练环境搭建、训练过程问题记录。在工作实践中给出了自己的一点规范建议,希望能帮助搭建跨过这些坑点。

java_chc的博客 3732

DeepLearning4j-使用Java训练YOLO模型

本文来自于csdn,文章介绍了数据集、模型训练中读取训练数据以及模型检测可视化等相关内容。在这个Yolov3发布的大好日子。 Deeplearning4j终于迎来了新的版本更新1.0.0-alpha,在zoomodel中引入TinyYolo模型可以训练自己的数据用于目标检测。 不得不说,在Yolov3这种性能和准确率上面都有大幅度提升的情况下,dl4j才引入TinyYolo总有一种49年加入国军的感觉 数据来源自

yolov3、yolov4训练遇到问题记录

can’t open label files 数据存储格式: 问题描述: 解决方法: 打开darknet/src/until.c 找到函数replace_image_to_label 将下述代码取消注释即可(212行) void replace_image_to_label(char *input_path, char *output_path) { ... find_replace(ou...

wbqxx的博客 2298

国科GK7202V300芯片开发避坑指南:从uboot编译到SDK配置的12个实战问题解决

本文针对国科GK7202V300芯片开发过程中的常见难题,提供从uboot编译、SDK配置到系统部署的实战解决方案。详细解析了开发环境搭建、内核编译、驱动模块加载、根文件系统构建及烧写部署等12个关键环节的避坑指南,帮助开发者高效解决编译错误、配置冲突等典型问题,提升开发效率。

sunny的博客 234

贴片二极管SOD封装详解:SOD-123/323/523尺寸焊盘设计要点

表面贴装技术中,二极管封装尺寸直接决定PCB布局与焊接可靠性。SOD封装作为小外形二极管的主流形态,其SOD-123、SOD-323、SOD-523三种规格分别对应不同的功耗与占板面积权衡。理解封装尺寸、焊盘设计计算逻辑和钢网开窗原理,是避免立碑、虚焊等工艺缺陷的关键。在可穿戴设备、电源保护等空间受限场景中,合理选择封装不仅能优化散热路径,还能提升量产良率。本文从焊盘计算、工艺要点到选型策略,全面解析SOD封装的工程实践。

weixin_42520780的博客 307

从‘炼丹’到‘量产’:手把手教你用YOLOv4训练自己的目标检测模型(附完整代码)

本文详细介绍了YOLOv4目标检测模型从环境配置到工业级部署的全流程指南。涵盖数据工程、模型训练核心参数解析、部署优化等关键环节,提供完整代码示例和实战技巧,帮助开发者快速掌握Object Detection技术并实现高效量产应用。

weixin_30700977的博客 2219

Unity2020 发布Android包,下载安装配置JDK、SDK、NDK详细教程

配置成功页面 JDK、SDK、NDK

qq_41263535的博客 1万+

Darknet/YOLO框架完全指南:从入门到精通的实时目标检测神器

想要快速实现准确的目标检测吗?Darknet/YOLO框架就是您的终极解决方案!这个开源神经网络框架结合了C、C++和CUDA的强大性能,让您能够轻松构建实时目标检测系统。无论您是计算机视觉新手还是经验丰富的开发者,本指南都将带您从零开始,掌握这一强大的目标检测神器。 ## 为什么选择Darknet/YOLO框架? Darknet/YOLO框架是目前最快速、最准确的目标检测框架之一。它完全免费

gitblog_00799的博客 696

智能驾驶感知模块的测试评估方法(上)

对于智能驾驶系统而言,感知模块是开发难度最大、投入资源最多的核心部分。在智能驾驶开发团队内部,感知模块需要独立进行评测才能及早发现潜在缺陷或判断性能是否有改进。随着近几年BEV、OCC、E2E等新技术方案被越来越多企业应用,感知的评测变得越来越艰难,效率也变得越来越低下。本文作者基于在智驾测试行业多年经验,试图总结感知评测的基本规律和效率提升方法,以供读者一些启发。

vincent_321的博客 2559

2026年VIVO嵌入式岗位高频面试题(含参考答案)

摘要:VIVO嵌入式岗位考核涵盖智能手机、IoT设备、芯片适配等方向,重点考察硬件底层交互、RTOS/Linux开发、C/C++功底与问题排查能力。题目按优先级排序,分硬件架构、RTOS、C/C++、数据结构、Linux实践、行业认知6大模块,共40道题。硬件部分涉及中断、ARM架构、加速技术、BSP开发等;RTOS部分区分硬/软实时系统;C/C++部分侧重内存管理、位操作;Linux部分考察常用命令;行业部分关注鸿蒙等系统理念。题目设计贴合实际工作场景,全面评估嵌入式开发能力。

Open 52

手把手带你使用 Java 快速实现目标检测:支持 YOLOv8,YOLOv11,YOLOv12 开箱即用(附源码)

Java目标检测、YOLO Java实现、SSD目标检测、Java深度学习、SmartJavaAI、图像识别、Java图像处理、Java人工智能、Java实现YOLO、Java实现SSD、Java AI实战、目标检测教程、Java智能视觉系统

deng775747758的博客 1975

21天教你学会PCIe专栏(14)--安全性考虑

1.1 定义安全性(Security):安全性是指保护系统免受未经授权的访问、攻击和破坏,确保数据的机密性、完整性和可用性。1.2 重要性数据保护:保护敏感数据,防止数据泄露和篡改。系统防护:防止恶意攻击,确保系统的稳定性和可靠性。合规性:满足行业标准和法律法规的要求,避免法律风险。用户信任:提高用户对系统的信任度,增强市场竞争力。通过今天的学习,你应该对PCIe安全性的重要性和常见威胁有了深入的了解,掌握了实施安全措施的方法和工具,以及安全开发的最佳实践。

xiaoheshang_123的博客 850
上一篇: web上传zip大文件,java服务接收并解压ZIP文件
下一篇: darknet + yolov4 训练自定义数据集 + windows环境搭建
网上搬砖
博客等级 码龄6年 4粉丝 9原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值