مورد استفاده تحلیل تصویر
تصویری با قابلیت دسترسی به 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 است (برای مثال، ۱۶ میلیثانیه برای ۶۰ فریم در ثانیه)، هریک از حالتهای عملکرد تجربه کلی روانی را ارائه میدهد. حالت مسدودسازی همچنان میتواند در برخی سناریوها مفید باشد، مثلاً هنگام مواجهه با لرزشهای بسیار کوتاه سیستم.
با یک تحلیلگر با تأخیر بالا و عملکرد بالا، حالت مسدود کردن با یک صف طولانیتر برای جبران تأخیر ضروری است. اما توجه داشته باشید که برنامه همچنان میتواند همه قابها را پردازش کند.
با تأخیر بالا و تحلیلگر زمانبر (تحلیلگر نمیتواند همه فریمها را پردازش کند)، حالت غیرمسدودکننده ممکن است انتخاب مناسبتری باشد، زیرا فریمها باید برای مسیر تحلیل حذف شوند، اما سایر موارد استفاده محدود همزمان همچنان میتوانند همه فریمها را ببینند.
پیادهسازی
برای استفاده از تجزیهوتحلیل تصویر در برنامهتان، این مراحل را دنبال کنید:
- مورد استفاده
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است. - وضوح و نسبت ابعادی: میتوانید هرکدام از این پارامترها را تنظیم کنید، اما توجه داشته باشید که نمیتوانید هر دو مقدار را همزمان تنظیم کنید.
- چرخش.
- نام هدف: از این پارامتر برای اهداف اشکالزدایی استفاده کنید.
- قالب: 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 دریافت میکنند که یک پوشاننده
برای 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 را ببینید.
درون تحلیلگر، برنامه باید کارهای زیر را انجام دهد:
- قاب دادهشده را در سریعترین زمان ممکن، ترجیحاً در محدوده زمانی نرخ فریم دادهشده (برای مثال، کمتر از ۳۲ میلیثانیه برای ۳۰ فریم در ثانیه)، تجزیهوتحلیل کنید. اگر برنامه نمیتواند قاب را بهاندازه کافی سریع تحلیل کند، یکی از سازوکارهای پشتیبانیشده حذف قاب را درنظر بگیرید.
- با فراخوانی
ImageProxy.close()،ImageProxyرا برای CameraX منتشر کنید. توجه داشته باشید که نباید تابع close مربوط به Media.Image بستهبندیشده را فراخوانی کنید (Media.Image.close()).
برنامهها میتوانند مستقیماً از Media.Image پیچیدهشده در ImageProxy استفاده کنند.
فقط Media.Image.close() را در تصویر پیچیده فراخوانی نکنید زیرا این کار باعث شکستن
مکانیزم همرسانی تصویر در CameraX میشود؛ درعوض، از
ImageProxy.close()
برای انتشار Media.Image زیرین به CameraX استفاده کنید.
پیکربندی کردن تحلیلگر برای ImageAnalysis
پساز ایجاد تحلیلگر، از
ImageAnalysis.setAnalyzer()
برای ثبت آن جهت شروع تحلیل استفاده کنید. وقتی کارتان با تجزیهوتحلیل تمام شد، از
ImageAnalysis.clearAnalyzer()
برای برداشتن تجزیهوتحلیلگر ثبتشده استفاده کنید.
فقط یک تحلیلگر فعال را میتوان برای تحلیل تصویر پیکربندی کرد. فراخوانی
ImageAnalysis.setAnalyzer() جایگزین تحلیلگر ثبتشده میشود اگر ازقبل
وجود داشته باشد. برنامهها میتوانند در هر زمانی، قبل یا بعداز اتصال مورد استفاده، تحلیلگر جدیدی تنظیم کنند.
Bind the ImageAnalysis to a Lifecycle
اکیداً توصیه میشود ImageAnalysis خود را با تابع
ProcessCameraProvider.bindToLifecycle()
به چرخه حیات AndroidX موجودی متصل کنید. توجه داشته باشید که تابع bindToLifecycle() دستگاه Camera انتخابشده را برمیگرداند که میتوان از آن برای تنظیم دقیق تنظیمات پیشرفته مانند نوردهی و غیره استفاده کرد. برای اطلاعات بیشتر درباره کنترل خروجی دوربین، این راهنما را ببینید.
مثال زیر همه موارد مراحل قبلی را ترکیب میکند و موارد استفاده CameraX ImageAnalysis و Preview را به مالک lifeCycle متصل میکند:
کاتلین
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)
جاوا
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
نمونه کد