使用OpenCv with Android Camera Surfaceview时OpenCVLoader失败问题

来源:互联网 发布:彩虹秒赞源码 编辑:程序博客网 时间:2024/06/05 15:41

今天在使用OpenCV Library 2.4.10建立了我的第一个基于opencv的Android程序,先贴出我的代码:

package com.example.facedetector;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.MatOfRect;import org.opencv.core.Point;import org.opencv.core.Rect;import org.opencv.core.Scalar;import org.opencv.highgui.Highgui;import org.opencv.imgproc.Imgproc;import org.opencv.objdetect.CascadeClassifier;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity implements CvCameraViewListener2, OnClickListener {private Button btnStart;private CameraBridgeViewBase cameraPreview = null; private Mat mRgba; private boolean startProcess = false;protected BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {@Overridepublic void onManagerConnected(int status) {switch (status) {case LoaderCallbackInterface.SUCCESS:{cameraPreview.enableView();} break;default:{super.onManagerConnected(status);} break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);cameraPreview = (CameraBridgeViewBase) findViewById(R.id.cameraView);cameraPreview.setVisibility(SurfaceView.VISIBLE);cameraPreview.setCvCameraViewListener(this);btnStart = (Button) findViewById(R.id.btnStart);btnStart.setOnClickListener(this);}@Overrideprotected void onResume() {super.onResume();<strong>OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, getApplicationContext(), mLoaderCallback );</strong>}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();if (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);}private void startFaceDetetion(Mat image){String xmlfilePath=getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);  CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);  // Detect faces in the image.  // MatOfRect is a special container class for Rect.  MatOfRect faceDetections = new MatOfRect();  faceDetector.detectMultiScale(image, faceDetections);  System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));  // Draw a bounding box around each face.  for (Rect rect : faceDetections.toArray()) {  Scalar color = new Scalar(0, 255, 0);Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), color);} }@Overrideprotected void onDestroy() {super.onDestroy();        if (cameraPreview != null) {        cameraPreview.disableView();        startProcess = false;        }}@Overrideprotected void onPause() {super.onPause();if(cameraPreview != null){cameraPreview.disableView();startProcess = false;}}@Overridepublic void onCameraViewStarted(int width, int height) {mRgba =  new Mat(height, width, CvType.CV_8UC4);}@Overridepublic void onCameraViewStopped() {mRgba.release();}@Overridepublic Mat onCameraFrame(CvCameraViewFrame inputFrame) {    if(startProcess == true){    mRgba = inputFrame.rgba();
                return mRgba    }    return null;}@Overridepublic void onClick(View v) {startProcess = !startProcess;}}
这段代码,按照Internet上各位前辈们的经验总结,是没有问题的,但是当我在真正run它的时候,还是出现了问题,logcat上出现了以下提示:

08-18 20:57:03.549: E/AndroidRuntime(3444): java.lang.RuntimeException: Unable to resume activity {com.example.facedetector/com.example.facedetector.MainActivity}: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=org.opencv.engine.BIND }
也就是说OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, getApplicationContext(), mLoaderCallback );无法运行成功。

网络上也有人遇到了同样的问题,给出的解决方案是:

Try using getApplicationContext() instead of this in OpenCVLoader.initAsync(..)

但是我在修改后,程序依然无法运行。

出现上述问题的原因主要是因为使用了Android 5.0作为targetsdk,专业的解释 in here。这里我就不多说,大家可以自行研究。简单解释是:

Android 5.0 service intents must be explicit intents and the OpenCV library uses implicit intents in the
AsyncServiceHelper.java ( new Intent("org.opencv.engine.BIND") ), so it doesn't work.

既然是因为SDK version 的问题,那么只需要改变version就可以了,因此这里我将我的targetsdk由API 21改为了API 19:

android:targetSdkVersion="21"  --------->  android:targetSdkVersion="19"

问题解决了,这时候就可以正常运行APP了。





0 0