Added camera calibration sample for android
[profile/ivi/opencv.git] / samples / android / camera-calibration / src / org / opencv / samples / cameracalibration / CameraCalibrationActivity.java
1 // This sample is based on "Camera calibration With OpenCV" tutorial:
2 // http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html
3 //
4 // It uses standard OpenCV asymmetric circles grid pattern 11x4:
5 // https://github.com/Itseez/opencv/blob/2.4/doc/acircles_pattern.png.
6 // The results are the camera matrix and 5 distortion coefficients.
7 //
8 // Tap on highlighted pattern to capture pattern corners for calibration.
9 // Move pattern along the whole screen and capture data.
10 //
11 // When you've captured necessary amount of pattern corners (usually ~20 are enough),
12 // press "Calibrate" button for performing camera calibration.
13
14 package org.opencv.samples.cameracalibration;
15
16 import org.opencv.android.BaseLoaderCallback;
17 import org.opencv.android.CameraBridgeViewBase;
18 import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
19 import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
20 import org.opencv.android.LoaderCallbackInterface;
21 import org.opencv.android.OpenCVLoader;
22 import org.opencv.core.Mat;
23
24 import android.app.Activity;
25 import android.app.ProgressDialog;
26 import android.content.res.Resources;
27 import android.os.AsyncTask;
28 import android.os.Bundle;
29 import android.util.Log;
30 import android.view.Menu;
31 import android.view.MenuItem;
32 import android.view.MotionEvent;
33 import android.view.SurfaceView;
34 import android.view.View;
35 import android.view.View.OnTouchListener;
36 import android.view.WindowManager;
37 import android.widget.Toast;
38
39 public class CameraCalibrationActivity extends Activity implements CvCameraViewListener2, OnTouchListener {
40     private static final String TAG = "OCVSample::Activity";
41
42     private CameraBridgeViewBase mOpenCvCameraView;
43     private CameraCalibrator mCalibrator;
44     private OnCameraFrameRender mOnCameraFrameRender;
45     private int mWidth;
46     private int mHeight;
47
48     private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
49         @Override
50         public void onManagerConnected(int status) {
51             switch (status) {
52             case LoaderCallbackInterface.SUCCESS:
53             {
54                 Log.i(TAG, "OpenCV loaded successfully");
55                 mOpenCvCameraView.enableView();
56                 mOpenCvCameraView.setOnTouchListener(CameraCalibrationActivity.this);
57             } break;
58             default:
59             {
60                 super.onManagerConnected(status);
61             } break;
62             }
63         }
64     };
65
66     public CameraCalibrationActivity() {
67         Log.i(TAG, "Instantiated new " + this.getClass());
68     }
69
70     @Override
71     public void onCreate(Bundle savedInstanceState) {
72         Log.i(TAG, "called onCreate");
73         super.onCreate(savedInstanceState);
74         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
75
76         setContentView(R.layout.camera_calibration_surface_view);
77
78         mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.camera_calibration_java_surface_view);
79         mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
80         mOpenCvCameraView.setCvCameraViewListener(this);
81     }
82
83     @Override
84     public void onPause()
85     {
86         super.onPause();
87         if (mOpenCvCameraView != null)
88             mOpenCvCameraView.disableView();
89     }
90
91     @Override
92     public void onResume()
93     {
94         super.onResume();
95         OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mLoaderCallback);
96     }
97
98     public void onDestroy() {
99         super.onDestroy();
100         if (mOpenCvCameraView != null)
101             mOpenCvCameraView.disableView();
102     }
103
104     @Override
105     public boolean onCreateOptionsMenu(Menu menu) {
106         super.onCreateOptionsMenu(menu);
107         getMenuInflater().inflate(R.menu.calibration, menu);
108
109         return true;
110     }
111
112     @Override
113     public boolean onPrepareOptionsMenu (Menu menu) {
114         super.onPrepareOptionsMenu(menu);
115         menu.findItem(R.id.preview_mode).setEnabled(true);
116         if (!mCalibrator.isCalibrated())
117             menu.findItem(R.id.preview_mode).setEnabled(false);
118
119         return true;
120     }
121
122     @Override
123     public boolean onOptionsItemSelected(MenuItem item) {
124         switch (item.getItemId()) {
125         case R.id.calibration:
126             mOnCameraFrameRender =
127                 new OnCameraFrameRender(new CalibrationFrameRender(mCalibrator));
128             item.setChecked(true);
129             return true;
130         case R.id.undistortion:
131             mOnCameraFrameRender =
132                 new OnCameraFrameRender(new UndistortionFrameRender(mCalibrator));
133             item.setChecked(true);
134             return true;
135         case R.id.comparison:
136             mOnCameraFrameRender =
137                 new OnCameraFrameRender(new ComparisonFrameRender(mCalibrator, mWidth, mHeight, getResources()));
138             item.setChecked(true);
139             return true;
140         case R.id.calibrate:
141             final Resources res = getResources();
142             if (mCalibrator.getCornersBufferSize() < 2) {
143                 (Toast.makeText(this, res.getString(R.string.more_samples), Toast.LENGTH_SHORT)).show();
144                 return true;
145             }
146
147             mOnCameraFrameRender = new OnCameraFrameRender(new PreviewFrameRender());
148             new AsyncTask<Void, Void, Void>() {
149                 private ProgressDialog calibrationProgress;
150
151                 @Override
152                 protected void onPreExecute() {
153                     calibrationProgress = new ProgressDialog(CameraCalibrationActivity.this);
154                     calibrationProgress.setTitle(res.getString(R.string.calibrating));
155                     calibrationProgress.setMessage(res.getString(R.string.please_wait));
156                     calibrationProgress.setCancelable(false);
157                     calibrationProgress.setIndeterminate(true);
158                     calibrationProgress.show();
159                 }
160
161                 @Override
162                 protected Void doInBackground(Void... arg0) {
163                     mCalibrator.calibrate();
164                     return null;
165                 }
166
167                 @Override
168                 protected void onPostExecute(Void result) {
169                     calibrationProgress.dismiss();
170                     mCalibrator.clearCorners();
171                     mOnCameraFrameRender = new OnCameraFrameRender(new CalibrationFrameRender(mCalibrator));
172                     String resultMessage = (mCalibrator.isCalibrated()) ?
173                             res.getString(R.string.calibration_successful)  + " " + mCalibrator.getAvgReprojectionError() :
174                             res.getString(R.string.calibration_unsuccessful);
175                     (Toast.makeText(CameraCalibrationActivity.this, resultMessage, Toast.LENGTH_SHORT)).show();
176
177                     if (mCalibrator.isCalibrated()) {
178                         CalibrationResult.save(CameraCalibrationActivity.this,
179                                 mCalibrator.getCameraMatrix(), mCalibrator.getDistortionCoefficients());
180                     }
181                 }
182             }.execute();
183             return true;
184         default:
185             return super.onOptionsItemSelected(item);
186         }
187     }
188
189     public void onCameraViewStarted(int width, int height) {
190         if (mWidth != width || mHeight != height) {
191             mWidth = width;
192             mHeight = height;
193             mCalibrator = new CameraCalibrator(mWidth, mHeight);
194             if (CalibrationResult.tryLoad(this, mCalibrator.getCameraMatrix(), mCalibrator.getDistortionCoefficients())) {
195                 mCalibrator.setCalibrated();
196             }
197
198             mOnCameraFrameRender = new OnCameraFrameRender(new CalibrationFrameRender(mCalibrator));
199         }
200     }
201
202     public void onCameraViewStopped() {
203     }
204
205     public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
206         return mOnCameraFrameRender.render(inputFrame);
207     }
208
209     @Override
210     public boolean onTouch(View v, MotionEvent event) {
211         Log.d(TAG, "onTouch invoked");
212
213         mCalibrator.addCorners();
214         return false;
215     }
216 }