Обнаружение движения с помощью opencv на Android

Привет, я пытаюсь реализовать обнаружение движения с помощью opencv на Android. Я применил образец кода обнаружения движения и сделал вызов jni. Я запустил это на Android, это работает, но обработанный предварительный просмотр очень медленный. Я удалил часть процесса обнаружения движения, после чего предварительный просмотр работал нормально. Как я могу улучшить производительность? Я добавил свой исходный код для обнаружения движения и jni. Пожалуйста, проверьте и посоветуйте мне.

    import java.util.ArrayList;
    import java.util.List;

    import org.opencv.android.BaseLoaderCallback;
    import org.opencv.android.CameraBridgeViewBase;
    import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
    import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
    import org.opencv.android.LoaderCallbackInterface;
    import org.opencv.android.OpenCVLoader;
    import org.opencv.core.Core;
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfPoint;
    import org.opencv.core.Point;
    import org.opencv.core.Rect;
    import org.opencv.core.Scalar;
    import org.opencv.core.Size;
    import org.opencv.imgproc.Imgproc;

    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.Intent;
    import android.hardware.Camera;
    import android.media.MediaRecorder;
    import android.os.Bundle;
    import android.os.CountDownTimer;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.WindowManager;
    import android.widget.TextView;
    import android.widget.Toast;


    public class CameraViewActivity extends Activity implements
    CvCameraViewListener2 {

        private CameraBridgeViewBase m_OpenCvCameraView;
        private Mat m_inputMat;
        private Mat m_dstMat;
        private Mat m_motionAvgMat;
        private Mat m_grayMat;
        private Mat m_diffMat;
        private Mat m_scaleMat;
        private static Mat m_contourKernel;
        private static Mat m_hierarchy;
        private Point m_rectPoint1;
        private Point m_rectPoint2;
        private static Point m_contourPoint;
        private Scalar m_rectColor;
        private Size m_kSize;
        private Size m_frameSize;
        private double m_totalPixels;
        private double m_motionPercent;

        private boolean isRecording = false;
        private boolean isMotionDetect = false;

        private Camera m_Camera;
        private MediaRecorder m_MediaRecorder;
        private Runnable m_Runnable;
        private Handler m_TimerHandler;
        private TextView m_tvTimer;
        private int value = 0;
        private CountDownTimer timer;

        private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    System.loadLibrary("motion_detect");
                    m_OpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
                }
            }
        };

        public CameraViewActivity() {
            Log.i(TAG, "Instantiated new " + this.getClass());
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            Log.i(TAG, "called onCreate");
            super.onCreate(savedInstanceState);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

            setContentView(R.layout.local_camera_view);
            m_OpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.local_camera_surface_view);
            m_OpenCvCameraView.setCvCameraViewListener(this);
            m_tvTimer = (TextView)findViewById(R.id.tv_timer);
        }


        @Override
        public void onPause()
        {
            super.onPause();
            if (m_OpenCvCameraView != null)
                m_OpenCvCameraView.disableView();
        }

        @Override
        public void onResume()
        {
            super.onResume();
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION
extern "C" {
JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_GussianBlur(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_GussianBlur(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mInput  = *(Mat*)addrGray;
Mat& mDst = *(Mat*)addrRgba;
cv::GaussianBlur(mInput, mDst, cv::Size(3, 3), -1);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CloneConverTo(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CloneConverTo(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mMotionAvgMat = *(Mat*)addrRgba;
mMotionAvgMat = mDest.clone();
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_AccumulateWeighted(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_AccumulateWeighted(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mMortion = *(Mat*)addrRgba;
cv::accumulateWeighted(mDest, mMortion, .03);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_ConvertScaleAbs(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_ConvertScaleAbs(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mMortion  = *(Mat*)addrGray;
Mat& mScale = *(Mat*)addrRgba;
cv::convertScaleAbs(mMortion, mScale);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Absdiff(JNIEnv*, jobject, jlong addrGray, jlong addrRgba, jlong addDiff);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Absdiff(JNIEnv*, jobject, jlong addrGray, jlong addrRgba, jlong addDiff)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mScale = *(Mat*)addrRgba;
Mat& mDiff = *(Mat*)addDiff;

cv::absdiff(mDest, mScale, mDiff);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CvtColor(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CvtColor(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDiff  = *(Mat*)addrGray;
Mat& mGray = *(Mat*)addrRgba;
cv::cvtColor(mDiff, mGray, 6);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Threshold(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Threshold(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mGray  = *(Mat*)addrGray;
Mat& m_Gray = *(Mat*)addrRgba;
cv::threshold(mGray, m_Gray, 25, 255, 0);
}
4_8, this, mLoaderCallback); } public void onDestroy() { super.onDestroy(); if (m_OpenCvCameraView != null) m_OpenCvCameraView.disableView(); m_inputMat.release(); m_dstMat.release(); m_motionAvgMat.release(); m_grayMat.release(); m_diffMat.release(); m_scaleMat.release(); m_contourKernel.release(); m_hierarchy.release(); } public void onCameraViewStarted(int width, int height) { m_inputMat = new Mat(); m_dstMat = new Mat(); m_motionAvgMat = null; m_grayMat = new Mat(); m_diffMat = new Mat(); m_scaleMat = new Mat(); m_rectPoint1 = new Point(); m_rectPoint2 = new Point(); m_rectColor = new Scalar(0, 255, 0); m_kSize = new Size(8, 8); m_motionPercent = 0.0; m_contourKernel = Imgproc.getStructuringElement(Imgproc.MORPH_DILATE, new Size(3, 3), new Point(1, 1)); m_hierarchy = new Mat(); m_contourPoint = new Point(-1, -1); startTimer(); } public void startTimer(){ timer = new CountDownTimer(5 * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { value++; m_tvTimer.setText("Test Value = " + value); } @Override public void onFinish() { timer.cancel(); } }; timer.start(); } public void onCameraViewStopped() { m_inputMat.release(); m_dstMat.release(); m_motionAvgMat.release(); m_grayMat.release(); m_diffMat.release(); m_scaleMat.release(); m_contourKernel.release(); m_hierarchy.release(); } @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { m_inputMat = inputFrame.rgba(); // TODO Auto-generated method stub m_frameSize= m_inputMat.size(); m_totalPixels = m_frameSize.area(); GussianBlur(m_inputMat.getNativeObjAddr(), m_dstMat.getNativeObjAddr()); if (m_motionAvgMat == null) { m_motionAvgMat = m_dstMat.clone(); m_motionAvgMat.convertTo(m_motionAvgMat, CvType.CV_32F); } AccumulateWeighted(m_dstMat.getNativeObjAddr(), m_motionAvgMat.getNativeObjAddr()); ConvertScaleAbs(m_motionAvgMat.getNativeObjAddr(), m_scaleMat.getNativeObjAddr()); Absdiff(m_dstMat.getNativeObjAddr(), m_scaleMat.getNativeObjAddr(), m_diffMat.getNativeObjAddr()); CvtColor(m_diffMat.getNativeObjAddr(), m_grayMat.getNativeObjAddr()); Threshold(m_grayMat.getNativeObjAddr(), m_grayMat.getNativeObjAddr()); m_motionPercent = 100.0 * Core.countNonZero(m_grayMat) / m_totalPixels; if (m_motionPercent > 1.0) { m_motionAvgMat = m_dstMat.clone(); m_motionAvgMat.convertTo(m_motionAvgMat, CvType.CV_32F); CloneConverTo(m_motionAvgMat.getNativeObjAddr(),m_dstMat.getNativeObjAddr()); } List<Rect> movementLocations = contours(m_grayMat); if (m_motionPercent > 1.0) { for (Rect rect : movementLocations) { m_rectPoint1.x = rect.x; m_rectPoint1.y = rect.y; m_rectPoint2.x = rect.x + rect.width; m_rectPoint2.y = rect.y + rect.height; Core.rectangle(m_inputMat, m_rectPoint1, m_rectPoint2, m_rectColor, 2); } isMotionDetect = true; m_handler.sendEmptyMessage(MOTION_DETECT); }else { isMotionDetect = false; } return m_inputMat; } Handler m_handler = new Handler() { @SuppressLint("NewApi") @Override public void handleMessage(Message msg) { switch (msg.what) { case MOTION_DETECT: Toast toast = Toast.makeText(CameraViewActivity.this, "Motion detect!!!!", Toast.LENGTH_SHORT); toast.show(); if(isRecording==false) { RecordVideo(); isRecording=true; } break; } } }; public static List<Rect> contours(final Mat source) { Imgproc.dilate(source, source, m_contourKernel, m_contourPoint, 15); Imgproc.erode(source, source, m_contourKernel, m_contourPoint, 10); final List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(source, contours, m_hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE); List<Rect> rectList = new ArrayList<Rect>(); // Convert MatOfPoint to Rectangles for (MatOfPoint mop : contours) { rectList.add(Imgproc.boundingRect(mop)); } return rectList; } public native void GussianBlur(long matAddrGr, long matAddrRgba); public native void CloneConverTo(long matAddrGr, long matAddrRgba); public native void AccumulateWeighted(long matAddrGr, long matAddrRgba); public native void ConvertScaleAbs(long matAddrGr, long matAddrRgba); public native void Absdiff(long matAddrGr, long matAddrRgba, long matDiff); public native void CvtColor(long matAddrGr, long matAddrRgba); public native void Threshold(long matAddrGr, long matAddrRgba); public native void RecordVideo(); }

ЗВОНОК ДЖНИ

extern "C" {
JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_GussianBlur(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_GussianBlur(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mInput  = *(Mat*)addrGray;
Mat& mDst = *(Mat*)addrRgba;
cv::GaussianBlur(mInput, mDst, cv::Size(3, 3), -1);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CloneConverTo(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CloneConverTo(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mMotionAvgMat = *(Mat*)addrRgba;
mMotionAvgMat = mDest.clone();
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_AccumulateWeighted(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_AccumulateWeighted(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mMortion = *(Mat*)addrRgba;
cv::accumulateWeighted(mDest, mMortion, .03);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_ConvertScaleAbs(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_ConvertScaleAbs(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mMortion  = *(Mat*)addrGray;
Mat& mScale = *(Mat*)addrRgba;
cv::convertScaleAbs(mMortion, mScale);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Absdiff(JNIEnv*, jobject, jlong addrGray, jlong addrRgba, jlong addDiff);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Absdiff(JNIEnv*, jobject, jlong addrGray, jlong addrRgba, jlong addDiff)
{
Mat& mDest  = *(Mat*)addrGray;
Mat& mScale = *(Mat*)addrRgba;
Mat& mDiff = *(Mat*)addDiff;

cv::absdiff(mDest, mScale, mDiff);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CvtColor(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_CvtColor(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mDiff  = *(Mat*)addrGray;
Mat& mGray = *(Mat*)addrRgba;
cv::cvtColor(mDiff, mGray, 6);
}

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Threshold(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_com_xx_xx_CameraViewActivity_Threshold(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mGray  = *(Mat*)addrGray;
Mat& m_Gray = *(Mat*)addrRgba;
cv::threshold(mGray, m_Gray, 25, 255, 0);
}

person user3348577    schedule 07.06.2014    source источник


Ответы (1)


Не могли бы вы рассказать немного больше о том, работаете ли вы на эмуляторе или на реальном устройстве? Если вы используете эмулятор, попробуйте установить HAXM(https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager) и включите технологию виртуализации в BIOS. Производительность эмулятора значительно повышается с помощью HAXM.

person G3M    schedule 09.06.2014