ניתוח תמונות
מספק לאפליקציה תמונה שנגישה למעבד (CPU), ובעזרתה
לבצע עיבוד תמונות, ראייה ממוחשבת או מסקנות מלמידת מכונה.
מממשת
analyze()
שתרוץ בכל מסגרת.
כדי ללמוד איך לשלב את ערכת ML Kit של Google עם אפליקציית CameraX, למידע נוסף, ראו ML Kit Analyzer.
מצבי הפעלה
כשצינור הניתוח של האפליקציה לא יכול לעמוד בפריים של CameraX ניתן להגדיר את CameraX לשחרור פריימים באחת מהדרכים הבאות:
ללא חסימה (ברירת מחדל): במצב הזה, העורך תמיד שומר במטמון את תמונה עדכנית בתוך מאגר תמונות (דומה לתור עם עומק של תמונה) בזמן שהאפליקציה מנתחת את התמונה הקודמת. אם CameraX מקבל תמונה חדשה לפני שהעיבוד של האפליקציה מסתיים, התמונה החדשה נשמרת באותו מאגר נתונים זמני ומחליפה את התמונה הקודמת. חשוב לשים לב: ל-
ImageAnalysis.Builder.setImageQueueDepth()
אין השפעה על בתרחיש הזה, והתוכן של מאגר הנתונים הזמני תמיד מחליף. אפשר להפעיל את המצב הזה של מניעת חסימה על ידי התקשרותsetBackpressureStrategy()
עםSTRATEGY_KEEP_ONLY_LATEST
. למידע נוסף על המשמעויות של המנהלים, ניתן לעיין בחומר העזר תיעוד עבורSTRATEGY_KEEP_ONLY_LATEST
חסימה: במצב הזה, הכלי הפנימי יכול להוסיף מספר תמונות לתור התמונות הפנימי, ויתחיל לשחרר פריימים רק כשהתור מלא. החסימה מתרחשת בכל ההיקף של מכשיר המצלמה: אם למכשיר המצלמה יש כמה תרחישים לדוגמה, חסום בזמן ש- CameraX מעבד את התמונות האלה. עבור לדוגמה, כשגם התצוגה המקדימה וגם ניתוח התמונות קשורים למכשיר מצלמה, אז גם התצוגה המקדימה תיחסם בזמן ש- CameraX מעבד את התמונות. כדי להפעיל את מצב החסימה, צריך להעביר
STRATEGY_BLOCK_PRODUCER
כדיsetBackpressureStrategy()
אפשר גם להגדיר את העומק של תור התמונות באמצעות ImageAnalysis.Builder.setImageQueueDepth().
עם זמן אחזור קצר וכלי לניתוח ביצועים גבוהים, שבו הזמן הכולל ניתוח תמונה קצר ממשך הפריים של CameraX (16 אלפיות שנייה עבור 60fps, לדוגמה), כל אחד ממצבי ההפעלה מספק ביצועים חלקה באופן כללי חוויה אישית. מצב חסימה עדיין יכול להיות שימושי בתרחישים מסוימים, כמו בהתמודדות עם רעידות מערכת קצרות מאוד.
עם זמן אחזור ארוך ועם מנתח ביצועים גבוהים, מצב חסימה עם נדרש תור ארוך יותר כדי לפצות על זמן האחזור. עם זאת, שימו לב האפליקציה עדיין יכולה לעבד את כל המסגרות.
המכשיר הזה עובד עם זמן אחזור ארוך ועם זמן אחזור ארוך (המנתח לא יכול לעבד את כל הנתונים פריימים), מצב ללא חסימה עלול להיות בחירה מתאימה יותר, כי צריך להסיר את הפריימים כדי לנתח את הנתיב, תרחישים לדוגמה אחרים שעוסקים בו-זמנית עדיין יכולים לראות את כל הפריימים.
הטמעה
כדי להשתמש בניתוח תמונות באפליקציה, מבצעים את השלבים הבאים:
- יצירת
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
. - רזולוציה ו-AspectRatio: אתם יכולים להגדיר כל אחד מהפרמטרים האלה, אבל חשוב לדעת שאי אפשר להגדיר את שניהם. בו-זמנית.
- רוטציה.
- שם יעד: השתמשו בפרמטר הזה למטרות ניפוי באגים.
- פורמט: יש תמיכה ב- CameraX
- פקדי זרימה של תמונה:
אפליקציות יכולות להגדיר את הרזולוציה או את יחס הגובה-רוחב, אבל לא
ובשניהם. רזולוציית הפלט המדויקת תלויה בגודל המבוקש של האפליקציה
(או יחס גובה-רוחב) ויכולות חומרה וייתכן שהם יהיו שונים
הגודל או היחס. מידע על האלגוריתם להתאמת רזולוציה זמין בכתובת
התיעוד עבור
setTargetResolution()
אפליקציה יכולה להגדיר שהפיקסלים של תמונת הפלט יהיו ב-YUV (ברירת המחדל)
או מרחבי צבעים של RGBA. כשמגדירים פורמט פלט RGBA, CameraX באופן פנימי
ממירה תמונות מ-YUV למרחב צבעי RGBA ואורזת ביטים של תמונות
ByteBuffer
של המישור הראשון של ImageProxy (לא נעשה שימוש בשני המישורים האחרים) עם
הרצף הבא:
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
, שהוא wrapper
בשביל Media.Image.
אפשר לשלוח שאילתה על פורמט התמונה
ImageProxy.getFormat()
הפורמט הוא אחד מהערכים הבאים שהיישום
מספק ImageAnalysis.Builder
:
ImageFormat.RGBA_8888
אם האפליקציה ביקשהOUTPUT_IMAGE_FORMAT_RGBA_8888
.ImageFormat.YUV_420_888
אם האפליקציה ביקשהOUTPUT_IMAGE_FORMAT_YUV_420_888
.
תרחיש לדוגמה של Build ImageAnalysis את ההגדרות של מרחב צבעים ואת המקומות שבהם ניתן לאחזר את הבייטים של הפיקסלים.
בתוך כלי הניתוח, האפליקציה צריכה לבצע את הפעולות הבאות:
- לנתח מסגרת נתונה במהירות האפשרית, עדיף במסגרת מגבלת זמן לקצב פריימים (לדוגמה, פחות מ-32 אלפיות השנייה במקרה של 30FPS). אם האפליקציה לא יכולה לנתח פריים מהר מספיק, כדאי לשקול אחת מ- מנגנונים נתמכים להסרת פריימים.
- צריך לשחרר את
ImageProxy
ל- CameraX באמצעות התקשרותImageProxy.close()
. חשוב לשים לב שאין לקרוא לפונקציה wrapped Media.Image. (Media.Image.close()
).
אפליקציות יכולות להשתמש ישירות ב-Media.Image
הארוז בתוך ImageProxy.
אסור לקרוא למספר Media.Image.close()
בתמונה העטופה כי זה יישבר
מנגנון שיתוף התמונות בתוך CameraX; במקום זאת, משתמשים
ImageProxy.close()
כדי להפיץ את Media.Image
הבסיסי ל- CameraX.
הגדרת המנתח ל-ImageAnalysis
אחרי שיוצרים מנתח,
ImageAnalysis.setAnalyzer()
כדי לרשום אותו ולהתחיל בניתוח. אחרי שמסיימים עם הניתוח, משתמשים
ImageAnalysis.clearAnalyzer()
כדי להסיר את המנתח הרשום.
ניתן להגדיר רק מנתח פעיל אחד לניתוח תמונות. ביצוע שיחה
ImageAnalysis.setAnalyzer()
מחליף את המנתח הרשום, אם הוא כבר
קיים. אפליקציות יכולות להגדיר מנתח חדש בכל שלב, לפני או אחרי הקישור
של התרחיש לדוגמה המבוקש.
קישור ניתוח ה-ImageAnalysis למחזור החיים
מומלץ מאוד לקשר את ImageAnalysis
לקובץ קיים
מחזור החיים של AndroidX עם
ProcessCameraProvider.bindToLifecycle()
מותאמת אישית. חשוב לשים לב שהפונקציה bindToLifecycle()
מחזירה את הערך שנבחר.
מכשיר Camera
, שבו ניתן להשתמש.
כדי לכוונן הגדרות מתקדמות כמו חשיפה ואחרות. במדריך הזה אפשר לקרוא מידע נוסף על שליטה בפלט של המצלמה.
בדוגמה הבאה אנחנו משלבים את כל המידע מהשלבים הקודמים,
תרחישים לדוגמה של CameraX ImageAnalysis
ו-Preview
לבעלים של lifeCycle
:
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, ניתן לעיין במשאבים הנוספים הבאים.
Codelab
דוגמת קוד