2017-01-30 79 views
11

写真を撮るときに、Androidの電話からAutoExposureCompensationレベル(明るさ)を取得する方法露出を取得するにはどのように写真を撮るときに、Java経由で、Androidの電話カメラからの補償レベル?

写真を撮ることができます。私は露出補正(常にチェックするとゼロ)を含むカメラのパラメータにアクセスできますが、撮影前と後ではなく、撮影時にAE補正レベルを取得する必要があります。

背景:特定の時刻に撮影されたすべての画像に、同じAE補正レベルを使用して撮影します。私はAndroidカメラが一般的にやっている露光レベルやホワイトバランスに何百という調整を加えることを望んでいません。私は一度取得し、すべての後続の写真、同じ設定を設定します。

写真、OpenCV、フラグメントなどに "インテント"を使用しようとしましたが、これらのいずれかでAE補正設定を取得できないようです。ここで私が試した最新のコードがJavaCameraViewの拡張版で始まる、だ:

import org.opencv.android.JavaCameraView; 
import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.PictureCallback; 
import android.hardware.Camera.Size; 
import android.util.AttributeSet; 
import android.util.Log; 
@SuppressWarnings("deprecation") 
public class NewJavaCameraView extends JavaCameraView implements PictureCallback { 

public int getExposureCompensation(){ 
    return mCamera.getParameters().getExposureCompensation(); 
} 
@SuppressWarnings("deprecation") 
public void takePicture(final String fileName) { 
    Log.i(TAG, "Taking picture"); 
    this.mPictureFileName = fileName; 

    Camera.Parameters params = mCamera.getParameters(); 
    int exposureComp = params.getExposureCompensation(); 
    mCamera.setPreviewCallback(null); 

    // PictureCallback is implemented by the current class 
    int otherexposureComp =this.getExposureCompensation(); 
    mCamera.takePicture(null, null, this); 
} 

@SuppressWarnings("deprecation") 
@Override 
public void onPictureTaken(byte[] data, Camera camera) { 

    Camera.Parameters params = mCamera.getParameters(); 
    int exposureComp = params.getExposureCompensation(); 
    int otherexposureComp =this.getExposureCompensation(); 
    mCamera.startPreview(); 
    mCamera.setPreviewCallback(this); 

    // Write the image in a file (in jpeg format) 
    try { 
     FileOutputStream fos = new FileOutputStream(mPictureFileName); 

     fos.write(data); 
     fos.close(); 

    } catch (java.io.IOException e) { 
     Log.e("Picture", "photoCallback", e); 
    } 
} 

ここでは、上記のクラスを使っているAndroidのビューからのコードの一部です:

public class DiscPhoto extends Activity implements CvCameraViewListener2, OnTouchListener { 
private static final String TAG = "OCVSample::Activity"; 
private NewJavaCameraView mOpenCvCameraView; 
private List<Size> mResolutionList; 

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { 
    @Override 
    public void onManagerConnected(int status) { 
     switch (status) { 
      case LoaderCallbackInterface.SUCCESS: 
      { 
       Log.i(TAG, "OpenCV loaded successfully"); 
       mOpenCvCameraView.enableView(); 
       mOpenCvCameraView.setOnTouchListener(DiscPhoto.this); 
      } break; 
      default: 
      { 
       super.onManagerConnected(status); 
      } break; 
     } 
    } 
}; 

public DiscPhoto() { 
    Log.i(TAG, "Instantiated new " + this.getClass()); 
} 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    Log.i(TAG, "called onCreate"); 
    super.onCreate(savedInstanceState); 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    setContentView(R.layout.activity_disc_photo); 

    mOpenCvCameraView = (NewJavaCameraView) findViewById(R.id.discPhotoPage); 
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); 
    mOpenCvCameraView.setCvCameraViewListener(this); 
} 

@SuppressLint("SimpleDateFormat") 
@Override 
public boolean onTouch(View v, MotionEvent event) { 
    Log.i(TAG,"onTouch event"); 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); 
    String currentDateandTime = sdf.format(new Date()); 
    String fileName = Environment.getExternalStorageDirectory().getPath() + 
      "/sample_picture_" + currentDateandTime + ".jpg"; 
    mOpenCvCameraView.takePicture(fileName); 
    Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show(); 
    return false; 
} 
+0

あなたはAE [ShutterCallback](https://developer.android.com/reference/android/hardware/を取得しようとしたことがありvoid関数と呼ばれるcreatePreviewSessions()を呼び出しCamera.ShutterCallback.html)が起動されますか? – NAmorim

+0

NAmorim ええ、私はそれのようなものを試しました。私はセンサー露出時間とセンサー感度を調べて、どこに行くか教えてください。それがうまくいくかどうかはわかりません。しかし、これを見ていただきありがとうございます。 – Brian

+0

android.hardware.camera2 APIをオプションとして使用していますか? https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys() – Fildor

答えて

3

私はカメラ2を考えますAPI()で十分です。

出典:https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_LOCK

カメラデバイスは、飛行中のリクエストのパイプラインを持っているので、ロックを取得 設定は必ずしもから受信した最新のキャプチャ結果に存在していた設定 に対応していません。 カメラデバイスの場合、結果が送信される前であっても、追加のキャプチャおよびAEアップデートで が発生している可能性があります。アプリケーションは、自動と手動制御の間 切り替えがあると にスイッチの間のいずれかのちらつきを解消したい場合は、以下の手順が推奨されます:

  • ロックAE
  • 待ち:

    1. が自動AEモードで起動しますAEがロックされている最初の結果が出力される
    2. その結果から要求にコピー設定をコピーし、要求を手動AEに設定します。
    3. キャプチャ要求を送信し、必要に応じて手動AEを実行します。 AEモードの説明の通りまた
  • (同じソース)ONモードのいずれかに設定

    、オーバーライドするためのカメラ デバイス自動露出ルーチンによって選択された値指定された キャプチャのフィールドは、そのCaptureResultで使用可能になります。

    あなたが最初CaptureRequestを作る一度だから、あなたはコールバック次からTotalCaptureResultを使用することができます。

    void onCaptureCompleted (CameraCaptureSession session, 
           CaptureRequest request, 
           TotalCaptureResult result) 
    { 
         int aecompensationlevel = result.get(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION) 
    } 
    
    +0

    OK、それをチェックし、それが動作するかどうかを見てみましょう。私はそれがうまくいくと思う。それは私が今やっていることよりずっと簡単です。 – Brian

    +0

    マニッシュ、 動作しませんでした。私は実際に成功する前にそれを試してみました。なぜか分かりませんが、CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATIONは、CaptureCallback(onCaptureComplete)イベントで使用されている場合でも、カメラのデフォルト設定である "0"を返します。 Control_AE_Exposure_Compensationは機能しませんが、この後で作業をポストします。 – Brian

    0

    [OK]を、私は同様の問題を発見し、誰のためにこれを自分自身に答えるつもりです。

    Manishは答えに近づきましたが、onCaptureSessionイベントで使用されても、CONTROL_AE_EXPOSURE_COMPENSATIONによって返されるのは0(ゼロ)です。これはカメラのデフォルトの開始値です。

    しかし、CameraCaptureSession.CaptureCallback(onCaptureSessionイベント)では、SENSOR_EXPOSURE_TIMEおよびSENSOR_SENSITIVITYの値を取得して、Androidカメラでの自動露出の問題を回避することができます。以下は

    は、私が使用したコードの抜粋です:

    private void captureStillPicture() { 
        try { 
          ... 
         CameraCaptureSession.CaptureCallback CaptureCallback 
           = new CameraCaptureSession.CaptureCallback() { 
    
          @Override 
          public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
                  @NonNull CaptureRequest request, 
                  @NonNull TotalCaptureResult result) { 
    
           long sensorTime= result.get(CaptureResult.SENSOR_EXPOSURE_TIME); 
           long sensorSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY); 
    
           int ONE_SECOND = 1000000000; //1 billion nanoseconds 
           int MICRO_SECOND = 1000000; 
           int MILLI_SECOND = 1000; 
           String exposureText = ""; 
           if (sensorTime > ONE_SECOND) { 
            exposureText = String.format("%.2f s", sensorTime/1e9); 
           } else if (sensorTime > MILLI_SECOND) { 
            exposureText = String.format("%.2f ms", sensorTime/1e6); 
           } else if (sensorTime > MICRO_SECOND) { 
            exposureText = String.format("%.2f us", sensorTime/1e3); 
           } else { 
            exposureText = String.format("%d ns", sensorTime); 
           } 
    
           int aecompensationlevel=result.get(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION); //only returns zero 
           showToast("Saved: " + mFile +" | " +exposureText); 
           Log.d(TAG, mFile.toString()); 
    
          } 
         }; 
    

    はここに私のデバッガからの結果の写真です:

    enter image description here

    1

    OK、疑問がで設定する方法を思い付きましたAndroidカメラを制御するためのコードを記述する際の露出、センサー感度などの変数を具体的に示します。これはLollipop以降でのみ有効です。投稿するコードはたくさんありますが、ハイライトを入れようとしています

    つまり、私はTextManagerView(AutoFitTextureView)をCameraManagerで使用しています。私はカメラを開くと、私は

    void openCamera() { 
        try { 
         mManager.openCamera(mCameraId, new CameraDevice.StateCallback() { 
          @Override 
          public void onOpened(CameraDevice camera) { 
           createPreviewSession(); 
          } 
         } 
    
    private void createPreviewSession() { 
        try { 
         SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
         assert texture != null; 
         texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
         final List<Surface> surfaceList = new ArrayList<>(); 
         Surface surface = mImageReader.getSurface(); 
         surfaceList.add(surface); 
    
         mCamera.createCaptureSession(surfaceList, new CameraCaptureSession.StateCallback() { 
          @Override 
          public void onConfigured(CameraCaptureSession session) { 
           mSession = session; 
    
           CaptureRequest request = createRequest(surfaceList, milliSecond, sensorSetting); //module variables 
          } ... 
         } ... 
    } 
    private CaptureRequest createRequest(List<Surface> surfaces, int milliSeconds, int sensorSetting) { 
        Log.v("createRequest","here"); 
        try { 
         CaptureRequest.Builder builder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
         builder.set(CaptureRequest.CONTROL_EFFECT_MODE, CameraMetadata.CONTROL_EFFECT_MODE_OFF); 
         for (Surface surface : surfaces) 
          builder.addTarget(surface); 
         int exposureTime = milliSeconds * (milliSecondFactor); //billionth 
         CaptureRequestSettings.SetRequestBuilder(builder,CONTROL_AWB_MODE_DAYLIGHT); 
    
         builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, Long.valueOf(exposureTime));  //set hard values based on settings caught when photo taken 
         builder.set(CaptureRequest.SENSOR_SENSITIVITY, Integer.valueOf(sensorSetting));  //same thing 
         builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 
         builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF); //CaptureRequest.CONTROL_AWB_MODE_OFF); //off here just like video mode 
         builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); //off ... don't want auto exposure 
    
         return builder.build(); 
        } catch (CameraAccessException e) { 
         Log.e("CaptureRequest", "CameraAccessException: " +e.getMessage()); 
        } catch (Exception e) { 
         Log.e("CaptureRequest", "Regular Exception: " +e.getMessage()); 
        } 
        Log.v("createRequest","shouldn't get here"); 
        return null; 
    } 
    
    +0

    ありがとうございました@Brian。私はまだAndroidの初心者なので、あなたがここで何をしたかについて明確な考えを得ることはできません。あなたはあなたの仕事に光を当てることができますか?それは本当に役立つだろう。 –

    +0

    あなたの手伝ってくれるコードが多すぎます。ごめんなさい。 – Brian

    関連する問題