自分のアプリケーションでカスタムカメラビューを作成しました。基本的には、アプリケーションのカメラがフォーカスされている限り、何かをする必要があります。アンドロイドでオートフォーカスで連続して画像を撮る
私のCamera.Parametersでは、私はFOCUS_MODE_CONTINUOUS_PICTUREを使用しており、意図どおりに動作します。今、私は、この連続的なオートフォーカスの練習からコールバックが必要です。ここでは、現在のフォーカスされた写真を撮り、何かをすることができます。
もう1つの方法は、一定時間ごとに起動する「タイマー」テクニックをフックすることでした。そして、mCamera.autofocus()を使って写真を撮り、自分の仕事をします。残念なことに、これは非常に悪い技術であることが判明しました。なぜなら、オートフォーカスはさまざまなデバイスに応じて複雑になるからです。
だから私は、これに対する完璧な解決策は何だろうと思っていました。
UPDATE:私は何をしたいかのスレッド
との試みを行った後、オートフォーカスで、限り、アプリがフォアグラウンドにあるよう何度も何度も写真を撮ります。
さまざまな試行の後で、これは私が今までには遠くても遠くないほど遠いです。
実行可能なコードを参照してください:
public class ODFragment extends Fragment {
View rootView;
static final String TAG = "DBG_" + MainActivity.class.getName();
private Camera mCamera;
private CameraPreview mCameraPreview;
int ROIHeight;
FrameLayout frameLayout_cameraLens;
TextView words_container;
Thread ocrThread;
OCRRunnable ocrRunnable; //TODO: this may cause problems because mCamera is null as of this moment
public ODFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_od, container, false);
//one time tasks
words_container = (TextView) rootView.findViewById(R.id.words_container);
setCameraViewDimensions();
ocrThread = new Thread(ocrRunnable); //start it in onResume()
return rootView;
}
@Override
public void onResume() {
super.onResume();
hookCamera();
}
@Override
public void onPause() {
super.onPause();
unhookCamera();
}
private void hookCamera() {
try {
// 1. open camera
mCamera = Camera.open();
// 2. initialize cameraPreview
mCameraPreview = new CameraPreview(this.getActivity(), mCamera);
// 3. add view to frameLayout
frameLayout_cameraLens.addView(mCameraPreview);
mCamera.startPreview();
// 4. hook camera related listeners and threads
ocrRunnable = new OCRRunnable(mCamera);
ocrThread = new Thread(ocrRunnable);
ocrThread.start();
ocrRunnable.onResume();
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Could not Camera.open(): " + e.getMessage());
}
}
private void unhookCamera() {
try {
// -4. unhook camera related listeners ans threads
ocrRunnable.onPause();
ocrThread = null;
ocrRunnable = null;
// -3. remove view from frameLayout
frameLayout_cameraLens.removeView(mCameraPreview);
// -2. destroy cameraPreview
mCameraPreview = null;
// -1. close camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void setCameraViewDimensions() {
//calculate and set dimensions of cameraLens
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = (int) (width * 1.3333333333333);
//Log.d(TAG, "frameLayout_cameraLens dimensions: "+height+"x"+width);
frameLayout_cameraLens = (FrameLayout) rootView.findViewById(R.id.frameLayout_cameraLens);
frameLayout_cameraLens.getLayoutParams().width = width;
frameLayout_cameraLens.getLayoutParams().height = height;
frameLayout_cameraLens.requestLayout();
//set height of ROI
ROIHeight = height/5;
LinearLayout linearLayout = (LinearLayout) rootView.findViewById(R.id.ROI);
linearLayout.getLayoutParams().height = ROIHeight;
linearLayout.requestLayout();
}
}
いくつかのポイント:
- 私は
camera.autofocus()
は別のスレッド自体に起こると思います。ここpublic class OCRRunnable implements Runnable { static final String TAG = "DBG_" + "OCRRunnable"; private final Object mPauseLockDummyObject; private boolean mPaused; private boolean mFinished; Camera mCamera; public OCRRunnable(Camera cameraParam) { mPauseLockDummyObject = new Object(); mPaused = false; mFinished = false; mCamera = cameraParam; } @Override public void run() { if (mCamera != null) { // since the main activity may have been late opening the camera try { mCamera.autoFocus(new mAutoFocusCallback()); Log.d(TAG, "run: mCamera.autofocus()"); } catch (Exception e) { Log.e(TAG, "run: " + e.getMessage()); } //sleep necessary //TODO: needs refinement //try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //Runnable regulator synchronized (mPauseLockDummyObject) { while (mPaused) { try { mPauseLockDummyObject.wait(); } catch (InterruptedException e) { Log.e(TAG, "run: " + e.getMessage()); } } } } } /** * Call this on pause of the activity. */ public void onPause() { //Log.d(TAG, "onPause: called"); synchronized (mPauseLockDummyObject) { mPaused = true; } } /** * Call this on resume of the activity */ public void onResume() { //Log.d(TAG, "onResume: called"); synchronized (mPauseLockDummyObject) { mPaused = false; mPauseLockDummyObject.notifyAll(); } } ////////////////////////////////////// protected class mAutoFocusCallback implements Camera.AutoFocusCallback { @Override public void onAutoFocus(boolean success, final Camera camera) { camera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "onPictureTaken() called"); /* NEED TO RUN THIS CODE PART REPETITIVELY */ camera.cancelAutoFocus(); //be ready for next autofocus camera.startPreview(); //re-start cameraPreview since taking a picture stops it run(); //TODO } }); } } }
は私の関連するフラグメントです。それで
while(true)
ループをrun()
に入れるのではなく、mAutoFocusCallback
の末尾にrun()を呼び出したのです。 - この時点では、実行は
Log.d(TAG, "run: mCamera.autofocus()");
になります。また、Log.d(TAG, "onPictureTaken() called");
は一度も呼び出されません。
は、ここに私の関連するログです:
05-29 12:51:58.460 W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
05-29 12:51:58.573 D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
05-29 12:51:58.655 W/FragmentManager: moveToState: Fragment state for VTFragment{fd65ec0 #0 id=0x7f0c006d android:switcher:2131492973:1} not updated inline; expected state 3 found 2
05-29 12:51:58.962 D/DBG_CameraPreview: CameraPreview() initialized
05-29 12:51:59.079 D/DBG_OCRRunnable: run: mCamera.autofocus()
05-29 12:51:59.097 I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8974_LA.BF.1.1.3_RB1__release_AU (I3f4bae6ca5)
OpenGL ES Shader Compiler Version: E031.29.00.00
Build Date: 02/14/16 Sun
Local Branch: mybranch18261495
Remote Branch: quic/LA.BF.1.1.3_rb1.10
Local Patches: NONE
Reconstruct Branch: NOTHING
05-29 12:51:59.101 I/OpenGLRenderer: Initialized EGL, version 1.4
05-29 12:51:59.366 I/Choreographer: Skipped 46 frames! The application may be doing too much work on its main thread.
05-29 12:51:59.556 I/Timeline: Timeline: Activity_idle id: [email protected] time:44964952
こんにちは、あなたの答えをありがとうございました。私の要件は、mCamera.autofocus(コールバック)をスケジュールされた関数で自分で呼び出す必要はないということです。 FOCUS_MODE_CONTINUOUS_PICTUREパラメータの良い点は、カメラが開いている間、繰り返しオートフォーカスが行われることです。このパラメータが自動的に同様のコールバックを呼び出すことはできませんか? –
いいえ、 'autofocus()'の呼び出しにはどのような複雑さがありますか? –
たとえば、3秒ごとに機能を実行するようにスケジュールを設定すると、前回のオートフォーカスの試みが途中で終了していないカメラデバイスが故障している可能性があります。これにより例外が発生します。 例外を処理すると、次のオートフォーカスに6秒間待機します。 リスクを回避して間隔を7秒または8秒に増やすと、この時間はあまりにも有用になりすぎます。 camera.paramterのオートフォーカスの方法はとても良いと高速です –