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

شما هر مورد 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ها را از رشته‌های پس‌زمینه فراخوانی می‌کند تا رشته اصلی مسدود نشود و رابط کاربری روان باقی بماند. 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 دیگر نمی تواند عملیات را انجام دهد و یک 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 ، با منابع اضافی زیر مشورت کنید.

    کدی

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

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

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

    ،

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

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

    کاتلین

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

    جاوا

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

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

    دوربین فیلمبرداری

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

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

    مدل استفاده

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

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

    کاتلین

    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() and CameraInfo.getZoomState().getValue().getMaxZoomRatio() . Otherwise the function returns a failed ListenableFuture .

    • 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 current ExposureState 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
    }
    

    Additional resources

    To learn more about CameraX, consult the following additional resources.

    Codelab

  • Getting Started with CameraX
  • Code sample

  • CameraX sample apps
  • جامعه توسعه دهندگان

    Android CameraX Discussion Group