2017-01-30 12 views
11

Fotoğraf çekildiğinde Android telefondan AutoExposureCompensation (Parlaklık) düzeyini nasıl alabilirim? ?Fotoğraf çekerken Android telefon kamerasından Java ile pozlama telafisi seviyesi nasıl edinilir?

Fotoğraf çekebilirim. Pozlama Telafisi (kontrol ettiğimde her zaman sıfır) dahil olmak üzere, Kameranın Parametrelerine erişebilirim, ancak daha önce değil, daha sonra değil, fotoğraf çekildiği anda AE Telafisi seviyesini almam gerekiyor.

Arka plan: Resimlerin çekildiği aynı AE Telafisi seviyesini kullanmak için belirli bir zamanda çekilen tüm fotoğrafların çekilmesini istiyorum. Bu yüzlerce ayarın, Android kameraların tipik olarak yaptığı poz seviyesine veya beyaz dengesine sahip olmasını istemiyorum. Bir kez olsun, tüm başarılı fotoğrafları ve aynı ayarları yapmak istiyorum.

Resimler, OpenCV, fragmanlar vb. Için "niyet" kullanmayı denedim. Bunlardan herhangi biriyle AE telafisi ayarını alamıyorum.

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

Eğer AE [ShutterCallback] (https://developer.android.com/reference/android/hardware/ almak denediniz bir boşluk fonksiyonu denir createPreviewSessions() diyoruz Camera.ShutterCallback.html) kovuldu? – NAmorim

+0

NAmorim Evet, böyle bir şey denedim. Nereye gittiğimi bulmak için sensör pozlama süresine ve sensör hassasiyetine bakıyorum. İşe yarayıp yaramadığından emin değil. Ama buna baktığın için teşekkürler. – Brian

+0

android.hardware.camera2 API'sını bir Option kullanıyor mu? Belki o zaman burada bir şey bulacaksınız: https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys() – Fildor

cevap

3

Ben camera2 düşünüyorum:

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); 
    } 
} 

İşte yukarıda belirtilen sınıfını kullanıyor Android adlı kod bazıları aşağıda verilmiştir: Burada ile JavaCameraView genişletilmiş bir versiyonunu başlayarak ben denedim en son kod API'lar (https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html) ihtiyacınızı karşılayacak.

Kaynak: Kamera cihazı uçakta istekleri bir boru hattı vardır

yana https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_LOCK, ille alınan son yakalama sonucu mevcuttu ayarlara karşılık gelmez hapse atarız ayarları kamera cihazı, ek yakalamalar ve AE güncellemeleri, sonuç gönderilmeden önce bile olabilir. Bir uygulama otomatik ve manuel kontrol arasındaki anahtarlama ve değişikliği sırasında herhangi titreşimlerini engelleyebilmek isterse, aşağıdaki prosedür önerilir:

  • Kilit AE
  • bekleyin:

    1. otomatik AE modunda başlatma AE kilitli olan ilk sonuç için çıktı
    2. Pozlama ayarlarını bu sonuçtan bir isteğe kopyalayın, isteği manuel olarak ayarlayın AE
    3. Yakalama isteğini gönderin, manuel AE'yi istediğiniz gibi çalıştırın. AE modunun tanımına göre olarak da
  • (aynı kaynak) AÇIK modlarından herhangi ayarlanmış

    , geçersiz kamera cihaz otomatik poz rutini tarafından seçilen değerler Belirli bir yakalama için alanlar, CaptureResult'da bulunabilir.İlk CaptureRequest yaptıktan sonra

    Yani, aşağıdaki callback'inde gelen TotalCaptureResult kullanabilirsiniz:

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

    numaralı postanın altına ekleyeceğim, kontrol edip çalışıp çalışmadığını kontrol edeyim. Umarım işe yarar; Şu an yaptığımdan çok daha kolay olurdu. – Brian

    +0

    Manish, Çalışmıyordu. Bunu başarmadan önce denedim. Nedenini bilmiyorum ama CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION, CaptureCallback (onCaptureComplete) olayında kullanıldığında bile, kamera için varsayılan ayar olan "0" değerini döndürür. Control_AE_Exposure_Compensation çalışmıyor, ancak işi bundan sonra yayınlayacağım. – Brian

    0

    Tamam, benzer bir sorun bulur kim bu kendim cevap vereceğim.

    Manish cevabına çok yaklaştı, ancak onCaptureSession olayında kullanıldığında bile, yalnızca 0 (sıfır), hiçbir şekilde kullanılmayan CONTROL_AE_EXPOSURE_COMPENSATION tarafından döndürülür; Bu kamera için sadece varsayılan başlangıç ​​değeri. Ancak, CameraCaptureSession.CaptureCallback (onCaptureSession olayı), Android kameralarla çalışmanın otomatik pozlama sorunuyla ilgili bir çalışma oluşturmak için SENSOR_EXPOSURE_TIME ve SENSOR_SENSITIVITY değerlerini almanıza izin veriyor. Aşağıda

    Ben kullanılan kod snippet'idir: Burada

    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()); 
    
          } 
         }; 
    

    benim ayıklayıcıya sonuçların bir resim: set nasıl

    enter image description here

    1

    Tamam, soru geldi Bir Android kamerayı kontrol etmek için kod yazarken pozlamayı, sensör hassasiyetini ve diğer değişkenleri betonlayın. Bu sadece Lollipop veya daha sonra çalışır. Gönderi yapmak için çok fazla kod var, ancak dikkat çekici noktalara koymaya çalışacağım.

    Özetle, bir CameraManager ile TextureView (AutoFitTextureView) kullanıyorum. Ben kamerayı açtığınızda, ben

    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 için teşekkürler. Android'de hala yeni bir kullanıcı olduğum için, burada ne yaptığınız konusunda net bir fikre sahip olamadım. İşine biraz ışık tutabilir misin? Bu gerçekten yardımcı olur. –

    +0

    Size daha fazla yardımcı olacak çok fazla kod var. Afedersiniz. – Brian

    İlgili konular