如何使用CvCameraViewListener

时间:2017-10-21 02:52:52

标签: java android opencv camera pixels

我想写一个简单的Android OpenCV应用程序,它接受每个相机帧并对帧的像素进行一些计算。我正在使用以下代码。问题是它死得很慢。

    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();
        for(int u = 0; u < frame_width; u++) {
        for (int v = 0; v < frame_height; v++) {
            double[] current_color = mRgba.get(v, u);
            current_color[0] = current_color[0]/2;
            mRgba.put(v,u, current_color);
        }
    }
    return mRgba;

或者,如果我使用下面的代码,它运行得非常顺利。

public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
Mat imgCanny = new Mat(height,width,CvType.CV_8UC1);
Imgproc.Canny(mRgba,imgCanny,50,150);
return imgCanny;
}

所以我认为缓慢是由访问每个像素引起的。这是我手机中的1024 * 768像素。不幸的是,我需要访问每个像素才能使我的逻辑工作。是否有更快的方式来访问和修改每个像素?

由于

1 个答案:

答案 0 :(得分:1)

1)您正在迭代图像的列。您的图像足够大,由于缓存未命中,这将非常慢。列中的每两个连续像素实际上是内存中彼此远离的扫描宽度像素。 通过交换循环的顺序来迭代行。从这个优化开始,你可能会感到惊讶它的速度有多快。

2)不要在循环中使用mRgba.get(u,v)。我不会在Java中使用openCV,但在C ++中,我会得到一个指向每行开头的指针,并在每一行中按顺序操作像素。在Java中,您可以创建一个行大小的double[]缓冲区,并使用int get(int row, int col, double[] data)一次获取整行数据。同样适用于put函数。我不知道如何用Java访问底层数据缓冲区(即:不复制)。如果你知道怎么做,请告诉我。

3)在您完成1和2后,如果您想要更快地完成并且您可以访问多个内核,则可以并行执行行操作。我无法建议您如何使用Java进行此操作,但也许其他人可以或您可以查看文档。

我对您的结果感兴趣,请尽可能报告。感谢。