Android 上的 OpenCV:net.forward 产生“215 断言失败”

OpenCV on Android: net.forward yields "215 Assertion failed"

跟随this tutorial from openCV,应该是直截了当的。但是,它因 net.forward 断言失败而崩溃,我无法在其他任何地方 resolve/find。

认为 this problem 看起来很相似,并试图通过 fix/problem 的发现。然而,重新开始讨论和试验表明它可能不一样。我最初使用的是 3.4.3,它以某种方式不支持相同的 Mat 类型。现在更新到 3.4.7,可以确认 blob 大小没问题(从图像生成)。还尝试了其他各种 prototxt 和 caffemodels,但现在怀疑问题出在那里(如果文件没问题就可以工作,否则网络加载失败)。关键代码应该是这样的:

// Load a network.
public void onCameraViewStarted(int width, int height) {
    String proto = getPath("deploy.prototxt", this);
    String weights = getPath("MobileNetSSD_deploy.caffemodel", this);
    net = Dnn.readNetFromCaffe(proto, weights);
    Log.i(TAG, "Network loaded successfully");
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    // Get a new frame
    Mat frame = inputFrame.rgba();
    Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);
    // Forward image through network.
    Mat blob = Dnn.blobFromImage(frame, 0.007843,
            new Size(300, 300),
            new Scalar(127.5, 127.5, 127.5));

    net.setInput(blob);
    Mat detections = net.forward(); //***215 ASSERTION FAILED occurs***
    int cols = frame.cols();
    int rows = frame.rows();
    detections = detections.reshape(1, (int)detections.total() / 7);
    for (int i = 0; i < detections.rows(); ++i) {
        double confidence = detections.get(i, 2)[0];
        if (confidence > 0.2) {
            int classId = (int)detections.get(i, 1)[0];
            int left   = (int)(detections.get(i, 3)[0] * cols);
            int top    = (int)(detections.get(i, 4)[0] * rows);
            int right  = (int)(detections.get(i, 5)[0] * cols);
            int bottom = (int)(detections.get(i, 6)[0] * rows);
            // Draw rectangle around detected object.
            Imgproc.rectangle(frame, new Point(left, top), new Point(right, bottom),
                    new Scalar(0, 255, 0));
            String label = classNames[classId] + ": " + confidence;
            int[] baseLine = new int[1];
            Size labelSize = Imgproc.getTextSize(label, Core.FONT_HERSHEY_SIMPLEX, 0.5, 1, baseLine);
            // Draw background for label.
            Imgproc.rectangle(frame, new Point(left, top - labelSize.height),
                    new Point(left + labelSize.width, top + baseLine[0]),
                    new Scalar(255, 255, 255), Core.FILLED);
            // Write class name and confidence.
            Imgproc.putText(frame, label, new Point(left, top),
                    Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 0));
        }
    }
    return frame;
}
public void onCameraViewStopped() {}
// Upload file to storage and return a path.
private static String getPath(String file, Context context) {
    AssetManager assetManager = context.getAssets();
    BufferedInputStream inputStream = null;
    try {
        // Read data from assets.
        inputStream = new BufferedInputStream(assetManager.open(file));
        byte[] data = new byte[inputStream.available()];
        inputStream.read(data);
        inputStream.close();
        // Create copy file in storage.
        File outFile = new File(context.getFilesDir(), file);
        FileOutputStream os = new FileOutputStream(outFile);
        os.write(data);
        os.close();
        // Return a path to file which may be read in common way.
        return outFile.getAbsolutePath();
    } catch (IOException ex) {
        Log.i(TAG, "Failed to upload a file");
    }
    return "";
}

完整的错误信息是

cv::Exception: OpenCV(3.4.7) /build/3_4_pack-android/opencv/modules/dnn/src/layers/batch_norm_layer.cpp:39: error: (-215:Assertion failed) blobs.size() >= 2 in function 'cv::dnn::BatchNormLayerImpl::BatchNormLayerImpl(const cv::dnn::experimental_dnn_34_v13::LayerParams&)'

我希望它不会崩溃。框架应该没问题(图像加载),网络不是空的,网络中的层看起来也很好(检查因为在 java 中使用 caffe 存在一些差异)。感谢您的帮助!

经过几天的不同方向的研究,我发现了问题:帧格式应该是BGR,而不是RGB!也就是说

Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2BGR);