Not: Bu sayfa Kamera2 paketiyle ilgilidir. Uygulamanız için Kamera2'nin belirli, alt düzey özellikleri gerekmiyorsa, KameraX'i kullanmanızı öneririz. Hem CameraX hem de Camera2, Android 5.0 (API düzeyi 21) ve sonraki sürümleri destekler.
Çoklu kamera, Android 9 (API düzeyi 28) sürümünde kullanıma sunulmuştur. Yayınlandığından beri cihaz piyasasına API'yi destekleyen ek özellikler getirmiştir. Çok kameralı birçok kullanım alanı belirli bir donanım yapılandırmasıyla sıkı sıkıya bağlantılı. Başka bir deyişle Tüm kullanım alanları her cihazla uyumludur, bu da birden fazla kameranın Oyun Özelliği için iyi bir adaya sahip. Yayınlama.
Bazı tipik kullanım alanları şunlardır:
- Yakınlaştırma: Kırpma bölgesine veya istenen odak noktasına bağlı olarak kameralar arasında geçiş yapma seçeceğiz.
- Derinlik: Derinlik haritası oluşturmak için birden fazla kamera kullanma.
- Bokeh: DSLR benzeri dar bir görünümü simüle etmek için tahmin edilen derinlik bilgilerinin kullanılması odak aralığı.
Mantıksal ve fiziksel kameralar arasındaki fark
Çoklu kamera API'sini anlamak, mantıksal ve fiziksel kameralar. Referans olarak, üç özellik olan bir cihaz düşünün: kameralar. Bu örnekte, arkadaki üç kameranın her biri fiziksel bir kamera olarak değerlendirilir. Mantıksal kamera, iki veya daha fazla kameradan oluşan bir gruptur çok daha kolay oluyor. Mantıksal kamera, alttaki fiziksel kameraların birinden gelen bir akış olabilir. temeldeki birden fazla fiziksel kameradan gelen karma akış olanak tanır. Her iki durumda da akış kamera Donanımı tarafından işlenir. Soyutlama Katmanı (HAL).
Birçok telefon üreticisi, genellikle birinci taraf kamera uygulamaları yüklü olarak gelir. Donanımın tüm özelliklerini kullanmak için gizli API'ler kullanabilir veya gizli API'lerden özel muamele görebilirler. diğer uygulamaların erişemediği sürücü uygulamasıdır. Biraz mantıksal kameralar kavramını uygulamaya koyan cihazlar, farklı fiziksel kameralardan kareler alır, ancak yalnızca belirli ayrıcalıklı kameralara izin verir. Çoğu zaman fiziksel kameralardan yalnızca biri görüntüye maruz kalır. bahsedeceğim. Android 9'dan önceki üçüncü taraf geliştiriciler için durum: aşağıdaki şemada gösterilmektedir:
![](https://developer.android.com/static/images/training/camera/camera2/multi-camera-1.png?authuser=0000&hl=tr)
Android 9'dan itibaren Android uygulamalarında gizli API'lere artık izin verilmemektedir. Çerçeveye birden fazla kamera desteğinin dahil edilmesiyle birlikte, Android en iyi telefon üreticilerinin mantığa dayalı bir kamera ya da kameralar oluşturur. Bu dönüşüm üçüncü taraf geliştiriciler, Android 9 ve sonraki sürümleri çalıştıran cihazlarda daha yüksek:
![](https://developer.android.com/static/images/training/camera/camera2/multi-camera-2.png?authuser=0000&hl=tr)
Mantıksal kameranın sağladıkları, tamamen OEM uygulamasına bağlıdır bir görüntü kalitesidir. Örneğin, Pixel 3 gibi bir cihaz mantıksal konumdaki fiziksel kameralardan birini seçecek şekilde istenen odak uzaklığı ve kırpma bölgesi.
Çok kameralı API
Yeni API, aşağıdaki yeni sabit değerleri, sınıfları ve yöntemleri ekler:
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
CameraCharacteristics.getPhysicalCameraIds()
CameraCharacteristics.getAvailablePhysicalCameraRequestKeys()
CameraDevice.createCaptureSession(SessionConfiguration config)
CameraCharacteritics.LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
OutputConfiguration
veSessionConfiguration
Android Uyumluluk Tanımlama Belgesi'nde (CDD) yapılan değişiklikler nedeniyle çoklu kamera API'sini kullanmak, geliştiricilerin belirli beklentilerini de beraberinde getiriyor. Cihazlar Android 9'dan önce de çift kamera bulunuyordu ancak birden fazla kamera açılıyor hem de deneme yanılma yöntemini kullanıyordu. Android 9 ve sonraki sürümlerde çok kameralı bir çift fiziksel aktivitenin açılabileceğini belirten bir dizi Bunlar aynı mantıksal kameranın parçası olan kameralar.
Çoğu durumda, Android 9 ve sonraki sürümleri çalıştıran cihazlar tüm fiziksel kameralar (kızılötesi gibi daha seyrek görülen sensör türleri hariç) kullanımı kolay, mantıklı bir kamera. En iyi performans gösteren akış kombinasyonları için çalışacağı garanti edildiğinde, mantıksal bir kameraya ait bir akış, temel fiziksel kameralardan gelen iki akış bulunur.
Aynı anda birden fazla yayın
Birden fazla kamera akışını aynı anda kullanma
, tek bir kamerada aynı anda birden çok yayın kullanmaya ilişkin kuralları kapsar.
Önemli bir eklemeyle birlikte aynı kurallar birden fazla kamera için geçerli olur.
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
Mantıksal bir YUV_420_888 veya ham akışın iki
gerçekleşebilir. Yani, YUV veya RAW türündeki her akış
aynı tür ve büyüklükte iki akıştan oluşur. Şu videoya ait kamera yayınıyla başlayabilirsiniz:
Tek kameralı cihazlar için aşağıdaki garantili yapılandırma:
- 1. akış: YUV türü, mantıksal kameradan
MAXIMUM
boyut (id = 0
)
Ardından, çoklu kamera desteği sunan bir cihaz ile oturum oluşturmanıza olanak tanır. bu mantıksal YUV akışını iki fiziksel akışla değiştirir:
- 1. akış: YUV türü, fiziksel kameradan
MAXIMUM
boyutid = 1
- 2. akış: YUV türü, fiziksel kameradan
MAXIMUM
boyutid = 2
Bir YUV veya RAW akışını yalnızca aşağıdaki durumlarda iki eşdeğer akışla değiştirebilirsiniz:
bu iki kamera mantıksal bir kamera gruplandırmasının parçasıdır. Bu gruplandırma
CameraCharacteristics.getPhysicalCameraIds()
.
Çerçevenin sağladığı garantiler, sözleşmenin uygulanması için gereken aynı anda birden fazla fiziksel kameradan kare alabilir. Ek akışlar çoğu cihazda desteklenir. Hatta bazen, birden fazla fiziksel ayrı ayrı çalışır. Daha kesin bir ifadeyle, bunu yaparken cihaz başına test ve ince ayar yapılmasını gerektirir. deneme yanılma yöntemidir.
Birden çok fiziksel kamerayla oturum oluşturma
Çok kameralı bir cihazda fiziksel kameralar kullanırken tek bir
CameraDevice
(mantıksal kamera) ve tek bir kamerada bu kamerayla etkileşimde bulunun
kabul edilir. API'yi kullanarak tek oturum oluşturma
Önceki fiyatı: CameraDevice.createCaptureSession(SessionConfiguration config)
API düzeyi 28'de eklenmiştir. Oturum yapılandırmasında bir dizi çıkış vardır.
Her biri bir dizi çıkış hedefine sahip yapılandırma ve isteğe bağlı olarak
fiziksel kamera kimliğini girin.
![](https://developer.android.com/static/images/training/camera/camera2/multi-camera-3.png?authuser=0000&hl=tr)
Yakalama isteklerinin ilişkilendirilmiş bir çıkış hedefi vardır. Çerçeve isteklerin hangi fiziksel (veya mantıksal) kameraya gönderileceğini belirler hedefin ekli olduğunu görebilirsiniz. Çıkış hedefi fiziksel yapılandırmayla birlikte çıkış yapılandırması olarak gönderilen çıkış hedefleri fiziksel kameranın isteği alıp işlediğini gösterir.
Bir çift fiziksel kamera kullanma
Çoklu kamera için kamera API'lerine ek bir özellik de mantıksal kameralar ve bunların arkasındaki fiziksel kameraları bulur. Hedeflerinize göre bir kullanabileceğiniz potansiyel fiziksel kamera çiftlerini tanımlamaya yardımcı olan bir işlev mantıksal kamera akışlarından birini değiştirin:
Kotlin
/** * Helper class used to encapsulate a logical camera and two underlying * physical cameras */ data class DualCamera(val logicalId: String, val physicalId1: String, val physicalId2: String) fun findDualCameras(manager: CameraManager, facing: Int? = null): List{ val dualCameras = MutableList () // Iterate over all the available camera characteristics manager.cameraIdList.map { Pair(manager.getCameraCharacteristics(it), it) }.filter { // Filter by cameras facing the requested direction facing == null || it.first.get(CameraCharacteristics.LENS_FACING) == facing }.filter { // Filter by logical cameras // CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA requires API >= 28 it.first.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)!!.contains( CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) }.forEach { // All possible pairs from the list of physical cameras are valid results // NOTE: There could be N physical cameras as part of a logical camera grouping // getPhysicalCameraIds() requires API >= 28 val physicalCameras = it.first.physicalCameraIds.toTypedArray() for (idx1 in 0 until physicalCameras.size) { for (idx2 in (idx1 + 1) until physicalCameras.size) { dualCameras.add(DualCamera( it.second, physicalCameras[idx1], physicalCameras[idx2])) } } } return dualCameras }
Java
/** * Helper class used to encapsulate a logical camera and two underlying * physical cameras */ final class DualCamera { final String logicalId; final String physicalId1; final String physicalId2; DualCamera(String logicalId, String physicalId1, String physicalId2) { this.logicalId = logicalId; this.physicalId1 = physicalId1; this.physicalId2 = physicalId2; } } ListfindDualCameras(CameraManager manager, Integer facing) { List dualCameras = new ArrayList<>(); List cameraIdList; try { cameraIdList = Arrays.asList(manager.getCameraIdList()); } catch (CameraAccessException e) { e.printStackTrace(); cameraIdList = new ArrayList<>(); } // Iterate over all the available camera characteristics cameraIdList.stream() .map(id -> { try { CameraCharacteristics characteristics = manager.getCameraCharacteristics(id); return new Pair<>(characteristics, id); } catch (CameraAccessException e) { e.printStackTrace(); return null; } }) .filter(pair -> { // Filter by cameras facing the requested direction return (pair != null) && (facing == null || pair.first.get(CameraCharacteristics.LENS_FACING).equals(facing)); }) .filter(pair -> { // Filter by logical cameras // CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA requires API >= 28 IntPredicate logicalMultiCameraPred = arg -> arg == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA; return Arrays.stream(pair.first.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)) .anyMatch(logicalMultiCameraPred); }) .forEach(pair -> { // All possible pairs from the list of physical cameras are valid results // NOTE: There could be N physical cameras as part of a logical camera grouping // getPhysicalCameraIds() requires API >= 28 String[] physicalCameras = pair.first.getPhysicalCameraIds().toArray(new String[0]); for (int idx1 = 0; idx1 < physicalCameras.length; idx1++) { for (int idx2 = idx1 + 1; idx2 < physicalCameras.length; idx2++) { dualCameras.add( new DualCamera(pair.second, physicalCameras[idx1], physicalCameras[idx2])); } } }); return dualCameras; }
Fiziksel kameraların durumu, mantıksal kamera tarafından kontrol edilir. Alıcı: "çift kamera"yı açın, fiziksel makineye karşılık gelen mantıksal kamerayı kameralar:
Kotlin
fun openDualCamera(cameraManager: CameraManager, dualCamera: DualCamera, // AsyncTask is deprecated beginning API 30 executor: Executor = AsyncTask.SERIAL_EXECUTOR, callback: (CameraDevice) -> Unit) { // openCamera() requires API >= 28 cameraManager.openCamera( dualCamera.logicalId, executor, object : CameraDevice.StateCallback() { override fun onOpened(device: CameraDevice) = callback(device) // Omitting for brevity... override fun onError(device: CameraDevice, error: Int) = onDisconnected(device) override fun onDisconnected(device: CameraDevice) = device.close() }) }
Java
void openDualCamera(CameraManager cameraManager, DualCamera dualCamera, Executor executor, CameraDeviceCallback cameraDeviceCallback ) { // openCamera() requires API >= 28 cameraManager.openCamera(dualCamera.logicalId, executor, new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice cameraDevice) { cameraDeviceCallback.callback(cameraDevice); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice cameraDevice, int i) { onDisconnected(cameraDevice); } }); }
Hangi kameranın açılacağını seçmenin dışındaki işlemler, kamera kullanıyor olması. Yeni oturum yapılandırma API'sı, çerçeveye belirli hedeflerin Belirli fiziksel kamera kimlikleri:
Kotlin
/** * Helper type definition that encapsulates 3 sets of output targets: * * 1. Logical camera * 2. First physical camera * 3. Second physical camera */ typealias DualCameraOutputs = Triple<MutableList?, MutableList?, MutableList?> fun createDualCameraSession(cameraManager: CameraManager, dualCamera: DualCamera, targets: DualCameraOutputs, // AsyncTask is deprecated beginning API 30 executor: Executor = AsyncTask.SERIAL_EXECUTOR, callback: (CameraCaptureSession) -> Unit) { // Create 3 sets of output configurations: one for the logical camera, and // one for each of the physical cameras. val outputConfigsLogical = targets.first?.map { OutputConfiguration(it) } val outputConfigsPhysical1 = targets.second?.map { OutputConfiguration(it).apply { setPhysicalCameraId(dualCamera.physicalId1) } } val outputConfigsPhysical2 = targets.third?.map { OutputConfiguration(it).apply { setPhysicalCameraId(dualCamera.physicalId2) } } // Put all the output configurations into a single flat array val outputConfigsAll = arrayOf( outputConfigsLogical, outputConfigsPhysical1, outputConfigsPhysical2) .filterNotNull().flatMap { it } // Instantiate a session configuration that can be used to create a session val sessionConfiguration = SessionConfiguration( SessionConfiguration.SESSION_REGULAR, outputConfigsAll, executor, object : CameraCaptureSession.StateCallback() { override fun onConfigured(session: CameraCaptureSession) = callback(session) // Omitting for brevity... override fun onConfigureFailed(session: CameraCaptureSession) = session.device.close() }) // Open the logical camera using the previously defined function openDualCamera(cameraManager, dualCamera, executor = executor) { // Finally create the session and return via callback it.createCaptureSession(sessionConfiguration) } }
Java
/** * Helper class definition that encapsulates 3 sets of output targets: ** 1. Logical camera * 2. First physical camera * 3. Second physical camera */ final class DualCameraOutputs { private final List
logicalCamera; private final List firstPhysicalCamera; private final List secondPhysicalCamera; public DualCameraOutputs(List logicalCamera, List firstPhysicalCamera, List third) { this.logicalCamera = logicalCamera; this.firstPhysicalCamera = firstPhysicalCamera; this.secondPhysicalCamera = third; } public List getLogicalCamera() { return logicalCamera; } public List getFirstPhysicalCamera() { return firstPhysicalCamera; } public List getSecondPhysicalCamera() { return secondPhysicalCamera; } } interface CameraCaptureSessionCallback { void callback(CameraCaptureSession cameraCaptureSession); } void createDualCameraSession(CameraManager cameraManager, DualCamera dualCamera, DualCameraOutputs targets, Executor executor, CameraCaptureSessionCallback cameraCaptureSessionCallback) { // Create 3 sets of output configurations: one for the logical camera, and // one for each of the physical cameras. List outputConfigsLogical = targets.getLogicalCamera().stream() .map(OutputConfiguration::new) .collect(Collectors.toList()); List outputConfigsPhysical1 = targets.getFirstPhysicalCamera().stream() .map(s -> { OutputConfiguration outputConfiguration = new OutputConfiguration(s); outputConfiguration.setPhysicalCameraId(dualCamera.physicalId1); return outputConfiguration; }) .collect(Collectors.toList()); List outputConfigsPhysical2 = targets.getSecondPhysicalCamera().stream() .map(s -> { OutputConfiguration outputConfiguration = new OutputConfiguration(s); outputConfiguration.setPhysicalCameraId(dualCamera.physicalId2); return outputConfiguration; }) .collect(Collectors.toList()); // Put all the output configurations into a single flat array List outputConfigsAll = Stream.of( outputConfigsLogical, outputConfigsPhysical1, outputConfigsPhysical2 ) .filter(Objects::nonNull) .flatMap(Collection::stream) .collect(Collectors.toList()); // Instantiate a session configuration that can be used to create a session SessionConfiguration sessionConfiguration = new SessionConfiguration( SessionConfiguration.SESSION_REGULAR, outputConfigsAll, executor, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { cameraCaptureSessionCallback.callback(cameraCaptureSession); } // Omitting for brevity... @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { cameraCaptureSession.getDevice().close(); } }); // Open the logical camera using the previously defined function openDualCamera(cameraManager, dualCamera, executor, (CameraDevice c) -> // Finally create the session and return via callback c.createCaptureSession(sessionConfiguration)); }
Görüntüleyin
createCaptureSession
başlıklı makaleye göz atın. Akışları birleştirme
tek bir mantıksal kamerada
birden fazla yayın yapmak için kullanılır. Uyumluluk
aynı yapılandırmayı kullanarak ve bu akışlardan birini iki akışla değiştirerek
iki fiziksel kameradan çekilmiş görüntülerdir.
Şununla kamera oturumu hazır, istenen öğeyi yakalama istekleri. Her biri yakalama isteğinin hedefi, verilerini ilişkili fiziksel cihazdan alır kameranın yerini değiştirebilir veya mantıksal kameraya geri dönebilirsiniz.
Zoom örneği kullanım alanı
Fiziksel kameraların birleştirilmesiyle tek bir akış kullanılabilir. Farklı fiziksel kameralar arasında geçiş yaparak etkili bir şekilde farklı bir "yakınlaştırma seviyesi" yakalayan farklı bir görüş alanı sağlar.
![](https://developer.android.com/static/images/training/camera/camera2/multi-camera-4.gif?authuser=0000&hl=tr)
Kullanıcıların geçiş yapmasına izin vermek için fiziksel kamera çiftini seçerek başlayın arasında yer alır. En yüksek efekt için, her bir resmi ayrı ayrı oynatan mevcut minimum ve maksimum odak uzaklığı.
Kotlin
fun findShortLongCameraPair(manager: CameraManager, facing: Int? = null): DualCamera? { return findDualCameras(manager, facing).map { val characteristics1 = manager.getCameraCharacteristics(it.physicalId1) val characteristics2 = manager.getCameraCharacteristics(it.physicalId2) // Query the focal lengths advertised by each physical camera val focalLengths1 = characteristics1.get( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) ?: floatArrayOf(0F) val focalLengths2 = characteristics2.get( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) ?: floatArrayOf(0F) // Compute the largest difference between min and max focal lengths between cameras val focalLengthsDiff1 = focalLengths2.maxOrNull()!! - focalLengths1.minOrNull()!! val focalLengthsDiff2 = focalLengths1.maxOrNull()!! - focalLengths2.minOrNull()!! // Return the pair of camera IDs and the difference between min and max focal lengths if (focalLengthsDiff1 < focalLengthsDiff2) { Pair(DualCamera(it.logicalId, it.physicalId1, it.physicalId2), focalLengthsDiff1) } else { Pair(DualCamera(it.logicalId, it.physicalId2, it.physicalId1), focalLengthsDiff2) } // Return only the pair with the largest difference, or null if no pairs are found }.maxByOrNull { it.second }?.first }
Java
// Utility functions to find min/max value in float[] float findMax(float[] array) { float max = Float.NEGATIVE_INFINITY; for(float cur: array) max = Math.max(max, cur); return max; } float findMin(float[] array) { float min = Float.NEGATIVE_INFINITY; for(float cur: array) min = Math.min(min, cur); return min; } DualCamera findShortLongCameraPair(CameraManager manager, Integer facing) { return findDualCameras(manager, facing).stream() .map(c -> { CameraCharacteristics characteristics1; CameraCharacteristics characteristics2; try { characteristics1 = manager.getCameraCharacteristics(c.physicalId1); characteristics2 = manager.getCameraCharacteristics(c.physicalId2); } catch (CameraAccessException e) { e.printStackTrace(); return null; } // Query the focal lengths advertised by each physical camera float[] focalLengths1 = characteristics1.get( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS); float[] focalLengths2 = characteristics2.get( CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS); // Compute the largest difference between min and max focal lengths between cameras Float focalLengthsDiff1 = findMax(focalLengths2) - findMin(focalLengths1); Float focalLengthsDiff2 = findMax(focalLengths1) - findMin(focalLengths2); // Return the pair of camera IDs and the difference between min and max focal lengths if (focalLengthsDiff1 < focalLengthsDiff2) { return new Pair<>(new DualCamera(c.logicalId, c.physicalId1, c.physicalId2), focalLengthsDiff1); } else { return new Pair<>(new DualCamera(c.logicalId, c.physicalId2, c.physicalId1), focalLengthsDiff2); } }) // Return only the pair with the largest difference, or null if no pairs are found .max(Comparator.comparing(pair -> pair.second)).get().first; }
Bunun için mantıklı bir mimari, iki
SurfaceViews
: Her akış için bir adet.
Bu SurfaceViews
, kullanıcı etkileşimine göre değiştirilir. Böylece yalnızca biri
görünür olmalıdır.
Aşağıdaki kod, mantıksal kameranın nasıl açılacağını, kameranın nasıl yapılandırılacağını gösterir kamera oturumu oluşturun ve iki önizleme akışı başlatın:
Kotlin
val cameraManager: CameraManager = ... // Get the two output targets from the activity / fragment val surface1 = ... // from SurfaceView val surface2 = ... // from SurfaceView val dualCamera = findShortLongCameraPair(manager)!! val outputTargets = DualCameraOutputs( null, mutableListOf(surface1), mutableListOf(surface2)) // Here you open the logical camera, configure the outputs and create a session createDualCameraSession(manager, dualCamera, targets = outputTargets) { session -> // Create a single request which has one target for each physical camera // NOTE: Each target receive frames from only its associated physical camera val requestTemplate = CameraDevice.TEMPLATE_PREVIEW val captureRequest = session.device.createCaptureRequest(requestTemplate).apply { arrayOf(surface1, surface2).forEach { addTarget(it) } }.build() // Set the sticky request for the session and you are done session.setRepeatingRequest(captureRequest, null, null) }
Java
CameraManager manager = ...; // Get the two output targets from the activity / fragment Surface surface1 = ...; // from SurfaceView Surface surface2 = ...; // from SurfaceView DualCamera dualCamera = findShortLongCameraPair(manager, null); DualCameraOutputs outputTargets = new DualCameraOutputs( null, Collections.singletonList(surface1), Collections.singletonList(surface2)); // Here you open the logical camera, configure the outputs and create a session createDualCameraSession(manager, dualCamera, outputTargets, null, (session) -> { // Create a single request which has one target for each physical camera // NOTE: Each target receive frames from only its associated physical camera CaptureRequest.Builder captureRequestBuilder; try { captureRequestBuilder = session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); Arrays.asList(surface1, surface2).forEach(captureRequestBuilder::addTarget); // Set the sticky request for the session and you are done session.setRepeatingRequest(captureRequestBuilder.build(), null, null); } catch (CameraAccessException e) { e.printStackTrace(); } });
Kalan tek şey, kullanıcının bu ikisi arasında geçiş yapması için bir kullanıcı arayüzü sağlamaktır.
(ör. düğme veya SurfaceView
simgesine iki kez dokunma) Hatta,
Bir tür sahne analizi yapma ve iki akış arasında geçiş yapma
otomatik olarak oluşturur.
Lens bozulması
Tüm lensler belirli bir miktarda distorsiyon oluşturur. Android'de,
kullanarak lenslerin oluşturduğu distorsiyon
CameraCharacteristics.LENS_DISTORTION
Bu segment, desteği sonlandırılan
CameraCharacteristics.LENS_RADIAL_DISTORTION
.
Mantıksal kameralarda bozulma minimum düzeydedir ve uygulamanız,
kameradan gelen kare sayısını artırır. Fiziksel kameralarda
özellikle geniş açılı çekimde çok farklı lens konfigürasyonları
lensler.
Bazı cihazlar otomatik distorsiyon düzeltmeyi
CaptureRequest.DISTORTION_CORRECTION_MODE
.
Distorsiyon düzeltme özelliği çoğu cihazda varsayılan olarak açıktır.
Kotlin
val cameraSession: CameraCaptureSession = ... // Use still capture template to build the capture request val captureRequest = cameraSession.device.createCaptureRequest( CameraDevice.TEMPLATE_STILL_CAPTURE ) // Determine if this device supports distortion correction val characteristics: CameraCharacteristics = ... val supportsDistortionCorrection = characteristics.get( CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES )?.contains( CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY ) ?: false if (supportsDistortionCorrection) { captureRequest.set( CaptureRequest.DISTORTION_CORRECTION_MODE, CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY ) } // Add output target, set other capture request parameters... // Dispatch the capture request cameraSession.capture(captureRequest.build(), ...)
Java
CameraCaptureSession cameraSession = ...; // Use still capture template to build the capture request CaptureRequest.Builder captureRequestBuilder = null; try { captureRequestBuilder = cameraSession.getDevice().createCaptureRequest( CameraDevice.TEMPLATE_STILL_CAPTURE ); } catch (CameraAccessException e) { e.printStackTrace(); } // Determine if this device supports distortion correction CameraCharacteristics characteristics = ...; boolean supportsDistortionCorrection = Arrays.stream( characteristics.get( CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES )) .anyMatch(i -> i == CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY); if (supportsDistortionCorrection) { captureRequestBuilder.set( CaptureRequest.DISTORTION_CORRECTION_MODE, CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY ); } // Add output target, set other capture request parameters... // Dispatch the capture request cameraSession.capture(captureRequestBuilder.build(), ...);
Bu modda bir yakalama isteği ayarlamak, üretiliyor. Distorsiyon düzeltmesini yalnızca şuna ayarlamayı seçebilirsiniz: hareketsiz görüntü alınır.