由于项目其他模块多用Scala/Java编写,与python交互不易。
将原多数用python/C++编写的目标检测程序,改写为Java。
建立目录,配置初始参数
类属性
static String pro_dir = "E:/yolov3/"; // 根路径
static float confThreshold = 0.3f; // 置信度阈值
static float nmsThreshold = 0.4f; // iou阈值
static int inpWidth = 416; // 修改输入图片的宽高
static int inpHeight = 416;
static List<String> classes = new ArrayList<String>(); // 存放类别的列表
主函数
public static void main(String[] args) throws Exception{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 配置 权重 图片路径 类别文件
String modelConfiguration = pro_dir + "yolov3.cfg"; // 模型配置文件
String modelWeights = pro_dir + "yolov3.weights"; // 模型权重文件
String image_path = "E:/pictures_test/pictureName.jpg"; // 图片路径,名字
String classesFile = pro_dir + "coco.names"; // 模型可识别类别的标签文件
// 进入识别图片的方法
detect_image(image_path, modelWeights, modelConfiguration, classesFile);
waitKey(0);
}
识别图片(detect_image)
读取可识别类别的标签文件,将所有类别存入List列表classses
coco.names的格式可能不同,读取时注意。
// 检测图片
public static void detect_image(String image_path, String modelWeights, String modelConfiguration, String classesFile) throws Exception {
// 读取classesFile路径的文件
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去除首尾空格,再按换行符分割。
System.out.println(tempContent.length);
// 遍历tempContent,添加到保存类别名的列表classes里。
for(int i=0; i<tempContent.length; i++){
classes.add(tempContent[i]);
}
System.out.println(classes.size());
加载网络配置与训练权重的文件,构建网络
Net net = Dnn.readNetFromDarknet(modelConfiguration, modelWeights);
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(Dnn.DNN_TARGET_OPENCL);
读入图片,配置宽高
Mat im = imread(image_path, Imgcodecs.IMREAD_COLOR); // 读入待检测的图片
// 当前是以窗体的形式查看检测后的图片,给窗体命名
final String kWinName = "Deep object detection in OpenCV";
namedWindow(kWinName, WINDOW_NORMAL);
// 将输入图片的宽高重新设置 (416, 416)
Mat frame = new Mat();
Size sz1 = new Size(im.cols(), im.rows());
Imgproc.resize(im, frame, sz1);
Mat resized = new Mat();
Size sz = new Size(inpWidth, inpHeight);
Imgproc.resize(im, resized, sz);
float scale = 1.0F / 255.0F; // 像素归一化
遍历得到Yolo输出层的名字
此处即原python代码
ln = [ln[i[0] - 1] for i in net.get