คุณกำหนดค่ากรณีการใช้งาน CameraX แต่ละกรณีเพื่อควบคุมการใช้งานในด้านต่างๆ ของเคสของคุณ
เช่น กำหนดสัดส่วนภาพเป้าหมายด้วย Use Case การจับภาพ และโหมดแฟลช โค้ดต่อไปนี้แสดงตัวอย่าง 1 รายการ
Kotlin
val imageCapture = ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build()
Java
ImageCapture imageCapture = new ImageCapture.Builder() .setFlashMode(...) .setTargetAspectRatio(...) .build();
นอกจากตัวเลือกการกำหนดค่าแล้ว กรณีการใช้งานบางกรณียังเผยแพร่ API ในแบบไดนามิก แก้ไขการตั้งค่าหลังจากที่สร้าง Use Case แล้ว สำหรับข้อมูลเกี่ยวกับ เฉพาะของแต่ละกรณีการใช้งาน โปรดดูที่ใช้ แสดงตัวอย่าง, วิเคราะห์ รูปภาพและรูปภาพ ภาพ
CameraXConfig
CameraX มีการกำหนดค่าเริ่มต้นต่างๆ เช่น ผู้ดำเนินการภายในเพื่อให้ใช้งานได้ง่าย
และเครื่องจัดการที่เหมาะสมกับสถานการณ์การใช้งานส่วนใหญ่ อย่างไรก็ตาม หาก
มีข้อกำหนดพิเศษหรือต้องการปรับแต่ง
การกำหนดค่า CameraXConfig
เป็นอินเทอร์เฟซสำหรับวัตถุประสงค์ดังกล่าว
แอปพลิเคชัน CameraXConfig
สามารถทำสิ่งต่อไปนี้ได้
- เพิ่มประสิทธิภาพเวลาในการตอบสนองของการเริ่มต้นด้วย
setAvailableCameraLimiter()
- ให้ผู้ดำเนินการของแอปพลิเคชันไปยัง CameraX ด้วย
setCameraExecutor()
- แทนที่เครื่องจัดการเครื่องจัดตารางเวลาเริ่มต้นด้วย
setSchedulerHandler()
- เปลี่ยนระดับการบันทึกด้วย
setMinimumLoggingLevel()
โมเดลการใช้งาน
ขั้นตอนต่อไปนี้จะอธิบายวิธีใช้ CameraXConfig
- สร้างออบเจ็กต์
CameraXConfig
ด้วยการกำหนดค่าที่คุณกำหนดเอง - ติดตั้งใช้งาน
CameraXConfig.Provider
อินเทอร์เฟซในApplication
และ ส่งคืนออบเจ็กต์CameraXConfig
ในgetCameraXConfig()
- เพิ่มชั้นเรียน
Application
ลงในไฟล์AndroidManifest.xml
เป็น ตามที่อธิบายไว้ที่นี่
เช่น ตัวอย่างโค้ดต่อไปนี้จำกัดการบันทึก CameraX ไม่ให้เกิดข้อผิดพลาด ข้อความเท่านั้น:
Kotlin
class CameraApplication : Application(), CameraXConfig.Provider { override fun getCameraXConfig(): CameraXConfig { return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig()) .setMinimumLoggingLevel(Log.ERROR).build() } }
เก็บสำเนาออบเจ็กต์ CameraXConfig
ไว้ในเครื่องหากแอปพลิเคชันจำเป็นต้อง
ทราบการกำหนดค่าของ CameraX หลังจากตั้งค่าแล้ว
ตัวจำกัดกล้อง
ระหว่างการเรียกใช้ครั้งแรก
ProcessCameraProvider.getInstance()
CameraX แจกแจงและลักษณะการค้นหาของกล้องที่มีอยู่ใน
อุปกรณ์ เนื่องจาก CameraX ต้องสื่อสารกับส่วนประกอบของฮาร์ดแวร์
อาจใช้เวลาเพียงเล็กน้อยสำหรับกล้องแต่ละตัว โดยเฉพาะเมื่อ
อุปกรณ์โลว์เอนด์ หากแอปพลิเคชันของคุณใช้เฉพาะกล้องบางตัวบนอุปกรณ์
เช่น กล้องหน้าเริ่มต้น คุณสามารถตั้งค่า CameraX ให้ละเว้นกล้องอื่นๆ
ซึ่งสามารถลดเวลาในการตอบสนองเริ่มต้นสำหรับกล้องที่แอปพลิเคชันใช้
หากCameraSelector
ผ่าน
ถึง
CameraXConfig.Builder.setAvailableCamerasLimiter()
กรองกล้องออก CameraX จะทำงานเสมือนว่าไม่มีกล้องอยู่ สำหรับ
ตัวอย่างเช่น โค้ดต่อไปนี้จะจำกัดให้แอปพลิเคชันใช้
กล้องหลังเริ่มต้น:
Kotlin
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 ของแพลตฟอร์มกล้องภายในทั้งหมดด้วย
สำหรับ Callback จาก API เหล่านี้ CameraX จัดสรรและจัดการ
Executor
เพื่อดำเนินการเหล่านี้
แต่หากแอปพลิเคชันของคุณต้องการการควบคุมชุดข้อความที่เข้มงวดขึ้น ให้ใช้
CameraXConfig.Builder.setCameraExecutor()
เครื่องจัดการเครื่องจัดตารางเวลา
เครื่องจัดการเครื่องจัดตารางเวลาใช้เพื่อกำหนดเวลางานภายในเป็นช่วงเวลาคงที่
เช่น ลองเปิดกล้องอีกครั้งเมื่อกล้องไม่พร้อมใช้งาน เครื่องจัดการนี้
ไม่เรียกใช้งาน และจ่ายให้กับผู้ดำเนินการของกล้องเท่านั้น และยัง
บางครั้งใช้บนแพลตฟอร์ม API เดิมซึ่งต้องใช้
Handler
สำหรับ Callback ในกรณีเหล่านี้ พารามิเตอร์
ระบบจะยังคงส่ง Callback ไปยังผู้ดำเนินการของกล้องโดยตรงเท่านั้น กล้องถ่ายรูป X
จัดสรรและจัดการองค์กร
HandlerThread
เพื่อดำเนินการเหล่านี้
แต่คุณสามารถลบล้างได้ด้วย CameraXConfig.Builder.setSchedulerHandler()
การบันทึก
การบันทึกของ CameraX ช่วยให้แอปพลิเคชันกรองข้อความ Logcat ได้ตามต้องการ เพื่อหลีกเลี่ยงข้อความแบบละเอียดในโค้ดการผลิต CameraX รองรับ ระดับการบันทึก 4 ระดับ ตั้งแต่ระดับละเอียดที่สุดไปจนถึงระดับร้ายแรงที่สุด ได้แก่
Log.DEBUG
(ค่าเริ่มต้น)Log.INFO
Log.WARN
Log.ERROR
โปรดดูเอกสารประกอบเกี่ยวกับบันทึกของ Android
เพื่อดูคำอธิบายโดยละเอียดของระดับการบันทึกเหล่านี้ ใช้
CameraXConfig.Builder.setMinimumLoggingLevel(int)
เพื่อตั้งค่าระดับการบันทึกที่เหมาะสมสำหรับแอปพลิเคชันของคุณ
การเลือกอัตโนมัติ
CameraX จะให้ฟังก์ชันการทำงานเฉพาะสำหรับอุปกรณ์ที่ ที่แอปของคุณทำงานอยู่ เช่น CameraX จะพิจารณา ที่ดีที่สุดที่จะใช้ในกรณีที่คุณไม่ได้ระบุความละเอียด หรือถ้าความละเอียด ที่คุณระบุไม่ได้รับการสนับสนุน ทั้งหมดนี้ได้รับการจัดการโดยไลบรารี ทำให้ ที่คุณจำเป็นต้องใช้ในการเขียนโค้ดเฉพาะอุปกรณ์
เป้าหมายของ CameraX คือการเริ่มต้นเซสชันของกล้องให้สำเร็จ ซึ่งหมายความว่า CameraX มีการเปลี่ยนแปลงความละเอียดและสัดส่วนภาพตามความสามารถของอุปกรณ์ การบุกรุกอาจเกิดขึ้นเนื่องจากสาเหตุต่อไปนี้
- อุปกรณ์ไม่รองรับการแก้ปัญหาที่ขอ
- อุปกรณ์มีปัญหาเรื่องความเข้ากันได้ เช่น อุปกรณ์เดิมที่ต้องใช้ เพื่อให้ทำงานได้อย่างถูกต้อง
- ในบางอุปกรณ์ บางรูปแบบจะใช้ได้ในบางลักษณะเท่านั้น ของคุณ
- อุปกรณ์นี้มีค่ากำหนด "mod16 ที่ใกล้เคียงที่สุด" สำหรับ JPEG หรือวิดีโอ
การเข้ารหัส สำหรับข้อมูลเพิ่มเติม โปรดดู
SCALER_STREAM_CONFIGURATION_MAP
แม้ว่า CameraX จะสร้างและจัดการเซสชัน ให้ตรวจสอบ แสดงผลขนาดรูปภาพในเอาต์พุตกรณีการใช้งานในโค้ดของคุณ แล้วปรับขนาดให้สอดคล้องกัน
การหมุน
การหมุนกล้องจะตั้งค่าให้ตรงกับการหมุนของจอแสดงผลเริ่มต้นโดยค่าเริ่มต้น ระหว่างการสร้าง Use Case ในกรณีเริ่มต้นนี้ CameraX จะสร้าง เพื่อให้แอปตรงกับสิ่งที่คุณคาดหวังที่จะเห็นใน เวอร์ชันตัวอย่าง คุณสามารถเปลี่ยนการหมุนเป็นค่าที่กำหนดเองเพื่อรองรับหลายจอแสดงผล โดยส่งในการวางแนวจอแสดงผลปัจจุบันเมื่อกำหนดค่า Use Case ออบเจ็กต์หรือแบบไดนามิกหลังจากที่สร้างขึ้น
แอปของคุณตั้งค่าการหมุนเวียนเป้าหมายได้โดยใช้การตั้งค่าการกําหนดค่า จากนั้นจะทำสิ่งต่อไปนี้ได้
อัปเดตการตั้งค่าการหมุนเวียนโดยใช้เมธอดจาก API ของ Use Case (เช่น
ImageAnalysis.setTargetRotation()
)
แม้ว่าวงจรจะอยู่ในสถานะทำงานอยู่ คุณอาจใช้เมื่อแอป
จะล็อกเป็นโหมดแนวตั้ง ดังนั้นจึงไม่มีการกำหนดค่าใหม่เกิดขึ้น
การหมุน แต่รูปภาพหรือกรณีการใช้งานการวิเคราะห์ต้องระวัง
การหมุนปัจจุบันของอุปกรณ์ เช่น อาจต้องใช้การรับรู้การหมุนเวียน
เอาละ
ใบหน้าอยู่ในทิศทางที่ถูกต้องสำหรับการตรวจจับใบหน้า หรือตั้งค่ารูปภาพเป็นแนวนอน
หรือภาพแนวตั้ง
ข้อมูลสำหรับรูปภาพที่จับภาพอาจถูกจัดเก็บโดยไม่มีข้อมูลการหมุน ข้อมูล Exif มีข้อมูลการหมุนเพื่อให้แอปพลิเคชันแกลเลอรีสามารถแสดงรูปภาพใน การวางแนวที่ถูกต้องหลังจากบันทึก
หากต้องการแสดงตัวอย่างข้อมูลที่มีการวางแนวที่ถูกต้อง คุณสามารถใช้ข้อมูลเมตา
เอาต์พุตจาก
Preview.PreviewOutput()
เพื่อสร้างการเปลี่ยนรูปแบบ
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีตั้งค่าการหมุนในเหตุการณ์การวางแนว
Kotlin
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() }
Java
@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
ครอบตัดรูปสี่เหลี่ยม
โดยค่าเริ่มต้น สี่เหลี่ยมครอบตัดจะเป็นบัฟเฟอร์เต็มรูป คุณสามารถปรับแต่งได้ด้วย
ViewPort
และ
UseCaseGroup
ด้วยการจัดกลุ่มการใช้งาน
CameraX รับประกันว่าการครอบตัดรูปสี่เหลี่ยมของ
กรณีการใช้งานในกลุ่มจะชี้ไปยังพื้นที่เดียวกันในเซ็นเซอร์ของกล้อง
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้คลาสทั้ง 2 รายการนี้
Kotlin
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)
Java
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 จะคำนวณ
รูปสี่เหลี่ยมครอบตัดที่ใหญ่ที่สุดเท่าที่จะเป็นไปได้ โดยพิจารณาจากคุณสมบัติของวิวพอร์ต
Use Case ที่แนบมา โดยทั่วไป ถ้าต้องการให้ได้ผลลัพธ์แบบ WYSIWYG คุณสามารถกำหนดค่า
วิวพอร์ตตามกรณีการใช้งานตัวอย่าง วิธีง่ายๆ ในการรับวิวพอร์ตคือ
เพื่อใช้ PreviewView
ข้อมูลโค้ดต่อไปนี้แสดงวิธีรับออบเจ็กต์ ViewPort
Kotlin
val viewport = findViewById<PreviewView>(R.id.preview_view).viewPort
Java
ViewPort viewPort = ((PreviewView)findViewById(R.id.preview_view)).getViewPort();
ในตัวอย่างก่อนหน้านี้ สิ่งที่แอปได้รับจาก ImageAnalysis
และ
ImageCapture
จะตรงกับสิ่งที่ผู้ใช้ปลายทางเห็นใน PreviewView
โดยสมมติว่า
ประเภทสเกลของ PreviewView
ตั้งเป็นค่าเริ่มต้น FILL_CENTER
หลังสมัคร
การครอบตัดและการหมุนไปยังบัฟเฟอร์เอาต์พุต รูปภาพจากกรณีการใช้งานทั้งหมด
จะเหมือนกัน แต่อาจจะมีความละเอียดต่างกัน สำหรับข้อมูลเพิ่มเติม
ดูวิธีใช้ข้อมูลการเปลี่ยนรูปแบบได้ที่การเปลี่ยนรูปแบบ
เอาต์พุต
การเลือกกล้อง
CameraX จะเลือกอุปกรณ์กล้องที่ดีที่สุดสำหรับแอปพลิเคชันของคุณโดยอัตโนมัติ ข้อกำหนดและกรณีการใช้งาน หากต้องการใช้อุปกรณ์อื่นที่ไม่ใช่ ซึ่งมีอยู่ 2-3 ตัวเลือกด้วยกัน ได้แก่
- ขอกล้องหน้าเริ่มต้นที่มี
CameraSelector.DEFAULT_FRONT_CAMERA
- ขอกล้องหลังเริ่มต้นพร้อม
CameraSelector.DEFAULT_BACK_CAMERA
- กรองรายการอุปกรณ์ที่พร้อมใช้งานตาม
CameraCharacteristics
กับCameraSelector.Builder.addCameraFilter()
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีสร้าง CameraSelector
ไปยัง
มีผลต่อการเลือกอุปกรณ์
Kotlin
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 เป็นต้นไป คุณจะเลือกกล้องหลายตัวพร้อมกันได้ด้วย เช่น เชื่อมโยงกับกล้องหน้าและกล้องหลังเพื่อถ่ายภาพหรือบันทึก วิดีโอจากทั้ง 2 มุมมองพร้อมกันได้
เมื่อใช้ฟีเจอร์กล้องหลายตัวพร้อมกัน อุปกรณ์จะใช้งานกล้อง 2 ตัวได้
ด้วยเลนส์หันหน้าที่แตกต่างกันพร้อมกัน หรือใช้กล้องหลัง 2 ตัว
ในเวลาเดียวกัน โค้ดบล็อกต่อไปนี้แสดงวิธีตั้งค่ากล้อง 2 ตัวเมื่อ
กำลังเรียก bindToLifecycle
และวิธีเรียกดูออบเจ็กต์กล้องทั้ง 2 ตัวจากการส่งคืน
ConcurrentCamera
ออบเจ็กต์
Kotlin
// 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]
Java
// 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 ตั้งค่าความละเอียดของภาพตามชุดค่าผสม ความสามารถของอุปกรณ์ ฮาร์ดแวร์ที่รองรับของอุปกรณ์ ระดับ Use Case และสัดส่วนการแสดงผลที่ให้ไว้ หรือคุณสามารถตั้งค่า ความละเอียดเป้าหมายหรือสัดส่วนการแสดงผลที่เฉพาะเจาะจง ในกรณีการใช้งานที่รองรับ การกำหนดค่า
ความละเอียดอัตโนมัติ
CameraX จะตรวจสอบการตั้งค่าความละเอียดที่ดีที่สุดได้โดยอัตโนมัติตาม
กรณีการใช้งานที่ระบุใน cameraProcessProvider.bindToLifecycle()
เมื่อใดก็ตามที่
ให้ระบุ Use Case ทั้งหมดที่จำเป็นต่อการทำงานพร้อมกันใน
ในการโทร bindToLifecycle()
ครั้งเดียว CameraX กำหนดความละเอียด
อิงตามชุดกรณีการใช้งานที่เกี่ยวข้องโดยพิจารณาจากการรองรับของอุปกรณ์
ระดับฮาร์ดแวร์ และพิจารณาจากความแตกต่างเฉพาะอุปกรณ์ (ซึ่งอุปกรณ์
เกินหรือไม่ตรงตามการกำหนดค่าสตรีม
พร้อมใช้งาน)
จุดประสงค์ในการใช้งานคือให้แอปพลิเคชัน ทำงานบนอุปกรณ์ที่หลากหลาย
การลดเส้นทางของโค้ดเฉพาะอุปกรณ์
สัดส่วนภาพเริ่มต้นสําหรับ Use Case การจับภาพและการวิเคราะห์รูปภาพคือ 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()
เพื่อเรียกข้อมูลนี้
|
ระบุความละเอียด
คุณสามารถตั้งความละเอียดที่เฉพาะเจาะจงเมื่อสร้าง Use Case ได้โดยใช้
setTargetResolution(Size resolution)
ดังที่แสดงในโค้ดต่อไปนี้
ตัวอย่าง:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(1280, 720)) .build()
Java
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 ยังได้นำอินเทอร์เฟซต่อไปนี้มาใช้เพื่อสนับสนุน การทำงานของกล้องโดยทั่วไปใน Use Case ที่มีผลผูกพันทั้งหมด
CameraControl
ช่วยให้คุณ กำหนดค่าฟีเจอร์ทั่วไปของกล้องCameraInfo
ช่วยให้คุณค้นหา สถานะของฟีเจอร์ทั่วไปของกล้องเหล่านั้น
ฟีเจอร์กล้องที่รองรับของ CameraControl มีดังนี้
- Zoom
- คบเพลิง
- โฟกัสและการวัด (แตะเพื่อโฟกัส)
- ชดเชยการรับแสง
รับอินสแตนซ์ของ CameraControl และ CameraInfo
เรียกข้อมูลอินสแตนซ์ของ CameraControl
และ CameraInfo
โดยใช้
Camera
ส่งคืนออบเจ็กต์โดย
ProcessCameraProvider.bindToLifecycle()
ตัวอย่างโค้ดต่อไปนี้
Kotlin
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
Java
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
ที่ล้มเหลว
Zoom
CameraControl มีวิธีการเปลี่ยนระดับการซูม 2 วิธี ได้แก่
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
เพื่ออัปเดตทั้ง 2 รายการโดยไม่ต้องดำเนินการใดๆ
Conversion
ListenableFuture
ที่แสดงผลโดย API ทั้งคู่มีตัวเลือกสำหรับแอปพลิเคชัน
เพื่อรับการแจ้งเตือนเมื่อคำขอซ้ำที่มีค่าการซูมที่ระบุเท่ากับ
เสร็จสมบูรณ์แล้ว นอกจากนี้ ถ้าคุณตั้งค่าการซูมใหม่ในขณะที่การดำเนินการก่อนหน้า
ยังคงดำเนินการอยู่ ListenableFuture
ของการดำเนินการซูมก่อนหน้านี้ล้มเหลว
ทันที
คบเพลิง
CameraControl.enableTorch(boolean)
เปิดหรือปิดไฟฉาย (หรือที่เรียกว่าไฟฉาย)
CameraInfo.getTorchState()
สามารถใช้เพื่อค้นหาสถานะของไฟฉายปัจจุบัน คุณสามารถตรวจสอบค่าที่ส่งคืนได้
โดย
CameraInfo.hasFlashUnit()
เพื่อดูว่าไฟฉายพร้อมใช้งานหรือไม่ หากไม่ กำลังโทร
CameraControl.enableTorch(boolean)
ทำให้ ListenableFuture
ที่แสดงผลเป็น
เสร็จสมบูรณ์ทันทีด้วยผลลัพธ์ที่ล้มเหลว และตั้งค่าสถานะไฟฉายเป็น
TorchState.OFF
เมื่อเปิดใช้ ไฟฉายจะติดอยู่ตลอดระหว่างจับภาพและวิดีโอ
โดยไม่คํานึงถึงการตั้งค่า FlashMode ก็ตาม
flashMode
นิ้ว
ImageCapture
จะทำงานเฉพาะเมื่อไฟฉายปิดอยู่
การโฟกัสและการวัด
CameraControl.startFocusAndMetering()
เรียกใช้การโฟกัสอัตโนมัติและการวัดการเปิดรับแสงโดยการตั้งค่าพื้นที่การวัด AF/AE/AWB
ตาม FocusMeteringAction ที่ระบุ มักจะใช้ขั้นตอน "การแตะ"
เพื่อโฟกัส" ในแอปพลิเคชันกล้องจำนวนมาก
จุดวัด
ในการเริ่มต้น ให้สร้าง
MeteringPoint
กำลังใช้
MeteringPointFactory.createPoint(float x, float y, float
size)
MeteringPoint
แสดงจุดเดียวบนกล้อง
Surface
โดยจะจัดเก็บไว้ในรูปแบบมาตรฐาน
เพื่อให้สามารถแปลงเป็นพิกัดเซ็นเซอร์เพื่อระบุ
ภูมิภาค AF/AE/AWB
ขนาดของ MeteringPoint
จะอยู่ในช่วงตั้งแต่ 0 ถึง 1 โดยมีขนาดเริ่มต้นดังนี้
0.15f เมื่อเรียกใช้ MeteringPointFactory.createPoint(float x, float y, float
size)
CameraX จะสร้างพื้นที่สี่เหลี่ยมผืนผ้าซึ่งมีศูนย์กลางอยู่ที่ (x, y)
สำหรับ
size
โค้ดต่อไปนี้แสดงวิธีสร้าง MeteringPoint
Kotlin
// 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
อย่างน้อย 1 รายการที่มีโหมดการตรวจสอบการใช้งานซึ่งไม่บังคับ
ชุดค่าผสมจาก
FLAG_AF
FLAG_AE
,
FLAG_AWB
ติดตามโค้ดแสดงการใช้งานนี้:
Kotlin
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
ได้รับ MeteringPoint 3 จุดบนแพลตฟอร์มที่รองรับ
เพียง 2 ระบบจะใช้ MeteringPoints 2 รายการแรกเท่านั้น MeteringPoint
สุดท้ายคือ
CameraX ไม่สนใจ
ชดเชยการรับแสง
การชดเชยแสงจะมีประโยชน์เมื่อแอปพลิเคชันต้องปรับการรับแสง (EV) ที่นอกเหนือจากผลที่ได้จากการรับแสงอัตโนมัติ (AE) ชดเชยการรับแสง ค่าต่างๆ จะรวมกันด้วยวิธีต่อไปนี้เพื่อระบุการรับแสงที่จำเป็นสำหรับ สภาพรูปภาพปัจจุบัน:
Exposure = ExposureCompensationIndex * ExposureCompensationStep
CameraX มอบความสามารถ
Camera.CameraControl.setExposureCompensationIndex()
สำหรับตั้งค่าชดเชยการรับแสงเป็นค่าดัชนี
ค่าดัชนีที่เป็นบวกจะทำให้รูปภาพสว่างขึ้น ส่วนค่าลบจะลดความสว่าง
รูปภาพ แอปพลิเคชันสามารถค้นหาช่วงที่สนับสนุนได้โดยใช้
CameraInfo.ExposureState.exposureCompensationRange()
ดังที่อธิบายไว้ในส่วนถัดไป หากระบบรองรับค่า ผลลัพธ์
ListenableFuture
จะเสร็จสมบูรณ์เมื่อเปิดใช้ค่าใน
คำขอบันทึก หากดัชนีที่ระบุอยู่นอกช่วงที่สนับสนุน
setExposureCompensationIndex()
ทำให้ ListenableFuture
ที่แสดงผลเป็น
เสร็จสมบูรณ์ทันทีที่มีผลลัพธ์ที่ไม่ผ่าน
CameraX จะเก็บเฉพาะ setExposureCompensationIndex()
ล่าสุดที่โดดเด่น
และการเรียกใช้ฟังก์ชันหลายครั้งก่อนหน้าคำขอก่อนหน้า
จะถูกเรียกใช้
ผลในการยกเลิก
ข้อมูลโค้ดต่อไปนี้ตั้งค่าดัชนีชดเชยจำนวนผู้ที่เห็นและลงทะเบียน Callback เมื่อมีการดำเนินการตามคำขอเปลี่ยนจำนวนผู้ที่เห็น:
Kotlin
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
ปัจจุบัน
มีดังนี้
Kotlin
val exposureState = camera.cameraInfo.exposureState binding.seekBar.apply { isEnabled = exposureState.isExposureCompensationSupported max = exposureState.exposureCompensationRange.upper min = exposureState.exposureCompensationRange.lower progress = exposureState.exposureCompensationIndex }
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับ CameraX ได้ในแหล่งข้อมูลเพิ่มเติมต่อไปนี้
Codelab
ตัวอย่างโค้ด