resolved conflicts, updated retina class interface and optimized a heavy retinacolor process
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OpenCV Sample - 15-puzzle</name>
|
||||
<name>OpenCV Sample - 15 puzzle</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.opencv.samples.puzzle15"
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
package="org.opencv.samples.puzzle15"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity
|
||||
android:name=".Puzzle15Activity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation" >
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="puzzle15Activity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<supports-screens android:resizeable="true"
|
||||
android:smallScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:largeScreens="true"
|
||||
android:anyDensity="true" />
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OCV 15 Puzzle</string>
|
||||
</resources>
|
||||
<string name="menu_toggle_tile_numbers">Show/hide tile numbers</string>
|
||||
<string name="menu_start_new_game">Start new game</string>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.opencv.samples.puzzle15;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
|
||||
import org.opencv.android.JavaCameraView;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class Puzzle15Activity extends Activity implements CvCameraViewListener, View.OnTouchListener {
|
||||
|
||||
private static final String TAG = "Sample::Puzzle15::Activity";
|
||||
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
private Puzzle15Processor mPuzzle15;
|
||||
private MenuItem mItemHideNumbers;
|
||||
private MenuItem mItemStartNewGame;
|
||||
|
||||
|
||||
private int mGameWidth;
|
||||
private int mGameHeight;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
|
||||
/* Now enable camera view to start receiving frames */
|
||||
mOpenCvCameraView.setOnTouchListener(Puzzle15Activity.this);
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
Log.d(TAG, "Creating and seting view");
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) new JavaCameraView(this, -1);
|
||||
setContentView(mOpenCvCameraView);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
mPuzzle15 = new Puzzle15Processor();
|
||||
mPuzzle15.prepareNewGame();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemHideNumbers = menu.add("Show/hide tile numbers");
|
||||
mItemStartNewGame = menu.add("Start new game");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "Menu Item selected " + item);
|
||||
if (item == mItemStartNewGame) {
|
||||
/* We need to start new game */
|
||||
mPuzzle15.prepareNewGame();
|
||||
} else if (item == mItemHideNumbers) {
|
||||
/* We need to enable or disable drawing of the tile numbers */
|
||||
mPuzzle15.toggleTileNumbers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
mGameWidth = width;
|
||||
mGameHeight = height;
|
||||
mPuzzle15.prepareGameSize(width, height);
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
}
|
||||
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
int xpos, ypos;
|
||||
|
||||
xpos = (view.getWidth() - mGameWidth) / 2;
|
||||
xpos = (int)event.getX() - xpos;
|
||||
|
||||
ypos = (view.getHeight() - mGameHeight) / 2;
|
||||
ypos = (int)event.getY() - ypos;
|
||||
|
||||
if (xpos >=0 && xpos <= mGameWidth && ypos >=0 && ypos <= mGameHeight) {
|
||||
/* click is inside the picture. Deliver this event to processor */
|
||||
mPuzzle15.deliverTouchEvent(xpos, ypos);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(Mat inputFrame) {
|
||||
return mPuzzle15.puzzleFrame(inputFrame);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package org.opencv.samples.puzzle15;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.core.Point;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* This class is a controller for puzzle game.
|
||||
* It converts the image from Camera into the shuffled image
|
||||
*/
|
||||
public class Puzzle15Processor {
|
||||
|
||||
private static final int GRID_SIZE = 4;
|
||||
private static final int GRID_AREA = GRID_SIZE * GRID_SIZE;
|
||||
private static final int GRID_EMPTY_INDEX = GRID_AREA - 1;
|
||||
private static final String TAG = "Puzzle15Processor";
|
||||
private static final Scalar GRID_EMPTY_COLOR = new Scalar(0x33, 0x33, 0x33, 0xFF);
|
||||
|
||||
private int[] mIndexes;
|
||||
private int[] mTextWidths;
|
||||
private int[] mTextHeights;
|
||||
|
||||
private Mat mRgba15;
|
||||
private Mat[] mCells15;
|
||||
private boolean mShowTileNumbers = true;
|
||||
|
||||
public Puzzle15Processor() {
|
||||
mTextWidths = new int[GRID_AREA];
|
||||
mTextHeights = new int[GRID_AREA];
|
||||
|
||||
mIndexes = new int [GRID_AREA];
|
||||
|
||||
for (int i = 0; i < GRID_AREA; i++)
|
||||
mIndexes[i] = i;
|
||||
}
|
||||
|
||||
/* this method is intended to make processor prepared for a new game */
|
||||
public synchronized void prepareNewGame() {
|
||||
do {
|
||||
shuffle(mIndexes);
|
||||
} while (!isPuzzleSolvable());
|
||||
}
|
||||
|
||||
/* This method is to make the processor know the size of the frames that
|
||||
* will be delivered via puzzleFrame.
|
||||
* If the frames will be different size - then the result is unpredictable
|
||||
*/
|
||||
public synchronized void prepareGameSize(int width, int height) {
|
||||
mRgba15 = new Mat(height, width, CvType.CV_8UC4);
|
||||
mCells15 = new Mat[GRID_AREA];
|
||||
|
||||
for (int i = 0; i < GRID_SIZE; i++) {
|
||||
for (int j = 0; j < GRID_SIZE; j++) {
|
||||
int k = i * GRID_SIZE + j;
|
||||
mCells15[k] = mRgba15.submat(i * height / GRID_SIZE, (i + 1) * height / GRID_SIZE, j * width / GRID_SIZE, (j + 1) * width / GRID_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < GRID_AREA; i++) {
|
||||
Size s = Core.getTextSize(Integer.toString(i + 1), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, 2, null);
|
||||
mTextHeights[i] = (int) s.height;
|
||||
mTextWidths[i] = (int) s.width;
|
||||
}
|
||||
}
|
||||
|
||||
/* this method to be called from the outside. it processes the frame and shuffles
|
||||
* the tiles as specified by mIndexes array
|
||||
*/
|
||||
public synchronized Mat puzzleFrame(Mat inputPicture) {
|
||||
Mat[] cells = new Mat[GRID_AREA];
|
||||
int rows = inputPicture.rows();
|
||||
int cols = inputPicture.cols();
|
||||
|
||||
rows = rows - rows%4;
|
||||
cols = cols - cols%4;
|
||||
|
||||
for (int i = 0; i < GRID_SIZE; i++) {
|
||||
for (int j = 0; j < GRID_SIZE; j++) {
|
||||
int k = i * GRID_SIZE + j;
|
||||
cells[k] = inputPicture.submat(i * inputPicture.rows() / GRID_SIZE, (i + 1) * inputPicture.rows() / GRID_SIZE, j * inputPicture.cols()/ GRID_SIZE, (j + 1) * inputPicture.cols() / GRID_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
rows = rows - rows%4;
|
||||
cols = cols - cols%4;
|
||||
|
||||
// copy shuffled tiles
|
||||
for (int i = 0; i < GRID_AREA; i++) {
|
||||
int idx = mIndexes[i];
|
||||
if (idx == GRID_EMPTY_INDEX)
|
||||
mCells15[i].setTo(GRID_EMPTY_COLOR);
|
||||
else {
|
||||
cells[idx].copyTo(mCells15[i]);
|
||||
if (mShowTileNumbers) {
|
||||
Core.putText(mCells15[i], Integer.toString(1 + idx), new Point((cols / GRID_SIZE - mTextWidths[idx]) / 2,
|
||||
(rows / GRID_SIZE + mTextHeights[idx]) / 2), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, new Scalar(255, 0, 0, 255), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < GRID_AREA; i++)
|
||||
cells[i].release();
|
||||
|
||||
drawGrid(cols, rows, mRgba15);
|
||||
|
||||
return mRgba15;
|
||||
}
|
||||
|
||||
public void toggleTileNumbers() {
|
||||
mShowTileNumbers = !mShowTileNumbers;
|
||||
}
|
||||
|
||||
public void deliverTouchEvent(int x, int y) {
|
||||
int rows = mRgba15.rows();
|
||||
int cols = mRgba15.cols();
|
||||
|
||||
int row = (int) Math.floor(y * GRID_SIZE / rows);
|
||||
int col = (int) Math.floor(x * GRID_SIZE / cols);
|
||||
|
||||
if (row < 0 || row >= GRID_SIZE || col < 0 || col >= GRID_SIZE) {
|
||||
Log.e(TAG, "It is not expected to get touch event outside of picture");
|
||||
return ;
|
||||
}
|
||||
|
||||
int idx = row * GRID_SIZE + col;
|
||||
int idxtoswap = -1;
|
||||
|
||||
// left
|
||||
if (idxtoswap < 0 && col > 0)
|
||||
if (mIndexes[idx - 1] == GRID_EMPTY_INDEX)
|
||||
idxtoswap = idx - 1;
|
||||
// right
|
||||
if (idxtoswap < 0 && col < GRID_SIZE - 1)
|
||||
if (mIndexes[idx + 1] == GRID_EMPTY_INDEX)
|
||||
idxtoswap = idx + 1;
|
||||
// top
|
||||
if (idxtoswap < 0 && row > 0)
|
||||
if (mIndexes[idx - GRID_SIZE] == GRID_EMPTY_INDEX)
|
||||
idxtoswap = idx - GRID_SIZE;
|
||||
// bottom
|
||||
if (idxtoswap < 0 && row < GRID_SIZE - 1)
|
||||
if (mIndexes[idx + GRID_SIZE] == GRID_EMPTY_INDEX)
|
||||
idxtoswap = idx + GRID_SIZE;
|
||||
|
||||
// swap
|
||||
if (idxtoswap >= 0) {
|
||||
synchronized (this) {
|
||||
int touched = mIndexes[idx];
|
||||
mIndexes[idx] = mIndexes[idxtoswap];
|
||||
mIndexes[idxtoswap] = touched;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawGrid(int cols, int rows, Mat drawMat) {
|
||||
for (int i = 1; i < GRID_SIZE; i++) {
|
||||
Core.line(drawMat, new Point(0, i * rows / GRID_SIZE), new Point(cols, i * rows / GRID_SIZE), new Scalar(0, 255, 0, 255), 3);
|
||||
Core.line(drawMat, new Point(i * cols / GRID_SIZE, 0), new Point(i * cols / GRID_SIZE, rows), new Scalar(0, 255, 0, 255), 3);
|
||||
}
|
||||
}
|
||||
|
||||
private static void shuffle(int[] array) {
|
||||
for (int i = array.length; i > 1; i--) {
|
||||
int temp = array[i - 1];
|
||||
int randIx = (int) (Math.random() * i);
|
||||
array[i - 1] = array[randIx];
|
||||
array[randIx] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPuzzleSolvable() {
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < GRID_AREA; i++) {
|
||||
if (mIndexes[i] == GRID_EMPTY_INDEX)
|
||||
sum += (i / GRID_SIZE) + 1;
|
||||
else {
|
||||
int smaller = 0;
|
||||
for (int j = i + 1; j < GRID_AREA; j++) {
|
||||
if (mIndexes[j] < mIndexes[i])
|
||||
smaller++;
|
||||
}
|
||||
sum += smaller;
|
||||
}
|
||||
}
|
||||
return sum % 2 == 0;
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package org.opencv.samples.puzzle15;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.highgui.Highgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private SurfaceHolder mHolder;
|
||||
private VideoCapture mCamera;
|
||||
|
||||
public SampleCvViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public synchronized boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
releaseCamera();
|
||||
Log.e(TAG, "Can't open native camera");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
protected abstract Bitmap processFrame(VideoCapture capture);
|
||||
|
||||
public void run() {
|
||||
Log.i(TAG, "Started processing thread");
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
|
||||
if (!mCamera.grab()) {
|
||||
Log.e(TAG, "mCamera.grab() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
package org.opencv.samples.puzzle15;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/** Activity class implements LoaderCallbackInterface to handle OpenCV initialization status **/
|
||||
public class puzzle15Activity extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private MenuItem mItemNewGame;
|
||||
private MenuItem mItemToggleNumbers;
|
||||
private puzzle15View mView = null;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new puzzle15View(mAppContext);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public puzzle15Activity() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemNewGame = menu.add("Start new game");
|
||||
mItemToggleNumbers = menu.add("Show/hide tile numbers");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemNewGame)
|
||||
mView.startNewGame();
|
||||
else if (item == mItemToggleNumbers)
|
||||
mView.tolggleTileNumbers();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
package org.opencv.samples.puzzle15;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
|
||||
public class puzzle15View extends SampleCvViewBase implements OnTouchListener {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
|
||||
private Mat mRgba;
|
||||
private Mat mRgba15;
|
||||
private Mat[] mCells;
|
||||
private Mat[] mCells15;
|
||||
private int[] mIndexses;
|
||||
private int[] mTextWidths;
|
||||
private int[] mTextHeights;
|
||||
private boolean mShowTileNumbers = true;
|
||||
|
||||
int gridSize = 4;
|
||||
int gridArea = gridSize * gridSize;
|
||||
int gridEmptyIdx = gridArea - 1;
|
||||
|
||||
public puzzle15View(Context context) {
|
||||
super(context);
|
||||
setOnTouchListener(this);
|
||||
|
||||
mTextWidths = new int[gridArea];
|
||||
mTextHeights = new int[gridArea];
|
||||
for (int i = 0; i < gridArea; i++) {
|
||||
Size s = Core.getTextSize(Integer.toString(i + 1), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, 2, null);
|
||||
mTextHeights[i] = (int) s.height;
|
||||
mTextWidths[i] = (int) s.width;
|
||||
}
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
synchronized (this) {
|
||||
// initialize Mat before usage
|
||||
mRgba = new Mat();
|
||||
}
|
||||
|
||||
super.surfaceCreated(holder);
|
||||
}
|
||||
|
||||
public static void shuffle(int[] array) {
|
||||
for (int i = array.length; i > 1; i--) {
|
||||
int temp = array[i - 1];
|
||||
int randIx = (int) (Math.random() * i);
|
||||
array[i - 1] = array[randIx];
|
||||
array[randIx] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPuzzleSolvable() {
|
||||
if (gridSize != 4)
|
||||
return true;
|
||||
|
||||
int sum = 0;
|
||||
for (int i = 0; i < gridArea; i++) {
|
||||
if (mIndexses[i] == gridEmptyIdx)
|
||||
sum += (i / gridSize) + 1;
|
||||
else {
|
||||
int smaller = 0;
|
||||
for (int j = i + 1; j < gridArea; j++) {
|
||||
if (mIndexses[j] < mIndexses[i])
|
||||
smaller++;
|
||||
}
|
||||
sum += smaller;
|
||||
}
|
||||
}
|
||||
|
||||
return sum % 2 == 0;
|
||||
}
|
||||
|
||||
private void createPuzzle(int cols, int rows, int type) {
|
||||
mCells = new Mat[gridArea];
|
||||
mCells15 = new Mat[gridArea];
|
||||
|
||||
mRgba15 = new Mat(rows, cols, type);
|
||||
mIndexses = new int[gridArea];
|
||||
|
||||
for (int i = 0; i < gridSize; i++) {
|
||||
for (int j = 0; j < gridSize; j++) {
|
||||
int k = i * gridSize + j;
|
||||
mIndexses[k] = k;
|
||||
mCells[k] = mRgba.submat(i * rows / gridSize, (i + 1) * rows / gridSize, j * cols / gridSize, (j + 1) * cols / gridSize);
|
||||
mCells15[k] = mRgba15.submat(i * rows / gridSize, (i + 1) * rows / gridSize, j * cols / gridSize, (j + 1) * cols / gridSize);
|
||||
}
|
||||
}
|
||||
|
||||
startNewGame();
|
||||
}
|
||||
|
||||
private void drawGrid(int cols, int rows) {
|
||||
for (int i = 1; i < gridSize; i++) {
|
||||
Core.line(mRgba15, new Point(0, i * rows / gridSize), new Point(cols, i * rows / gridSize), new Scalar(0, 255, 0, 255), 3);
|
||||
Core.line(mRgba15, new Point(i * cols / gridSize, 0), new Point(i * cols / gridSize, rows), new Scalar(0, 255, 0, 255), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void startNewGame() {
|
||||
do {
|
||||
shuffle(mIndexses);
|
||||
} while (!isPuzzleSolvable());
|
||||
}
|
||||
|
||||
public void tolggleTileNumbers() {
|
||||
mShowTileNumbers = !mShowTileNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
int cols = mRgba.cols();
|
||||
int rows = mRgba.rows();
|
||||
|
||||
rows = rows - rows%4;
|
||||
cols = cols - cols%4;
|
||||
|
||||
if (mCells == null)
|
||||
createPuzzle(cols, rows, mRgba.type());
|
||||
else if(mRgba15.cols() != cols || mRgba15.rows() != rows) {
|
||||
releaseMats();
|
||||
createPuzzle(cols, rows, mRgba.type());
|
||||
}
|
||||
|
||||
// copy shuffled tiles
|
||||
for (int i = 0; i < gridArea; i++) {
|
||||
int idx = mIndexses[i];
|
||||
if (idx == gridEmptyIdx)
|
||||
mCells15[i].setTo(new Scalar(0x33, 0x33, 0x33, 0xFF));
|
||||
else {
|
||||
mCells[idx].copyTo(mCells15[i]);
|
||||
if (mShowTileNumbers) {
|
||||
Core.putText(mCells15[i], Integer.toString(1 + idx), new Point((cols / gridSize - mTextWidths[idx]) / 2,
|
||||
(rows / gridSize + mTextHeights[idx]) / 2), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, new Scalar(255, 0, 0, 255), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawGrid(cols, rows);
|
||||
Bitmap bmp = Bitmap.createBitmap(cols, rows, Bitmap.Config.ARGB_8888);
|
||||
try {
|
||||
Utils.matToBitmap(mRgba15, bmp);
|
||||
return bmp;
|
||||
} catch(Exception e) {
|
||||
Log.e("org.opencv.samples.puzzle15", "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
|
||||
synchronized (this) {
|
||||
releaseMats();
|
||||
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
mRgba = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseMats() {
|
||||
// Explicitly deallocate Mats
|
||||
if (mCells != null) {
|
||||
for (Mat m : mCells)
|
||||
m.release();
|
||||
}
|
||||
if (mCells15 != null) {
|
||||
for (Mat m : mCells15)
|
||||
m.release();
|
||||
}
|
||||
|
||||
if (mRgba15 != null)
|
||||
mRgba15.release();
|
||||
|
||||
mRgba15 = null;
|
||||
mCells = null;
|
||||
mCells15 = null;
|
||||
mIndexses = null;
|
||||
}
|
||||
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if(mRgba==null) return false;
|
||||
|
||||
int cols = mRgba.cols();
|
||||
int rows = mRgba.rows();
|
||||
float xoffset = (getWidth() - cols) / 2;
|
||||
float yoffset = (getHeight() - rows) / 2;
|
||||
|
||||
float x = event.getX() - xoffset;
|
||||
float y = event.getY() - yoffset;
|
||||
|
||||
int row = (int) Math.floor(y * gridSize / rows);
|
||||
int col = (int) Math.floor(x * gridSize / cols);
|
||||
|
||||
if (row < 0 || row >= gridSize || col < 0 || col >= gridSize)
|
||||
return false;
|
||||
|
||||
int idx = row * gridSize + col;
|
||||
int idxtoswap = -1;
|
||||
|
||||
// left
|
||||
if (idxtoswap < 0 && col > 0)
|
||||
if (mIndexses[idx - 1] == gridEmptyIdx)
|
||||
idxtoswap = idx - 1;
|
||||
// right
|
||||
if (idxtoswap < 0 && col < gridSize - 1)
|
||||
if (mIndexses[idx + 1] == gridEmptyIdx)
|
||||
idxtoswap = idx + 1;
|
||||
// top
|
||||
if (idxtoswap < 0 && row > 0)
|
||||
if (mIndexses[idx - gridSize] == gridEmptyIdx)
|
||||
idxtoswap = idx - gridSize;
|
||||
// bottom
|
||||
if (idxtoswap < 0 && row < gridSize - 1)
|
||||
if (mIndexses[idx + gridSize] == gridEmptyIdx)
|
||||
idxtoswap = idx + gridSize;
|
||||
|
||||
// swap
|
||||
if (idxtoswap >= 0) {
|
||||
synchronized (this) {
|
||||
int touched = mIndexses[idx];
|
||||
mIndexses[idx] = mIndexses[idxtoswap];
|
||||
mIndexses[idxtoswap] = touched;
|
||||
}
|
||||
}
|
||||
|
||||
return false;// don't need subsequent touch events
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,13 @@ add_subdirectory(face-detection)
|
||||
add_subdirectory(image-manipulations)
|
||||
add_subdirectory(color-blob-detection)
|
||||
|
||||
add_subdirectory(tutorial-0-androidcamera)
|
||||
add_subdirectory(tutorial-1-addopencv)
|
||||
add_subdirectory(tutorial-2-opencvcamera)
|
||||
add_subdirectory(tutorial-3-native)
|
||||
add_subdirectory(tutorial-4-mixed)
|
||||
if (ANDROID_NATIVE_API_LEVEL GREATER 8)
|
||||
add_subdirectory(native-activity)
|
||||
endif()
|
||||
|
||||
add_subdirectory(tutorial-1-camerapreview)
|
||||
add_subdirectory(tutorial-2-mixedprocessing)
|
||||
add_subdirectory(tutorial-3-cameracontrol)
|
||||
|
||||
#hello-android sample
|
||||
if(HAVE_opencv_highgui)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="ColorBlobDetectionActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
@@ -22,7 +26,7 @@
|
||||
android:largeScreens="true"
|
||||
android:anyDensity="true" />
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/color_blob_detection_activity_surface_view" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,62 +1,54 @@
|
||||
package org.opencv.samples.colorblobdetect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
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.Rect;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.View.OnTouchListener;
|
||||
|
||||
public class ColorBlobDetectionActivity extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
public class ColorBlobDetectionActivity extends Activity implements OnTouchListener, CvCameraViewListener2 {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private ColorBlobDetectionView mView;
|
||||
private boolean mIsColorSelected = false;
|
||||
private Mat mRgba;
|
||||
private Scalar mBlobColorRgba;
|
||||
private Scalar mBlobColorHsv;
|
||||
private ColorBlobDetector mDetector;
|
||||
private Mat mSpectrum;
|
||||
private Size SPECTRUM_SIZE;
|
||||
private Scalar CONTOUR_COLOR;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new ColorBlobDetectionView(mAppContext);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
mOpenCvCameraView.enableView();
|
||||
mOpenCvCameraView.setOnTouchListener(ColorBlobDetectionActivity.this);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
@@ -70,25 +62,6 @@ public class ColorBlobDetectionActivity extends Activity {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -96,5 +69,122 @@ public class ColorBlobDetectionActivity extends Activity {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
setContentView(R.layout.color_blob_detection_surface_view);
|
||||
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.color_blob_detection_activity_surface_view);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
mRgba = new Mat(height, width, CvType.CV_8UC4);
|
||||
mDetector = new ColorBlobDetector();
|
||||
mSpectrum = new Mat();
|
||||
mBlobColorRgba = new Scalar(255);
|
||||
mBlobColorHsv = new Scalar(255);
|
||||
SPECTRUM_SIZE = new Size(200, 64);
|
||||
CONTOUR_COLOR = new Scalar(255,0,0,255);
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
mRgba.release();
|
||||
}
|
||||
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
int cols = mRgba.cols();
|
||||
int rows = mRgba.rows();
|
||||
|
||||
int xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
|
||||
int yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
|
||||
|
||||
int x = (int)event.getX() - xOffset;
|
||||
int y = (int)event.getY() - yOffset;
|
||||
|
||||
Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")");
|
||||
|
||||
if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false;
|
||||
|
||||
Rect touchedRect = new Rect();
|
||||
|
||||
touchedRect.x = (x>4) ? x-4 : 0;
|
||||
touchedRect.y = (y>4) ? y-4 : 0;
|
||||
|
||||
touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;
|
||||
touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;
|
||||
|
||||
Mat touchedRegionRgba = mRgba.submat(touchedRect);
|
||||
|
||||
Mat touchedRegionHsv = new Mat();
|
||||
Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
|
||||
// Calculate average color of touched region
|
||||
mBlobColorHsv = Core.sumElems(touchedRegionHsv);
|
||||
int pointCount = touchedRect.width*touchedRect.height;
|
||||
for (int i = 0; i < mBlobColorHsv.val.length; i++)
|
||||
mBlobColorHsv.val[i] /= pointCount;
|
||||
|
||||
mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv);
|
||||
|
||||
Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] +
|
||||
", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")");
|
||||
|
||||
mDetector.setHsvColor(mBlobColorHsv);
|
||||
|
||||
Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE);
|
||||
|
||||
mIsColorSelected = true;
|
||||
|
||||
touchedRegionRgba.release();
|
||||
touchedRegionHsv.release();
|
||||
|
||||
return false; // don't need subsequent touch events
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
mRgba = inputFrame.rgba();
|
||||
|
||||
if (mIsColorSelected) {
|
||||
mDetector.process(mRgba);
|
||||
List<MatOfPoint> contours = mDetector.getContours();
|
||||
Log.e(TAG, "Contours count: " + contours.size());
|
||||
Core.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
|
||||
|
||||
Mat colorLabel = mRgba.submat(4, 68, 4, 68);
|
||||
colorLabel.setTo(mBlobColorRgba);
|
||||
|
||||
Mat spectrumLabel = mRgba.submat(4, 4 + mSpectrum.rows(), 70, 70 + mSpectrum.cols());
|
||||
mSpectrum.copyTo(spectrumLabel);
|
||||
}
|
||||
|
||||
return mRgba;
|
||||
}
|
||||
|
||||
private Scalar converScalarHsv2Rgba(Scalar hsvColor) {
|
||||
Mat pointMatRgba = new Mat();
|
||||
Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor);
|
||||
Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4);
|
||||
|
||||
return new Scalar(pointMatRgba.get(0, 0));
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package org.opencv.samples.colorblobdetect;
|
||||
|
||||
import java.util.List;
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfPoint;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
|
||||
public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchListener {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
|
||||
private Mat mRgba;
|
||||
private boolean mIsColorSelected = false;
|
||||
private Scalar mBlobColorRgba = new Scalar(255);
|
||||
private Scalar mBlobColorHsv = new Scalar(255);
|
||||
private ColorBlobDetector mDetector = new ColorBlobDetector();
|
||||
private Mat mSpectrum = new Mat();
|
||||
private static Size SPECTRUM_SIZE = new Size(200, 32);
|
||||
private static final Scalar CONTOUR_COLOR = new Scalar(255,0,0,255);
|
||||
|
||||
|
||||
public ColorBlobDetectionView(Context context) {
|
||||
super(context);
|
||||
setOnTouchListener(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
synchronized (this) {
|
||||
// initialize Mat before usage
|
||||
mRgba = new Mat();
|
||||
}
|
||||
|
||||
super.surfaceCreated(holder);
|
||||
}
|
||||
|
||||
private Scalar converScalarHsv2Rgba(Scalar hsvColor) {
|
||||
Mat pointMatRgba = new Mat();
|
||||
Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor);
|
||||
Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4);
|
||||
|
||||
return new Scalar(pointMatRgba.get(0, 0));
|
||||
}
|
||||
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
int cols = mRgba.cols();
|
||||
int rows = mRgba.rows();
|
||||
|
||||
int xOffset = (getWidth() - cols) / 2;
|
||||
int yOffset = (getHeight() - rows) / 2;
|
||||
|
||||
int x = (int)event.getX() - xOffset;
|
||||
int y = (int)event.getY() - yOffset;
|
||||
|
||||
Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")");
|
||||
|
||||
if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false;
|
||||
|
||||
Rect touchedRect = new Rect();
|
||||
|
||||
touchedRect.x = (x>4) ? x-4 : 0;
|
||||
touchedRect.y = (y>4) ? y-4 : 0;
|
||||
|
||||
touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;
|
||||
touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;
|
||||
|
||||
Mat touchedRegionRgba = mRgba.submat(touchedRect);
|
||||
|
||||
Mat touchedRegionHsv = new Mat();
|
||||
Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
|
||||
// Calculate average color of touched region
|
||||
mBlobColorHsv = Core.sumElems(touchedRegionHsv);
|
||||
int pointCount = touchedRect.width*touchedRect.height;
|
||||
for (int i = 0; i < mBlobColorHsv.val.length; i++)
|
||||
mBlobColorHsv.val[i] /= pointCount;
|
||||
|
||||
mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv);
|
||||
|
||||
Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] +
|
||||
", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")");
|
||||
|
||||
mDetector.setHsvColor(mBlobColorHsv);
|
||||
|
||||
Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE);
|
||||
|
||||
mIsColorSelected = true;
|
||||
|
||||
return false; // don't need subsequent touch events
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
if (mIsColorSelected) {
|
||||
mDetector.process(mRgba);
|
||||
List<MatOfPoint> contours = mDetector.getContours();
|
||||
Log.e(TAG, "Contours count: " + contours.size());
|
||||
Core.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
|
||||
|
||||
Mat colorLabel = mRgba.submat(2, 34, 2, 34);
|
||||
colorLabel.setTo(mBlobColorRgba);
|
||||
|
||||
Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols());
|
||||
mSpectrum.copyTo(spectrumLabel);
|
||||
}
|
||||
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
bmp = null;
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
|
||||
synchronized (this) {
|
||||
// Explicitly deallocate Mats
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
|
||||
mRgba = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,13 @@ public class ColorBlobDetector {
|
||||
private Mat mSpectrum = new Mat();
|
||||
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) {
|
||||
mColorRadius = radius;
|
||||
}
|
||||
@@ -61,23 +68,17 @@ public class ColorBlobDetector {
|
||||
}
|
||||
|
||||
public void process(Mat rgbaImage) {
|
||||
Mat pyrDownMat = new Mat();
|
||||
Imgproc.pyrDown(rgbaImage, mPyrDownMat);
|
||||
Imgproc.pyrDown(mPyrDownMat, mPyrDownMat);
|
||||
|
||||
Imgproc.pyrDown(rgbaImage, pyrDownMat);
|
||||
Imgproc.pyrDown(pyrDownMat, pyrDownMat);
|
||||
Imgproc.cvtColor(mPyrDownMat, mHsvMat, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
|
||||
Mat hsvMat = new Mat();
|
||||
Imgproc.cvtColor(pyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
|
||||
Mat Mask = new Mat();
|
||||
Core.inRange(hsvMat, mLowerBound, mUpperBound, Mask);
|
||||
Mat dilatedMask = new Mat();
|
||||
Imgproc.dilate(Mask, dilatedMask, new Mat());
|
||||
Core.inRange(mHsvMat, mLowerBound, mUpperBound, mMask);
|
||||
Imgproc.dilate(mMask, mDilatedMask, new Mat());
|
||||
|
||||
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
|
||||
double maxArea = 0;
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package org.opencv.samples.colorblobdetect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.highgui.Highgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private SurfaceHolder mHolder;
|
||||
private VideoCapture mCamera;
|
||||
|
||||
public SampleCvViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public synchronized boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
releaseCamera();
|
||||
Log.e(TAG, "Can't open native camera");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
protected abstract Bitmap processFrame(VideoCapture capture);
|
||||
|
||||
public void run() {
|
||||
Log.i(TAG, "Started processing thread");
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
|
||||
if (!mCamera.grab()) {
|
||||
Log.e(TAG, "mCamera.grab() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.303359177" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.373249505" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.1424359063" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
@@ -40,8 +40,8 @@
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1156172258" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.149918263" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.719752707" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.opencv.samples.fd"
|
||||
package="org.opencv.samples.facedetect"
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="FdActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS := -frtti -fexceptions
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_PLATFORM := android-8
|
||||
|
||||
@@ -65,15 +65,15 @@ struct DetectorAgregator
|
||||
}
|
||||
};
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject
|
||||
JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject
|
||||
(JNIEnv * jenv, jclass, jstring jFileName, jint faceSize)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject enter");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject enter");
|
||||
const char* jnamestr = jenv->GetStringUTFChars(jFileName, NULL);
|
||||
string stdFileName(jnamestr);
|
||||
jlong result = 0;
|
||||
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -86,9 +86,9 @@ JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeC
|
||||
//trackingDetector->setMinObjectSize(Size(faceSize, faceSize));
|
||||
}
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeCreateObject catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeCreateObject caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -96,20 +96,20 @@ JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeC
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeCreateObject catched unknown exception");
|
||||
LOGD("nativeCreateObject caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject(...)}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject exit");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject exit");
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDestroyObject
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDestroyObject
|
||||
(JNIEnv * jenv, jclass, jlong thiz)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDestroyObject");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDestroyObject");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -119,9 +119,9 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDe
|
||||
delete (DetectorAgregator*)thiz;
|
||||
}
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeestroyObject catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeestroyObject caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -129,25 +129,25 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDe
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeDestroyObject catched unknown exception");
|
||||
LOGD("nativeDestroyObject caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDestroyObject(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDestroyObject(...)}");
|
||||
}
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDestroyObject exit");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDestroyObject exit");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStart
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStart
|
||||
(JNIEnv * jenv, jclass, jlong thiz)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStart");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStart");
|
||||
|
||||
try
|
||||
{
|
||||
((DetectorAgregator*)thiz)->tracker->run();
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeStart catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeStart caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -155,25 +155,25 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSt
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeStart catched unknown exception");
|
||||
LOGD("nativeStart caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStart(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStart(...)}");
|
||||
}
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStart exit");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStart exit");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStop
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStop
|
||||
(JNIEnv * jenv, jclass, jlong thiz)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStop");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStop");
|
||||
|
||||
try
|
||||
{
|
||||
((DetectorAgregator*)thiz)->tracker->stop();
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeStop catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeStop caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -181,17 +181,17 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSt
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeStop catched unknown exception");
|
||||
LOGD("nativeStop caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStop(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStop(...)}");
|
||||
}
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStop exit");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStop exit");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSetFaceSize
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSetFaceSize
|
||||
(JNIEnv * jenv, jclass, jlong thiz, jint faceSize)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSetFaceSize -- BEGIN");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSetFaceSize -- BEGIN");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -201,9 +201,9 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSe
|
||||
//((DetectorAgregator*)thiz)->trackingDetector->setMinObjectSize(Size(faceSize, faceSize));
|
||||
}
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeStop catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeStop caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -211,18 +211,18 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSe
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeSetFaceSize catched unknown exception");
|
||||
LOGD("nativeSetFaceSize caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSetFaceSize(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSetFaceSize(...)}");
|
||||
}
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSetFaceSize -- END");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSetFaceSize -- END");
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDetect
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect
|
||||
(JNIEnv * jenv, jclass, jlong thiz, jlong imageGray, jlong faces)
|
||||
{
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDetect");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -231,9 +231,9 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDe
|
||||
((DetectorAgregator*)thiz)->tracker->getObjects(RectFaces);
|
||||
*((Mat*)faces) = Mat(RectFaces, true);
|
||||
}
|
||||
catch(cv::Exception e)
|
||||
catch(cv::Exception& e)
|
||||
{
|
||||
LOGD("nativeCreateObject catched cv::Exception: %s", e.what());
|
||||
LOGD("nativeCreateObject caught cv::Exception: %s", e.what());
|
||||
jclass je = jenv->FindClass("org/opencv/core/CvException");
|
||||
if(!je)
|
||||
je = jenv->FindClass("java/lang/Exception");
|
||||
@@ -241,9 +241,9 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDe
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGD("nativeDetect catched unknown exception");
|
||||
LOGD("nativeDetect caught unknown exception");
|
||||
jclass je = jenv->FindClass("java/lang/Exception");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDetect(...)}");
|
||||
jenv->ThrowNew(je, "Unknown exception in JNI code {Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect(...)}");
|
||||
}
|
||||
LOGD("Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDetect END");
|
||||
LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect END");
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ extern "C" {
|
||||
* Method: nativeCreateObject
|
||||
* Signature: (Ljava/lang/String;F)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeCreateObject
|
||||
JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject
|
||||
(JNIEnv *, jclass, jstring, jint);
|
||||
|
||||
/*
|
||||
@@ -20,7 +20,7 @@ JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeC
|
||||
* Method: nativeDestroyObject
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDestroyObject
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDestroyObject
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
@@ -28,7 +28,7 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDe
|
||||
* Method: nativeStart
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStart
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStart
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
@@ -36,7 +36,7 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSt
|
||||
* Method: nativeStop
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeStop
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeStop
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
@@ -44,7 +44,7 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSt
|
||||
* Method: nativeSetFaceSize
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSetFaceSize
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSetFaceSize
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
|
||||
/*
|
||||
@@ -52,7 +52,7 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeSt
|
||||
* Method: nativeDetect
|
||||
* Signature: (JJJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBasedTracker_nativeDetect
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect
|
||||
(JNIEnv *, jclass, jlong, jlong, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/fd_activity_surface_view" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.opencv.samples.fd;
|
||||
package org.opencv.samples.facedetect;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfRect;
|
||||
@@ -0,0 +1,243 @@
|
||||
package org.opencv.samples.facedetect;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfRect;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
import org.opencv.objdetect.CascadeClassifier;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class FdActivity extends Activity implements CvCameraViewListener2 {
|
||||
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
|
||||
public static final int JAVA_DETECTOR = 0;
|
||||
public static final int NATIVE_DETECTOR = 1;
|
||||
|
||||
private MenuItem mItemFace50;
|
||||
private MenuItem mItemFace40;
|
||||
private MenuItem mItemFace30;
|
||||
private MenuItem mItemFace20;
|
||||
private MenuItem mItemType;
|
||||
|
||||
private Mat mRgba;
|
||||
private Mat mGray;
|
||||
private File mCascadeFile;
|
||||
private CascadeClassifier mJavaDetector;
|
||||
private DetectionBasedTracker mNativeDetector;
|
||||
|
||||
private int mDetectorType = JAVA_DETECTOR;
|
||||
private String[] mDetectorName;
|
||||
|
||||
private float mRelativeFaceSize = 0.2f;
|
||||
private int mAbsoluteFaceSize = 0;
|
||||
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
|
||||
// Load native library after(!) OpenCV initialization
|
||||
System.loadLibrary("detection_based_tracker");
|
||||
|
||||
try {
|
||||
// load cascade file from application resources
|
||||
InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
|
||||
File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
|
||||
mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
|
||||
FileOutputStream os = new FileOutputStream(mCascadeFile);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
|
||||
mJavaDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());
|
||||
if (mJavaDetector.empty()) {
|
||||
Log.e(TAG, "Failed to load cascade classifier");
|
||||
mJavaDetector = null;
|
||||
} else
|
||||
Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());
|
||||
|
||||
mNativeDetector = new DetectionBasedTracker(mCascadeFile.getAbsolutePath(), 0);
|
||||
|
||||
cascadeDir.delete();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
|
||||
}
|
||||
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public FdActivity() {
|
||||
mDetectorName = new String[2];
|
||||
mDetectorName[JAVA_DETECTOR] = "Java";
|
||||
mDetectorName[NATIVE_DETECTOR] = "Native (tracking)";
|
||||
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@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.face_detect_surface_view);
|
||||
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.fd_activity_surface_view);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
mGray = new Mat();
|
||||
mRgba = new Mat();
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
mGray.release();
|
||||
mRgba.release();
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
|
||||
mRgba = inputFrame.rgba();
|
||||
mGray = inputFrame.gray();
|
||||
|
||||
if (mAbsoluteFaceSize == 0) {
|
||||
int height = mGray.rows();
|
||||
if (Math.round(height * mRelativeFaceSize) > 0) {
|
||||
mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
|
||||
}
|
||||
mNativeDetector.setMinFaceSize(mAbsoluteFaceSize);
|
||||
}
|
||||
|
||||
MatOfRect faces = new MatOfRect();
|
||||
|
||||
if (mDetectorType == JAVA_DETECTOR) {
|
||||
if (mJavaDetector != null)
|
||||
mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
|
||||
new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
|
||||
}
|
||||
else if (mDetectorType == NATIVE_DETECTOR) {
|
||||
if (mNativeDetector != null)
|
||||
mNativeDetector.detect(mGray, faces);
|
||||
}
|
||||
else {
|
||||
Log.e(TAG, "Detection method is not selected!");
|
||||
}
|
||||
|
||||
Rect[] facesArray = faces.toArray();
|
||||
for (int i = 0; i < facesArray.length; i++)
|
||||
Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);
|
||||
|
||||
return mRgba;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemFace50 = menu.add("Face size 50%");
|
||||
mItemFace40 = menu.add("Face size 40%");
|
||||
mItemFace30 = menu.add("Face size 30%");
|
||||
mItemFace20 = menu.add("Face size 20%");
|
||||
mItemType = menu.add(mDetectorName[mDetectorType]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemFace50)
|
||||
setMinFaceSize(0.5f);
|
||||
else if (item == mItemFace40)
|
||||
setMinFaceSize(0.4f);
|
||||
else if (item == mItemFace30)
|
||||
setMinFaceSize(0.3f);
|
||||
else if (item == mItemFace20)
|
||||
setMinFaceSize(0.2f);
|
||||
else if (item == mItemType) {
|
||||
mDetectorType = (mDetectorType + 1) % mDetectorName.length;
|
||||
item.setTitle(mDetectorName[mDetectorType]);
|
||||
setDetectorType(mDetectorType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setMinFaceSize(float faceSize) {
|
||||
mRelativeFaceSize = faceSize;
|
||||
mAbsoluteFaceSize = 0;
|
||||
}
|
||||
|
||||
private void setDetectorType(int type) {
|
||||
if (mDetectorType != type) {
|
||||
mDetectorType = type;
|
||||
|
||||
if (type == NATIVE_DETECTOR) {
|
||||
Log.i(TAG, "Detection Based Tracker enabled");
|
||||
mNativeDetector.start();
|
||||
} else {
|
||||
Log.i(TAG, "Cascade detector enabled");
|
||||
mNativeDetector.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package org.opencv.samples.fd;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class FdActivity extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private MenuItem mItemFace50;
|
||||
private MenuItem mItemFace40;
|
||||
private MenuItem mItemFace30;
|
||||
private MenuItem mItemFace20;
|
||||
private MenuItem mItemType;
|
||||
private int mDetectorType = 0;
|
||||
private String[] mDetectorName;
|
||||
private FdView mView;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
|
||||
// Load native libs after OpenCV initialization
|
||||
System.loadLibrary("detection_based_tracker");
|
||||
|
||||
// Create and set View
|
||||
mView = new FdView(mAppContext);
|
||||
mView.setDetectorType(mDetectorType);
|
||||
mView.setMinFaceSize(0.2f);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public FdActivity() {
|
||||
mDetectorName = new String[2];
|
||||
mDetectorName[FdView.JAVA_DETECTOR] = "Java";
|
||||
mDetectorName[FdView.NATIVE_DETECTOR] = "Native (tracking)";
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemFace50 = menu.add("Face size 50%");
|
||||
mItemFace40 = menu.add("Face size 40%");
|
||||
mItemFace30 = menu.add("Face size 30%");
|
||||
mItemFace20 = menu.add("Face size 20%");
|
||||
mItemType = menu.add(mDetectorName[mDetectorType]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemFace50)
|
||||
mView.setMinFaceSize(0.5f);
|
||||
else if (item == mItemFace40)
|
||||
mView.setMinFaceSize(0.4f);
|
||||
else if (item == mItemFace30)
|
||||
mView.setMinFaceSize(0.3f);
|
||||
else if (item == mItemFace20)
|
||||
mView.setMinFaceSize(0.2f);
|
||||
else if (item == mItemType) {
|
||||
mDetectorType = (mDetectorType + 1) % mDetectorName.length;
|
||||
item.setTitle(mDetectorName[mDetectorType]);
|
||||
mView.setDetectorType(mDetectorType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
package org.opencv.samples.fd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfRect;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.objdetect.CascadeClassifier;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
class FdView extends SampleCvViewBase {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
private Mat mRgba;
|
||||
private Mat mGray;
|
||||
private File mCascadeFile;
|
||||
private CascadeClassifier mJavaDetector;
|
||||
private DetectionBasedTracker mNativeDetector;
|
||||
|
||||
private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
|
||||
|
||||
public static final int JAVA_DETECTOR = 0;
|
||||
public static final int NATIVE_DETECTOR = 1;
|
||||
|
||||
private int mDetectorType = JAVA_DETECTOR;
|
||||
|
||||
private float mRelativeFaceSize = 0;
|
||||
private int mAbsoluteFaceSize = 0;
|
||||
|
||||
public void setMinFaceSize(float faceSize) {
|
||||
mRelativeFaceSize = faceSize;
|
||||
mAbsoluteFaceSize = 0;
|
||||
}
|
||||
|
||||
public void setDetectorType(int type) {
|
||||
if (mDetectorType != type) {
|
||||
mDetectorType = type;
|
||||
|
||||
if (type == NATIVE_DETECTOR) {
|
||||
Log.i(TAG, "Detection Based Tracker enabled");
|
||||
mNativeDetector.start();
|
||||
} else {
|
||||
Log.i(TAG, "Cascade detector enabled");
|
||||
mNativeDetector.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FdView(Context context) {
|
||||
super(context);
|
||||
|
||||
try {
|
||||
// load cascade file from application resources
|
||||
InputStream is = context.getResources().openRawResource(R.raw.lbpcascade_frontalface);
|
||||
File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE);
|
||||
mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
|
||||
FileOutputStream os = new FileOutputStream(mCascadeFile);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
|
||||
mJavaDetector = new CascadeClassifier(mCascadeFile.getAbsolutePath());
|
||||
if (mJavaDetector.empty()) {
|
||||
Log.e(TAG, "Failed to load cascade classifier");
|
||||
mJavaDetector = null;
|
||||
} else
|
||||
Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());
|
||||
|
||||
mNativeDetector = new DetectionBasedTracker(mCascadeFile.getAbsolutePath(), 0);
|
||||
|
||||
cascadeDir.delete();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
synchronized (this) {
|
||||
// initialize Mats before usage
|
||||
mGray = new Mat();
|
||||
mRgba = new Mat();
|
||||
}
|
||||
|
||||
super.surfaceCreated(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
|
||||
|
||||
if (mAbsoluteFaceSize == 0) {
|
||||
int height = mGray.rows();
|
||||
if (Math.round(height * mRelativeFaceSize) > 0) {
|
||||
mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
|
||||
}
|
||||
mNativeDetector.setMinFaceSize(mAbsoluteFaceSize);
|
||||
}
|
||||
|
||||
MatOfRect faces = new MatOfRect();
|
||||
|
||||
if (mDetectorType == JAVA_DETECTOR) {
|
||||
if (mJavaDetector != null)
|
||||
mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
|
||||
new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
|
||||
}
|
||||
else if (mDetectorType == NATIVE_DETECTOR) {
|
||||
if (mNativeDetector != null)
|
||||
mNativeDetector.detect(mGray, faces);
|
||||
}
|
||||
else {
|
||||
Log.e(TAG, "Detection method is not selected!");
|
||||
}
|
||||
|
||||
Rect[] facesArray = faces.toArray();
|
||||
for (int i = 0; i < facesArray.length; i++)
|
||||
Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
bmp = null;
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
|
||||
synchronized (this) {
|
||||
// Explicitly deallocate Mats
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
if (mGray != null)
|
||||
mGray.release();
|
||||
if (mCascadeFile != null)
|
||||
mCascadeFile.delete();
|
||||
if (mNativeDetector != null)
|
||||
mNativeDetector.release();
|
||||
|
||||
mRgba = null;
|
||||
mGray = null;
|
||||
mCascadeFile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.opencv.samples.fd;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.Log;
|
||||
|
||||
public class FpsMeter {
|
||||
private static final String TAG = "OCVSample::FpsMeter";
|
||||
int step;
|
||||
int framesCouner;
|
||||
double freq;
|
||||
long prevFrameTime;
|
||||
String strfps;
|
||||
DecimalFormat twoPlaces = new DecimalFormat("0.00");
|
||||
Paint paint;
|
||||
|
||||
public void init() {
|
||||
step = 20;
|
||||
framesCouner = 0;
|
||||
freq = Core.getTickFrequency();
|
||||
prevFrameTime = Core.getTickCount();
|
||||
strfps = "";
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor(Color.BLUE);
|
||||
paint.setTextSize(50);
|
||||
}
|
||||
|
||||
public void measure() {
|
||||
framesCouner++;
|
||||
if (framesCouner % step == 0) {
|
||||
long time = Core.getTickCount();
|
||||
double fps = step * freq / (time - prevFrameTime);
|
||||
prevFrameTime = time;
|
||||
DecimalFormat twoPlaces = new DecimalFormat("0.00");
|
||||
strfps = twoPlaces.format(fps) + " FPS";
|
||||
Log.i(TAG, strfps);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, float offsetx, float offsety) {
|
||||
canvas.drawText(strfps, 20 + offsetx, 10 + 50 + offsety, paint);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
package org.opencv.samples.fd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.highgui.Highgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private SurfaceHolder mHolder;
|
||||
private VideoCapture mCamera;
|
||||
private FpsMeter mFps;
|
||||
|
||||
public SampleCvViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
mFps = new FpsMeter();
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public synchronized boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
releaseCamera();
|
||||
Log.e(TAG, "Can't open native camera");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
protected abstract Bitmap processFrame(VideoCapture capture);
|
||||
|
||||
public void run() {
|
||||
Log.i(TAG, "Started processing thread");
|
||||
mFps.init();
|
||||
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
|
||||
if (!mCamera.grab()) {
|
||||
Log.e(TAG, "mCamera.grab() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
|
||||
mFps.measure();
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
|
||||
mFps.draw(canvas, (canvas.getWidth() - bmp.getWidth()) / 2, 0);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ int main(int argc, char* argv[])
|
||||
printf("%s\n", message);
|
||||
|
||||
// put message to simple image
|
||||
Size textsize = getTextSize(message, CV_FONT_HERSHEY_COMPLEX, 3, 5, 0);
|
||||
Size textsize = getTextSize(message, FONT_HERSHEY_COMPLEX, 3, 5, 0);
|
||||
Mat img(textsize.height + 20, textsize.width + 20, CV_32FC1, Scalar(230,230,230));
|
||||
putText(img, message, Point(10, img.rows - 10), CV_FONT_HERSHEY_COMPLEX, 3, Scalar(0, 0, 0), 5);
|
||||
putText(img, message, Point(10, img.rows - 10), FONT_HERSHEY_COMPLEX, 3, Scalar(0, 0, 0), 5);
|
||||
|
||||
// save\show resulting image
|
||||
#if ANDROID
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="ImageManipulationsActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/image_manipulations_activity_surface_view" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.opencv.samples.imagemanipulations;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.Log;
|
||||
|
||||
public class FpsMeter {
|
||||
private static final String TAG = "OCVSample::FpsMeter";
|
||||
int step;
|
||||
int framesCouner;
|
||||
double freq;
|
||||
long prevFrameTime;
|
||||
String strfps;
|
||||
DecimalFormat twoPlaces = new DecimalFormat("0.00");
|
||||
Paint paint;
|
||||
|
||||
public void init() {
|
||||
step = 20;
|
||||
framesCouner = 0;
|
||||
freq = Core.getTickFrequency();
|
||||
prevFrameTime = Core.getTickCount();
|
||||
strfps = "";
|
||||
|
||||
paint = new Paint();
|
||||
paint.setColor(Color.BLUE);
|
||||
paint.setTextSize(50);
|
||||
}
|
||||
|
||||
public void measure() {
|
||||
framesCouner++;
|
||||
if (framesCouner % step == 0) {
|
||||
long time = Core.getTickCount();
|
||||
double fps = step * freq / (time - prevFrameTime);
|
||||
prevFrameTime = time;
|
||||
DecimalFormat twoPlaces = new DecimalFormat("0.00");
|
||||
strfps = twoPlaces.format(fps) + " FPS";
|
||||
Log.i(TAG, strfps);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, float offsetx, float offsety) {
|
||||
canvas.drawText(strfps, 20 + offsetx, 10 + 50 + offsety, paint);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +1,87 @@
|
||||
package org.opencv.samples.imagemanipulations;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
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.MatOfFloat;
|
||||
import org.opencv.core.MatOfInt;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class ImageManipulationsActivity extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
public class ImageManipulationsActivity extends Activity implements CvCameraViewListener2 {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
public static final int VIEW_MODE_RGBA = 0;
|
||||
public static final int VIEW_MODE_HIST = 1;
|
||||
public static final int VIEW_MODE_CANNY = 2;
|
||||
public static final int VIEW_MODE_SEPIA = 3;
|
||||
public static final int VIEW_MODE_SOBEL = 4;
|
||||
public static final int VIEW_MODE_ZOOM = 5;
|
||||
public static final int VIEW_MODE_PIXELIZE = 6;
|
||||
public static final int VIEW_MODE_POSTERIZE = 7;
|
||||
public static final int VIEW_MODE_RGBA = 0;
|
||||
public static final int VIEW_MODE_HIST = 1;
|
||||
public static final int VIEW_MODE_CANNY = 2;
|
||||
public static final int VIEW_MODE_SEPIA = 3;
|
||||
public static final int VIEW_MODE_SOBEL = 4;
|
||||
public static final int VIEW_MODE_ZOOM = 5;
|
||||
public static final int VIEW_MODE_PIXELIZE = 6;
|
||||
public static final int VIEW_MODE_POSTERIZE = 7;
|
||||
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewHist;
|
||||
private MenuItem mItemPreviewCanny;
|
||||
private MenuItem mItemPreviewSepia;
|
||||
private MenuItem mItemPreviewSobel;
|
||||
private MenuItem mItemPreviewZoom;
|
||||
private MenuItem mItemPreviewPixelize;
|
||||
private MenuItem mItemPreviewPosterize;
|
||||
private ImageManipulationsView mView;
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewHist;
|
||||
private MenuItem mItemPreviewCanny;
|
||||
private MenuItem mItemPreviewSepia;
|
||||
private MenuItem mItemPreviewSobel;
|
||||
private MenuItem mItemPreviewZoom;
|
||||
private MenuItem mItemPreviewPixelize;
|
||||
private MenuItem mItemPreviewPosterize;
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
private Size mSize0;
|
||||
private Size mSizeRgba;
|
||||
private Size mSizeRgbaInner;
|
||||
|
||||
private Mat mRgba;
|
||||
private Mat mGray;
|
||||
private Mat mIntermediateMat;
|
||||
private Mat mHist;
|
||||
private Mat mMat0;
|
||||
private MatOfInt mChannels[];
|
||||
private MatOfInt mHistSize;
|
||||
private int mHistSizeNum;
|
||||
private MatOfFloat mRanges;
|
||||
private Scalar mColorsRGB[];
|
||||
private Scalar mColorsHue[];
|
||||
private Scalar mWhilte;
|
||||
private Point mP1;
|
||||
private Point mP2;
|
||||
private float mBuff[];
|
||||
private Mat mRgbaInnerWindow;
|
||||
private Mat mGrayInnerWindow;
|
||||
private Mat mZoomWindow;
|
||||
private Mat mZoomCorner;
|
||||
private Mat mSepiaKernel;
|
||||
|
||||
public static int viewMode = VIEW_MODE_RGBA;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new ImageManipulationsView(mAppContext);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
@@ -91,32 +95,38 @@ public class ImageManipulationsActivity extends Activity {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
setContentView(R.layout.image_manipulations_surface_view);
|
||||
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.image_manipulations_activity_surface_view);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,4 +164,199 @@ public class ImageManipulationsActivity extends Activity {
|
||||
viewMode = VIEW_MODE_POSTERIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
mGray = new Mat();
|
||||
mRgba = new Mat();
|
||||
mIntermediateMat = new Mat();
|
||||
mSize0 = new Size();
|
||||
mHist = new Mat();
|
||||
mChannels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1), new MatOfInt(2) };
|
||||
mHistSizeNum = 25;
|
||||
mBuff = new float[mHistSizeNum];
|
||||
mHistSize = new MatOfInt(mHistSizeNum);
|
||||
mRanges = new MatOfFloat(0f, 256f);
|
||||
mMat0 = new Mat();
|
||||
mColorsRGB = new Scalar[] { new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255) };
|
||||
mColorsHue = new Scalar[] {
|
||||
new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255),
|
||||
new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255),
|
||||
new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255),
|
||||
new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255),
|
||||
new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255)
|
||||
};
|
||||
mWhilte = Scalar.all(255);
|
||||
mP1 = new Point();
|
||||
mP2 = new Point();
|
||||
|
||||
// Fill sepia kernel
|
||||
mSepiaKernel = new Mat(4, 4, CvType.CV_32F);
|
||||
mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f);
|
||||
mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f);
|
||||
mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f);
|
||||
mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f);
|
||||
}
|
||||
|
||||
private void CreateAuxiliaryMats() {
|
||||
if (mRgba.empty())
|
||||
return;
|
||||
|
||||
mSizeRgba = mRgba.size();
|
||||
|
||||
int rows = (int) mSizeRgba.height;
|
||||
int cols = (int) mSizeRgba.width;
|
||||
|
||||
int left = cols / 8;
|
||||
int top = rows / 8;
|
||||
|
||||
int width = cols * 3 / 4;
|
||||
int height = rows * 3 / 4;
|
||||
|
||||
if (mRgbaInnerWindow == null)
|
||||
mRgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);
|
||||
mSizeRgbaInner = mRgbaInnerWindow.size();
|
||||
|
||||
if (mGrayInnerWindow == null && !mGray.empty())
|
||||
mGrayInnerWindow = mGray.submat(top, top + height, left, left + width);
|
||||
|
||||
if (mZoomCorner == null)
|
||||
mZoomCorner = mRgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10);
|
||||
|
||||
if (mZoomWindow == null)
|
||||
mZoomWindow = mRgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100);
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
// Explicitly deallocate Mats
|
||||
if (mZoomWindow != null)
|
||||
mZoomWindow.release();
|
||||
if (mZoomCorner != null)
|
||||
mZoomCorner.release();
|
||||
if (mGrayInnerWindow != null)
|
||||
mGrayInnerWindow.release();
|
||||
if (mRgbaInnerWindow != null)
|
||||
mRgbaInnerWindow.release();
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
if (mGray != null)
|
||||
mGray.release();
|
||||
if (mIntermediateMat != null)
|
||||
mIntermediateMat.release();
|
||||
|
||||
mRgba = null;
|
||||
mGray = null;
|
||||
mIntermediateMat = null;
|
||||
mRgbaInnerWindow = null;
|
||||
mGrayInnerWindow = null;
|
||||
mZoomCorner = null;
|
||||
mZoomWindow = null;
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
mRgba = inputFrame.rgba();
|
||||
|
||||
switch (ImageManipulationsActivity.viewMode) {
|
||||
case ImageManipulationsActivity.VIEW_MODE_RGBA:
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_HIST:
|
||||
if ((mSizeRgba == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
int thikness = (int) (mSizeRgba.width / (mHistSizeNum + 10) / 5);
|
||||
if(thikness > 5) thikness = 5;
|
||||
int offset = (int) ((mSizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2);
|
||||
// RGB
|
||||
for(int c=0; c<3; c++) {
|
||||
Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (c * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mColorsRGB[c], thikness);
|
||||
}
|
||||
}
|
||||
// Value and Hue
|
||||
Imgproc.cvtColor(mRgba, mIntermediateMat, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
// Value
|
||||
Imgproc.calcHist(Arrays.asList(mIntermediateMat), mChannels[2], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (3 * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mWhilte, thikness);
|
||||
}
|
||||
// Hue
|
||||
Imgproc.calcHist(Arrays.asList(mIntermediateMat), mChannels[0], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (4 * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mColorsHue[h], thikness);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_CANNY:
|
||||
if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 80, 90);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_SOBEL:
|
||||
mGray = inputFrame.gray();
|
||||
|
||||
if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
|
||||
Imgproc.Sobel(mGrayInnerWindow, mIntermediateMat, CvType.CV_8U, 1, 1);
|
||||
Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_SEPIA:
|
||||
if ((mRgbaInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Core.transform(mRgbaInnerWindow, mRgbaInnerWindow, mSepiaKernel);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_ZOOM:
|
||||
if ((mZoomCorner == null) || (mZoomWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.resize(mZoomWindow, mZoomCorner, mZoomCorner.size());
|
||||
|
||||
Size wsize = mZoomWindow.size();
|
||||
Core.rectangle(mZoomWindow, new Point(1, 1), new Point(wsize.width - 2, wsize.height - 2), new Scalar(255, 0, 0, 255), 2);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_PIXELIZE:
|
||||
if ((mRgbaInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.resize(mRgbaInnerWindow, mIntermediateMat, mSize0, 0.1, 0.1, Imgproc.INTER_NEAREST);
|
||||
Imgproc.resize(mIntermediateMat, mRgbaInnerWindow, mSizeRgbaInner, 0., 0., Imgproc.INTER_NEAREST);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_POSTERIZE:
|
||||
if ((mRgbaInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
/*
|
||||
Imgproc.cvtColor(mRgbaInnerWindow, mIntermediateMat, Imgproc.COLOR_RGBA2RGB);
|
||||
Imgproc.pyrMeanShiftFiltering(mIntermediateMat, mIntermediateMat, 5, 50);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_RGB2RGBA);
|
||||
*/
|
||||
|
||||
Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 80, 90);
|
||||
mRgbaInnerWindow.setTo(new Scalar(0, 0, 0, 255), mIntermediateMat);
|
||||
Core.convertScaleAbs(mRgbaInnerWindow, mIntermediateMat, 1./16, 0);
|
||||
Core.convertScaleAbs(mIntermediateMat, mRgbaInnerWindow, 16, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return mRgba;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
package org.opencv.samples.imagemanipulations;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfFloat;
|
||||
import org.opencv.core.MatOfInt;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
class ImageManipulationsView extends SampleCvViewBase {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
private Size mSize0;
|
||||
private Size mSizeRgba;
|
||||
private Size mSizeRgbaInner;
|
||||
|
||||
private Mat mRgba;
|
||||
private Mat mGray;
|
||||
private Mat mIntermediateMat;
|
||||
private Mat mHist;
|
||||
private Mat mMat0;
|
||||
private MatOfInt mChannels[];
|
||||
private MatOfInt mHistSize;
|
||||
private int mHistSizeNum;
|
||||
private MatOfFloat mRanges;
|
||||
private Scalar mColorsRGB[];
|
||||
private Scalar mColorsHue[];
|
||||
private Scalar mWhilte;
|
||||
private Point mP1;
|
||||
private Point mP2;
|
||||
private float mBuff[];
|
||||
private Mat mRgbaInnerWindow;
|
||||
private Mat mGrayInnerWindow;
|
||||
private Mat mBlurWindow;
|
||||
private Mat mZoomWindow;
|
||||
private Mat mZoomCorner;
|
||||
private Mat mSepiaKernel;
|
||||
|
||||
public ImageManipulationsView(Context context) {
|
||||
super(context);
|
||||
|
||||
mSepiaKernel = new Mat(4, 4, CvType.CV_32F);
|
||||
mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f);
|
||||
mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f);
|
||||
mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f);
|
||||
mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f);
|
||||
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
synchronized (this) {
|
||||
// initialize Mats before usage
|
||||
mGray = new Mat();
|
||||
mRgba = new Mat();
|
||||
mIntermediateMat = new Mat();
|
||||
mSize0 = new Size();
|
||||
mHist = new Mat();
|
||||
mChannels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1), new MatOfInt(2) };
|
||||
mHistSizeNum = 25;
|
||||
mBuff = new float[mHistSizeNum];
|
||||
mHistSize = new MatOfInt(mHistSizeNum);
|
||||
mRanges = new MatOfFloat(0f, 256f);
|
||||
mMat0 = new Mat();
|
||||
mColorsRGB = new Scalar[] { new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255) };
|
||||
mColorsHue = new Scalar[] {
|
||||
new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255),
|
||||
new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255),
|
||||
new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255),
|
||||
new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255),
|
||||
new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255)
|
||||
};
|
||||
mWhilte = Scalar.all(255);
|
||||
mP1 = new Point();
|
||||
mP2 = new Point();
|
||||
}
|
||||
|
||||
super.surfaceCreated(holder);
|
||||
}
|
||||
|
||||
private void CreateAuxiliaryMats() {
|
||||
if (mRgba.empty())
|
||||
return;
|
||||
|
||||
mSizeRgba = mRgba.size();
|
||||
|
||||
int rows = (int) mSizeRgba.height;
|
||||
int cols = (int) mSizeRgba.width;
|
||||
|
||||
int left = cols / 8;
|
||||
int top = rows / 8;
|
||||
|
||||
int width = cols * 3 / 4;
|
||||
int height = rows * 3 / 4;
|
||||
|
||||
if (mRgbaInnerWindow == null)
|
||||
mRgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);
|
||||
mSizeRgbaInner = mRgbaInnerWindow.size();
|
||||
|
||||
if (mGrayInnerWindow == null && !mGray.empty())
|
||||
mGrayInnerWindow = mGray.submat(top, top + height, left, left + width);
|
||||
|
||||
if (mBlurWindow == null)
|
||||
mBlurWindow = mRgba.submat(0, rows, cols / 3, cols * 2 / 3);
|
||||
|
||||
if (mZoomCorner == null)
|
||||
mZoomCorner = mRgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10);
|
||||
|
||||
if (mZoomWindow == null)
|
||||
mZoomWindow = mRgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
switch (ImageManipulationsActivity.viewMode) {
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_RGBA:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_HIST:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
if ((mSizeRgba == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
int thikness = (int) (mSizeRgba.width / (mHistSizeNum + 10) / 5);
|
||||
if(thikness > 5) thikness = 5;
|
||||
int offset = (int) ((mSizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2);
|
||||
// RGB
|
||||
for(int c=0; c<3; c++) {
|
||||
Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (c * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mColorsRGB[c], thikness);
|
||||
}
|
||||
}
|
||||
// Value and Hue
|
||||
Imgproc.cvtColor(mRgba, mIntermediateMat, Imgproc.COLOR_RGB2HSV_FULL);
|
||||
// Value
|
||||
Imgproc.calcHist(Arrays.asList(mIntermediateMat), mChannels[2], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (3 * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mWhilte, thikness);
|
||||
}
|
||||
// Hue
|
||||
Imgproc.calcHist(Arrays.asList(mIntermediateMat), mChannels[0], mMat0, mHist, mHistSize, mRanges);
|
||||
Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
|
||||
mHist.get(0, 0, mBuff);
|
||||
for(int h=0; h<mHistSizeNum; h++) {
|
||||
mP1.x = mP2.x = offset + (4 * (mHistSizeNum + 10) + h) * thikness;
|
||||
mP1.y = mSizeRgba.height-1;
|
||||
mP2.y = mP1.y - 2 - (int)mBuff[h];
|
||||
Core.line(mRgba, mP1, mP2, mColorsHue[h], thikness);
|
||||
}
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_CANNY:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
|
||||
if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 80, 90);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_SOBEL:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
|
||||
|
||||
if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
|
||||
Imgproc.Sobel(mGrayInnerWindow, mIntermediateMat, CvType.CV_8U, 1, 1);
|
||||
Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_SEPIA:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
Core.transform(mRgba, mRgba, mSepiaKernel);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_ZOOM:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
if ((mZoomCorner == null) || (mZoomWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.resize(mZoomWindow, mZoomCorner, mZoomCorner.size());
|
||||
|
||||
Size wsize = mZoomWindow.size();
|
||||
Core.rectangle(mZoomWindow, new Point(1, 1), new Point(wsize.width - 2, wsize.height - 2), new Scalar(255, 0, 0, 255), 2);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_PIXELIZE:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
if ((mRgbaInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
Imgproc.resize(mRgbaInnerWindow, mIntermediateMat, mSize0, 0.1, 0.1, Imgproc.INTER_NEAREST);
|
||||
Imgproc.resize(mIntermediateMat, mRgbaInnerWindow, mSizeRgbaInner, 0., 0., Imgproc.INTER_NEAREST);
|
||||
break;
|
||||
|
||||
case ImageManipulationsActivity.VIEW_MODE_POSTERIZE:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
if ((mRgbaInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
|
||||
CreateAuxiliaryMats();
|
||||
/*
|
||||
Imgproc.cvtColor(mRgbaInnerWindow, mIntermediateMat, Imgproc.COLOR_RGBA2RGB);
|
||||
Imgproc.pyrMeanShiftFiltering(mIntermediateMat, mIntermediateMat, 5, 50);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_RGB2RGBA);
|
||||
*/
|
||||
Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 80, 90);
|
||||
mRgbaInnerWindow.setTo(new Scalar(0, 0, 0, 255), mIntermediateMat);
|
||||
Core.convertScaleAbs(mRgbaInnerWindow, mIntermediateMat, 1./16, 0);
|
||||
Core.convertScaleAbs(mIntermediateMat, mRgbaInnerWindow, 16, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
return bmp;
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
|
||||
synchronized (this) {
|
||||
// Explicitly deallocate Mats
|
||||
if (mZoomWindow != null)
|
||||
mZoomWindow.release();
|
||||
if (mZoomCorner != null)
|
||||
mZoomCorner.release();
|
||||
if (mBlurWindow != null)
|
||||
mBlurWindow.release();
|
||||
if (mGrayInnerWindow != null)
|
||||
mGrayInnerWindow.release();
|
||||
if (mRgbaInnerWindow != null)
|
||||
mRgbaInnerWindow.release();
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
if (mGray != null)
|
||||
mGray.release();
|
||||
if (mIntermediateMat != null)
|
||||
mIntermediateMat.release();
|
||||
|
||||
mRgba = null;
|
||||
mGray = null;
|
||||
mIntermediateMat = null;
|
||||
mRgbaInnerWindow = null;
|
||||
mGrayInnerWindow = null;
|
||||
mBlurWindow = null;
|
||||
mZoomCorner = null;
|
||||
mZoomWindow = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package org.opencv.samples.imagemanipulations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.highgui.Highgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private SurfaceHolder mHolder;
|
||||
private VideoCapture mCamera;
|
||||
private FpsMeter mFps;
|
||||
|
||||
public SampleCvViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
mFps = new FpsMeter();
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public synchronized boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
releaseCamera();
|
||||
Log.e(TAG, "Can't open native camera");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
protected abstract Bitmap processFrame(VideoCapture capture);
|
||||
|
||||
public void run() {
|
||||
Log.i(TAG, "Started processing thread");
|
||||
mFps.init();
|
||||
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
|
||||
if (!mCamera.grab()) {
|
||||
Log.e(TAG, "mCamera.grab() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
|
||||
mFps.measure();
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()), null);
|
||||
mFps.draw(canvas, (canvas.getWidth() - bmp.getWidth()) / 2, 0);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,75 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="0.1851062783">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1851062783" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="0.1851062783" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.1851062783." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.114738979" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.114738979.901399641" name=""/>
|
||||
<builder autoBuildTarget="" command="${NDKROOT}/ndk-build.cmd" enableAutoBuild="true" enableCleanBuild="false" id="org.eclipse.cdt.build.core.settings.default.builder.1153158428" incrementalBuildTarget="" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.835006420" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1350943194" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1640025837" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.982773030" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.332905639" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.1475512260" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ANDROID=1"/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1082980466" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.472513352" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1490236166" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.945696849" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ANDROID=1"/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.775624510" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="jni"/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="OpenCV Tutorial 3 - Add Native OpenCV.null.1740260315" name="OpenCV Tutorial 3 - Add Native OpenCV"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="0.1851062783">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope" versionNumber="1">
|
||||
<resource resourceType="PROJECT" workspacePath="/OpenCV Tutorial 3 - Add Native OpenCV"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cproject>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="0.129633445">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.129633445" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="0.129633445" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.129633445." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.2006441180" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.2006441180.527973180" name=""/>
|
||||
<builder autoBuildTarget="" command="${NDKROOT}/ndk-build.cmd" enableAutoBuild="true" enableCleanBuild="false" id="org.eclipse.cdt.build.core.settings.default.builder.180541221" incrementalBuildTarget="" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.791069665" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1894181736" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.588929884" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.303359177" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.373249505" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.1424359063" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ANDROID=1"/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.360067880" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1156172258" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.149918263" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.symbols.719752707" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="ANDROID=1"/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.232493949" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="jni"/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="OpenCV Sample - face-detection.null.1639518055" name="OpenCV Sample - face-detection"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="0.129633445">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope" versionNumber="1">
|
||||
<resource resourceType="PROJECT" workspacePath="/OpenCV Sample - face-detection"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cproject>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OpenCV Tutorial 1 - Add OpenCV</name>
|
||||
<name>OpenCV Sample - native-activity</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
33
samples/android/native-activity/AndroidManifest.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.opencv.samples.NativeActivity"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk android:minSdkVersion="9" />
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:debuggable="true">
|
||||
|
||||
<activity android:name="CvNativeActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
android:label="@string/app_name">
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="native_activity" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
|
||||
|
||||
</manifest>
|
||||
@@ -1,12 +1,12 @@
|
||||
set(sample example-tutorial-3-native)
|
||||
set(sample example-native-activity)
|
||||
|
||||
if(BUILD_FAT_JAVA_LIB)
|
||||
set(native_deps opencv_java)
|
||||
else()
|
||||
set(native_deps opencv_features2d)
|
||||
set(native_deps opencv_highgui opencv_imgproc)
|
||||
endif()
|
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps})
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 9 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps})
|
||||
if(TARGET ${sample})
|
||||
add_dependencies(opencv_android_examples ${sample})
|
||||
endif()
|
||||
14
samples/android/native-activity/jni/Android.mk
Normal file
@@ -0,0 +1,14 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include ../../sdk/native/jni/OpenCV.mk
|
||||
|
||||
LOCAL_MODULE := native_activity
|
||||
LOCAL_SRC_FILES := native.cpp
|
||||
LOCAL_LDLIBS += -lm -llog -landroid
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,android/native_app_glue)
|
||||
@@ -1,3 +1,4 @@
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS := -frtti -fexceptions
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_PLATFORM := android-9
|
||||
221
samples/android/native-activity/jni/native.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <jni.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <queue>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
#define LOG_TAG "OCV:libnative_activity"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
struct Engine
|
||||
{
|
||||
android_app* app;
|
||||
cv::Ptr<cv::VideoCapture> capture;
|
||||
};
|
||||
|
||||
static cv::Size calc_optimal_camera_resolution(const char* supported, int width, int height)
|
||||
{
|
||||
int frame_width = 0;
|
||||
int frame_height = 0;
|
||||
|
||||
size_t prev_idx = 0;
|
||||
size_t idx = 0;
|
||||
float min_diff = FLT_MAX;
|
||||
|
||||
do
|
||||
{
|
||||
int tmp_width;
|
||||
int tmp_height;
|
||||
|
||||
prev_idx = idx;
|
||||
while ((supported[idx] != '\0') && (supported[idx] != ','))
|
||||
idx++;
|
||||
|
||||
sscanf(&supported[prev_idx], "%dx%d", &tmp_width, &tmp_height);
|
||||
|
||||
int w_diff = width - tmp_width;
|
||||
int h_diff = height - tmp_height;
|
||||
if ((h_diff >= 0) && (w_diff >= 0))
|
||||
{
|
||||
if ((h_diff <= min_diff) && (tmp_height <= 720))
|
||||
{
|
||||
frame_width = tmp_width;
|
||||
frame_height = tmp_height;
|
||||
min_diff = h_diff;
|
||||
}
|
||||
}
|
||||
|
||||
idx++; // to skip coma symbol
|
||||
|
||||
} while(supported[idx-1] != '\0');
|
||||
|
||||
return cv::Size(frame_width, frame_height);
|
||||
}
|
||||
|
||||
static void engine_draw_frame(Engine* engine, const cv::Mat& frame)
|
||||
{
|
||||
if (engine->app->window == NULL)
|
||||
return; // No window.
|
||||
|
||||
ANativeWindow_Buffer buffer;
|
||||
if (ANativeWindow_lock(engine->app->window, &buffer, NULL) < 0)
|
||||
{
|
||||
LOGW("Unable to lock window buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
void* pixels = buffer.bits;
|
||||
|
||||
int left_indent = (buffer.width-frame.cols)/2;
|
||||
int top_indent = (buffer.height-frame.rows)/2;
|
||||
|
||||
for (int yy = top_indent; yy < std::min(frame.rows+top_indent, buffer.height); yy++)
|
||||
{
|
||||
unsigned char* line = (unsigned char*)pixels;
|
||||
memcpy(line+left_indent*4*sizeof(unsigned char), frame.ptr<unsigned char>(yy),
|
||||
std::min(frame.cols, buffer.width)*4*sizeof(unsigned char));
|
||||
// go to next line
|
||||
pixels = (int32_t*)pixels + buffer.stride;
|
||||
}
|
||||
ANativeWindow_unlockAndPost(engine->app->window);
|
||||
}
|
||||
|
||||
static void engine_handle_cmd(android_app* app, int32_t cmd)
|
||||
{
|
||||
Engine* engine = (Engine*)app->userData;
|
||||
switch (cmd)
|
||||
{
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
if (app->window != NULL)
|
||||
{
|
||||
LOGI("APP_CMD_INIT_WINDOW");
|
||||
|
||||
engine->capture = new cv::VideoCapture(0);
|
||||
|
||||
union {double prop; const char* name;} u;
|
||||
u.prop = engine->capture->get(CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING);
|
||||
|
||||
int view_width = ANativeWindow_getWidth(app->window);
|
||||
int view_height = ANativeWindow_getHeight(app->window);
|
||||
|
||||
cv::Size camera_resolution;
|
||||
if (u.name)
|
||||
camera_resolution = calc_optimal_camera_resolution(u.name, 640, 480);
|
||||
else
|
||||
{
|
||||
LOGE("Cannot get supported camera camera_resolutions");
|
||||
camera_resolution = cv::Size(ANativeWindow_getWidth(app->window),
|
||||
ANativeWindow_getHeight(app->window));
|
||||
}
|
||||
|
||||
if ((camera_resolution.width != 0) && (camera_resolution.height != 0))
|
||||
{
|
||||
engine->capture->set(CV_CAP_PROP_FRAME_WIDTH, camera_resolution.width);
|
||||
engine->capture->set(CV_CAP_PROP_FRAME_HEIGHT, camera_resolution.height);
|
||||
}
|
||||
|
||||
float scale = std::min((float)view_width/camera_resolution.width,
|
||||
(float)view_height/camera_resolution.height);
|
||||
|
||||
if (ANativeWindow_setBuffersGeometry(app->window, (int)(view_width/scale),
|
||||
int(view_height/scale), WINDOW_FORMAT_RGBA_8888) < 0)
|
||||
{
|
||||
LOGE("Cannot set pixel format!");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("Camera initialized at resoution %dx%d", camera_resolution.width, camera_resolution.height);
|
||||
}
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
LOGI("APP_CMD_TERM_WINDOW");
|
||||
|
||||
engine->capture->release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void android_main(android_app* app)
|
||||
{
|
||||
Engine engine;
|
||||
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
memset(&engine, 0, sizeof(engine));
|
||||
app->userData = &engine;
|
||||
app->onAppCmd = engine_handle_cmd;
|
||||
engine.app = app;
|
||||
|
||||
float fps = 0;
|
||||
cv::Mat drawing_frame;
|
||||
std::queue<int64> time_queue;
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
while (1)
|
||||
{
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
android_poll_source* source;
|
||||
|
||||
// Process system events
|
||||
while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
|
||||
{
|
||||
// Process this event.
|
||||
if (source != NULL)
|
||||
{
|
||||
source->process(app, source);
|
||||
}
|
||||
|
||||
// Check if we are exiting.
|
||||
if (app->destroyRequested != 0)
|
||||
{
|
||||
LOGI("Engine thread destroy requested!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int64 then;
|
||||
int64 now = cv::getTickCount();
|
||||
time_queue.push(now);
|
||||
|
||||
// Capture frame from camera and draw it
|
||||
if (!engine.capture.empty())
|
||||
{
|
||||
if (engine.capture->grab())
|
||||
engine.capture->retrieve(drawing_frame, CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
|
||||
char buffer[256];
|
||||
sprintf(buffer, "Display performance: %dx%d @ %.3f", drawing_frame.cols, drawing_frame.rows, fps);
|
||||
cv::putText(drawing_frame, std::string(buffer), cv::Point(8,64),
|
||||
cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(0,255,0,255));
|
||||
engine_draw_frame(&engine, drawing_frame);
|
||||
}
|
||||
|
||||
if (time_queue.size() >= 2)
|
||||
then = time_queue.front();
|
||||
else
|
||||
then = 0;
|
||||
|
||||
if (time_queue.size() >= 25)
|
||||
time_queue.pop();
|
||||
|
||||
fps = time_queue.size() * (float)cv::getTickFrequency() / (now-then);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OCV T0 Android Camera</string>
|
||||
<string name="app_name">OCV Native Activity</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.opencv.samples.NativeActivity;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class CvNativeActivity extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
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("native_activity");
|
||||
Intent intent = new Intent(CvNativeActivity.this, android.app.NativeActivity.class);
|
||||
CvNativeActivity.this.startActivity(intent);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public CvNativeActivity() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,5 +0,0 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.opencv.samples.tutorial0"
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="Sample0Base"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<supports-screens android:resizeable="true"
|
||||
android:smallScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:largeScreens="true"
|
||||
android:anyDensity="true" />
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
|
||||
|
||||
</manifest>
|
||||
@@ -1,7 +0,0 @@
|
||||
set(sample example-tutorial-0-androidcamera)
|
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" SDK_TARGET 11 ${ANDROID_SDK_TARGET})
|
||||
if(TARGET ${sample})
|
||||
add_dependencies(opencv_android_examples ${sample})
|
||||
endif()
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.opencv.samples.tutorial0;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
|
||||
public class Sample0Base extends Activity {
|
||||
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewGray;
|
||||
private Sample0View mView;
|
||||
|
||||
public Sample0Base() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
super.onPause();
|
||||
mView.releaseCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(this).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
mView = new Sample0View(this);
|
||||
setContentView(mView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemPreviewRGBA = menu.add("Preview RGBA");
|
||||
mItemPreviewGray = menu.add("Preview GRAY");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemPreviewRGBA)
|
||||
mView.setViewMode(Sample0View.VIEW_MODE_RGBA);
|
||||
else if (item == mItemPreviewGray)
|
||||
mView.setViewMode(Sample0View.VIEW_MODE_GRAY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package org.opencv.samples.tutorial0;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
class Sample0View extends SampleViewBase {
|
||||
|
||||
private static final String TAG = "OCVSample::View";
|
||||
|
||||
public static final int VIEW_MODE_RGBA = 0;
|
||||
public static final int VIEW_MODE_GRAY = 1;
|
||||
|
||||
int mSize;
|
||||
int[] mRGBA;
|
||||
private Bitmap mBitmap;
|
||||
private int mViewMode;
|
||||
|
||||
public Sample0View(Context context) {
|
||||
super(context);
|
||||
mSize = 0;
|
||||
mViewMode = VIEW_MODE_RGBA;
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(byte[] data) {
|
||||
int frameSize = getFrameWidth() * getFrameHeight();
|
||||
|
||||
int[] rgba = mRGBA;
|
||||
|
||||
final int view_mode = mViewMode;
|
||||
if (view_mode == VIEW_MODE_GRAY) {
|
||||
for (int i = 0; i < frameSize; i++) {
|
||||
int y = (0xff & ((int) data[i]));
|
||||
rgba[i] = 0xff000000 + (y << 16) + (y << 8) + y;
|
||||
}
|
||||
} else if (view_mode == VIEW_MODE_RGBA) {
|
||||
for (int i = 0; i < getFrameHeight(); i++) {
|
||||
for (int j = 0; j < getFrameWidth(); j++) {
|
||||
int index = i * getFrameWidth() + j;
|
||||
int supply_index = frameSize + (i >> 1) * getFrameWidth() + (j & ~1);
|
||||
int y = (0xff & ((int) data[index]));
|
||||
int u = (0xff & ((int) data[supply_index + 0]));
|
||||
int v = (0xff & ((int) data[supply_index + 1]));
|
||||
y = y < 16 ? 16 : y;
|
||||
|
||||
float y_conv = 1.164f * (y - 16);
|
||||
int r = Math.round(y_conv + 1.596f * (v - 128));
|
||||
int g = Math.round(y_conv - 0.813f * (v - 128) - 0.391f * (u - 128));
|
||||
int b = Math.round(y_conv + 2.018f * (u - 128));
|
||||
|
||||
r = r < 0 ? 0 : (r > 255 ? 255 : r);
|
||||
g = g < 0 ? 0 : (g > 255 ? 255 : g);
|
||||
b = b < 0 ? 0 : (b > 255 ? 255 : b);
|
||||
|
||||
rgba[i * getFrameWidth() + j] = 0xff000000 + (b << 16) + (g << 8) + r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBitmap.setPixels(rgba, 0/* offset */, getFrameWidth() /* stride */, 0, 0, getFrameWidth(), getFrameHeight());
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreviewStarted(int previewWidth, int previewHeight) {
|
||||
Log.i(TAG, "called onPreviewStarted("+previewWidth+", "+previewHeight+")");
|
||||
/* Create a bitmap that will be used through to calculate the image to */
|
||||
mBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
|
||||
mRGBA = new int[previewWidth * previewHeight];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreviewStopped() {
|
||||
Log.i(TAG, "called onPreviewStopped");
|
||||
if(mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
mBitmap = null;
|
||||
}
|
||||
|
||||
if(mRGBA != null) {
|
||||
mRGBA = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewMode(int viewMode) {
|
||||
Log.i(TAG, "called setViewMode("+viewMode+")");
|
||||
mViewMode = viewMode;
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package org.opencv.samples.tutorial0;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private Camera mCamera;
|
||||
private SurfaceHolder mHolder;
|
||||
private int mFrameWidth;
|
||||
private int mFrameHeight;
|
||||
private byte[] mFrame;
|
||||
private volatile boolean mThreadRun;
|
||||
private byte[] mBuffer;
|
||||
private SurfaceTexture mSf;
|
||||
|
||||
|
||||
public SampleViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public int getFrameWidth() {
|
||||
return mFrameWidth;
|
||||
}
|
||||
|
||||
public int getFrameHeight() {
|
||||
return mFrameHeight;
|
||||
}
|
||||
|
||||
public void setPreview() throws IOException {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
mSf = new SurfaceTexture(10);
|
||||
mCamera.setPreviewTexture( mSf );
|
||||
}
|
||||
else
|
||||
mCamera.setPreviewDisplay(null);
|
||||
}
|
||||
|
||||
public boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = null;
|
||||
|
||||
try {
|
||||
mCamera = Camera.open();
|
||||
}
|
||||
catch (Exception e){
|
||||
Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
|
||||
try {
|
||||
mCamera = Camera.open(camIdx);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mCamera == null) {
|
||||
Log.e(TAG, "Can't open any camera");
|
||||
return false;
|
||||
}
|
||||
|
||||
mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
synchronized (SampleViewBase.this) {
|
||||
System.arraycopy(data, 0, mFrame, 0, data.length);
|
||||
SampleViewBase.this.notify();
|
||||
}
|
||||
camera.addCallbackBuffer(mBuffer);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
mThreadRun = false;
|
||||
synchronized (this) {
|
||||
if (mCamera != null) {
|
||||
mCamera.stopPreview();
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
onPreviewStopped();
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
Camera.Parameters params = mCamera.getParameters();
|
||||
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
|
||||
mFrameWidth = width;
|
||||
mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
int minDiff = Integer.MAX_VALUE;
|
||||
for (Camera.Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = size.width;
|
||||
mFrameHeight = size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.setPreviewSize(getFrameWidth(), getFrameHeight());
|
||||
|
||||
List<String> FocusModes = params.getSupportedFocusModes();
|
||||
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
|
||||
{
|
||||
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
||||
}
|
||||
|
||||
mCamera.setParameters(params);
|
||||
|
||||
/* Now allocate the buffer */
|
||||
params = mCamera.getParameters();
|
||||
int size = params.getPreviewSize().width * params.getPreviewSize().height;
|
||||
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
|
||||
mBuffer = new byte[size];
|
||||
/* The buffer where the current frame will be copied */
|
||||
mFrame = new byte [size];
|
||||
mCamera.addCallbackBuffer(mBuffer);
|
||||
|
||||
/* Notify that the preview is about to be started and deliver preview size */
|
||||
onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height);
|
||||
|
||||
try {
|
||||
setPreview();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e);
|
||||
}
|
||||
|
||||
/* Now we can start a preview */
|
||||
mCamera.startPreview();
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
// stop preview before making changes
|
||||
try {
|
||||
mCamera.stopPreview();
|
||||
} catch (Exception e){
|
||||
// ignore: tried to stop a non-existent preview
|
||||
}
|
||||
|
||||
// start preview with new settings
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
/* The bitmap returned by this method shall be owned by the child and released in onPreviewStopped() */
|
||||
protected abstract Bitmap processFrame(byte[] data);
|
||||
|
||||
/**
|
||||
* This method is called when the preview process is being started. It is called before the first frame delivered and processFrame is called
|
||||
* It is called with the width and height parameters of the preview process. It can be used to prepare the data needed during the frame processing.
|
||||
* @param previewWidth - the width of the preview frames that will be delivered via processFrame
|
||||
* @param previewHeight - the height of the preview frames that will be delivered via processFrame
|
||||
*/
|
||||
protected abstract void onPreviewStarted(int previewWidtd, int previewHeight);
|
||||
|
||||
/**
|
||||
* This method is called when preview is stopped. When this method is called the preview stopped and all the processing of frames already completed.
|
||||
* If the Bitmap object returned via processFrame is cached - it is a good time to recycle it.
|
||||
* Any other resources used during the preview can be released.
|
||||
*/
|
||||
protected abstract void onPreviewStopped();
|
||||
|
||||
public void run() {
|
||||
mThreadRun = true;
|
||||
Log.i(TAG, "Started processing thread");
|
||||
while (mThreadRun) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait();
|
||||
if (!mThreadRun)
|
||||
break;
|
||||
bmp = processFrame(mFrame);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
@@ -1,127 +0,0 @@
|
||||
package org.opencv.samples.tutorial1;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class Sample1Java extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewGray;
|
||||
private MenuItem mItemPreviewCanny;
|
||||
private Sample1View mView;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new Sample1View(mAppContext);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Sample1Java() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemPreviewRGBA = menu.add("Preview RGBA");
|
||||
mItemPreviewGray = menu.add("Preview GRAY");
|
||||
mItemPreviewCanny = menu.add("Canny");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemPreviewRGBA) {
|
||||
mView.setViewMode(Sample1View.VIEW_MODE_RGBA);
|
||||
} else if (item == mItemPreviewGray) {
|
||||
mView.setViewMode(Sample1View.VIEW_MODE_GRAY);
|
||||
} else if (item == mItemPreviewCanny) {
|
||||
mView.setViewMode(Sample1View.VIEW_MODE_CANNY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package org.opencv.samples.tutorial1;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
class Sample1View extends SampleViewBase {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
|
||||
public static final int VIEW_MODE_RGBA = 0;
|
||||
public static final int VIEW_MODE_GRAY = 1;
|
||||
public static final int VIEW_MODE_CANNY = 2;
|
||||
|
||||
private Mat mYuv;
|
||||
private Mat mRgba;
|
||||
private Mat mGraySubmat;
|
||||
private Mat mIntermediateMat;
|
||||
private Bitmap mBitmap;
|
||||
private int mViewMode;
|
||||
|
||||
public Sample1View(Context context) {
|
||||
super(context);
|
||||
mViewMode = VIEW_MODE_RGBA;
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreviewStarted(int previewWidth, int previewHeight) {
|
||||
Log.i(TAG, "called onPreviewStarted("+previewWidth+", "+previewHeight+")");
|
||||
|
||||
// initialize Mats before usage
|
||||
mYuv = new Mat(getFrameHeight() + getFrameHeight() / 2, getFrameWidth(), CvType.CV_8UC1);
|
||||
mGraySubmat = mYuv.submat(0, getFrameHeight(), 0, getFrameWidth());
|
||||
|
||||
mRgba = new Mat();
|
||||
mIntermediateMat = new Mat();
|
||||
|
||||
mBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreviewStopped() {
|
||||
Log.i(TAG, "called onPreviewStopped");
|
||||
|
||||
if(mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
mBitmap = null;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
// Explicitly deallocate Mats
|
||||
if (mYuv != null)
|
||||
mYuv.release();
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
if (mGraySubmat != null)
|
||||
mGraySubmat.release();
|
||||
if (mIntermediateMat != null)
|
||||
mIntermediateMat.release();
|
||||
|
||||
mYuv = null;
|
||||
mRgba = null;
|
||||
mGraySubmat = null;
|
||||
mIntermediateMat = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(byte[] data) {
|
||||
mYuv.put(0, 0, data);
|
||||
|
||||
final int viewMode = mViewMode;
|
||||
|
||||
switch (viewMode) {
|
||||
case VIEW_MODE_GRAY:
|
||||
Imgproc.cvtColor(mGraySubmat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
|
||||
break;
|
||||
case VIEW_MODE_RGBA:
|
||||
Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
|
||||
Core.putText(mRgba, "OpenCV + Android", new Point(10, 100), 3/* CV_FONT_HERSHEY_COMPLEX */, 2, new Scalar(255, 0, 0, 255), 3);
|
||||
break;
|
||||
case VIEW_MODE_CANNY:
|
||||
Imgproc.Canny(mGraySubmat, mIntermediateMat, 80, 100);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
Bitmap bmp = mBitmap;
|
||||
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
} catch(Exception e) {
|
||||
Log.e("org.opencv.samples.tutorial1", "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
bmp = null;
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public void setViewMode(int viewMode) {
|
||||
Log.i(TAG, "called setViewMode("+viewMode+")");
|
||||
mViewMode = viewMode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package org.opencv.samples.tutorial1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private Camera mCamera;
|
||||
private SurfaceHolder mHolder;
|
||||
private int mFrameWidth;
|
||||
private int mFrameHeight;
|
||||
private byte[] mFrame;
|
||||
private volatile boolean mThreadRun;
|
||||
private byte[] mBuffer;
|
||||
private SurfaceTexture mSf;
|
||||
|
||||
|
||||
public SampleViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public int getFrameWidth() {
|
||||
return mFrameWidth;
|
||||
}
|
||||
|
||||
public int getFrameHeight() {
|
||||
return mFrameHeight;
|
||||
}
|
||||
|
||||
public void setPreview() throws IOException {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
mSf = new SurfaceTexture(10);
|
||||
mCamera.setPreviewTexture( mSf );
|
||||
}
|
||||
else
|
||||
mCamera.setPreviewDisplay(null);
|
||||
}
|
||||
|
||||
public boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = null;
|
||||
|
||||
try {
|
||||
mCamera = Camera.open();
|
||||
}
|
||||
catch (Exception e){
|
||||
Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
|
||||
try {
|
||||
mCamera = Camera.open(camIdx);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mCamera == null) {
|
||||
Log.e(TAG, "Can't open any camera");
|
||||
return false;
|
||||
}
|
||||
|
||||
mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
synchronized (SampleViewBase.this) {
|
||||
System.arraycopy(data, 0, mFrame, 0, data.length);
|
||||
SampleViewBase.this.notify();
|
||||
}
|
||||
camera.addCallbackBuffer(mBuffer);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
mThreadRun = false;
|
||||
synchronized (this) {
|
||||
if (mCamera != null) {
|
||||
mCamera.stopPreview();
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
onPreviewStopped();
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
Camera.Parameters params = mCamera.getParameters();
|
||||
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
|
||||
mFrameWidth = width;
|
||||
mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
int minDiff = Integer.MAX_VALUE;
|
||||
for (Camera.Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = size.width;
|
||||
mFrameHeight = size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.setPreviewSize(getFrameWidth(), getFrameHeight());
|
||||
|
||||
List<String> FocusModes = params.getSupportedFocusModes();
|
||||
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
|
||||
{
|
||||
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
||||
}
|
||||
|
||||
mCamera.setParameters(params);
|
||||
|
||||
/* Now allocate the buffer */
|
||||
params = mCamera.getParameters();
|
||||
int size = params.getPreviewSize().width * params.getPreviewSize().height;
|
||||
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
|
||||
mBuffer = new byte[size];
|
||||
/* The buffer where the current frame will be copied */
|
||||
mFrame = new byte [size];
|
||||
mCamera.addCallbackBuffer(mBuffer);
|
||||
|
||||
/* Notify that the preview is about to be started and deliver preview size */
|
||||
onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height);
|
||||
|
||||
try {
|
||||
setPreview();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e);
|
||||
}
|
||||
|
||||
/* Now we can start a preview */
|
||||
mCamera.startPreview();
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
// stop preview before making changes
|
||||
try {
|
||||
mCamera.stopPreview();
|
||||
} catch (Exception e){
|
||||
// ignore: tried to stop a non-existent preview
|
||||
}
|
||||
|
||||
// start preview with new settings
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
/* The bitmap returned by this method shall be owned by the child and released in onPreviewStopped() */
|
||||
protected abstract Bitmap processFrame(byte[] data);
|
||||
|
||||
/**
|
||||
* This method is called when the preview process is being started. It is called before the first frame delivered and processFrame is called
|
||||
* It is called with the width and height parameters of the preview process. It can be used to prepare the data needed during the frame processing.
|
||||
* @param previewWidth - the width of the preview frames that will be delivered via processFrame
|
||||
* @param previewHeight - the height of the preview frames that will be delivered via processFrame
|
||||
*/
|
||||
protected abstract void onPreviewStarted(int previewWidtd, int previewHeight);
|
||||
|
||||
/**
|
||||
* This method is called when preview is stopped. When this method is called the preview stopped and all the processing of frames already completed.
|
||||
* If the Bitmap object returned via processFrame is cached - it is a good time to recycle it.
|
||||
* Any other resources used during the preview can be released.
|
||||
*/
|
||||
protected abstract void onPreviewStopped();
|
||||
|
||||
public void run() {
|
||||
mThreadRun = true;
|
||||
Log.i(TAG, "Started processing thread");
|
||||
while (mThreadRun) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait();
|
||||
if (!mThreadRun)
|
||||
break;
|
||||
bmp = processFrame(mFrame);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OpenCV Tutorial 0 - Android Camera</name>
|
||||
<name>OpenCV Tutorial 1 - Camera Preview</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -4,8 +4,12 @@
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="Sample1Java"
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="Tutorial1Activity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
@@ -1,7 +1,6 @@
|
||||
set(sample example-tutorial-1-addopencv)
|
||||
set(sample example-tutorial-1-camerapreview)
|
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET})
|
||||
if(TARGET ${sample})
|
||||
add_dependencies(opencv_android_examples ${sample})
|
||||
endif()
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,23 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:opencv="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/tutorial1_activity_java_surface_view"
|
||||
opencv:show_fps="true"
|
||||
opencv:camera_id="any" />
|
||||
|
||||
<org.opencv.android.NativeCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/tutorial1_activity_native_surface_view"
|
||||
opencv:show_fps="true"
|
||||
opencv:camera_id="any" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OCV T1 Add OpenCV</string>
|
||||
<string name="app_name">OCV T1 Preview</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.opencv.samples.tutorial1;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class Tutorial1Activity extends Activity implements CvCameraViewListener2 {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
private boolean mIsJavaCamera = true;
|
||||
private MenuItem mItemSwitchCamera = null;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Tutorial1Activity() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@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.tutorial1_surface_view);
|
||||
|
||||
if (mIsJavaCamera)
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
|
||||
else
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);
|
||||
|
||||
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
|
||||
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemSwitchCamera = menu.add("Toggle Native/Java camera");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
String toastMesage = new String();
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
|
||||
if (item == mItemSwitchCamera) {
|
||||
mOpenCvCameraView.setVisibility(SurfaceView.GONE);
|
||||
mIsJavaCamera = !mIsJavaCamera;
|
||||
|
||||
if (mIsJavaCamera) {
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
|
||||
toastMesage = "Java Camera";
|
||||
} else {
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);
|
||||
toastMesage = "Native Camera";
|
||||
}
|
||||
|
||||
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
mOpenCvCameraView.enableView();
|
||||
Toast toast = Toast.makeText(this, toastMesage, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
return inputFrame.rgba();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -31,8 +31,8 @@
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1772035264" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.159439464" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
@@ -43,8 +43,8 @@
|
||||
</option>
|
||||
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1841493632" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/platforms/android-9/arch-arm/usr/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include""/>
|
||||
<listOptionValue builtIn="false" value=""${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include""/>
|
||||
<listOptionValue builtIn="false" value=""${ProjDirPath}/../../sdk/native/jni/include""/>
|
||||
</option>
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.608739504" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
@@ -60,7 +60,7 @@
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="OpenCV Tutorial 4 - Mix Java+Native OpenCV.null.1819504790" name="OpenCV Tutorial 4 - Mix Java+Native OpenCV"/>
|
||||
<project id="OpenCV Tutorial 2 - Mixed Processing OpenCV.null.1819504790" name="OpenCV Tutorial 2 - Mixed Processing"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
@@ -69,6 +69,6 @@
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope" versionNumber="1">
|
||||
<resource resourceType="PROJECT" workspacePath="/OpenCV Tutorial 4 - Mix Java+Native OpenCV"/>
|
||||
<resource resourceType="PROJECT" workspacePath="/OpenCV Tutorial 2 - Mixed Processing"/>
|
||||
</storageModule>
|
||||
</cproject>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OpenCV Tutorial 3 - Add Native OpenCV</name>
|
||||
<name>OpenCV Tutorial 2 - Mixed Processing</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -4,8 +4,12 @@
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="Sample2NativeCamera"
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="Tutorial2Activity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
@@ -1,4 +1,4 @@
|
||||
set(sample example-tutorial-4-mixed)
|
||||
set(sample example-tutorial-2-mixedprocessing)
|
||||
|
||||
if(BUILD_FAT_JAVA_LIB)
|
||||
set(native_deps opencv_java)
|
||||
@@ -1,3 +1,4 @@
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS := -frtti -fexceptions
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_PLATFORM := android-8
|
||||
27
samples/android/tutorial-2-mixedprocessing/jni/jni_part.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <jni.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
|
||||
{
|
||||
Mat& mGr = *(Mat*)addrGray;
|
||||
Mat& mRgb = *(Mat*)addrRgba;
|
||||
vector<KeyPoint> v;
|
||||
|
||||
FastFeatureDetector detector(50);
|
||||
detector.detect(mGr, v);
|
||||
for( unsigned int i = 0; i < v.size(); i++ )
|
||||
{
|
||||
const KeyPoint& kp = v[i];
|
||||
circle(mRgb, Point(kp.pt.x, kp.pt.y), 10, Scalar(255,0,0,255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,11 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.android.JavaCameraView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/tutorial2_activity_surface_view" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OCV T2 Use OpenCV Camera</string>
|
||||
<string name="app_name">OCV T2 Mixed Processing</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,166 @@
|
||||
package org.opencv.samples.tutorial2;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.android.CameraBridgeViewBase;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class Tutorial2Activity extends Activity implements CvCameraViewListener2 {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private static final int VIEW_MODE_RGBA = 0;
|
||||
private static final int VIEW_MODE_GRAY = 1;
|
||||
private static final int VIEW_MODE_CANNY = 2;
|
||||
private static final int VIEW_MODE_FEATURES = 5;
|
||||
|
||||
private int mViewMode;
|
||||
private Mat mRgba;
|
||||
private Mat mIntermediateMat;
|
||||
private Mat mGray;
|
||||
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewGray;
|
||||
private MenuItem mItemPreviewCanny;
|
||||
private MenuItem mItemPreviewFeatures;
|
||||
|
||||
private CameraBridgeViewBase mOpenCvCameraView;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
|
||||
// Load native library after(!) OpenCV initialization
|
||||
System.loadLibrary("mixed_sample");
|
||||
|
||||
mOpenCvCameraView.enableView();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Tutorial2Activity() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@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.tutorial2_surface_view);
|
||||
|
||||
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial2_activity_surface_view);
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemPreviewRGBA = menu.add("Preview RGBA");
|
||||
mItemPreviewGray = menu.add("Preview GRAY");
|
||||
mItemPreviewCanny = menu.add("Canny");
|
||||
mItemPreviewFeatures = menu.add("Find features");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
mRgba = new Mat(height, width, CvType.CV_8UC4);
|
||||
mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
|
||||
mGray = new Mat(height, width, CvType.CV_8UC1);
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
mRgba.release();
|
||||
mGray.release();
|
||||
mIntermediateMat.release();
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
final int viewMode = mViewMode;
|
||||
switch (viewMode) {
|
||||
case VIEW_MODE_GRAY:
|
||||
// input frame has gray scale format
|
||||
Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
|
||||
break;
|
||||
case VIEW_MODE_RGBA:
|
||||
// input frame has RBGA format
|
||||
mRgba = inputFrame.rgba();
|
||||
break;
|
||||
case VIEW_MODE_CANNY:
|
||||
// input frame has gray scale format
|
||||
mRgba = inputFrame.rgba();
|
||||
Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
|
||||
break;
|
||||
case VIEW_MODE_FEATURES:
|
||||
// input frame has RGBA format
|
||||
mRgba = inputFrame.rgba();
|
||||
mGray = inputFrame.gray();
|
||||
FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
|
||||
break;
|
||||
}
|
||||
|
||||
return mRgba;
|
||||
}
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
|
||||
if (item == mItemPreviewRGBA) {
|
||||
mViewMode = VIEW_MODE_RGBA;
|
||||
} else if (item == mItemPreviewGray) {
|
||||
mViewMode = VIEW_MODE_GRAY;
|
||||
} else if (item == mItemPreviewCanny) {
|
||||
mViewMode = VIEW_MODE_CANNY;
|
||||
} else if (item == mItemPreviewFeatures) {
|
||||
mViewMode = VIEW_MODE_FEATURES;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public native void FindFeatures(long matAddrGr, long matAddrRgba);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#Wed Jun 29 04:36:40 MSD 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
@@ -1,132 +0,0 @@
|
||||
package org.opencv.samples.tutorial2;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class Sample2NativeCamera extends Activity {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
public static final int VIEW_MODE_RGBA = 0;
|
||||
public static final int VIEW_MODE_GRAY = 1;
|
||||
public static final int VIEW_MODE_CANNY = 2;
|
||||
|
||||
private MenuItem mItemPreviewRGBA;
|
||||
private MenuItem mItemPreviewGray;
|
||||
private MenuItem mItemPreviewCanny;
|
||||
private Sample2View mView;
|
||||
|
||||
public static int viewMode = VIEW_MODE_RGBA;
|
||||
|
||||
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
// Create and set View
|
||||
mView = new Sample2View(mAppContext);
|
||||
setContentView(mView);
|
||||
|
||||
// Check native OpenCV camera
|
||||
if( !mView.openCamera() ) {
|
||||
AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
|
||||
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||
ad.setMessage("Fatal error: can't open camera!");
|
||||
ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
} break;
|
||||
|
||||
/** OpenCV loader cannot start Google Play **/
|
||||
case LoaderCallbackInterface.MARKET_ERROR:
|
||||
{
|
||||
Log.d(TAG, "Google Play service is not accessible!");
|
||||
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
|
||||
MarketErrorMessage.setTitle("OpenCV Manager");
|
||||
MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
|
||||
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
|
||||
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
MarketErrorMessage.show();
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Sample2NativeCamera() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.i(TAG, "called onPause");
|
||||
if (null != mView)
|
||||
mView.releaseCamera();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.i(TAG, "called onResume");
|
||||
super.onResume();
|
||||
|
||||
Log.i(TAG, "Trying to load OpenCV library");
|
||||
if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
|
||||
Log.e(TAG, "Cannot connect to OpenCV Manager");
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "called onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
Log.i(TAG, "called onCreateOptionsMenu");
|
||||
mItemPreviewRGBA = menu.add("Preview RGBA");
|
||||
mItemPreviewGray = menu.add("Preview GRAY");
|
||||
mItemPreviewCanny = menu.add("Canny");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item == mItemPreviewRGBA)
|
||||
viewMode = VIEW_MODE_RGBA;
|
||||
else if (item == mItemPreviewGray)
|
||||
viewMode = VIEW_MODE_GRAY;
|
||||
else if (item == mItemPreviewCanny)
|
||||
viewMode = VIEW_MODE_CANNY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package org.opencv.samples.tutorial2;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
class Sample2View extends SampleCvViewBase {
|
||||
private static final String TAG = "OCVSample::View";
|
||||
|
||||
private Mat mRgba;
|
||||
private Mat mGray;
|
||||
private Mat mIntermediateMat;
|
||||
|
||||
public Sample2View(Context context) {
|
||||
super(context);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
synchronized (this) {
|
||||
// initialize Mats before usage
|
||||
mGray = new Mat();
|
||||
mRgba = new Mat();
|
||||
mIntermediateMat = new Mat();
|
||||
}
|
||||
|
||||
super.surfaceCreated(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap processFrame(VideoCapture capture) {
|
||||
switch (Sample2NativeCamera.viewMode) {
|
||||
case Sample2NativeCamera.VIEW_MODE_GRAY:
|
||||
capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
|
||||
Imgproc.cvtColor(mGray, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
|
||||
break;
|
||||
case Sample2NativeCamera.VIEW_MODE_RGBA:
|
||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||
Core.putText(mRgba, "OpenCV+Android", new Point(10, 50), 3, 1, new Scalar(255, 0, 0, 255), 2);
|
||||
break;
|
||||
case Sample2NativeCamera.VIEW_MODE_CANNY:
|
||||
capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
|
||||
Imgproc.Canny(mGray, mIntermediateMat, 80, 100);
|
||||
Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2BGRA, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
try {
|
||||
Utils.matToBitmap(mRgba, bmp);
|
||||
return bmp;
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||
bmp.recycle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
|
||||
synchronized (this) {
|
||||
// Explicitly deallocate Mats
|
||||
if (mRgba != null)
|
||||
mRgba.release();
|
||||
if (mGray != null)
|
||||
mGray.release();
|
||||
if (mIntermediateMat != null)
|
||||
mIntermediateMat.release();
|
||||
|
||||
mRgba = null;
|
||||
mGray = null;
|
||||
mIntermediateMat = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package org.opencv.samples.tutorial2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.VideoCapture;
|
||||
import org.opencv.highgui.Highgui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
|
||||
private static final String TAG = "OCVSample::BaseView";
|
||||
|
||||
private SurfaceHolder mHolder;
|
||||
private VideoCapture mCamera;
|
||||
|
||||
public SampleCvViewBase(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
public synchronized boolean openCamera() {
|
||||
Log.i(TAG, "Opening Camera");
|
||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
|
||||
if (!mCamera.isOpened()) {
|
||||
releaseCamera();
|
||||
Log.e(TAG, "Can't open native camera");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void releaseCamera() {
|
||||
Log.i(TAG, "Releasing Camera");
|
||||
if (mCamera != null) {
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setupCamera(int width, int height) {
|
||||
if (mCamera != null && mCamera.isOpened()) {
|
||||
Log.i(TAG, "Setup Camera - " + width + "x" + height);
|
||||
List<Size> sizes = mCamera.getSupportedPreviewSizes();
|
||||
int mFrameWidth = width;
|
||||
int mFrameHeight = height;
|
||||
|
||||
// selecting optimal camera preview size
|
||||
{
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
for (Size size : sizes) {
|
||||
if (Math.abs(size.height - height) < minDiff) {
|
||||
mFrameWidth = (int) size.width;
|
||||
mFrameHeight = (int) size.height;
|
||||
minDiff = Math.abs(size.height - height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
|
||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
|
||||
Log.i(TAG, "called surfaceChanged");
|
||||
setupCamera(width, height);
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceCreated");
|
||||
(new Thread(this)).start();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i(TAG, "called surfaceDestroyed");
|
||||
}
|
||||
|
||||
protected abstract Bitmap processFrame(VideoCapture capture);
|
||||
|
||||
public void run() {
|
||||
Log.i(TAG, "Started processing thread");
|
||||
while (true) {
|
||||
Bitmap bmp = null;
|
||||
|
||||
synchronized (this) {
|
||||
if (mCamera == null)
|
||||
break;
|
||||
|
||||
if (!mCamera.grab()) {
|
||||
Log.e(TAG, "mCamera.grab() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
bmp = processFrame(mCamera);
|
||||
}
|
||||
|
||||
if (bmp != null) {
|
||||
Canvas canvas = mHolder.lockCanvas();
|
||||
if (canvas != null) {
|
||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
|
||||
mHolder.unlockCanvasAndPost(canvas);
|
||||
}
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Finished processing thread");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OpenCV Tutorial 2 - Use OpenCV Camera</name>
|
||||
<name>OpenCV Tutorial 3 - Camera Control</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -4,8 +4,12 @@
|
||||
android:versionCode="21"
|
||||
android:versionName="2.1">
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="Sample3Native"
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
|
||||
<activity android:name="Tutorial3Activity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
@@ -30,5 +34,6 @@
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
</manifest>
|
||||
@@ -1,7 +1,6 @@
|
||||
set(sample example-tutorial-2-opencvcamera)
|
||||
set(sample example-tutorial-3-cameracontrol)
|
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET})
|
||||
if(TARGET ${sample})
|
||||
add_dependencies(opencv_android_examples ${sample})
|
||||
endif()
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,12 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<org.opencv.samples.tutorial3.Tutorial3View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/tutorial3_activity_java_surface_view" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OCV T3 Add Native OpenCV</string>
|
||||
<string name="app_name">OCV T3 Camera Control</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,178 @@
|
||||
package org.opencv.samples.tutorial3;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.opencv.android.BaseLoaderCallback;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
|
||||
import org.opencv.android.LoaderCallbackInterface;
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SubMenu;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class Tutorial3Activity extends Activity implements CvCameraViewListener2, OnTouchListener {
|
||||
private static final String TAG = "OCVSample::Activity";
|
||||
|
||||
private Tutorial3View mOpenCvCameraView;
|
||||
private List<Size> mResolutionList;
|
||||
private MenuItem[] mEffectMenuItems;
|
||||
private SubMenu mColorEffectsMenu;
|
||||
private MenuItem[] mResolutionMenuItems;
|
||||
private SubMenu mResolutionMenu;
|
||||
|
||||
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
|
||||
@Override
|
||||
public void onManagerConnected(int status) {
|
||||
switch (status) {
|
||||
case LoaderCallbackInterface.SUCCESS:
|
||||
{
|
||||
Log.i(TAG, "OpenCV loaded successfully");
|
||||
mOpenCvCameraView.enableView();
|
||||
mOpenCvCameraView.setOnTouchListener(Tutorial3Activity.this);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
super.onManagerConnected(status);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Tutorial3Activity() {
|
||||
Log.i(TAG, "Instantiated new " + this.getClass());
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@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.tutorial3_surface_view);
|
||||
|
||||
mOpenCvCameraView = (Tutorial3View) findViewById(R.id.tutorial3_activity_java_surface_view);
|
||||
|
||||
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
|
||||
|
||||
mOpenCvCameraView.setCvCameraViewListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mOpenCvCameraView != null)
|
||||
mOpenCvCameraView.disableView();
|
||||
}
|
||||
|
||||
public void onCameraViewStarted(int width, int height) {
|
||||
}
|
||||
|
||||
public void onCameraViewStopped() {
|
||||
}
|
||||
|
||||
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
|
||||
return inputFrame.rgba();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
List<String> effects = mOpenCvCameraView.getEffectList();
|
||||
|
||||
if (effects == null) {
|
||||
Log.e(TAG, "Color effects are not supported by device!");
|
||||
return true;
|
||||
}
|
||||
|
||||
mColorEffectsMenu = menu.addSubMenu("Color Effect");
|
||||
mEffectMenuItems = new MenuItem[effects.size()];
|
||||
|
||||
int idx = 0;
|
||||
ListIterator<String> effectItr = effects.listIterator();
|
||||
while(effectItr.hasNext()) {
|
||||
String element = effectItr.next();
|
||||
mEffectMenuItems[idx] = mColorEffectsMenu.add(1, idx, Menu.NONE, element);
|
||||
idx++;
|
||||
}
|
||||
|
||||
mResolutionMenu = menu.addSubMenu("Resolution");
|
||||
mResolutionList = mOpenCvCameraView.getResolutionList();
|
||||
mResolutionMenuItems = new MenuItem[mResolutionList.size()];
|
||||
|
||||
ListIterator<Size> resolutionItr = mResolutionList.listIterator();
|
||||
idx = 0;
|
||||
while(resolutionItr.hasNext()) {
|
||||
Size element = resolutionItr.next();
|
||||
mResolutionMenuItems[idx] = mResolutionMenu.add(2, idx, Menu.NONE,
|
||||
Integer.valueOf(element.width).toString() + "x" + Integer.valueOf(element.height).toString());
|
||||
idx++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
|
||||
if (item.getGroupId() == 1)
|
||||
{
|
||||
mOpenCvCameraView.setEffect((String) item.getTitle());
|
||||
Toast.makeText(this, mOpenCvCameraView.getEffect(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else if (item.getGroupId() == 2)
|
||||
{
|
||||
int id = item.getItemId();
|
||||
Size resolution = mResolutionList.get(id);
|
||||
mOpenCvCameraView.setResolution(resolution);
|
||||
resolution = mOpenCvCameraView.getResolution();
|
||||
String caption = Integer.valueOf(resolution.width).toString() + "x" + Integer.valueOf(resolution.height).toString();
|
||||
Toast.makeText(this, caption, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
Log.i(TAG,"onTouch event");
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
String currentDateandTime = sdf.format(new Date());
|
||||
String fileName = Environment.getExternalStorageDirectory().getPath() +
|
||||
"/sample_picture_" + currentDateandTime + ".jpg";
|
||||
mOpenCvCameraView.takePicture(fileName);
|
||||
Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||