کالیبراسیون دوربین و بازسازی سه‌بعدی

نقشه عمق از تصاویر استریو

۴ دقیقه مطالعهOpenCV 5.xبه‌روزرسانی:

هدف#

در این جلسه،

  • یاد خواهیم گرفت چگونه از تصاویر استریو یک نقشه عمق (Depth Map) ایجاد کنیم.

مفاهیم پایه#

در جلسه گذشته، مفاهیم اساسی مانند قیود اپی‌پولار و سایر اصطلاحات مرتبط را دیدیم. همچنین دیدیم که اگر دو تصویر از یک صحنه داشته باشیم، می‌توانیم اطلاعات عمق را به شیوه‌ای شهودی از آن به دست آوریم. در زیر یک تصویر و چند فرمول ساده ریاضی ارائه شده است که این شهود را ثابت می‌کنند. (تصویر به نقل از:

نقشه عمق از تصاویر استریو — تصویر ۱

نمودار فوق شامل مثلث‌های متشابه است. نوشتن معادلات هم‌ارز آن‌ها نتیجه زیر را برای ما به همراه خواهد داشت:

و فاصله بین نقاط در صفحه تصویر متناظر با نقطه سه‌بعدی صحنه و مرکز دوربین آن‌ها هستند. فاصله بین دو دوربین (که آن را می‌دانیم) و فاصله کانونی دوربین (که از قبل معلوم است) می‌باشد. بنابراین به طور خلاصه، معادله فوق بیان می‌کند که عمق یک نقطه در صحنه با اختلاف فاصله نقاط متناظر تصویر و مراکز دوربین آن‌ها نسبت عکس دارد. بنابراین با این اطلاعات، می‌توانیم عمق تمام پیکسل‌ها را در یک تصویر استخراج کنیم.

بنابراین الگوریتم تطابق‌های متناظر را بین دو تصویر پیدا می‌کند. پیش از این دیده‌ایم که چگونه قید خط اپی‌پولار این عملیات را سریع‌تر و دقیق‌تر می‌سازد. به محض اینکه تطابق‌ها پیدا شوند، ناهمخوانی (Disparity) را محاسبه می‌کند. بیایید ببینیم چگونه می‌توانیم این کار را با OpenCV انجام دهیم.

کد#

قطعه کد زیر رویه ساده‌ای را برای ایجاد یک نقشه ناهمخوانی (Disparity Map) نشان می‌دهد:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

imgL = cv.imread('tsukuba_l.png', cv.IMREAD_GRAYSCALE)
imgR = cv.imread('tsukuba_r.png', cv.IMREAD_GRAYSCALE)

stereo = cv.StereoBM.create(numDisparities=16, blockSize=15)
disparity = stereo.compute(imgL,imgR)
plt.imshow(disparity,'gray')
plt.show()

تصویر زیر شامل تصویر اصلی (چپ) و نقشه ناهمخوانی آن (راست) است. همانطور که مشاهده می‌کنید، نتیجه به درجه بالایی از نویز آلوده است. با تنظیم مقادیر numDisparities و blockSize، می‌توانید نتیجه بهتری به دست آورید:

نقشه عمق از تصاویر استریو — تصویر ۲

هنگامی که با StereoBM آشنا شدید، پارامترهایی وجود دارند که ممکن است برای دستیابی به نتایج بهتر و یکدست‌تر نیاز به تنظیم دقیق (Fine-tune) آن‌ها داشته باشید. پارامترها:

  • texture_threshold: نواحی را که بافت کافی برای تطبیق قابل اعتماد ندارند فیلتر می‌کند
  • Speckle range and size: تطبیق‌دهنده‌های مبتنی بر بلوک اغلب در نزدیکی مرزهای اشیاء "لکه" (speckle) تولید می‌کنند، جایی که پنجره تطبیق از یک طرف پیش‌زمینه و از طرف دیگر پس‌زمینه را می‌گیرد. در این صحنه به نظر می‌رسد که تطبیق‌دهنده همچنین تطابق‌های کاذب کوچکی را در بافت پرتاب‌شده روی میز پیدا می‌کند. برای خلاص شدن از شر این آرتیفکت‌ها، تصویر ناهمخوانی را با یک فیلتر لکه که توسط پارامترهای speckle_size و speckle_range کنترل می‌شود، پس‌پردازش می‌کنیم. speckle_size تعداد پیکسل‌هایی است که کمتر از آن یک حباب ناهمخوانی به عنوان "لکه" رد می‌شود. speckle_range کنترل می‌کند که ناهمخوانی‌ها چقدر باید از نظر مقدار به هم نزدیک باشند تا بخشی از یک حباب در نظر گرفته شوند.
  • Number of disparities: تعداد پیکسل‌هایی که پنجره روی آن‌ها لغزانده می‌شود. هرچه بزرگ‌تر باشد، دامنه عمق‌های قابل مشاهده بزرگ‌تر است، اما محاسبات بیشتری مورد نیاز خواهد بود.
  • min_disparity: آفست از موقعیت x پیکسل چپ که جستجو از آنجا شروع می‌شود.
  • uniqueness_ratio: مرحله دیگری از پس‌فیلتر کردن است. اگر بهترین ناهمخوانی تطبیق‌یافته به اندازه کافی بهتر از سایر ناهمخوانی‌ها در محدوده جستجو نباشد، پیکسل فیلتر می‌شود. اگر texture_threshold و فیلتر کردن لکه هنوز اجازه عبور تطابق‌های کاذب را می‌دهند، می‌توانید این مورد را تغییر دهید.
  • prefilter_size and prefilter_cap: فاز پیش‌فیلتر کردن که روشنایی تصویر را نرمال کرده و بافت را در آماده‌سازی برای تطبیق بلوکی بهبود می‌بخشد. معمولاً نیازی به تنظیم این موارد ندارید.

این پارامترها با استفاده از توابع اختصاصی setter و getter پس از مقداردهی اولیه الگوریتم تنظیم می‌شوند، مانند setTextureThreshold، setSpeckleRange، setUniquenessRatio و موارد دیگر. برای جزئیات به مستندات cv::StereoBM مراجعه کنید.

منابع اضافی#

تمرین‌ها#

  1. نمونه کدهای OpenCV حاوی مثالی از تولید نقشه ناهمخوانی و بازسازی سه‌بعدی آن است. فایل stereo_match.py را در نمونه کدهای OpenCV-Python بررسی کنید.