0

I make an object detection application with OpenCV in Android studio. I use yolo for object detection. I get the necessary yolo files from the phone's memory.

String tinyCfg =  Environment.getExternalStorageDirectory() + "/dnns/yolov3-tiny.cfg";
String tinyWeights = Environment.getExternalStorageDirectory() + "/dnns/yolov3-tiny.weights";
tinyYolo = Dnn.readNetFromDarknet(tinyCfg, tinyWeights);

I want to transfer these files to application files and use them from there. I am using this code for this.

String tinyCfg = "dnns/yolov3-tiny.cfg";
String tinyWeights = "dnns/yolov3-tiny.weights";
tinyYolo = Dnn.readNetFromDarknet(tinyCfg, tinyWeights);

enter image description here

But I get this error

E/cv::error(): OpenCV(3.4.5) Error: Parsing error (Failed to parse NetParameter file: dnns/yolov3-tiny.cfg) in cv::dnn::experimental_dnn_34_v11::Net cv::dnn::experimental_dnn_34_v11::readNetFromDarknet(const cv::String&, const cv::String&), file /build/3_4_pack-android/opencv/modules/dnn/src/darknet/darknet_importer.cpp, line 207
E/org.opencv.dnn: dnn::readNetFromDarknet_10() caught cv::Exception: OpenCV(3.4.5) /build/3_4_pack-android/opencv/modules/dnn/src/darknet/darknet_importer.cpp:207: error: (-212:Parsing error) Failed to parse NetParameter file: dnns/yolov3-tiny.cfg in function 'cv::dnn::experimental_dnn_34_v11::Net cv::dnn::experimental_dnn_34_v11::readNetFromDarknet(const cv::String&, const cv::String&)'
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.vision, PID: 26157
    CvException [org.opencv.core.CvException: cv::Exception: OpenCV(3.4.5) /build/3_4_pack-android/opencv/modules/dnn/src/darknet/darknet_importer.cpp:207: error: (-212:Parsing error) Failed to parse NetParameter file: dnns/yolov3-tiny.cfg in function 'cv::dnn::experimental_dnn_34_v11::Net cv::dnn::experimental_dnn_34_v11::readNetFromDarknet(const cv::String&, const cv::String&)']
Krishna Sony
  • 1,286
  • 13
  • 27
user13179766
  • 13
  • 1
  • 4

3 Answers3

0

If you want to put files directly in your app package you should put them in the assets or the raw resource folder (here is a question for comparison). Then you can access them by AssetManager or Resources.openRawResource() or using an appropriate Uri.

I don't know whether or not the readNetFromDarknet can accept InputStreams.

  • If true, the you can use AssetManager.open("dnns/yolov3-tiny.cfg") or Resources.openRawResource(your_resource_id) to get the stream.

  • If not, if it accepts Uri as input you can use file:///android_asset/dnns/yolov3-tiny.cfg or android.resource://[package]/[res type]/[res name] (based on this) to locate the files.

  • If non of those, you can copy them to your app files directory and then give the path to the function.

If you don't know how to put files in assets folder check this.

momvart
  • 1,737
  • 1
  • 20
  • 32
  • Thank you for your answer. I did what he said, but readNetFromDarknet did not accept InputStream. – user13179766 Jun 03 '20 at 12:20
  • @user13179766 so you should employ the last approach. – momvart Jun 03 '20 at 16:23
  • I created an assets folder and put the files here. When the application is first opened, I get the files from here and upload them to the phone's memory. In this way, the user does not need to take any extra action. I solved the problem this way. – user13179766 Jun 03 '20 at 16:35
0

I had the same exact issue, what I did to fix this was I added the files in the asset folder, then I created two files and copied the content of the asset folder files there. make sure to use this path:

applicationContext.filesDir.absolutePath

and create your files there!

0

I ran into this issue and found a solution in this pytorch repo:

Java:

    public static String assetFilePath(Context context, String assetName) throws IOException {
    File file = new File(context.getFilesDir(), assetName);
    if (file.exists() && file.length() > 0) {
        return file.getAbsolutePath();
    }

    try (InputStream is = context.getAssets().open(assetName)) {
        try (OutputStream os = new FileOutputStream(file)) {
            byte[] buffer = new byte[4 * 1024];
            int read;
            while ((read = is.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
            os.flush();
        }
        return file.getAbsolutePath();
    }
}

Kotlin:

@Throws(IOException::class)
fun assetFilePath(context: Context, assetName: String?): String? {
    val file = File(context.filesDir, assetName)
    if (file.exists() && file.length() > 0) {
        return file.absolutePath
    }
    context.assets.open(assetName!!).use { `is` ->
        FileOutputStream(file).use { os ->
            val buffer = ByteArray(4 * 1024)
            var read: Int
            while (`is`.read(buffer).also { read = it } != -1) {
                os.write(buffer, 0, read)
            }
            os.flush()
        }
        return file.absolutePath
    }
}

I set my yoloConfigPath = assetFilePath(applicationContext, "yolov4.cfg") and yoloWeights = assetFilePath(applicationContext, "yolov4.weights") and that did the trick.

alayan2
  • 1
  • 1