OpenCV Samples testing problems fixed:

Memory leak in color-blob-detection sample fixed;
Default face size in face-detection is set to 20%;
Error handling improved;
Some possible mat leak fixed;
Manager verison and engine interface version incremented to fix incompatibilities;
Docs updated;
This commit is contained in:
Alexander Smorkalov 2012-10-31 15:20:49 +04:00
parent 78fd99abdb
commit a1a2cb0aeb
17 changed files with 126 additions and 88 deletions

View File

@ -20,4 +20,4 @@ if (not os.path.exists(TARGET_PATH)):
for filename in os.listdir("."): for filename in os.listdir("."):
if ("dia" == filename[-3:]): if ("dia" == filename[-3:]):
os.system("%s --export %s %s" % (DiaPath, os.path.join(TARGET_PATH, filename[0:len(filename)-4] + ".png"), filename)) os.system("%s --export %s %s" % (DiaPath, os.path.join(TARGET_PATH, filename[0:len(filename)-4] + ".png"), filename))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.opencv.engine" package="org.opencv.engine"
android:versionCode="18" android:versionCode="20"
android:versionName="1.8" > android:versionName="2.0" >
<uses-sdk android:minSdkVersion="8" /> <uses-sdk android:minSdkVersion="8" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/> <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>

View File

@ -6,7 +6,7 @@
#define LOG_TAG "OpenCVEngine" #define LOG_TAG "OpenCVEngine"
#ifndef OPEN_CV_ENGINE_VERSION #ifndef OPEN_CV_ENGINE_VERSION
#define OPEN_CV_ENGINE_VERSION 1 #define OPEN_CV_ENGINE_VERSION 2
#endif #endif
#define LIB_OPENCV_INFO_NAME "libopencv_info.so" #define LIB_OPENCV_INFO_NAME "libopencv_info.so"

View File

@ -41,7 +41,7 @@ class AsyncServiceHelper
} }
protected static final String TAG = "OpenCVManager/Helper"; protected static final String TAG = "OpenCVManager/Helper";
protected static final int MINIMUM_ENGINE_VERSION = 1; protected static final int MINIMUM_ENGINE_VERSION = 2;
protected OpenCVEngineInterface mEngineService; protected OpenCVEngineInterface mEngineService;
protected LoaderCallbackInterface mUserAppCallback; protected LoaderCallbackInterface mUserAppCallback;
protected String mOpenCVersion; protected String mOpenCVersion;

View File

@ -52,7 +52,7 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
Log.d(TAG, "OpenCV Manager Service is uncompatible with this app!"); Log.d(TAG, "OpenCV Manager Service is uncompatible with this app!");
AlertDialog IncomatibilityMessage = new AlertDialog.Builder(mAppContext).create(); AlertDialog IncomatibilityMessage = new AlertDialog.Builder(mAppContext).create();
IncomatibilityMessage.setTitle("OpenCV Manager"); IncomatibilityMessage.setTitle("OpenCV Manager");
IncomatibilityMessage.setMessage("OpenCV Manager service is incompatible with this app. Update it!"); IncomatibilityMessage.setMessage("OpenCV Manager service is incompatible with this app. Try to update it via Google Play.");
IncomatibilityMessage.setCancelable(false); // This blocks the 'BACK' button IncomatibilityMessage.setCancelable(false); // This blocks the 'BACK' button
IncomatibilityMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() { IncomatibilityMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
@ -60,7 +60,7 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
} }
}); });
IncomatibilityMessage.show(); IncomatibilityMessage.show();
} } break;
/** Other status, i.e. INIT_FAILED. **/ /** Other status, i.e. INIT_FAILED. **/
default: default:
{ {
@ -113,7 +113,7 @@ public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
{ {
AlertDialog WaitMessage = new AlertDialog.Builder(mAppContext).create(); AlertDialog WaitMessage = new AlertDialog.Builder(mAppContext).create();
WaitMessage.setTitle("OpenCV is not ready"); WaitMessage.setTitle("OpenCV is not ready");
WaitMessage.setMessage("Installation is in progeress. Wait or exit?"); WaitMessage.setMessage("Installation is in progress. Wait or exit?");
WaitMessage.setCancelable(false); // This blocks the 'BACK' button WaitMessage.setCancelable(false); // This blocks the 'BACK' button
WaitMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Wait", new OnClickListener() { WaitMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Wait", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {

View File

@ -1,6 +1,5 @@
package org.opencv.android; package org.opencv.android;
import java.io.IOException;
import java.util.List; import java.util.List;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -36,7 +35,8 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
private Mat mBaseMat; private Mat mBaseMat;
private byte mBuffer[]; private byte mBuffer[];
private Mat[] mFrameChain;
private int mChainIdx = 0;
private Thread mThread; private Thread mThread;
private boolean mStopThread; private boolean mStopThread;
@ -65,6 +65,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
@TargetApi(11) @TargetApi(11)
protected boolean initializeCamera(int width, int height) { protected boolean initializeCamera(int width, int height) {
Log.d(TAG, "Initialize java camera"); Log.d(TAG, "Initialize java camera");
boolean result = true;
synchronized (this) { synchronized (this) {
mCamera = null; mCamera = null;
@ -99,59 +100,76 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
Log.d(TAG, "getSupportedPreviewSizes()"); Log.d(TAG, "getSupportedPreviewSizes()");
List<android.hardware.Camera.Size> sizes = params.getSupportedPreviewSizes(); List<android.hardware.Camera.Size> sizes = params.getSupportedPreviewSizes();
/* Select the size that fits surface considering maximum size allowed */ if (sizes != null) {
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height); /* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
params.setPreviewFormat(ImageFormat.NV21); params.setPreviewFormat(ImageFormat.NV21);
Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height)); Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height));
params.setPreviewSize((int)frameSize.width, (int)frameSize.height); params.setPreviewSize((int)frameSize.width, (int)frameSize.height);
List<String> FocusModes = params.getSupportedFocusModes(); List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{ {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
params = mCamera.getParameters();
mFrameWidth = params.getPreviewSize().width;
mFrameHeight = params.getPreviewSize().height;
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mBaseMat = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
mFrameChain = new Mat[2];
mFrameChain[0] = new Mat();
mFrameChain[1] = new Mat();
AllocateCache();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
} }
else
mCamera.setParameters(params); result = false;
params = mCamera.getParameters(); } catch (Exception e) {
result = false;
mFrameWidth = params.getPreviewSize().width;
mFrameHeight = params.getPreviewSize().height;
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mBaseMat = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
AllocateCache();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
} catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
} }
return true; return result;
} }
protected void releaseCamera() { protected void releaseCamera() {
synchronized (this) { synchronized (this) {
mCamera.stopPreview(); if (mCamera != null) {
mCamera.release(); mCamera.stopPreview();
mCamera.release();
}
mCamera = null; mCamera = null;
if (mBaseMat != null)
mBaseMat.release();
if (mFrameChain != null) {
mFrameChain[0].release();
mFrameChain[1].release();
}
} }
} }
@ -187,7 +205,8 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
this.notify(); this.notify();
} }
Log.d(TAG, "Wating for thread"); Log.d(TAG, "Wating for thread");
mThread.join(); if (mThread != null)
mThread.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
@ -224,19 +243,19 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
} }
if (!mStopThread) { if (!mStopThread) {
Mat frameMat = new Mat();
switch (mPreviewFormat) { switch (mPreviewFormat) {
case Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA: case Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA:
Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4); Imgproc.cvtColor(mBaseMat, mFrameChain[mChainIdx], Imgproc.COLOR_YUV2RGBA_NV21, 4);
break; break;
case Highgui.CV_CAP_ANDROID_GREY_FRAME: case Highgui.CV_CAP_ANDROID_GREY_FRAME:
frameMat = mBaseMat.submat(0, mFrameHeight, 0, mFrameWidth); mFrameChain[mChainIdx] = mBaseMat.submat(0, mFrameHeight, 0, mFrameWidth);
break; break;
default: default:
Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!"); Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!");
}; };
deliverAndDrawFrame(frameMat); if (!mFrameChain[mChainIdx].empty())
frameMat.release(); deliverAndDrawFrame(mFrameChain[mChainIdx]);
mChainIdx = 1 - mChainIdx;
} }
} while (!mStopThread); } while (!mStopThread);
Log.d(TAG, "Finish processing thread"); Log.d(TAG, "Finish processing thread");

View File

@ -63,7 +63,8 @@ public class Puzzle15Activity extends Activity implements CvCameraViewListener,
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -76,7 +77,8 @@ public class Puzzle15Activity extends Activity implements CvCameraViewListener,
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
@Override @Override

View File

@ -78,7 +78,8 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -91,7 +92,8 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
public void onCameraViewStarted(int width, int height) { public void onCameraViewStarted(int width, int height) {
@ -100,7 +102,7 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
mSpectrum = new Mat(); mSpectrum = new Mat();
mBlobColorRgba = new Scalar(255); mBlobColorRgba = new Scalar(255);
mBlobColorHsv = new Scalar(255); mBlobColorHsv = new Scalar(255);
SPECTRUM_SIZE = new Size(200, 32); SPECTRUM_SIZE = new Size(200, 64);
CONTOUR_COLOR = new Scalar(255,0,0,255); CONTOUR_COLOR = new Scalar(255,0,0,255);
} }
@ -152,6 +154,9 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
mIsColorSelected = true; mIsColorSelected = true;
touchedRegionRgba.release();
touchedRegionHsv.release();
return false; // don't need subsequent touch events return false; // don't need subsequent touch events
} }
@ -164,10 +169,10 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe
Log.e(TAG, "Contours count: " + contours.size()); Log.e(TAG, "Contours count: " + contours.size());
Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR); Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
Mat colorLabel = mRgba.submat(2, 34, 2, 34); Mat colorLabel = mRgba.submat(4, 68, 4, 68);
colorLabel.setTo(mBlobColorRgba); colorLabel.setTo(mBlobColorRgba);
Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols()); Mat spectrumLabel = mRgba.submat(4, 4 + mSpectrum.rows(), 70, 70 + mSpectrum.cols());
mSpectrum.copyTo(spectrumLabel); mSpectrum.copyTo(spectrumLabel);
} }

View File

@ -22,6 +22,13 @@ public class ColorBlobDetector {
private Mat mSpectrum = new Mat(); private Mat mSpectrum = new Mat();
private List<MatOfPoint> mContours = new ArrayList<MatOfPoint>(); private List<MatOfPoint> mContours = new ArrayList<MatOfPoint>();
// Cache
Mat mPyrDownMat = new Mat();
Mat mHsvMat = new Mat();
Mat mMask = new Mat();
Mat mDilatedMask = new Mat();
Mat mHierarchy = new Mat();
public void setColorRadius(Scalar radius) { public void setColorRadius(Scalar radius) {
mColorRadius = radius; mColorRadius = radius;
} }
@ -61,23 +68,17 @@ public class ColorBlobDetector {
} }
public void process(Mat rgbaImage) { public void process(Mat rgbaImage) {
Mat pyrDownMat = new Mat(); Imgproc.pyrDown(rgbaImage, mPyrDownMat);
Imgproc.pyrDown(mPyrDownMat, mPyrDownMat);
Imgproc.pyrDown(rgbaImage, pyrDownMat); Imgproc.cvtColor(mPyrDownMat, mHsvMat, Imgproc.COLOR_RGB2HSV_FULL);
Imgproc.pyrDown(pyrDownMat, pyrDownMat);
Mat hsvMat = new Mat(); Core.inRange(mHsvMat, mLowerBound, mUpperBound, mMask);
Imgproc.cvtColor(pyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL); Imgproc.dilate(mMask, mDilatedMask, new Mat());
Mat Mask = new Mat();
Core.inRange(hsvMat, mLowerBound, mUpperBound, Mask);
Mat dilatedMask = new Mat();
Imgproc.dilate(Mask, dilatedMask, new Mat());
List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(dilatedMask, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); Imgproc.findContours(mDilatedMask, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// Find max contour area // Find max contour area
double maxArea = 0; double maxArea = 0;

View File

@ -50,7 +50,7 @@ public class FdActivity extends Activity implements CvCameraViewListener {
private int mDetectorType = JAVA_DETECTOR; private int mDetectorType = JAVA_DETECTOR;
private String[] mDetectorName; private String[] mDetectorName;
private float mRelativeFaceSize = 0; private float mRelativeFaceSize = 0.2f;
private int mAbsoluteFaceSize = 0; private int mAbsoluteFaceSize = 0;
private CameraBridgeViewBase mOpenCvCameraView; private CameraBridgeViewBase mOpenCvCameraView;
@ -132,7 +132,8 @@ public class FdActivity extends Activity implements CvCameraViewListener {
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }

View File

@ -113,7 +113,8 @@ public class ImageManipulationsActivity extends Activity implements CvCameraView
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -126,7 +127,8 @@ public class ImageManipulationsActivity extends Activity implements CvCameraView
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
@Override @Override

View File

@ -68,7 +68,8 @@ public class Sample1Java extends Activity implements CvCameraViewListener {
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -81,7 +82,8 @@ public class Sample1Java extends Activity implements CvCameraViewListener {
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
@Override @Override

View File

@ -75,7 +75,8 @@ public class Sample2NativeCamera extends Activity implements CvCameraViewListene
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -88,7 +89,8 @@ public class Sample2NativeCamera extends Activity implements CvCameraViewListene
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
public void onCameraViewStarted(int width, int height) { public void onCameraViewStarted(int width, int height) {

View File

@ -64,7 +64,8 @@ public class Sample3Native extends Activity implements CvCameraViewListener {
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -77,7 +78,8 @@ public class Sample3Native extends Activity implements CvCameraViewListener {
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
public void onCameraViewStarted(int width, int height) { public void onCameraViewStarted(int width, int height) {

View File

@ -90,7 +90,8 @@ public class Sample4Mixed extends Activity implements CvCameraViewListener {
@Override @Override
public void onPause() public void onPause()
{ {
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
super.onPause(); super.onPause();
} }
@ -103,7 +104,8 @@ public class Sample4Mixed extends Activity implements CvCameraViewListener {
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOpenCvCameraView.disableView(); if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
} }
public void onCameraViewStarted(int width, int height) { public void onCameraViewStarted(int width, int height) {