You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Java使用OpenCV ReadNet读取Assets输入流问题

问题

我需要调用OpenCV的readNetFromDarknet函数,但模型文件(yolov4-tiny.cfg和yolov4-tiny.weights)来自Android项目的Assets目录,目前只能通过InputStream获取这些文件,无法直接传入readNetFromDarknet。已经成功解析了Assets中的coco.names类名,但不知道该如何正确调用这个函数——能不能直接用Assets的路径?还是必须先把Assets里的文件导出到安卓设备本地再调用?

当前代码:

public DNN(Context m_context){

    AssetManager assetManager = m_context.getAssets();

    try {
        InputStream ims1 = assetManager.open("coco.names");
        InputStream ims2 = assetManager.open("yolov4-tiny.cfg");
        InputStream ims3 = assetManager.open("yolov4-tiny.weights");
        classes = new BufferedReader(new InputStreamReader(ims1, StandardCharsets.UTF_8)).lines().collect(Collectors.toList());
    }
    catch(IOException e) {
        e.printStackTrace();
    }

    net = Dnn.readNetFromDarknet("yolov4-tiny.cfg", "yolov4-tiny.weights");
}

解决方案

核心结论

OpenCV的readNetFromDarknet函数不支持直接传入InputStream,也无法直接使用Assets目录的路径(Assets是APK内的压缩资源,没有系统可直接访问的文件路径)。必须先将Assets中的.cfg和.weights文件复制到安卓设备的本地存储(比如内部缓存目录),再用本地文件路径调用函数。

具体实现步骤

  1. 添加文件复制工具方法
    写一个通用方法,将Assets中的文件复制到本地指定路径:
private void copyAssetToLocal(Context context, String assetFileName, String destFilePath) throws IOException {
    AssetManager assetManager = context.getAssets();
    try (InputStream in = assetManager.open(assetFileName);
         OutputStream out = new FileOutputStream(destFilePath)) {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
    }
}
  1. 修改DNN类构造方法
    在初始化网络前,先把模型文件复制到本地缓存目录,再用本地路径加载:
public DNN(Context m_context){
    AssetManager assetManager = m_context.getAssets();
    File cacheDir = m_context.getCacheDir();
    String cfgLocalPath = new File(cacheDir, "yolov4-tiny.cfg").getAbsolutePath();
    String weightsLocalPath = new File(cacheDir, "yolov4-tiny.weights").getAbsolutePath();

    try {
        // 解析coco.names类名
        InputStream ims1 = assetManager.open("coco.names");
        classes = new BufferedReader(new InputStreamReader(ims1, StandardCharsets.UTF_8)).lines().collect(Collectors.toList());

        // 复制模型文件到本地缓存
        copyAssetToLocal(m_context, "yolov4-tiny.cfg", cfgLocalPath);
        copyAssetToLocal(m_context, "yolov4-tiny.weights", weightsLocalPath);
    } catch(IOException e) {
        e.printStackTrace();
    }

    // 使用本地路径加载网络
    net = Dnn.readNetFromDarknet(cfgLocalPath, weightsLocalPath);
}

优化建议

可以添加文件存在判断,避免每次初始化都重复复制文件,提升性能:

File cfgFile = new File(cacheDir, "yolov4-tiny.cfg");
if (!cfgFile.exists()) {
    copyAssetToLocal(m_context, "yolov4-tiny.cfg", cfgLocalPath);
}

File weightsFile = new File(cacheDir, "yolov4-tiny.weights");
if (!weightsFile.exists()) {
    copyAssetToLocal(m_context, "yolov4-tiny.weights", weightsLocalPath);
}

内容的提问来源于stack exchange,提问作者Mich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 01:27:39