11

Как получить уровень автоэкспозицииКомпенсация (яркость) с телефона Android , когда сделана фотография?Как получить уровень компенсации экспозиции с камеры телефона Android через Java, когда снимок сделан?

Я могу сфотографировать. Я могу получить доступ к параметрам камеры, включая компенсацию экспозиции (всегда ноль, когда я проверяю), но мне нужно получить уровень компенсации 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 View, который с помощью вышеупомянутого класса:

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/ Camera.ShutterCallback.html) уволен? – NAmorim

+0

NAmorim Да, я пробовал что-то подобное. Я просматриваю время экспозиции датчика и чувствительность датчика, чтобы получить меня туда, куда я иду. Не уверен, что это сработает или нет. Но спасибо за это. – Brian

+0

Использует API android.hardware.camera2 API? Возможно, вы найдете здесь что-то здесь: https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys() – Fildor

ответ

3

Я думаю Camera2 API (https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html) будет достаточным для вас.

Источник: https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_LOCK

Поскольку устройство камеры имеет трубопровод запросов в полете, то настройки, которые блокируются не обязательно соответствуют настройкам , которые присутствовали в последнем результате захвата, полученной от , поскольку дополнительные снимки и обновления AE могут иметь , даже до того, как был отправлен результат. Если приложение переключение между автоматическим и ручным управлением и желает устранить любой мерцания во время переключения, рекомендуется следующая процедура:

  1. Запуск в автоматическом режиме AE:
  2. Блокировка AE
  3. Wait для вывода первого результата, который заблокирован AE
  4. Скопируйте настройки экспозиции из этого результата в запрос, установите запрос на ручной AE
  5. Отправьте запрос на захват, приступайте к выполнению ручного AE по желанию.

Кроме того, в соответствии с описанием режима AE (тот же источник)

При установке в любом из режимов, значения, выбранные камеры устройства обычной автоматической экспозиции для переопределены поля для данного захвата будут доступны в CaptureResult.

Так как только вы сделаете первый CaptureRequest, вы можете использовать TotalCaptureResult из следующего обратного вызова:

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

Хорошо, позвольте мне проверить это и посмотреть, работает ли он. Надеюсь это работает; это было бы намного проще, чем то, что я сейчас делаю. – Brian

+0

Manish, Это не сработало. Я на самом деле пробовал это раньше, но безуспешно. Я не знаю почему, но CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION возвращает только «0», значение по умолчанию для камеры, даже если оно используется в событии CaptureCallback (onCaptureComplete). Control_AE_Exposure_Compensation не работает, но после этого я опубликую работу. – Brian

0

ОК, я собираюсь ответить на этот вопрос сам для тех, кто считает подобную проблему.

Manish получил свой ответ, но даже при использовании в событии onCaptureSession только 0 (ноль) возвращается CONTROL_AE_EXPOSURE_COMPENSATION, что бесполезно; это только начальное значение по умолчанию для камеры.

Однако 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

ОК, встал вопрос, как установить в конкретную экспозицию, чувствительность сенсора и другие переменные при написании кода для управления камерой Android. Это будет работать только на Lollipop или позже. Там много кода для публикации, но я постараюсь поставить основные моменты.

Одним словом, я использую TextureView (AutoFitTextureView) с CameraManager. Когда я открываю камеру, вызвать функцию аннулируются называемые createPreviewSessions()

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

Смежные вопросы