Friday, January 8, 2016

Android App with OpenCV and C++, Part 3

1. Add Camera

a. Add permission line  in file "AndroidManifest.xml": 
<uses-permission android:name="android.permission.CAMERA" />
b. Subclass SurfaceView: MyView:
 public class MyView extends SurfaceView{
     Bitmap bmp2Display;
     public MyView(Context context, AttributeSet attrs) {
           super(context, attrs);
     }
     Paint paint = new Paint();
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
         canvas.drawText("time = "+System.currentTimeMillis(), 50, 100, paint);
     }
}

c. Add an instance of MyView in "activity_mail.xml":
<org.ski.helloworld.MyView
      android:id="@+id/myView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentLeft="true"
      android:layout_alignParentTop="true" />

d. Add "implements SurfaceHolder.Callback" in MainActivity, and added unimplemented functions as hinted

public class MainActivity extends Activity implements SurfaceHolder.Callback{
    //...
    // ...
}

e. Add MyView, Camera, its callback and image size:

MyView myView; 
int width = 960, height=720;
Camera mCamera;
Camera.PreviewCallback cbWithBuffer;

f. Define callback function:

 Camera.PreviewCallback cabWithBuffer = new Camera.PreviewCallback() {
    public void onPreviewFrame(byte[] _data, Camera _camera) {
                       // do something
        _camera.addCallbackBuffer(_data);
    }
 };
g. Add implementations for SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
    mCamera = Camera.open();
    mCamera.addCallbackBuffer(new byte[width * height * 2]); // YUV
    mCamera.setPreviewCallbackWithBuffer(cabWithBuffer);  
    try {
        mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(width, height);
    mCamera.setParameters(parameters);
    mCamera.setPreviewCallbackWithBuffer(cbWithBuffer);
    mCamera.startPreview();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    mCamera.stopPreview();
    mCamera.setPreviewCallbackWithBuffer(null);
    mCamera.release();
    mCamera = null;
}

2. Process video: 

a. Declare matrices:
Mat mYuv, mRgba;
b. Allocate space for mYuv, mRgb in createOpencvMatrices():
    mYuv = new Mat(height + height/2, width, CvType.CV_8UC1);
    mRgb = new Mat(height, width, CvType.CV_8UC3);

c. Process image in cbWithBuffer:

    mYuv.put(0, 0, _data); 
    Imgproc.cvtColor(mYuv, mRgb, Imgproc.COLOR_YUV2RGB_NV21, 3);
    processImage(mRgb.getNativeObjAddr());

d. Add function declaration

    public native int processImage(long matAddrRgb);

e. Add image processing implementation in HelloWorld.cpp:

JNIEXPORT void JNICALL Java_org_ski_helloworld_MainActivity_processImage(JNIEnv*, jobject, jlong addrRgb)
{
    Mat &rgb = *(Mat *) addrRgb;
    int w = rgb.cols, h = rgb.rows;
    Rect r(w/4,h/4,w/2,h/2);
    Mat roi = rgb(r).clone();
    Mat gray, edge;
    cvtColor(roi, gray, CV_RGB2GRAY);
    blur( gray, gray, Size(5,5));
    Canny( gray, edge, 50, 150, 3);
    edge.convertTo(gray, CV_8UC1);
    cvtColor(gray,roi, CV_GRAY2RGB);
    roi.copyTo(rgb(r));
}
The zipped project is HelloWorld_02.zip

No comments:

Post a Comment