61181

opencv implementation with with custom layout (on SurfaceView)

Question:

I have an openCV application program working, but need to add buttons etc. to the layout. So basically I want to display the opencv camera view on a surfaceView and the add the other stuff underneath.

I've been searching the internet and forums for a while, only seeing the guy with a opencv facial detection application also wanting to add a custom layout... no solution.

I am really desperate for a solution so would hugely appreciate help. For this purpose I used the OpenCV sample 3 application (as a simple example) and tried to bind to a surfaceview on a simple custom layout. I managed it in a normal Camera application, but struggling quite a bit with the opencv example.

So this is the code that I have for the Sample3Native.java, Sample3View.java and SampleViewBase.java (as in example) files respectively:

public class Sample3Native extends Activity { private Sample3View mView; private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { // Load native library after(!) OpenCV initialization System.loadLibrary("native_sample"); // Create and set View mView = new Sample3View(mAppContext); setContentView(R.layout.main); //setContentView(mView); // Check native OpenCV camera mView.openCamera(); } break; default: { super.onManagerConnected(status); } break; } } }; //constructor public Sample3Native() {} @Override protected void onPause() { super.onPause(); if (null != mView) mView.releaseCamera(); } @Override protected void onResume() { super.onResume(); if((null != mView) && !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("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); ad.show(); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack); }

}

class Sample3View extends SampleViewBase { private int mFrameSize; private Bitmap mBitmap; private int[] mRGBA; public Sample3View(Context context) { super(context); } @Override protected void onPreviewStarted(int previewWidtd, int previewHeight) { mFrameSize = previewWidtd * previewHeight; mRGBA = new int[mFrameSize]; mBitmap = Bitmap.createBitmap(previewWidtd, previewHeight, Bitmap.Config.ARGB_8888); } @Override protected void onPreviewStopped() { if(mBitmap != null) { mBitmap.recycle(); mBitmap = null; } mRGBA = null; } @Override protected Bitmap processFrame(byte[] data) { int[] rgba = mRGBA; FindFeatures(getFrameWidth(), getFrameHeight(), data, rgba); Bitmap bmp = mBitmap; bmp.setPixels(rgba, 0, getFrameWidth(), 0, 0, getFrameWidth(), getFrameHeight()); return bmp; } public native void FindFeatures(int width, int height, byte yuv[], int[] rgba);

}

public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable { private Camera mCamera; private SurfaceHolder mHolder; private SurfaceView mViewer; private int mFrameWidth; private int mFrameHeight; private byte[] mFrame; private boolean mThreadRun; private byte[] mBuffer; public SampleViewBase(Context context) { super(context); mViewer = (SurfaceView)this.findViewById(R.id.camera_view); mHolder = mViewer.getHolder(); mHolder.addCallback(this); } public int getFrameWidth() { return mFrameWidth; } public int getFrameHeight() { return mFrameHeight; } public boolean openCamera() { releaseCamera(); mCamera = Camera.open(); if(mCamera == null) 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() { mThreadRun = false; synchronized (this) { if (mCamera != null) { mCamera.stopPreview(); mCamera.setPreviewCallback(null); mCamera.release(); mCamera = null; } } onPreviewStopped(); } public void setupCamera(SurfaceHolder holder,int width, int height) { synchronized (this) { if (mCamera != null) { 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); try { mCamera.setPreviewDisplay(holder); //mCamera.setPreviewDisplay(null); } catch (IOException e) {} /* Notify that the preview is about to be started and deliver preview size */ onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height); /* Now we can start a preview */ mCamera.startPreview(); } } } public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) { setupCamera(_holder,width, height); } public void surfaceCreated(SurfaceHolder holder) { (new Thread(this)).start(); } public void surfaceDestroyed(SurfaceHolder holder) { releaseCamera(); } //abstract functions used by child class protected abstract Bitmap processFrame(byte[] data); protected abstract void onPreviewStarted(int previewWidtd, int previewHeight); protected abstract void onPreviewStopped(); //================================ public void run() { mThreadRun = true; while (mThreadRun) { Bitmap bmp = null; synchronized (this) { try { this.wait(); bmp = processFrame(mFrame); } catch (InterruptedException e) { e.printStackTrace(); } } if (bmp != null) { Canvas canvas = mHolder.lockCanvas(); if (canvas != null) { canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null); mHolder.unlockCanvasAndPost(canvas); } } } }

}

I know this must be a MAJOR drag to go through my code, but I really need the help. Or even if I could get a link to a working example of this type of implementation. Also, please just don't send me this link (it doesn't help me):<a href="http://opencv.itseez.com/doc/tutorials/introduction/android_binary_package/android_binary_package.html" rel="nofollow">openCV in custom applications</a>

Answer1:

This is my acitivity_main.xml

<RelativeLayout 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" /> <Button android:id="@+id/btnOK" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="105dp" android:layout_marginTop="139dp" android:onClick="OKClicked" android:text="@string/OK" /> <TextView android:id="@+id/txtDisp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/btnOK" android:layout_alignBottom="@+id/btnOK" android:layout_marginLeft="25dp" android:layout_toRightOf="@+id/btnOK" android:text="@string/app_name" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>

And these code must be edited to MainActivity.java class

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 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); ArrayList<View> views = new ArrayList<View>(); views.add(findViewById(R.id.btnOK)); views.add(findViewById(R.id.txtDisp)); mOpenCvCameraView.addTouchables(views); } public void OKClicked(View view){ TextView disp = (TextView)findViewById(R.id.txtDisp); disp.setText("OK Clicked"); }

This code is modified to OpenCV Tutorial 1.

You will see a button and a TextView over the surfaceview. When you click OK button TextView will show "OK Clicked". This is working for me on Samsung Galaxy.

Recommend

  • Loading an array from a .txt file? (Android)
  • XSL numbering at different levels
  • how can I use remove for this code?
  • Some data changes in the database. How can I trigger some C# code doing some work upon these changes
  • Notification for keyboard
  • In python, why does 0xbin() return False? [duplicate]
  • Memory error: numpy.genfromtxt()
  • How to use loop in Jquery to add table multiple times into div
  • jQuery Accordion Functionality panel opens when it shouldn't be opening
  • Do elements with “position: absolute;” behave as block-level elements?
  • globals() vs locals() mutability
  • Is it possible to print a function as a string in Python? [duplicate]
  • how do I Sort and organize data from csv file in php
  • What's the difference between list() and [] [duplicate]
  • Scapy sniff() in a class that subclassess threading.Thread()
  • navigator.notification.alert fires 4 alerts for 1 call on IOS - jquery mobile - phonegap 2.2.0
  • Adobe CQ5 regex that will reject an entire string if either of 2 different substrings are found with
  • How and where to install a module in python from github
  • PHP shell_exec running a shellscript with ssh
  • Lucene Query Boosting
  • Unpickling mid-stream (python)
  • Converting a PEM private key file to a JAVA PrivateKey Object
  • Query with in a loop getting slower and slower
  • Store additional information during registration with Firebase in Android
  • Shuffling an Array in Android
  • How to add an item to a ListView with each Button click
  • Where are files stored on an Android emulator?
  • Is Android's ARGB_8888 Bitmap internal format always RGBA?
  • android-How to enable cache or buffering when videoView have downloaded a video
  • OnItemSelectedListener for Spinner that was added programmatically does not trigger
  • Listview - list item selection and initial setting (custom made items)
  • how to set id for each item in ListView
  • Returning this from a constructor function in JS
  • dismiss Progress Dialog in another Activity … Android
  • Javascript (MVC) load image (byte array) from database
  • How to wait for all async tasks to finish in Node.js?
  • How to remove all of a jQuery UI dialog when it is closed
  • Installing libCurl - ruby 1.9.3 .. rails 3.2.12 .. Windows
  • Galaxy S4 Android Custom Camera Issue
  • Replace Fragment with another on back button
  • Send data from edittext to listview
  • How to create a new Bundle object?
  • Avoid registering duplicate broadcast receivers in Android
  • Splash Screen will not display
  • Jquery Mobile pageLoading() Method how does it work?
  • How to get listview position?
  • Clear activity stack before launching another activity
  • Android Activity.onWindowFocusChanged doesn't get called from within TabHost
  • Simulate click Geckofx vb,net
  • Connect .sks to skscene.h
  • Visual Studio 2010 debugger build correctly - compiler pdb and linker pdb not in synch?
  • How to test if a URL from an Eclipse bundle is a directory?
  • Alert pop up with LWUIT
  • Q promise. Difference between .when and .then
  • javascript inside java/jsp code
  • Sending data from AppleScript to FileMaker records
  • Cannot Parse HTML Data Using Android / JSOUP
  • KeystoneJS: Relationships in Admin UI not updating
  • AngularJs get employee from factory
  • Load html files in TinyMce
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • failed to connect to specific WiFi in android programmatically