1. 程式人生 > >Android Camera高階特性——手動對焦

Android Camera高階特性——手動對焦

Android Camera 系列目錄

1. 前言

對焦可以說是相機最基本的功能。
Android Camera提供了多種對焦方式:

  • FOCUS_MODE_AUTO:個人認為這個名字起的有點隨意
  • FOCUS_MODE_CONTINUOUS_PICTURE : 持續對焦模式,適用於拍照,此模式可呼叫autoFocus(AutoFocusCallback)

Applications can call autoFocus(AutoFocusCallback) in this mode. If the autofocus is in the middle of scanning, the focus callback will return when it completes. If the autofocus is not scanning, the focus callback will immediately return with a boolean that indicates whether the focus is sharp or not. The apps can then decide if they want to take a picture immediately or to change the focus mode to auto, and run a full autofocus cycle. The focus position is locked after autoFocus call. If applications want to resume the continuous focus, cancelAutoFocus must be called. Restarting the preview will not resume the continuous autofocus. To stop continuous focus, applications should change the focus mode to other modes.1

  • FOCUS_MODE_CONTINUOUS_VIDEO :持續對焦模式,適用錄製視訊,對焦比FOCUS_MODE_CONTINUOUS_PICTURE要消極一些,官方文件上說,這是錄製視訊時最好的選擇,因為焦點變化時更加順滑。此模式可呼叫autoFocus(AutoFocusCallback)

Since API level 14, applications can call autoFocus(AutoFocusCallback) in this mode. The focus callback will immediately return with a boolean that indicates whether the focus is sharp or not. The focus position is locked after autoFocus call. If applications want to resume the continuous focus, cancelAutoFocus must be called. Restarting the preview will not resume the continuous autofocus. To stop continuous focus, applications should change the focus mode to other modes.

  • FOCUS_MODE_EDOF : Extended depth of field (EDOF),此模式不能呼叫autoFocus(AutoFocusCallback)
  • FOCUS_MODE_FIXED : 適用於超焦距對焦,此模式不能呼叫autoFocus(AutoFocusCallback)
  • FOCUS_MODE_INFINITY : 無窮(??)模式,此模式不能呼叫autoFocus(AutoFocusCallback)
  • FOCUS_MODE_MACRO :巨集觀(特寫)對焦模式,此模式可呼叫autoFocus(AutoFocusCallback)

其中前三種是常用的對焦模式。

2. 實現

2.1 預設對焦設定

在前一篇文章《Android Camera API使用指南
》中我提到可以再配置Camera.Parameters中設定對焦型別,這裡就不介紹了。

        //對焦方式
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
            mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        }

---------------------

本文來自 微巖 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/matrix_laboratory/article/details/82871064?utm_source=copy 

2.2 手動對焦實現

2.2.1 最簡單的對焦實現

所謂的手動對焦就是使用者點選了螢幕的某塊區域,需要把相機對焦到使用者點選的區域。(又廢話了…… -_-||)
一般我們看到文章介紹Camera API1時,通常會說它使用非常簡單(當然相對於Camera API2來說),原因是修改Camera的狀態非常簡單,只要重新配置下Camera.Parameters,然後設定給Camera就OK。最簡單的設定步驟是:

    public synchronized void setFocusMode(String focusMode) {

        if (mCameraDevice == null)
            return;

        mParams = mCameraDevice.getParameters();
        List<String> focusModes = mParams.getSupportedFocusModes();
        if (focusModes.contains(focusMode)) {
            mParams.setFocusMode(focusMode);
        }
    }

上面的對焦實現是非常簡單的,切換對焦模式後效果基本沒有明顯的變化,而且也沒有設定對焦區域……(呃~該對焦效果確實生效了…………)

2.2.2 系統相機對焦效果模擬實現

需求分析

首先分析下系統相機的對焦都有哪些效果:

  1. 支援使用者設定對焦區域,重新設定對焦區域後會觸發相機對焦。
  2. 重新設定對焦區域後,畫面有明顯的亮度變化。

第1點很正常,就是預期的對焦效果。
第2點觸發影象亮度變化,實際上這已經不是對焦的範疇了,而是測光。從效果上看,系統相機響應手動對焦的同時根據焦點重新測光。

實現方案

通過上面的分析,我們需要設定對焦區域和測光區域,Camera.Parameters中提供了依賴的介面:

  • getMaxNumFocusAreas:獲取支援的對焦區域的個數
  • setFocusAreas:設定對焦區域列表
  • getFocusAreas:獲取對焦區域列表
  • getMaxNumMeteringAreas: 獲取支援的測光區域的個數
  • setMeteringAreas:設定測光區域列表
  • getMeteringAreas:獲取測光區域列表

用到的介面就這幾個。具體操作如下:

  1. 計算對焦和測光區域
    Camera中區域是由Camera.Area定義的,用於相機計算自動曝光、自動白平衡、自動聚焦。其中包含兩個成員:
    /**
     * Create an area with specified rectangle and weight.
     *
     * @param rect the bounds of the area.
     * @param weight the weight of the area.
     */
    public Area(Rect rect, int weight) {
        this.rect = rect;					//區域:[-1000, 1000]
        this.weight = weight;			//權重: [1, 1000]
    }

Area到螢幕的對映如下,座標(-1000,-1000)代表Camera影象的左上角:
在這裡插入圖片描述

如此就需要把使用者點選的螢幕座標轉換為Camera.Area,下面一段簡單轉換的程式碼:

            int focusRadius = (int) (radius * 1000.0f);
            int left = (int) (x * 2000.0f - 1000.0f) - focusRadius;
            int top = (int) (y * 2000.0f - 1000.0f) - focusRadius;

            Rect focusArea = new Rect();
            focusArea.left = Math.max(left, -1000);
            focusArea.top = Math.max(top, -1000);
            focusArea.right = Math.min(left + focusRadius, 1000);
            focusArea.bottom = Math.min(top + focusRadius, 1000);
            Camera.Area cameraArea = new Camera.Area(focusArea, 800);
  1. 新增對焦/測光區域
	List<Camera.Area> meteringAreas;
	List<Camera.Area> focusAreas;
	if (mParams.getMaxNumMeteringAreas() > 0) {
		List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
		meteringAreas.add(cameraArea);
	}
	if (mParams.getMaxNumMeteringAreas() > 0) {
		focusAreas = new ArrayList<Camera.Area>();
		focusAreas.add(cameraArea);
	}
    mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    mParams.setFocusAreas(meteringAreas);
  1. 設定對焦策略
            try {
                mCameraDevice.cancelAutoFocus();
                mCameraDevice.setParameters(mParams);
                mCameraDevice.autoFocus(callback);
            } catch (Exception e) {
                LogUtil.e(TAG, "Error: focusAtPoint failed: " + e.toString());
            }

上面三個步驟都是必須的,對焦不是瞬間完成,而是一個持續的過程。1

  • cancelAutoFocus:結束上一次的對焦操作,不管是有沒有完成對焦
  • autoFocus:執行一次對焦操作,通過Camera.AutoFocusCallback返回對焦結果。

至此,一次對焦操作就完成了。

3. 參考文獻