گزینه های پیکربندی

شما هر مورد CameraX را برای کنترل جنبه‌های مختلف عملیات کیس استفاده پیکربندی می‌کنید.

به عنوان مثال، با استفاده از عکس گرفتن، می توانید نسبت تصویر هدف و حالت فلاش را تنظیم کنید. کد زیر یک مثال را نشان می دهد:

کاتلین

val imageCapture = ImageCapture.Builder()
    .setFlashMode(...)
    .setTargetAspectRatio(...)
    .build()

جاوا

ImageCapture imageCapture =
    new ImageCapture.Builder()
        .setFlashMode(...)
        .setTargetAspectRatio(...)
        .build();

علاوه بر گزینه‌های پیکربندی، برخی موارد استفاده APIها را در معرض تغییر پویا تنظیمات پس از ایجاد مورد استفاده قرار می‌دهند. برای اطلاعات در مورد پیکربندی که مختص موارد استفاده فردی است، به اجرای پیش‌نمایش ، تجزیه و تحلیل تصاویر ، و ضبط تصویر مراجعه کنید.

CameraXConfig

برای سادگی، CameraX دارای تنظیمات پیش‌فرض مانند مجری‌های داخلی و کنترل‌کننده‌هایی است که برای اکثر سناریوهای استفاده مناسب هستند. با این حال، اگر برنامه شما دارای الزامات خاصی است یا ترجیح می دهد آن تنظیمات را سفارشی کند، CameraXConfig رابطی برای این منظور است.

با CameraXConfig ، یک برنامه می تواند کارهای زیر را انجام دهد:

مدل استفاده

روش زیر نحوه استفاده از CameraXConfig را شرح می دهد:

  1. یک شی CameraXConfig با تنظیمات سفارشی خود ایجاد کنید.
  2. رابط CameraXConfig.Provider را در Application خود پیاده کنید و شی CameraXConfig خود را در getCameraXConfig() برگردانید.
  3. همانطور که در اینجا توضیح داده شده است، کلاس 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 برای تأثیرگذاری بر انتخاب دستگاه را نشان می دهد:

کاتلین

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
  • نمونه کد

  • نمونه برنامه های CameraX
  • جامعه توسعه دهندگان

    گروه بحث Android CameraX

    ،

    شما هر مورد CameraX را برای کنترل جنبه‌های مختلف عملیات کیس استفاده پیکربندی می‌کنید.

    به عنوان مثال، با استفاده از عکس گرفتن، می توانید نسبت تصویر هدف و حالت فلاش را تنظیم کنید. کد زیر یک مثال را نشان می دهد:

    کاتلین

    val imageCapture = ImageCapture.Builder()
        .setFlashMode(...)
        .setTargetAspectRatio(...)
        .build()

    جاوا

    ImageCapture imageCapture =
        new ImageCapture.Builder()
            .setFlashMode(...)
            .setTargetAspectRatio(...)
            .build();

    علاوه بر گزینه‌های پیکربندی، برخی موارد استفاده APIها را در معرض تغییر پویا تنظیمات پس از ایجاد مورد استفاده قرار می‌دهند. برای اطلاعات در مورد پیکربندی که مختص موارد استفاده فردی است، به اجرای پیش‌نمایش ، تجزیه و تحلیل تصاویر ، و ضبط تصویر مراجعه کنید.

    CameraXConfig

    برای سادگی، CameraX دارای تنظیمات پیش‌فرض مانند مجری‌های داخلی و کنترل‌کننده‌هایی است که برای اکثر سناریوهای استفاده مناسب هستند. با این حال، اگر برنامه شما دارای الزامات خاصی است یا ترجیح می دهد آن تنظیمات را سفارشی کند، CameraXConfig رابطی برای این منظور است.

    با CameraXConfig ، یک برنامه می تواند کارهای زیر را انجام دهد:

    مدل استفاده

    روش زیر نحوه استفاده از CameraXConfig را شرح می دهد:

    1. یک شی CameraXConfig با تنظیمات سفارشی خود ایجاد کنید.
    2. رابط CameraXConfig.Provider را در Application خود پیاده کنید و شی CameraXConfig خود را در getCameraXConfig() برگردانید.
    3. همانطور که در اینجا توضیح داده شده است، کلاس 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 برای تأثیرگذاری بر انتخاب دستگاه نشان می دهد:

    کاتلین

    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() را بررسی کنید. اگر اینگونه نباشد ، فراخوانی CameraControl.enableTorch(boolean) باعث می شود که بلافاصله با یک نتیجه ناموفق به ListenableFuture برسد و وضعیت مشعل را به 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 ، با منابع اضافی زیر مشورت کنید.

    کدی

  • شروع کار با فیلمبرداری
  • نمونه کد

  • برنامه های نمونه دوربین
  • جامعه توسعه دهنده

    گروه بحث و گفتگوی فیلمبرداری اندرویدی