实现Tap To Focus相机的正确方法是什么?

我正在开发一款具有自定义相机屏幕的应用程序,我应该实现自拍对焦,就像Android(更具体地说,Galaxy S4)相机应用程序一样。

我已尝试使用此处列出的步骤,但似乎没有引起任何明显的关注。 对焦模式设置为连续图片(我们仅支持特定设备)。

当用户点击相机预览时,我需要关注图像的上半部分。 为此,我使用代码片段

Parameters parameters = mCamera.getParameters(); if (parameters.getMaxNumFocusAreas() > 0) { ArrayList focusAreas = new ArrayList(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750)); parameters.setFocusAreas(focusAreas); mCamera.setParameters(parameters); } 

我不想要自动聚焦,因为聚焦图像需要很长时间。 我只对图像的上半部分感兴趣。 有没有人成功实现Tap to Focus和连续图片模式?

Related of "实现Tap To Focus相机的正确方法是什么?"

最近陷入了这个问题。 正如MatheusJardimB所说, 这个问题有很多帮助。

但是,在我的情况下,我想从ContinuousPicture模式开始,然后能够点击聚焦,然后继续ContinuousPicture模式。

我设法通过使用Camera.AutoFocusCallback()onAutoFocus方法使其工作。 我不确定它是最好还是最漂亮的方式,但它似乎有效。

这是代码:

 setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mCamera != null) { Camera camera = mCamera.getCamera(); camera.cancelAutoFocus(); Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f); Parameters parameters = camera.getParameters(); parameters.setFocusMode(Parameters.FOCUS_MODE_MACRO); if (parameters.getMaxNumFocusAreas() > 0) { List mylist = new ArrayList(); mylist.add(new Camera.Area(focusRect, 1000)); parameters.setFocusAreas(mylist); } camera.setParameters(parameters); camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { camera.cancelAutoFocus(); Parameters params = camera.getParameters(); if (params.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(params); } } }); } return true; } return false; }); 

您可以将焦点区域更改为

 ArrayList focusAreas = new ArrayList(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750)); 

它应该工作。

UPDATE

我最近收购了三星S5并对其进行了测试。 它没有那么好用,所以我添加了一些修改,现在它正在运行。 这也在Galaxy S6和Galaxy Note4上成功测试过。

这是修改后的代码:

 setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mCamera != null) { Camera camera = mCamera.getCamera(); camera.cancelAutoFocus(); Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f); Parameters parameters = camera.getParameters(); if (parameters.getFocusMode().equals( Camera.Parameters.FOCUS_MODE_AUTO) { parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); } if (parameters.getMaxNumFocusAreas() > 0) { List mylist = new ArrayList(); mylist.add(new Camera.Area(focusRect, 1000)); parameters.setFocusAreas(mylist); } try { camera.cancelAutoFocus(); camera.setParameters(parameters); camera.startPreview(); camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (camera.getParameters().getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { Parameters parameters = camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); if (parameters.getMaxNumFocusAreas() > 0) { parameters.setFocusAreas(null); } camera.setParameters(parameters); camera.startPreview(); } } }); } catch (Exception e) { e.printStackTrace(); } } return true; } }); 

这有解决方案。 我刚刚在他的代码中添加了一些缺少方法的实现。

 private static final int FOCUS_AREA_SIZE= 300; 

//

 mCameraPreview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { focusOnTouch(event); } return true; } }); 

//

  private void focusOnTouch(MotionEvent event) { if (mCamera != null ) { Camera.Parameters parameters = mCamera.getParameters(); if (parameters.getMaxNumMeteringAreas() > 0){ Log.i(TAG,"fancy !"); Rect rect = calculateFocusArea(event.getX(), event.getY()); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); List meteringAreas = new ArrayList(); meteringAreas.add(new Camera.Area(rect, 800)); parameters.setFocusAreas(meteringAreas); mCamera.setParameters(parameters); mCamera.autoFocus(mAutoFocusTakePictureCallback); }else { mCamera.autoFocus(mAutoFocusTakePictureCallback); } } } private Rect calculateFocusArea(float x, float y) { int left = clamp(Float.valueOf((x / mCameraPreview.getWidth()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE); int top = clamp(Float.valueOf((y / mCameraPreview.getHeight()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE); return new Rect(left, top, left + FOCUS_AREA_SIZE, top + FOCUS_AREA_SIZE); } private int clamp(int touchCoordinateInCameraReper, int focusAreaSize) { int result; if (Math.abs(touchCoordinateInCameraReper)+focusAreaSize/2>1000){ if (touchCoordinateInCameraReper>0){ result = 1000 - focusAreaSize/2; } else { result = -1000 + focusAreaSize/2; } } else{ result = touchCoordinateInCameraReper - focusAreaSize/2; } return result; } 

//实现此回调以触发焦点。

 private Camera.AutoFocusCallback mAutoFocusTakePictureCallback = new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { // do something... Log.i("tap_to_focus","success!"); } else { // do something... Log.i("tap_to_focus","fail!"); } } }; 

其他一个答案会导致您的相机丢弃先前给出的焦点并返回连续焦点,这是我认为没有意义的。

另外,如果您查看post中的链接,原始答案将使用parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

我用这行代码而不是连续焦点实现了上面的代码,它似乎工作得更好。

我有同样的问题。 我在很多设备和许多Android版本上都检查过这个。

焦点区域似乎无法在连续对焦模式下工作

我的解决方法是将焦点模式设置为AUTO或MACRO以及设置焦点区域:

 params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO); params.setFocusAreas(focusAreas); mCamera.setParameters(params); 

请注意,Galaxy S3和S4上的库存相机应用程序的工作方式相同:它永久处于连续模式。 当您触摸屏幕时,它会切换到自动并设置对焦区域。 但过了一段时间它又回到了连续模式,焦点区域又回到了屏幕的中心。

我希望这能以某种方式帮助你。