圖片分析用途可為您的應用程式提供方便 CPU 存取的圖片,以便執行圖片處理作業、電腦視覺或機器學習推論。應用程式會導入在每個影格上執行的 analyze()
方法。
如要瞭解如何整合 Google 的 ML Kit 與 CameraX 應用程式,請參閱「ML Kit 分析工具」一文。
運作模式
如果應用程式的分析管道無法達到 CameraX 的畫面更新率要求,您可以透過下列任一種方式將 CameraX 設定為捨棄影格:
非封鎖 (預設):在此模式下,應用程式分析上一張圖片時,執行程式一律會將最新的圖片快取至圖片緩衝區 (類似深度為一的佇列)。如果 CameraX 在應用程式處理完成之前收到新的圖片,系統會將其儲存至同一個緩衝區,並覆寫先前的圖片。請注意,
ImageAnalysis.Builder.setImageQueueDepth()
在 而且緩衝區內容一律會被覆寫。 您可以利用STRATEGY_KEEP_ONLY_LATEST
呼叫setBackpressureStrategy()
來啟動此非封鎖模式。如要進一步瞭解執行程式的影響,請參閱參考資料 說明文件STRATEGY_KEEP_ONLY_LATEST
。封鎖:在此模式下,內部執行程式可將多張圖片加入內部圖片佇列,並且僅在佇列已滿時才捨棄影格。封鎖模式適用於整個相機裝置範圍:如果相機裝置有多個已繫結的用途,則在 CameraX 處理這些圖片時,這些用途均會遭到封鎖。舉例來說,如果預覽和圖片分析均繫結至某個相機裝置,那麼當 CameraX 處理圖片時,預覽也會一併遭到封鎖。您只要將
STRATEGY_BLOCK_PRODUCER
敬上 到setBackpressureStrategy()
。 您也可以使用 ImageAnalysis.Builder.setImageQueueDepth() 設定圖片佇列深度。
如果使用低延遲度且高效能的工具,使分析圖片的總時間少於 CameraX 影格的時間 (例如 60fps 耗時 16 毫秒),則不論是上述何種操作模式,都能提供順暢的體驗。封鎖模式在某些情況下仍是很實用的,例如: 但在處理非常短的系統時基誤差
具備高延遲和高效能分析工具 封鎖模式具有 需要較長的佇列來彌補延遲時間但請注意,應用程式仍可以處理所有影格。
搭配使用高延遲和耗時的分析工具時 (分析工具無法處理所有影格),非封鎖模式可能較為適用,因為分析路徑必須捨棄影格,但其他並行的繫結用途仍能看到所有影格。
實作
如要在應用程式中使用圖片分析,請按照下列步驟操作:
- 建立
ImageAnalysis
具體來說,您可以設計提示來解決業務工作 - 撰寫
ImageAnalysis.Analyzer
。 - 將分析工具設定 至
ImageAnalysis
。 - 特徵分塊
生命週期擁有者、相機選取器和
ImageAnalysis
用途 生命週期到此結束
繫結後,CameraX 會立即將圖片傳送至已註冊的分析工具。
完成分析後,請呼叫
ImageAnalysis.clearAnalyzer()
敬上
取消繫結 ImageAnalysis
用途即可停止分析。
建構 ImageAnalysis 應用實例
ImageAnalysis
連線
將分析工具 (圖片使用者) 轉移至 CameraX,也就是圖片製作工具
應用程式可以使用
ImageAnalysis.Builder
敬上
建構 ImageAnalysis
物件透過 ImageAnalysis.Builder
,
應用程式可以設定下列項目:
- 圖片輸出參數:
- 格式:CameraX 支援
YUV_420_888
敬上 和RGBA_8888
透過setOutputImageFormat(int)
關閉通知。 預設格式為YUV_420_888
。 - Resolution 和 AspectRatio:您可以設定其中任一參數,不過請注意,兩者無法同時設定。
- 旋轉。
- 目標名稱: 請將這個參數用於偵錯。
- 格式:CameraX 支援
- 圖片流程控制項:
應用程式可以設定解析度或長寬比,但無法設定
兩者。確切的輸出解析度取決於應用程式要求的大小 (或顯示比例) 及硬體功能,且可能會與要求的大小或比例不同。如需解析度比對演算法的相關資訊,請參閱:
相關說明文件
setTargetResolution()
敬上
應用程式可將輸出圖片像素設為 YUV (預設值)
或 RGBA 色域設定 RGBA 輸出格式時,CameraX 會在內部執行
會將 YUV 轉換為 RGBA 色域,並將圖片位元封裝為
ByteBuffer
敬上
擷取此物件
下列順序:
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...
執行複雜的圖片分析作業時,如果裝置無法達到畫面更新率,可以按照本文「操作模式」一節所述的做法設定 CameraX,以便捨棄影格。
建立分析工具
應用程式可透過實作
ImageAnalysis.Analyzer
敬上
介面並覆寫設定
analyze(ImageProxy image)
。
在每個分析工具中,應用程式會收到
ImageProxy
,這是包裝函式
Media.Image 的程序。
您可以使用
ImageProxy.getFormat()
。
格式是應用程式的下列其中一個值
提供 ImageAnalysis.Builder
:
ImageFormat.RGBA_8888
(如果應用程式要求OUTPUT_IMAGE_FORMAT_RGBA_8888
)。ImageFormat.YUV_420_888
(如果應用程式要求OUTPUT_IMAGE_FORMAT_YUV_420_888
)。
請參閱「建構 ImageAnalysis 用途」瞭解色域設定,以及可以擷取像素位元組的位置。
在分析工具中,應用程式應執行以下操作:
- 最好在特定的畫面更新率時間限制內 (例如 30 fps 時不超過 32 毫秒),盡快分析特定影格。如果應用程式無法快速分析影格,請考慮使用其中一種支援的影格捨棄機制。
- 呼叫即可將
ImageProxy
發布至 CameraXImageProxy.close()
。 請注意,您不應呼叫已包裝的 Media.Image 關閉函式 (Media.Image.close()
)。
應用程式可以直接在 ImageProxy 中使用已包裝的 Media.Image
。
不要在已包裝的圖片上呼叫 Media.Image.close()
,因為這可能會損毀
採用 CameraX 的圖片分享機制而是改用
ImageProxy.close()
將基礎 Media.Image
發布至 CameraX。
設定 ImageAnalysis 分析工具
建立分析工具後,請使用
ImageAnalysis.setAnalyzer()
敬上
註冊即可開始分析分析完成後,請使用
ImageAnalysis.clearAnalyzer()
敬上
移除已註冊的分析工具。
只能設定一個有效的分析工具進行圖片分析。撥號中
ImageAnalysis.setAnalyzer()
會取代已註冊的分析工具 (如有)
存在。在繫結用途前後,應用程式可以隨時設定新的分析工具。
將 ImageAnalysis 繫結至生命週期
強烈建議您將 ImageAnalysis
繫結至現有
AndroidX 生命週期和
ProcessCameraProvider.bindToLifecycle()
函式。請注意,bindToLifecycle()
函式會傳回所選值
Camera
裝置 (可使用)
可讓您微調進階設定 (例如曝光等)請參閱這份指南,進一步瞭解如何控制相機輸出。
以下範例結合了先前步驟中的所有元素
對 lifeCycle
擁有者的 CameraX ImageAnalysis
和 Preview
用途:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() // enable the following line if RGBA output is needed. // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> val rotationDegrees = imageProxy.imageInfo.rotationDegrees // insert your code here. ... // after done, release the ImageProxy object imageProxy.close() }) cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() // enable the following line if RGBA output is needed. //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(new Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { @Override public void analyze(@NonNull ImageProxy imageProxy) { int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); // insert your code here. ... // after done, release the ImageProxy object imageProxy.close(); } }); cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
其他資源
如要進一步瞭解 CameraX,請參閱下列其他資源。
程式碼研究室
程式碼範例