تحلیل تصویر

مورد استفاده تحلیل تصویر تصویری قابل‌دسترسی برای 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 است (برای مثال، ۱۶ میلی‌ثانیه برای ۶۰ قاب در ثانیه)، هریک از حالت‌های عملکرد تجربه کلی روانی را ارائه می‌دهد. حالت مسدودسازی همچنان می‌تواند در برخی سناریوها مفید باشد، مثلاً هنگام مواجهه با لرزش‌های بسیار کوتاه سیستم.

با تحلیل‌گر تأخیر بالا و عملکرد بالا، حالت مسدودسازی با صف طولانی‌تر برای جبران تأخیر ضروری است. اما توجه داشته باشید که برنامه همچنان می‌تواند همه فریم‌ها را پردازش کند.

با یک تحلیل‌گر با تأخیر بالا و زمان‌بر (تحلیل‌گر قادر به پردازش همه فریم‌ها نیست)، حالت غیرمسدودکننده ممکن است انتخاب مناسب‌تری باشد، زیرا فریم‌ها باید برای مسیر تحلیل حذف شوند، اما سایر موارد استفاده هم‌زمان محدود همچنان می‌توانند همه فریم‌ها را ببینند.

پیاده‌سازی

برای استفاده از تجزیه‌وتحلیل تصویر در برنامه‌تان، این مراحل را دنبال کنید:

بلافاصله پس‌از اتصال، CameraX تصاویر را به تحلیل‌گر ثبت‌شده شما ارسال می‌کند. پس‌از تکمیل تجزیه‌وتحلیل، ImageAnalysis.clearAnalyzer() را فراخوانی کنید یا برای توقف تجزیه‌وتحلیل، مورد استفاده ImageAnalysis را لغو اتصال کنید.

ساختن مورد استفاده ImageAnalysis

ImageAnalysis تحلیل‌گر شما (مصرف‌کننده تصویر) را به CameraX (تولیدکننده تصویر) متصل می‌کند. برنامه‌ها می‌توانند از ImageAnalysis.Builder برای ساختن شیء ImageAnalysis استفاده کنند. با ImageAnalysis.Builder، برنامه می‌تواند موارد زیر را پیکربندی کند:

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

درون تحلیل‌گر، برنامه باید کارهای زیر را انجام دهد:

  1. قاب داده‌شده را در سریع‌ترین زمان ممکن، ترجیحاً در محدوده زمانی نرخ فریم داده‌شده (برای مثال، کمتر از ۳۲ میلی‌ثانیه برای ۳۰ فریم در ثانیه)، تجزیه‌وتحلیل کنید. اگر برنامه نتواند قاب را به‌اندازه کافی سریع تحلیل کند، یکی از سازوکارهای پشتیبانی‌شده حذف قاب را درنظر بگیرید.
  2. با فراخوانی 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)

منابع بیشتر

برای کسب اطلاعات بیشتر درباره CameraX، منابع اضافی زیر را ببینید.

Codelab

  • شروع به کار کردن با CameraX
  • نمونه کد

  • برنامه‌های نمونه CameraX