شما هر مورد CameraX را برای کنترل جنبههای مختلف عملیات کیس استفاده پیکربندی میکنید.
به عنوان مثال، با استفاده از عکس گرفتن، می توانید نسبت تصویر هدف و حالت فلاش را تنظیم کنید. کد زیر یک مثال را نشان می دهد:
کاتلین
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
جاوا
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
علاوه بر گزینههای پیکربندی، برخی موارد استفاده APIها را در معرض تغییر پویا تنظیمات پس از ایجاد مورد استفاده قرار میدهند. برای اطلاعات در مورد پیکربندی که مختص موارد استفاده فردی است، به اجرای پیشنمایش ، تجزیه و تحلیل تصاویر ، و ضبط تصویر مراجعه کنید.
CameraXConfig
برای سادگی، CameraX دارای تنظیمات پیشفرض مانند مجریهای داخلی و کنترلکنندههایی است که برای اکثر سناریوهای استفاده مناسب هستند. با این حال، اگر برنامه شما دارای الزامات خاصی است یا ترجیح می دهد آن تنظیمات را سفارشی کند، CameraXConfig
رابطی برای این منظور است.
با CameraXConfig
، یک برنامه می تواند کارهای زیر را انجام دهد:
- تأخیر راه اندازی را با
setAvailableCameraLimiter()
بهینه کنید. - اجرای برنامه را با
setCameraExecutor()
در اختیار CameraX قرار دهید. - کنترل کننده زمانبندی پیش فرض را با
setSchedulerHandler()
جایگزین کنید. - سطح لاگ را با
setMinimumLoggingLevel()
تغییر دهید.
مدل استفاده
روش زیر نحوه استفاده از CameraXConfig
را شرح می دهد:
- یک شی
CameraXConfig
با تنظیمات سفارشی خود ایجاد کنید. - رابط
CameraXConfig.Provider
را درApplication
خود پیاده کنید و شیCameraXConfig
خود را درgetCameraXConfig()
برگردانید. - همانطور که در اینجا توضیح داده شده است، کلاس
Application
خود را به فایلAndroidManifest.xml
خود اضافه کنید.
به عنوان مثال، نمونه کد زیر ثبت CameraX را فقط به پیام های خطا محدود می کند:
کاتلین
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
اگر برنامه شما نیاز به دانستن پیکربندی CameraX پس از تنظیم آن دارد، یک کپی محلی از شی CameraXConfig
نگه دارید.
محدود کننده دوربین
در طول اولین فراخوانی ProcessCameraProvider.getInstance()
، CameraX ویژگی های دوربین های موجود در دستگاه را برمی شمارد و پرس و جو می کند. از آنجایی که CameraX نیاز به برقراری ارتباط با اجزای سخت افزاری دارد، این فرآیند برای هر دوربین، به ویژه در دستگاه های ارزان قیمت، می تواند مدت زمان کمی طول بکشد. اگر برنامه شما فقط از دوربینهای خاصی روی دستگاه استفاده میکند، مانند دوربین جلوی پیشفرض، میتوانید CameraX را طوری تنظیم کنید که دوربینهای دیگر را نادیده بگیرد، که میتواند تأخیر راهاندازی دوربینهایی را که برنامه شما استفاده میکند کاهش دهد.
اگر CameraSelector
به CameraXConfig.Builder.setAvailableCamerasLimiter()
ارسال شود، دوربینی را فیلتر می کند، CameraX طوری رفتار می کند که انگار آن دوربین وجود ندارد. به عنوان مثال، کد زیر برنامه را محدود می کند تا فقط از دوربین پشتی پیش فرض دستگاه استفاده کند:
کاتلین
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
موضوعات
بسیاری از APIهای پلتفرمی که CameraX بر روی آنها ساخته شده است نیاز به مسدود کردن ارتباطات بین پردازشی (IPC) با سخت افزار دارند که گاهی اوقات ممکن است صدها میلی ثانیه طول بکشد تا پاسخ دهند. به همین دلیل، CameraX فقط این APIها را از رشتههای پسزمینه فراخوانی میکند تا رشته اصلی مسدود نشود و UI روان باقی بماند. CameraX به صورت داخلی این رشته های پس زمینه را مدیریت می کند تا این رفتار شفاف به نظر برسد. با این حال، برخی از برنامه ها نیاز به کنترل دقیق موضوعات دارند. CameraXConfig
به یک برنامه اجازه میدهد رشتههای پسزمینه را که از طریق CameraXConfig.Builder.setCameraExecutor()
و CameraXConfig.Builder.setSchedulerHandler()
استفاده میشوند را تنظیم کند.
مجری دوربین
مجری دوربین برای همه تماسهای API داخلی پلتفرم دوربین و همچنین برای تماسهای برگشتی از این APIها استفاده میشود. CameraX یک Executor
داخلی را برای انجام این وظایف اختصاص داده و مدیریت می کند. با این حال، اگر برنامه شما نیاز به کنترل دقیق تری بر موضوعات دارد، از CameraXConfig.Builder.setCameraExecutor()
استفاده کنید.
برنامه ریز
کنترلکننده زمانبندی برای برنامهریزی کارهای داخلی در فواصل زمانی ثابت، مانند باز کردن مجدد دوربین در زمانی که در دسترس نیست، استفاده میشود. این کنترلر کارها را اجرا نمی کند و فقط آنها را به مجری دوربین ارسال می کند. همچنین گاهی اوقات در پلتفرم های API قدیمی که به یک Handler
برای پاسخگویی به تماس نیاز دارند استفاده می شود. در این موارد باز هم تماسهای تماس مستقیماً به مجری دوربین ارسال میشوند. CameraX یک HandlerThread
داخلی را برای انجام این کارها اختصاص داده و مدیریت می کند، اما می توانید با CameraXConfig.Builder.setSchedulerHandler()
آن را لغو کنید.
ورود به سیستم
گزارش CameraX به برنامهها اجازه میدهد پیامهای logcat را فیلتر کنند، زیرا میتواند تمرین خوبی برای جلوگیری از پیامهای پرمخاطب در کد تولید شما باشد. CameraX از چهار سطح گزارش گیری، از پرحرف ترین تا شدیدترین، پشتیبانی می کند:
-
Log.DEBUG
(پیشفرض) -
Log.INFO
-
Log.WARN
-
Log.ERROR
برای توصیف دقیق این سطوح گزارش به مستندات Android Log مراجعه کنید. از CameraXConfig.Builder.setMinimumLoggingLevel(int)
برای تنظیم سطح گزارش مناسب برای برنامه خود استفاده کنید.
انتخاب خودکار
CameraX به طور خودکار عملکردی را ارائه می دهد که مخصوص دستگاهی است که برنامه شما روی آن اجرا می شود. به عنوان مثال، CameraX به طور خودکار بهترین رزولوشن را برای استفاده در صورتی که وضوحی را مشخص نکردهاید، یا اگر وضوحی که مشخص میکنید پشتیبانی نمیشود، تعیین میکند. همه اینها توسط کتابخانه انجام می شود و نیازی به نوشتن کدهای خاص دستگاه را از بین می برد.
هدف CameraX این است که با موفقیت یک جلسه دوربین را راه اندازی کند. این بدان معناست که CameraX بر اساس قابلیت دستگاه، رزولوشن و نسبت ابعاد را به خطر می اندازد. سازش می تواند اتفاق بیفتد زیرا:
- دستگاه از وضوح درخواستی پشتیبانی نمی کند.
- دستگاه دارای مشکلات سازگاری است، مانند دستگاههای قدیمی که برای عملکرد صحیح به وضوحهای خاصی نیاز دارند.
- در برخی از دستگاهها، فرمتهای خاص فقط با نسبتهای تصویری خاص در دسترس هستند.
- این دستگاه برای کدگذاری JPEG یا ویدیو، «نزدیکترین mod16» را ترجیح می دهد. برای اطلاعات بیشتر،
SCALER_STREAM_CONFIGURATION_MAP
ببینید.
اگرچه CameraX جلسه را ایجاد و مدیریت می کند، همیشه اندازه های تصویر برگشتی را در خروجی Use case در کد خود بررسی کنید و بر اساس آن تنظیم کنید.
چرخش
بهطور پیشفرض، چرخش دوربین به گونهای تنظیم میشود که با چرخش نمایشگر پیشفرض در طول ایجاد کیس استفاده مطابقت داشته باشد. در این حالت پیشفرض، CameraX خروجیهایی تولید میکند تا به برنامه اجازه دهد با آنچه انتظار دارید در پیشنمایش ببینید مطابقت داشته باشد. میتوانید چرخش را به یک مقدار سفارشی تغییر دهید تا از دستگاههای چند نمایشگر پشتیبانی کند، با عبور از جهت نمایش فعلی هنگام پیکربندی اشیاء مورد استفاده یا به صورت پویا پس از ایجاد آنها.
برنامه شما می تواند چرخش هدف را با استفاده از تنظیمات پیکربندی تنظیم کند. سپس میتواند تنظیمات چرخش را با استفاده از روشهای استفاده از APIهای مورد استفاده (مانند ImageAnalysis.setTargetRotation()
) بهروزرسانی کند، حتی زمانی که چرخه حیات در حالت در حال اجرا است. هنگامی که برنامه در حالت عمودی قفل است، ممکن است از این استفاده کنید - و بنابراین هیچ پیکربندی مجدد در چرخش رخ نمی دهد - اما مورد استفاده از عکس یا تجزیه و تحلیل باید از چرخش فعلی دستگاه آگاه باشد. برای مثال، آگاهی از چرخش ممکن است لازم باشد تا چهرهها برای تشخیص چهره به درستی جهتگیری شوند، یا عکسها روی افقی یا عمودی تنظیم شوند.
داده های تصاویر گرفته شده ممکن است بدون اطلاعات چرخش ذخیره شوند. دادههای Exif حاوی اطلاعات چرخش هستند تا برنامههای گالری بتوانند تصویر را پس از ذخیره کردن در جهت صحیح نشان دهند.
برای نمایش داده های پیش نمایش با جهت گیری صحیح، می توانید از خروجی ابرداده از Preview.PreviewOutput()
برای ایجاد تبدیل استفاده کنید.
نمونه کد زیر نحوه تنظیم چرخش روی یک رویداد جهتگیری را نشان میدهد:
کاتلین
override fun onCreate() { val imageCapture = ImageCapture.Builder().build() val orientationEventListener = object : OrientationEventListener(this as Context) { override fun onOrientationChanged(orientation : Int) { // Monitors orientation values to determine the target rotation value val rotation : Int = when (orientation) { in 45..134 -> Surface.ROTATION_270 in 135..224 -> Surface.ROTATION_180 in 225..314 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageCapture.targetRotation = rotation } } orientationEventListener.enable() }
جاوا
@Override public void onCreate() { ImageCapture imageCapture = new ImageCapture.Builder().build(); OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) { @Override public void onOrientationChanged(int orientation) { int rotation; // Monitors orientation values to determine the target rotation value if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
بر اساس چرخش تنظیم شده، هر مورد استفاده یا داده های تصویر را مستقیماً می چرخاند یا ابرداده چرخشی را به مصرف کنندگان داده های تصویر چرخانده نشده ارائه می دهد.
- پیش نمایش : خروجی ابرداده به گونه ای ارائه می شود که چرخش وضوح هدف با استفاده از
Preview.getTargetRotation()
مشخص می شود. - ImageAnalysis : خروجی فراداده ارائه می شود تا مختصات بافر تصویر نسبت به مختصات نمایش شناخته شود.
- ImageCapture : فراداده Exif، بافر یا هر دو بافر و ابرداده برای توجه به تنظیمات چرخش تغییر می کنند. مقدار تغییر یافته بستگی به اجرای HAL دارد.
Crop rect
به طور پیش فرض، crop rect بافر کامل rect است. می توانید آن را با ViewPort
و UseCaseGroup
سفارشی کنید. CameraX با گروه بندی موارد استفاده و تنظیم درگاه دید، تضمین می کند که برش تمام موارد استفاده در گروه به همان ناحیه در سنسور دوربین اشاره می کند.
قطعه کد زیر نحوه استفاده از این دو کلاس را نشان می دهد:
کاتلین
val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build() val useCaseGroup = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build() cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)
جاوا
ViewPort viewPort = new ViewPort.Builder( new Rational(width, height), getDisplay().getRotation()).build(); UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build(); cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
ViewPort
بافر مستقیم قابل مشاهده برای کاربران نهایی را تعریف می کند. سپس CameraX بزرگترین Crop Rect ممکن را بر اساس ویژگی های viewport و موارد استفاده پیوست شده محاسبه می کند. معمولاً برای دستیابی به افکت WYSIWYG، میتوانید Viewport را بر اساس مورد استفاده پیشنمایش پیکربندی کنید. یک راه ساده برای دریافت ویوپورت استفاده از PreviewView
است.
قطعه کد زیر نحوه دریافت شی ViewPort
را نشان می دهد:
کاتلین
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
جاوا
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
در مثال قبل، آنچه برنامه از ImageAnalysis
و ImageCapture
دریافت میکند با آنچه کاربر نهایی در PreviewView
میبیند مطابقت دارد، با این فرض که نوع مقیاس PreviewView
روی پیشفرض، FILL_CENTER
تنظیم شده است. پس از اعمال برش راست و چرخش در بافر خروجی، تصویر همه موارد استفاده یکسان است، اگرچه احتمالاً با وضوحهای متفاوت. برای اطلاعات بیشتر درباره نحوه اعمال اطلاعات تبدیل، خروجی تبدیل را ببینید.
انتخاب دوربین
CameraX به طور خودکار بهترین دستگاه دوربین را برای نیازهای برنامه و موارد استفاده شما انتخاب می کند. اگر می خواهید از دستگاهی متفاوت از دستگاهی که برای شما انتخاب شده است استفاده کنید، چند گزینه وجود دارد:
- دوربین جلوی پیشفرض را با
CameraSelector.DEFAULT_FRONT_CAMERA
درخواست کنید.DEFAULT_FRONT_CAMERA. - دوربین عقب پیشفرض را با
CameraSelector.DEFAULT_BACK_CAMERA
درخواست کنید.DEFAULT_BACK_CAMERA. - با
CameraSelector.Builder.addCameraFilter()
لیست دستگاه های موجود را بر اساسCameraCharacteristics
آنها فیلتر کنید.
نمونه کد زیر نحوه ایجاد CameraSelector
برای تأثیرگذاری بر انتخاب دستگاه را نشان می دهد:
کاتلین
fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? { val cam2Infos = provider.availableCameraInfos.map { Camera2CameraInfo.from(it) }.sortedByDescending { // HARDWARE_LEVEL is Int type, with the order of: // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) } return when { cam2Infos.isNotEmpty() -> { CameraSelector.Builder() .addCameraFilter { it.filter { camInfo -> // cam2Infos[0] is either EXTERNAL or best built-in camera val thisCamId = Camera2CameraInfo.from(camInfo).cameraId thisCamId == cam2Infos[0].cameraId } }.build() } else -> null } } // create a CameraSelector for the USB camera (or highest level internal camera) val selector = selectExternalOrBestCamera(processCameraProvider) processCameraProvider.bindToLifecycle(this, selector, preview, analysis)
چندین دوربین را به طور همزمان انتخاب کنید
با شروع با CameraX 1.3، شما همچنین می توانید چندین دوربین را به طور همزمان انتخاب کنید. به عنوان مثال، می توانید به دوربین جلو و عقب متصل شوید تا از هر دو منظر به طور همزمان عکس بگیرید یا فیلم بگیرید.
هنگام استفاده از ویژگی دوربین همزمان، دستگاه میتواند همزمان با دو دوربین با لنزهای مختلف کار کند یا دو دوربین پشتی را به طور همزمان کار کند. بلوک کد زیر نحوه تنظیم دو دوربین را هنگام فراخوانی bindToLifecycle
و نحوه دریافت هر دو شی Camera از شی ConcurrentCamera
برگشتی را نشان می دهد.
کاتلین
// Build ConcurrentCameraConfig val primary = ConcurrentCamera.SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ) val secondary = ConcurrentCamera.SingleCameraConfig( secondaryCameraSelector, useCaseGroup, lifecycleOwner ) val concurrentCamera = cameraProvider.bindToLifecycle( listOf(primary, secondary) ) val primaryCamera = concurrentCamera.cameras[0] val secondaryCamera = concurrentCamera.cameras[1]
جاوا
// Build ConcurrentCameraConfig SingleCameraConfig primary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); SingleCameraConfig secondary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); ConcurrentCamera concurrentCamera = mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary)); Camera primaryCamera = concurrentCamera.getCameras().get(0); Camera secondaryCamera = concurrentCamera.getCameras().get(1);
وضوح دوربین
میتوانید به CameraX اجازه دهید وضوح تصویر را بر اساس ترکیبی از قابلیتهای دستگاه، سطح سختافزار پشتیبانیشده دستگاه، موارد استفاده و نسبت تصویر ارائهشده تنظیم کند. از طرف دیگر، میتوانید رزولوشن هدف یا نسبت ابعاد خاصی را در موارد استفاده که از آن پیکربندی پشتیبانی میکنند، تنظیم کنید.
وضوح خودکار
CameraX می تواند به طور خودکار بهترین تنظیمات وضوح را بر اساس موارد استفاده مشخص شده در cameraProcessProvider.bindToLifecycle()
تعیین کند. در صورت امکان، تمام موارد استفاده مورد نیاز برای اجرای همزمان در یک جلسه در یک فراخوانی bindToLifecycle()
را مشخص کنید. CameraX بر اساس مجموعه موارد استفاده محدود شده با در نظر گرفتن سطح سختافزار پشتیبانی شده دستگاه و با در نظر گرفتن واریانس خاص دستگاه (در مواردی که دستگاه از پیکربندیهای جریان موجود فراتر میرود یا مطابقت ندارد)، وضوحها را تعیین میکند. هدف این است که به برنامه اجازه دهیم در طیف گسترده ای از دستگاه ها اجرا شود و در عین حال مسیرهای کد خاص دستگاه را به حداقل برسانیم.
نسبت تصویر پیش فرض برای موارد استفاده از عکس برداری و تحلیل تصویر 4:3 است.
موارد استفاده دارای نسبت ابعاد قابل تنظیم هستند تا به برنامه اجازه دهند نسبت تصویر مورد نظر را بر اساس طراحی UI مشخص کند. خروجی CameraX برای مطابقت با نسبت های درخواستی به همان میزانی که دستگاه پشتیبانی می کند تولید می شود. اگر وضوح تطابق دقیقی وجود نداشته باشد، گزینه ای که بیشترین شرایط را برآورده می کند انتخاب می شود. بنابراین، برنامه نحوه نمایش دوربین در برنامه را دیکته میکند و CameraX بهترین تنظیمات وضوح دوربین را برای برآورده کردن آن در دستگاههای مختلف تعیین میکند.
به عنوان مثال، یک برنامه می تواند یکی از کارهای زیر را انجام دهد:
- وضوح هدف 4:3 یا 16:9 را برای یک مورد استفاده مشخص کنید
- رزولوشن سفارشی را مشخص کنید، که CameraX سعی میکند نزدیکترین تطابق را پیدا کند
- یک نسبت تصویر برش برای
ImageCapture
مشخص کنید
CameraX وضوح سطح داخلی Camera2 را به طور خودکار انتخاب می کند. جدول زیر قطعنامه ها را نشان می دهد:
مورد استفاده | وضوح سطح داخلی | وضوح داده های خروجی |
---|---|---|
پیش نمایش | نسبت تصویر: وضوحی که بهترین تناسب را با هدف با تنظیمات دارد. | وضوح سطح داخلی ابرداده ارائه شده است تا امکان برش، مقیاس و چرخش View برای نسبت ابعاد هدف را فراهم کند. |
وضوح پیشفرض: بالاترین وضوح پیشنمایش یا بالاترین وضوح ترجیحی دستگاه که با نسبت تصویر پیشنمایش مطابقت دارد. | ||
حداکثر وضوح: اندازه پیش نمایش، که به بهترین اندازه مطابقت با وضوح صفحه نمایش دستگاه یا به 1080p (1920x1080) اشاره دارد که هر کدام کوچکتر باشد. | ||
تجزیه و تحلیل تصویر | نسبت تصویر: وضوحی که بهترین تناسب با هدف را با تنظیمات دارد. | وضوح سطح داخلی |
وضوح پیش فرض: تنظیم وضوح هدف پیش فرض 640x480 است. تنظیم وضوح هدف و نسبت تصویر متناظر منجر به بهترین وضوح پشتیبانی می شود. | ||
حداکثر وضوح: حداکثر وضوح خروجی دستگاه دوربین با فرمت YUV_420_888 که از StreamConfigurationMap.getOutputSizes() بازیابی شده است. رزولوشن هدف به طور پیشفرض 640x480 تنظیم شده است، بنابراین اگر رزولوشن بزرگتر از 640x480 میخواهید، باید از setTargetResolution() و setTargetAspectRatio() استفاده کنید تا نزدیکترین وضوح را از وضوحهای پشتیبانی شده بدست آورید. | ||
ضبط تصویر | نسبت تصویر: نسبت تصویری که به بهترین شکل با تنظیمات مطابقت دارد. | وضوح سطح داخلی |
وضوح پیشفرض: بالاترین وضوح موجود، یا بالاترین وضوح ترجیحی دستگاه که با نسبت تصویر ImageCapture مطابقت دارد. | ||
حداکثر وضوح: حداکثر وضوح خروجی دستگاه دوربین در فرمت JPEG. برای بازیابی از StreamConfigurationMap.getOutputSizes() استفاده کنید. |
قطعنامه را مشخص کنید
همانطور که در نمونه کد زیر نشان داده شده است، می توانید هنگام ساخت موارد استفاده با استفاده از روش setTargetResolution(Size resolution)
رزولوشن های خاصی را تنظیم کنید:
کاتلین
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
جاوا
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
شما نمی توانید هم نسبت تصویر هدف و هم وضوح هدف را در یک مورد استفاده تنظیم کنید. انجام این کار باعث ایجاد یک IllegalArgumentException
در هنگام ساختن شیء پیکربندی می شود.
پس از چرخاندن اندازه های پشتیبانی شده توسط چرخش هدف، وضوح Size
را در کادر مختصات بیان کنید. به عنوان مثال، دستگاهی با جهت گیری طبیعی پرتره در چرخش هدف طبیعی که درخواست تصویر پرتره می کند، می تواند 480x640 را مشخص کند و همان دستگاه، با چرخش 90 درجه و جهت گیری افقی هدف می تواند 640x480 را مشخص کند.
رزولوشن هدف تلاش میکند حداقل حدی را برای وضوح تصویر ایجاد کند. وضوح تصویر واقعی نزدیکترین وضوح موجود در اندازه است که از وضوح هدف کوچکتر نیست، همانطور که توسط اجرای دوربین تعیین می شود.
با این حال، اگر وضوحی برابر یا بزرگتر از وضوح هدف وجود نداشته باشد، نزدیکترین وضوح موجود کوچکتر از وضوح هدف انتخاب می شود. رزولوشن هایی با نسبت ابعاد یکسان با Size
ارائه شده اولویت بیشتری نسبت به وضوح نسبت های مختلف دارند.
CameraX بهترین وضوح مناسب را بر اساس درخواست اعمال می کند. اگر نیاز اولیه برآوردن نسبت تصویر است، فقط setTargetAspectRatio
مشخص کنید، و CameraX وضوح خاصی را بر اساس دستگاه تعیین می کند. اگر نیاز اولیه برنامه تعیین وضوح برای کارآمدتر کردن پردازش تصویر است (به عنوان مثال یک تصویر کوچک یا متوسط بر اساس قابلیت پردازش دستگاه)، از setTargetResolution(Size resolution)
استفاده کنید.
اگر برنامه شما به وضوح دقیق نیاز دارد، جدول موجود در createCaptureSession()
را ببینید تا تعیین کنید که حداکثر وضوح توسط هر سطح سخت افزاری پشتیبانی می شود. برای بررسی وضوحهای خاص پشتیبانی شده توسط دستگاه فعلی، به StreamConfigurationMap.getOutputSizes(int)
مراجعه کنید.
اگر برنامه شما روی Android 10 یا بالاتر اجرا میشود، میتوانید از isSessionConfigurationSupported()
برای تأیید یک SessionConfiguration
خاص استفاده کنید.
کنترل خروجی دوربین
CameraX علاوه بر اینکه به شما امکان میدهد خروجی دوربین را بر اساس نیاز برای هر مورد شخصی پیکربندی کنید، رابطهای زیر را نیز برای پشتیبانی از عملیات دوربین مشترک برای همه موارد استفاده محدود پیادهسازی میکند:
-
CameraControl
به شما امکان می دهد ویژگی های رایج دوربین را پیکربندی کنید. -
CameraInfo
به شما امکان می دهد وضعیت آن ویژگی های رایج دوربین را جویا شوید.
اینها ویژگی های دوربین پشتیبانی شده با CameraControl هستند:
- بزرگنمایی ضربه بزنید؛
- مشعل
- فوکوس و اندازه گیری (ضربه به فوکوس)
- جبران نوردهی
نمونه هایی از CameraControl و CameraInfo را دریافت کنید
نمونه هایی از CameraControl
و CameraInfo
را با استفاده از شی Camera
که توسط ProcessCameraProvider.bindToLifecycle()
برگردانده شده است، بازیابی کنید. کد زیر یک مثال را نشان می دهد:
کاتلین
val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. val cameraControl = camera.cameraControl // For querying information and states. val cameraInfo = camera.cameraInfo
جاوا
Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. CameraControl cameraControl = camera.getCameraControl() // For querying information and states. CameraInfo cameraInfo = camera.getCameraInfo()
برای مثال، میتوانید زوم و سایر عملیات CameraControl
را پس از فراخوانی bindToLifecycle()
ارسال کنید. پس از توقف یا از بین بردن فعالیت مورد استفاده برای اتصال نمونه دوربین، CameraControl
دیگر نمی تواند عملیات را اجرا کند و ListenableFuture
ناموفق را برمی گرداند.
بزرگنمایی ضربه بزنید؛
CameraControl دو روش برای تغییر سطح زوم ارائه می دهد:
setZoomRatio()
بزرگنمایی را با نسبت بزرگنمایی تنظیم می کند.نسبت باید در محدوده
CameraInfo.getZoomState().getValue().getMinZoomRatio()
وCameraInfo.getZoomState().getValue().getMaxZoomRatio()
باشد. در غیر این صورت تابع یکListenableFuture
ناموفق را برمی گرداند.setLinearZoom()
زوم فعلی را با مقدار زوم خطی از 0 تا 1.0 تنظیم می کند.مزیت بزرگنمایی خطی این است که با تغییر در بزرگنمایی، میدان دید (FOV) را مقیاس می کند. این آن را برای استفاده با نمای
Slider
ایده آل می کند.
CameraInfo.getZoomState()
یک LiveData از حالت زوم فعلی را برمی گرداند. هنگامی که دوربین مقداردهی اولیه می شود یا اگر سطح زوم با استفاده از setZoomRatio()
یا setLinearZoom()
تنظیم شود، مقدار تغییر می کند. فراخوانی هر یک از متدها، مقادیر پشتیبان ZoomState.getZoomRatio()
و ZoomState.getLinearZoom()
را تنظیم می کند. اگر میخواهید متن نسبت بزرگنمایی را در کنار یک نوار لغزنده نمایش دهید، مفید است. به سادگی ZoomState
LiveData
مشاهده کنید تا هر دو را بدون نیاز به انجام تبدیل به روز کنید.
ListenableFuture
که توسط هر دو API بازگردانده شده است، این گزینه را برای برنامهها ارائه میدهد که در صورت تکمیل درخواست تکراری با مقدار بزرگنمایی مشخص شده، مطلع شوند. علاوه بر این، اگر در حالی که عملیات قبلی هنوز در حال اجرا است، مقدار بزرگنمایی جدیدی تنظیم کنید، ListenableFuture
عملیات بزرگنمایی قبلی فوراً از کار می افتد.
مشعل
CameraControl.enableTorch(boolean)
مشعل را فعال یا غیرفعال می کند (همچنین به عنوان چراغ قوه شناخته می شود).
CameraInfo.getTorchState()
را می توان برای پرس و جو از وضعیت فعلی مشعل استفاده کرد. می توانید مقدار بازگردانده شده توسط CameraInfo.hasFlashUnit()
را بررسی کنید تا مشخص کنید مشعل موجود است یا خیر. در غیر این صورت، فراخوانی CameraControl.enableTorch(boolean)
باعث می شود که ListenableFuture
برگشتی فوراً با نتیجه ناموفق کامل شود و حالت مشعل را روی TorchState.OFF
تنظیم می کند.
هنگامی که مشعل فعال است، بدون در نظر گرفتن تنظیمات حالت فلش، در هنگام گرفتن عکس و فیلم روشن می ماند. flashMode
در ImageCapture
فقط زمانی کار می کند که مشعل غیرفعال باشد.
فوکوس و اندازه گیری
CameraControl.startFocusAndMetering()
با تنظیم مناطق اندازه گیری AF/AE/AWB بر اساس FocusMeteringAction داده شده، فوکوس خودکار و نورسنجی را فعال می کند. این اغلب برای پیاده سازی ویژگی "ضربه برای فوکوس" در بسیاری از برنامه های دوربین استفاده می شود.
نقطه اندازه گیری
برای شروع، با استفاده از MeteringPointFactory.createPoint(float x, float y, float size)
یک MeteringPoint
ایجاد کنید. یک MeteringPoint
یک نقطه روی Surface
دوربین را نشان می دهد. این به شکل عادی ذخیره می شود تا بتوان آن را به راحتی به مختصات حسگر برای تعیین مناطق AF/AE/AWB تبدیل کرد.
اندازه MeteringPoint
از 0 تا 1 با اندازه پیش فرض 0.15f متغیر است. هنگام فراخوانی MeteringPointFactory.createPoint(float x, float y, float size)
، CameraX یک ناحیه مستطیلی در مرکز (x, y)
برای size
ارائه شده ایجاد می کند.
کد زیر نحوه ایجاد MeteringPoint
را نشان می دهد:
کاتلین
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview. previewView.setOnTouchListener((view, motionEvent) -> { val meteringPoint = previewView.meteringPointFactory .createPoint(motionEvent.x, motionEvent.y) … } // Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for // preview. Please note that if the preview is scaled or cropped in the View, // it’s the application's responsibility to transform the coordinates properly // so that the width and height of this factory represents the full Preview FOV. // And the (x,y) passed to create MeteringPoint might need to be adjusted with // the offsets. val meteringPointFactory = DisplayOrientedMeteringPointFactory( surfaceView.display, camera.cameraInfo, surfaceView.width, surfaceView.height ) // Use SurfaceOrientedMeteringPointFactory if the point is specified in // ImageAnalysis ImageProxy. val meteringPointFactory = SurfaceOrientedMeteringPointFactory( imageWidth, imageHeight, imageAnalysis)
startFocusAndMetering و FocusMeteringAction
برای فراخوانی startFocusAndMetering()
، برنامه ها باید یک FocusMeteringAction
بسازند که شامل یک یا چند MeteringPoints
با ترکیب حالت اندازه گیری اختیاری از FLAG_AF
، FLAG_AE
، FLAG_AWB
است. کد زیر این استفاده را نشان می دهد:
کاتلین
val meteringPoint1 = meteringPointFactory.createPoint(x1, x1) val meteringPoint2 = meteringPointFactory.createPoint(x2, y2) val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB // Optionally add meteringPoint2 for AF/AE. .addPoint(meteringPoint2, FLAG_AF | FLAG_AE) // The action is canceled in 3 seconds (if not set, default is 5s). .setAutoCancelDuration(3, TimeUnit.SECONDS) .build() val result = cameraControl.startFocusAndMetering(action) // Adds listener to the ListenableFuture if you need to know the focusMetering result. result.addListener({ // result.get().isFocusSuccessful returns if the auto focus is successful or not. }, ContextCompat.getMainExecutor(this)
همانطور که در کد قبل نشان داده شده است، startFocusAndMetering()
یک FocusMeteringAction
متشکل از یک MeteringPoint
برای مناطق اندازه گیری AF/AE/AWB و MeteringPoint دیگر فقط برای AF و AE می گیرد.
در داخل، CameraX آن را به Camera2 MeteringRectangles
تبدیل میکند و پارامترهای مربوطه CONTROL_AF_REGIONS
/ CONTROL_AE_REGIONS
/ CONTROL_AWB_REGIONS
را به درخواست عکسبرداری تنظیم میکند.
از آنجایی که هر دستگاهی از AF/AE/AWB و چندین ناحیه پشتیبانی نمیکند، CameraX FocusMeteringAction
با بهترین تلاش اجرا میکند. CameraX از حداکثر تعداد MeteringPoints پشتیبانی شده استفاده می کند، به ترتیبی که نقاط اضافه شده اند. تمام MeteringPoints اضافه شده پس از حداکثر تعداد نادیده گرفته می شود. به عنوان مثال، اگر یک FocusMeteringAction
با 3 MeteringPoint در پلتفرمی که فقط 2 را پشتیبانی می کند عرضه شود، فقط از 2 MeteringPoint اول استفاده می شود. آخرین MeteringPoint
توسط CameraX نادیده گرفته می شود.
جبران نوردهی
جبران نوردهی زمانی مفید است که برنامهها نیاز به تنظیم دقیق مقادیر نوردهی (EV) فراتر از نتیجه خروجی نوردهی خودکار (AE) دارند. مقادیر جبران نوردهی به روش زیر برای تعیین نوردهی لازم برای شرایط فعلی تصویر ترکیب میشوند:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX تابع Camera.CameraControl.setExposureCompensationIndex()
را برای تنظیم جبران نوردهی به عنوان مقدار شاخص ارائه می دهد.
مقادیر شاخص مثبت تصویر را روشن تر می کند، در حالی که مقادیر منفی تصویر را کم نور می کند. برنامه ها می توانند محدوده پشتیبانی شده را توسط CameraInfo.ExposureState.exposureCompensationRange()
که در بخش بعدی توضیح داده شده است، جستجو کنند. اگر مقدار پشتیبانی شود، ListenableFuture
برگشتی زمانی تکمیل می شود که مقدار با موفقیت در درخواست ضبط فعال شود. اگر نمایه مشخص شده خارج از محدوده پشتیبانی شده باشد، setExposureCompensationIndex()
باعث می شود که ListenableFuture
برگشتی بلافاصله با نتیجه ناموفق کامل شود.
CameraX فقط آخرین درخواست setExposureCompensationIndex()
را نگه می دارد و چندین بار فراخوانی تابع قبل از اجرای درخواست قبلی منجر به لغو آن می شود.
قطعه زیر یک شاخص جبران نوردهی را تنظیم می کند و برای زمانی که درخواست تغییر نوردهی اجرا شده است، یک تماس برگشتی ثبت می کند:
کاتلین
camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex) .addListener({ // Get the current exposure compensation index, it might be // different from the asked value in case this request was // canceled by a newer setting request. val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex … }, mainExecutor)
Camera.CameraInfo.getExposureState()
ExposureState
فعلی را از جمله:- قابلیت پشتیبانی کنترل جبران نوردهی
- شاخص جبران مواجهه فعلی
- محدوده شاخص جبران نوردهی
- مرحله جبران نوردهی مورد استفاده در محاسبه ارزش جبران نوردهی.
به عنوان مثال، کد زیر تنظیمات یک SeekBar
نوردهی با مقادیر ExposureState
فعلی را مقداردهی اولیه می کند:
کاتلین
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
منابع اضافی
برای کسب اطلاعات بیشتر در مورد CameraX، به منابع اضافی زیر مراجعه کنید.
Codelab
نمونه کد
جامعه توسعه دهندگان
،شما هر مورد CameraX را برای کنترل جنبههای مختلف عملیات کیس استفاده پیکربندی میکنید.
به عنوان مثال، با استفاده از عکس گرفتن، می توانید نسبت تصویر هدف و حالت فلاش را تنظیم کنید. کد زیر یک مثال را نشان می دهد:
کاتلین
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
جاوا
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
علاوه بر گزینههای پیکربندی، برخی موارد استفاده APIها را در معرض تغییر پویا تنظیمات پس از ایجاد مورد استفاده قرار میدهند. برای اطلاعات در مورد پیکربندی که مختص موارد استفاده فردی است، به اجرای پیشنمایش ، تجزیه و تحلیل تصاویر ، و ضبط تصویر مراجعه کنید.
CameraXConfig
برای سادگی، CameraX دارای تنظیمات پیشفرض مانند مجریهای داخلی و کنترلکنندههایی است که برای اکثر سناریوهای استفاده مناسب هستند. با این حال، اگر برنامه شما دارای الزامات خاصی است یا ترجیح می دهد آن تنظیمات را سفارشی کند، CameraXConfig
رابطی برای این منظور است.
با CameraXConfig
، یک برنامه می تواند کارهای زیر را انجام دهد:
- تأخیر راه اندازی را با
setAvailableCameraLimiter()
بهینه کنید. - اجرای برنامه را با
setCameraExecutor()
در اختیار CameraX قرار دهید. - کنترل کننده زمانبندی پیش فرض را با
setSchedulerHandler()
جایگزین کنید. - سطح لاگ را با
setMinimumLoggingLevel()
تغییر دهید.
مدل استفاده
روش زیر نحوه استفاده از CameraXConfig
را شرح می دهد:
- یک شی
CameraXConfig
با تنظیمات سفارشی خود ایجاد کنید. - رابط
CameraXConfig.Provider
را درApplication
خود پیاده کنید و شیCameraXConfig
خود را درgetCameraXConfig()
برگردانید. - همانطور که در اینجا توضیح داده شده است، کلاس
Application
خود را به فایلAndroidManifest.xml
خود اضافه کنید.
به عنوان مثال، نمونه کد زیر ثبت CameraX را فقط به پیام های خطا محدود می کند:
کاتلین
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
اگر برنامه شما نیاز به دانستن پیکربندی CameraX پس از تنظیم آن دارد، یک کپی محلی از شی CameraXConfig
نگه دارید.
محدود کننده دوربین
در طول اولین فراخوانی ProcessCameraProvider.getInstance()
، CameraX ویژگی های دوربین های موجود در دستگاه را برمی شمارد و پرس و جو می کند. از آنجایی که CameraX نیاز به برقراری ارتباط با اجزای سخت افزاری دارد، این فرآیند برای هر دوربین، به ویژه در دستگاه های ارزان قیمت، می تواند مدت زمان کمی طول بکشد. اگر برنامه شما فقط از دوربینهای خاصی روی دستگاه استفاده میکند، مانند دوربین جلوی پیشفرض، میتوانید CameraX را طوری تنظیم کنید که دوربینهای دیگر را نادیده بگیرد، که میتواند تأخیر راهاندازی دوربینهایی را که برنامه شما استفاده میکند کاهش دهد.
اگر CameraSelector
به CameraXConfig.Builder.setAvailableCamerasLimiter()
ارسال شود، دوربینی را فیلتر می کند، CameraX طوری رفتار می کند که انگار آن دوربین وجود ندارد. به عنوان مثال، کد زیر برنامه را محدود می کند تا فقط از دوربین پشتی پیش فرض دستگاه استفاده کند:
کاتلین
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
موضوعات
بسیاری از APIهای پلتفرمی که CameraX بر روی آنها ساخته شده است نیاز به مسدود کردن ارتباطات بین پردازشی (IPC) با سخت افزار دارند که گاهی اوقات ممکن است صدها میلی ثانیه طول بکشد تا پاسخ دهند. به همین دلیل، CameraX فقط این APIها را از رشتههای پسزمینه فراخوانی میکند تا رشته اصلی مسدود نشود و UI روان باقی بماند. CameraX به صورت داخلی این رشته های پس زمینه را مدیریت می کند تا این رفتار شفاف به نظر برسد. با این حال، برخی از برنامه ها نیاز به کنترل دقیق موضوعات دارند. CameraXConfig
به یک برنامه اجازه میدهد رشتههای پسزمینه را که از طریق CameraXConfig.Builder.setCameraExecutor()
و CameraXConfig.Builder.setSchedulerHandler()
استفاده میشوند را تنظیم کند.
مجری دوربین
مجری دوربین برای همه تماسهای API داخلی پلتفرم دوربین و همچنین برای تماسهای برگشتی از این APIها استفاده میشود. CameraX یک Executor
داخلی را برای انجام این وظایف اختصاص داده و مدیریت می کند. با این حال، اگر برنامه شما نیاز به کنترل دقیق تری بر موضوعات دارد، از CameraXConfig.Builder.setCameraExecutor()
استفاده کنید.
برنامه ریز
کنترلکننده زمانبندی برای برنامهریزی کارهای داخلی در فواصل زمانی ثابت، مانند باز کردن مجدد دوربین در زمانی که در دسترس نیست، استفاده میشود. این کنترلر کارها را اجرا نمی کند و فقط آنها را به مجری دوربین ارسال می کند. همچنین گاهی اوقات در پلتفرم های API قدیمی که به یک Handler
برای پاسخگویی به تماس نیاز دارند استفاده می شود. در این موارد باز هم تماسهای تماس مستقیماً به مجری دوربین ارسال میشوند. CameraX یک HandlerThread
داخلی را برای انجام این کارها اختصاص داده و مدیریت می کند، اما می توانید با CameraXConfig.Builder.setSchedulerHandler()
آن را لغو کنید.
ورود به سیستم
گزارش CameraX به برنامهها اجازه میدهد پیامهای logcat را فیلتر کنند، زیرا میتواند تمرین خوبی برای جلوگیری از پیامهای پرمخاطب در کد تولید شما باشد. CameraX از چهار سطح گزارش گیری، از پرحرف ترین تا شدیدترین، پشتیبانی می کند:
-
Log.DEBUG
(پیشفرض) -
Log.INFO
-
Log.WARN
-
Log.ERROR
برای توصیف دقیق این سطوح گزارش به مستندات Android Log مراجعه کنید. از CameraXConfig.Builder.setMinimumLoggingLevel(int)
برای تنظیم سطح گزارش مناسب برای برنامه خود استفاده کنید.
انتخاب خودکار
CameraX به طور خودکار عملکردی را ارائه می دهد که مخصوص دستگاهی است که برنامه شما روی آن اجرا می شود. به عنوان مثال، CameraX به طور خودکار بهترین رزولوشن را برای استفاده در صورتی که وضوحی را مشخص نکردهاید، یا اگر وضوحی که مشخص میکنید پشتیبانی نمیشود، تعیین میکند. همه اینها توسط کتابخانه انجام می شود و نیازی به نوشتن کدهای خاص دستگاه را از بین می برد.
هدف CameraX این است که با موفقیت یک جلسه دوربین را راه اندازی کند. این بدان معناست که CameraX بر اساس قابلیت دستگاه، رزولوشن و نسبت ابعاد را به خطر می اندازد. سازش می تواند اتفاق بیفتد زیرا:
- دستگاه از وضوح درخواستی پشتیبانی نمی کند.
- دستگاه دارای مشکلات سازگاری است، مانند دستگاههای قدیمی که برای عملکرد صحیح به وضوحهای خاصی نیاز دارند.
- در برخی از دستگاهها، فرمتهای خاص فقط با نسبتهای تصویری خاص در دسترس هستند.
- این دستگاه برای کدگذاری JPEG یا ویدیو، «نزدیکترین mod16» را ترجیح می دهد. برای اطلاعات بیشتر،
SCALER_STREAM_CONFIGURATION_MAP
ببینید.
اگرچه CameraX جلسه را ایجاد و مدیریت می کند، همیشه اندازه های تصویر برگشتی را در خروجی Use case در کد خود بررسی کنید و بر اساس آن تنظیم کنید.
چرخش
بهطور پیشفرض، چرخش دوربین به گونهای تنظیم میشود که با چرخش نمایشگر پیشفرض در طول ایجاد کیس استفاده مطابقت داشته باشد. در این حالت پیشفرض، CameraX خروجیهایی تولید میکند تا به برنامه اجازه دهد با آنچه انتظار دارید در پیشنمایش ببینید مطابقت داشته باشد. میتوانید چرخش را به یک مقدار سفارشی تغییر دهید تا از دستگاههای چند نمایشگر پشتیبانی کند، با عبور از جهت نمایش فعلی هنگام پیکربندی اشیاء مورد استفاده یا به صورت پویا پس از ایجاد آنها.
برنامه شما می تواند چرخش هدف را با استفاده از تنظیمات پیکربندی تنظیم کند. سپس میتواند تنظیمات چرخش را با استفاده از روشهای استفاده از APIهای مورد استفاده (مانند ImageAnalysis.setTargetRotation()
) بهروزرسانی کند، حتی زمانی که چرخه حیات در حالت در حال اجرا است. هنگامی که برنامه در حالت عمودی قفل است، ممکن است از این استفاده کنید - و بنابراین هیچ پیکربندی مجدد در چرخش رخ نمی دهد - اما مورد استفاده از عکس یا تجزیه و تحلیل باید از چرخش فعلی دستگاه آگاه باشد. برای مثال، آگاهی از چرخش ممکن است لازم باشد تا چهرهها برای تشخیص چهره به درستی جهتگیری شوند، یا عکسها روی افقی یا عمودی تنظیم شوند.
داده های تصاویر گرفته شده ممکن است بدون اطلاعات چرخش ذخیره شوند. دادههای Exif حاوی اطلاعات چرخش هستند تا برنامههای گالری بتوانند تصویر را پس از ذخیره کردن در جهت صحیح نشان دهند.
برای نمایش داده های پیش نمایش با جهت گیری صحیح، می توانید از خروجی ابرداده از Preview.PreviewOutput()
برای ایجاد تبدیل استفاده کنید.
نمونه کد زیر نحوه تنظیم چرخش روی یک رویداد جهتگیری را نشان میدهد:
کاتلین
override fun onCreate() { val imageCapture = ImageCapture.Builder().build() val orientationEventListener = object : OrientationEventListener(this as Context) { override fun onOrientationChanged(orientation : Int) { // Monitors orientation values to determine the target rotation value val rotation : Int = when (orientation) { in 45..134 -> Surface.ROTATION_270 in 135..224 -> Surface.ROTATION_180 in 225..314 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageCapture.targetRotation = rotation } } orientationEventListener.enable() }
جاوا
@Override public void onCreate() { ImageCapture imageCapture = new ImageCapture.Builder().build(); OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) { @Override public void onOrientationChanged(int orientation) { int rotation; // Monitors orientation values to determine the target rotation value if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
بر اساس چرخش تنظیم شده، هر مورد استفاده یا داده های تصویر را مستقیماً می چرخاند یا ابرداده چرخشی را به مصرف کنندگان داده های تصویر چرخانده نشده ارائه می دهد.
- پیش نمایش : خروجی ابرداده به گونه ای ارائه می شود که چرخش وضوح هدف با استفاده از
Preview.getTargetRotation()
مشخص می شود. - ImageAnalysis : خروجی فراداده ارائه می شود تا مختصات بافر تصویر نسبت به مختصات نمایش شناخته شود.
- ImageCapture : فراداده Exif، بافر یا هر دو بافر و ابرداده برای توجه به تنظیمات چرخش تغییر می کنند. مقدار تغییر یافته بستگی به اجرای HAL دارد.
Crop rect
به طور پیش فرض، crop rect بافر کامل rect است. می توانید آن را با ViewPort
و UseCaseGroup
سفارشی کنید. با گروه بندی موارد استفاده و تنظیم دیدگاه ، دوربین فیلمبرداری تضمین می کند که محصولات زراعی کلیه موارد استفاده در گروه به همان منطقه در سنسور دوربین اشاره می کنند.
قطعه کد زیر نحوه استفاده از این دو کلاس را نشان می دهد:
کاتلین
val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build() val useCaseGroup = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build() cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)
جاوا
ViewPort viewPort = new ViewPort.Builder( new Rational(width, height), getDisplay().getRotation()).build(); UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build(); cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
ViewPort
بافر رکت را برای کاربران نهایی مشخص می کند. سپس دوربین فیلمبرداری بر اساس خواص Viewport و موارد استفاده متصل ، بزرگترین رکت محصول ممکن را محاسبه می کند. معمولاً برای دستیابی به اثر WysiWyg ، می توانید ViewPort را بر اساس مورد استفاده از پیش نمایش پیکربندی کنید. یک روش ساده برای به دست آوردن Viewport استفاده از PreviewView
است.
قطعه کد زیر نحوه دریافت شیء ViewPort
را نشان می دهد:
کاتلین
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
جاوا
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
در مثال قبلی ، آنچه برنامه از ImageAnalysis
و ImageCapture
به دست می آید با آنچه کاربر نهایی در PreviewView
می بیند مطابقت دارد ، با فرض اینکه نوع مقیاس PreviewView
روی پیش فرض ، FILL_CENTER
تنظیم شده است. پس از اعمال رکت و چرخش محصول به بافر خروجی ، تصویر از همه موارد استفاده یکسان است ، هر چند احتمالاً با وضوح مختلف. برای اطلاعات بیشتر در مورد نحوه اعمال اطلاعات تحول ، به Output Transform مراجعه کنید.
انتخاب دوربین
Camerax به طور خودکار بهترین دستگاه دوربین را برای نیازهای برنامه شما انتخاب می کند و مواردی را استفاده می کند. اگر مایل به استفاده از دستگاه متفاوتی از دستگاه انتخاب شده برای شما هستید ، چند گزینه وجود دارد:
- دوربین پیش فرض جلوی پیش فرض را با
CameraSelector.DEFAULT_FRONT_CAMERA
درخواست کنید. - دوربین پیش فرض عقب را با
CameraSelector.DEFAULT_BACK_CAMERA
درخواست کنید. - لیست دستگاه های موجود را توسط
CameraCharacteristics
خود باCameraSelector.Builder.addCameraFilter()
فیلتر کنید.
نمونه کد زیر نحوه ایجاد یک CameraSelector
برای تأثیرگذاری بر انتخاب دستگاه نشان می دهد:
کاتلین
fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? { val cam2Infos = provider.availableCameraInfos.map { Camera2CameraInfo.from(it) }.sortedByDescending { // HARDWARE_LEVEL is Int type, with the order of: // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) } return when { cam2Infos.isNotEmpty() -> { CameraSelector.Builder() .addCameraFilter { it.filter { camInfo -> // cam2Infos[0] is either EXTERNAL or best built-in camera val thisCamId = Camera2CameraInfo.from(camInfo).cameraId thisCamId == cam2Infos[0].cameraId } }.build() } else -> null } } // create a CameraSelector for the USB camera (or highest level internal camera) val selector = selectExternalOrBestCamera(processCameraProvider) processCameraProvider.bindToLifecycle(this, selector, preview, analysis)
چندین دوربین را همزمان انتخاب کنید
با شروع کار با فیلمبرداری 1.3 ، می توانید چندین دوربین را همزمان انتخاب کنید. به عنوان مثال ، شما می توانید به یک دوربین جلو و عقب متصل شوید تا به طور همزمان از هر دو منظر عکس بگیرید یا فیلم هایی را ضبط کنید.
هنگام استفاده از ویژگی دوربین همزمان ، این دستگاه می تواند دو دوربین با لنزهای مختلف را به طور همزمان کار کند یا به طور همزمان دو دوربین پشتی کار کند. بلوک کد زیر نحوه تنظیم دو دوربین را هنگام فراخوانی bindToLifecycle
نشان می دهد ، و چگونه می توان هر دو شیء دوربین را از شیء ConcurrentCamera
بازگردانده دریافت کرد.
کاتلین
// Build ConcurrentCameraConfig val primary = ConcurrentCamera.SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ) val secondary = ConcurrentCamera.SingleCameraConfig( secondaryCameraSelector, useCaseGroup, lifecycleOwner ) val concurrentCamera = cameraProvider.bindToLifecycle( listOf(primary, secondary) ) val primaryCamera = concurrentCamera.cameras[0] val secondaryCamera = concurrentCamera.cameras[1]
جاوا
// Build ConcurrentCameraConfig SingleCameraConfig primary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); SingleCameraConfig secondary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); ConcurrentCamera concurrentCamera = mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary)); Camera primaryCamera = concurrentCamera.getCameras().get(0); Camera secondaryCamera = concurrentCamera.getCameras().get(1);
وضوح دوربین
شما می توانید اجازه دهید Camerax وضوح تصویر را بر اساس ترکیبی از قابلیت های دستگاه ، سطح سخت افزار پشتیبانی شده دستگاه ، استفاده از مورد استفاده کند و نسبت ابعاد را ارائه دهد. از طرف دیگر ، می توانید در مواردی که از آن پیکربندی پشتیبانی می کنند ، یک وضوح هدف خاص یا نسبت ابعاد خاص را تعیین کنید.
وضوح خودکار
دوربین فیلمبرداری می تواند به طور خودکار بهترین تنظیمات وضوح را بر اساس موارد استفاده مشخص شده در cameraProcessProvider.bindToLifecycle()
تعیین کند. در هر زمان ممکن ، تمام موارد استفاده مورد نیاز برای اجرای همزمان در یک جلسه واحد را در یک تماس bindToLifecycle()
مشخص کنید. Camerax قطعنامه ها را بر اساس مجموعه موارد استفاده که با در نظر گرفتن سطح سخت افزار پشتیبانی شده دستگاه و با حسابداری از واریانس خاص دستگاه (جایی که یک دستگاه از تنظیمات موجود فراتر رفته یا برآورده نمی کند) تعیین می کند. هدف این است که اجازه دهید برنامه در حالی که مسیرهای کد خاص دستگاه را به حداقل می رساند ، در دستگاه های متنوعی اجرا شود.
نسبت ابعاد پیش فرض برای ضبط تصویر و موارد استفاده از تجزیه و تحلیل تصویر 4: 3 است.
موارد استفاده از نسبت ابعاد قابل تنظیم برای اجازه دادن به برنامه ، نسبت ابعاد مورد نظر را بر اساس طراحی UI مشخص می کند. خروجی Camerax برای مطابقت با نسبت ابعاد درخواست شده به همان اندازه که از دستگاه پشتیبانی می کند ، تولید می شود. اگر وضوح دقیق مسابقه پشتیبانی نشده باشد ، یکی از مواردی که بیشترین شرایط را برآورده می کند انتخاب شده است. بنابراین ، برنامه نحوه نمایش دوربین در برنامه را بیان می کند و Camerax بهترین تنظیمات وضوح دوربین را برای برآورده کردن آن در دستگاه های مختلف تعیین می کند.
به عنوان مثال ، یک برنامه می تواند هر یک از موارد زیر را انجام دهد:
- وضوح هدف 4: 3 یا 16: 9 را برای یک مورد استفاده مشخص کنید
- وضوح سفارشی را مشخص کنید ، که Camerax سعی در یافتن نزدیکترین مسابقه دارد
- نسبت ابعاد محصول را برای
ImageCapture
مشخص کنید
Camerax قطعنامه های داخلی Camera2 را بطور خودکار انتخاب می کند. جدول زیر قطعنامه ها را نشان می دهد:
مورد استفاده | وضوح سطح داخلی | وضوح داده خروجی |
---|---|---|
پیش نمایش | نسبت ابعاد: وضوح مناسب برای هدف. | وضوح سطح داخلی. ابرداده ارائه شده است تا بتواند از نظر نسبت ابعاد هدف محصول ، مقیاس و چرخش را بچرخاند. |
وضوح پیش فرض: بالاترین وضوح پیش نمایش ، یا بالاترین وضوح دستگاه ترجیح داده شده که با نسبت ابعاد پیش نمایش مطابقت دارد. | ||
حداکثر وضوح: اندازه پیش نمایش ، که به بهترین اندازه مطابقت با وضوح صفحه دستگاه یا 1080p (1920x1080) اشاره دارد ، هر کدام کوچکتر باشد. | ||
تجزیه و تحلیل تصویر | نسبت ابعاد: وضوح مناسب برای هدف. | وضوح سطح داخلی. |
وضوح پیش فرض: تنظیم پیش فرض وضوح هدف 640x480 است. تنظیم هر دو وضوح هدف و نسبت ابعاد مربوطه منجر به وضوح بهترین پشتیبانی می شود. | ||
وضوح حداکثر: حداکثر وضوح خروجی دستگاه دوربین از فرمت YUV_420_888 که از StreamConfigurationMap.getOutputSizes() بازیابی می شود. وضوح هدف به طور پیش فرض به صورت 640x480 تعیین شده است ، بنابراین اگر می خواهید وضوح بزرگتر از 640x480 داشته باشید ، باید از setTargetResolution() و setTargetAspectRatio() استفاده کنید تا از وضوح پشتیبانی شده نزدیکترین آن را بدست آورید. | ||
ضبط تصویر | نسبت ابعاد: نسبت ابعاد که به بهترین وجه در تنظیمات قرار دارد. | وضوح سطح داخلی. |
وضوح پیش فرض: بالاترین وضوح موجود ، یا بالاترین وضوح دستگاهی که با نسبت ابعاد ImageCapture مطابقت دارد. | ||
وضوح حداکثر: حداکثر وضوح خروجی دستگاه دوربین در قالب JPEG. برای بازیابی این کار StreamConfigurationMap.getOutputSizes() استفاده کنید. |
قطعنامه را مشخص کنید
همانطور که در نمونه کد زیر نشان داده شده است ، می توانید هنگام استفاده از موارد استفاده از موارد استفاده از موارد استفاده از موارد استفاده را با استفاده از روش setTargetResolution(Size resolution)
تنظیم کنید:
کاتلین
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
جاوا
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
شما نمی توانید هر دو نسبت ابعاد هدف و وضوح هدف را در همان مورد استفاده تنظیم کنید. انجام این کار هنگام ساختن شی پیکربندی ، یک IllegalArgumentException
به همراه می آورد.
Size
وضوح را در قاب مختصات پس از چرخاندن اندازه های پشتیبانی شده توسط چرخش هدف بیان کنید. به عنوان مثال ، دستگاهی با جهت گیری طبیعی پرتره در چرخش هدف طبیعی که درخواست یک تصویر پرتره می کند می تواند 480x640 را مشخص کند ، و همان دستگاه ، 90 درجه چرخانده شده و هدف قرار دادن جهت گیری چشم انداز می تواند 640x480 را مشخص کند.
وضوح هدف سعی در تعیین حداقل وضوح تصویر دارد. وضوح تصویر واقعی نزدیکترین وضوح موجود در اندازه است که از وضوح هدف کوچکتر نیست ، همانطور که توسط اجرای دوربین تعیین می شود.
با این حال ، اگر هیچ وضوح وجود نداشته باشد که برابر یا بزرگتر از وضوح هدف باشد ، نزدیکترین وضوح موجود کوچکتر از وضوح هدف انتخاب شده است. قطعنامه هایی با نسبت ابعاد یکسان از Size
ارائه شده از اولویت بالاتری نسبت به وضوح نسبت ابعاد مختلف استفاده می شود.
Camerax بهترین وضوح مناسب را بر اساس درخواست ها اعمال می کند. اگر نیاز اصلی برآورده کردن نسبت ابعاد است ، فقط setTargetAspectRatio
مشخص کنید و Camerax یک وضوح خاص را بر اساس دستگاه تعیین می کند. اگر نیاز اصلی برنامه مشخص کردن وضوح به منظور کارآمدتر کردن پردازش تصویر (به عنوان مثال یک تصویر کوچک یا متوسط بر اساس قابلیت پردازش دستگاه) است ، از setTargetResolution(Size resolution)
استفاده کنید.
اگر برنامه شما به وضوح دقیق نیاز دارد ، به جدول موجود در createCaptureSession()
مراجعه کنید تا مشخص شود که حداکثر وضوح توسط هر سطح سخت افزاری پشتیبانی می شود. برای بررسی وضوح خاص پشتیبانی شده توسط دستگاه فعلی ، به StreamConfigurationMap.getOutputSizes(int)
مراجعه کنید.
اگر برنامه شما در Android 10 یا بالاتر اجرا شده است ، می توانید از isSessionConfigurationSupported()
برای تأیید یک SessionConfiguration
خاص استفاده کنید.
خروجی دوربین را کنترل کنید
علاوه بر این که به شما اجازه می دهد خروجی دوربین را به عنوان مورد نیاز برای هر مورد استفاده فردی پیکربندی کنید ، Camerax همچنین رابط های زیر را برای پشتیبانی از عملیات دوربین مشترک برای همه موارد استفاده محدود پیاده سازی می کند:
-
CameraControl
به شما امکان می دهد ویژگی های دوربین مشترک را پیکربندی کنید. -
CameraInfo
به شما امکان می دهد از حالت های دوربین مشترک استفاده کنید.
این ویژگی های دوربین پشتیبانی شده با Cameracontrol است:
- بزرگنمایی ضربه بزنید؛
- مشعل
- تمرکز و اندازه گیری (ضربه زدن به فوکوس)
- جبران نوردهی
مواردی از دوربین و camerainfo دریافت کنید
با استفاده از شیء Camera
که توسط ProcessCameraProvider.bindToLifecycle()
بازیابی شده است ، مواردی از CameraControl
و CameraInfo
را بازیابی کنید. کد زیر مثالی را نشان می دهد:
کاتلین
val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. val cameraControl = camera.cameraControl // For querying information and states. val cameraInfo = camera.cameraInfo
جاوا
Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. CameraControl cameraControl = camera.getCameraControl() // For querying information and states. CameraInfo cameraInfo = camera.getCameraInfo()
به عنوان مثال ، شما می توانید پس از فراخوانی bindToLifecycle()
عملیات ZOOM و سایر CameraControl
را ارسال کنید. پس از متوقف کردن یا از بین بردن فعالیت مورد استفاده برای اتصال به نمونه دوربین ، CameraControl
دیگر نمی تواند عملیات را انجام دهد و یک FASEBLEATURE ListenableFuture
را بازگرداند.
بزرگنمایی ضربه بزنید؛
Cameracontrol دو روش برای تغییر سطح بزرگنمایی ارائه می دهد:
setZoomRatio()
بزرگنمایی را با نسبت بزرگنمایی تنظیم می کند.این نسبت باید در محدوده camerainfo.getzoomstate
CameraInfo.getZoomState().getValue().getMaxZoomRatio()
CameraInfo.getZoomState().getValue().getMinZoomRatio()
باشد. در غیر این صورت ، عملکرد یکListenableFuture
ناموفق را برمی گرداند.setLinearZoom()
بزرگنمایی فعلی را با مقدار بزرگنمایی خطی از 0 تا 1.0 تنظیم می کند.مزیت زوم خطی این است که با تغییر در زوم ، مقیاس میدان دید (FOV) را ایجاد می کند. این باعث می شود با نمای
Slider
ایده آل باشد.
CameraInfo.getZoomState()
یک زندگی از حالت بزرگنمایی فعلی را برمی گرداند. مقدار هنگام شروع دوربین تغییر می کند یا اگر سطح بزرگنمایی با استفاده از setZoomRatio()
یا setLinearZoom()
تنظیم شود. تماس با هر روش مقادیر پشتیبان ZoomState.getZoomRatio()
و ZoomState.getLinearZoom()
را تنظیم می کند. اگر می خواهید متن نسبت زوم را در کنار یک کشویی نمایش دهید ، این مفید است. به سادگی ZoomState
LiveData
مشاهده کنید تا هر دو را بدون نیاز به انجام تبدیل به روز کنید.
ListenableFuture
که توسط هر دو API بازگردانده شده است ، گزینه ای را برای برنامه های کاربردی ارائه می دهد که هنگام تکمیل درخواست تکرار شده با مقدار زوم مشخص شده ، به آنها اطلاع داده شود. علاوه بر این ، اگر مقدار بزرگنمایی جدیدی را تعیین کنید در حالی که عملیات قبلی هنوز در حال اجرا است ، ListenableFuture
عملیات زوم قبلی بلافاصله شکست می خورد.
مشعل
CameraControl.enableTorch(boolean)
مشعل را فعال یا غیرفعال می کند (همچنین به عنوان چراغ قوه نیز شناخته می شود).
CameraInfo.getTorchState()
می تواند برای پرس و جو از وضعیت مشعل فعلی استفاده شود. برای تعیین اینکه آیا مشعل در دسترس است ، می توانید مقدار برگشتی توسط CameraInfo.hasFlashUnit()
را بررسی کنید. اگر اینگونه نباشد ، فراخوانی ListenableFuture
CameraControl.enableTorch(boolean)
باعث می شود که بلافاصله با یک نتیجه ناموفق به پایان برسد و وضعیت مشعل را به TorchState.OFF
برساند.
هنگامی که مشعل فعال می شود ، بدون در نظر گرفتن تنظیمات FlashMode ، در حین ضبط عکس و فیلم ادامه می یابد. flashMode
در ImageCapture
فقط در هنگام غیرفعال کردن مشعل کار می کند.
تمرکز و اندازه گیری
CameraControl.startFocusAndMetering()
با تنظیم مناطق اندازه گیری AF/AE/AWB بر اساس تمرکز تعیین شده ، باعث فوکوس خودکار و اندازه گیری قرار می گیرد. این اغلب برای اجرای ویژگی "شیر به تمرکز" در بسیاری از برنامه های دوربین استفاده می شود.
نقطه اندازه گیری
برای شروع ، با استفاده از MeteringPointFactory.createPoint(float x, float y, float size)
یک MeteringPoint
ایجاد کنید. یک MeteringPoint
یک نقطه واحد را روی Surface
دوربین نشان می دهد. آن را به صورت عادی ذخیره می کند تا بتواند به راحتی به مختصات سنسور برای مشخص کردن مناطق AF/AE/AWB تبدیل شود.
اندازه MeteringPoint
از 0 تا 1 متغیر است ، با اندازه پیش فرض 0.15f. هنگام فراخوانی MeteringPointFactory.createPoint(float x, float y, float size)
، camerax یک منطقه مستطیل را با محوریت (x, y)
برای size
ارائه شده ایجاد می کند.
کد زیر نحوه ایجاد یک MeteringPoint
را نشان می دهد:
کاتلین
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview. previewView.setOnTouchListener((view, motionEvent) -> { val meteringPoint = previewView.meteringPointFactory .createPoint(motionEvent.x, motionEvent.y) … } // Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for // preview. Please note that if the preview is scaled or cropped in the View, // it’s the application's responsibility to transform the coordinates properly // so that the width and height of this factory represents the full Preview FOV. // And the (x,y) passed to create MeteringPoint might need to be adjusted with // the offsets. val meteringPointFactory = DisplayOrientedMeteringPointFactory( surfaceView.display, camera.cameraInfo, surfaceView.width, surfaceView.height ) // Use SurfaceOrientedMeteringPointFactory if the point is specified in // ImageAnalysis ImageProxy. val meteringPointFactory = SurfaceOrientedMeteringPointFactory( imageWidth, imageHeight, imageAnalysis)
startFocusAndMetering و FocusmeteringAction
برای فراخوانی startFocusAndMetering()
، برنامه ها باید یک FocusMeteringAction
بسازند ، که شامل یک یا چند MeteringPoints
با ترکیب حالت اندازه گیری اختیاری از FLAG_AF
، FLAG_AE
، FLAG_AWB
است. کد زیر این استفاده را نشان می دهد:
کاتلین
val meteringPoint1 = meteringPointFactory.createPoint(x1, x1) val meteringPoint2 = meteringPointFactory.createPoint(x2, y2) val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB // Optionally add meteringPoint2 for AF/AE. .addPoint(meteringPoint2, FLAG_AF | FLAG_AE) // The action is canceled in 3 seconds (if not set, default is 5s). .setAutoCancelDuration(3, TimeUnit.SECONDS) .build() val result = cameraControl.startFocusAndMetering(action) // Adds listener to the ListenableFuture if you need to know the focusMetering result. result.addListener({ // result.get().isFocusSuccessful returns if the auto focus is successful or not. }, ContextCompat.getMainExecutor(this)
همانطور که در کد قبلی نشان داده شده است ، startFocusAndMetering()
یک FocusMeteringAction
متشکل از یک MeteringPoint
برای مناطق اندازه گیری AF/AE/AWB و یک نقطه اندازه گیری دیگر فقط برای AF و AE می گیرد.
در داخل ، Camerax آن را به Camera2 MeteringRectangles
تبدیل می کند و CONTROL_AF_REGIONS
/ CONTROL_AE_REGIONS
/ CONTROL_AWB_REGIONS
را به درخواست ضبط تنظیم می کند.
از آنجا که همه دستگاه ها از AF/AE/AWB و مناطق مختلف پشتیبانی نمی کنند ، Camerax با بهترین تلاش ، FocusMeteringAction
انجام می دهد. دوربین فیلمبرداری از حداکثر تعداد اندازه گیری های پشتیبانی شده استفاده می کند ، به این ترتیب که امتیاز اضافه می شود. تمام نقاط اندازه گیری اضافه شده پس از حداکثر تعداد نادیده گرفته می شوند. به عنوان مثال ، اگر یک FocusMeteringAction
با 3 MeteringPoints در یک سکو که فقط 2 را پشتیبانی می کند ، تهیه می شود ، فقط از 2 Meteringpoints اول استفاده می شود. MeteringPoint
نهایی توسط Camerax نادیده گرفته می شود.
جبران نوردهی
جبران قرار گرفتن در معرض هنگامی مفید است که برنامه ها نیاز به تنظیم دقیق مقادیر قرار گرفتن در معرض (EV) فراتر از نتیجه خروجی قرار گرفتن در معرض خودکار (AE) داشته باشند. مقادیر جبران خسارت قرار گرفتن در معرض به روش زیر برای تعیین قرار گرفتن در معرض لازم برای شرایط تصویر فعلی ترکیب می شوند:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
Camerax برای تنظیم جبران خسارت قرار گرفتن در معرض به عنوان یک مقدار شاخص ، عملکرد Camera.CameraControl.setExposureCompensationIndex()
را فراهم می کند.
مقادیر شاخص مثبت تصویر را روشن تر می کند ، در حالی که مقادیر منفی تصویر را کم می کنند. برنامه ها می توانند از دامنه پشتیبانی شده توسط CameraInfo.ExposureState.exposureCompensationRange()
شرح داده شده در بخش بعدی پرس و جو کنند. اگر مقدار پشتیبانی شود ، هنگامی که مقدار با موفقیت در درخواست ضبط فعال شود ، ListenableFuture
شده است. اگر شاخص مشخص شده از محدوده پشتیبانی شده خارج باشد ، setExposureCompensationIndex()
باعث می شود که ListenableFuture
برگشتی بلافاصله با نتیجه ناموفق تکمیل شود.
Camerax تنها آخرین درخواست setExposureCompensationIndex()
را نگه می دارد و قبل از اجرای درخواست قبلی ، چندین بار این عملکرد را فراخوانی می کند.
قطعه زیر شاخص جبران خسارت قرار گرفتن در معرض را تعیین می کند و در هنگام اجرای درخواست تغییر قرار گرفتن در معرض ، پاسخ به تماس را ثبت می کند:
کاتلین
camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex) .addListener({ // Get the current exposure compensation index, it might be // different from the asked value in case this request was // canceled by a newer setting request. val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex … }, mainExecutor)
Camera.CameraInfo.getExposureState()
ExposureState
فعلی را بازیابی می کند:- حمایت از کنترل جبران خسارت در معرض.
- شاخص جبران خسارت فعلی.
- دامنه شاخص جبران خسارت قرار گرفتن در معرض.
- مرحله جبران قرار گرفتن در معرض مورد استفاده در محاسبه مقدار جبران قرار گرفتن در معرض.
به عنوان مثال ، کد زیر تنظیمات مربوط به SeekBar
در معرض را با مقادیر فعلی ExposureState
آغاز می کند:
کاتلین
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
منابع اضافی
برای کسب اطلاعات بیشتر در مورد Camerax ، با منابع اضافی زیر مشورت کنید.
Codelab
نمونه کد
جامعه توسعه دهندگان
گروه بحث و گفتگوی فیلمبرداری اندرویدی
،شما هر مورد استفاده از دوربین فیلمبرداری را برای کنترل جنبه های مختلف عملیات مورد استفاده پیکربندی می کنید.
به عنوان مثال ، با استفاده از مورد استفاده از ضبط تصویر ، می توانید نسبت ابعاد هدف و یک حالت فلش را تنظیم کنید. کد زیر یک مثال را نشان می دهد:
کاتلین
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
جاوا
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
علاوه بر گزینه های پیکربندی ، برخی از موارد استفاده API را در معرض تغییر پویا تنظیمات پس از ایجاد مورد استفاده قرار می دهند. برای کسب اطلاعات در مورد پیکربندی که مخصوص موارد استفاده فردی است ، به اجرای پیش نمایش ، تجزیه و تحلیل تصاویر و ضبط تصویر مراجعه کنید.
دوربین فیلمبرداری
برای سادگی ، Camerax دارای پیکربندی های پیش فرض مانند مجریان داخلی و دستگیرندگان مناسب برای اکثر سناریوهای استفاده است. با این حال ، اگر برنامه شما نیازهای ویژه ای دارد یا ترجیح می دهد آن تنظیمات را سفارشی کند ، CameraXConfig
رابط برای این منظور است.
با استفاده از CameraXConfig
، یک برنامه می تواند موارد زیر را انجام دهد:
- تأخیر راه اندازی را با
setAvailableCameraLimiter()
بهینه کنید. - مجری برنامه را با
setCameraExecutor()
به Camerax ارائه دهید. - کنترل کننده برنامه ریزی پیش فرض را با
setSchedulerHandler()
جایگزین کنید. - سطح ورود به سیستم را با
setMinimumLoggingLevel()
تغییر دهید.
مدل استفاده
روش زیر نحوه استفاده از CameraXConfig
را شرح می دهد:
- با تنظیمات سفارشی خود یک شیء
CameraXConfig
ایجاد کنید. - رابط
CameraXConfig.Provider
را درApplication
خود پیاده سازی کنید و شیءCameraXConfig
خود را درgetCameraXConfig()
برگردانید. - همانطور که در اینجا توضیح داده شده است ، کلاس
Application
خود را به پروندهAndroidManifest.xml
خود اضافه کنید.
به عنوان مثال ، نمونه کد زیر ورود دوربین فیلمبرداری را فقط به پیام های خطا محدود می کند:
کاتلین
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
اگر برنامه شما نیاز به دانستن پیکربندی Camerax پس از تنظیم آن دارد ، یک نسخه محلی از شی CameraXConfig
را نگه دارید.
محدود کننده دوربین
در اولین فراخوانی از ProcessCameraProvider.getInstance()
، فیلمبرداری و ویژگی های نمایش داده های دوربین های موجود در دستگاه را ذکر می کند. از آنجا که دوربین فیلمبرداری نیاز به برقراری ارتباط با اجزای سخت افزاری دارد ، این فرایند می تواند برای هر دوربین ، به ویژه در دستگاه های کم مصرف ، زمان غیرعادی را به خود اختصاص دهد. اگر برنامه شما فقط از دوربین های خاص در دستگاه استفاده می کند ، مانند دوربین جلو پیش فرض ، می توانید دوربین فیلمبرداری را برای نادیده گرفتن سایر دوربین ها تنظیم کنید ، که می تواند تأخیر راه اندازی را برای دوربین هایی که از برنامه شما استفاده می کند ، کاهش دهد.
اگر CameraSelector
به CameraXConfig.Builder.setAvailableCamerasLimiter()
یک دوربین را منتقل کند ، دوربین فیلمبرداری طوری رفتار می کند که گویی این دوربین وجود ندارد. به عنوان مثال ، کد زیر برنامه را فقط از دوربین پشتی پیش فرض دستگاه استفاده می کند:
کاتلین
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
موضوعات
بسیاری از API های سکو که در آن فیلمبرداری ساخته شده است ، نیاز به مسدود کردن ارتباطات بین پردازش (IPC) با سخت افزار دارند که بعضی اوقات می تواند صدها میلی ثانیه را برای پاسخگویی به وجود آورد. به همین دلیل ، دوربین فیلمبرداری فقط این API ها را از موضوعات پس زمینه فراخوانی می کند ، به طوری که موضوع اصلی مسدود نشده و UI روان باقی می ماند. Camerax داخلی این موضوعات پس زمینه را به گونه ای مدیریت می کند تا این رفتار شفاف به نظر برسد. با این حال ، برخی از برنامه ها نیاز به کنترل دقیق موضوعات دارند. CameraXConfig
به یک برنامه اجازه می دهد تا موضوعات پس زمینه ای را که از طریق CameraXConfig.Builder.setCameraExecutor()
و CameraXConfig.Builder.setSchedulerHandler()
استفاده می کنند ، تنظیم کند.
مجری دوربین
از مجری دوربین برای کلیه تماس های API سیستم عامل داخلی و همچنین برای تماس با این API استفاده می شود. دوربین فیلمبرداری یک Executor
داخلی را برای انجام این کارها اختصاص داده و مدیریت می کند. با این حال ، اگر برنامه شما نیاز به کنترل دقیق تر موضوعات دارد ، از CameraXConfig.Builder.setCameraExecutor()
استفاده کنید.
کنترل کننده برنامه ریز
از کنترل کننده Scheduler برای برنامه ریزی کارهای داخلی در فواصل ثابت استفاده می شود ، مانند تلاش مجدد باز کردن دوربین در صورت عدم دسترسی. این کنترل کننده مشاغل را اجرا نمی کند و فقط آنها را به مجری دوربین اعزام می کند. همچنین گاهی اوقات در سیستم عامل های API Legacy استفاده می شود که برای تماس تلفنی به یک Handler
نیاز دارند. در این موارد ، تماس های برگشتی هنوز مستقیماً به مجری دوربین اعزام می شوند. Camerax برای انجام این کارها یک HandlerThread
داخلی را اختصاص داده و مدیریت می کند ، اما می توانید آن را با CameraXConfig.Builder.setSchedulerHandler()
بیش از حد واگذار کنید.
ورود به سیستم
ورود به سیستم Camerax به برنامه ها اجازه می دهد تا پیام های LogCat را فیلتر کند ، زیرا این امر می تواند برای جلوگیری از پیام های کلامی در کد تولید شما عمل خوبی باشد. دوربین فیلمبرداری از چهار سطح ورود به سیستم ، از لفظ ترین تا شدیدترین آنها پشتیبانی می کند:
-
Log.DEBUG
(پیش فرض) -
Log.INFO
-
Log.WARN
-
Log.ERROR
برای توضیحات دقیق این سطح ورود به سیستم به اسناد ورود به سیستم Android مراجعه کنید. برای تعیین سطح ورود به سیستم مناسب برای برنامه خود ، از CameraXConfig.Builder.setMinimumLoggingLevel(int)
استفاده کنید.
انتخاب خودکار
Camerax به طور خودکار عملکردی را ارائه می دهد که مخصوص دستگاهی است که برنامه شما در حال اجرا است. به عنوان مثال ، Camerax به طور خودکار بهترین وضوح را برای استفاده در صورت مشخص کردن وضوح تعیین می کند ، یا اگر وضوح مشخصی که مشخص می کنید پشتیبانی نشده است. همه اینها توسط کتابخانه اداره می شود و نیاز شما برای نوشتن کد خاص دستگاه را از بین می برد.
هدف فیلمبرداری این است که با موفقیت در یک جلسه دوربین آغاز شود. این بدان معنی است که دوربین فیلمبرداری بر اساس وضوح و نسبت ابعاد بر اساس قابلیت دستگاه سازش می کند. سازش می تواند اتفاق بیفتد زیرا:
- دستگاه از وضوح درخواست شده پشتیبانی نمی کند.
- این دستگاه دارای مشکلات سازگاری است ، مانند دستگاه های میراث که برای عملکرد صحیح به وضوح خاصی نیاز دارند.
- در برخی از دستگاه ها ، قالب های خاصی فقط در نسبت های خاص در دسترس هستند.
- این دستگاه ترجیح می دهد "نزدیکترین MOD16" برای رمزگذاری JPEG یا ویدیویی باشد. برای اطلاعات بیشتر ، به
SCALER_STREAM_CONFIGURATION_MAP
مراجعه کنید.
اگرچه Camerax جلسه را ایجاد و مدیریت می کند ، همیشه اندازه تصویر برگشتی را در خروجی مورد استفاده در کد خود بررسی کرده و مطابق آن تنظیم کنید.
چرخش
به طور پیش فرض ، چرخش دوربین تنظیم شده است تا هنگام ایجاد مورد استفاده ، چرخش صفحه نمایش پیش فرض را مطابقت دهد. در این مورد پیش فرض ، Camerax خروجی ها را تولید می کند تا برنامه با آنچه انتظار دارید در پیش نمایش مشاهده کنید مطابقت داشته باشد. شما می توانید چرخش را به یک مقدار سفارشی تغییر دهید تا با عبور در جهت گیری فعلی نمایشگر هنگام پیکربندی اشیاء مورد استفاده یا پویا پس از ایجاد ، از دستگاه های چند صفحه نمایش پشتیبانی کنید.
برنامه شما می تواند چرخش هدف را با استفاده از تنظیمات پیکربندی تنظیم کند. سپس می تواند تنظیمات چرخش را با استفاده از روش های API های مورد استفاده (مانند ImageAnalysis.setTargetRotation()
) به روز کند ، حتی اگر چرخه حیات در حالت در حال اجرا باشد. شما ممکن است از این استفاده کنید که برنامه در حالت پرتره قفل شود - و بنابراین هیچ پیکربندی در چرخش رخ نمی دهد - اما مورد استفاده از عکس یا تجزیه و تحلیل باید از چرخش فعلی دستگاه آگاه باشد. به عنوان مثال ، ممکن است آگاهی از چرخش مورد نیاز باشد تا چهره ها به درستی برای تشخیص چهره جهت یابی شوند ، یا عکس ها به چشم انداز یا پرتره تنظیم شوند.
داده های مربوط به تصاویر ضبط شده ممکن است بدون اطلاعات چرخش ذخیره شود. داده های EXIF حاوی اطلاعات چرخش است تا برنامه های گالری بتوانند پس از صرفه جویی ، تصویر را در جهت گیری صحیح نشان دهند.
برای نمایش داده های پیش نمایش با جهت گیری صحیح ، می توانید از خروجی ابرداده از Preview.PreviewOutput()
برای ایجاد تبدیل استفاده کنید.
نمونه کد زیر نحوه تنظیم چرخش در یک رویداد جهت گیری را نشان می دهد:
کاتلین
override fun onCreate() { val imageCapture = ImageCapture.Builder().build() val orientationEventListener = object : OrientationEventListener(this as Context) { override fun onOrientationChanged(orientation : Int) { // Monitors orientation values to determine the target rotation value val rotation : Int = when (orientation) { in 45..134 -> Surface.ROTATION_270 in 135..224 -> Surface.ROTATION_180 in 225..314 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageCapture.targetRotation = rotation } } orientationEventListener.enable() }
جاوا
@Override public void onCreate() { ImageCapture imageCapture = new ImageCapture.Builder().build(); OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) { @Override public void onOrientationChanged(int orientation) { int rotation; // Monitors orientation values to determine the target rotation value if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
بر اساس چرخش تنظیم ، هر مورد استفاده یا داده های تصویر را مستقیماً می چرخاند یا ابرداده چرخش را برای مصرف کنندگان داده های تصویر غیر پیچیده فراهم می کند.
- پیش نمایش : خروجی ابرداده به گونه ای ارائه شده است که چرخش وضوح هدف با استفاده از
Preview.getTargetRotation()
شناخته شده است. - ImageAnalysis : خروجی ابرداده به گونه ای ارائه شده است که مختصات بافر تصویر نسبت به مختصات نمایش شناخته شده باشد.
- ImageCapture : ابرداده Exif ، بافر ، یا بافر و ابرداده برای توجه به تنظیم چرخش تغییر یافته است. مقدار تغییر یافته به اجرای HAL بستگی دارد.
خرد کردن
به طور پیش فرض ، Crop Rect رکت بافر کامل است. می توانید آن را با ViewPort
و UseCaseGroup
سفارشی کنید. با گروه بندی موارد استفاده و تنظیم دیدگاه ، دوربین فیلمبرداری تضمین می کند که محصولات زراعی کلیه موارد استفاده در گروه به همان منطقه در سنسور دوربین اشاره می کنند.
قطعه کد زیر نحوه استفاده از این دو کلاس را نشان می دهد:
کاتلین
val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build() val useCaseGroup = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build() cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)
جاوا
ViewPort viewPort = new ViewPort.Builder( new Rational(width, height), getDisplay().getRotation()).build(); UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build(); cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
ViewPort
بافر رکت را برای کاربران نهایی مشخص می کند. سپس دوربین فیلمبرداری بر اساس خواص Viewport و موارد استفاده متصل ، بزرگترین رکت محصول ممکن را محاسبه می کند. معمولاً برای دستیابی به اثر WysiWyg ، می توانید ViewPort را بر اساس مورد استفاده از پیش نمایش پیکربندی کنید. یک روش ساده برای به دست آوردن Viewport استفاده از PreviewView
است.
قطعه کد زیر نحوه دریافت شیء ViewPort
را نشان می دهد:
کاتلین
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
جاوا
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
در مثال قبلی ، آنچه برنامه از ImageAnalysis
و ImageCapture
به دست می آید با آنچه کاربر نهایی در PreviewView
می بیند مطابقت دارد ، با فرض اینکه نوع مقیاس PreviewView
روی پیش فرض ، FILL_CENTER
تنظیم شده است. پس از اعمال رکت و چرخش محصول به بافر خروجی ، تصویر از همه موارد استفاده یکسان است ، هر چند احتمالاً با وضوح مختلف. برای اطلاعات بیشتر در مورد نحوه اعمال اطلاعات تحول ، به Output Transform مراجعه کنید.
انتخاب دوربین
Camerax به طور خودکار بهترین دستگاه دوربین را برای نیازهای برنامه شما انتخاب می کند و مواردی را استفاده می کند. اگر مایل به استفاده از دستگاه متفاوتی از دستگاه انتخاب شده برای شما هستید ، چند گزینه وجود دارد:
- دوربین پیش فرض جلوی پیش فرض را با
CameraSelector.DEFAULT_FRONT_CAMERA
درخواست کنید. - دوربین پیش فرض عقب را با
CameraSelector.DEFAULT_BACK_CAMERA
درخواست کنید. - لیست دستگاه های موجود را توسط
CameraCharacteristics
خود باCameraSelector.Builder.addCameraFilter()
فیلتر کنید.
نمونه کد زیر نحوه ایجاد یک CameraSelector
برای تأثیرگذاری بر انتخاب دستگاه نشان می دهد:
کاتلین
fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? { val cam2Infos = provider.availableCameraInfos.map { Camera2CameraInfo.from(it) }.sortedByDescending { // HARDWARE_LEVEL is Int type, with the order of: // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) } return when { cam2Infos.isNotEmpty() -> { CameraSelector.Builder() .addCameraFilter { it.filter { camInfo -> // cam2Infos[0] is either EXTERNAL or best built-in camera val thisCamId = Camera2CameraInfo.from(camInfo).cameraId thisCamId == cam2Infos[0].cameraId } }.build() } else -> null } } // create a CameraSelector for the USB camera (or highest level internal camera) val selector = selectExternalOrBestCamera(processCameraProvider) processCameraProvider.bindToLifecycle(this, selector, preview, analysis)
چندین دوربین را همزمان انتخاب کنید
با شروع کار با فیلمبرداری 1.3 ، می توانید چندین دوربین را همزمان انتخاب کنید. به عنوان مثال ، شما می توانید به یک دوربین جلو و عقب متصل شوید تا به طور همزمان از هر دو منظر عکس بگیرید یا فیلم هایی را ضبط کنید.
هنگام استفاده از ویژگی دوربین همزمان ، این دستگاه می تواند دو دوربین با لنزهای مختلف را به طور همزمان کار کند یا به طور همزمان دو دوربین پشتی کار کند. بلوک کد زیر نحوه تنظیم دو دوربین را هنگام فراخوانی bindToLifecycle
نشان می دهد ، و چگونه می توان هر دو شیء دوربین را از شیء ConcurrentCamera
بازگردانده دریافت کرد.
کاتلین
// Build ConcurrentCameraConfig val primary = ConcurrentCamera.SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ) val secondary = ConcurrentCamera.SingleCameraConfig( secondaryCameraSelector, useCaseGroup, lifecycleOwner ) val concurrentCamera = cameraProvider.bindToLifecycle( listOf(primary, secondary) ) val primaryCamera = concurrentCamera.cameras[0] val secondaryCamera = concurrentCamera.cameras[1]
جاوا
// Build ConcurrentCameraConfig SingleCameraConfig primary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); SingleCameraConfig secondary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); ConcurrentCamera concurrentCamera = mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary)); Camera primaryCamera = concurrentCamera.getCameras().get(0); Camera secondaryCamera = concurrentCamera.getCameras().get(1);
وضوح دوربین
شما می توانید اجازه دهید Camerax وضوح تصویر را بر اساس ترکیبی از قابلیت های دستگاه ، سطح سخت افزار پشتیبانی شده دستگاه ، استفاده از مورد استفاده کند و نسبت ابعاد را ارائه دهد. از طرف دیگر ، می توانید در مواردی که از آن پیکربندی پشتیبانی می کنند ، یک وضوح هدف خاص یا نسبت ابعاد خاص را تعیین کنید.
وضوح خودکار
دوربین فیلمبرداری می تواند به طور خودکار بهترین تنظیمات وضوح را بر اساس موارد استفاده مشخص شده در cameraProcessProvider.bindToLifecycle()
تعیین کند. در هر زمان ممکن ، تمام موارد استفاده مورد نیاز برای اجرای همزمان در یک جلسه واحد را در یک تماس bindToLifecycle()
مشخص کنید. Camerax قطعنامه ها را بر اساس مجموعه موارد استفاده که با در نظر گرفتن سطح سخت افزار پشتیبانی شده دستگاه و با حسابداری از واریانس خاص دستگاه (جایی که یک دستگاه از تنظیمات موجود فراتر رفته یا برآورده نمی کند) تعیین می کند. هدف این است که اجازه دهید برنامه در حالی که مسیرهای کد خاص دستگاه را به حداقل می رساند ، در دستگاه های متنوعی اجرا شود.
نسبت ابعاد پیش فرض برای ضبط تصویر و موارد استفاده از تجزیه و تحلیل تصویر 4: 3 است.
موارد استفاده از نسبت ابعاد قابل تنظیم برای اجازه دادن به برنامه ، نسبت ابعاد مورد نظر را بر اساس طراحی UI مشخص می کند. خروجی Camerax برای مطابقت با نسبت ابعاد درخواست شده به همان اندازه که از دستگاه پشتیبانی می کند ، تولید می شود. اگر وضوح دقیق مسابقه پشتیبانی نشده باشد ، یکی از مواردی که بیشترین شرایط را برآورده می کند انتخاب شده است. بنابراین ، برنامه نحوه نمایش دوربین در برنامه را بیان می کند و Camerax بهترین تنظیمات وضوح دوربین را برای برآورده کردن آن در دستگاه های مختلف تعیین می کند.
به عنوان مثال ، یک برنامه می تواند هر یک از موارد زیر را انجام دهد:
- وضوح هدف 4: 3 یا 16: 9 را برای یک مورد استفاده مشخص کنید
- وضوح سفارشی را مشخص کنید ، که Camerax سعی در یافتن نزدیکترین مسابقه دارد
- نسبت ابعاد محصول را برای
ImageCapture
مشخص کنید
Camerax قطعنامه های داخلی Camera2 را بطور خودکار انتخاب می کند. جدول زیر قطعنامه ها را نشان می دهد:
مورد استفاده | وضوح سطح داخلی | وضوح داده خروجی |
---|---|---|
پیش نمایش | نسبت ابعاد: وضوح مناسب برای هدف. | وضوح سطح داخلی. ابرداده ارائه شده است تا بتواند از نظر نسبت ابعاد هدف محصول ، مقیاس و چرخش را بچرخاند. |
وضوح پیش فرض: بالاترین وضوح پیش نمایش ، یا بالاترین وضوح دستگاه ترجیح داده شده که با نسبت ابعاد پیش نمایش مطابقت دارد. | ||
حداکثر وضوح: اندازه پیش نمایش ، که به بهترین اندازه مطابقت با وضوح صفحه دستگاه یا 1080p (1920x1080) اشاره دارد ، هر کدام کوچکتر باشد. | ||
تجزیه و تحلیل تصویر | نسبت ابعاد: وضوح مناسب برای هدف. | وضوح سطح داخلی. |
وضوح پیش فرض: تنظیم پیش فرض وضوح هدف 640x480 است. تنظیم هر دو وضوح هدف و نسبت ابعاد مربوطه منجر به وضوح بهترین پشتیبانی می شود. | ||
وضوح حداکثر: حداکثر وضوح خروجی دستگاه دوربین از فرمت YUV_420_888 که از StreamConfigurationMap.getOutputSizes() بازیابی می شود. وضوح هدف به طور پیش فرض به صورت 640x480 تعیین شده است ، بنابراین اگر می خواهید وضوح بزرگتر از 640x480 داشته باشید ، باید از setTargetResolution() و setTargetAspectRatio() استفاده کنید تا از وضوح پشتیبانی شده نزدیکترین آن را بدست آورید. | ||
ضبط تصویر | نسبت ابعاد: نسبت ابعاد که به بهترین وجه در تنظیمات قرار دارد. | وضوح سطح داخلی. |
وضوح پیش فرض: بالاترین وضوح موجود ، یا بالاترین وضوح دستگاهی که با نسبت ابعاد ImageCapture مطابقت دارد. | ||
وضوح حداکثر: حداکثر وضوح خروجی دستگاه دوربین در قالب JPEG. برای بازیابی این کار StreamConfigurationMap.getOutputSizes() استفاده کنید. |
قطعنامه را مشخص کنید
همانطور که در نمونه کد زیر نشان داده شده است ، می توانید هنگام استفاده از موارد استفاده از موارد استفاده از موارد استفاده از موارد استفاده را با استفاده از روش setTargetResolution(Size resolution)
تنظیم کنید:
کاتلین
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
جاوا
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
شما نمی توانید هر دو نسبت ابعاد هدف و وضوح هدف را در همان مورد استفاده تنظیم کنید. انجام این کار هنگام ساختن شی پیکربندی ، یک IllegalArgumentException
به همراه می آورد.
Size
وضوح را در قاب مختصات پس از چرخاندن اندازه های پشتیبانی شده توسط چرخش هدف بیان کنید. به عنوان مثال ، دستگاهی با جهت گیری طبیعی پرتره در چرخش هدف طبیعی که درخواست یک تصویر پرتره می کند می تواند 480x640 را مشخص کند ، و همان دستگاه ، 90 درجه چرخانده شده و هدف قرار دادن جهت گیری چشم انداز می تواند 640x480 را مشخص کند.
وضوح هدف سعی در تعیین حداقل وضوح تصویر دارد. وضوح تصویر واقعی نزدیکترین وضوح موجود در اندازه است که از وضوح هدف کوچکتر نیست ، همانطور که توسط اجرای دوربین تعیین می شود.
با این حال ، اگر هیچ وضوح وجود نداشته باشد که برابر یا بزرگتر از وضوح هدف باشد ، نزدیکترین وضوح موجود کوچکتر از وضوح هدف انتخاب شده است. قطعنامه هایی با نسبت ابعاد یکسان از Size
ارائه شده از اولویت بالاتری نسبت به وضوح نسبت ابعاد مختلف استفاده می شود.
Camerax بهترین وضوح مناسب را بر اساس درخواست ها اعمال می کند. اگر نیاز اصلی برآورده کردن نسبت ابعاد است ، فقط setTargetAspectRatio
مشخص کنید و Camerax یک وضوح خاص را بر اساس دستگاه تعیین می کند. اگر نیاز اصلی برنامه مشخص کردن وضوح به منظور کارآمدتر کردن پردازش تصویر (به عنوان مثال یک تصویر کوچک یا متوسط بر اساس قابلیت پردازش دستگاه) است ، از setTargetResolution(Size resolution)
استفاده کنید.
If your app requires an exact resolution, see the table within createCaptureSession()
to determine what maximum resolutions are supported by each hardware level. To check for the specific resolutions supported by the current device, see StreamConfigurationMap.getOutputSizes(int)
.
If your app is running on Android 10 or higher, you can use isSessionConfigurationSupported()
to verify a specific SessionConfiguration
.
Control camera output
In addition to letting you configure the camera output as-needed for each individual use case, CameraX also implements the following interfaces to support camera operations common to all bound use cases:
-
CameraControl
lets you configure common camera features. -
CameraInfo
lets you query the states of those common camera features.
These are the supported camera features with CameraControl:
- بزرگنمایی ضربه بزنید؛
- مشعل
- Focus and Metering (tap-to-focus)
- جبران نوردهی
Get instances of CameraControl and CameraInfo
Retrieve instances of CameraControl
and CameraInfo
using the Camera
object returned by ProcessCameraProvider.bindToLifecycle()
. The following code shows an example:
کاتلین
val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. val cameraControl = camera.cameraControl // For querying information and states. val cameraInfo = camera.cameraInfo
جاوا
Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. CameraControl cameraControl = camera.getCameraControl() // For querying information and states. CameraInfo cameraInfo = camera.getCameraInfo()
For example, you can submit zoom and other CameraControl
operations after calling bindToLifecycle()
. After you stop or destroy the activity used to bind the camera instance, CameraControl
can no longer execute operations and returns a failed ListenableFuture
.
بزرگنمایی ضربه بزنید؛
CameraControl offers two methods for changing the zoom level:
setZoomRatio()
sets the zoom by the zoom ratio.The ratio must be within the range of
CameraInfo.getZoomState().getValue().getMinZoomRatio()
andCameraInfo.getZoomState().getValue().getMaxZoomRatio()
. Otherwise the function returns a failedListenableFuture
.setLinearZoom()
sets the current zoom with a linear zoom value ranging from 0 to 1.0.The advantage of linear zoom is that it makes the field of view (FOV) scale with changes in zoom. This makes it ideal for use with a
Slider
view.
CameraInfo.getZoomState()
returns a LiveData of the current zoom state. The value changes when the camera is initialized or if the zoom level is set using setZoomRatio()
or setLinearZoom()
. Calling either method sets the values backing ZoomState.getZoomRatio()
and ZoomState.getLinearZoom()
. This is helpful if you want to display zoom ratio text alongside a slider. Simply observe the ZoomState
LiveData
to update both without needing to do a conversion.
The ListenableFuture
returned by both APIs offers the option for applications to be notified when a repeating request with the specified zoom value is completed. In addition, if you set a new zoom value while the previous operation is still executing, the previous zoom operation's ListenableFuture
fails immediately.
مشعل
CameraControl.enableTorch(boolean)
enables or disables the torch (also known as the flashlight).
CameraInfo.getTorchState()
can be used to query the current torch state. You can check the value returned by CameraInfo.hasFlashUnit()
to determine whether a torch is available. If not, calling CameraControl.enableTorch(boolean)
causes the returned ListenableFuture
to complete immediately with a failed result and sets the torch state to TorchState.OFF
.
When the torch is enabled, it remains on during photo and video capture regardless of the flashMode setting. The flashMode
in ImageCapture
works only when the torch is disabled.
Focus and Metering
CameraControl.startFocusAndMetering()
triggers autofocus and exposure metering by setting AF/AE/AWB metering regions based on the given FocusMeteringAction. This is often used to implement the “tap to focus” feature in many camera applications.
MeteringPoint
To begin, create a MeteringPoint
using MeteringPointFactory.createPoint(float x, float y, float size)
. A MeteringPoint
represents a single point on the camera Surface
. It's stored in a normalized form so that it can be easily converted to sensor coordinates for specifying AF/AE/AWB regions.
The size of the MeteringPoint
ranges from 0 to 1, with a default size of 0.15f. When calling MeteringPointFactory.createPoint(float x, float y, float size)
, CameraX creates a rectangle region centered at (x, y)
for the provided size
.
The following code demonstrates how to create a MeteringPoint
:
کاتلین
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview. previewView.setOnTouchListener((view, motionEvent) -> { val meteringPoint = previewView.meteringPointFactory .createPoint(motionEvent.x, motionEvent.y) … } // Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for // preview. Please note that if the preview is scaled or cropped in the View, // it’s the application's responsibility to transform the coordinates properly // so that the width and height of this factory represents the full Preview FOV. // And the (x,y) passed to create MeteringPoint might need to be adjusted with // the offsets. val meteringPointFactory = DisplayOrientedMeteringPointFactory( surfaceView.display, camera.cameraInfo, surfaceView.width, surfaceView.height ) // Use SurfaceOrientedMeteringPointFactory if the point is specified in // ImageAnalysis ImageProxy. val meteringPointFactory = SurfaceOrientedMeteringPointFactory( imageWidth, imageHeight, imageAnalysis)
startFocusAndMetering and FocusMeteringAction
To invoke startFocusAndMetering()
, applications must build a FocusMeteringAction
, which consists of one or more MeteringPoints
with optional metering mode combinations from FLAG_AF
, FLAG_AE
, FLAG_AWB
. The follow code demonstrates this usage:
کاتلین
val meteringPoint1 = meteringPointFactory.createPoint(x1, x1) val meteringPoint2 = meteringPointFactory.createPoint(x2, y2) val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB // Optionally add meteringPoint2 for AF/AE. .addPoint(meteringPoint2, FLAG_AF | FLAG_AE) // The action is canceled in 3 seconds (if not set, default is 5s). .setAutoCancelDuration(3, TimeUnit.SECONDS) .build() val result = cameraControl.startFocusAndMetering(action) // Adds listener to the ListenableFuture if you need to know the focusMetering result. result.addListener({ // result.get().isFocusSuccessful returns if the auto focus is successful or not. }, ContextCompat.getMainExecutor(this)
As shown in the preceding code, startFocusAndMetering()
takes a FocusMeteringAction
consisting of one MeteringPoint
for AF/AE/AWB metering regions and another MeteringPoint for AF and AE only.
Internally, CameraX converts it into Camera2 MeteringRectangles
and sets the corresponding CONTROL_AF_REGIONS
/ CONTROL_AE_REGIONS
/ CONTROL_AWB_REGIONS
parameters to the capture request.
Since not every device supports AF/AE/AWB and multiple regions, CameraX executes the FocusMeteringAction
with best effort. CameraX uses the maximum number of MeteringPoints supported, in the order that points were added. All MeteringPoints added after the maximum count are ignored. For example, if a FocusMeteringAction
is supplied with 3 MeteringPoints on a platform supporting just 2, only the first 2 MeteringPoints are used. The final MeteringPoint
is ignored by CameraX.
جبران نوردهی
Exposure compensation is useful when applications need to fine-tune exposure values (EV) beyond the auto exposure (AE) output result. Exposure compensation values are combined in the following way to determine the necessary exposure for current image conditions:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX provides the Camera.CameraControl.setExposureCompensationIndex()
function for setting the exposure compensation as an index value.
Positive index values make the image brighter, while negative values dim the image. Applications can query the supported range by CameraInfo.ExposureState.exposureCompensationRange()
described in the next section. If the value is supported, the returned ListenableFuture
completes when the value is successfully enabled in the capture request; if the specified index is out of the supported range, setExposureCompensationIndex()
causes the returned ListenableFuture
to complete immediately with a failed result.
CameraX keeps only the latest outstanding setExposureCompensationIndex()
request, and calling the function multiple times before the previous request gets executed results in its cancellation.
The following snippet sets an exposure compensation index and registers a callback for when the exposure change request has been executed:
کاتلین
camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex) .addListener({ // Get the current exposure compensation index, it might be // different from the asked value in case this request was // canceled by a newer setting request. val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex … }, mainExecutor)
Camera.CameraInfo.getExposureState()
retrieves the currentExposureState
including:- The supportability of exposure compensation control.
- The current exposure compensation index.
- The exposure compensation index range.
- The exposure compensation step used in exposure compensation value calculation.
For example, the following code initializes the settings for an exposure SeekBar
with current ExposureState
values:
کاتلین
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
منابع اضافی
To learn more about CameraX, consult the following additional resources.
Codelab
نمونه کد
جامعه توسعه دهندگان
Android CameraX Discussion Group
،You configure each CameraX use case to control different aspects of the use case's operations.
For example, with the image capture use case, you can set a target aspect ratio and a flash mode. The following code shows one example:
کاتلین
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
جاوا
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
In addition to configuration options, some use cases expose APIs to dynamically alter settings after the use case has been created. For information about configuration that is specific to the individual use cases, see Implement a preview , Analyze images , and Image capture .
CameraXConfig
For simplicity, CameraX has default configurations such as internal executors and handlers that are suitable for most usage scenarios. However, if your application has special requirements or prefers to customize those configurations, CameraXConfig
is the interface for that purpose.
With CameraXConfig
, an application can do the following:
- Optimize startup latency with
setAvailableCameraLimiter()
. - Provide the application's executor to CameraX with
setCameraExecutor()
. - Replace the default scheduler handler with
setSchedulerHandler()
. - Change the logging level with
setMinimumLoggingLevel()
.
Usage Model
The following procedure describes how to use CameraXConfig
:
- Create a
CameraXConfig
object with your customized configurations. - Implement the
CameraXConfig.Provider
interface in yourApplication
, and return yourCameraXConfig
object ingetCameraXConfig()
. - Add your
Application
class to yourAndroidManifest.xml
file, as described here .
For example, the following code sample restricts CameraX logging to error messages only:
کاتلین
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
Keep a local copy of the CameraXConfig
object if your application needs to know the CameraX configuration after setting it.
Camera Limiter
During the first invocation of ProcessCameraProvider.getInstance()
, CameraX enumerates and queries characteristics of the cameras available on the device. Because CameraX needs to communicate with hardware components, this process can take a non-trivial amount of time for each camera, particularly on low-end devices. If your application only uses specific cameras on the device, such as the default front camera, you can set CameraX to ignore other cameras, which can reduce startup latency for the cameras your application uses.
If the CameraSelector
passed to CameraXConfig.Builder.setAvailableCamerasLimiter()
filters out a camera, CameraX behaves as if that camera doesn't exist. For example, the following code limits the application to only use the device's default back camera:
کاتلین
class MainApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setAvailableCamerasLimiter(CameraSelector.DEFAULT_BACK_CAMERA) .build() } }
موضوعات
Many of the platform APIs on which CameraX is built require blocking interprocess communication (IPC) with hardware that can sometimes take hundreds of milliseconds to respond. For this reason, CameraX only calls these APIs from background threads, so that the main thread isn't blocked and the UI remains fluid. CameraX internally manages these background threads so that this behavior appears transparent. However, some applications require strict control of threads. CameraXConfig
lets an application set the background threads that are used through CameraXConfig.Builder.setCameraExecutor()
and CameraXConfig.Builder.setSchedulerHandler()
.
Camera Executor
The camera executor is used for all internal Camera platform API calls, as well as for callbacks from these APIs. CameraX allocates and manages an internal Executor
to perform these tasks. However, if your application requires stricter control of threads, use CameraXConfig.Builder.setCameraExecutor()
.
Scheduler Handler
The scheduler handler is used to schedule internal tasks at fixed intervals, such as retrying opening the camera when it isn't available. This handler does not execute jobs, and only dispatches them to the camera executor. It is also sometimes used on the legacy API platforms that require a Handler
for callbacks. In these cases, the callbacks are still only dispatched directly to the camera executor. CameraX allocates and manages an internal HandlerThread
to perform these tasks, but you can overridde it with CameraXConfig.Builder.setSchedulerHandler()
.
ورود به سیستم
CameraX logging lets applications filter logcat messages, as it can be good practice to avoid verbose messages in your production code. CameraX supports four logging levels, from the most verbose to the most severe:
-
Log.DEBUG
(default) -
Log.INFO
-
Log.WARN
-
Log.ERROR
Refer to the Android Log documentation for detailed descriptions of these log levels. Use CameraXConfig.Builder.setMinimumLoggingLevel(int)
to set the appropriate logging level for your application.
Automatic selection
CameraX automatically provides functionality that is specific to the device that your app is running on. For example, CameraX automatically determines the best resolution to use if you don't specify a resolution, or if the resolution you specify is unsupported. All of this is handled by the library, eliminating the need for you to write device-specific code.
CameraX's goal is to successfully initialize a camera session. This means CameraX compromises on resolution and aspect ratios based on device capability. The compromise can happen because:
- The device doesn't support the requested resolution.
- The device has compatibility issues, such as legacy devices that require certain resolutions to operate correctly.
- On some devices, certain formats are only available at certain aspect ratios.
- The device has a preference for a "nearest mod16" for JPEG or video encoding. For more information, see
SCALER_STREAM_CONFIGURATION_MAP
.
Although CameraX creates and manages the session, always check the returned image sizes on the use case output in your code and adjust accordingly.
چرخش
By default, the camera rotation is set to match the default display's rotation during the creation of the use case. In this default case, CameraX produces outputs to let the app match what you expect to see in the preview. You can change the rotation to a custom value to support multi-display devices by passing in the current display orientation when configuring use case objects or dynamically after they have been created.
Your app can set the target rotation using configuration settings. It can then update rotation settings by using the methods from the use case APIs (such as ImageAnalysis.setTargetRotation()
), even while the lifecycle is in a running state. You might use this when the app is locked to portrait mode—and so no reconfiguration occurs on rotation—but the photo or analysis use case needs to be aware of the current rotation of the device. For example, rotation awareness might be needed so faces are oriented correctly for face detection, or photos are set to landscape or portrait.
Data for captured images might be stored without rotation information. Exif data contains rotation information so that gallery applications can show the image in the correct orientation after saving.
To display preview data with the correct orientation, you can use the metadata output from Preview.PreviewOutput()
to create transforms.
The following code sample shows how to set the rotation on an orientation event:
کاتلین
override fun onCreate() { val imageCapture = ImageCapture.Builder().build() val orientationEventListener = object : OrientationEventListener(this as Context) { override fun onOrientationChanged(orientation : Int) { // Monitors orientation values to determine the target rotation value val rotation : Int = when (orientation) { in 45..134 -> Surface.ROTATION_270 in 135..224 -> Surface.ROTATION_180 in 225..314 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageCapture.targetRotation = rotation } } orientationEventListener.enable() }
جاوا
@Override public void onCreate() { ImageCapture imageCapture = new ImageCapture.Builder().build(); OrientationEventListener orientationEventListener = new OrientationEventListener((Context)this) { @Override public void onOrientationChanged(int orientation) { int rotation; // Monitors orientation values to determine the target rotation value if (orientation >= 45 && orientation < 135) { rotation = Surface.ROTATION_270; } else if (orientation >= 135 && orientation < 225) { rotation = Surface.ROTATION_180; } else if (orientation >= 225 && orientation < 315) { rotation = Surface.ROTATION_90; } else { rotation = Surface.ROTATION_0; } imageCapture.setTargetRotation(rotation); } }; orientationEventListener.enable(); }
Based on the set rotation, each use case either rotates the image data directly or provides rotation metadata to the consumers of the non-rotated image data.
- Preview : Metadata output is provided so that the rotation of the target resolution is known using
Preview.getTargetRotation()
. - ImageAnalysis : Metadata output is provided so that image buffer coordinates are known relative to display coordinates.
- ImageCapture : The image Exif metadata, buffer, or both the buffer and metadata are altered to note the rotation setting. The value altered depends upon the HAL implementation.
Crop rect
By default, the crop rect is the full buffer rect. You can customize it with ViewPort
and UseCaseGroup
. By grouping use cases and setting the viewport, CameraX guarantees that the crop rects of all the use cases in the group point to the same area in the camera sensor.
The following code snippet shows how to use these two classes:
کاتلین
val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build() val useCaseGroup = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build() cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup)
جاوا
ViewPort viewPort = new ViewPort.Builder( new Rational(width, height), getDisplay().getRotation()).build(); UseCaseGroup useCaseGroup = new UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(imageAnalysis) .addUseCase(imageCapture) .setViewPort(viewPort) .build(); cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, useCaseGroup);
ViewPort
defines the buffer rect visible to end users. Then CameraX calculates the largest possible crop rect based on the properties of the viewport and the attached use cases. Usually, to achieve a WYSIWYG effect, you can configure the viewport based on the preview use case. A simple way to get the viewport is to use PreviewView
.
The following code snippets shows how to get the ViewPort
object:
کاتلین
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
جاوا
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
In the preceding example, what the app gets from ImageAnalysis
and ImageCapture
matches what the end user sees in PreviewView
, assuming the PreviewView
's scale type is set to the default, FILL_CENTER
. After applying the crop rect and rotation to the output buffer, the image from all use cases is the same, though possibly with different resolutions. For more information about how to apply the transformation info, see transform output .
انتخاب دوربین
CameraX automatically selects the best camera device for your application's requirements and use cases. If you wish to use a different device than the one selected for you, there are a few options:
- Request the default front facing camera with
CameraSelector.DEFAULT_FRONT_CAMERA
. - Request the default rear facing camera with
CameraSelector.DEFAULT_BACK_CAMERA
. - Filter the list of available devices by their
CameraCharacteristics
withCameraSelector.Builder.addCameraFilter()
.
The following code sample illustrates how to create a CameraSelector
to influence device selection:
کاتلین
fun selectExternalOrBestCamera(provider: ProcessCameraProvider):CameraSelector? { val cam2Infos = provider.availableCameraInfos.map { Camera2CameraInfo.from(it) }.sortedByDescending { // HARDWARE_LEVEL is Int type, with the order of: // LEGACY < LIMITED < FULL < LEVEL_3 < EXTERNAL it.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) } return when { cam2Infos.isNotEmpty() -> { CameraSelector.Builder() .addCameraFilter { it.filter { camInfo -> // cam2Infos[0] is either EXTERNAL or best built-in camera val thisCamId = Camera2CameraInfo.from(camInfo).cameraId thisCamId == cam2Infos[0].cameraId } }.build() } else -> null } } // create a CameraSelector for the USB camera (or highest level internal camera) val selector = selectExternalOrBestCamera(processCameraProvider) processCameraProvider.bindToLifecycle(this, selector, preview, analysis)
Select multiple cameras concurrently
Starting with CameraX 1.3, you can also select multiple cameras concurrently. For example, you can bind to a front and back camera to take photos or record videos from both perspectives simultaneously.
When using the Concurrent Camera feature, the device can operate two cameras with different-facing lenses at the same time, or operate two back cameras at the same time. The following code block shows how to set two cameras when calling bindToLifecycle
, and how to get both Camera objects from the returned ConcurrentCamera
object.
کاتلین
// Build ConcurrentCameraConfig val primary = ConcurrentCamera.SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ) val secondary = ConcurrentCamera.SingleCameraConfig( secondaryCameraSelector, useCaseGroup, lifecycleOwner ) val concurrentCamera = cameraProvider.bindToLifecycle( listOf(primary, secondary) ) val primaryCamera = concurrentCamera.cameras[0] val secondaryCamera = concurrentCamera.cameras[1]
جاوا
// Build ConcurrentCameraConfig SingleCameraConfig primary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); SingleCameraConfig secondary = new SingleCameraConfig( primaryCameraSelector, useCaseGroup, lifecycleOwner ); ConcurrentCamera concurrentCamera = mCameraProvider.bindToLifecycle(Arrays.asList(primary, secondary)); Camera primaryCamera = concurrentCamera.getCameras().get(0); Camera secondaryCamera = concurrentCamera.getCameras().get(1);
وضوح دوربین
You can choose to let CameraX set the image resolution based on a combination of the device capabilities, device's supported hardware level , use case, and provided aspect ratio. Alternatively, you can set a specific target resolution or a specific aspect ratio in use cases that support that configuration.
Automatic resolution
CameraX can automatically determine the best resolution settings based on the use cases specified in cameraProcessProvider.bindToLifecycle()
. Whenever possible, specify all the use cases needed to run concurrently in a single session in a single bindToLifecycle()
call. CameraX determines resolutions based on the set of use cases bound by considering the device's supported hardware level and by accounting for device-specific variance (where a device exceeds or doesn't meet the stream configurations available ). The intent is to let the application run on a wide variety of devices while minimizing device-specific code paths.
The default aspect ratio for image capture and image analysis use cases is 4:3.
Use cases have a configurable aspect ratio to let the application specify the desired aspect ratio based on UI design. CameraX output is produced to match the aspect ratios requested as closely as the device supports. If there is no exact-match resolution supported, the one that fulfills the most conditions is selected. Thus, the application dictates how the camera appears in the app, and CameraX determines the best camera resolution settings to satisfy that on different devices.
For example, an app can do any of the following:
- Specify a target resolution of 4:3 or 16:9 for a use case
- Specify a custom resolution, which CameraX attempts to find the closest match to
- Specify a cropping aspect ratio for
ImageCapture
CameraX chooses the internal Camera2 surface resolutions automatically. The following table shows the resolutions:
مورد استفاده | Internal surface resolution | Output data resolution |
---|---|---|
پیش نمایش | Aspect Ratio: The resolution that best fits the target to the setting. | Internal surface resolution. Metadata is provided to let a View crop, scale, and rotate for the target aspect ratio. |
Default resolution: Highest preview resolution, or highest device-preferred resolution that matches the Preview's aspect ratio. | ||
Max resolution: Preview size, which refers to the best size match to the device's screen resolution, or to 1080p (1920x1080), whichever is smaller. | ||
تجزیه و تحلیل تصویر | Aspect ratio: The resolution that best fits the target to the setting. | Internal surface resolution. |
Default resolution: The default target resolution setting is 640x480. Adjusting both target resolution and corresponding aspect ratio results in a best-supported resolution. | ||
Max resolution: The camera device's maximum output resolution of YUV_420_888 format which is retrieved from StreamConfigurationMap.getOutputSizes() . The target resolution is set as 640x480 by default, so if you want a resolution larger than 640x480, you must use setTargetResolution() and setTargetAspectRatio() to get the closest one from the supported resolutions. | ||
ضبط تصویر | Aspect ratio: Aspect ratio that best fits the setting. | Internal surface resolution. |
Default resolution: Highest resolution available, or highest device-preferred resolution that matches the ImageCapture's aspect ratio. | ||
Max resolution: The camera device's maximum output resolution in a JPEG format. Use StreamConfigurationMap.getOutputSizes() to retrieve this. |
Specify a resolution
You can set specific resolutions when building use cases using the setTargetResolution(Size resolution)
method, as shown in the following code sample:
کاتلین
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
جاوا
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetResolution(new Size(1280, 720)) .build();
You can't set both target aspect ratio and target resolution on the same use case. Doing so throws an IllegalArgumentException
when building the configuration object.
Express the resolution Size
in the coordinate frame after rotating the supported sizes by the target rotation. For example, a device with portrait natural orientation in natural target rotation requesting a portrait image can specify 480x640, and the same device, rotated 90 degrees and targeting landscape orientation can specify 640x480.
The target resolution attempts to establish a minimum bound for the image resolution. The actual image resolution is the closest available resolution in size that isn't smaller than the target resolution, as determined by the Camera implementation.
However, if no resolution exists that is equal to or larger than the target resolution, the nearest available resolution smaller than the target resolution is chosen. Resolutions with the same aspect ratio of the provided Size
are given higher priority than resolutions of different aspect ratios.
CameraX applies the best suitable resolution based on the requests. If the primary need is to satisfy aspect ratio, specify only setTargetAspectRatio
, and CameraX determines a specific resolution suitable based on the device. If the primary need of the app is to specify a resolution in order to make image processing more efficient (for example a small or mid-sized image based on device processing capability), use setTargetResolution(Size resolution)
.
If your app requires an exact resolution, see the table within createCaptureSession()
to determine what maximum resolutions are supported by each hardware level. To check for the specific resolutions supported by the current device, see StreamConfigurationMap.getOutputSizes(int)
.
If your app is running on Android 10 or higher, you can use isSessionConfigurationSupported()
to verify a specific SessionConfiguration
.
Control camera output
In addition to letting you configure the camera output as-needed for each individual use case, CameraX also implements the following interfaces to support camera operations common to all bound use cases:
-
CameraControl
lets you configure common camera features. -
CameraInfo
lets you query the states of those common camera features.
These are the supported camera features with CameraControl:
- بزرگنمایی ضربه بزنید؛
- مشعل
- Focus and Metering (tap-to-focus)
- جبران نوردهی
Get instances of CameraControl and CameraInfo
Retrieve instances of CameraControl
and CameraInfo
using the Camera
object returned by ProcessCameraProvider.bindToLifecycle()
. The following code shows an example:
کاتلین
val camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. val cameraControl = camera.cameraControl // For querying information and states. val cameraInfo = camera.cameraInfo
جاوا
Camera camera = processCameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) // For performing operations that affect all outputs. CameraControl cameraControl = camera.getCameraControl() // For querying information and states. CameraInfo cameraInfo = camera.getCameraInfo()
For example, you can submit zoom and other CameraControl
operations after calling bindToLifecycle()
. After you stop or destroy the activity used to bind the camera instance, CameraControl
can no longer execute operations and returns a failed ListenableFuture
.
بزرگنمایی ضربه بزنید؛
CameraControl offers two methods for changing the zoom level:
setZoomRatio()
sets the zoom by the zoom ratio.The ratio must be within the range of
CameraInfo.getZoomState().getValue().getMinZoomRatio()
andCameraInfo.getZoomState().getValue().getMaxZoomRatio()
. Otherwise the function returns a failedListenableFuture
.setLinearZoom()
sets the current zoom with a linear zoom value ranging from 0 to 1.0.The advantage of linear zoom is that it makes the field of view (FOV) scale with changes in zoom. This makes it ideal for use with a
Slider
view.
CameraInfo.getZoomState()
returns a LiveData of the current zoom state. The value changes when the camera is initialized or if the zoom level is set using setZoomRatio()
or setLinearZoom()
. Calling either method sets the values backing ZoomState.getZoomRatio()
and ZoomState.getLinearZoom()
. This is helpful if you want to display zoom ratio text alongside a slider. Simply observe the ZoomState
LiveData
to update both without needing to do a conversion.
The ListenableFuture
returned by both APIs offers the option for applications to be notified when a repeating request with the specified zoom value is completed. In addition, if you set a new zoom value while the previous operation is still executing, the previous zoom operation's ListenableFuture
fails immediately.
مشعل
CameraControl.enableTorch(boolean)
enables or disables the torch (also known as the flashlight).
CameraInfo.getTorchState()
can be used to query the current torch state. You can check the value returned by CameraInfo.hasFlashUnit()
to determine whether a torch is available. If not, calling CameraControl.enableTorch(boolean)
causes the returned ListenableFuture
to complete immediately with a failed result and sets the torch state to TorchState.OFF
.
When the torch is enabled, it remains on during photo and video capture regardless of the flashMode setting. The flashMode
in ImageCapture
works only when the torch is disabled.
Focus and Metering
CameraControl.startFocusAndMetering()
triggers autofocus and exposure metering by setting AF/AE/AWB metering regions based on the given FocusMeteringAction. This is often used to implement the “tap to focus” feature in many camera applications.
MeteringPoint
To begin, create a MeteringPoint
using MeteringPointFactory.createPoint(float x, float y, float size)
. A MeteringPoint
represents a single point on the camera Surface
. It's stored in a normalized form so that it can be easily converted to sensor coordinates for specifying AF/AE/AWB regions.
The size of the MeteringPoint
ranges from 0 to 1, with a default size of 0.15f. When calling MeteringPointFactory.createPoint(float x, float y, float size)
, CameraX creates a rectangle region centered at (x, y)
for the provided size
.
The following code demonstrates how to create a MeteringPoint
:
کاتلین
// Use PreviewView.getMeteringPointFactory if PreviewView is used for preview. previewView.setOnTouchListener((view, motionEvent) -> { val meteringPoint = previewView.meteringPointFactory .createPoint(motionEvent.x, motionEvent.y) … } // Use DisplayOrientedMeteringPointFactory if SurfaceView / TextureView is used for // preview. Please note that if the preview is scaled or cropped in the View, // it’s the application's responsibility to transform the coordinates properly // so that the width and height of this factory represents the full Preview FOV. // And the (x,y) passed to create MeteringPoint might need to be adjusted with // the offsets. val meteringPointFactory = DisplayOrientedMeteringPointFactory( surfaceView.display, camera.cameraInfo, surfaceView.width, surfaceView.height ) // Use SurfaceOrientedMeteringPointFactory if the point is specified in // ImageAnalysis ImageProxy. val meteringPointFactory = SurfaceOrientedMeteringPointFactory( imageWidth, imageHeight, imageAnalysis)
startFocusAndMetering and FocusMeteringAction
To invoke startFocusAndMetering()
, applications must build a FocusMeteringAction
, which consists of one or more MeteringPoints
with optional metering mode combinations from FLAG_AF
, FLAG_AE
, FLAG_AWB
. The follow code demonstrates this usage:
کاتلین
val meteringPoint1 = meteringPointFactory.createPoint(x1, x1) val meteringPoint2 = meteringPointFactory.createPoint(x2, y2) val action = FocusMeteringAction.Builder(meteringPoint1) // default AF|AE|AWB // Optionally add meteringPoint2 for AF/AE. .addPoint(meteringPoint2, FLAG_AF | FLAG_AE) // The action is canceled in 3 seconds (if not set, default is 5s). .setAutoCancelDuration(3, TimeUnit.SECONDS) .build() val result = cameraControl.startFocusAndMetering(action) // Adds listener to the ListenableFuture if you need to know the focusMetering result. result.addListener({ // result.get().isFocusSuccessful returns if the auto focus is successful or not. }, ContextCompat.getMainExecutor(this)
As shown in the preceding code, startFocusAndMetering()
takes a FocusMeteringAction
consisting of one MeteringPoint
for AF/AE/AWB metering regions and another MeteringPoint for AF and AE only.
Internally, CameraX converts it into Camera2 MeteringRectangles
and sets the corresponding CONTROL_AF_REGIONS
/ CONTROL_AE_REGIONS
/ CONTROL_AWB_REGIONS
parameters to the capture request.
Since not every device supports AF/AE/AWB and multiple regions, CameraX executes the FocusMeteringAction
with best effort. CameraX uses the maximum number of MeteringPoints supported, in the order that points were added. All MeteringPoints added after the maximum count are ignored. For example, if a FocusMeteringAction
is supplied with 3 MeteringPoints on a platform supporting just 2, only the first 2 MeteringPoints are used. The final MeteringPoint
is ignored by CameraX.
جبران نوردهی
Exposure compensation is useful when applications need to fine-tune exposure values (EV) beyond the auto exposure (AE) output result. Exposure compensation values are combined in the following way to determine the necessary exposure for current image conditions:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX provides the Camera.CameraControl.setExposureCompensationIndex()
function for setting the exposure compensation as an index value.
Positive index values make the image brighter, while negative values dim the image. Applications can query the supported range by CameraInfo.ExposureState.exposureCompensationRange()
described in the next section. If the value is supported, the returned ListenableFuture
completes when the value is successfully enabled in the capture request; if the specified index is out of the supported range, setExposureCompensationIndex()
causes the returned ListenableFuture
to complete immediately with a failed result.
CameraX keeps only the latest outstanding setExposureCompensationIndex()
request, and calling the function multiple times before the previous request gets executed results in its cancellation.
The following snippet sets an exposure compensation index and registers a callback for when the exposure change request has been executed:
کاتلین
camera.cameraControl.setExposureCompensationIndex(exposureCompensationIndex) .addListener({ // Get the current exposure compensation index, it might be // different from the asked value in case this request was // canceled by a newer setting request. val currentExposureIndex = camera.cameraInfo.exposureState.exposureCompensationIndex … }, mainExecutor)
Camera.CameraInfo.getExposureState()
retrieves the currentExposureState
including:- The supportability of exposure compensation control.
- The current exposure compensation index.
- The exposure compensation index range.
- The exposure compensation step used in exposure compensation value calculation.
For example, the following code initializes the settings for an exposure SeekBar
with current ExposureState
values:
کاتلین
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
منابع اضافی
To learn more about CameraX, consult the following additional resources.
Codelab
نمونه کد
جامعه توسعه دهندگان
Android CameraX Discussion Group